Skip to content

Commit a41f78c

Browse files
committed
Optimize CI workflows with change-driven gating
1 parent 5f195a7 commit a41f78c

File tree

14 files changed

+1247
-31
lines changed

14 files changed

+1247
-31
lines changed

.claude/commands/run-ci.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Run CI Command
2+
3+
Analyze the current branch changes and run appropriate CI checks locally.
4+
5+
## Instructions
6+
7+
1. First, run `script/ci-changes-detector origin/master` to analyze what changed
8+
2. Show the user what the detector recommends
9+
3. Ask the user if they want to:
10+
- Run the recommended CI jobs (`bin/ci-local`)
11+
- Run all CI jobs (`bin/ci-local --all`)
12+
- Run a fast subset (`bin/ci-local --fast`)
13+
- Run specific jobs manually
14+
4. Execute the chosen option and report results
15+
5. If any jobs fail, offer to help fix the issues
16+
17+
## Options
18+
19+
- `bin/ci-local` - Run CI based on detected changes
20+
- `bin/ci-local --all` - Run all CI checks (same as CI on master)
21+
- `bin/ci-local --fast` - Run only fast checks, skip slow integration tests
22+
- `bin/ci-local [base-ref]` - Compare against a specific ref instead of origin/master
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
name: Detect Changes
2+
3+
on:
4+
workflow_call:
5+
outputs:
6+
docs_only:
7+
description: 'Only documentation files changed'
8+
value: ${{ jobs.detect.outputs.docs_only }}
9+
run_lint:
10+
description: 'Should run linting'
11+
value: ${{ jobs.detect.outputs.run_lint }}
12+
run_ruby_tests:
13+
description: 'Should run Ruby tests'
14+
value: ${{ jobs.detect.outputs.run_ruby_tests }}
15+
run_js_tests:
16+
description: 'Should run JS tests'
17+
value: ${{ jobs.detect.outputs.run_js_tests }}
18+
run_dummy_tests:
19+
description: 'Should run dummy app tests'
20+
value: ${{ jobs.detect.outputs.run_dummy_tests }}
21+
run_generators:
22+
description: 'Should run generator tests'
23+
value: ${{ jobs.detect.outputs.run_generators }}
24+
25+
jobs:
26+
detect:
27+
runs-on: ubuntu-22.04
28+
outputs:
29+
docs_only: ${{ steps.changes.outputs.docs_only }}
30+
run_lint: ${{ steps.changes.outputs.run_lint }}
31+
run_ruby_tests: ${{ steps.changes.outputs.run_ruby_tests }}
32+
run_js_tests: ${{ steps.changes.outputs.run_js_tests }}
33+
run_dummy_tests: ${{ steps.changes.outputs.run_dummy_tests }}
34+
run_generators: ${{ steps.changes.outputs.run_generators }}
35+
steps:
36+
- uses: actions/checkout@v4
37+
with:
38+
fetch-depth: 0
39+
persist-credentials: false
40+
41+
- name: Detect changes
42+
id: changes
43+
run: |
44+
# For master branch, always run everything
45+
if [ "${{ github.ref }}" = "refs/heads/master" ]; then
46+
echo "docs_only=false" >> "$GITHUB_OUTPUT"
47+
echo "run_lint=true" >> "$GITHUB_OUTPUT"
48+
echo "run_ruby_tests=true" >> "$GITHUB_OUTPUT"
49+
echo "run_js_tests=true" >> "$GITHUB_OUTPUT"
50+
echo "run_dummy_tests=true" >> "$GITHUB_OUTPUT"
51+
echo "run_generators=true" >> "$GITHUB_OUTPUT"
52+
exit 0
53+
fi
54+
55+
# For PRs, analyze changes
56+
BASE_SHA="${{ github.event.pull_request.base.sha || github.event.before }}"
57+
script/ci-changes-detector "$BASE_SHA"

.github/workflows/examples.yml

Lines changed: 35 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,45 @@ on:
44
push:
55
branches:
66
- 'master'
7+
paths-ignore:
8+
- '**.md'
9+
- 'docs/**'
710
pull_request:
11+
paths-ignore:
12+
- '**.md'
13+
- 'docs/**'
814

