Skip to content

Commit 6ce5ef0

Browse files
committed
add option to skip packages to deprecate and restore workflows
1 parent cd19c9a commit 6ce5ef0

File tree

10 files changed

+108
-25
lines changed

10 files changed

+108
-25
lines changed

.github/workflows/deprecate_release.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,12 @@ on:
2121
description: |
2222
By default, the most recent release from HEAD (inclusive) of the target branch will be deprecated.
2323
To deprecate a different release, specify the release commit to deprecate here.
24+
packagesToSkip:
25+
required: false
26+
type: string
27+
default: []
28+
description: |
29+
JSON array with packages to skip. Empty by default.
2430
2531
jobs:
2632
install:
@@ -47,6 +53,7 @@ jobs:
4753
INPUT_DEPRECATIONMESSAGE: ${{ inputs.deprecationMessage }}
4854
INPUT_USENPMREGISTRY: ${{ inputs.useNpmRegistry }}
4955
INPUT_SEARCHFORRELEASESTARTINGFROM: ${{ inputs.searchForReleaseStartingFrom }}
56+
INPUT_PACKAGESTOSKIP: ${{ inputs.packagesToSkip }}
5057
steps:
5158
- uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # version 4.1.4
5259
with:

.github/workflows/restore_release.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@ on:
1717
description: |
1818
By default, the most recent release from HEAD (inclusive) of the target branch will be restored.
1919
To restore a different release, specify the release commit to restore here.
20+
packagesToSkip:
21+
required: false
22+
type: string
23+
default: []
24+
description: |
25+
JSON array with packages to skip. Empty by default.
2026
2127
jobs:
2228
install:
@@ -42,6 +48,7 @@ jobs:
4248
# mapping the inputs to these environment variables allows the @actions/core toolkit to pick up the inputs
4349
INPUT_USENPMREGISTRY: ${{ inputs.useNpmRegistry }}
4450
INPUT_SEARCHFORRELEASESTARTINGFROM: ${{ inputs.searchForReleaseStartingFrom }}
51+
INPUT_PACKAGESTOSKIP: ${{ inputs.packagesToSkip }}
4552
steps:
4653
- uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # version 4.1.4
4754
with:

scripts/components/git_client.ts

