Skip to content

Commit 2481779

Browse files
chore(ci): refine release process (#238)
* chore(ci): refine release process * chore: create tag if env var is given * chore: revert test code * Update scripts/common.ts Co-authored-by: Clément Vannicatte <[email protected]> * chore: add comment Co-authored-by: Clément Vannicatte <[email protected]>
1 parent e8e25ab commit 2481779

File tree

5 files changed

+72
-40
lines changed

5 files changed

+72
-40
lines changed

.github/workflows/process-release.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,4 @@ jobs:
2626
env:
2727
EVENT_NUMBER: ${{ github.event.issue.number }}
2828
GITHUB_TOKEN: ${{ secrets.TOKEN_RELEASE_BOT }}
29+
VERSION_TAG_ON_RELEASE: $${{ secrets.VERSION_TAG_ON_RELEASE }}

scripts/common.ts

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ export const DOCKER = Boolean(process.env.DOCKER);
1313
// This script is run by `yarn workspace ...`, which means the current working directory is `./script`
1414
export const ROOT_DIR = path.resolve(process.cwd(), '..');
1515

16+
export const ROOT_ENV_PATH = path.resolve(ROOT_DIR, '.env');
17+
1618
export const GENERATORS: Record<string, Generator> = {
1719
// Default `algoliasearch` package as it's built similarly to generated clients
1820
'javascript-algoliasearch': {
@@ -65,7 +67,17 @@ export function splitGeneratorKey(generatorKey: string): Generator {
6567
return { language, client, key: generatorKey };
6668
}
6769

68-
export function getGitHubUrl(lang: string): string {
70+
type GitHubUrl = (
71+
lang: string,
72+
options?: {
73+
token?: string;
74+
}
75+
) => string;
76+
77+
export const getGitHubUrl: GitHubUrl = (
78+
lang: string,
79+
{ token } = {}
80+
): string => {
6981
const entry = Object.entries(openapitools['generator-cli'].generators).find(
7082
(_entry) => _entry[0].startsWith(`${lang}-`)
7183
);
@@ -74,8 +86,16 @@ export function getGitHubUrl(lang: string): string {
7486
throw new Error(`\`${lang}\` is not found from \`openapitools.json\`.`);
7587
}
7688
const { gitHost, gitRepoId } = entry[1];
77-
return `https://github.com/${gitHost}/${gitRepoId}`;
78-
}
89+
90+
// GitHub Action provides a default token for authentication
91+
// https://docs.github.com/en/actions/security-guides/automatic-token-authentication
92+
// But it has access to only the self repository.
93+
// If we want to do something like pushing commits to other repositories,
94+
// we need to specify a token with more access.
95+
return token
96+
? `https://${token}:${token}@github.com/${gitHost}/${gitRepoId}`
97+
: `https://github.com/${gitHost}/${gitRepoId}`;
98+
};
7999

80100
export function createGeneratorKey({
81101
language,

scripts/release/create-release-issue.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@ import { Octokit } from '@octokit/rest';
33
import dotenv from 'dotenv';
44
import semver from 'semver';
55

6-
import { GENERATORS, LANGUAGES, run } from '../common';
6+
import { GENERATORS, LANGUAGES, ROOT_ENV_PATH, run } from '../common';
77

88
import { RELEASED_TAG, MAIN_BRANCH, OWNER, REPO } from './common';
99
import TEXT from './text';
1010

11-
dotenv.config();
11+
dotenv.config({ path: ROOT_ENV_PATH });
1212

1313
type Version = {
1414
current: string;

scripts/release/process-release.ts

Lines changed: 46 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,26 @@ import dotenv from 'dotenv';
55
import execa from 'execa';
66

77
import openapitools from '../../openapitools.json';
8-
import { toAbsolutePath, run, exists, getGitHubUrl } from '../common';
8+
import {
9+
ROOT_ENV_PATH,
10+
toAbsolutePath,
11+
run,
12+
exists,
13+
getGitHubUrl,
14+
} from '../common';
915
import { getLanguageFolder } from '../config';
1016

1117
import {
1218
RELEASED_TAG,
1319
OWNER,
1420
REPO,
1521
getMarkdownSection,
16-
getTargetBranch,
1722
getGitAuthor,
23+
getTargetBranch,
1824
} from './common';
1925
import TEXT from './text';
2026

21-
dotenv.config();
27+
dotenv.config({ path: ROOT_ENV_PATH });
2228

2329
if (!process.env.GITHUB_TOKEN) {
2430
throw new Error('Environment variable `GITHUB_TOKEN` does not exist.');
@@ -42,11 +48,18 @@ type VersionsToRelease = {
4248
[lang: string]: {
4349
current: string;
4450
next: string;
51+
dateStamp: string;
4552
};
4653
};
4754

55+
function getDateStamp(): string {
56+
return new Date().toISOString().split('T')[0];
57+
}
58+
4859
function getVersionsToRelease(issueBody: string): VersionsToRelease {
4960
const versionsToRelease: VersionsToRelease = {};
61+
const dateStamp = getDateStamp();
62+
5063
getMarkdownSection(issueBody, TEXT.versionChangeHeader)
5164
.split('\n')
5265
.forEach((line) => {
@@ -58,6 +71,7 @@ function getVersionsToRelease(issueBody: string): VersionsToRelease {
5871
versionsToRelease[lang] = {
5972
current,
6073
next,
74+
dateStamp,
6175
};
6276
});
6377

@@ -129,17 +143,10 @@ async function processRelease(): Promise<void> {
129143

130144
for (const lang of langsToReleaseOrUpdate) {
131145
// prepare the submodule
132-
const clientPath = toAbsolutePath(getLanguageFolder(lang));
133-
const targetBranch = getTargetBranch(lang);
134-
await run(`git checkout ${targetBranch}`, { cwd: clientPath });
135-
await run(`git pull origin ${targetBranch}`, { cwd: clientPath });
136-
137146
console.log(`Generating ${lang} client(s)...`);
138147
console.log(await run(`yarn cli generate ${lang}`));
139148

140-
const dateStamp = new Date().toISOString().split('T')[0];
141-
const currentVersion = versionsToRelease[lang].current;
142-
const nextVersion = versionsToRelease[lang].next;
149+
const { current, next, dateStamp } = versionsToRelease[lang];
143150

144151
// update changelog
145152
const changelogPath = toAbsolutePath(
@@ -149,9 +156,7 @@ async function processRelease(): Promise<void> {
149156
? (await fsp.readFile(changelogPath)).toString()
150157
: '';
151158
const changelogHeader = willReleaseLibrary(lang)
152-
? `## [v${nextVersion}](${getGitHubUrl(
153-
lang
154-
)}/compare/v${currentVersion}...v${nextVersion})`
159+
? `## [v${next}](${getGitHubUrl(lang)}/compare/v${current}...v${next})`
155160
: `## ${dateStamp}`;
156161
const newChangelog = getMarkdownSection(
157162
getMarkdownSection(issueBody, TEXT.changelogHeader),
@@ -162,22 +167,7 @@ async function processRelease(): Promise<void> {
162167
[changelogHeader, newChangelog, existingContent].join('\n\n')
163168
);
164169

165-
// commit changelog and the generated client
166-
await configureGitHubAuthor(clientPath);
167-
await run(`git add .`, { cwd: clientPath });
168-
if (willReleaseLibrary(lang)) {
169-
await execa('git', ['commit', '-m', `chore: release ${nextVersion}`], {
170-
cwd: clientPath,
171-
});
172-
await execa('git', ['tag', `v${nextVersion}`], { cwd: clientPath });
173-
} else {
174-
await execa('git', ['commit', '-m', `chore: update repo ${dateStamp}`], {
175-
cwd: clientPath,
176-
});
177-
}
178-
179-
// add the new reference of the submodule in the monorepo
180-
await run(`git add ${getLanguageFolder(lang)}`);
170+
await run(`git add ${changelogPath}`);
181171
}
182172

183173
// We push commits from submodules AFTER all the generations are done.
@@ -186,14 +176,37 @@ async function processRelease(): Promise<void> {
186176
const clientPath = toAbsolutePath(getLanguageFolder(lang));
187177
const targetBranch = getTargetBranch(lang);
188178

189-
await run(`git push origin ${targetBranch}`, { cwd: clientPath });
179+
const gitHubUrl = getGitHubUrl(lang, { token: process.env.GITHUB_TOKEN });
180+
const tempGitDir = `${process.env.RUNNER_TEMP}/${lang}`;
181+
await run(`rm -rf ${tempGitDir}`);
182+
await run(
183+
`git clone --depth 1 --branch ${targetBranch} ${gitHubUrl} ${tempGitDir}`
184+
);
185+
186+
await run(`cp -r ${clientPath}/ ${tempGitDir}`);
187+
await configureGitHubAuthor(tempGitDir);
188+
await run(`git add .`, { cwd: tempGitDir });
189+
190+
const { next, dateStamp } = versionsToRelease[lang];
191+
190192
if (willReleaseLibrary(lang)) {
191-
await run('git push --tags', { cwd: clientPath });
193+
await execa('git', ['commit', '-m', `chore: release ${next}`], {
194+
cwd: tempGitDir,
195+
});
196+
if (process.env.VERSION_TAG_ON_RELEASE === 'true') {
197+
await execa('git', ['tag', `v${next}`], { cwd: tempGitDir });
198+
await run(`git push --tags`, { cwd: tempGitDir });
199+
}
200+
} else {
201+
await execa('git', ['commit', '-m', `chore: update repo ${dateStamp}`], {
202+
cwd: tempGitDir,
203+
});
192204
}
205+
await run(`git push`, { cwd: tempGitDir });
193206
}
194207

195208
// Commit and push from the monorepo level.
196-
await execa('git', ['commit', '-m', TEXT.commitMessage]);
209+
await execa('git', ['commit', '-m', `chore: release ${getDateStamp()}`]);
197210
await run(`git push`);
198211

199212
// remove old `released` tag

scripts/release/text.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,4 @@ export default {
2323
`To skip this release, just close the issue.`,
2424
`- [ ] ${APPROVED}`,
2525
].join('\n'),
26-
27-
commitMessage: `chore: update versions and submodules`,
2826
};

0 commit comments

Comments
 (0)