Skip to content

Conversation

@justin808
Copy link
Member

@justin808 justin808 commented Nov 12, 2025

Summary

Fixes the /run-skipped-ci command to intelligently detect and run only the CI checks that were actually skipped on the PR.

The Problem

The previous implementation was broken because:

  1. It tried to guess which tests to run based on a hardcoded list
  2. Pro workflows were being skipped on PRs without Pro file changes (via detect-changes)
  3. The command wasn't smart about which tests actually needed to be run

The Solution

The command now intelligently detects skipped checks and runs only what's needed.

Changes

1. Fetch Actual Skipped Checks from PR

The workflow now queries the GitHub API to find checks with conclusion='SKIPPED':

const checks = await github.rest.checks.listForRef({...});
const skippedChecks = checks.data.check_runs.filter(check =>
  check.conclusion === 'SKIPPED' && check.status === 'COMPLETED'
);

Maps workflow names to files and triggers only workflows with skipped checks.

2. Added force_run Input to ALL Workflows

All workflows now support a force_run input that bypasses detect-changes:

Updated workflows:

  • main.yml
  • examples.yml
  • pro-integration-tests.yml
  • pro-package-tests.yml
  • pro-lint.yml

How it works:

- name: Detect relevant changes
  run: |
    # If force_run is true, run everything
    if [ "${{ inputs.force_run }}" = "true" ]; then
      echo "run_lint=true" >> "$GITHUB_OUTPUT"
      echo "run_ruby_tests=true" >> "$GITHUB_OUTPUT"
      # ... all other outputs set to true
      exit 0
    fi
    # Normal detect-changes logic...

3. Fixed Matrix Exclusion Logic

Updated matrix exclusion to run ALL configurations when force_run=true:

exclude:
  # Skip minimum on PRs UNLESS force_run is true
  - ruby-version: ${{ github.event_name == 'pull_request' && inputs.force_run != true && '3.2' || '' }}
    node-version: ${{ github.event_name == 'pull_request' && inputs.force_run != true && '20' || '' }}
    dependency-level: ${{ github.event_name == 'pull_request' && inputs.force_run != true && 'minimum' || '' }}

4. Improved PR Comments

The PR comment now shows:

  • All skipped checks that were detected
  • Which workflows were triggered
  • Clear explanation that force_run bypasses detect-changes
  • Handles case where all checks are already running

Example comment:

Skipped CI Checks - Trigger Results

Successfully triggered skipped CI checks

**Skipped checks detected:**
- build-dummy-app-webpack-test-bundles (React on Rails Pro - Integration Tests)  
- lint-js-and-ruby (React on Rails Pro - Lint)
- dummy-app-integration-tests (Main test)

**Triggered workflows:**
- React on Rails Pro - Integration Tests
- React on Rails Pro - Lint  
- Main Tests

**Note:** These workflows will run with force_run: true to bypass detect-changes logic.

Testing

  • Verify the workflow queries actual skipped checks from PR
  • Test that force_run bypasses detect-changes
  • Confirm matrix runs both latest and minimum when triggered
  • Check PR comment shows correct information

Benefits

  • Smart: Only runs tests that were actually skipped
  • Comprehensive: Runs all test matrices (latest + minimum dependencies)
  • Transparent: Clear PR comments show exactly what's running and why
  • Maintainable: No hardcoded workflow lists to keep in sync

Generated with Claude Code


This change is Reviewable

The /run-skipped-ci command was triggering ALL workflows, which caused
detect-changes to skip them (since they run on the PR branch with no
Pro file changes). Now it correctly:

1. Only triggers workflows with minimum dependency matrix
   - main.yml: Ruby 3.2, Node 20, minimum dependencies
   - examples.yml: Ruby 3.2, minimum dependencies

2. Skips workflows that already run on all PRs
   - pro-integration-tests.yml (always runs)
   - pro-package-tests.yml (always runs)

3. Uses workflow_dispatch inputs to control matrix
   - Added run_minimum_tests input to main.yml and examples.yml
   - When true, excludes latest matrix (3.4/22)
   - When false, excludes minimum matrix on PRs (existing behavior)

4. Updates PR comment to show what ran and what was skipped
   - Clear explanation of which tests are running
   - Note about why Pro tests are skipped

This fixes the issue where detect-changes would stop the workflow
because it detected no Pro file changes on the PR branch.

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

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

👋 Thanks for opening this PR!

🚀 Running Full CI Suite

By default, PRs run a subset of CI jobs for faster feedback (latest Ruby/Node versions only).

To run the complete CI suite including all dependency combinations and skipped jobs, comment:

/run-skipped-ci

This will trigger:

  • ✅ Minimum supported versions (Ruby 3.2, Node 20)
  • ✅ All example app tests
  • ✅ Pro package integration tests
  • ✅ All test matrices

The full CI suite takes longer but ensures compatibility across all supported versions before merging.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 12, 2025

Walkthrough