Lines changed: 46 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -120,10 +120,19 @@ export class GitClient {
120120
/**
121121
* Returns a list of tags that point to the given commit
122122
*/
123-
getTagsAtCommit = async (commitHash: string) => {
123+
getTagsAtCommit = async (
124+
commitHash: string,
125+
packagesToSkip?: Set<string>,
126+
) => {
124127
const { stdout: tagsString } = await this
125128
.exec`git tag --points-at ${commitHash}`;
126-
return tagsString.split(EOL).filter((line) => line.trim().length > 0);
129+
let tags = tagsString.split(EOL).filter((line) => line.trim().length > 0);
130+
if (packagesToSkip) {
131+
tags = tags.filter(
132+
(tag) => !packagesToSkip.has(tag.substring(0, tag.indexOf('@'))),
133+
);
134+
}
135+
return tags;
127136
};
128137

129138
/**
@@ -159,9 +168,15 @@ export class GitClient {
159168
* This method will walk through past release tags until it finds the previous version of all of the input package versions
160169
* If a previous version of some package cannot be found, an error is thrown.
161170
*/
162-
getPreviousReleaseTags = async (releaseCommitHash: string) => {
171+
getPreviousReleaseTags = async (
172+
releaseCommitHash: string,
173+
packagesToSkip: Set<string>,
174+
) => {
163175
await this.validateReleaseCommitHash(releaseCommitHash);
164-
const releaseTags = await this.getTagsAtCommit(releaseCommitHash);
176+
const releaseTags = await this.getTagsAtCommit(
177+
releaseCommitHash,
178+
packagesToSkip,
179+
);
165180

166181
// create a set of just the package names (strip off the version suffix) associated with this release commit
167182
const packageNamesRemaining = new Set(
@@ -175,22 +190,34 @@ export class GitClient {
175190
// the method return value that we will append release tags to in the loop
176191
const previousReleaseTags: string[] = [];
177192

178-
while (packageNamesRemaining.size > 0) {
179-
releaseCommitCursor = await this.getNearestReleaseCommit(
180-
releaseCommitCursor,
181-
{ inclusive: false },
193+
try {
194+
while (packageNamesRemaining.size > 0) {
195+
releaseCommitCursor = await this.getNearestReleaseCommit(
196+
releaseCommitCursor,
197+
{ inclusive: false },
198+
);
199+
const releaseTagsAtCursor = await this.getTagsAtCommit(
200+
releaseCommitCursor,
201+
packagesToSkip,
202+
);
203+
releaseTagsAtCursor.forEach((releaseTag) => {
204+
const { packageName } = releaseTagToNameAndVersion(releaseTag);
205+
if (packageNamesRemaining.has(packageName)) {
206+
// this means we've found the previous version of "packageNameRemaining" that was released in releaseCommitHash
207+
// so we add it to the return list and remove it from the search set
208+
previousReleaseTags.push(releaseTag);
209+
packageNamesRemaining.delete(packageName);
210+
}
211+
});
212+
}
213+
} catch (e) {
214+
// In case error was thrown print out remaining packages.
215+
packageNamesRemaining.forEach((packageName) =>
216+
console.log(
217+
`Unable to resolve previous release tags for ${packageName}`,
218+
),
182219
);
183-
const releaseTagsAtCursor =
184-
await this.getTagsAtCommit(releaseCommitCursor);
185-
releaseTagsAtCursor.forEach((releaseTag) => {
186-
const { packageName } = releaseTagToNameAndVersion(releaseTag);
187-
if (packageNamesRemaining.has(packageName)) {
188-
// this means we've found the previous version of "packageNameRemaining" that was released in releaseCommitHash
189-
// so we add it to the return list and remove it from the search set
190-
previousReleaseTags.push(releaseTag);
191-
packageNamesRemaining.delete(packageName);
192-
}
193-
});
220+
throw e;
194221
}
195222

196223
return previousReleaseTags;

scripts/components/release_deprecator.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export class ReleaseDeprecator {
1414
constructor(
1515
private readonly gitRefToStartReleaseSearchFrom: string,
1616
private readonly deprecationMessage: string,
17+
private readonly packagesToSkip: Set<string>,
1718
private readonly githubClient: GithubClient,
1819
private readonly gitClient: GitClient,
1920
private readonly npmClient: NpmClient,
@@ -41,10 +42,12 @@ export class ReleaseDeprecator {
4142

4243
const releaseTagsToDeprecate = await this.gitClient.getTagsAtCommit(
4344
releaseCommitHashToDeprecate,
45+
this.packagesToSkip,
4446
);
4547

4648
const previousReleaseTags = await this.gitClient.getPreviousReleaseTags(
4749
releaseCommitHashToDeprecate,
50+
this.packagesToSkip,
4851
);
4952

5053
// Create the changeset revert PR

scripts/components/release_lifecycle.test.ts

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ void describe('release lifecycle', async () => {
2929

3030
let cantaloupePackageName: string;
3131
let platypusPackageName: string;
32+
let brandNewPackageName: string;
3233

3334
before(async () => {
3435
await import('../start_npm_proxy.js');
@@ -43,10 +44,12 @@ void describe('release lifecycle', async () => {
4344
* It seeds the local npm proxy with a few releases of these packages.
4445
* When its done, the state of the git refs and npm dist-tags should be as follows:
4546
*
46-
* third release commit ● <- HEAD, [email protected], cantaloupe@latest
47+
* third release commit ● <- HEAD, [email protected], cantaloupe@latest, [email protected], brand-new-package@latest
4748
* |
4849
* minor bump of cantaloupe only ●
4950
* |
51+
* add brand-new-package ●
52+
* |
5053
* second release commit ● <- [email protected], platypus@latest
5154
* |
5255
* minor bump of platypus only ●
@@ -82,6 +85,8 @@ void describe('release lifecycle', async () => {
8285
`${testNameNormalized}-cantaloupe-${shortId}`.toLocaleLowerCase();
8386
platypusPackageName =
8487
`${testNameNormalized}-platypus-${shortId}`.toLocaleLowerCase();
88+
brandNewPackageName =
89+
`${testNameNormalized}-brand-new-package-${shortId}`.toLocaleLowerCase();
8590

8691
await gitClient.init();
8792
await gitClient.switchToBranch('main');
@@ -123,6 +128,11 @@ void describe('release lifecycle', async () => {
123128
await gitClient.commitAllChanges('Version Packages (second release)');
124129
await runPublishInTestDir();
125130

131+
await npmClient.initWorkspacePackage(brandNewPackageName);
132+
await setPackageToPublic(
133+
path.join(testWorkingDir, 'packages', brandNewPackageName),
134+
);
135+
126136
await commitVersionBumpChangeset(
127137
testWorkingDir,
128138
gitClient,
@@ -146,6 +156,12 @@ void describe('release lifecycle', async () => {
146156
'1.2.0',
147157
'latest',
148158
);
159+
await expectDistTagAtVersion(
160+
npmClient,
161+
brandNewPackageName,
162+
'1.0.0',
163+
'latest',
164+
);
149165
});
150166

151167
void it('can deprecate and restore packages using npm metadata', async () => {
@@ -158,6 +174,7 @@ void describe('release lifecycle', async () => {
158174
const releaseDeprecator1 = new ReleaseDeprecator(
159175
'HEAD',
160176
'the cantaloupe is rotten',
177+
new Set([brandNewPackageName]), // skip brand-new package,
161178
githubClient,
162179
gitClient,
163180
npmClient,
@@ -185,6 +202,7 @@ void describe('release lifecycle', async () => {
185202
const releaseDeprecator2 = new ReleaseDeprecator(
186203
'HEAD~',
187204
'RIP platypus',
205+
new Set([brandNewPackageName]), // skip brand-new package,
188206
githubClient,
189207
gitClient,
190208
npmClient,
@@ -213,6 +231,7 @@ void describe('release lifecycle', async () => {
213231
const releaseDeprecator3 = new ReleaseDeprecator(
214232
'HEAD~3',
215233
'real big mess',
234+
new Set([brandNewPackageName]), // skip brand-new package,
216235
githubClient,
217236
gitClient,
218237
npmClient,
@@ -252,6 +271,7 @@ void describe('release lifecycle', async () => {
252271
await gitClient.switchToBranch('main');
253272
const releaseRestorer1 = new ReleaseRestorer(
254273
'HEAD~3',
274+
new Set([brandNewPackageName]), // skip brand-new package,
255275
githubClient,
256276
gitClient,
257277
npmClient,
@@ -279,6 +299,7 @@ void describe('release lifecycle', async () => {
279299
await gitClient.switchToBranch('main');
280300
const releaseRestorer2 = new ReleaseRestorer(
281301
'HEAD~',
302+
new Set([brandNewPackageName]), // skip brand-new package,
282303
githubClient,
283304
gitClient,
284305
npmClient,
@@ -299,6 +320,7 @@ void describe('release lifecycle', async () => {
299320
await gitClient.switchToBranch('main');
300321
const releaseRestorer3 = new ReleaseRestorer(
301322
'HEAD',
323+
new Set([brandNewPackageName]), // skip brand-new package,
302324
githubClient,
303325
gitClient,
304326
npmClient,

scripts/components/release_restorer.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export class ReleaseRestorer {
1414
*/
1515
constructor(
1616
private readonly gitRefToStartReleaseSearchFrom: string,
17+
private readonly packagesToSkip: Set<string>,
1718
private readonly githubClient: GithubClient,
1819
private readonly gitClient: GitClient,
1920
private readonly npmClient: NpmClient,
@@ -39,10 +40,12 @@ export class ReleaseRestorer {
3940

4041
const releaseTagsToRestore = await this.gitClient.getTagsAtCommit(
4142
releaseCommitHashToRestore,
43+
this.packagesToSkip,
4244
);
4345

4446
const previousReleaseTags = await this.gitClient.getPreviousReleaseTags(
4547
releaseCommitHashToRestore,
48+
this.packagesToSkip,
4649
);
4750

4851
// first create the changeset restore PR

scripts/deprecate_release.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,16 @@ const npmClient = new NpmClient(
3131

3232
await npmClient.configureNpmRc();
3333

34+
const packagesToSkipJSON = getInput('packagesToSkip', {
35+
required: true,
36+
});
37+
38+
const packagesToSkip = new Set(JSON.parse(packagesToSkipJSON) as Array<string>);
39+
3440
const releaseDeprecator = new ReleaseDeprecator(
3541
searchForReleaseStartingFrom,
3642
deprecationMessage,
43+
packagesToSkip,
3744
new GithubClient(),
3845
new GitClient(),
3946
npmClient,

scripts/publish_runner.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,12 @@ export const runPublish = async (props?: PublishOptions, cwd?: string) => {
5656
if (options.snapshotRelease) {
5757
if (fs.existsSync(path.join('.changeset', 'pre.json'))) {
5858
// Snapshot releases are not allowed in pre mode.
59-
await execa('changeset', ['pre', 'exit'], execaOptions);
59+
await execa('npx', ['changeset', 'pre', 'exit'], execaOptions);
6060
}
6161
await runVersion(['--snapshot', snapshotTag], cwd);
6262
}
6363

64-
const changesetArgs = ['publish'];
64+
const changesetArgs = ['changeset', 'publish'];
6565
if (!options.includeGitTags) {
6666
changesetArgs.push('--no-git-tag');
6767
}
@@ -75,5 +75,5 @@ export const runPublish = async (props?: PublishOptions, cwd?: string) => {
7575
? { env: { npm_config_registry: 'http://localhost:4873/' } }
7676
: {}),
7777
};
78-
await execa('changeset', changesetArgs, execaPublishOptions);
78+
await execa('npx', changesetArgs, execaPublishOptions);
7979
};

scripts/restore_release.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,15 @@ const npmClient = new NpmClient(
2828

2929
await npmClient.configureNpmRc();
3030

31+
const packagesToSkipJSON = getInput('packagesToSkip', {
32+
required: true,
33+
});
34+
35+
const packagesToSkip = new Set(JSON.parse(packagesToSkipJSON) as Array<string>);
36+
3137
const releaseRestorer = new ReleaseRestorer(
3238
searchForReleaseStartingFrom,
39+
packagesToSkip,
3340
new GithubClient(),
3441
new GitClient(),
3542
npmClient,

scripts/version_runner.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ export const runVersion = async (
2323
);
2424
}
2525

26-
const args = ['version', ...additionalArgs];
27-
await execa('changeset', args, {
26+
const args = ['changeset', 'version', ...additionalArgs];
27+
await execa('npx', args, {
2828
stdio: 'inherit',
2929
cwd,
3030
});

0 commit comments

Comments
 (0)