915
jobs:
16+
detect-changes:
17+
runs-on: ubuntu-22.04
18+
outputs:
19+
docs_only: ${{ steps.detect.outputs.docs_only }}
20+
run_lint: ${{ steps.detect.outputs.run_lint }}
21+
run_js_tests: ${{ steps.detect.outputs.run_js_tests }}
22+
run_ruby_tests: ${{ steps.detect.outputs.run_ruby_tests }}
23+
run_dummy_tests: ${{ steps.detect.outputs.run_dummy_tests }}
24+
run_generators: ${{ steps.detect.outputs.run_generators }}
25+
steps:
26+
- uses: actions/checkout@v4
27+
with:
28+
fetch-depth: 0
29+
persist-credentials: false
30+
- name: Detect relevant changes
31+
id: detect
32+
run: |
33+
BASE_REF="${{ github.event.pull_request.base.sha || github.event.before || 'origin/master' }}"
34+
script/ci-changes-detector "$BASE_REF"
35+
shell: bash
36+
1037
examples:
38+
needs: detect-changes
39+
if: github.ref == 'refs/heads/master' || needs.detect-changes.outputs.run_generators == 'true'
1140
strategy:
1241
fail-fast: false
1342
matrix:
14-
ruby-version: ['3.2', '3.4']
15-
dependency-level: ['minimum', 'latest']
43+
# On master: test both minimum and latest. On PRs: test only latest for speed
44+
ruby-version: ${{ github.ref == 'refs/heads/master' && fromJSON('["3.2", "3.4"]') || fromJSON('["3.4"]') }}
45+
dependency-level: ${{ github.ref == 'refs/heads/master' && fromJSON('["minimum", "latest"]') || fromJSON('["latest"]') }}
1646
include:
1747
- ruby-version: '3.2'
1848
dependency-level: 'minimum'
@@ -23,6 +53,9 @@ jobs:
2353
dependency-level: 'latest'
2454
- ruby-version: '3.4'
2555
dependency-level: 'minimum'
56+
# On PRs, exclude the minimum dependency combination to run faster
57+
- ruby-version: ${{ github.ref != 'refs/heads/master' && '3.2' || 'none' }}
58+
dependency-level: 'minimum'
2659
env:
2760
SKIP_YARN_COREPACK_CHECK: 0
2861
BUNDLE_FROZEN: ${{ matrix.dependency-level == 'minimum' && 'false' || 'true' }}
@@ -31,23 +64,6 @@ jobs:
3164
- uses: actions/checkout@v4
3265
with:
3366
persist-credentials: false
34-
- name: Get changed files
35-
id: changed-files
36-
run: |
37-
BASE_SHA=${{ github.event.pull_request.base.sha || github.event.before }}
38-
git fetch origin $BASE_SHA
39-
CHANGED_FILES=$(git diff --name-only $BASE_SHA ${{ github.sha }} -- \
40-
lib/generators/ \
41-
rakelib/example_type.rb \
42-
rakelib/example_config.yml \
43-
rakelib/examples.rake \
44-
rakelib/run_rspec.rake)
45-
if [ -n "$CHANGED_FILES" ]; then
46-
ANY_CHANGED=true
47-
else
48-
ANY_CHANGED=false
49-
fi
50-
echo "any_changed=$ANY_CHANGED" >> "$GITHUB_OUTPUT"
5167
- name: Setup Ruby
5268
uses: ruby/setup-ruby@v1
5369
with:
@@ -108,7 +124,6 @@ jobs:
108124
run: |
109125
echo "CI_DEPENDENCY_LEVEL=${{ matrix.dependency-level }}" >> $GITHUB_ENV
110126
- name: Main CI
111-
if: steps.changed-files.outputs.any_changed == 'true'
112127
run: bundle exec rake run_rspec:shakapacker_examples
113128
- name: Store test results
114129
uses: actions/upload-artifact@v4

.github/workflows/lint-js-and-ruby.yml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,39 @@ on:
44
push:
55
branches:
66
- 'master'
7+
paths-ignore:
8+
- '**.md'
9+
- 'docs/**'
710
pull_request:
11+
paths-ignore:
12+
- '**.md'
13+
- 'docs/**'
814

915
jobs:
16+
detect-changes:
17+
runs-on: ubuntu-22.04
18+
outputs:
19+
docs_only: ${{ steps.detect.outputs.docs_only }}
20+
run_lint: ${{ steps.detect.outputs.run_lint }}
21+
run_js_tests: ${{ steps.detect.outputs.run_js_tests }}
22+
run_ruby_tests: ${{ steps.detect.outputs.run_ruby_tests }}
23+
run_dummy_tests: ${{ steps.detect.outputs.run_dummy_tests }}
24+
run_generators: ${{ steps.detect.outputs.run_generators }}
25+
steps:
26+
- uses: actions/checkout@v4
27+
with:
28+
fetch-depth: 0
29+
persist-credentials: false
30+
- name: Detect relevant changes
31+
id: detect
32+
run: |
33+
BASE_REF="${{ github.event.pull_request.base.sha || github.event.before || 'origin/master' }}"
34+
script/ci-changes-detector "$BASE_REF"
35+
shell: bash
36+
1037
build:
38+
needs: detect-changes
39+
if: github.ref == 'refs/heads/master' || needs.detect-changes.outputs.run_lint == 'true'
1140
env:
1241
BUNDLE_FROZEN: true
1342
runs-on: ubuntu-22.04