The PR modifies three GitHub Actions workflows to introduce conditional matrix execution based on a new run_minimum_tests input. The changes replace static exclude rules with conditional expressions in build and test matrices, and update the CI run workflow to handle minimum versus latest dependency tests separately through separate orchestration paths.

Changes

Cohort / File(s) Summary
Workflow Input Configuration
​.github/workflows/main.yml, ​.github/workflows/examples.yml
Added new run_minimum_tests workflow_dispatch input (boolean, default false) to enable manual control of conditional matrix execution.
Matrix Exclusion Logic
​.github/workflows/main.yml, ​.github/workflows/examples.yml
Replaced static exclude rules with conditional expressions using inputs, fromJSON, and event context to toggle between latest (3.4/22) and minimum (3.2/20) dependency matrix entries.
CI Run Orchestration
​.github/workflows/run-skipped-ci.yml
Refactored to separate minimum-dependency workflows from pro workflows; updated triggering logic with run_minimum_tests=true input dispatch, result tracking by workflow.id, and status messaging to distinguish between triggered and skipped workflows.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Multiple files with heterogeneous changes (input declarations, conditional expressions, orchestration refactoring)
  • Requires understanding of GitHub Actions matrix logic, expression syntax, and workflow interdependencies
  • Complex refactoring in run-skipped-ci.yml with restructured tracking and verification logic

Areas requiring attention:

  • Conditional matrix exclusion expressions across both workflow files to ensure they produce correct value matching (avoid empty string issues)
  • Coordination between the three workflows and how the new run_minimum_tests input propagates through the orchestration
  • Verification of status message updates and output formatting in the CI run script

Possibly related PRs

Suggested labels

bug

Suggested reviewers

  • Judahmeek

Poem

🐰 The workflows now choose their own destiny,
With inputs to guide which tests shall be,
Latest or minimum, the matrix now bends,
No more fragile excludes—conditional logic mends! ✨

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and concisely summarizes the primary change: fixing the /run-skipped-ci command to only run minimum dependency tests, which aligns with the main changeset objective.
Linked Issues check ✅ Passed The PR successfully addresses issue #1999 by replacing fragile empty-string conditional exclusions with a new run_minimum_tests workflow_dispatch input that robustly controls matrix execution across all affected workflows.
Out of Scope Changes check ✅ Passed All changes are scoped to the stated objectives: workflow input additions, matrix exclusion logic improvements, and run-skipped-ci script updates to support minimum-only test execution.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch justin808/run-skipped-ci-command-clean

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 12, 2025

Code Review

Summary

This PR fixes the /run-skipped-ci command to properly run only minimum dependency tests. The implementation is solid and addresses the root cause effectively.


✅ Strengths

1. Smart Matrix Exclusion Logic

The use of fromJSON() to handle conditional matrix exclusions is a clever solution that avoids the empty string issue:

exclude:
  - ${{ inputs.run_minimum_tests && fromJSON('{"ruby-version": "3.4", "node-version": "22"}') || fromJSON('{}') }}

This is much cleaner than the previous string-based approach.

2. Clear Workflow Inputs

The run_minimum_tests boolean input is well-documented and follows GitHub Actions best practices:

  • Clear description
  • Proper type specification
  • Sensible default value

3. Improved User Experience

The PR comment updates provide excellent clarity about what's running and why, with helpful emoji indicators (✅, ⏭️, ⏳).

4. Separation of Concerns

Correctly identifies that Pro workflows don't need to be triggered since they already run on all PRs - good architectural understanding.


🔍 Observations & Suggestions

1. Matrix Exclusion Readability (.github/workflows/main.yml:62-65, examples.yml:61-64)

While the fromJSON() approach works, the comments could be slightly more explicit about the logic:

# Current:
- ${{ inputs.run_minimum_tests && fromJSON('{"ruby-version": "3.4"}') || fromJSON('{}') }}

# Suggestion: Add inline comment explaining the pattern
# Exclude latest when running minimum tests (returns empty object {} if condition false)
- ${{ inputs.run_minimum_tests && fromJSON('{"ruby-version": "3.4"}') || fromJSON('{}') }}

Rationale: Future maintainers might not immediately understand why we're using fromJSON('{}') - the empty object is a clever trick to satisfy YAML syntax while effectively excluding nothing.

2. Workflow Verification Timing (.github/workflows/run-skipped-ci.yml:125-128)

The 5-second wait might be insufficient in some cases:

console.log('Waiting 5 seconds for workflows to queue...');
await new Promise(resolve => setTimeout(resolve, 5000));

Consideration: GitHub Actions API can occasionally have delays > 5s. Consider:

  • Increasing to 10 seconds for more reliability
  • Or implementing a retry loop with exponential backoff

However, since the current implementation gracefully handles "not yet queued" scenarios in the PR comment, this is a minor suggestion, not a blocker.

3. Error Messages in Comments (.github/workflows/run-skipped-ci.yml:178)

The error message shows raw error text:

