Skip to content

Commit c6629d0

Browse files
authored
fix(scripts): add dry run release and fix major bump for python (#3175)
1 parent 907c748 commit c6629d0

File tree

3 files changed

+38
-44
lines changed

3 files changed

+38
-44
lines changed

scripts/cli/index.ts

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -39,18 +39,6 @@ const flags = {
3939
flag: '-s, --skip-cache',
4040
description: 'skip cache checking to force building specs',
4141
},
42-
outputType: {
43-
flag: '-json, --output-json',
44-
description: 'outputs the spec in JSON instead of yml',
45-
},
46-
docs: {
47-
flag: '-d, --docs',
48-
description: 'generates the doc specs with the code snippets',
49-
},
50-
major: {
51-
flag: '-m, --major',
52-
description: 'triggers a major release for the given language list',
53-
},
5442
};
5543

5644
program.name('cli');
@@ -97,8 +85,8 @@ buildCommand
9785
.addArgument(args.clients)
9886
.option(flags.verbose.flag, flags.verbose.description)
9987
.option(flags.skipCache.flag, flags.skipCache.description)
100-
.option(flags.outputType.flag, flags.outputType.description)
101-
.option(flags.docs.flag, flags.docs.description)
88+
.option('-json, --output-json', 'outputs the spec in JSON instead of yml')
89+
.option('-d, --docs', 'generates the doc specs with the code snippets')
10290
.action(async (clientArg: string[], { verbose, skipCache, outputJson, docs }) => {
10391
const { client, clientList } = transformSelection({
10492
langArg: ALL,
@@ -212,8 +200,9 @@ program
212200
.description('Releases the client')
213201
.addArgument(args.languages)
214202
.option(flags.verbose.flag, flags.verbose.description)
215-
.option(flags.major.flag, flags.major.description)
216-
.action(async (langArgs: LangArg[], { verbose, major }) => {
203+
.option('-m, --major', 'triggers a major release for the given language list')
204+
.option('-d, --dry-run', 'does not push anything to GitHub')
205+
.action(async (langArgs: LangArg[], { verbose, major, dryRun }) => {
217206
setVerbose(Boolean(verbose));
218207

219208
if (langArgs.length === 0) {
@@ -223,6 +212,7 @@ program
223212
await createReleasePR({
224213
languages: langArgs.includes(ALL) ? LANGUAGES : (langArgs as Language[]),
225214
major,
215+
dryRun,
226216
});
227217
});
228218

scripts/release/createReleasePR.ts

Lines changed: 29 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,11 @@ dotenv.config({ path: ROOT_ENV_PATH });
4444

4545
export const COMMON_SCOPES = ['specs', 'clients'];
4646

47+
// python pre-releases have a pattern like `X.Y.ZaN` for alpha or `X.Y.ZbN` for beta
48+
// see https://peps.python.org/pep-0440/
49+
// It also support ruby pre-releases like `X.Y.Z.alpha.N` for alpha or `X.Y.Z.beta.N` for beta
50+
const preReleaseRegExp = new RegExp(/\d\.\d\.\d(\.?a(lpha\.)?\d+|\.?b(eta\.)?\d+)$/);
51+
4752
// Prevent fetching the same user multiple times
4853
const fetchedUsers: Record<string, string> = {};
4954

@@ -181,14 +186,13 @@ export function getNextVersion(current: string, releaseType: semver.ReleaseType
181186

182187
let nextVersion: string | null = current;
183188

184-
// python pre-releases have a pattern like `X.Y.ZaN` for alpha or `X.Y.ZbN` for beta
185-
// see https://peps.python.org/pep-0440/
186-
// It also support ruby pre-releases like `X.Y.Z.alpha.N` for alpha or `X.Y.Z.beta.N` for beta
187-
if (
188-
releaseType !== 'major' &&
189-
(/\d\.\d\.\d\.?a(lpha\.)?\d+$/.test(current) || /\d\.\d\.\d\.?b(eta\.)?\d+$/.test(current))
190-
) {
191-
nextVersion = current.replace(/\d+$/, (match) => `${parseInt(match, 10) + 1}`);
189+
const preReleaseVersion = current.match(preReleaseRegExp);
190+
if (preReleaseVersion?.length) {
191+
if (releaseType === 'major') {
192+
nextVersion = current.replace(preReleaseVersion[1], '');
193+
} else {
194+
nextVersion = current.replace(/\d+$/, (match) => `${parseInt(match, 10) + 1}`);
195+
}
192196
} else if (current.endsWith('-SNAPSHOT')) {
193197
// snapshots should not be bumped
194198
nextVersion = current;
@@ -210,11 +214,13 @@ export async function decideReleaseStrategy({
210214
commits,
211215
languages,
212216
major,
217+
dryRun,
213218
}: {
214219
versions: VersionsBeforeBump;
215220
commits: PassedCommit[];
216221
languages: Language[];
217222
major?: boolean;
223+
dryRun?: boolean;
218224
}): Promise<Versions> {
219225
const versionsToPublish: Versions = {};
220226

@@ -247,8 +253,7 @@ export async function decideReleaseStrategy({
247253

248254
console.log(`Deciding next version bump for ${lang}.`);
249255

250-
// allows forcing a client release
251-
if (process.env.LOCAL_TEST_DEV) {
256+
if (dryRun) {
252257
nbGitDiff = 1;
253258
}
254259

@@ -362,8 +367,6 @@ async function getCommits(): Promise<{
362367

363368
/**
364369
* Ensure the release environment is correct before triggering.
365-
*
366-
* You can bypass blocking checks by setting LOCAL_TEST_DEV to true.
367370
*/
368371
async function prepareGitEnvironment(): Promise<void> {
369372
ensureGitHubToken();
@@ -372,19 +375,11 @@ async function prepareGitEnvironment(): Promise<void> {
372375
await configureGitHubAuthor();
373376
}
374377

375-
if (
376-
!process.env.LOCAL_TEST_DEV &&
377-
(await run('git rev-parse --abbrev-ref HEAD')) !== MAIN_BRANCH
378-
) {
378+
if ((await run('git rev-parse --abbrev-ref HEAD')) !== MAIN_BRANCH) {
379379
throw new Error(`You can run this script only from \`${MAIN_BRANCH}\` branch.`);
380380
}
381381

382-
if (
383-
!process.env.LOCAL_TEST_DEV &&
384-
(await getNbGitDiff({
385-
head: null,
386-
})) !== 0
387-
) {
382+
if ((await getNbGitDiff({ head: null })) !== 0) {
388383
throw new Error('Working directory is not clean. Commit all the changes first.');
389384
}
390385

@@ -483,11 +478,15 @@ async function updateLTS(versions: Versions, withGraphs?: boolean): Promise<void
483478
export async function createReleasePR({
484479
languages,
485480
major,
481+
dryRun,
486482
}: {
487483
languages: Language[];
488484
major?: boolean;
485+
dryRun?: boolean;
489486
}): Promise<void> {
490-
await prepareGitEnvironment();
487+
if (!dryRun) {
488+
await prepareGitEnvironment();
489+
}
491490

492491
console.log('Searching for commits since last release...');
493492
const { validCommits, skippedCommits } = await getCommits();
@@ -538,6 +537,12 @@ export async function createReleasePR({
538537

539538
await updateLTS(versions, true);
540539

540+
if (dryRun) {
541+
console.log(' > asked for a dryrun, stopping here');
542+
543+
return;
544+
}
545+
541546
const headBranch = `chore/prepare-release-${TODAY}`;
542547
console.log(`Switching to branch: ${headBranch}`);
543548
if (await gitBranchExists(headBranch)) {
@@ -551,11 +556,7 @@ export async function createReleasePR({
551556
console.log(`Pushing updated changes to: ${headBranch}`);
552557
const commitMessage = generationCommitText.commitPrepareReleaseMessage;
553558
await run('git add .');
554-
if (process.env.LOCAL_TEST_DEV) {
555-
await run(`git commit -m "${commitMessage} [skip ci]"`);
556-
} else {
557-
await run(`CI=false git commit -m "${commitMessage}"`);
558-
}
559+
await run(`CI=false git commit -m "${commitMessage}"`);
559560

560561
// cleanup all the changes to the generated files (the ones not commited because of the pre-commit hook)
561562
await run(`git checkout .`);

website/docs/contributing/release-process.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ Once setup, you can run:
1616

1717
```bash
1818
apic release
19+
20+
# or if you just want to see what it does without pushing the releases
21+
apic release --dry-run
1922
```
2023

2124
It will create [a release PR](https://github.com/algolia/api-clients-automation/pull/545).

0 commit comments

Comments
 (0)