-
-
Notifications
You must be signed in to change notification settings - Fork 638
Optimize CI with change-driven gating #1902
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
a41f78c
e569c15
b0b49cd
deb7bb9
fbda2dc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| # Run CI Command | ||
|
|
||
| Analyze the current branch changes and run appropriate CI checks locally. | ||
|
|
||
| ## Instructions | ||
|
|
||
| 1. First, run `script/ci-changes-detector origin/master` to analyze what changed | ||
| 2. Show the user what the detector recommends | ||
| 3. Ask the user if they want to: | ||
| - Run the recommended CI jobs (`bin/ci-local`) | ||
| - Run all CI jobs (`bin/ci-local --all`) | ||
| - Run a fast subset (`bin/ci-local --fast`) | ||
| - Run specific jobs manually | ||
| 4. Execute the chosen option and report results | ||
| 5. If any jobs fail, offer to help fix the issues | ||
|
|
||
| ## Options | ||
|
|
||
| - `bin/ci-local` - Run CI based on detected changes | ||
| - `bin/ci-local --all` - Run all CI checks (same as CI on master) | ||
| - `bin/ci-local --fast` - Run only fast checks, skip slow integration tests | ||
| - `bin/ci-local [base-ref]` - Compare against a specific ref instead of origin/master |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| name: Detect Changes | ||
|
|
||
| on: | ||
| workflow_call: | ||
| outputs: | ||
| docs_only: | ||
| description: 'Only documentation files changed' | ||
| value: ${{ jobs.detect.outputs.docs_only }} | ||
| run_lint: | ||
| description: 'Should run linting' | ||
| value: ${{ jobs.detect.outputs.run_lint }} | ||
| run_ruby_tests: | ||
| description: 'Should run Ruby tests' | ||
| value: ${{ jobs.detect.outputs.run_ruby_tests }} | ||
| run_js_tests: | ||
| description: 'Should run JS tests' | ||
| value: ${{ jobs.detect.outputs.run_js_tests }} | ||
| run_dummy_tests: | ||
| description: 'Should run dummy app tests' | ||
| value: ${{ jobs.detect.outputs.run_dummy_tests }} | ||
| run_generators: | ||
| description: 'Should run generator tests' | ||
| value: ${{ jobs.detect.outputs.run_generators }} | ||
|
|
||
| jobs: | ||
| detect: | ||
| runs-on: ubuntu-22.04 | ||
| outputs: | ||
| docs_only: ${{ steps.changes.outputs.docs_only }} | ||
| run_lint: ${{ steps.changes.outputs.run_lint }} | ||
| run_ruby_tests: ${{ steps.changes.outputs.run_ruby_tests }} | ||
| run_js_tests: ${{ steps.changes.outputs.run_js_tests }} | ||
| run_dummy_tests: ${{ steps.changes.outputs.run_dummy_tests }} | ||
| run_generators: ${{ steps.changes.outputs.run_generators }} | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| with: | ||
| fetch-depth: 0 | ||
| persist-credentials: false | ||
|
|
||
| - name: Detect changes | ||
| id: changes | ||
| run: | | ||
| # For master branch, always run everything | ||
| if [ "${{ github.ref }}" = "refs/heads/master" ]; then | ||
| echo "docs_only=false" >> "$GITHUB_OUTPUT" | ||
| echo "run_lint=true" >> "$GITHUB_OUTPUT" | ||
| echo "run_ruby_tests=true" >> "$GITHUB_OUTPUT" | ||
| echo "run_js_tests=true" >> "$GITHUB_OUTPUT" | ||
| echo "run_dummy_tests=true" >> "$GITHUB_OUTPUT" | ||
| echo "run_generators=true" >> "$GITHUB_OUTPUT" | ||
| exit 0 | ||
| fi | ||
| # For PRs, analyze changes | ||
| BASE_SHA="${{ github.event.pull_request.base.sha || github.event.before }}" | ||
| script/ci-changes-detector "$BASE_SHA" | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,24 +4,52 @@ | |
| push: | ||
| branches: | ||
| - 'master' | ||
| paths-ignore: | ||
| - '**.md' | ||
| - 'docs/**' | ||
| pull_request: | ||
| paths-ignore: | ||
| - '**.md' | ||
| - 'docs/**' | ||
|
|
||
| jobs: | ||
| detect-changes: | ||
| runs-on: ubuntu-22.04 | ||
| outputs: | ||
| docs_only: ${{ steps.detect.outputs.docs_only }} | ||
| run_lint: ${{ steps.detect.outputs.run_lint }} | ||
| run_js_tests: ${{ steps.detect.outputs.run_js_tests }} | ||
| run_ruby_tests: ${{ steps.detect.outputs.run_ruby_tests }} | ||
| run_dummy_tests: ${{ steps.detect.outputs.run_dummy_tests }} | ||
| run_generators: ${{ steps.detect.outputs.run_generators }} | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| with: | ||
| # Fetch enough history for change detection (50 commits is usually sufficient for PRs) | ||
| fetch-depth: 50 | ||
| persist-credentials: false | ||
| - name: Detect relevant changes | ||
| id: detect | ||
| run: | | ||
| BASE_REF="${{ github.event.pull_request.base.sha || github.event.before || 'origin/master' }}" | ||
| script/ci-changes-detector "$BASE_REF" | ||
| shell: bash | ||
|
|
||
| examples: | ||
| needs: detect-changes | ||
| # Run on master OR when generators changed on PR (but skip minimum deps on PR) | ||
|
||
| if: | | ||
| (github.ref == 'refs/heads/master' || needs.detect-changes.outputs.run_generators == 'true') | ||
|
Check failure on line 42 in .github/workflows/examples.yml
|
||
| && (github.ref == 'refs/heads/master' || matrix.dependency-level == 'latest') | ||
| strategy: | ||
| fail-fast: false | ||
| matrix: | ||
| ruby-version: ['3.2', '3.4'] | ||
| dependency-level: ['minimum', 'latest'] | ||
| include: | ||
| - ruby-version: '3.2' | ||
| dependency-level: 'minimum' | ||
| # Always run: Latest versions (fast feedback on PRs) | ||
| - ruby-version: '3.4' | ||
| dependency-level: 'latest' | ||
| exclude: | ||
| # Master only: Minimum supported versions (full coverage) | ||
| - ruby-version: '3.2' | ||
| dependency-level: 'latest' | ||
| - ruby-version: '3.4' | ||
| dependency-level: 'minimum' | ||
| env: | ||
| SKIP_YARN_COREPACK_CHECK: 0 | ||
|
|
@@ -31,23 +59,6 @@ | |
| - uses: actions/checkout@v4 | ||
| with: | ||
| persist-credentials: false | ||
| - name: Get changed files | ||
| id: changed-files | ||
| run: | | ||
| BASE_SHA=${{ github.event.pull_request.base.sha || github.event.before }} | ||
| git fetch origin $BASE_SHA | ||
| CHANGED_FILES=$(git diff --name-only $BASE_SHA ${{ github.sha }} -- \ | ||
| lib/generators/ \ | ||
| rakelib/example_type.rb \ | ||
| rakelib/example_config.yml \ | ||
| rakelib/examples.rake \ | ||
| rakelib/run_rspec.rake) | ||
| if [ -n "$CHANGED_FILES" ]; then | ||
| ANY_CHANGED=true | ||
| else | ||
| ANY_CHANGED=false | ||
| fi | ||
| echo "any_changed=$ANY_CHANGED" >> "$GITHUB_OUTPUT" | ||
| - name: Setup Ruby | ||
| uses: ruby/setup-ruby@v1 | ||
| with: | ||
|
|
@@ -108,7 +119,6 @@ | |
| run: | | ||
| echo "CI_DEPENDENCY_LEVEL=${{ matrix.dependency-level }}" >> $GITHUB_ENV | ||
| - name: Main CI | ||
| if: steps.changed-files.outputs.any_changed == 'true' | ||
| run: bundle exec rake run_rspec:shakapacker_examples | ||
| - name: Store test results | ||
| uses: actions/upload-artifact@v4 | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -4,16 +4,47 @@ on: | |||||||||||||
| push: | ||||||||||||||
| branches: | ||||||||||||||
| - 'master' | ||||||||||||||
| paths-ignore: | ||||||||||||||
| - '**.md' | ||||||||||||||
| - 'docs/**' | ||||||||||||||
| pull_request: | ||||||||||||||
| paths-ignore: | ||||||||||||||
| - '**.md' | ||||||||||||||
| - 'docs/**' | ||||||||||||||
|
|
||||||||||||||
| jobs: | ||||||||||||||
| detect-changes: | ||||||||||||||
| runs-on: ubuntu-22.04 | ||||||||||||||
| outputs: | ||||||||||||||
| docs_only: ${{ steps.detect.outputs.docs_only }} | ||||||||||||||
| run_lint: ${{ steps.detect.outputs.run_lint }} | ||||||||||||||
| run_js_tests: ${{ steps.detect.outputs.run_js_tests }} | ||||||||||||||
| run_ruby_tests: ${{ steps.detect.outputs.run_ruby_tests }} | ||||||||||||||
| run_dummy_tests: ${{ steps.detect.outputs.run_dummy_tests }} | ||||||||||||||
| run_generators: ${{ steps.detect.outputs.run_generators }} | ||||||||||||||
| steps: | ||||||||||||||
| - uses: actions/checkout@v4 | ||||||||||||||
| with: | ||||||||||||||
| fetch-depth: 0 | ||||||||||||||
| persist-credentials: false | ||||||||||||||
| - name: Detect relevant changes | ||||||||||||||
| id: detect | ||||||||||||||
| run: | | ||||||||||||||
| BASE_REF="${{ github.event.pull_request.base.sha || github.event.before || 'origin/master' }}" | ||||||||||||||
| script/ci-changes-detector "$BASE_REF" | ||||||||||||||
| shell: bash | ||||||||||||||
|
Comment on lines
+33
to
+35
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Invoke detector via $GITHUB_WORKSPACE The Pro pipelines currently fail ( - script/ci-changes-detector "$BASE_REF"
+ "$GITHUB_WORKSPACE/script/ci-changes-detector" "$BASE_REF"📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||
|
|
||||||||||||||
| build: | ||||||||||||||
| needs: detect-changes | ||||||||||||||
| if: github.ref == 'refs/heads/master' || needs.detect-changes.outputs.run_lint == 'true' | ||||||||||||||
| env: | ||||||||||||||
| BUNDLE_FROZEN: true | ||||||||||||||
| runs-on: ubuntu-22.04 | ||||||||||||||
| steps: | ||||||||||||||
| - uses: actions/checkout@v4 | ||||||||||||||
| with: | ||||||||||||||
| # No need for history in lint job | ||||||||||||||
| fetch-depth: 1 | ||||||||||||||
| persist-credentials: false | ||||||||||||||
| - name: Setup Ruby | ||||||||||||||
| uses: ruby/setup-ruby@v1 | ||||||||||||||
|
|
||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -4,26 +4,54 @@ | |||||||||||||
| push: | ||||||||||||||
| branches: | ||||||||||||||
| - 'master' | ||||||||||||||
| paths-ignore: | ||||||||||||||
| - '**.md' | ||||||||||||||
| - 'docs/**' | ||||||||||||||
| pull_request: | ||||||||||||||
| paths-ignore: | ||||||||||||||
| - '**.md' | ||||||||||||||
| - 'docs/**' | ||||||||||||||
|
|
||||||||||||||
| jobs: | ||||||||||||||
| detect-changes: | ||||||||||||||
| runs-on: ubuntu-22.04 | ||||||||||||||
| outputs: | ||||||||||||||
| docs_only: ${{ steps.detect.outputs.docs_only }} | ||||||||||||||
| run_lint: ${{ steps.detect.outputs.run_lint }} | ||||||||||||||
| run_js_tests: ${{ steps.detect.outputs.run_js_tests }} | ||||||||||||||
| run_ruby_tests: ${{ steps.detect.outputs.run_ruby_tests }} | ||||||||||||||
| run_dummy_tests: ${{ steps.detect.outputs.run_dummy_tests }} | ||||||||||||||
| run_generators: ${{ steps.detect.outputs.run_generators }} | ||||||||||||||
| steps: | ||||||||||||||
| - uses: actions/checkout@v4 | ||||||||||||||
| with: | ||||||||||||||
| # Fetch enough history for change detection (50 commits is usually sufficient for PRs) | ||||||||||||||
| fetch-depth: 50 | ||||||||||||||
| persist-credentials: false | ||||||||||||||
| - name: Detect relevant changes | ||||||||||||||
| id: detect | ||||||||||||||
| run: | | ||||||||||||||
| BASE_REF="${{ github.event.pull_request.base.sha || github.event.before || 'origin/master' }}" | ||||||||||||||
| script/ci-changes-detector "$BASE_REF" | ||||||||||||||
| shell: bash | ||||||||||||||
|
Comment on lines
+34
to
+36
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use workspace-qualified path for detector Same root cause as the failing Pro jobs: when the working directory isn’t the repo root, - script/ci-changes-detector "$BASE_REF"
+ "$GITHUB_WORKSPACE/script/ci-changes-detector" "$BASE_REF"📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||
|
|
||||||||||||||
| build-dummy-app-webpack-test-bundles: | ||||||||||||||
| needs: detect-changes | ||||||||||||||
| # Run on master OR when tests needed on PR (but skip minimum deps on PR) | ||||||||||||||
| if: | | ||||||||||||||
| (github.ref == 'refs/heads/master' || needs.detect-changes.outputs.run_dummy_tests == 'true') | ||||||||||||||
|
Check failure on line 42 in .github/workflows/main.yml
|
||||||||||||||
| && (github.ref == 'refs/heads/master' || matrix.dependency-level == 'latest') | ||||||||||||||
| strategy: | ||||||||||||||
| matrix: | ||||||||||||||
| ruby-version: ['3.2', '3.4'] | ||||||||||||||
| node-version: ['20', '22'] | ||||||||||||||
| include: | ||||||||||||||
| - ruby-version: '3.2' | ||||||||||||||
| node-version: '20' | ||||||||||||||
| dependency-level: 'minimum' | ||||||||||||||
| # Always run: Latest versions (fast feedback on PRs) | ||||||||||||||
| - ruby-version: '3.4' | ||||||||||||||
| node-version: '22' | ||||||||||||||
| dependency-level: 'latest' | ||||||||||||||
| exclude: | ||||||||||||||
| # Master only: Minimum supported versions (full coverage) | ||||||||||||||
| - ruby-version: '3.2' | ||||||||||||||
| node-version: '22' | ||||||||||||||
| - ruby-version: '3.4' | ||||||||||||||
| node-version: '20' | ||||||||||||||
| dependency-level: 'minimum' | ||||||||||||||
| runs-on: ubuntu-22.04 | ||||||||||||||
| steps: | ||||||||||||||
| - uses: actions/checkout@v4 | ||||||||||||||
|
|
@@ -91,24 +119,23 @@ | |||||||||||||
| key: dummy-app-webpack-bundle-${{ steps.get-sha.outputs.sha }}-ruby${{ matrix.ruby-version }}-${{ matrix.dependency-level }} | ||||||||||||||
|
|
||||||||||||||
| dummy-app-integration-tests: | ||||||||||||||
| needs: build-dummy-app-webpack-test-bundles | ||||||||||||||
| needs: [detect-changes, build-dummy-app-webpack-test-bundles] | ||||||||||||||
| # Run on master OR when tests needed on PR (but skip minimum deps on PR) | ||||||||||||||
| if: | | ||||||||||||||
| (github.ref == 'refs/heads/master' || needs.detect-changes.outputs.run_dummy_tests == 'true') | ||||||||||||||
|
Check failure on line 125 in .github/workflows/main.yml
|
||||||||||||||
| && (github.ref == 'refs/heads/master' || matrix.dependency-level == 'latest') | ||||||||||||||
| strategy: | ||||||||||||||
| fail-fast: false | ||||||||||||||
| matrix: | ||||||||||||||
| ruby-version: ['3.2', '3.4'] | ||||||||||||||
| node-version: ['20', '22'] | ||||||||||||||
| include: | ||||||||||||||
| - ruby-version: '3.2' | ||||||||||||||
| node-version: '20' | ||||||||||||||
| dependency-level: 'minimum' | ||||||||||||||
| # Always run: Latest versions (fast feedback on PRs) | ||||||||||||||
| - ruby-version: '3.4' | ||||||||||||||
| node-version: '22' | ||||||||||||||
| dependency-level: 'latest' | ||||||||||||||
| exclude: | ||||||||||||||
| # Master only: Minimum supported versions (full coverage) | ||||||||||||||
| - ruby-version: '3.2' | ||||||||||||||
| node-version: '22' | ||||||||||||||
| - ruby-version: '3.4' | ||||||||||||||
| node-version: '20' | ||||||||||||||
| dependency-level: 'minimum' | ||||||||||||||
| runs-on: ubuntu-22.04 | ||||||||||||||
| steps: | ||||||||||||||
| - uses: actions/checkout@v4 | ||||||||||||||
|
|
||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,13 +4,54 @@ | |
| push: | ||
| branches: | ||
| - 'master' | ||
| paths-ignore: | ||
| - '**.md' | ||
| - 'docs/**' | ||
| - 'lib/**' | ||
| - 'spec/react_on_rails/**' | ||
| pull_request: | ||
| paths-ignore: | ||
| - '**.md' | ||
| - 'docs/**' | ||
| - 'lib/**' | ||
| - 'spec/react_on_rails/**' | ||
|
|
||
| jobs: | ||
| detect-changes: | ||
| runs-on: ubuntu-22.04 | ||
| outputs: | ||
| docs_only: ${{ steps.detect.outputs.docs_only }} | ||
| run_lint: ${{ steps.detect.outputs.run_lint }} | ||
| run_js_tests: ${{ steps.detect.outputs.run_js_tests }} | ||
| run_ruby_tests: ${{ steps.detect.outputs.run_ruby_tests }} | ||
| run_dummy_tests: ${{ steps.detect.outputs.run_dummy_tests }} | ||
| run_generators: ${{ steps.detect.outputs.run_generators }} | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| with: | ||
| # Fetch enough history for change detection (50 commits is usually sufficient for PRs) | ||
| fetch-depth: 50 | ||
| persist-credentials: false | ||
| - name: Detect relevant changes | ||
| id: detect | ||
| run: | | ||
| BASE_REF="${{ github.event.pull_request.base.sha || github.event.before || 'origin/master' }}" | ||
| script/ci-changes-detector "$BASE_REF" | ||
| shell: bash | ||
|
|
||
| build: | ||
| needs: detect-changes | ||
| # Run on master OR when JS tests needed on PR (but skip Node 20 on PR) | ||
| if: | | ||
| (github.ref == 'refs/heads/master' || needs.detect-changes.outputs.run_js_tests == 'true') | ||
|
Check failure on line 46 in .github/workflows/package-js-tests.yml
|
||
| && (github.ref == 'refs/heads/master' || matrix.node-version == '22') | ||
| strategy: | ||
| matrix: | ||
| node-version: ['20', '22'] | ||
| include: | ||
| # Always run: Latest Node version (fast feedback on PRs) | ||
| - node-version: '22' | ||
| # Master only: Minimum supported Node version (full coverage) | ||
| - node-version: '20' | ||
| runs-on: ubuntu-22.04 | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
Verify if this reusable workflow is actually called via
workflow_call.The
detect-changes.ymlis defined as a reusable workflow usingworkflow_call, but the other workflows (main.yml, lint-js-and-ruby.yml, etc.) don't appear to call it. Instead, they duplicate the detect-changes job inline. This breaks the DRY principle and creates maintenance burden if the detection logic changes.Option A (recommended): Refactor workflows to call this reusable workflow instead of duplicating it. Example:
Option B: If inline duplication is intentional (e.g., to avoid job dependency overhead), remove the standalone
detect-changes.ymlfile to avoid confusion.Please clarify which approach is intended.
🏁 Script executed:
Length of output: 497
Length of output: 1893
Length of output: 930
Fix missing fallback in detect-changes.yml and consolidate reusable workflow usage.
The reusable workflow is correctly defined but not used—8 workflows duplicate the detect-changes job inline instead. More critically, detect-changes.yml has a bug: it lacks the
'origin/master'fallback forBASE_SHAthat all inline implementations include.Line 56 in detect-changes.yml:
BASE_SHA="${{ github.event.pull_request.base.sha || github.event.before }}"Should match the robust fallback used in main.yml, lint-js-and-ruby.yml, and others:
BASE_SHA="${{ github.event.pull_request.base.sha || github.event.before || 'origin/master' }}"Once fixed, refactor workflows to call the reusable workflow via
uses: ./.github/workflows/detect-changes.ymlto eliminate duplication.🤖 Prompt for AI Agents