Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions .claude/commands/run-ci.md
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
57 changes: 57 additions & 0 deletions .github/workflows/detect-changes.yml
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"
Comment on lines +1 to +57
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Verify if this reusable workflow is actually called via workflow_call.

The detect-changes.yml is defined as a reusable workflow using workflow_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:

jobs:
  detect-changes:
    uses: ./.github/workflows/detect-changes.yml

Option B: If inline duplication is intentional (e.g., to avoid job dependency overhead), remove the standalone detect-changes.yml file to avoid confusion.

Please clarify which approach is intended.


🏁 Script executed:

#!/bin/bash
# Count how many times detect-changes job is defined across workflows
echo "=== detect-changes job definitions ==="
find .github/workflows -name "*.yml" -type f -exec grep -l "jobs:" {} \; | while read file; do
  if grep -A5 "^  detect-changes:" "$file" > /dev/null 2>&1; then
    echo "Inline in: $file"
  fi
done

echo ""
echo "=== Uses of reusable detect-changes.yml ==="
grep -r "uses:.*detect-changes" .github/workflows || echo "No reusable workflow calls found"

Length of output: 497



---

🏁 Script executed:

```shell
#!/bin/bash
# Check if script/ci-changes-detector exists
if [ -f "script/ci-changes-detector" ]; then
  echo "✓ script/ci-changes-detector exists"
  head -20 "script/ci-changes-detector"
else
  echo "✗ script/ci-changes-detector NOT found"
  find . -name "*ci-changes*" -o -name "*changes-detector*" 2>/dev/null | head -20
fi

echo ""
echo "=== Checking inline detect-changes job from main.yml ==="
grep -A 30 "^  detect-changes:" .github/workflows/main.yml | head -35

Length of output: 1893



---

🏁 Script executed:

```shell
#!/bin/bash
# Compare BASE_SHA/BASE_REF logic across workflows

echo "=== Checking BASE_SHA/BASE_REF fallback in reusable detect-changes.yml ==="
grep -A 2 "BASE_SHA=" .github/workflows/detect-changes.yml

echo ""
echo "=== Checking BASE_REF/BASE_SHA fallback in inline detect-changes jobs ==="
for file in .github/workflows/{main,lint-js-and-ruby,examples}.yml; do
  if [ -f "$file" ]; then
    echo "--- $file ---"
    grep -A 2 "BASE_REF\|BASE_SHA" "$file" | head -5
  fi
done

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 for BASE_SHA that 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.yml to eliminate duplication.

🤖 Prompt for AI Agents
.github/workflows/detect-changes.yml lines 1-57: the Detect changes step sets
BASE_SHA using only github.event.pull_request.base.sha or github.event.before,
missing the 'origin/master' fallback used elsewhere; update the BASE_SHA
assignment to include the third fallback 'origin/master' (so it tries
pull_request.base.sha, then github.event.before, then 'origin/master') and then
replace duplicated inline detect-changes jobs across workflows with calls to
this reusable workflow via uses: ./.github/workflows/detect-changes.yml to
consolidate and eliminate duplication.

60 changes: 35 additions & 25 deletions .github/workflows/examples.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

Extract duplicated detect-changes job to a shared reusable workflow.

The detect-changes job defined here is identical to the one in rspec-package-specs.yml. This duplication violates the DRY principle and creates maintenance burden—any future updates to the change detector logic must be applied to multiple files.

Extract this into a shared reusable workflow (.github/workflows/detect-changes.yml) with on: workflow_call, then call it from both workflows using jobs.detect-changes: uses: ./.github/workflows/detect-changes.yml@<ref>.

Example refactor structure:

# .github/workflows/detect-changes.yml
name: Detect changes
on:
  workflow_call:
    outputs:
      docs_only:
        value: ${{ jobs.detect.outputs.docs_only }}
      run_lint:
        value: ${{ jobs.detect.outputs.run_lint }}
      # ... other outputs
jobs:
  detect:
    runs-on: ubuntu-22.04
    outputs:
      docs_only: ${{ steps.detect.outputs.docs_only }}
      # ... other outputs
    steps:
      # ... detection steps

Then in examples.yml:

jobs:
  detect-changes:
    uses: ./.github/workflows/detect-changes.yml