.github/workflows/main.yml

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,44 @@ on:
44
push:
55
branches:
66
- 'master'
7+
paths-ignore:
8+
- '**.md'
9+
- 'docs/**'
710
pull_request:
11+
paths-ignore:
12+
- '**.md'
13+
- 'docs/**'
814

915
jobs:
16+
detect-changes:
17+
runs-on: ubuntu-22.04
18+
outputs:
19+
docs_only: ${{ steps.detect.outputs.docs_only }}
20+
run_lint: ${{ steps.detect.outputs.run_lint }}
21+
run_js_tests: ${{ steps.detect.outputs.run_js_tests }}
22+
run_ruby_tests: ${{ steps.detect.outputs.run_ruby_tests }}
23+
run_dummy_tests: ${{ steps.detect.outputs.run_dummy_tests }}
24+
run_generators: ${{ steps.detect.outputs.run_generators }}
25+
steps:
26+
- uses: actions/checkout@v4
27+
with:
28+
fetch-depth: 0
29+
persist-credentials: false
30+
- name: Detect relevant changes
31+
id: detect
32+
run: |
33+
BASE_REF="${{ github.event.pull_request.base.sha || github.event.before || 'origin/master' }}"
34+
script/ci-changes-detector "$BASE_REF"
35+
shell: bash
36+
1037
build-dummy-app-webpack-test-bundles:
38+
needs: detect-changes
39+
if: github.ref == 'refs/heads/master' || needs.detect-changes.outputs.run_dummy_tests == 'true'
1140
strategy:
1241
matrix:
13-
ruby-version: ['3.2', '3.4']
14-
node-version: ['20', '22']
42+
# On master: test all combinations. On PRs: test only latest versions for speed
43+
ruby-version: ${{ github.ref == 'refs/heads/master' && fromJSON('["3.2", "3.4"]') || fromJSON('["3.4"]') }}
44+
node-version: ${{ github.ref == 'refs/heads/master' && fromJSON('["20", "22"]') || fromJSON('["22"]') }}
1545
include:
1646
- ruby-version: '3.2'
1747
node-version: '20'
@@ -24,6 +54,9 @@ jobs:
2454
node-version: '22'
2555
- ruby-version: '3.4'
2656
node-version: '20'
57+
# On PRs, exclude the minimum dependency combination to run faster
58+
- ruby-version: ${{ github.ref != 'refs/heads/master' && '3.2' || 'none' }}
59+
node-version: '20'
2760
runs-on: ubuntu-22.04
2861
steps:
2962
- uses: actions/checkout@v4
@@ -91,12 +124,14 @@ jobs:
91124
key: dummy-app-webpack-bundle-${{ steps.get-sha.outputs.sha }}-ruby${{ matrix.ruby-version }}-${{ matrix.dependency-level }}
92125

93126
dummy-app-integration-tests:
94-
needs: build-dummy-app-webpack-test-bundles
127+
needs: [detect-changes, build-dummy-app-webpack-test-bundles]
128+
if: github.ref == 'refs/heads/master' || needs.detect-changes.outputs.run_dummy_tests == 'true'
95129
strategy:
96130
fail-fast: false
97131
matrix:
98-
ruby-version: ['3.2', '3.4']
99-
node-version: ['20', '22']
132+
# On master: test all combinations. On PRs: test only latest versions for speed
133+
ruby-version: ${{ github.ref == 'refs/heads/master' && fromJSON('["3.2", "3.4"]') || fromJSON('["3.4"]') }}
134+
node-version: ${{ github.ref == 'refs/heads/master' && fromJSON('["20", "22"]') || fromJSON('["22"]') }}
100135
include:
101136
- ruby-version: '3.2'
102137
node-version: '20'
@@ -109,6 +144,9 @@ jobs:
109144
node-version: '22'
110145
- ruby-version: '3.4'
111146
node-version: '20'
147+
# On PRs, exclude the minimum dependency combination to run faster
148+
- ruby-version: ${{ github.ref != 'refs/heads/master' && '3.2' || 'none' }}
149+
node-version: '20'
112150
runs-on: ubuntu-22.04
113151
steps:
114152
- uses: actions/checkout@v4

