Skip to content

Commit a2c089a

Browse files
committed
fix: repair published release tags idempotently
1 parent c464cf1 commit a2c089a

1 file changed

Lines changed: 37 additions & 0 deletions

File tree

‎scripts/publish-packages.mjs‎

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,31 @@ function incompleteStateMessage(state) {
8484
return details.join('; ');
8585
}
8686

87+
function repairMissingTags(state, cwd, environment) {
88+
if (state.missingVersions.length > 0 || state.missingTags.length === 0) return;
89+
for (const tag of state.missingTags) {
90+
const create = spawnSync('git', ['tag', tag], {
91+
cwd,
92+
env: environment,
93+
encoding: 'utf8',
94+
stdio: 'pipe',
95+
});
96+
if (create.status !== 0) {
97+
throw new Error(`Unable to create missing release tag ${tag}: ${create.stderr || create.error || 'git tag failed'}`);
98+
}
99+
const push = spawnSync('git', ['push', 'origin', `refs/tags/${tag}`], {
100+
cwd,
101+
env: environment,
102+
encoding: 'utf8',
103+
stdio: 'pipe',
104+
});
105+
if (push.status !== 0) {
106+
throw new Error(`Unable to push missing release tag ${tag}: ${push.stderr || push.error || 'git push failed'}`);
107+
}
108+
process.stdout.write(`Repaired missing release tag ${tag}; npm version already exists.\n`);
109+
}
110+
}
111+
87112
async function waitForCompleteState(inspect, attempts, delayMs) {
88113
let state;
89114
for (let attempt = 0; attempt < attempts; attempt += 1) {
@@ -110,6 +135,18 @@ export async function publishPackages(options = {}) {
110135
process.stdout.write(`All ${packages.length} package versions and git tags already exist; skipping publish.\n`);
111136
return;
112137
}
138+
if (initialState.missingVersions.length === 0 && initialState.missingTags.length > 0) {
139+
repairMissingTags(initialState, cwd, environment);
140+
const repairedState = await waitForCompleteState(
141+
inspect,
142+
options.postconditionAttempts ?? 5,
143+
options.postconditionDelayMs ?? 2000,
144+
);
145+
if (!repairedState.complete) {
146+
throw new Error(`Release tags were repaired but release is still incomplete: ${incompleteStateMessage(repairedState)}`);
147+
}
148+
return;
149+
}
113150

114151
const cliPath = options.cliPath ?? require.resolve('@changesets/cli/bin.js');
115152
const result = spawnSync(process.execPath, [cliPath, 'publish'], {

0 commit comments

Comments
 (0)