Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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.

55 changes: 35 additions & 20 deletions .github/workflows/examples.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,45 @@ 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

examples:
needs: detect-changes
if: github.ref == 'refs/heads/master' || needs.detect-changes.outputs.run_generators == 'true'
strategy:
fail-fast: false
matrix:
ruby-version: ['3.2', '3.4']
dependency-level: ['minimum', 'latest']
# On master: test both minimum and latest. On PRs: test only latest for speed
ruby-version: ${{ github.ref == 'refs/heads/master' && fromJSON('["3.2", "3.4"]') || fromJSON('["3.4"]') }}
dependency-level: ${{ github.ref == 'refs/heads/master' && fromJSON('["minimum", "latest"]') || fromJSON('["latest"]') }}
include:
- ruby-version: '3.2'
dependency-level: 'minimum'
Expand All @@ -23,6 +53,9 @@ jobs:
dependency-level: 'latest'
- ruby-version: '3.4'
dependency-level: 'minimum'
# On PRs, exclude the minimum dependency combination to run faster
- ruby-version: ${{ github.ref != 'refs/heads/master' && '3.2' || 'none' }}
dependency-level: 'minimum'
env:
SKIP_YARN_COREPACK_CHECK: 0
BUNDLE_FROZEN: ${{ matrix.dependency-level == 'minimum' && 'false' || 'true' }}
Expand All @@ -31,23 +64,6 @@ jobs:
- 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 +124,6 @@ jobs:
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
29 changes: 29 additions & 0 deletions .github/workflows/lint-js-and-ruby.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,39 @@ 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
Expand Down
48 changes: 43 additions & 5 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,44 @@ 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 +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
if: github.ref == 'refs/heads/master' || needs.detect-changes.outputs.run_dummy_tests == 'true'
strategy:
matrix:
ruby-version: ['3.2', '3.4']
node-version: ['20', '22']
# On master: test all combinations. On PRs: test only latest versions for speed
ruby-version: ${{ github.ref == 'refs/heads/master' && fromJSON('["3.2", "3.4"]') || fromJSON('["3.4"]') }}
node-version: ${{ github.ref == 'refs/heads/master' && fromJSON('["20", "22"]') || fromJSON('["22"]') }}
include:
- ruby-version: '3.2'
node-version: '20'
Expand All @@ -24,6 +54,9 @@ jobs:
node-version: '22'
- ruby-version: '3.4'
node-version: '20'
# On PRs, exclude the minimum dependency combination to run faster
- ruby-version: ${{ github.ref != 'refs/heads/master' && '3.2' || 'none' }}
node-version: '20'
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
Expand Down Expand Up @@ -91,12 +124,14 @@ jobs:
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]
if: github.ref == 'refs/heads/master' || needs.detect-changes.outputs.run_dummy_tests == 'true'
strategy:
fail-fast: false
matrix:
ruby-version: ['3.2', '3.4']
node-version: ['20', '22']
# On master: test all combinations. On PRs: test only latest versions for speed
ruby-version: ${{ github.ref == 'refs/heads/master' && fromJSON('["3.2", "3.4"]') || fromJSON('["3.4"]') }}
node-version: ${{ github.ref == 'refs/heads/master' && fromJSON('["20", "22"]') || fromJSON('["22"]') }}
include:
- ruby-version: '3.2'
node-version: '20'
Expand All @@ -109,6 +144,9 @@ jobs:
node-version: '22'
- ruby-version: '3.4'
node-version: '20'
# On PRs, exclude the minimum dependency combination to run faster
- ruby-version: ${{ github.ref != 'refs/heads/master' && '3.2' || 'none' }}
node-version: '20'
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
Expand Down
36 changes: 35 additions & 1 deletion .github/workflows/package-js-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,47 @@ on:
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-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

build:
needs: detect-changes
if: github.ref == 'refs/heads/master' || needs.detect-changes.outputs.run_js_tests == 'true'
strategy:
matrix:
node-version: ['20', '22']
# On master: test both Node versions. On PRs: test only latest for speed
node-version: ${{ github.ref == 'refs/heads/master' && fromJSON('["20", "22"]') || fromJSON('["22"]') }}
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
Expand Down
31 changes: 29 additions & 2 deletions .github/workflows/pro-integration-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,29 @@ defaults:
working-directory: react_on_rails_pro

jobs:
detect-changes:
runs-on: ubuntu-22.04
outputs:
docs_only: ${{ steps.detect.outputs.docs_only }}
run_pro_lint: ${{ steps.detect.outputs.run_pro_lint }}
run_pro_tests: ${{ steps.detect.outputs.run_pro_tests }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
persist-credentials: false
- name: Detect relevant changes
id: detect
working-directory: ..
run: |
BASE_REF="${{ github.event.pull_request.base.sha || github.event.before || 'origin/master' }}"
script/ci-changes-detector "$BASE_REF"
shell: bash

# Build webpack test bundles for dummy app
build-dummy-app-webpack-test-bundles:
needs: detect-changes
if: github.ref == 'refs/heads/master' || needs.detect-changes.outputs.run_pro_tests == 'true'
runs-on: ubuntu-22.04
env:
REACT_ON_RAILS_PRO_LICENSE: ${{ secrets.REACT_ON_RAILS_PRO_LICENSE }}
Expand Down Expand Up @@ -96,7 +117,10 @@ jobs:

# RSpec integration tests with Node renderer
rspec-dummy-app-node-renderer:
needs: build-dummy-app-webpack-test-bundles
needs:
- detect-changes
- build-dummy-app-webpack-test-bundles
if: github.ref == 'refs/heads/master' || needs.detect-changes.outputs.run_pro_tests == 'true'
runs-on: ubuntu-22.04
env:
REACT_ON_RAILS_PRO_LICENSE: ${{ secrets.REACT_ON_RAILS_PRO_LICENSE }}
Expand Down Expand Up @@ -270,7 +294,10 @@ jobs:

# Playwright E2E tests with Redis service
dummy-app-node-renderer-e2e-tests:
needs: build-dummy-app-webpack-test-bundles
needs:
- detect-changes
- build-dummy-app-webpack-test-bundles
if: github.ref == 'refs/heads/master' || needs.detect-changes.outputs.run_pro_tests == 'true'
runs-on: ubuntu-22.04
env:
REACT_ON_RAILS_PRO_LICENSE: ${{ secrets.REACT_ON_RAILS_PRO_LICENSE }}
Expand Down
Loading
Loading