.github/workflows/package-js-tests.yml

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,47 @@ on:
44
push:
55
branches:
66
- 'master'
7+
paths-ignore:
8+
- '**.md'
9+
- 'docs/**'
10+
- 'lib/**'
11+
- 'spec/react_on_rails/**'
712
pull_request:
13+
paths-ignore:
14+
- '**.md'
15+
- 'docs/**'
16+
- 'lib/**'
17+
- 'spec/react_on_rails/**'
818

919
jobs:
20+
detect-changes:
21+
runs-on: ubuntu-22.04
22+
outputs:
23+
docs_only: ${{ steps.detect.outputs.docs_only }}
24+
run_lint: ${{ steps.detect.outputs.run_lint }}
25+
run_js_tests: ${{ steps.detect.outputs.run_js_tests }}
26+
run_ruby_tests: ${{ steps.detect.outputs.run_ruby_tests }}
27+
run_dummy_tests: ${{ steps.detect.outputs.run_dummy_tests }}
28+
run_generators: ${{ steps.detect.outputs.run_generators }}
29+
steps:
30+
- uses: actions/checkout@v4
31+
with:
32+
fetch-depth: 0
33+
persist-credentials: false
34+
- name: Detect relevant changes
35+
id: detect
36+
run: |
37+
BASE_REF="${{ github.event.pull_request.base.sha || github.event.before || 'origin/master' }}"
38+
script/ci-changes-detector "$BASE_REF"
39+
shell: bash
40+
1041
build:
42+
needs: detect-changes
43+
if: github.ref == 'refs/heads/master' || needs.detect-changes.outputs.run_js_tests == 'true'
1144
strategy:
1245
matrix:
13-
node-version: ['20', '22']
46+
# On master: test both Node versions. On PRs: test only latest for speed
47+
node-version: ${{ github.ref == 'refs/heads/master' && fromJSON('["20", "22"]') || fromJSON('["22"]') }}
1448
runs-on: ubuntu-22.04
1549
steps:
1650
- uses: actions/checkout@v4

.github/workflows/pro-integration-tests.yml

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,29 @@ defaults:
1111
working-directory: react_on_rails_pro
1212

1313
jobs:
14+
detect-changes:
15+
runs-on: ubuntu-22.04
16+
outputs:
17+
docs_only: ${{ steps.detect.outputs.docs_only }}
18+
run_pro_lint: ${{ steps.detect.outputs.run_pro_lint }}
19+
run_pro_tests: ${{ steps.detect.outputs.run_pro_tests }}
20+
steps:
21+
- uses: actions/checkout@v4
22+
with:
23+
fetch-depth: 0
24+
persist-credentials: false
25+
- name: Detect relevant changes
26+
id: detect
27+
working-directory: ..
28+
run: |
29+
BASE_REF="${{ github.event.pull_request.base.sha || github.event.before || 'origin/master' }}"
30+
script/ci-changes-detector "$BASE_REF"
31+
shell: bash
32+
1433
# Build webpack test bundles for dummy app
1534
build-dummy-app-webpack-test-bundles:
35+
needs: detect-changes
36+
if: github.ref == 'refs/heads/master' || needs.detect-changes.outputs.run_pro_tests == 'true'
1637
runs-on: ubuntu-22.04
1738
env:
1839
REACT_ON_RAILS_PRO_LICENSE: ${{ secrets.REACT_ON_RAILS_PRO_LICENSE }}
@@ -96,7 +117,10 @@ jobs:
96117

97118
# RSpec integration tests with Node renderer
98119
rspec-dummy-app-node-renderer:
99-
needs: build-dummy-app-webpack-test-bundles
120+
needs:
121+
- detect-changes
122+
- build-dummy-app-webpack-test-bundles
123+
if: github.ref == 'refs/heads/master' || needs.detect-changes.outputs.run_pro_tests == 'true'
100124
runs-on: ubuntu-22.04
101125
env:
102126
REACT_ON_RAILS_PRO_LICENSE: ${{ secrets.REACT_ON_RAILS_PRO_LICENSE }}
@@ -270,7 +294,10 @@ jobs:
270294

271295
# Playwright E2E tests with Redis service
272296
dummy-app-node-renderer-e2e-tests:
273-
needs: build-dummy-app-webpack-test-bundles
297+
needs:
298+
- detect-changes
299+
- build-dummy-app-webpack-test-bundles
300+
if: github.ref == 'refs/heads/master' || needs.detect-changes.outputs.run_pro_tests == 'true'
274301
runs-on: ubuntu-22.04
275302
env:
276303
REACT_ON_RAILS_PRO_LICENSE: ${{ secrets.REACT_ON_RAILS_PRO_LICENSE }}

0 commit comments

Comments
 (0)