Skip to content

Conversation

@justin808
Copy link
Member

@justin808 justin808 commented Nov 26, 2025

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 Fix duplicate rake task execution by removing explicit task loading #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

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.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 26, 2025

Walkthrough

Adds a CI job and helper script that run RAILS_ENV=production bin/rake assets:precompile against the dummy app, capture stdout/stderr, scan the log for known failure patterns, annotate errors in GitHub Actions, and upload the precompile log as an artifact.

Changes

Cohort / File(s) Summary
Assets Precompile Check Workflow
​.github/workflows/precompile-check.yml
New workflow with detect-changes (decides whether to run based on labels/base/ref/PR diffs and exposes outputs) and precompile-check (sets up Ruby/Node/pnpm, uses yalc to publish/link react-on-rails, prepares dummy app, runs assets:precompile, captures output, scans for failure/warning patterns, emits GH Actions annotations, fails on severe patterns, and uploads artifact).
CI workflow yalc / install tweaks
​.github/workflows/integration-tests.yml, ​.github/workflows/lint-js-and-ruby.yml
Replace yalc add react-on-rails with yalc add --link react-on-rails; adjust pnpm install to append --no-frozen-lockfile for matrix.dependency-level == 'minimum'; add explanatory comments.
Precompile output validator script
script/validate-precompile-output
New executable Bash script that accepts file/stdin, checks basic integrity, scans for many known failure patterns (duplicate webpack/rake tasks, module resolution/ENOENT, webpack/build/Ruby/Bundler errors, asset pipeline and memory issues), emits structured warnings/errors (with GH Actions annotations), and returns non-zero on detected failures.

Sequence Diagram

sequenceDiagram
    actor Trigger as Workflow Trigger
    participant GHA as GitHub Actions
    participant DC as detect-changes
    participant PC as precompile-check
    participant Env as Env Setup (Ruby/Node/pnpm)
    participant Yalc as yalc (publish & link)
    participant Dummy as Dummy Rails App
    participant Scanner as validate-precompile-output

    Trigger->>GHA: workflow dispatch / push
    GHA->>DC: run detect-changes
    DC->>DC: evaluate labels/base/ref/PR diffs
    DC-->>GHA: outputs (docs_only, run_dummy_tests, has_full_ci_label)

    alt Guarded master docs-only push
        GHA->>GHA: skip precompile-check
    else Run precompile-check
        GHA->>PC: start precompile-check
        PC->>Env: setup Ruby, Node, pnpm, install deps
        Env-->>PC: environment ready
        PC->>Yalc: yalc publish && yalc add --link react-on-rails
        Yalc-->>PC: package linked
        PC->>Dummy: prepare dummy app (install, link)
        Dummy-->>PC: ready
        PC->>Dummy: run assets:precompile (capture stdout/stderr -> precompile_output.txt)
        Dummy-->>PC: precompile_output.txt
        PC->>Scanner: invoke script/validate-precompile-output
        alt Failure patterns found
            Scanner-->>GHA: emit error annotations & exit non-zero
        else No failures
            Scanner-->>GHA: pass
        end
        PC->>GHA: upload precompile_output.txt artifact
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~30–40 minutes

  • Review pattern regexes and thresholds in script/validate-precompile-output for false positives/negatives.
  • Verify detect-changes gating logic and edge cases (force_run, full-CI label, master docs-only guard).
  • Confirm yalc publish/link + pnpm install behavior works on GH runners across matrix permutations.

Possibly related PRs

Suggested reviewers

  • Judahmeek
  • AbanoubGhadban

Poem

🐰 I hopped through logs with twitching nose,
I sniffed for doubles and hidden woes.
When webpack repeats or modules hide,
I thump a warning — then watch the tide. 🥕

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately describes the main change: adding a CI workflow to validate assets:precompile output for failure patterns.
Linked Issues check ✅ Passed All primary objectives from issue #2081 are met: workflow runs assets:precompile, captures output, validates against failure patterns, integrates with existing CI change detection, uploads artifacts, and provides error annotations.
Out of Scope Changes check ✅ Passed All changes are directly related to implementing the precompile validation workflow. Updates to existing workflows (integration-tests.yml and lint-js-and-ruby.yml) use yalc --link for consistency, supporting the new validation.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch jg/precompile-ci-check

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@claude
Copy link

claude bot commented Nov 26, 2025

Code Review for PR #2134: Assets Precompile Check Workflow

