1+ ---
12name : CI & Release
3+
4+ # Workflow name based on selected inputs. Fallback to default Github naming when expression evaluates to empty string
5+ run-name : >-
6+ ${{
7+ inputs.release && inputs.test && 'Build ➤ Test ➤ Publish to NPM' ||
8+ inputs.release && !inputs.test && 'Build ➤ Skip Tests ➤ Publish to NPM' ||
9+ github.event_name == 'workflow_dispatch' && inputs.test && 'Build ➤ Test' ||
10+ github.event_name == 'workflow_dispatch' && !inputs.test && 'Build ➤ Skip Tests' ||
11+ ''
12+ }}
13+
214on :
3- # Build on pushes to release branches
4- push :
5- branches : ["v3"]
6- # Build on pull requests targeting release branches
15+ # Build on pushes branches that have a PR (including drafts)
716 pull_request :
8- branches : ["v3"]
17+ # Build on commits pushed to branches without a PR if it's in the allowlist
18+ push :
19+ branches : [main, v3]
20+ # https://docs.github.com/en/actions/managing-workflow-runs/manually-running-a-workflow
921 workflow_dispatch :
1022 inputs :
23+ test :
24+ description : Run tests
25+ required : true
26+ default : true
27+ type : boolean
1128 release :
1229 description : Release new version
1330 required : true
1431 default : false
1532 type : boolean
1633
34+ concurrency :
35+ # On PRs builds will cancel if new pushes happen before the CI completes, as it defines `github.head_ref` and gives it the name of the branch the PR wants to merge into
36+ # Otherwise `github.run_id` ensures that you can quickly merge a queue of PRs without causing tests to auto cancel on any of the commits pushed to main.
37+ group : ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
38+ cancel-in-progress : true
39+
1740jobs :
1841 log-the-inputs :
1942 name : Log inputs
@@ -25,61 +48,85 @@ jobs:
2548 INPUTS: ${{ toJSON(inputs) }}
2649
2750 build :
28- name : Lint & Build
2951 runs-on : ubuntu-latest
52+ name : Lint & Build
3053 steps :
31- - name : Set git to use LF
32- run : |
33- git config --global core.autocrlf false
34- git config --global core.eol lf
35- - uses : actions/checkout@v3
36- - uses : actions/setup-node@v3
54+ - uses : actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # tag=v3
55+ - uses : actions/setup-node@8c91899e586c5b171469028077307d293428b516 # tag=v3
3756 with :
38- node-version : lts/*
3957 cache : npm
58+ node-version : lts/*
4059 - run : npm ci
60+ # Linting can be skipped
4161 - run : npm run lint --if-present
42- - run : npm run prepublishOnly
62+ if : github.event.inputs.test != 'false'
63+ # But not the build script, as semantic-release will crash if this command fails so it makes sense to test it early
64+ - run : npm run prepublishOnly --if-present
4365
4466 test :
45- name : Test
4667 needs : build
68+ # The test matrix can be skipped, in case a new release needs to be fast-tracked and tests are already passing on main
69+ if : github.event.inputs.test != 'false'
70+ runs-on : ${{ matrix.os }}
71+ name : Node.js ${{ matrix.node }} / ${{ matrix.os }}
4772 strategy :
73+ # A test failing on windows doesn't mean it'll fail on macos. It's useful to let all tests run to its completion to get the full picture
74+ fail-fast : false
4875 matrix :
49- os : [ macos-latest, ubuntu-latest ]
50- node : [ lts/*, current ]
51- runs-on : ${{ matrix.os }}
76+ # Run the testing suite on each major OS with the latest LTS release of Node.js
77+ os : [macos-latest, ubuntu-latest, windows-latest]
78+ node : [lts/*]
79+ # It makes sense to also test the oldest, and latest, versions of Node.js, on ubuntu-only since it's the fastest CI runner
80+ include :
81+ - os : ubuntu-latest
82+ # Test the oldest LTS release of Node that's still receiving bugfixes and security patches, versions older than that have reached End-of-Life
83+ node : lts/-2
84+ - os : ubuntu-latest
85+ # Test the actively developed version that will become the latest LTS release next October
86+ node : current
5287 steps :
53- - uses : actions/checkout@v3
54- - uses : actions/setup-node@v3
88+ # It's only necessary to do this for windows, as mac and ubuntu are sane OS's that already use LF
89+ - name : Set git to use LF
90+ if : matrix.os == 'windows-latest'
91+ run : |
92+ git config --global core.autocrlf false
93+ git config --global core.eol lf
94+ - uses : actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # tag=v3
95+ - uses : actions/setup-node@8c91899e586c5b171469028077307d293428b516 # tag=v3
5596 with :
56- node-version : ${{ matrix.node }}
5797 cache : npm
98+ node-version : ${{ matrix.node }}
5899 - run : npm ci
59100 - run : npm test --if-present
60101
61102 release :
62- name : Semantic release
63- needs : test
64- runs-on : ubuntu-latest
103+ needs : [build, test]
65104 # only run if opt-in during workflow_dispatch
66- if : inputs.release == true
105+ if : always() && github.event.inputs.release == 'true' && needs.build.result != 'failure' && needs.test.result != 'failure' && needs.test.result != 'cancelled'
106+ runs-on : ubuntu-latest
107+ name : Semantic release
67108 steps :
68- - uses : actions/checkout@v3
109+ - uses : actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # tag= v3
69110 with :
70111 # Need to fetch entire commit history to
71112 # analyze every commit since last release
72113 fetch-depth : 0
73- - uses : actions/setup-node@v3
114+ - uses : actions/setup-node@8c91899e586c5b171469028077307d293428b516 # tag= v3
74115 with :
75- node-version : lts/*
76116 cache : npm
117+ node-version : lts/*
77118 - run : npm ci
78119 # Branches that will release new versions are defined in .releaserc.json
79- - run : npx semantic-release --dry-run
120+ - run : npx semantic-release
80121 # Don't allow interrupting the release step if the job is cancelled, as it can lead to an inconsistent state
81122 # e.g. git tags were pushed but it exited before `npm publish`
82123 if : always()
83124 env :
84125 GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
85126 NPM_TOKEN : ${{ secrets.NPM_PUBLISH_TOKEN }}
127+ # Re-run semantic release with rich logs if it failed to publish for easier debugging
128+ - run : npx semantic-release --dry-run --debug
129+ if : failure()
130+ env :
131+ GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
132+ NPM_TOKEN : ${{ secrets.NPM_PUBLISH_TOKEN }}
0 commit comments