1- name : Checks and release
1+ name : JS CI/CD Pipeline
22
33on :
44 push :
55 branches :
66 - main
7+ paths :
8+ - ' js/**'
9+ - ' scripts/**'
10+ - ' .github/workflows/js.yml'
711 pull_request :
812 types : [opened, synchronize, reopened]
13+ paths :
14+ - ' js/**'
15+ - ' scripts/**'
16+ - ' .github/workflows/js.yml'
917 # Manual release support - consolidated here to work with npm trusted publishing
1018 # npm only allows ONE workflow file as trusted publisher, so all publishing
11- # must go through this workflow (release .yml)
19+ # must go through this workflow (js .yml)
1220 workflow_dispatch :
1321 inputs :
1422 release_mode :
3240 required : false
3341 type : string
3442
35- concurrency : ${{ github.workflow }}-${{ github.ref }}
43+ concurrency :
44+ group : js-${{ github.workflow }}-${{ github.ref }}
45+ cancel-in-progress : true
46+
47+ defaults :
48+ run :
49+ working-directory : js
3650
3751jobs :
38- # Changeset check - only runs on PRs
52+ # === DETECT CHANGES - determines which jobs should run ===
53+ detect-changes :
54+ name : Detect Changes
55+ runs-on : ubuntu-latest
56+ if : github.event_name != 'workflow_dispatch'
57+ outputs :
58+ mjs-changed : ${{ steps.changes.outputs.mjs-changed }}
59+ js-changed : ${{ steps.changes.outputs.js-changed }}
60+ package-changed : ${{ steps.changes.outputs.package-changed }}
61+ docs-changed : ${{ steps.changes.outputs.docs-changed }}
62+ workflow-changed : ${{ steps.changes.outputs.workflow-changed }}
63+ any-code-changed : ${{ steps.changes.outputs.any-code-changed }}
64+ js-code-changed : ${{ steps.changes.outputs.js-code-changed }}
65+ steps :
66+ - uses : actions/checkout@v4
67+ with :
68+ fetch-depth : 0
69+
70+ - name : Detect changes
71+ id : changes
72+ working-directory : .
73+ env :
74+ GITHUB_EVENT_NAME : ${{ github.event_name }}
75+ GITHUB_BASE_SHA : ${{ github.event.pull_request.base.sha }}
76+ GITHUB_HEAD_SHA : ${{ github.event.pull_request.head.sha }}
77+ run : node scripts/detect-code-changes.mjs
78+
79+ # === CHANGESET CHECK - only runs on PRs with code changes ===
80+ # Docs-only PRs (./docs folder, markdown files) don't require changesets
3981 changeset-check :
4082 name : Check for Changesets
4183 runs-on : ubuntu-latest
42- if : github.event_name == 'pull_request'
84+ needs : [detect-changes]
85+ if : github.event_name == 'pull_request' && needs.detect-changes.outputs.js-code-changed == 'true'
4386 steps :
4487 - uses : actions/checkout@v4
4588 with :
@@ -71,12 +114,20 @@ jobs:
71114 # Pre-existing changesets from other merged PRs are ignored
72115 node scripts/validate-changeset.mjs
73116
74- # Linting and formatting - runs after changeset check on PRs, immediately on main
117+ # === LINT AND FORMAT CHECK ===
118+ # Lint runs independently of changeset-check - it's a fast check that should always run
75119 lint :
76120 name : Lint and Format Check
77121 runs-on : ubuntu-latest
78- needs : [changeset-check]
79- if : always() && (github.event_name == 'push' || needs.changeset-check.result == 'success')
122+ needs : [detect-changes]
123+ if : |
124+ github.event_name == 'push' ||
125+ github.event_name == 'workflow_dispatch' ||
126+ needs.detect-changes.outputs.mjs-changed == 'true' ||
127+ needs.detect-changes.outputs.js-changed == 'true' ||
128+ needs.detect-changes.outputs.docs-changed == 'true' ||
129+ needs.detect-changes.outputs.package-changed == 'true' ||
130+ needs.detect-changes.outputs.workflow-changed == 'true'
80131 steps :
81132 - uses : actions/checkout@v4
82133
@@ -97,12 +148,13 @@ jobs:
97148 - name : Check code duplication
98149 run : npm run check:duplication
99150
100- # Test job - runs on Node.js only (browser automation requires specific setup )
151+ # Test matrix: Node.js x 3 OS (Ubuntu, macOS, Windows )
101152 test :
102153 name : Test (Node.js on ${{ matrix.os }})
103154 runs-on : ${{ matrix.os }}
104- needs : [changeset-check]
105- if : always() && (github.event_name == 'push' || needs.changeset-check.result == 'success')
155+ needs : [detect-changes, changeset-check]
156+ # Run if: push event, OR changeset-check succeeded, OR changeset-check was skipped (docs-only PR)
157+ if : always() && (github.event_name == 'push' || github.event_name == 'workflow_dispatch' || needs.changeset-check.result == 'success' || needs.changeset-check.result == 'skipped')
106158 strategy :
107159 fail-fast : false
108160 matrix :
@@ -118,7 +170,7 @@ jobs:
118170 - name : Install dependencies
119171 run : npm install
120172
121- - name : Run unit tests
173+ - name : Run tests
122174 run : npm test
123175
124176 # Release - only runs on main after tests pass (for push events)
@@ -190,7 +242,7 @@ jobs:
190242 run : node scripts/format-github-release.mjs --release-version "${{ steps.publish.outputs.published_version }}" --repository "${{ github.repository }}" --commit-sha "${{ github.sha }}"
191243
192244 # Manual Instant Release - triggered via workflow_dispatch with instant mode
193- # This job is in release .yml because npm trusted publishing
245+ # This job is in js .yml because npm trusted publishing
194246 # only allows one workflow file to be registered as a trusted publisher
195247 instant-release :
196248 name : Instant Release
@@ -275,12 +327,12 @@ jobs:
275327 uses : peter-evans/create-pull-request@v7
276328 with :
277329 token : ${{ secrets.GITHUB_TOKEN }}
278- commit-message : ' chore: add changeset for manual ${{ github.event.inputs.bump_type }} release'
279- branch : changeset-manual-release-${{ github.run_id }}
330+ commit-message : ' chore(js) : add changeset for manual ${{ github.event.inputs.bump_type }} release'
331+ branch : changeset-manual-release-js- ${{ github.run_id }}
280332 delete-branch : true
281- title : ' chore: manual ${{ github.event.inputs.bump_type }} release'
333+ title : ' chore(js) : manual ${{ github.event.inputs.bump_type }} release'
282334 body : |
283- ## Manual Release Request
335+ ## Manual JS Release Request
284336
285337 This PR was created by a manual workflow trigger to prepare a **${{ github.event.inputs.bump_type }}** release.
286338
0 commit comments