I've reviewed this PR against the repository's CLAUDE.md guidelines and best practices. Overall, this is a well-structured addition that addresses a real pain point (issue #2081). Here's my detailed feedback:


✅ Strengths

1. Excellent Problem Alignment

2. Consistent with Existing CI Patterns

  • Properly integrates with the detect-changes job and change detection system
  • Uses the same conditional logic as other workflows (lines 61-70)
  • Follows the paths-ignore pattern for docs/Pro files

3. Good Error Detection Coverage

The 8 failure patterns cover realistic scenarios:

  • Duplicate task execution (lines 148-159, 162-168) ✅
  • Module resolution errors (lines 171-174) ✅
  • Webpack compilation failures (lines 177-179) ✅
  • Ruby runtime errors (lines 183-186) ✅
  • Asset pipeline issues (lines 189-192) ✅
  • Memory problems (lines 195-198) ✅
  • High warning counts (lines 201-204) ✅

4. Helpful Debugging Features

  • Captures full output with tee (line 139)
  • Uploads artifacts for failed runs (lines 220-226)
  • Clear error annotations using GitHub Actions syntax (e.g., ::error::)

🔍 Issues & Suggestions

1. Critical: Logic Error in Duplicate Compilation Detection (Lines 148-159)

Current code:

WEBPACK_COMPILE_COUNT=$(grep -c "Compiled" precompile_output.txt || true)
if [ "$WEBPACK_COMPILE_COUNT" -gt 1 ]; then
  DUPLICATE_COMPILES=$(sort precompile_output.txt | uniq -d | grep -c "Compiled" || true)
  if [ "$DUPLICATE_COMPILES" -gt 0 ]; then
    echo "::error::FAILURE: Detected duplicate webpack compilations..."

Problem: sort precompile_output.txt | uniq -d only detects consecutive identical lines. Webpack compilation messages are rarely identical character-for-character because they include timestamps, file sizes, hash values, and compilation times.

Example that would NOT be detected:

Compiled successfully in 2453ms
Compiled successfully in 2461ms  ← Different timestamp, won't be caught by uniq -d

Recommended fix:

# Count how many times the word "Compiled" appears in the output
WEBPACK_COMPILE_COUNT=$(grep -c "Compiled" precompile_output.txt || true)

# If we see "Compiled" more than once, it's likely a duplicate execution
# (Shakapacker typically only compiles once during assets:precompile)
if [ "$WEBPACK_COMPILE_COUNT" -gt 1 ]; then
  echo "::error::FAILURE: Detected $WEBPACK_COMPILE_COUNT webpack compilations (expected 1)."
  echo "  This may indicate rake tasks are running multiple times."
  FAILURES_FOUND=1
fi

2. Minor: Possible Path Inconsistency (Line 116)

Lines 116, 118, 132, and 225 use react_on_rails/spec/dummy, but based on CLAUDE.md, the dummy app should be at spec/dummy/ (root level).

Verification needed: Check if react_on_rails/ is now a subdirectory in this repo. If not, these paths should be updated to spec/dummy.

3. Enhancement: Add Exit Code Check (After Line 139)

The current script only checks patterns in the output, but doesn't verify that rake assets:precompile itself succeeded.

Recommended addition:

# Run precompile and capture exit code
RAILS_ENV=production bin/rake assets:precompile 2>&1 | tee precompile_output.txt
PRECOMPILE_EXIT_CODE=${PIPESTATUS[0]}

if [ $PRECOMPILE_EXIT_CODE -ne 0 ]; then
  echo "::error::FAILURE: rake assets:precompile exited with status $PRECOMPILE_EXIT_CODE"
  exit $PRECOMPILE_EXIT_CODE
fi

4. Minor: Overly Broad Ruby Error Detection (Lines 183-186)

Current:

if grep -Ei "NameError|LoadError|NoMethodError|SyntaxError" precompile_output.txt; then

Issue: This could trigger false positives from comments, logs, or handled exceptions.

Recommended refinement:

# Look for actual error traces, not just the word "Error"
if grep -E "^[[:space:]]*(NameError|LoadError|NoMethodError|SyntaxError):" precompile_output.txt; then
  echo "::error::FAILURE: Ruby errors detected during precompile."
  FAILURES_FOUND=1
fi

This anchors the pattern to error message format, reducing false positives.

5. Enhancement: Show Matching Lines on Failure

When a pattern matches, showing which lines matched would aid debugging:

if grep -Ei "module not found|cannot find module|can't resolve" precompile_output.txt; then
  echo "::error::FAILURE: Module resolution errors detected in precompile output."
  echo "Matching lines:"
  grep -Ei "module not found|cannot find module|can't resolve" precompile_output.txt | head -10
  FAILURES_FOUND=1
fi

🛡️ Security Considerations

✅ No security concerns identified:

  • Uses standard GitHub Actions and trusted actions
  • No credential handling or secrets exposure
  • Output artifacts have appropriate 7-day retention

🧪 Test Coverage Recommendations

Recommended test plan:

  1. Test duplicate task detection: Temporarily re-introduce the duplicate load bug and verify detection
  2. Test module not found: Add a non-existent import temporarily
  3. Test with clean precompile: Verify workflow passes on current code
  4. Test paths-ignore: Verify workflow skips for docs-only changes

📋 Adherence to CLAUDE.md Guidelines

Follows change detection pattern from existing workflows
Uses PNPM (lines 89, 111, 118) as required
Proper job naming and structure
Uses ubuntu-22.04 runner consistent with other workflows
Ruby 3.4 / Node 22 matches "latest" configuration
⚠️ Path consistency - verify react_on_rails/spec/dummy vs spec/dummy


🎯 Overall Assessment

Quality: High
Impact: Positive - prevents regression of critical bugs
Recommendation:Approve with changes

Required Changes:

  1. Fix the duplicate compilation detection logic (lines 148-159)
  2. Verify and correct the dummy app paths (lines 116, 118, 132, 225)
  3. Add exit code check for the rake command

Optional Enhancements:

  1. Refine Ruby error pattern matching
  2. Add matched line output for easier debugging

Great work on this defensive CI addition! Once the duplicate detection logic is fixed, this will be a valuable safeguard against infrastructure regressions.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (4)
.github/workflows/precompile-check.yml (4)

163-170: Add context to task duplication error for debugging.

When react_on_rails:generate_packs is detected running multiple times, the error message (line 167) only shows the count, not the actual lines or execution order. This makes it harder to understand what triggered the duplication.

          # Pattern 2: Duplicate task execution messages
          if grep -q "react_on_rails:generate_packs" precompile_output.txt; then
            GENERATE_PACKS_COUNT=$(grep -c "react_on_rails:generate_packs" precompile_output.txt || true)
            if [ "$GENERATE_PACKS_COUNT" -gt 1 ]; then
              echo "::error::FAILURE: react_on_rails:generate_packs task ran $GENERATE_PACKS_COUNT times (should only run once)."
+             echo "  Matching lines:"
+             grep -n "react_on_rails:generate_packs" precompile_output.txt
              FAILURES_FOUND=1
            fi
          fi

172-176: Add context to module resolution error for debugging.

When module resolution errors are detected, only a generic message is shown. Including sample matching lines makes it easier to triage issues in CI.

          # Pattern 3: Module not found errors
          if grep -Ei "module not found|cannot find module|can't resolve" precompile_output.txt; then
            echo "::error::FAILURE: Module resolution errors detected in precompile output."
+           echo "  Sample matching lines:"
+           grep -Ei "module not found|cannot find module|can't resolve" precompile_output.txt | head -3
            FAILURES_FOUND=1
          fi

190-194: Sprockets error pattern could be case-sensitive mismatch.

The pattern "sprockets::filenotfound" (line 191) uses lowercase, but actual Ruby exception class names typically follow PascalCase (e.g., Sprockets::FileNotFound). While -Ei makes the grep case-insensitive, the class name would be more clearly matched with the proper casing shown in the pattern.

-         if grep -Ei "sprockets::filenotfound|asset .* was not declared" precompile_output.txt; then
+         if grep -Ei "Sprockets::FileNotFound|Asset.*was not declared" precompile_output.txt; then
            echo "::error::FAILURE: Asset pipeline errors detected."
+           echo "  Sample matching lines:"
+           grep -Ei "Sprockets::FileNotFound|Asset.*was not declared" precompile_output.txt | head -3
            FAILURES_FOUND=1
          fi

202-206: Warning count detection uses case-insensitive match; clarify intent or adjust threshold.

The pattern grep -ci "warning" matches any line containing "warning" (case-insensitive). This could include false positives from messages like "This is a warning to users" or unrelated logging. The threshold of >10 warnings is also arbitrary and may not reflect actual build health.

Consider narrowing the pattern to specific warning types (e.g., webpack or Rails deprecation warnings) or document the current threshold choice:

          # Pattern 8: Check for warnings that might indicate problems
-         WARNING_COUNT=$(grep -ci "warning" precompile_output.txt || true)
+         # Count webpack/build warnings (case-insensitive to catch "Warning:" and similar)
+         WARNING_COUNT=$(grep -Ei "warning|warn" precompile_output.txt | grep -v "User warning" | wc -l || true)
          if [ "$WARNING_COUNT" -gt 10 ]; then
-           echo "::warning::High number of warnings detected: $WARNING_COUNT warnings found. Please review."
+           echo "::warning::High number of build warnings detected: $WARNING_COUNT warnings found. Please review."
+           echo "  Sample warnings:"
+           grep -Ei "warning|warn" precompile_output.txt | grep -v "User warning" | head -3
          fi

This helps distinguish build warnings from other logged text.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 16b3908 and 4160998.

📒 Files selected for processing (1)
  • .github/workflows/precompile-check.yml (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: Applies to lib/react_on_rails/*.rb : Create RBS signature files for new Ruby files in `lib/react_on_rails/` by adding corresponding `.rbs` file in `sig/react_on_rails/`, adding to Steepfile, and validating before committing
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: The `react_on_rails_pro/` directory has its own Prettier/ESLint configuration and must be linted separately
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (9)
  • GitHub Check: dummy-app-integration-tests (3.4, 22, latest)
  • GitHub Check: examples (3.4, latest)
  • GitHub Check: build
  • GitHub Check: pro-lint-js-and-ruby
  • GitHub Check: precompile-check
  • GitHub Check: build-dummy-app-webpack-test-bundles
  • GitHub Check: rspec-package-tests (3.4, latest)
  • GitHub Check: build-dummy-app-webpack-test-bundles
  • GitHub Check: claude-review
🔇 Additional comments (1)
.github/workflows/precompile-check.yml (1)

222-228: Artifact configuration is sound for CI diagnostics.

The artifact upload uses if: always() to ensure logs are captured even on failure, includes a run-specific ID for uniqueness, and sets a reasonable 7-day retention window. This is good practice for debugging precompile failures.

@claude
Copy link

claude bot commented Nov 26, 2025

Code Review: Assets Precompile Check Workflow

I've reviewed PR #2134 and overall this is a well-implemented and valuable addition to the CI pipeline. The workflow effectively addresses the issue of detecting silent failures during asset precompilation. Below are my findings:


Strengths

1. Excellent Pattern Detection Strategy

The workflow checks for 8 critical failure patterns that have caused production issues:

This comprehensive approach will catch both obvious and subtle failures.

2. Proper CI Integration

  • ✅ Uses the same detect-changes pattern as other workflows
  • ✅ Correctly skips for docs-only changes on master
  • ✅ Respects full-ci label and workflow_dispatch
  • ✅ Consistent with existing workflow conditional logic (lines 61-70)

3. Good Error Handling

  • Uses set -o pipefail to catch rake failures even when piped through tee (line 144)
  • Captures exit code in PRECOMPILE_EXIT variable (line 146)
  • Provides clear GitHub Actions annotations with ::error:: and ::warning::

4. Helpful Debugging Features

  • Uploads precompile output as artifact (lines 246-252) for post-mortem analysis
  • Shows sample matching lines for each failure pattern
  • 7-day retention is reasonable

🔍 Areas for Improvement

1. Potential False Positives in Pattern Detection

Issue: Some patterns might be too broad and trigger false positives.

Pattern 3 (lines 185-190): Module errors

grep -Ei "module not found|cannot find module|can't resolve"

Concern: This could match warnings in addition to actual errors. Webpack often emits deprecation warnings that contain these phrases but don't fail the build.

Suggestion: Consider adding context to ensure these are actual errors:

if grep -Ei "(ERROR|error).*module not found|(ERROR|error).*cannot find module|(ERROR|error).*can't resolve" precompile_output.txt; then

Pattern 4 (lines 193-198): Webpack errors

grep -Ei "webpack.*error|failed to compile|compilation failed|ERROR in"

Concern: webpack.*error could match benign strings like "webpack handles errors gracefully".

Suggestion: Use more specific patterns:

grep -Ei "webpack.*ERROR|ERROR in [./]|compilation failed|failed to compile" precompile_output.txt

2. Warning Threshold May Need Tuning

Line 226: WARNING_COUNT -gt 10

Question: Is 10 warnings an appropriate threshold for this codebase?

Suggestion:

  • Document why 10 was chosen in a comment
  • Consider making it configurable via workflow input
  • Or start with a higher threshold (like 20) and tune based on actual runs

3. Missing Pattern: Build Timeout/Hung Processes

Observation: The workflow doesn't have a timeout specified for the precompile step.

Risk: If webpack hangs, the job could run for the default 6-hour timeout.

Suggestion: Add a timeout to the precompile step:

- name: Run assets:precompile and check output
  timeout-minutes: 20  # or whatever is reasonable
  run: |

4. Pattern Validation: Empty Matches

Lines 163-230: Several patterns use || true to avoid failing on no matches, but some don't.

Potential Issue: If grep finds no matches and set -e is implied, some checks might exit prematurely.

Observation: Line 144 uses set -o pipefail but not set -e, so this should be okay. But it's worth double-checking.

5. Documentation: What Each Pattern Prevents

Suggestion: Add comments above each pattern explaining which past incident it prevents:

# Pattern 1: Prevents duplicate webpack compilations (regression test for PR #2052)
# Context: Rails::Engine was loading rake tasks twice, causing duplicate builds
if grep -q "Compiled successfully" precompile_output.txt; then
  ...
fi

This helps future maintainers understand why each check exists.


🔒 Security Considerations

No security concerns identified:

  • No secrets exposure risk
  • No untrusted input execution
  • Artifact uploads are scoped to repo

🎯 Performance Considerations

Good:

  • ✅ Proper caching of pnpm store and Ruby gems
  • ✅ Skips appropriately for docs-only changes
  • ✅ Pattern matching is efficient (linear scans with grep)

Minor:

  • The workflow setup time (~3-5 min) is unavoidable for a realistic precompile test
  • Multiple grep passes could theoretically be combined, but readability is more important here

🧪 Test Coverage

From PR description test plan:

  • CI workflow passes on this PR ✓ (verifiable)
  • Verify the workflow runs and captures output correctly ✓ (check artifacts)
  • Manually test by introducing a known failure ⚠️ (recommended but not blocking)

Suggestion: After merge, consider creating a follow-up issue to:

  1. Intentionally break each pattern in a test branch
  2. Verify the workflow catches it
  3. Document results for future reference

This validates the detection logic comprehensively.


📋 Checklist for Merge

Before merging, verify:

  • The workflow file passes actionlint (should be checked by another workflow)
  • Artifact uploads work correctly (test with workflow_dispatch)
  • Pattern thresholds are appropriate (consider tuning warning count)
  • Add timeout to precompile step (recommended)
  • Consider tightening pattern regexes to reduce false positives (optional)

🎓 Alignment with Project Guidelines

Checked against CLAUDE.md:

Follows CI/CD patterns: Uses standard detect-changes and conditional logic
Proper permissions: Only contents: read, actions: read
Error prevention: Directly addresses "silent failures" concern from docs
Artifact management: 7-day retention is reasonable
No manual formatting needed: Workflow YAML is properly formatted

References:


Final Verdict

APPROVED with minor suggestions

This PR effectively solves the problem stated in issue #2081. The workflow is well-structured, follows existing patterns, and will catch critical production issues. The suggestions above are non-blocking improvements that can be addressed in follow-up PRs or ignored if the current implementation proves robust in practice.

Recommended next steps:

  1. Merge as-is to get monitoring in place
  2. Monitor first ~10 runs for false positives
  3. Tune patterns/thresholds based on real data
  4. Add timeout to precompile step in follow-up if needed

Great work! This will significantly improve build reliability. 🚀


Review performed by Claude Code following project standards from CLAUDE.md

@justin808 justin808 self-assigned this Dec 5, 2025
@justin808 justin808 added the AI_ON label Dec 5, 2025
@justin808
Copy link
Member Author

@claude review this PR.

@claude
Copy link

claude bot commented Dec 9, 2025

Claude finished @justin808's task —— View job


Code Review for PR #2134

I've completed a thorough review of this PR. Overall, this is an excellent addition that addresses a real pain point (issue #2081) and follows the project's defensive programming philosophy. The implementation is well-structured and comprehensive.


✅ Strengths

1. Addresses Real Problems

2. Excellent Pattern Detection Strategy

The validation script (script/validate-precompile-output) checks for 9 well-documented failure patterns:

  • ✅ Duplicate webpack compilations with multiple detection methods (lines 105-150)
  • ✅ Duplicate rake task execution (lines 122-141)
  • ✅ Module resolution errors with strict matching to avoid false positives (lines 159-164)
  • ✅ Webpack compilation errors with specific error markers (lines 185-196)
  • ✅ Ruby/Rails errors and gem dependency issues (lines 217-233)
  • ✅ Sprockets/Asset pipeline errors (lines 239-244)
  • ✅ Memory issues (OOM, killed processes) (lines 251-256)
  • ✅ Warning count threshold (advisory, configurable) (lines 265-271)
  • ✅ Deprecation warnings (advisory) (lines 278-283)

Each pattern includes:

  • Detailed comments explaining what it prevents and historical context
  • Sample matching lines in error output for debugging
  • GitHub Actions annotations using ::error:: and ::warning::

3. Proper CI Integration

The workflow file (.github/workflows/precompile-check.yml):

  • ✅ Uses the standard detect-changes pattern consistent with other workflows
  • ✅ Correctly skips for docs-only changes on master (lines 61-70)
  • ✅ Respects full-ci label and workflow_dispatch force_run
  • ✅ Properly handles exit codes with set -o pipefail (line 147) and PIPESTATUS (line 149)
  • ✅ Includes timeout protection (15 minutes) to prevent hung processes (line 138)
  • ✅ Uploads artifacts for debugging (lines 160-166)

4. Excellent Documentation

  • Comprehensive comments in validation script explaining each pattern's purpose
  • Usage examples at the top of the script (lines 1-28)
  • Configurable thresholds via environment variables
  • Links to relevant GitHub issues and PRs

5. Smart Error Handling

  • Checks for empty output and suspiciously small output (lines 53-70)
  • Validates rake command exit code before pattern checking (lines 154-157)
  • Uses set -o pipefail to catch failures in pipe chains
  • Supports both file input and stdin piping

🔍 Observations & Suggestions

1. Pattern Validation: "killed" May Be Too Broad (Line 251)

script/validate-precompile-output:251

The pattern grep -Ei "javascript heap out of memory|killed|out of memory" might produce false positives. The word "killed" could appear in legitimate contexts (e.g., "process killed gracefully", log messages, comments).

Consideration: This may be acceptable given that OOM issues are critical. However, if false positives occur in practice, consider tightening to:

grep -Ei "javascript heap out of memory|process killed|SIGKILL|out of memory"

2. Warning Threshold Default of 20 (Line 265)

The script sets WARNING_THRESHOLD="${WARNING_THRESHOLD:-20}" with this explanation:

"Default of 20 chosen based on typical precompile output having ~10-15 benign warnings from node deprecations and peer dependency notices."

Suggestion: Document this threshold choice in the PR description or a comment so future maintainers understand the baseline. Consider monitoring actual warning counts in the first few CI runs and adjusting if needed.

3. Path Reference: react_on_rails/spec/dummy

The workflow references react_on_rails/spec/dummy in multiple places (lines 116, 118, 132, 140, 159, 165). Based on the repository structure and CLAUDE.md, this appears correct for the current monorepo layout where the gem is in react_on_rails/ subdirectory.

Verification: ✅ This is consistent with the repository structure shown in the git status and other workflow files.

4. Validation Script is Reusable

The validation script is well-designed for reuse:

  • Accepts file path or stdin
  • Configurable via environment variables
  • GitHub Actions annotation support with fallback to plain text
  • Could be used in local development or other CI systems

Excellent design decision to separate the validation logic into a standalone script rather than embedding it in the workflow YAML.


🎯 Alignment with Project Guidelines

Checked against CLAUDE.md and related documentation:

Follows CI/CD patterns: Uses standard detect-changes job and conditional logic
Proper permissions: Only contents: read, actions: read
Error prevention philosophy: Directly addresses "Avoiding CI Failure Cycles" guidance
Artifact management: 7-day retention is reasonable
Build script validation: Uses yalc publish pattern correctly
Ruby 3.4 / Node 22 / PNPM: Matches "latest" configuration from CLAUDE.md
Timeout protection: Prevents CI resource waste from hung processes
Exit code handling: Correctly uses pipefail and PIPESTATUS

Referenced Documentation:


🧪 Test Plan Assessment

The PR description test plan is appropriate:

  • CI workflow passes on this PR ✓ (can be verified by checking Actions tab)
  • Verify the workflow runs and captures output correctly ✓ (check artifact upload)
  • Manually test by introducing known failure ⚠️ (recommended for validation)

Recommendation: After merge, consider creating a follow-up task to:

  1. Intentionally introduce each failure pattern in a test branch
  2. Verify the workflow catches it with correct error messages
  3. Document results for future reference

This would validate the detection logic comprehensively and provide confidence in the patterns.


📊 Comparison with Previous Reviews

I note that two previous CodeRabbit reviews provided detailed feedback. Here's my assessment of their suggestions:

CodeRabbit Suggestions Already Addressed:

  • ✅ Exit code checking with PIPEFAIL and PRECOMPILE_EXIT - Already implemented (lines 147-157)
  • ✅ Duplicate compilation detection improved - Already uses specific pattern "Compiled successfully" (line 105)
  • ✅ Sample matching lines in error output - Already implemented for all patterns
  • ✅ Context around errors - Already shows context for COMPILATION FAILED (lines 190-194)

CodeRabbit Suggestions That Are Matters of Preference:

  • Pattern specificity (e.g., webpack error matching) - The current patterns seem reasonable and can be tuned based on real-world usage
  • Warning count threshold - 20 is documented as intentional; can be adjusted if needed

🎓 Final Assessment

Quality: Excellent
Impact: High - prevents regression of critical bugs and catches silent failures
Recommendation: ✅ APPROVE

This PR effectively solves the problem stated in issue #2081. The implementation is:

  • Well-structured and follows existing patterns
  • Comprehensive in failure detection
  • Properly documented with historical context
  • Reusable beyond just GitHub Actions
  • Defensive without being overly strict

Suggestions for Follow-up (Non-blocking):

  1. Monitor first ~10 runs for false positives and tune patterns if needed
  2. Document baseline warning counts from initial runs
  3. Create validation test to intentionally trigger each pattern and verify detection
  4. Consider adding to CLAUDE.md under "CI workflows" section as an example of defensive CI

Great work! This will significantly improve build reliability and prevent silent failures from slipping through. The defensive programming approach and comprehensive pattern detection are exactly what's needed. 🚀


justin808 and others added 12 commits December 8, 2025 19:39
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:

- Duplicate webpack compilations (tasks running twice)
- Duplicate rake task execution (e.g., generate_packs running multiple times)
- Module not found / cannot resolve errors
- Webpack compilation errors
- Ruby errors (NameError, LoadError, etc.)
- Asset pipeline errors
- Memory issues (heap out of memory)
- High warning counts (>10 warnings triggers a warning annotation)

The workflow runs on PRs and master pushes, uses the same change
detection as other CI jobs, and uploads the precompile output as an
artifact for debugging when failures occur.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
The precompile check needs to run react_on_rails:generate_packs first
to generate the server-bundle-generated.js file that webpack imports.
This matches what other CI jobs do before running webpack builds.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
The dummy app uses ReScript components that need to be compiled before
webpack can bundle them. This adds `pnpm run build:rescript` to compile
HelloWorldReScript.res.js and other ReScript files.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Changes based on CodeRabbit review comments:

1. Capture rake exit code with PIPESTATUS to detect silent failures
   - Added set -o pipefail to propagate pipe failures
   - Check PIPESTATUS[0] after tee to catch rake failures

2. Improved duplicate webpack compilation detection
   - Changed pattern from generic "Compiled" to "Compiled successfully"
   - Simplified logic to count successful compilations directly
   - Added line numbers to matching output for debugging

3. Improved webpack error pattern detection
   - Changed from overly broad "error in" to more specific patterns
   - Now matches: webpack.*error, failed to compile, compilation failed, ERROR in

4. Better Ruby error detection
   - Pattern now matches error class format with colon (e.g., "NameError:")
   - Reduces false positives from log messages

5. Fixed asset pipeline error pattern
   - Use proper casing for Sprockets::FileNotFound

6. Added sample output for all error patterns
   - Each error now shows the first few matching lines for easier debugging

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Added checks for:
- Duplicate locale generation (react_on_rails:locale task)
- Duplicate webpack builds (via "Built at:" message count)
- ENOENT errors (missing files/directories)
- Deprecation warnings (logged as warning, not failure)

These patterns were explicitly requested in the updated issue description
to catch silent bugs that don't cause precompile to fail but indicate
problems like doubled build times or missing dependencies.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Extracted all pattern detection logic into script/validate-precompile-output
so it can be:
- Run locally: script/validate-precompile-output <output_file>
- Piped: RAILS_ENV=production rake assets:precompile 2>&1 | script/validate-precompile-output -
- Used by CI with GitHub Actions annotations

The script supports both local and CI usage, automatically using GitHub
Actions annotation format when GITHUB_ACTIONS env var is set.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Detect empty output (0 bytes) as failure, indicating command failed
  before producing any output
- Add warning for suspiciously small output (<10 lines by default)
- Add Pattern 5b: Detect bundler/gem errors like "Could not find gem"
- Fix shellcheck warning: use single quotes in trap command
- Update usage docs to emphasize pipefail requirement when piping
- Add timeout-minutes: 15 comment to CI workflow step

The empty output detection addresses the case where rake fails immediately
(e.g., missing gem) but produces no stdout, causing the validation to
incorrectly pass when piped without pipefail.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Show context (20 lines) after COMPILATION FAILED to reveal actual error
- Add specific pattern to detect missing webpack-cli with actionable fix
- The validation script now provides much clearer error messages

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
The dummy app's JS dependencies were missing a lockfile, which meant
dependency versions could vary between installs. This lockfile ensures
reproducible builds for local development and CI.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
The pnpm-lock.yaml in spec/dummy uses link: protocol for the
react-on-rails dependency, but yalc add (without --link) changes
package.json to use file: protocol, causing ERR_PNPM_OUTDATED_LOCKFILE
errors in CI.

Adding --link flag ensures yalc maintains the link: protocol that
matches the lockfile, fixing all CI workflow failures.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Ensures CI tests a fresh webpack build rather than potentially getting
"Everything's up-to-date" from cached assets. The clobber task removes
both Sprockets assets (public/assets) and webpack output (public/webpack).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
The minimum config job switches shakapacker from 9.4.0 to 8.2.0 via
bin/ci-switch-config, which modifies package.json. This causes
pnpm-lock.yaml to be out of sync, requiring --no-frozen-lockfile.

Added conditional --no-frozen-lockfile flag to dummy app pnpm install
steps when running with minimum dependency level.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@justin808 justin808 force-pushed the jg/precompile-ci-check branch from 8795487 to 24c93f0 Compare December 9, 2025 05:39
@claude
Copy link

claude bot commented Dec 9, 2025

Code Review: Assets Precompile Check CI Workflow

Excellent work on this PR! This adds valuable infrastructure to catch build issues early. Here's my detailed review:


Strengths

1. Comprehensive Error Detection

The validate-precompile-output script catches a wide range of real-world issues:

The pattern detection is well-thought-out with good historical context in comments.

2. Well-Documented Script

  • Clear usage examples at the top
  • Each pattern section has comments explaining what it detects and why
  • GitHub issue/PR references for historical context
  • Helpful error messages with actionable advice

3. GitHub Actions Integration

  • Proper use of ::error:: and ::warning:: annotations
  • Artifact uploads for debugging (precompile_output.txt)
  • Appropriate timeout (15 minutes) prevents hung processes
  • Smart change detection to skip docs-only changes

4. Production Realism

Running RAILS_ENV=production rake assets:precompile mirrors real deployment scenarios, which is exactly what you want to test.


⚠️ Issues & Suggestions

CRITICAL: pnpm-lock.yaml Addition

Issue: This PR adds a 7,666-line pnpm-lock.yaml to react_on_rails/spec/dummy/. According to CLAUDE.md testing guidelines, the dummy app previously didn't have a lockfile.

From integration-tests.yml before this PR:

# The dummy app doesn't have a pnpm-lock.yaml and shouldn't use frozen lockfile
run: cd react_on_rails/spec/dummy && pnpm install --ignore-workspace

After this PR:

# minimum config changes package.json (shakapacker version), so can't use frozen lockfile
run: cd react_on_rails/spec/dummy && pnpm install --ignore-workspace

Questions:

  1. Is this intentional? The lockfile uses link:.yalc/react-on-rails protocol, which requires yalc add --link (you've updated this correctly).
  2. Does this affect local development? Developers will now have a committed lockfile that may conflict with their local .yalc/ links.
  3. CI consistency: For latest config, you're implicitly using frozen lockfile now. Is this desired behavior?

Recommendation:

  • If keeping the lockfile: Document WHY in CLAUDE.md and ensure it doesn't break local workflows
  • If not keeping: Add react_on_rails/spec/dummy/pnpm-lock.yaml to .gitignore and remove it from this PR
  • Either way: Update the workflow comments to reflect the new reality

Medium: Pattern Detection Edge Cases

script/validate-precompile-output:159-164

if grep -Ei "(^|\\s)(ERROR|Error:).*module not found|..." "\"; then

Potential issue: The regex (^|\\s)(ERROR|Error:) might not catch all webpack module errors. Webpack often outputs:

Module not found: Error: Can't resolve 'some-package' in '/path/to/app'

The current pattern would catch this (via Module not found: Error:), but the comment says "preceded by ERROR, Error:" which isn't accurate for this format.

Suggestion: Update the comment to reflect that Module not found: Error: is the primary pattern being matched.

Medium: Memory Error Pattern Too Broad

script/validate-precompile-output:251

if grep -Ei "javascript heap out of memory|killed|out of memory" "\"; then

Issue: The pattern killed could match benign text like "killed the bug" in commit messages or comments that appear in output.

Suggestion: Make it more specific:

if grep -Ei "javascript heap out of memory|\\bkilled\\b|out of memory" "\"; then

The \\b word boundaries ensure "killed" is a standalone word.

Low: Duplicate Detection Logic

You detect duplicate webpack builds three ways:

  1. Compiled successfully count (lines 105-114)
  2. Built at: count (lines 144-150)
  3. React on Rails task execution count (lines 122-141)

Question: Is checking both "Compiled successfully" AND "Built at:" redundant? They should always appear together in successful webpack builds.

Suggestion: Document why both are needed, or remove one if redundant.

Low: Exit Code Handling

precompile-check.yml:152-162

Good use of pipefail and PIPESTATUS! However, if the rake command fails, you still create the output file, then the validation step runs anyway.

Suggestion: Add if: success() to the validation step, OR let it run always (current behavior) but make the script handle empty/partial output gracefully (which it does at lines 53-70). Current approach is fine, just noting it.


🔧 Code Quality

Bash Script Best Practices

  • Uses set -e for error propagation
  • Proper quoting of variables
  • Uses || true for grep commands that might not match
  • Temp file cleanup with trap
  • Clear error messages

Security

  • No arbitrary code execution
  • No unvalidated input usage
  • Proper file existence checks

Testing Coverage

The PR description mentions:

  • Manually test by introducing a known failure

Recommendation: Before merging, actually test at least one failure pattern (e.g., temporarily duplicate a rake task) to verify the detection works as expected.


📋 Minor Nits

  1. Typo in comment (line 138): "Clobber" is correct terminology, but consider adding that it's a Rails/Sprockets concept for clarity.

  2. Hardcoded paths: react_on_rails/spec/dummy/precompile_output.txt appears in multiple places. Consider using a variable or GitHub Actions output.

  3. Retention days: Artifacts kept for 7 days. Is this sufficient for debugging historical issues? Consider 14-30 days.

  4. Timeout might be generous: 15 minutes timeout when typical precompile is 2-5 minutes. Consider 10 minutes to fail faster on hung processes.


🎯 Overall Assessment

This is solid infrastructure work that will save debugging time. The validation script is well-crafted with good historical context. The main concern is the pnpm-lock.yaml addition—please clarify if this is intentional and document the implications.

Before Merging:

  1. ✅ Decide on pnpm-lock.yaml strategy (keep vs. gitignore)
  2. ✅ Update workflow/CLAUDE.md comments to match reality
  3. ✅ Test at least one failure pattern manually
  4. ⚠️ Consider tightening the "killed" regex pattern
  5. ⚠️ Clarify module error detection comment

Approval Status: Approved with requested changes

Great work on improving the CI infrastructure! 🚀

Changes based on review suggestions:

1. Remove pnpm-lock.yaml from dummy app
   - The dummy app didn't have a lockfile before this PR
   - Keeping it could cause issues for local development with yalc
   - Updated workflow comment to clarify no lockfile exists

2. Fix memory error pattern to be more specific
   - Changed "killed" to "\bKilled\b" with word boundary
   - Use capital K which matches OOM killer message format
   - Prevents false positives from "killed the bug" etc.

3. Update module error comment for accuracy
   - Clarified that primary match is webpack's "Module not found: Error:" format
   - Also matches ERROR/Error: prefixed messages

4. Document duplicate detection rationale
   - Explained why both "Compiled successfully" and "Built at:" are checked
   - "Compiled successfully" may be absent on failed builds
   - "Built at:" is always present, catches duplicates on any outcome

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
script/validate-precompile-output (1)

122-141: Consider limiting output for duplicate task detection.

Patterns 2a and 2b don't limit their grep -n output like other patterns do. If there are many duplicates, this could produce verbose output.

   if [ "$GENERATE_PACKS_COUNT" -gt 1 ]; then
     report_error "react_on_rails:generate_packs task ran $GENERATE_PACKS_COUNT times (should only run once)."
     echo "  Matching lines:"
-    grep -n "react_on_rails:generate_packs" "$OUTPUT_FILE"
+    grep -n "react_on_rails:generate_packs" "$OUTPUT_FILE" | head -5
     FAILURES_FOUND=1
   fi
 fi
 
 # Pattern 2b: Duplicate locale generation (same root cause as 2a)
 if grep -q "react_on_rails:locale" "$OUTPUT_FILE"; then
   LOCALE_COUNT=$(grep -c "react_on_rails:locale" "$OUTPUT_FILE" || true)
   if [ "$LOCALE_COUNT" -gt 1 ]; then
     report_error "react_on_rails:locale task ran $LOCALE_COUNT times (should only run once)."
     echo "  Matching lines:"
-    grep -n "react_on_rails:locale" "$OUTPUT_FILE"
+    grep -n "react_on_rails:locale" "$OUTPUT_FILE" | head -5
     FAILURES_FOUND=1
   fi
 fi
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 98a983f and 0f69f03.

📒 Files selected for processing (4)
  • .github/workflows/integration-tests.yml (2 hunks)
  • .github/workflows/lint-js-and-ruby.yml (1 hunks)
  • .github/workflows/precompile-check.yml (1 hunks)
  • script/validate-precompile-output (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • .github/workflows/precompile-check.yml
🧰 Additional context used
📓 Path-based instructions (1)
**/*

📄 CodeRabbit inference engine (CLAUDE.md)

ALWAYS ensure files end with a newline character before committing/pushing

Files:

  • script/validate-precompile-output
🧠 Learnings (5)
📚 Learning: 2025-11-25T08:05:17.804Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: Applies to /CHANGELOG.md : Update `/CHANGELOG.md` for user-visible changes (features, bug fixes, breaking changes, deprecations, performance improvements) to the open-source React on Rails gem and npm package

Applied to files:

  • .github/workflows/lint-js-and-ruby.yml
📚 Learning: 2025-11-25T08:05:17.804Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: The `react_on_rails_pro/` directory has its own Prettier/ESLint configuration and must be linted separately

Applied to files:

  • .github/workflows/lint-js-and-ruby.yml
  • .github/workflows/integration-tests.yml
📚 Learning: 2025-04-26T21:55:55.874Z
Learnt from: alexeyr-ci2
Repo: shakacode/react_on_rails PR: 1732
File: spec/dummy/client/app-react16/startup/ReduxSharedStoreApp.client.jsx:40-44
Timestamp: 2025-04-26T21:55:55.874Z
Learning: In the react_on_rails project, files under `app-react16` directories are copied/moved to corresponding `/app` directories during the conversion process (removing the `-react16` suffix), which affects their relative import paths at runtime.

Applied to files:

  • .github/workflows/lint-js-and-ruby.yml
📚 Learning: 2025-01-23T18:20:45.824Z
Learnt from: alexeyr-ci
Repo: shakacode/react_on_rails PR: 1687
File: spec/dummy/package.json:0-0
Timestamp: 2025-01-23T18:20:45.824Z
Learning: When adding or updating dependencies in spec/dummy/package.json, maintain version consistency with other package.json files in the codebase to avoid potential version conflicts.

Applied to files:

  • .github/workflows/integration-tests.yml
📚 Learning: 2025-11-25T08:05:17.804Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: Applies to spec/dummy/e2e/playwright/**/*.spec.js : Use Rails helpers (`appFactories`, `appEval`) in Playwright tests instead of UI-based setup to leverage factory_bot and arbitrary Ruby code execution

Applied to files:

  • .github/workflows/integration-tests.yml
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (10)
  • GitHub Check: build-dummy-app-webpack-test-bundles (3.2, 20, minimum)
  • GitHub Check: examples (3.4, latest)
  • GitHub Check: examples (3.2, minimum)
  • GitHub Check: build-dummy-app-webpack-test-bundles
  • GitHub Check: build
  • GitHub Check: pro-lint-js-and-ruby
  • GitHub Check: rspec-package-tests (3.2, minimum)
  • GitHub Check: rspec-package-tests (3.4, latest)
  • GitHub Check: build-dummy-app-webpack-test-bundles
  • GitHub Check: claude-review
🔇 Additional comments (15)
.github/workflows/lint-js-and-ruby.yml (1)

135-136: LGTM!

The --link flag is the correct approach to maintain consistency with pnpm's link: protocol in the lockfile. The comment clearly explains the rationale.

.github/workflows/integration-tests.yml (4)

153-154: LGTM!

Consistent use of --link flag matching the lint workflow. The comment explains the rationale.


157-158: LGTM!

The conditional lockfile handling correctly accounts for the minimum dependency configuration's package.json modifications. This is consistent with line 148's approach.


260-261: LGTM!

Consistent with the changes in the build job.


264-265: LGTM!

Consistent with the build job's approach at line 158.

script/validate-precompile-output (10)

1-45: Well-structured script with good documentation.

The header documentation, input handling, and temp file cleanup are well implemented. The trap ensures proper cleanup on exit.


47-70: LGTM!

Good validation of output integrity. The distinction between hard failure (empty file) and soft warning (low line count) is appropriate. The configurable threshold provides flexibility.


75-95: LGTM!

Clean helper functions with proper GitHub Actions annotation support. The $GITHUB_ACTIONS environment variable check is the standard way to detect CI context.


97-114: LGTM!

Good detection logic with helpful context. The || true correctly prevents set -e from triggering on zero matches with grep -c.


164-169: LGTM!

The regex carefully balances catching real errors while avoiding false positives from informational messages. The documentation explains the matching strategy well.


179-215: LGTM!

Good defensive pattern matching with the ^ERROR in anchor to avoid false positives. The context extraction around COMPILATION FAILED and actionable webpack-cli fix instructions are helpful.


217-238: LGTM!

Matching specific exception class names is a good approach to reduce false positives. The Bundler error detection covers common scenarios with actionable guidance.


251-262: LGTM!

The \bKilled\b word boundary correctly avoids false positives while catching the OOM killer's output format.


264-289: LGTM!

Good advisory patterns that surface potential issues without blocking CI. The configurable threshold and clear distinction between fatal errors and warnings is well designed.


291-304: LGTM!

Clear summary output with appropriate exit codes matching the documented behavior. The file correctly ends with a newline as per coding guidelines.

@claude
Copy link

claude bot commented Dec 9, 2025

Code Review - PR #2134: Add CI workflow to check assets:precompile output

Excellent work on this proactive quality check! This is exactly the kind of defensive measure that prevents silent regressions.

✅ Strengths

1. Well-Designed Workflow

  • Proper integration with existing change detection logic
  • Follows the same skip pattern as other workflows (docs-only commits)
  • Good timeout protection (15 minutes) to prevent hung processes
  • Smart use of pipefail to catch rake failures even when piped

2. Comprehensive Pattern Detection

The validation script covers a wide range of issues including duplicate task execution, module resolution errors, webpack compilation failures, Ruby exceptions, bundler/gem issues, memory issues, and asset pipeline errors.

3. Excellent Documentation

4. Good CI Practices

  • Uploads output as artifact for debugging (7-day retention is appropriate)
  • Uses GitHub Actions annotations
  • Runs assets:clobber to ensure fresh builds

🔍 Issues & Suggestions

Critical: Verify Executable Flag

Ensure the script executable bit is tracked in git. Run: git ls-files -s script/validate-precompile-output

If it shows 100644, add permission: git update-index --chmod=+x script/validate-precompile-output

Pattern Detection Refinements

Line 164: Overly Broad Module Error Pattern - Current pattern could match informational text. Suggest making it more specific to actual error contexts.

Line 190: Webpack Error Pattern - The pattern "failed to compile" could match documentation text. Suggest anchoring to webpack-specific output.

Line 232: Bundler Pattern - The pattern "Run bundle install" could appear in documentation. Suggest only matching actual error output.

Workflow Configuration

Currently runs only with Ruby 3.4 and Node 22. Consider adding matrix strategy later if version-specific issues are discovered.

📝 Additional Suggestions

Add Test Suite

Create script/test-validate-precompile-output with test cases to ensure patterns work correctly.

Document Expected Output

Add comments showing typical successful output to help future maintainers.

🎯 Performance Considerations

Impact: Adds ~2-5 minutes to CI. The workflow properly reuses pnpm cache, gem cache, and runs in parallel with other jobs.

✅ Testing Requirements (Per CLAUDE.md)

Before merging, please verify locally:

  1. cd react_on_rails/spec/dummy
  2. RAILS_ENV=production bundle exec rake assets:clobber
  3. RAILS_ENV=production bin/rake assets:precompile 2>&1 | tee precompile_output.txt
  4. ../../script/validate-precompile-output precompile_output.txt

📚 Documentation

Suggest adding to CLAUDE.md:

Precompile Output Validation

The precompile-check workflow validates assets:precompile output for known failure patterns. Run locally with: RAILS_ENV=production rake assets:precompile 2>&1 | script/validate-precompile-output -

Summary

Overall Assessment: ⭐⭐⭐⭐⭐ (5/5)

This is an excellent defensive measure that will catch regressions early. The implementation is solid, well-documented, and follows best practices.

Recommendation: Approve with minor refinements

Before Merging:

  1. Verify executable bit is tracked in git
  2. Test locally with production precompile
  3. Consider refining overly broad regex patterns (optional but recommended)
  4. Add brief documentation to CLAUDE.md about this workflow

Future Enhancements (not blocking):

  • Add test suite for validation script
  • Consider matrix strategy for version coverage
  • Monitor false positive rate and adjust patterns as needed

Great work! This will save the team significant debugging time in the future.

🤖 Generated with Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Ci check of assets:precompile stdout

2 participants