Skip to content

Commit c53192a

Browse files
authored
Merge pull request #96 from ConvertAPI/trunk-based-release
Trunk-based release: main, required build check, publish by GitHub Release
2 parents 8b09eea + fd2449c commit c53192a

12 files changed

Lines changed: 756 additions & 95 deletions

File tree

‎.github/dependabot.yml‎

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Weekly dependency updates, each opened as a pull request against main that must pass the `build` check
2+
# and is merged like any other change (merge commit). Merging releases nothing: a new npm version still
3+
# needs a GitHub Release (see RELEASING.md).
4+
version: 2
5+
updates:
6+
# The workflows pin every action to a commit SHA with a `# vX.Y.Z` comment; Dependabot updates both.
7+
- package-ecosystem: github-actions
8+
directory: /
9+
schedule:
10+
interval: weekly
11+
day: monday
12+
groups:
13+
github-actions:
14+
patterns: ["*"]
15+
commit-message:
16+
prefix: ci
17+
labels: [dependencies]
18+
19+
# A bump in "dependencies" raises the minimum version every consumer gets, so it belongs in the
20+
# CHANGELOG of the next release. Dev dependencies only affect the build.
21+
- package-ecosystem: npm
22+
directory: /
23+
schedule:
24+
interval: weekly
25+
day: monday
26+
groups:
27+
npm-minor-and-patch:
28+
update-types: [minor, patch]
29+
commit-message:
30+
prefix: deps
31+
labels: [dependencies]
32+
open-pull-requests-limit: 5

‎.github/examples-base-uri.js‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// Preloaded by CI before the examples (node --require): the examples call require('../lib')(token)
2+
// against the production API, so this points every client they create at CONVERT_API_BASE_URI instead.
3+
const lib = require.resolve('../lib');
4+
const ConvertAPI = require(lib);
5+
6+
if (process.env.CONVERT_API_BASE_URI) {
7+
require.cache[lib].exports = (credentials, options = {}) => ConvertAPI(
8+
credentials,
9+
Object.assign({ baseUri: process.env.CONVERT_API_BASE_URI }, options),
10+
);
11+
}