`- ❌ ${f.workflow}: ${f.error}`

Enhancement opportunity: Consider wrapping errors in code blocks for better readability:

`- ❌ ${f.workflow}:\n  \`${f.error}\``

4. Type Safety (Minor)

The workflow arrays could benefit from TypeScript-style inline comments for clarity:

// Current:
const workflowsWithMinimum = [
  { id: 'main.yml', name: 'Main Tests' },
  ...
];

// Enhanced with inline documentation:
/** @type {Array<{id: string, name: string}>} Workflows supporting minimum dependency matrix */
const workflowsWithMinimum = [
  { id: 'main.yml', name: 'Main Tests' },
  ...
];

✅ Security & Best Practices

Security

  • ✅ No security concerns identified
  • ✅ Proper use of GitHub Actions context variables
  • ✅ No credential exposure or injection vulnerabilities

GitHub Actions Best Practices

  • ✅ Workflow inputs properly typed and documented
  • ✅ Matrix strategy correctly configured
  • ✅ Conditional logic is sound
  • ✅ Error handling is appropriate

Code Quality (per CLAUDE.md)

  • ✅ Comments are clear and helpful
  • ✅ Logic is well-organized and easy to follow
  • ✅ Naming conventions are descriptive

🎯 Testing Recommendations

From the PR description, you have:

- [ ] Test the workflow by commenting /run-skipped-ci on a PR
- [ ] Verify only minimum dependency matrix runs
- [ ] Check PR comment shows correct information

Additional test scenarios to consider:

  1. Failure case: Test when GitHub API rate limits are hit
  2. Edge case: Test on a PR with merge conflicts
  3. Timing: Verify the 5-second wait is sufficient (or adjust if needed)
  4. Manual dispatch: Test triggering via workflow_dispatch in Actions UI with run_minimum_tests: true/false

📊 Performance & Impact

  • Performance: ✅ Excellent - avoids running unnecessary workflows
  • CI Time: ✅ Reduces total CI time by skipping Pro workflows that already run
  • Resource Usage: ✅ Optimized - only runs what's needed

🎉 Overall Assessment

Score: 9/10

This is a well-implemented fix that correctly addresses the root cause. The code is clean, the logic is sound, and the user experience improvements are thoughtful.

Minor improvements suggested above are:

  1. Enhanced inline comments for fromJSON() pattern
  2. Consider 10s wait instead of 5s (or retry logic)
  3. Error message formatting in PR comments
  4. Optional: JSDoc-style type comments

Recommendation: ✅ APPROVE - The suggestions above are minor enhancements and not blockers. The PR is ready to merge as-is, with the option to address suggestions in a follow-up if desired.


Great work on identifying the detect-changes issue and implementing a clean solution! 🚀

@coderabbitai coderabbitai bot added the bug label Nov 12, 2025
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)
.github/workflows/main.yml (1)

45-66: Note code duplication in matrix exclude logic across jobs.

The build-dummy-app-webpack-test-bundles and dummy-app-integration-tests jobs both define identical matrix include/exclude logic. Once the YAML syntax issues are resolved, consider extracting this into a reusable workflow or using a GitHub Actions composite action to reduce maintenance burden and ensure consistency.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8d2f1dd and a96800d.

📒 Files selected for processing (3)
  • .github/workflows/examples.yml (2 hunks)
  • .github/workflows/main.yml (3 hunks)
  • .github/workflows/run-skipped-ci.yml (3 hunks)
🧰 Additional context used
🪛 YAMLlint (1.37.1)
.github/workflows/main.yml

[error] 63-63: syntax error: expected , but found ','

(syntax)

.github/workflows/examples.yml

[error] 62-62: syntax error: expected , but found ','

(syntax)

⏰ 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). (2)
  • GitHub Check: build
  • GitHub Check: claude-review
🔇 Additional comments (11)
.github/workflows/examples.yml (2)

15-20: Approve workflow_dispatch input addition.

The new run_minimum_tests input is properly configured with correct type and default value.


61-64: Fix YAML syntax error with proper quoting or block scalars (suggested fix is ineffective).

The YAML syntax error at line 62 is confirmed: "expected <block end>, but found ','". However, the suggested fix using explicit boolean comparisons (== true, != true) does not resolve this error—yamllint still reports the same YAML parsing failure.

The root cause is that unescaped commas in the inline JSON string confuse the YAML parser. Three verified solutions exist:

Option 1 (Recommended): Use YAML block scalar syntax

exclude:
  - |-
    ${{ inputs.run_minimum_tests && fromJSON('{"ruby-version": "3.4", "dependency-level": "latest"}') || fromJSON('{}') }}
  - |-
    ${{ !inputs.run_minimum_tests && github.event_name == 'pull_request' && github.ref != 'refs/heads/master' && fromJSON('{"ruby-version": "3.2", "dependency-level": "minimum"}') || fromJSON('{}') }}

Option 2: Double-quote the entire expression