🤖 Prompt for AI Agents
.github/workflows/examples.yml lines 16-40: the detect-changes job is duplicated
here (and in rspec-package-specs.yml); extract it into a reusable workflow file
.github/workflows/detect-changes.yml with on: workflow_call, move the job and
its steps there preserving outputs (docs_only, run_lint, run_js_tests,
run_ruby_tests, run_dummy_tests, run_generators), then replace the
detect-changes job in this file with a caller that uses:
./.github/workflows/detect-changes.yml@<ref> and maps/consumes the outputs as
before; ensure the reusable workflow defines the same job id (detect) and steps,
declares the outputs from steps.detect, and update both calling workflows to
reference the reusable workflow.

if: |
(github.ref == 'refs/heads/master' || needs.detect-changes.outputs.run_generators == 'true')

Check failure on line 42 in .github/workflows/examples.yml

View workflow job for this annotation

GitHub Actions / build

context "matrix" is not allowed here. available contexts are "github", "inputs", "needs", "vars". see https://docs.github.com/en/actions/learn-github-actions/contexts#context-availability for more details
&& (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
Expand All @@ -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:
Expand Down Expand Up @@ -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
Expand Down
31 changes: 31 additions & 0 deletions .github/workflows/lint-js-and-ruby.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Invoke detector via $GITHUB_WORKSPACE

The Pro pipelines currently fail (script/ci-changes-detector "$BASE_REF": No such file or directory) because those jobs run with defaults.run.working-directory: react_on_rails_pro, so the relative path can’t resolve. Point to the repository root via $GITHUB_WORKSPACE to make the command work regardless of working directory, and mirror this change in the other workflows that call the detector.

-          script/ci-changes-detector "$BASE_REF"
+          "$GITHUB_WORKSPACE/script/ci-changes-detector" "$BASE_REF"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
BASE_REF="${{ github.event.pull_request.base.sha || github.event.before || 'origin/master' }}"
script/ci-changes-detector "$BASE_REF"
shell: bash
BASE_REF="${{ github.event.pull_request.base.sha || github.event.before || 'origin/master' }}"
"$GITHUB_WORKSPACE/script/ci-changes-detector" "$BASE_REF"
shell: bash
🤖 Prompt for AI Agents
.github/workflows/lint-js-and-ruby.yml lines 33-35: the CI changes detector is
invoked with a relative path which fails when the job's working-directory is set
to react_on_rails_pro; change the invocation to use the absolute repository root
by prefixing the script path with $GITHUB_WORKSPACE (e.g.
$GITHUB_WORKSPACE/script/ci-changes-detector "$BASE_REF") so it resolves
regardless of working directory, and apply the same $GITHUB_WORKSPACE prefix to
any other workflows that call the detector.


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
Expand Down
61 changes: 44 additions & 17 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

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 can’t be found and the job exits 127. Referencing the script via $GITHUB_WORKSPACE fixes this across all workflows.

-          script/ci-changes-detector "$BASE_REF"
+          "$GITHUB_WORKSPACE/script/ci-changes-detector" "$BASE_REF"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
BASE_REF="${{ github.event.pull_request.base.sha || github.event.before || 'origin/master' }}"
script/ci-changes-detector "$BASE_REF"
shell: bash
BASE_REF="${{ github.event.pull_request.base.sha || github.event.before || 'origin/master' }}"
"$GITHUB_WORKSPACE/script/ci-changes-detector" "$BASE_REF"
shell: bash
🤖 Prompt for AI Agents
.github/workflows/main.yml lines 34-36: the workflow invokes
script/ci-changes-detector without a workspace-qualified path which fails with
exit 127 when the job's working directory isn't the repo root; update the
invocation to reference the script via $GITHUB_WORKSPACE (e.g. replace
script/ci-changes-detector with $GITHUB_WORKSPACE/script/ci-changes-detector) so
the action can find and execute the detector regardless of working directory.


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

View workflow job for this annotation

GitHub Actions / build

context "matrix" is not allowed here. available contexts are "github", "inputs", "needs", "vars". see https://docs.github.com/en/actions/learn-github-actions/contexts#context-availability for more details
&& (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
Expand Down Expand Up @@ -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

View workflow job for this annotation

GitHub Actions / build

context "matrix" is not allowed here. available contexts are "github", "inputs", "needs", "vars". see https://docs.github.com/en/actions/learn-github-actions/contexts#context-availability for more details
&& (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
Expand Down
43 changes: 42 additions & 1 deletion .github/workflows/package-js-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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

View workflow job for this annotation

GitHub Actions / build

context "matrix" is not allowed here. available contexts are "github", "inputs", "needs", "vars". see https://docs.github.com/en/actions/learn-github-actions/contexts#context-availability for more details
&& (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
Expand Down
Loading
Loading