Skip to content

Commit 42fe0ad

Browse files
authored
ci: Set up automated checks and npm publishing (#61)
1 parent 07b950f commit 42fe0ad

10 files changed

Lines changed: 720 additions & 16 deletions
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/* eslint-disable no-console */
2+
import { execSync } from 'node:child_process';
3+
import { readFileSync, writeFileSync } from 'node:fs';
4+
import { dirname, join } from 'node:path';
5+
import { fileURLToPath } from 'node:url';
6+
7+
const PKG_JSON_PATH = join(dirname(fileURLToPath(import.meta.url)), '..', '..', 'package.json');
8+
9+
const pkgJson = JSON.parse(readFileSync(PKG_JSON_PATH, 'utf8'));
10+
11+
const PACKAGE_NAME = pkgJson.name;
12+
const VERSION = pkgJson.version;
13+
14+
const nextVersion = addBetaSuffixToVersion(VERSION);
15+
console.log(`before-deploy: Setting version to ${nextVersion}`);
16+
pkgJson.version = nextVersion;
17+
18+
writeFileSync(PKG_JSON_PATH, `${JSON.stringify(pkgJson, null, 2)}\n`);
19+
20+
function addBetaSuffixToVersion(version) {
21+
const versionString = execSync(`npm show ${PACKAGE_NAME} versions --json`, { encoding: 'utf8' });
22+
const versions = JSON.parse(versionString);
23+
24+
if (versions.some((v) => v === version)) {
25+
console.error(
26+
`before-deploy: A release with version ${version} already exists. Please increment version accordingly.`,
27+
);
28+
process.exit(1);
29+
}
30+
31+
const prereleaseNumbers = versions
32+
.filter((v) => v.startsWith(version) && v.includes('-'))
33+
.map((v) => Number(v.match(/\.(\d+)$/)[1]));
34+
const lastPrereleaseNumber = Math.max(-1, ...prereleaseNumbers);
35+
return `${version}-beta.${lastPrereleaseNumber + 1}`;
36+
}

.github/workflows/_check_code.yaml

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
name: Code checks
2+
3+
on:
4+
workflow_call:
5+
workflow_dispatch:
6+
7+
permissions:
8+
contents: read
9+
10+
jobs:
11+
actions_lint_check:
12+
name: Actions lint check
13+
runs-on: ubuntu-latest
14+
steps:
15+
- name: Checkout repository
16+
uses: actions/checkout@v6
17+
- name: Run actionlint
18+
uses: rhysd/actionlint@v1.7.11
19+
20+
spell_check:
21+
name: Spell check
22+
runs-on: ubuntu-latest
23+
steps:
24+
- name: Checkout repository
25+
uses: actions/checkout@v6
26+
- name: Check spelling with typos
27+
uses: crate-ci/typos@v1
28+
29+
lint_check:
30+
name: Lint check
31+
runs-on: ubuntu-latest
32+
steps:
33+
- name: Checkout repository
34+
uses: actions/checkout@v6
35+
- name: Use Node.js
36+
uses: actions/setup-node@v6
37+
with:
38+
node-version: 24
39+
cache: 'npm'
40+
cache-dependency-path: 'package-lock.json'
41+
- name: Install dependencies
42+
run: npm ci
43+
- name: Lint
44+
run: npm run lint
45+
46+
type_check:
47+
name: Type check
48+
runs-on: ubuntu-latest
49+
steps:
50+
- name: Checkout repository
51+
uses: actions/checkout@v6
52+
- name: Use Node.js
53+
uses: actions/setup-node@v6
54+
with:
55+
node-version: 24
56+
cache: 'npm'
57+
cache-dependency-path: 'package-lock.json'
58+
- name: Install dependencies
59+
run: npm ci
60+
- name: Type check
61+
run: npm run type-check
62+
63+
build:
64+
name: Build
65+
runs-on: ubuntu-latest
66+
steps:
67+
- name: Checkout repository
68+
uses: actions/checkout@v6
69+
- name: Use Node.js
70+
uses: actions/setup-node@v6
71+
with:
72+
node-version: 24
73+
cache: 'npm'
74+
cache-dependency-path: 'package-lock.json'
75+
- name: Install dependencies
76+
run: npm ci
77+
- name: Build
78+
run: npm run build

.github/workflows/_tests.yaml

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
name: Tests
2+
3+
on:
4+
workflow_dispatch:
5+
workflow_call:
6+
7+
permissions:
8+
contents: read
9+
10+
jobs:
11+
unit_tests:
12+
name: Unit tests (Node.js ${{ matrix.node-version }})
13+
runs-on: ubuntu-latest
14+
15+
strategy:
16+
fail-fast: false
17+
matrix:
18+
node-version: [18, 20, 22, 24]
19+
20+
steps:
21+
- name: Checkout repository
22+
uses: actions/checkout@v6
23+
24+
- name: Use Node.js ${{ matrix.node-version }}
25+
uses: actions/setup-node@v6
26+
with:
27+
node-version: ${{ matrix.node-version }}
28+
cache: 'npm'
29+
cache-dependency-path: 'package-lock.json'
30+
31+
- name: Install dependencies
32+
run: npm ci
33+
34+
- name: Unit tests
35+
run: npm test
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
name: Update release metadata
2+
3+
on:
4+
workflow_call:
5+
inputs:
6+
release_type:
7+
description: Release type
8+
type: string
9+
default: auto
10+
custom_version:
11+
description: The custom version to bump to (only for "custom" type)
12+
type: string
13+
default: ''
14+
outputs:
15+
version_number:
16+
description: The version number for the release
17+
value: ${{ jobs.release_metadata.outputs.version_number }}
18+
tag_name:
19+
description: The tag name for the release
20+
value: ${{ jobs.release_metadata.outputs.tag_name }}
21+
changelog:
22+
description: The full changelog content
23+
value: ${{ jobs.release_metadata.outputs.changelog }}
24+
release_notes:
25+
description: The release notes for this version
26+
value: ${{ jobs.release_metadata.outputs.release_notes }}
27+
changelog_commitish:
28+
description: The commit SHA after changelog update
29+
value: ${{ jobs.update_changelog.outputs.changelog_commitish }}
30+
31+
permissions:
32+
contents: write
33+
34+
jobs:
35+
release_metadata:
36+
name: Prepare release metadata
37+
runs-on: ubuntu-latest
38+
outputs:
39+
version_number: ${{ steps.release_metadata.outputs.version_number }}
40+
tag_name: ${{ steps.release_metadata.outputs.tag_name }}
41+
changelog: ${{ steps.release_metadata.outputs.changelog }}
42+
release_notes: ${{ steps.release_metadata.outputs.release_notes }}
43+
steps:
44+
- uses: apify/workflows/git-cliff-release@main
45+
name: Prepare release metadata
46+
id: release_metadata
47+
with:
48+
release_type: ${{ inputs.release_type }}
49+
custom_version: ${{ inputs.custom_version }}
50+
existing_changelog_path: CHANGELOG.md
51+
token: ${{ secrets.APIFY_SERVICE_ACCOUNT_GITHUB_TOKEN }}
52+
53+
update_changelog:
54+
needs: [release_metadata]
55+
name: Update changelog
56+
runs-on: ubuntu-latest
57+
outputs:
58+
changelog_commitish: ${{ steps.commit.outputs.commit_long_sha || github.sha }}
59+
steps:
60+
- name: Checkout repository
61+
uses: actions/checkout@v6
62+
with:
63+
token: ${{ secrets.APIFY_SERVICE_ACCOUNT_GITHUB_TOKEN }}
64+
65+
- name: Use Node.js
66+
uses: actions/setup-node@v6
67+
with:
68+
node-version: 24
69+
70+
- name: Update package version
71+
run: npm version --no-git-tag-version --allow-same-version ${{ needs.release_metadata.outputs.version_number }}
72+
73+
- name: Update changelog
74+
uses: DamianReeves/write-file-action@master
75+
with:
76+
path: CHANGELOG.md
77+
write-mode: overwrite
78+
contents: ${{ needs.release_metadata.outputs.changelog }}
79+
80+
- name: Commit changes
81+
id: commit
82+
uses: EndBug/add-and-commit@v9
83+
with:
84+
author_name: Apify Release Bot
85+
author_email: noreply@apify.com
86+
message: 'chore(release): Update changelog and package version [skip ci]'
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
name: NPM publish
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
ref:
7+
description: Git ref to publish (branch, tag, or commit SHA)
8+
required: true
9+
type: string
10+
tag:
11+
description: NPM dist-tag
12+
required: true
13+
type: choice
14+
default: latest
15+
options:
16+
- latest
17+
- beta
18+
19+
permissions:
20+
id-token: write
21+
contents: read
22+
23+
jobs:
24+
npm_publish:
25+
name: NPM publish
26+
runs-on: ubuntu-latest
27+
steps:
28+
- name: Checkout repository
29+
uses: actions/checkout@v6
30+
with:
31+
ref: ${{ inputs.ref }}
32+
- name: Use Node.js
33+
uses: actions/setup-node@v6
34+
with:
35+
node-version: 24
36+
registry-url: 'https://registry.npmjs.org'
37+
cache: 'npm'
38+
cache-dependency-path: 'package-lock.json'
39+
- name: Update npm
40+
run: npm install -g npm@latest
41+
- name: Install dependencies
42+
run: npm ci
43+
- name: Bump pre-release version
44+
if: ${{ inputs.tag == 'beta' }}
45+
run: node ./.github/scripts/before-beta-release.js
46+
- name: Build
47+
run: npm run build
48+
- name: Publish
49+
run: npm publish --provenance --tag ${{ inputs.tag }}
50+
env:
51+
NODE_AUTH_TOKEN: ${{ secrets.APIFY_SERVICE_ACCOUNT_NPM_TOKEN }}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
name: Stable release
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
release_type:
7+
description: Release type
8+
required: true
9+
type: choice
10+
default: auto
11+
options:
12+
- auto
13+
- custom
14+
- patch
15+
- minor
16+
- major
17+
custom_version:
18+
description: The custom version to bump to (only for "custom" type)
19+
required: false
20+
type: string
21+
default: ''
22+
23+
concurrency:
24+
group: release
25+
cancel-in-progress: false
26+
27+
permissions:
28+
contents: read
29+
30+
jobs:
31+
code_checks:
32+
name: Code checks
33+
uses: ./.github/workflows/_check_code.yaml
34+
35+
tests:
36+
name: Tests
37+
uses: ./.github/workflows/_tests.yaml
38+
39+
release_metadata:
40+
name: Update release metadata
41+
needs: [code_checks, tests]
42+
permissions:
43+
contents: write
44+
uses: ./.github/workflows/_update_release_metadata.yaml
45+
secrets: inherit
46+
with:
47+
release_type: ${{ inputs.release_type }}
48+
custom_version: ${{ inputs.custom_version }}
49+
50+
github_release:
51+
name: GitHub release
52+
needs: [release_metadata]
53+
runs-on: ubuntu-latest
54+
permissions:
55+
contents: write
56+
env:
57+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
58+
steps:
59+
- name: GitHub release
60+
uses: softprops/action-gh-release@v2
61+
with:
62+
tag_name: ${{ needs.release_metadata.outputs.tag_name }}
63+
name: ${{ needs.release_metadata.outputs.version_number }}
64+
target_commitish: ${{ needs.release_metadata.outputs.changelog_commitish }}
65+
body: ${{ needs.release_metadata.outputs.release_notes }}
66+
67+
npm_publish:
68+
name: NPM publish
69+
needs: [release_metadata]
70+
runs-on: ubuntu-latest
71+
steps:
72+
- name: Execute publish workflow
73+
uses: apify/workflows/execute-workflow@main
74+
with:
75+
workflow: manual_publish_to_npm.yaml
76+
inputs: >
77+
{
78+
"ref": "${{ needs.release_metadata.outputs.changelog_commitish }}",
79+
"tag": "latest"
80+
}

0 commit comments

Comments
 (0)