Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion collateral-abi/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,4 @@ Contents are generated — do not edit by hand:
- `src/` is copied from `../contracts/abi` (the Hardhat codegen output) by `scripts/build.mjs`, then compiled to `dist/`.
- `deployments.json` is the canonical address manifest for this repo; it is updated when contracts are (re)deployed.

Publishing happens from CI (see `.github/workflows/publish-collateral-abi.yml`). A `dev` publish updates `environments.testnet` and is tagged `dev` (minor bump). A `main` publish updates `environments.mainnet` and is tagged `latest`; the first mainnet cut is `1.0.0`.
Publishing happens from CI (see `.github/workflows/publish-collateral-abi.yml`). A `dev` publish updates `environments.testnet` and is tagged `dev` (minor bump). A `main` publish updates `environments.mainnet` and is tagged `latest`; the first mainnet cut is `3.0.0`, skipping any major npm has already used.
33 changes: 27 additions & 6 deletions collateral-abi/scripts/plan-release.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
// The base is the `dev` tag, or the highest published 0.x if that
// tag does not exist yet. Never moves `latest`.
// main -> dist-tag `latest`. The first publish whose mainnet block has
// addresses is 1.0.0. After that, an ABI break bumps major, an
// ABI addition bumps minor, and a mainnet address change bumps patch.
// addresses is 3.0.0, or the next free major if that version was
// already published (npm will not reuse an unpublished version).
// After that, an ABI break bumps major, an ABI addition bumps
// minor, and a mainnet address change bumps patch.
//
// Writes package.json's version in the working copy (npm holds the version
// of record; nothing is committed). Set DRY_RUN=1 to print the decision only.
Expand Down Expand Up @@ -56,6 +58,24 @@ function versionsOf() {
}
}

// `npm view versions` hides unpublished releases. `time` still lists them,
// and npm rejects a publish that reuses one of those version numbers.
function takenVersions() {
try {
const time = npmJson(["view", pkg, "time", "--json"]);
return new Set(Object.keys(time).filter((key) => /^\d+\.\d+\.\d+$/.test(key)));
} catch {
return new Set(versionsOf());
}
}

function firstMainnetVersion() {
const taken = takenVersions();
let major = 3;
while (taken.has(`${major}.0.0`)) major += 1;
return `${major}.0.0`;
}

function parts(version) {
return version.split(".").map((part) => Number(part));
}
Expand Down Expand Up @@ -123,7 +143,7 @@ if (channel === "main" && !hasAddresses(current.environments?.mainnet)) {
}

if (!tags.latest) {
const version = channel === "main" ? "1.0.0" : JSON.parse(readFileSync(path.join(root, "package.json"), "utf8")).version;
const version = channel === "main" ? firstMainnetVersion() : JSON.parse(readFileSync(path.join(root, "package.json"), "utf8")).version;
setVersion(version);
console.log(`First publish ${pkg}@${version} (${distTag})`);
emit({ level: "first", version, dist_tag: distTag });
Expand All @@ -135,9 +155,10 @@ if (channel === "main") {
try {
const published = JSON.parse(readFileSync(path.join(latest.pkgRoot, "deployments.json"), "utf8"));
if (!hasAddresses(published.environments?.mainnet)) {
setVersion("1.0.0");
console.log(`First mainnet manifest — publishing ${pkg}@1.0.0 on latest`);
emit({ level: "mainnet", version: "1.0.0", dist_tag: distTag });
const version = firstMainnetVersion();
setVersion(version);
console.log(`First mainnet manifest — publishing ${pkg}@${version} on latest`);
emit({ level: "mainnet", version, dist_tag: distTag });
process.exit(0);
}
} finally {
Expand Down