Skip to content

Commit 753b75f

Browse files
justin808claude
andauthored
Add CI workflow to check assets:precompile output for failures (#2134)
## Summary Closes #2081 This adds a new GitHub Actions workflow that runs `RAILS_ENV=production bin/rake assets:precompile` on the dummy app and checks the output for known failure patterns that have been encountered in the past. ## Failure Patterns Detected The workflow checks for: - **Duplicate webpack compilations** - indicates rake tasks running twice (like the issue fixed in PR #2052) - **Duplicate rake task execution** - e.g., `generate_packs` running multiple times - **Module not found / cannot resolve errors** - missing dependencies - **Webpack compilation errors** - build failures - **Ruby errors** - NameError, LoadError, NoMethodError, SyntaxError - **Asset pipeline errors** - Sprockets file not found, undeclared assets - **Memory issues** - JavaScript heap out of memory, killed processes - **High warning counts** - triggers a warning annotation if >10 warnings found ## Features - Uses the same change detection as other CI jobs (skips for docs-only changes) - Uploads precompile output as an artifact for debugging when failures occur - Provides clear error annotations in GitHub Actions UI - Runs on PRs and master pushes ## Test plan - [ ] CI workflow passes on this PR - [ ] Verify the workflow runs and captures output correctly - [ ] Manually test by introducing a known failure (e.g., duplicate task execution) to verify detection works 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Chores** * Added an automated assets precompile check in CI that conditionally runs on relevant pushes and manual triggers, captures precompile output, scans for failure/warning patterns, and uploads logs as an artifact. * Introduced a standalone validation utility to analyze precompile output and fail CI on known error patterns. * **Tests / CI** * Improved package linking in CI to preserve local linked packages and made installs tolerant of minimum-dependency matrix runs by conditionally relaxing lockfile enforcement. <sub>✏️ Tip: You can customize this high-level summary in your review settings.</sub> <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 8100792 commit 753b75f

File tree

4 files changed

+486
-7
lines changed

4 files changed

+486
-7
lines changed

.github/workflows/integration-tests.yml

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -150,11 +150,12 @@ jobs:
150150
- name: yalc publish for react-on-rails
151151
run: cd packages/react-on-rails && yalc publish
152152
- name: yalc add react-on-rails
153-
run: cd react_on_rails/spec/dummy && yalc add react-on-rails
153+
# Use --link to maintain the link: protocol that matches pnpm-lock.yaml
154+
run: cd react_on_rails/spec/dummy && yalc add --link react-on-rails
154155
- name: Install Node modules with pnpm for dummy app
155156
# --ignore-workspace prevents pnpm from treating this as part of the parent workspace
156-
# The dummy app doesn't have a pnpm-lock.yaml and shouldn't use frozen lockfile
157-
run: cd react_on_rails/spec/dummy && pnpm install --ignore-workspace
157+
# minimum config changes package.json (shakapacker version), so can't use frozen lockfile
158+
run: cd react_on_rails/spec/dummy && pnpm install --ignore-workspace ${{ matrix.dependency-level == 'minimum' && '--no-frozen-lockfile' || '' }}
158159
- name: Save dummy app ruby gems to cache
159160
uses: actions/cache@v4
160161
with:
@@ -256,11 +257,12 @@ jobs:
256257
- name: yalc publish for react-on-rails
257258
run: cd packages/react-on-rails && yalc publish
258259
- name: yalc add react-on-rails
259-
run: cd react_on_rails/spec/dummy && yalc add react-on-rails
260+
# Use --link to maintain the link: protocol that matches pnpm-lock.yaml
261+
run: cd react_on_rails/spec/dummy && yalc add --link react-on-rails
260262
- name: Install Node modules with pnpm for dummy app
261263
# --ignore-workspace prevents pnpm from treating this as part of the parent workspace
262-
# The dummy app doesn't have a pnpm-lock.yaml and shouldn't use frozen lockfile
263-
run: cd react_on_rails/spec/dummy && pnpm install --ignore-workspace
264+
# minimum config changes package.json (shakapacker version), so can't use frozen lockfile
265+
run: cd react_on_rails/spec/dummy && pnpm install --ignore-workspace ${{ matrix.dependency-level == 'minimum' && '--no-frozen-lockfile' || '' }}
264266
- name: Dummy JS tests
265267
run: |
266268
cd react_on_rails/spec/dummy

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,8 @@ jobs:
132132
- name: yalc publish for react-on-rails
133133
run: cd packages/react-on-rails && yalc publish
134134
- name: yalc add react-on-rails
135-
run: cd react_on_rails/spec/dummy && yalc add react-on-rails
135+
# Use --link to maintain the link: protocol that matches pnpm-lock.yaml
136+
run: cd react_on_rails/spec/dummy && yalc add --link react-on-rails
136137
- name: Install Node modules with pnpm for dummy app
137138
# --ignore-workspace prevents pnpm from treating this as part of the parent workspace
138139
# The dummy app has its own dependencies and uses yalc links
Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
name: Assets Precompile Check
2+
3+
on:
4+
push:
5+
branches:
6+
- 'master'
7+
pull_request:
8+
paths-ignore:
9+
- '**.md'
10+
- 'docs/**'
11+
- 'react_on_rails_pro/**'
12+
workflow_dispatch:
13+
inputs:
14+
force_run:
15+
description: 'Force run all jobs (bypass detect-changes)'
16+
required: false
17+
type: boolean
18+
default: false
19+
20+
jobs:
21+
detect-changes:
22+
permissions:
23+
contents: read
24+
actions: read
25+
runs-on: ubuntu-22.04
26+
outputs:
27+
docs_only: ${{ steps.detect.outputs.docs_only }}
28+
run_dummy_tests: ${{ steps.detect.outputs.run_dummy_tests }}
29+
has_full_ci_label: ${{ steps.check-label.outputs.result }}
30+
steps:
31+
- uses: actions/checkout@v4
32+
with:
33+
fetch-depth: 50
34+
persist-credentials: false
35+
- name: Check for full-ci label
36+
id: check-label
37+
uses: ./.github/actions/check-full-ci-label
38+
- name: Detect relevant changes
39+
id: detect
40+
run: |
41+
if [ "${{ inputs.force_run }}" = "true" ] || [ "${{ steps.check-label.outputs.result }}" = "true" ]; then
42+
echo "run_dummy_tests=true" >> "$GITHUB_OUTPUT"
43+
echo "docs_only=false" >> "$GITHUB_OUTPUT"
44+
exit 0
45+
fi
46+
47+
BASE_REF="${{ github.event.pull_request.base.sha || github.event.before || 'origin/master' }}"
48+
script/ci-changes-detector "$BASE_REF"
49+
shell: bash
50+
- name: Guard docs-only master pushes
51+
if: github.event_name == 'push' && github.ref == 'refs/heads/master'
52+
uses: ./.github/actions/ensure-master-docs-safety
53+
with:
54+
docs-only: ${{ steps.detect.outputs.docs_only }}
55+
previous-sha: ${{ github.event.before }}
56+
57+
precompile-check:
58+
needs: detect-changes
59+
# Skip only if: master push AND docs-only changes
60+
# Otherwise run if: on master OR workflow_dispatch OR dummy tests needed
61+
if: |
62+
!(
63+
github.event_name == 'push' &&
64+
github.ref == 'refs/heads/master' &&
65+
needs.detect-changes.outputs.docs_only == 'true'
66+
) && (
67+
github.ref == 'refs/heads/master' ||
68+
github.event_name == 'workflow_dispatch' ||
69+
needs.detect-changes.outputs.run_dummy_tests == 'true'
70+
)
71+
runs-on: ubuntu-22.04
72+
steps:
73+
- uses: actions/checkout@v4
74+
with:
75+
persist-credentials: false
76+
- name: Setup Ruby
77+
uses: ruby/setup-ruby@v1
78+
with:
79+
ruby-version: '3.4'
80+
bundler: 2.5.9
81+
# libyaml-dev is needed for psych v5
82+
- name: Fix dependency for libyaml-dev
83+
run: sudo apt install libyaml-dev
84+
- name: Setup Node
85+
uses: ./.github/actions/setup-node-with-retry
86+
with:
87+
node-version: '22'
88+
- name: Setup pnpm
89+
uses: pnpm/action-setup@v4
90+
- name: Get pnpm store directory
91+
shell: bash
92+
run: echo "STORE_PATH=$(pnpm store path --silent)" >> "$GITHUB_ENV"
93+
- name: Setup pnpm cache
94+
uses: actions/cache@v4
95+
with:
96+
path: ${{ env.STORE_PATH }}
97+
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
98+
restore-keys: |
99+
${{ runner.os }}-pnpm-store-
100+
- name: Print system information
101+
run: |
102+
echo "Linux release: "; cat /etc/issue
103+
echo "Current user: "; whoami
104+
echo "Current directory: "; pwd
105+
echo "Ruby version: "; ruby -v
106+
echo "Node version: "; node -v
107+
echo "pnpm version: "; pnpm --version
108+
echo "Bundler version: "; bundle --version
109+
- name: Install Node modules with pnpm for renderer package
110+
run: |
111+
pnpm install --frozen-lockfile
112+
pnpm add -g yalc
113+
- name: yalc publish for react-on-rails
114+
run: cd packages/react-on-rails && yalc publish
115+
- name: yalc add react-on-rails
116+
run: cd react_on_rails/spec/dummy && yalc add react-on-rails
117+
- name: Install Node modules with pnpm for dummy app
118+
# --ignore-workspace prevents pnpm from treating this as part of the parent workspace
119+
# The dummy app doesn't have a pnpm-lock.yaml
120+
run: cd react_on_rails/spec/dummy && pnpm install --ignore-workspace
121+
- name: Save dummy app ruby gems to cache
122+
uses: actions/cache@v4
123+
with:
124+
path: react_on_rails/spec/dummy/vendor/bundle
125+
key: dummy-app-gem-cache-${{ hashFiles('react_on_rails/spec/dummy/Gemfile.lock') }}-precompile
126+
- name: Install Ruby Gems for dummy app
127+
run: |
128+
cd react_on_rails/spec/dummy
129+
bundle lock --add-platform 'x86_64-linux'
130+
if ! bundle check --path=vendor/bundle; then
131+
bundle _2.5.9_ install --path=vendor/bundle --jobs=4 --retry=3
132+
fi
133+
- name: Build ReScript files
134+
run: cd react_on_rails/spec/dummy && pnpm run build:rescript
135+
- name: Generate file system-based packs
136+
run: cd react_on_rails/spec/dummy && RAILS_ENV=production bundle exec rake react_on_rails:generate_packs
137+
- name: Clean compiled assets
138+
# Clobber removes both Sprockets assets (public/assets) and webpack output (public/webpack)
139+
# This ensures we test a fresh build, not cached "Everything's up-to-date" output
140+
run: cd react_on_rails/spec/dummy && RAILS_ENV=production bundle exec rake assets:clobber
141+
- name: Run assets:precompile and capture output
142+
# Timeout prevents hung webpack processes from running for 6 hours.
143+
# Typical precompile takes 2-5 minutes; 15 minutes is generous.
144+
timeout-minutes: 15
145+
run: |
146+
cd react_on_rails/spec/dummy
147+
148+
echo "Running RAILS_ENV=production bin/rake assets:precompile..."
149+
echo "=========================================="
150+
151+
# Run precompile and capture both stdout and stderr
152+
# Use pipefail to catch rake failures even when piped through tee
153+
set -o pipefail
154+
RAILS_ENV=production bin/rake assets:precompile 2>&1 | tee precompile_output.txt
155+
PRECOMPILE_EXIT=${PIPESTATUS[0]}
156+
157+
echo "=========================================="
158+
159+
# Check if rake command itself failed
160+
if [ "$PRECOMPILE_EXIT" -ne 0 ]; then
161+
echo "::error::Precompile command failed with exit code $PRECOMPILE_EXIT"
162+
exit "$PRECOMPILE_EXIT"
163+
fi
164+
- name: Validate precompile output
165+
run: script/validate-precompile-output react_on_rails/spec/dummy/precompile_output.txt
166+
- name: Upload precompile output
167+
if: always()
168+
uses: actions/upload-artifact@v4
169+
with:
170+
name: precompile-output-${{ github.run_id }}
171+
path: react_on_rails/spec/dummy/precompile_output.txt
172+
retention-days: 7

0 commit comments

Comments
 (0)