‎.github/workflows/build.yml‎

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
name: Build
2+
run-name: >-
3+
${{ github.event_name == 'pull_request' && format('Checking that #{0} builds', github.event.pull_request.number)
4+
|| format('Building {0}', github.ref_name) }}
5+
6+
# Trunk-based: main is the only long-lived branch. Every pull request and every push to main lints, tests
7+
# and builds the package on each supported Node.js LTS line and packs it, but nothing is published here:
8+
# this is a public npm package, and npm versions are permanent, so a release is a deliberate act -
9+
# publishing a GitHub Release v{semver}, which runs publish.yml. The required status check is the last
10+
# job's name, `build`, which passes only when every Node.js version passed.
11+
on:
12+
pull_request:
13+
branches: [main]
14+
push:
15+
branches: [main]
16+
workflow_dispatch:
17+
18+
permissions:
19+
contents: read
20+
21+
# A newer push to the same pull request cancels the older build; builds of main never cancel each other.
22+
concurrency:
23+
group: build-${{ github.event_name == 'pull_request' && format('pr-{0}', github.event.pull_request.number) || github.run_id }}
24+
cancel-in-progress: true
25+
26+
env:
27+
# The tests and the examples convert real files, so they run against the staging API with a staging
28+
# token. Pull requests from forks get no secrets, so their tests fail until an admin merges them.
29+
CONVERT_API_BASE_URI: https://stag-v2.convertapi.com/
30+
31+
jobs:
32+
test:
33+
name: test (Node ${{ matrix.node }})
34+
runs-on: ubuntu-latest
35+
timeout-minutes: 15
36+
strategy:
37+
fail-fast: false
38+
matrix:
39+
node: [20, 22, 24]
40+
steps:
41+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
42+
with:
43+
persist-credentials: false
44+
45+
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
46+
with:
47+
node-version: ${{ matrix.node }}
48+
cache: npm
49+
50+
# --ignore-scripts: no dependency runs install scripts on the runner.
51+
- name: Install
52+
run: npm ci --ignore-scripts
53+
54+
- name: Lint and test
55+
env:
56+
CONVERT_API_SECRET: ${{ secrets.CONVERTAPI_STAGING_TOKEN }}
57+
run: |
58+
if [ -z "$CONVERT_API_SECRET" ]; then
59+
echo "::error::The CONVERTAPI_STAGING_TOKEN secret is not available to this run (a pull request from a fork gets no secrets)"
60+
exit 1
61+
fi
62+
npm test
63+
64+
- name: Build
65+
run: npm run build
66+
67+
# The examples call the production API and catch and print their own errors, so the preload points
68+
# them at CONVERT_API_BASE_URI and any printed error fails the step.
69+
- name: Run the examples
70+
env:
71+
API_TOKEN: ${{ secrets.CONVERTAPI_STAGING_TOKEN }}
72+
run: |
73+
set -euo pipefail
74+
node --require ./.github/examples-base-uri.js examples/ 2>&1 | tee examples.log
75+
if grep -q '^Error' examples.log; then
76+
echo "::error::An example failed, see the errors above"
77+
exit 1
78+
fi
79+
80+
build:
81+
name: build
82+
needs: test
83+
# Runs even when a test job failed, so that the required check reports a failure instead of being
84+
# skipped (a skipped required check counts as passed).
85+
if: ${{ !cancelled() }}
86+
runs-on: ubuntu-latest
87+
timeout-minutes: 15
88+
steps:
89+
- name: Check every Node.js version passed
90+
env:
91+
RESULT: ${{ needs.test.result }}
92+
run: |
93+
if [ "$RESULT" != success ]; then
94+
echo "::error::The tests did not pass on every Node.js version ($RESULT)"
95+
exit 1
96+
fi
97+
98+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
99+
with:
100+
persist-credentials: false
101+
102+
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
103+
with:
104+
node-version: 24
105+
cache: npm
106+
107+
- name: Install
108+
run: npm ci --ignore-scripts
109+
110+
# A high or critical advisory in what consumers install (dev dependencies are not shipped) fails the
111+
# build rather than reaching a release.
112+
- name: Audit the runtime dependencies
113+
run: npm audit --omit=dev --audit-level=high
114+
115+
- name: Build
116+
run: npm run build
117+
118+
# A pre-release version that sorts below any real release and names the run, so a package
119+
# downloaded from this run can be tried out but never mistaken for a published one.
120+
- name: Pack
121+
id: pack
122+
env:
123+
RUN: ${{ github.run_number }}
124+
SHORT_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
125+
run: |
126+
set -euo pipefail
127+
VERSION="0.0.0-ci.$RUN.g${SHORT_SHA:0:7}"
128+
npm version "$VERSION" --no-git-tag-version --ignore-scripts
129+
mkdir out
130+
npm pack --ignore-scripts --pack-destination out
131+
test -f "out/convertapi-$VERSION.tgz"
132+
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
133+
134+
- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
135+
with:
136+
name: convertapi-${{ steps.pack.outputs.version }}
137+
path: out/
138+
retention-days: 14
139+
if-no-files-found: error
140+
141+
- name: Summary
142+
env:
143+
VERSION: ${{ steps.pack.outputs.version }}
144+
run: |
145+
{
146+
echo "| | |"
147+
echo "|---|---|"
148+
echo "| Package | \`convertapi $VERSION\` (artifact only, not published) |"
149+
echo "| Dependencies | $(jq -r '.dependencies | to_entries | map("\(.key) \(.value)") | join(", ")' package.json) |"
150+
echo "| Files | $(tar -tzf "out/convertapi-$VERSION.tgz" | wc -l) |"
151+
} >> "$GITHUB_STEP_SUMMARY"

‎.github/workflows/main.yml‎

Lines changed: 0 additions & 30 deletions
This file was deleted.

0 commit comments

Comments
 (0)