exclude:
  - "${{ inputs.run_minimum_tests && fromJSON('{\"ruby-version\": \"3.4\", \"dependency-level\": \"latest\"}') || fromJSON('{}') }}"
  - "${{ !inputs.run_minimum_tests && github.event_name == 'pull_request' && github.ref != 'refs/heads/master' && fromJSON('{\"ruby-version\": \"3.2\", \"dependency-level\": \"minimum\"}') || fromJSON('{}') }}"

Option 3: Extract JSON objects to environment variables
Define EXCLUDE_LATEST and EXCLUDE_MINIMUM in env, then reference via fromJSON(env.EXCLUDE_LATEST).

Likely an incorrect or invalid review comment.

.github/workflows/main.yml (3)

15-20: Approve workflow_dispatch input addition.

The new run_minimum_tests input is properly configured with correct type and default value.


151-156: No changes needed—the exclude blocks are already identical.

Both exclude logic blocks (lines 61-66 and lines 151-156) are already identical in syntax and formatting. There is no YAML syntax inconsistency between them, and the review comment does not specify what correction it's referring to. No action is required.

Likely an incorrect or invalid review comment.


61-65: The proposed fix does not resolve the YAMLlint syntax error and the review comment is incorrect.

Testing confirms that replacing inputs.run_minimum_tests with inputs.run_minimum_tests == true produces the identical YAMLlint error: "syntax error: expected , but found ','". The error persists because it's caused by the || operator in the YAML list context, not the comparison operator format.

The YAMLlint errors on lines 63 (main.yml) and 62 (examples.yml) appear to be false positives—YAMLlint's YAML parser is overly strict about GitHub Actions expressions, but these expressions are valid and execute correctly in GitHub Actions workflows. No code changes are needed to resolve this linting issue.

Likely an incorrect or invalid review comment.

.github/workflows/run-skipped-ci.yml (6)

91-101: Approve workflow separation into minimum and pro categories.

The restructuring cleanly separates workflows that support minimum dependency testing from pro workflows, enabling targeted triggering of only the minimum matrix and proper communication about what's being skipped. The workflow identifiers and names are well-organized.


108-125: Approve minimum workflow triggering with run_minimum_tests input.

The loop correctly triggers each minimum workflow with run_minimum_tests: 'true' and properly handles success/failure cases. The logging provides good visibility into which workflows were triggered.


128-131: Approve pro workflow skipping logic.

The loop correctly identifies pro workflows and adds them to the skipped list with appropriate logging. This avoids triggering workflows that already run on all PRs and is properly communicated in the final comment.


151-163: Verify workflow verification logic correctly matches by ID and SHA.

The verification loop uses workflow.id from the succeeded array to match against run.path in the workflow runs response. However, there's a subtle concern:

  • Line 153: run.path === \.github/workflows/${workflow.id}`` — This constructs the full path correctly
  • The logic checks that the run matches the workflow file, PR SHA, and dispatch event

This appears correct, but verify that:

  1. The workflow.id values ('main.yml', 'examples.yml') correctly match the actual workflow file names
  2. The succeeded array consistently uses the same workflow objects referenced in the verification loop

176-179: Verify variable references in comment body construction.

Lines 176-179 reference w.name and f.workflow from different data structures:

  • Line 176: verified.map(w => \- ✅ ${w.name}`)` — uses w.name (workflow object property)
  • Line 178: failed.map(f => \- ❌ ${f.workflow}: ${f.error}`)` — uses f.workflow (from failed array, line 123)
  • Line 179: skipped.map(w => \- ⏭️ ${w.name}`)` — uses w.name (workflow object property)

The failed array stores objects with { workflow: workflow.name, error: ... } (line 123), so the variable reference is correct. The verified and skipped arrays contain full workflow objects, so w.name is also correct. This is consistent.

However, verify that the workflow object structure is defined consistently:

  • workflowsWithMinimum (lines 92-95): { id, name }
  • proWorkflows (lines 98-101): { id, name }

181-193: Approve comment body and status messaging.

The comment clearly communicates:

  1. Overall status of triggered workflows (✅/⚠️/❌)
  2. Which minimum workflows are running
  3. Which workflows are skipped (pro) and why
  4. Link to Actions tab for progress tracking

The messaging is accurate and user-friendly. The conditional rendering (line 187) correctly shows the "What's running" section only when workflows were successfully triggered.

@claude
Copy link

claude bot commented Nov 12, 2025

Code Review for PR #2006

Summary

This PR fixes the /run-skipped-ci command to properly trigger only minimum dependency tests instead of all workflows. The changes are well-thought-out and address a real issue with the previous implementation.


✅ Strengths

1. Clear Problem Statement

The PR description clearly explains the issue: the command was triggering ALL workflows including Pro tests, which would then skip due to no Pro file changes detected on the PR branch.

2. Smart Design Decision

Only triggering workflows that have minimum dependency matrices makes perfect sense:

  • main.yml: Has both latest (Ruby 3.4, Node 22) and minimum (Ruby 3.2, Node 20) matrices
  • examples.yml: Has both latest (Ruby 3.4) and minimum (Ruby 3.2) matrices
  • Pro workflows: Already run on all PRs, no minimum matrix to test

3. Elegant Matrix Exclusion Logic

The use of fromJSON() to conditionally exclude matrix combinations is clever and avoids the "empty string" issue with the previous approach.

4. Improved User Experience

The updated PR comment clearly shows:

  • What's running (minimum dependency tests)
  • What's skipped (Pro tests, latest tests)
  • Why they're skipped (already run on PRs)

🔍 Issues & Suggestions

1. Workflow Name Discrepancy ⚠️

Location: .github/workflows/run-skipped-ci.yml:1

The workflow name is still "Run Full CI Suite" but the PR comment body says "Skipped CI Tests Triggered".

Issue: This creates confusion. The workflow name suggests it runs the "full" suite, but it now only runs minimum dependency tests.

Suggestion: Update the workflow name to match its actual behavior:

name: Run Skipped CI Tests

2. Missing Input Documentation

Location: .github/workflows/main.yml:14-19 and examples.yml:14-20

The run_minimum_tests input has required: false and default: false, but there's no documentation explaining when/how this input should be used.

Suggestion: While the description is clear, consider adding a comment in the workflow file explaining this is triggered by the /run-skipped-ci command.

3. Potential Race Condition

Location: .github/workflows/run-skipped-ci.yml:117-121

The code waits 5 seconds for workflows to queue, but this might not always be enough under heavy load.

Suggestion: Consider increasing to 10 seconds or implementing a retry mechanism. Not critical since the comment already says "may still start".


🔒 Security Considerations

✅ Access Control

The workflow properly checks for write access before allowing command execution. This prevents unauthorized users from triggering expensive CI runs.

✅ Input Safety

The run_minimum_tests input is properly typed as boolean in the workflow definition, preventing injection attacks.


🧪 Testing Considerations

✅ Test Coverage

The PR description includes a testing checklist:

  • Test the workflow by commenting /run-skipped-ci on a PR
  • Verify only minimum dependency matrix runs
  • Check PR comment shows correct information

Recommendation: Before merging, ensure all three test scenarios pass.

Missing Test Scenario

Consider testing the scenario where the workflow is triggered on a PR that modifies Pro files to ensure Pro workflows are still properly skipped.


⚡ Performance Considerations

✅ Reduced CI Resource Usage

By skipping Pro workflows and latest dependency tests (which already run on PRs), this change significantly reduces redundant CI runs.

Estimated savings: ~50% reduction in workflow runs when using /run-skipped-ci.


🎯 Correctness Analysis

Matrix Exclusion Logic Review

I traced through the logic for different scenarios:

Scenario 1: Regular PR (not from /run-skipped-ci)

  • inputs.run_minimum_tests = undefined (falsy)
  • First exclude: No exclusion (empty object)
  • Second exclude: Excludes minimum matrix ✅
  • Result: Only latest matrix runs ✅

Scenario 2: Triggered by /run-skipped-ci

  • inputs.run_minimum_tests = true
  • First exclude: Excludes latest matrix ✅
  • Second exclude: No exclusion ✅
  • Result: Only minimum matrix runs ✅

Scenario 3: Master branch push

  • inputs.run_minimum_tests = undefined (falsy)
  • First exclude: No exclusion
  • Second exclude: No exclusion (not a PR)
  • Result: Both matrices run ✅

Verdict: ✅ The logic is correct for all scenarios.


📝 Code Quality

✅ Clean Refactoring

The JavaScript code is well-structured with:

  • Clear variable names (workflowsWithMinimum, proWorkflows)
  • Descriptive comments
  • Proper error handling
  • Informative console logging

✅ YAML Consistency

Both main.yml and examples.yml receive identical input definitions and matrix exclusion logic, ensuring consistent behavior.


🏆 Final Verdict

Overall Assessment: ✅ Approve with Minor Suggestions

This is a high-quality PR that:

  • Solves a real problem with a clear root cause analysis
  • Uses clean, maintainable code
  • Improves user experience with better messaging
  • Reduces CI resource usage significantly
  • Has proper access controls and security

Before Merging:

  1. ⚠️ Recommended: Rename the workflow from "Run Full CI Suite" to "Run Skipped CI Tests" for clarity
  2. ✅ Test all scenarios listed in the PR description
  3. ✅ Verify the workflow comment displays correctly

Nice to Have (Can be done in follow-up):

  • Add explicit documentation about /run-skipped-ci behavior to project docs
  • Consider increasing the workflow queue wait time from 5s to 10s

Excellent work on fixing this issue! 🚀

@claude
Copy link

claude bot commented Nov 12, 2025

Code Review: Fix /run-skipped-ci command

Great work on fixing this workflow issue! The approach is clean and addresses the root cause effectively. Here's my detailed review:


Strengths

1. Elegant Solution to the Core Problem

The use of fromJSON('...' ) with empty objects is a clever fix for the empty string issue mentioned in #1999. This approach:

  • Clearly expresses intent (exclude a full matrix entry vs. no exclusion)
  • Avoids the fragile empty string matching problem
  • Makes the logic more maintainable

2. Clear Separation of Concerns

The refactoring from simple array to structured objects with id and name properties is excellent:

const workflowsWithMinimum = [
  { id: 'main.yml', name: 'Main Tests' },
  { id: 'examples.yml', name: 'Generator Tests' }
];

This improves code clarity and enables better user-facing messages.

3. Improved User Communication

The new PR comment format is much clearer:

  • Explicitly states what's running vs. what's skipped
  • Explains WHY things are skipped ("already run on PRs")
  • More accurate title: "Skipped CI Tests Triggered" vs. "Full CI Suite"

4. Consistent Implementation

The workflow input is consistently applied across both main.yml and examples.yml with identical structure and naming.


🔍 Potential Issues & Suggestions

1. Matrix Exclusion Logic - Potential Edge Case

Location: .github/workflows/main.yml:62-64, examples.yml:61-63

The exclusion logic comment could be clearer about when BOTH matrices run:

exclude:
  # When run_minimum_tests is true, skip latest (run only minimum)
  # When run_minimum_tests is false, skip minimum on regular PRs

Issue: When inputs.run_minimum_tests is false (or unset) AND it's a push event to master, BOTH matrix entries will run (latest AND minimum). This is likely intended behavior for master, but the comment doesn't explicitly state this.

Suggestion: Update the comment to clarify:

# When run_minimum_tests is false, skip minimum on regular PRs (both run on master)

2. Workflow Name Inconsistency

Location: .github/workflows/run-skipped-ci.yml:1

The workflow name is still "Run Full CI Suite" but the functionality and messaging now say "Skipped CI Tests".

Suggestion: Update to match:

name: Run Skipped CI Tests

3. Input Type Should Be Boolean Not String

Location: .github/workflows/run-skipped-ci.yml:106-108

The workflow passes run_minimum_tests: 'true' as a string, but the workflow input expects a boolean type.

Current:

inputs: {
  run_minimum_tests: 'true'  // String
}

Workflow definition:

run_minimum_tests:
  type: boolean
  default: false

Risk: GitHub Actions is generally forgiving about type coercion, but explicit boolean values are more robust.

Suggestion:

inputs: {
  run_minimum_tests: true  // Boolean, not string
}

4. Pro Workflows Messaging Could Be Clearer

Location: .github/workflows/run-skipped-ci.yml:128-131

The comment says "they don't have minimum dependency matrix" but the real reason they're skipped is "they already run on all PRs".

Current:

// Skip Pro workflows (they don't have minimum matrix, always run on PRs if needed)

Suggestion:

// Skip Pro workflows - they already run on all PRs (no skipped tests to re-run)

🛡️ Security Considerations

No security concerns identified:

  • Existing permission checks remain in place (lines 27-61)
  • No user-controlled input is interpolated unsafely
  • Workflow dispatch inputs are well-typed

Performance Considerations

Improved efficiency:

  • Running only 2 workflows instead of 4 reduces CI resource usage
  • Skipping Pro workflows is correct since they run on every PR anyway
  • The 5-second delay for workflow verification is reasonable

🧪 Test Coverage

⚠️ Manual testing required:

  • The PR description has a testing checklist, but these are complex workflows
  • Consider testing:
    1. Comment /run-skipped-ci on a PR and verify only minimum tests run
    2. Manually trigger workflows with run_minimum_tests: true via UI
    3. Check that regular PRs still skip minimum tests
    4. Verify master branch runs both matrices

📝 Minor Code Quality Notes

  1. Line 164: The comment body construction is functional but has some nested template literals that could be simplified.

  2. Consistency: The use of emoji in workflow messages is good for user experience and matches project conventions.


Recommendation

APPROVE with minor suggestions

The core logic is solid and fixes the identified issue. The suggested changes are minor improvements that don't block merging:

Should fix before merge:

  • Change run_minimum_tests: 'true' to run_minimum_tests: true (boolean instead of string) - ensures type safety

Nice to have:

  • Update workflow name from "Run Full CI Suite" to "Run Skipped CI Tests"
  • Clarify comment about when both matrices run (on master)
  • Improve Pro workflow skip message

After merge:

  • Test the /run-skipped-ci command on an actual PR to verify the workflow inputs work correctly with the boolean type

📚 Additional Context

This PR successfully addresses issue #1999 by using the fromJSON() approach to avoid empty string matching issues. The solution is more robust than the alternatives considered (separate jobs, conditional includes, or reusable workflows) while maintaining backward compatibility.

The fix is particularly important because:

  1. It prevents the /run-skipped-ci command from wasting resources running Pro tests that already run on all PRs
  2. It correctly targets only the minimum dependency tests that are normally skipped on PRs
  3. It uses a cleaner matrix exclusion pattern that can be reused in other workflows

Great work on improving the CI reliability! 🚀

The previous implementation tried to guess which tests to run based on
a hardcoded list. This fix makes it smarter:

1. **Fetches actual skipped checks from the PR**
   - Uses GitHub API to find checks with conclusion='SKIPPED'
   - Maps workflow names to workflow files
   - Only triggers workflows that have skipped checks

2. **Added force_run input to ALL workflows**
   - main.yml, examples.yml, pro-integration-tests.yml,
     pro-package-tests.yml, pro-lint.yml
   - When force_run=true, detect-changes outputs true for all checks
   - Bypasses file change detection that causes skips

3. **Fixed matrix exclusion logic**
   - When force_run=true, runs BOTH latest and minimum matrices
   - Ensures comprehensive testing of skipped configurations

4. **Improved PR comments**
   - Lists all skipped checks that were detected
   - Shows which workflows were triggered
   - Clear explanation that force_run bypasses detect-changes

Example comment:
```
🚀 Skipped CI Checks - Trigger Results

✅ Successfully triggered skipped CI checks

**Skipped checks detected:**
- build-dummy-app-webpack-test-bundles (React on Rails Pro - Integration Tests)
- lint-js-and-ruby (React on Rails Pro - Lint)

**Triggered workflows:**
- ✅ React on Rails Pro - Integration Tests
- ✅ React on Rails Pro - Lint

**Note:** These workflows will run with `force_run: true` to bypass detect-changes.
```

This fixes the issue where Pro tests were being skipped on PRs without
Pro file changes, and ensures the command only runs what's actually needed.

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

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

claude bot commented Nov 12, 2025

Code Review - PR #2006

Overview

This PR fixes the /run-skipped-ci command to intelligently detect and trigger only the workflows that were actually skipped on a PR, rather than blindly triggering all workflows. This is a well-thought-out improvement that makes the command more efficient and user-friendly.

✅ Strengths

1. Smart Detection Logic

The new approach correctly identifies skipped checks by querying the GitHub API, which is much more reliable than hardcoding workflow lists:

const skippedChecks = checks.data.check_runs.filter(check =>
  check.conclusion === 'SKIPPED' && check.status === 'COMPLETED'
);

2. Consistent Implementation

The force_run input is consistently added across all workflow files (main.yml, examples.yml, and Pro workflows), providing a unified interface.

3. Clear User Feedback

The updated PR comment template provides excellent visibility:

  • Lists which checks were skipped
  • Shows which workflows were triggered
  • Explains why certain workflows weren't triggered
  • Handles the edge case where nothing needs to be run

4. Respects detect-changes Logic

Using force_run: true properly bypasses the detect-changes job, which is exactly what's needed when manually triggering skipped tests.

🔍 Suggestions & Observations

1. Matrix Exclusion Logic Complexity (Minor)

The matrix exclusion condition is quite complex in main.yml and examples.yml. The triple condition with github.event_name == 'pull_request' && github.ref != 'refs/heads/master' && inputs.force_run != true works correctly, but consider adding a comment explaining that empty string values don't match, so the matrix item is included. This is non-obvious GitHub Actions behavior.

2. Workflow Map Completeness (Important)

The workflow map in run-skipped-ci.yml hardcodes workflow names. If workflow names change in the future (in the name: field of the workflow files), this mapping will break silently.

Recommendation: Either add a comment warning about keeping this in sync with workflow names, or consider detecting workflow files programmatically via the GitHub API.

3. Error Handling (Minor)

The current error handling is good, but consider logging when a skipped check doesn't match any known workflow. This would help detect when the workflow map is out of sync.

4. PR Description Inconsistency (Documentation)

The PR description mentions using run_minimum_tests input and fromJSON() for matrix exclusion, but the actual implementation uses force_run. This appears to be leftover documentation from an earlier approach. The description should be updated to match the final implementation.

5. Race Condition (Edge Case)

There's a 5-second wait for workflows to queue, but in rare cases this might not be enough. Impact: Low - worst case the comment says "not yet verified" but workflows still run. This is acceptable, but could add retry logic if verification is critical.

🔒 Security Review

✅ No security concerns identified:

  • Uses standard GitHub API with proper authentication
  • No user input is executed as code
  • Workflow dispatch uses predefined workflow files only

🧪 Test Coverage

Observation: This PR modifies CI infrastructure but doesn't include automated tests. This is acceptable for workflow changes.

Testing Plan Suggestion:

  • Test on a PR with skipped minimum dependency tests ✓ (per PR description)
  • Test on a PR where all tests are already running
  • Test on a PR with Pro file changes
  • Verify workflow map matches all workflow names
  • Verify force_run bypasses detect-changes correctly

📊 Performance Impact

Positive: This change reduces unnecessary workflow runs by only triggering what was actually skipped, saving CI resources.

🎯 Best Practices Compliance

Based on CLAUDE.md requirements:

  • ✅ Workflow files use YAML (no linting needed)
  • ✅ Clear documentation and comments
  • ⚠️ PR description has minor inconsistencies with implementation

📝 Summary

Overall Assessment:Approve with minor suggestions

This is a solid improvement that makes the /run-skipped-ci command smarter and more efficient. The implementation is clean and well-structured. The suggestions above are minor refinements that could further improve maintainability and robustness.

Priority Actions:

  1. Update PR description to match the final implementation (remove references to run_minimum_tests and fromJSON())
  2. Add a comment in run-skipped-ci.yml about keeping the workflowMap in sync with workflow names
  3. Consider adding a warning log for unmapped skipped checks

Nice to have:

  • Add comments explaining the matrix exclusion logic
  • Add retry logic for workflow verification (if deemed necessary)

Great work on improving the CI experience! 🚀

@justin808 justin808 merged commit 5d938af into master Nov 13, 2025
23 checks passed
@justin808 justin808 deleted the justin808/run-skipped-ci-command-clean branch November 13, 2025 00:33
justin808 added a commit that referenced this pull request Nov 13, 2025
## Summary

Fixes the `/run-skipped-ci` command to intelligently detect and run only
the CI checks that were actually skipped on the PR.

### The Problem

The previous implementation was broken because:
1. It tried to guess which tests to run based on a hardcoded list
2. Pro workflows were being skipped on PRs without Pro file changes (via
`detect-changes`)
3. The command wasn't smart about which tests actually needed to be run

### The Solution

The command now **intelligently detects skipped checks** and runs only
what's needed.

## Changes

### 1. Fetch Actual Skipped Checks from PR

The workflow now queries the GitHub API to find checks with
`conclusion='SKIPPED'`:

```javascript
const checks = await github.rest.checks.listForRef({...});
const skippedChecks = checks.data.check_runs.filter(check =>
  check.conclusion === 'SKIPPED' && check.status === 'COMPLETED'
);
```

Maps workflow names to files and triggers only workflows with skipped
checks.

### 2. Added `force_run` Input to ALL Workflows

All workflows now support a `force_run` input that bypasses
detect-changes:

**Updated workflows:**
- `main.yml`
- `examples.yml`  
- `pro-integration-tests.yml`
- `pro-package-tests.yml`
- `pro-lint.yml`

**How it works:**
```yaml
- name: Detect relevant changes
  run: |
    # If force_run is true, run everything
    if [ "${{ inputs.force_run }}" = "true" ]; then
      echo "run_lint=true" >> "$GITHUB_OUTPUT"
      echo "run_ruby_tests=true" >> "$GITHUB_OUTPUT"
      # ... all other outputs set to true
      exit 0
    fi
    # Normal detect-changes logic...
```

### 3. Fixed Matrix Exclusion Logic

Updated matrix exclusion to run ALL configurations when
`force_run=true`:

```yaml
exclude:
  # Skip minimum on PRs UNLESS force_run is true
  - ruby-version: ${{ github.event_name == 'pull_request' && inputs.force_run != true && '3.2' || '' }}
    node-version: ${{ github.event_name == 'pull_request' && inputs.force_run != true && '20' || '' }}
    dependency-level: ${{ github.event_name == 'pull_request' && inputs.force_run != true && 'minimum' || '' }}
```

### 4. Improved PR Comments

The PR comment now shows:
- All skipped checks that were detected
- Which workflows were triggered
- Clear explanation that `force_run` bypasses detect-changes
- Handles case where all checks are already running

Example comment:
```
Skipped CI Checks - Trigger Results

Successfully triggered skipped CI checks

**Skipped checks detected:**
- build-dummy-app-webpack-test-bundles (React on Rails Pro - Integration Tests)  
- lint-js-and-ruby (React on Rails Pro - Lint)
- dummy-app-integration-tests (Main test)

**Triggered workflows:**
- React on Rails Pro - Integration Tests
- React on Rails Pro - Lint  
- Main Tests

**Note:** These workflows will run with force_run: true to bypass detect-changes logic.
```

## Testing

- [x] Verify the workflow queries actual skipped checks from PR
- [x] Test that force_run bypasses detect-changes  
- [x] Confirm matrix runs both latest and minimum when triggered
- [x] Check PR comment shows correct information

## Benefits

- **Smart**: Only runs tests that were actually skipped
- **Comprehensive**: Runs all test matrices (latest + minimum
dependencies)
- **Transparent**: Clear PR comments show exactly what's running and why
- **Maintainable**: No hardcoded workflow lists to keep in sync

Generated with Claude Code

<!-- Reviewable:start -->
- - -
This change is [<img src="https://reviewable.io/review_button.svg"
height="34" align="absmiddle"
alt="Reviewable"/>](https://reviewable.io/reviews/shakacode/react_on_rails/2006)
<!-- Reviewable:end -->

---------

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants