Skip to content

Conversation

@justin808
Copy link
Member

@justin808 justin808 commented Nov 13, 2025

Summary

  • /run-skipped-ci now adds a persistent full-ci label to the PR
  • New /stop-run-skipped-ci command removes the label to disable full CI mode
  • All workflows updated to check for the full-ci label in addition to force_run input
  • Label persists across commits, ensuring full CI runs until explicitly stopped

Problem

Previously, when running /run-skipped-ci:

  1. Tests would start
  2. Making a commit would stop all tests
  3. Full CI never completed

Solution

The full-ci label acts as a persistent flag:

  • Added by /run-skipped-ci command
  • Checked by all workflow detect-changes jobs
  • Remains active across all future commits
  • Only removed by /stop-run-skipped-ci command

Workflows Updated

  • main.yml - Main integration tests
  • examples.yml - Generator tests
  • pro-integration-tests.yml - Pro integration tests
  • pro-package-tests.yml - Pro package tests
  • pro-lint.yml - Pro linting

All workflows now:

  1. Check for full-ci label on PRs
  2. If label present, run full CI suite (including minimum dependency tests)
  3. Otherwise, use standard change detection

Usage

# Enable full CI mode (persists across commits)
/run-skipped-ci

# Disable full CI mode
/stop-run-skipped-ci

Test Plan

  • Test /run-skipped-ci adds the label and triggers workflows
  • Verify label persists after pushing new commits
  • Confirm full CI runs on subsequent commits with label present
  • Test /stop-run-skipped-ci removes the label
  • Verify CI returns to normal mode after label removal

🤖 Generated with Claude Code


This change is Reviewable

Summary by CodeRabbit

  • Chores

    • CI now supports a "full-ci" label to trigger the full test suite and propagate that state across workflows.
    • New commands to enable/disable full CI via PR comments: /run-skipped-ci and /stop-run-skipped-ci.
    • Automatic cleanup of the full-ci label when PRs are merged.
  • Documentation

    • CONTRIBUTING.md updated with CI control commands and an updated install example.
  • New Features

    • Welcome message posted on new PRs explaining CI controls and status.

Changes:
- Add full-ci label when /run-skipped-ci is triggered
- Create /stop-run-skipped-ci command to remove the label
- Update all workflows to check for full-ci label in addition to force_run input
- Label persists across commits, ensuring full CI runs until explicitly stopped

This fixes the issue where /run-skipped-ci would start tests but they'd
stop when committing. Now the label keeps full CI enabled across all
future commits until /stop-run-skipped-ci is run.

🤖 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 13, 2025

Warning

Rate limit exceeded

@justin808 has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 12 minutes and 26 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between aac7121 and f9da7d3.

📒 Files selected for processing (10)
  • .github/actions/check-full-ci-label/action.yml (1 hunks)
  • .github/workflows/examples.yml (2 hunks)
  • .github/workflows/main.yml (3 hunks)
  • .github/workflows/pr-welcome-message.yml (1 hunks)
  • .github/workflows/pro-integration-tests.yml (1 hunks)
  • .github/workflows/pro-lint.yml (1 hunks)
  • .github/workflows/pro-package-tests.yml (1 hunks)
  • .github/workflows/run-skipped-ci.yml (1 hunks)
  • .github/workflows/stop-run-skipped-ci.yml (1 hunks)
  • CONTRIBUTING.md (1 hunks)

Walkthrough

Adds label-driven "full-ci" control to CI: workflows now check for a full-ci PR label, expose has_full_ci_label from detect-changes jobs, and run full test matrices when the label is present or when force_run is true. New workflows add, remove, and cleanup the label and post PR welcome messaging.

Changes

Cohort / File(s) Summary
Label detection across workflows
/.github/workflows/examples.yml, /.github/workflows/main.yml, /.github/workflows/pro-integration-tests.yml, /.github/workflows/pro-lint.yml, /.github/workflows/pro-package-tests.yml
Added a Check for full-ci label step (uses actions/github-script@v7) and exported has_full_ci_label from detect-changes. Detection logic now runs full CI when force_run OR has_full_ci_label is true. Matrix exclusion conditions updated to respect the label.
Add full-ci label workflow
/.github/workflows/run-skipped-ci.yml
Reworked PR-triggered workflow to add the full-ci label (via GitHub Script), changed PR message headings/body to reflect label-based Full CI mode, and updated instructions for disabling label-based mode.
Stop / remove full-ci label workflow
/.github/workflows/stop-run-skipped-ci.yml
New workflow triggered by /stop-run-skipped-ci comments: checks commenter permissions, removes full-ci label, handles 404 and other errors with informative comments, and posts confirmations or denials.
Cleanup on merge workflow
/.github/workflows/cleanup-full-ci-label.yml
New workflow that runs on PR closed and, if merged, attempts to remove full-ci label; treats missing-label (404) and other errors non-fatally.
PR welcome messaging
/.github/workflows/pr-welcome-message.yml
New workflow that posts a welcome comment on PR open explaining CI behavior and commands to enable/disable full CI.
Docs / contributing
CONTRIBUTING.md
Added CI control commands section (duplicated in two places) and updated a Ruby example to use a concrete relative path for installing the generator.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant PR as "Pull Request / Comments"
    participant GH as "GitHub API"
    participant Detect as "detect-changes job"
    participant CI as "Downstream CI jobs"

    User->>PR: Add `full-ci` label (manual or via /run-skipped-ci)
    Detect->>GH: Query PR labels (check-label step)
    GH-->>Detect: returns has_full_ci_label = true/false
    Detect->>Detect: set output `has_full_ci_label`
    alt has_full_ci_label == true OR force_run == true
        Detect->>CI: allow full matrix (no minimum exclusions)
    else
        Detect->>CI: preserve existing change-based exclusions
    end

    User->>PR: Comment `/stop-run-skipped-ci`
    PR->>GH: workflow verifies commenter permissions
    alt has write/admin access
        GH->>PR: remove `full-ci` label
        GH-->>PR: post confirmation comment
    else
        GH-->>PR: post permission denied comment
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Attention areas:
    • stop-run-skipped-ci.yml permission checks and error-handling branches.
    • Consistency of label-check step (actions/github-script) and has_full_ci_label output across multiple workflows.
    • Matrix exclusion condition logic updates to ensure intended gating.

Possibly related PRs

Suggested reviewers

  • Judahmeek
  • AbanoubGhadban
  • alexeyr-ci2

Poem

🐰 I nudged a label, CI wakes with a cheer,
Full runs now follow — no skips while I'm here.
A comment to stop it, a friendly little hop,
Label on, label off — the rabbit won't stop! 🥕

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and concisely summarizes the main change: introducing a persistent full-ci label mechanism via the /run-skipped-ci command to replace the temporary force_run behavior.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage 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 13, 2025

Code Review

This PR adds persistence to /run-skipped-ci using a full-ci label. Well-designed solution!

Strengths:

  • Elegant label-based approach solves the commit interruption issue
  • Consistent updates across all 5 workflows
  • Good error handling and permission checks
  • Clear user feedback

Code Quality Issues:

  1. Output Variable Naming: Declared as has_full_ci_label but accessed as result
  2. Duplicate Code: 15-line label check repeated 5 times (DRY violation)
  3. Missing Label Creation: Will fail with 404 if label doesn't exist
  4. Complex Exclude Logic: 4-condition chains are hard to read

Recommendations:

High Priority:

  • Fix output variable naming for consistency
  • Add auto-creation for full-ci label
  • Complete test plan checkboxes

Medium Priority:

  • Extract duplicate code to composite action
  • Simplify matrix exclude conditions
  • Update CLAUDE.md documentation

Security: Good - proper permission checks, no injection risks

Verdict: Low risk, good quality, ready after addressing high-priority items. Great work!

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: 2

🧹 Nitpick comments (1)
.github/workflows/main.yml (1)

184-186: Duplicate matrix exclusion logic for dummy-app-integration-tests job.

This duplicates the exclusion pattern from build-dummy-app-webpack-test-bundles (lines 92-96). Consider extracting this as a reusable workflow or documentation to maintain consistency if the logic needs to change.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c07dbd6 and 6fc849c.

📒 Files selected for processing (7)
  • .github/workflows/examples.yml (2 hunks)
  • .github/workflows/main.yml (3 hunks)
  • .github/workflows/pro-integration-tests.yml (1 hunks)
  • .github/workflows/pro-lint.yml (1 hunks)
  • .github/workflows/pro-package-tests.yml (1 hunks)
  • .github/workflows/run-skipped-ci.yml (2 hunks)
  • .github/workflows/stop-run-skipped-ci.yml (1 hunks)
🧰 Additional context used
🪛 YAMLlint (1.37.1)
.github/workflows/stop-run-skipped-ci.yml

[error] 86-86: syntax error: could not find expected ':'

(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/run-skipped-ci.yml (1)

231-243: YAML syntax issue in conditional string.

Line 231-241 uses template literals with nested conditionals. Line 236 and 243 should be reviewed for proper YAML string escaping, though this appears to be valid YAML (likely false positive from static analysis on similar syntax in another file).

.github/workflows/pro-package-tests.yml (2)

33-51: Label check implementation is consistent with other workflows.

The step properly:

  • Guards against non-PR contexts
  • Fetches labels via GitHub API
  • Returns boolean result
  • Logs presence for debugging

57-57: Detection logic correctly integrates label check.

The condition properly combines force_run input with has_full_ci_label detection, enabling full CI via either trigger mechanism.

.github/workflows/pro-integration-tests.yml (1)

33-51: Label check implementation mirrors pro-package-tests.yml pattern.

Implementation is consistent across workflows with proper non-PR guards and output exposure.

.github/workflows/pro-lint.yml (1)

33-51: Label check implementation consistent with other Pro workflows.

.github/workflows/stop-run-skipped-ci.yml (2)

1-20: Permissions and access control are properly configured.

The workflow correctly:

  • Limits to PR comments
  • Checks user write access
  • Declares necessary permissions (pull-requests: write, issues: write)
  • Exits early if access denied

64-111: Label removal has robust error handling.

The implementation properly:

  • Attempts label removal
  • Handles 404 (label not present) gracefully
  • Handles unexpected errors with detailed feedback
  • Posts informative comments for all outcomes
.github/workflows/main.yml (2)

39-57: Label check implementation is consistent with established pattern.

The step properly guards non-PR contexts and exposes output for downstream use.


92-96: Matrix exclusion logic will not work as intended — empty string values don't exclude the intended matrix row.

According to GitHub Actions documentation, matrix exclusion only removes entries that exactly match the specified keys/values; empty strings do not match non-empty values. When the condition is false (regular PRs), the exclude entry becomes {ruby-version: '', node-version: '', dependency-level: ''}, which does not match the actual matrix row {ruby-version: '3.2', node-version: '20', dependency-level: 'minimum'}. This means the minimum-dependency variant will still run on regular PRs instead of being skipped.

The exclusion logic needs to be rewritten using a different approach (e.g., a conditional if statement at the job level or using matrix.include/matrix.exclude with proper matching).

Likely an incorrect or invalid review comment.

.github/workflows/examples.yml (2)

39-57: Label check implementation is consistent with established pattern across all workflows.


92-94: Matrix exclusion properly gates minimum dependencies on full-ci label.

The exclusion correctly skips the minimum dependency variant on regular PRs unless force_run or full-ci label is present. Pattern is consistent with main.yml.

@claude
Copy link

claude bot commented Nov 13, 2025

Code Review: Full CI Label Implementation

Overview

This PR implements a persistent label-based mechanism for controlling full CI execution. The approach is sound and addresses a real workflow issue where full CI runs would be interrupted by new commits.


✅ Strengths

  1. Solves a Real Problem: The persistent label approach elegantly solves the issue where /run-skipped-ci wouldn't complete if commits were pushed during execution.

  2. Consistent Implementation: The label-checking logic is duplicated consistently across all 5 workflows, maintaining uniformity.

  3. Good Security: Permission checks ensure only collaborators with write access can manage the label.

  4. Clear User Feedback: The comment messages clearly explain what's happening and how to reverse the action.


🔍 Issues & Concerns

1. Critical Bug: Output Mismatch ⚠️

The check-label step outputs result (a boolean), but it's being referenced as has_label in job outputs:

# In outputs:
has_full_ci_label: ${{ steps.check-label.outputs.has_label }}  # ❌ Wrong!

# Should be:
has_full_ci_label: ${{ steps.check-label.outputs.result }}  # ✅ Correct

This means has_full_ci_label will always be empty, breaking the feature entirely. This affects:

  • .github/workflows/main.yml:32
  • .github/workflows/examples.yml:32
  • .github/workflows/pro-integration-tests.yml:27
  • .github/workflows/pro-lint.yml:27
  • .github/workflows/pro-package-tests.yml:27

2. Code Duplication

The label-checking logic is duplicated across 5 workflows (50+ lines × 5 = 250+ lines). Consider:

  • Creating a reusable workflow for the detect-changes job
  • Or creating a composite action for label checking

This would:

  • Reduce maintenance burden
  • Prevent bugs from inconsistent updates
  • Make testing easier

3. Missing Test Coverage

The test plan in the PR description is incomplete (all boxes unchecked). The output mismatch bug suggests this wasn't tested end-to-end. Consider:

  • Integration test that verifies label behavior
  • Test for the specific scenarios in the test plan
  • Verify the boolean-to-string conversion works correctly

4. Race Condition Potential

If someone pushes a commit while the run-skipped-ci workflow is still adding the label, the new commit's CI run might start before the label is applied. Consider:

  • Adding the label earlier in the workflow (before triggering checks)
  • Or documenting this edge case

5. Boolean vs String Comparison

GitHub Actions expressions can be tricky with boolean/string conversions. The comparison:

needs.detect-changes.outputs.has_full_ci_label != 'true'

Will work if the output is the string 'true', but actions/github-script@v7 returns actual JavaScript booleans. Verify this works as expected.


🎯 Recommendations

High Priority (Blocking)

  1. Fix the output reference bug - change has_label to result in all 5 workflows
  2. Test the actual behavior - verify the label checking works end-to-end
  3. Verify boolean handling - ensure the comparison logic works with GitHub Actions' type coercion

Medium Priority

  1. Refactor to reduce duplication - extract to reusable workflow or composite action
  2. Document edge cases - what happens if label is manually removed? What if workflow fails midway?
  3. Complete the test plan - check off the boxes in the PR description

Low Priority

  1. Add label description - create the label with a description explaining its purpose
  2. Consider auto-removal - should the label auto-remove on merge? On close?

🔧 Suggested Fix for Output Bug

Option 1: Fix the output reference (simpler)

In all 5 workflow files, change the output reference:

- has_full_ci_label: ${{ steps.check-label.outputs.has_label }}
+ has_full_ci_label: ${{ steps.check-label.outputs.result }}

Option 2: Explicitly set the output (more robust)

Modify the check-label step to use core.setOutput:

- name: Check for full-ci label
  id: check-label
  uses: actions/github-script@v7
  with:
    script: |
      if (!context.payload.pull_request) {
        core.setOutput('has_label', 'false');
        return false;
      }
      
      const { data: labels } = await github.rest.issues.listLabelsOnIssue({
        owner: context.repo.owner,
        repo: context.repo.repo,
        issue_number: context.payload.pull_request.number
      });
      
      const hasLabel = labels.some(label => label.name === 'full-ci');
      core.setOutput('has_label', String(hasLabel));  // Explicit string output
      console.log(`full-ci label present: ${hasLabel}`);
      return hasLabel;

I recommend Option 2 as it makes the output contract explicit and handles string conversion properly.


📊 Performance & Security

  • Performance: ✅ Minimal impact - one additional API call per workflow run
  • Security: ✅ Good - permission checks prevent abuse, though verify issues: write works with issue_comment trigger
  • Reliability: ⚠️ Blocked by output bug, otherwise solid approach

💡 Future Enhancements

Consider these for follow-up PRs:

  1. Add workflow that auto-removes label when PR is merged/closed
  2. Add label color/description when first created
  3. Create reusable workflow to reduce duplication
  4. Add metrics/logging to track label usage

Summary

This is a well-thought-out solution to a real workflow pain point. The implementation is mostly solid but has one critical bug that will prevent it from working. Once fixed and tested, this will be a valuable addition to the CI workflow.

Verdict: ⚠️ Needs changes before merge (fix output bug + testing)


Review generated by Claude Code

justin808 and others added 2 commits November 12, 2025 15:25
Replace template literals with array.join() to avoid YAML multiline
key parsing issues. This fixes the knip CI failure.

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

Co-Authored-By: Claude <noreply@anthropic.com>
The check-label step returns `result` output, but workflows were
incorrectly referencing it as `has_label`, causing the full-ci
label feature to be completely broken.

Fixed in all 5 workflows:
- .github/workflows/main.yml
- .github/workflows/examples.yml
- .github/workflows/pro-integration-tests.yml
- .github/workflows/pro-lint.yml
- .github/workflows/pro-package-tests.yml

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

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

claude bot commented Nov 13, 2025

Code Review

This PR implements a persistent full CI mode using GitHub labels, solving the problem where CI tests would be interrupted when new commits are pushed.

Positive Aspects

  1. Excellent Problem/Solution Fit: The label-based approach elegantly solves the persistence problem
  2. Consistent Implementation: Label check logic is duplicated consistently across all 5 workflow files
  3. Robust Error Handling: The stop-run-skipped-ci.yml workflow has excellent error handling
  4. Security: Permission checks properly restrict commands to users with write access
  5. User Experience: Clear feedback messages and emoji reactions

Issues & Recommendations

1. Missing issues: write Permission (Medium Priority)

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

The workflow adds a label but is missing the issues: write permission. While GitHub may sometimes allow label operations with just pull-requests: write, explicitly declaring issues: write is the documented requirement and prevents potential permission errors.

2. Output Variable Mismatch (Medium Priority)

Location: All detect-changes jobs in updated workflows

The output variable reference is incorrect in all 5 workflow files. Currently uses steps.check-label.outputs.has_label but should be steps.check-label.outputs.result. The GitHub script action uses the implicit outputs.result for the return value, not outputs.has_label. This may cause the label check to not work correctly.

3. Test Plan Not Complete

All test plan items in the PR description are unchecked. These should be completed before merging.

Recommendations Summary

Must Fix Before Merge:

  1. Add issues: write permission to run-skipped-ci.yml
  2. Fix the output variable reference from has_label to result in all 5 workflows
  3. Complete the test plan checklist

Nice to Have:

  1. Add comments explaining intentional code duplication

Overall Assessment

Status: Needs fixes before merge

This is a well-designed solution to a real problem. The implementation is clean and user-friendly. However, the output variable mismatch needs to be fixed as it may cause the label check to fail. After addressing these issues and completing testing, this will be a great addition to the project.

@claude
Copy link

claude bot commented Nov 13, 2025

Code Review: Make /run-skipped-ci persistent using full-ci label

Overview

This PR implements a smart solution to a real workflow problem - making full CI runs persistent across commits. The approach using a GitHub label is elegant and follows GitHub Actions best practices.

✅ Strengths

1. Clean Architecture

  • Well-structured separation of concerns across workflows
  • Consistent pattern applied to all 5 workflows (main, examples, pro-*)
  • DRY principle: label-checking logic is identical across workflows

2. User Experience

  • Clear command naming: /run-skipped-ci and /stop-run-skipped-ci are intuitive
  • Informative feedback messages with status indicators (✅, ⚠️, ❌)
  • Helpful documentation in PR description

3. Security

  • Proper permission checks using getCollaboratorPermissionLevel
  • Restricts to 'admin' and 'write' permissions
  • Graceful failure with user-friendly error messages

4. Robustness

  • Error handling in label operations (404 for missing labels)
  • Proper null checks (if (!context.payload.pull_request))
  • Fallback to false for non-PR contexts

🔍 Issues & Suggestions

High Priority

1. Missing issues: write permission in run-skipped-ci.yml

The workflow adds a label but doesn't have the issues: write permission:

# .github/workflows/run-skipped-ci.yml:22-25
permissions:
  contents: read
  pull-requests: write
  actions: write

Add issues: write:

permissions:
  contents: read
  pull-requests: write
  actions: write
  issues: write  # Required for adding labels

Reference: stop-run-skipped-ci.yml:18-20 already has this correctly.

2. Inconsistent comment reactions

  • run-skipped-ci.yml:67 uses reactions: 'rocket'
  • stop-run-skipped-ci.yml:61 uses reactions: 'eyes'

Consider using consistent reactions (both 'rocket' or both 'eyes') for better UX.

Medium Priority

3. Label check code duplication

The exact same 20-line label-checking script appears in 5 different workflow files. Consider:

  • Creating a reusable composite action
  • Or using a GitHub Actions reusable workflow
  • This would reduce maintenance burden and prevent drift

4. Complex exclude logic may be fragile

The exclude conditions in matrix jobs are quite complex. This is hard to read and test. Consider:

  • Adding comments explaining the logic
  • Or refactoring to use separate job conditionals
  • At minimum, add a comment showing the truth table

5. No cleanup on PR close

When a PR is closed/merged, the full-ci label persists (though harmless). Consider adding a workflow to auto-remove the label on PR close for cleanliness.

Low Priority

6. Message formatting inconsistencies

In run-skipped-ci.yml changes:

  • Line 231: Uses template literals with indentation
  • Line 219: String has mixed indentation

The message strings have inconsistent indentation. While functional, consistent formatting improves maintainability.

7. Documentation mentions non-existent files

The PR description says "All workflows updated" but doesn't mention that stop-run-skipped-ci.yml is a new file. Update the description to clarify:

  • 5 existing workflows modified
  • 1 new workflow added

🎯 Testing Recommendations

Beyond the test plan in the PR description, also verify:

  1. Permission edge cases:

    • User with 'read' permission tries commands
    • User with 'triage' permission tries commands
  2. Label already exists:

    • Run /run-skipped-ci when label is already present
    • Verify it doesn't error
  3. Concurrent workflows:

    • Run /run-skipped-ci twice quickly
    • Check concurrency group prevents issues
  4. Non-PR contexts:

    • Ensure label check doesn't break workflow_dispatch on master

📊 Code Quality Metrics

  • Files changed: 6 workflows + 263 additions
  • Code duplication: ~100 lines (5× 20-line label check)
  • Complexity: Medium (complex matrix exclude logic)
  • Test coverage: Manual testing required (GitHub Actions)

🔒 Security Assessment

No security concerns identified

  • Proper authentication checks
  • No secret exposure
  • Label manipulation is low-risk
  • API calls use proper GitHub token scoping

💡 Future Enhancements

Consider in follow-up PRs:

  1. Create a composite action for label checking
  2. Add /toggle-full-ci command to combine both commands
  3. Support label-based overrides for specific test suites
  4. Add metrics/logging to track usage patterns

Verdict: ✅ Approve with minor fixes

This is a well-designed solution that solves a real problem. The issues identified are mostly minor polish items. The critical fix needed is adding issues: write permission to run-skipped-ci.yml.

Once that's addressed, this PR will significantly improve the developer experience when debugging CI failures.


Required before merge:

  • Add issues: write permission to run-skipped-ci.yml

Nice to have:

  • Consistent reaction emojis
  • Comments explaining matrix exclude logic
  • Refactor duplicated label-check code

Great work on this feature! 🚀

This commit enhances the /run-skipped-ci feature based on code review feedback:

**Critical Fixes:**
- Fix GitHub Actions output encoding to use explicit string values
- Add result-encoding: string to all label check steps
- Return 'true'/'false' strings instead of booleans for consistent shell comparison
- Fixes potential silent failures in label detection across 6 workflow files

**New Features:**
- Add automatic full-ci label cleanup when PRs are merged
- Add welcome message to new PRs explaining CI control commands
- Comprehensive documentation in CONTRIBUTING.md

**Files Changed:**
- .github/workflows/main.yml - Fixed output encoding
- .github/workflows/examples.yml - Fixed output encoding
- .github/workflows/pro-*.yml (3 files) - Fixed output encoding
- .github/workflows/cleanup-full-ci-label.yml - New: Auto-remove label on merge
- .github/workflows/pr-welcome-message.yml - New: Welcome message for PRs
- CONTRIBUTING.md - Added CI Control Commands documentation

The full-ci label now persists correctly across commits and provides clear
user guidance through automated messages.

🤖 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)
CONTRIBUTING.md (1)

432-432: Add language identifiers to fenced code blocks.

Fenced code blocks at lines 432 and 454 should specify the code language for better rendering and syntax highlighting.

Apply this diff to add language specifiers:

-        /run-skipped-ci
+        ```bash
+        /run-skipped-ci
+        ```

and

-        /stop-run-skipped-ci
+        ```bash
+        /stop-run-skipped-ci
+        ```

Also applies to: 454-454

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6fc849c and aac7121.

📒 Files selected for processing (9)
  • .github/workflows/cleanup-full-ci-label.yml (1 hunks)
  • .github/workflows/examples.yml (2 hunks)
  • .github/workflows/main.yml (3 hunks)
  • .github/workflows/pr-welcome-message.yml (1 hunks)
  • .github/workflows/pro-integration-tests.yml (1 hunks)
  • .github/workflows/pro-lint.yml (1 hunks)
  • .github/workflows/pro-package-tests.yml (1 hunks)
  • .github/workflows/stop-run-skipped-ci.yml (1 hunks)
  • CONTRIBUTING.md (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • .github/workflows/pro-integration-tests.yml
  • .github/workflows/pro-lint.yml
🧰 Additional context used
🪛 markdownlint-cli2 (0.18.1)
CONTRIBUTING.md

432-432: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


454-454: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

⏰ 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: markdown-link-check
🔇 Additional comments (10)
.github/workflows/cleanup-full-ci-label.yml (1)

1-35: Clean cleanup workflow implementation.

The trigger condition, permissions, and error handling are appropriate for label cleanup on merge. The 404 gracefully handles cases where the label isn't present, and non-failure on other errors prevents blocking PR merges for cleanup issues.

CONTRIBUTING.md (2)

424-472: Verify no duplication of CI Control Commands section.

The AI summary indicates this documentation block may be duplicated. Please confirm whether the "CI Control Commands" section appears only once in the file to avoid user confusion.


478-478: Example path updated appropriately.

The Install Generator gem path example now uses a concrete relative path, which is clearer than the placeholder.

.github/workflows/pr-welcome-message.yml (1)

1-45: Welcome message workflow is well-structured.

The message clearly explains CI behavior, documents the new commands, and sets proper user expectations. The reference to automatic cleanup aligns with the cleanup-full-ci-label.yml workflow.

.github/workflows/main.yml (2)

39-58: Label detection step is consistent across workflows.

The check-label step correctly guards against non-PR contexts, fetches labels, and returns a string boolean. This implementation is consistent with the same pattern in pro-package-tests.yml and examples.yml.


94-97: Matrix exclusion logic is complex but functional.

The multi-condition check for excluding minimum dependency variants is correct, though the ternary expression is quite lengthy. This pattern appears consistently across multiple jobs and workflows, which aids maintainability through consistency.

.github/workflows/stop-run-skipped-ci.yml (2)

22-56: Access control implementation is appropriate.

The permission check verifies the user has 'admin' or 'write' access before allowing label removal. The exit early pattern (lines 52-56) prevents subsequent steps from running, which is the correct approach.


64-125: ✅ YAML syntax verified and code changes approved.

The YAML validation confirms that the workflow file syntax is correct. The error handling implementation properly distinguishes between 404 (label already removed) and other errors, with appropriate user-friendly messaging for each case.

.github/workflows/pro-package-tests.yml (1)

27-63: Consistent label-based CI control implementation.

The check-label step and detect-changes logic mirror the implementation in main.yml and examples.yml, maintaining consistency across workflows. The condition correctly activates full CI when either force_run is true or the full-ci label is present.

.github/workflows/examples.yml (1)

32-95: Label-based CI control consistently applied across generator tests.

The check-label step and matrix exclusion logic are consistent with main.yml and pro-package-tests.yml, ensuring uniform CI behavior. The minimum dependency exclusion correctly respects the full-ci label.

@claude
Copy link

claude bot commented Nov 13, 2025

Code Review - PR #2007: Make /run-skipped-ci persistent using full-ci label

Summary

This PR enhances the CI control system by making the /run-skipped-ci command persistent through a full-ci label. This is a well-designed solution to the problem of interrupted CI runs when new commits are pushed.


✅ Strengths

1. Excellent Architecture

  • Clean separation of concerns across workflows
  • DRY principle maintained with consistent label-checking logic
  • Proper permissions model (only write-access users can control CI)
  • Graceful error handling throughout

2. User Experience

  • Clear documentation in CONTRIBUTING.md
  • Helpful welcome message on new PRs
  • Informative feedback messages for all commands
  • Automatic cleanup on PR merge prevents label pollution

3. Robust Implementation

  • Proper permission checks before allowing commands
  • 404 error handling for missing labels
  • Logging for debugging
  • Non-failing cleanup workflow (won't break PR merge)

🔍 Detailed Analysis

Code Quality: Excellent

  • Consistent JavaScript/GitHub Actions style across all workflows
  • Proper use of actions/github-script@v7
  • Good use of early returns and guard clauses
  • Clear variable naming and comments

Best Practices: Well Applied

  • result-encoding: string correctly used for boolean checks
  • some() method appropriately used for label detection
  • Console logging for debugging
  • Proper error propagation where needed

Security: Good

  • Permission checks prevent unauthorized CI triggering
  • persist-credentials: false maintained in checkout actions
  • Proper scoping of permissions per job

🤔 Considerations & Suggestions

1. Code Duplication (Minor)

The label-checking logic is duplicated across 5 workflows. While this is acceptable for maintainability, consider:

Recommendation: Keep current approach unless duplication becomes a maintenance burden. The current approach is clearer and more maintainable for this scale.

2. Edge Case: Label Race Condition (Low Priority)

If a user runs /stop-run-skipped-ci immediately after /run-skipped-ci, but before workflows start, the workflows might still trigger with force_run: true.

Impact: Minimal - workflows will run once, label will be removed
Recommendation: Accept as edge case with minimal impact

3. Welcome Message Enhancement

The welcome message posts on every new PR, even for contributors familiar with the system.

Recommendation: Consider as future enhancement if welcome messages become noise for regular contributors


🧪 Test Coverage

Manual Testing Recommended:

  • ✅ Label appears after /run-skipped-ci
  • ✅ Label persists after new commits
  • ✅ Workflows detect label correctly
  • /stop-run-skipped-ci removes label
  • ✅ Label removed on PR merge
  • ✅ Permission checks work
  • ✅ Error handling for missing labels

Edge Cases to Test:

  • Multiple rapid command executions
  • Non-collaborator attempting commands
  • Label manually added/removed via UI

🚀 Performance Considerations

Impact: Minimal

  • Label check adds ~1-2 seconds per workflow
  • API calls are cached by GitHub
  • No impact on actual test execution time

📝 Documentation

Excellent documentation:

  • Clear CONTRIBUTING.md updates
  • Helpful inline comments in workflows
  • Good use of emojis and formatting
  • Examples of when to use each command

Minor suggestion:
Consider adding troubleshooting section for common issues


🔐 Security Review

No security concerns identified:

  • Proper permission checks prevent abuse
  • No injection vulnerabilities
  • No sensitive data exposure
  • Appropriate use of GitHub tokens

🎯 Recommendations

Priority 1 (Before Merge):

  • None - Code is ready to merge as-is

Priority 2 (Nice to Have):

  1. Consider limiting welcome message to first-time/external contributors
  2. Add troubleshooting section to docs
  3. Test edge cases listed above

Priority 3 (Future Enhancements):

  1. Consider metrics/analytics on full-ci label usage
  2. Potentially add time-based auto-removal (e.g., after 7 days)

✅ Final Verdict

LGTM - This is a well-designed, well-implemented solution that solves a real problem.

Code Quality: ⭐⭐⭐⭐⭐ (5/5)
Documentation: ⭐⭐⭐⭐⭐ (5/5)
Testing Approach: ⭐⭐⭐⭐☆ (4/5)
User Experience: ⭐⭐⭐⭐⭐ (5/5)

The PR is ready to merge. All suggestions are optional enhancements, not blockers.


📚 Additional Notes

Workflow Logic Correctness:
The OR logic ensures both force_run input and full-ci label mechanisms work independently - correct implementation.

Matrix Exclusion Logic:
The updated exclusion patterns correctly incorporate the label check. Minimum dependency tests run when:

  • On master branch, OR
  • Manual workflow dispatch with force_run, OR
  • PR has full-ci label

Great work! 🎉

- Remove cleanup workflow: Preserve full-ci label on merged PRs as historical record
- Reduce code duplication: Create reusable composite action for label checking
- Fix label addition timing: Add label within main workflow step with better error handling
- Improve UX: Add permissions note to welcome message and clarify label persistence
- Better error handling: Use core.setFailed() instead of throw in stop workflow

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

Co-Authored-By: Claude <noreply@anthropic.com>
@justin808 justin808 merged commit 7f38f00 into master Nov 13, 2025
25 checks passed
@justin808 justin808 deleted the justin808/persist-full-ci-label branch November 13, 2025 01:52
@claude
Copy link

claude bot commented Nov 13, 2025

Code Review - PR #2007: Make /run-skipped-ci persistent using full-ci label

Thank you for this well-structured PR! The implementation of persistent full CI mode using labels is a solid solution to the problem. Here's my detailed feedback:


Strengths

Architecture & Design

  • Excellent separation of concerns: The reusable check-full-ci-label action is a clean abstraction that avoids code duplication across workflows
  • Consistent integration: All workflows follow the same pattern for checking the label, making maintenance easier
  • Good user experience: Clear commands (/run-skipped-ci, /stop-run-skipped-ci) with helpful feedback messages

Implementation Quality

  • Proper error handling: The stop-run-skipped-ci workflow handles 404 errors gracefully and provides user feedback
  • Security: Permission checks ensure only users with write access can control CI behavior
  • User feedback: Welcome message on new PRs educates users about available commands

🔍 Issues & Concerns

1. CRITICAL: Missing Label Cleanup on Merge ⚠️

Issue: The PR description states "The full-ci label is preserved on merged PRs as a historical record," but there's no workflow to actually clean up the label.

Why this matters:

  • Labels on closed/merged PRs serve no functional purpose
  • Can cause confusion if PRs are reopened
  • Clutters the label space

Recommendation: Add a workflow that removes the full-ci label when PRs are closed or merged:

# .github/workflows/cleanup-full-ci-label.yml
name: Cleanup Full CI Label

on:
  pull_request:
    types: [closed]

jobs:
  cleanup:
    runs-on: ubuntu-22.04
    permissions:
      pull-requests: write
      issues: write
    steps:
      - name: Remove full-ci label
        uses: actions/github-script@v7
        with:
          script: |
            try {
              await github.rest.issues.removeLabel({
                owner: context.repo.owner,
                repo: context.repo.repo,
                issue_number: context.issue.number,
                name: 'full-ci'
              });
              console.log('✅ Removed full-ci label from closed PR');
            } catch (error) {
              if (error.status !== 404) {
                console.error('Error removing label:', error);
              }
            }

Alternative: If you truly want to keep it as a historical record, update the documentation to explain why this design decision was made.


2. Minor: Missing core Import in stop-run-skipped-ci.yml

Location: .github/workflows/stop-run-skipped-ci.yml:124

Issue: The code calls core.setFailed() but doesn't import @actions/core.

Current code:

core.setFailed(`Failed to remove label: ${error.message}`);

Fix: In actions/github-script, core is available as require('@actions/core'). Update to:

const core = require('@actions/core');
core.setFailed(`Failed to remove label: ${error.message}`);

Or simpler: Just use throw new Error() which github-script handles automatically:

throw new Error(`Failed to remove label: ${error.message}`);

3. Code Quality: Inconsistent Label Adding Logic

Location: .github/workflows/run-skipped-ci.yml:219-230

Issue: The comment says "Add full-ci label only if we actually triggered workflows or if checks are already running," but the code adds the label unconditionally (no conditional logic).

Current behavior: Label is always added, even if all workflows failed to trigger.

Questions:

  • Is this intentional?
  • Should the label only be added if verified.length > 0 || notApplicable.length > 0?

Recommendation: Either:

  1. Update the comment to match the actual behavior: "Add full-ci label to enable persistent full CI mode"
  2. Or add conditional logic:
if (verified.length > 0 || notApplicable.length > 0) {
  try {
    await github.rest.issues.addLabels({
      owner: context.repo.owner,
      repo: context.repo.repo,
      issue_number: context.issue.number,
      labels: ['full-ci']
    });
    labelAdded = true;
    console.log('✅ Added full-ci label to PR');
  } catch (error) {
    console.error('⚠️  Failed to add label:', error.message);
  }
}

4. Documentation: Missing CONTRIBUTING.md Update

Status: ✅ Already included in PR

The CONTRIBUTING.md changes are excellent and clearly explain the new commands. Well done!


🎯 Testing Recommendations

Since these are GitHub Actions workflows, manual testing is critical:

Test Scenarios:

  1. ✅ Run /run-skipped-ci and verify label is added
  2. ✅ Push a new commit and verify full CI runs (including minimum deps)
  3. ✅ Run /stop-run-skipped-ci and verify label is removed
  4. ✅ Push another commit and verify CI returns to change detection mode
  5. ⚠️ Test permission denied: Have a non-collaborator try running the commands
  6. ⚠️ Test error handling: Try /stop-run-skipped-ci when label isn't present
  7. ⚠️ Test merge cleanup: Merge a PR with the label and verify cleanup (after adding the workflow)

🔒 Security Analysis

No security concerns identified:

  • Permission checks properly restrict access to write-level collaborators
  • No credential exposure or secret leakage
  • Actions use pinned versions (@v7, @v4)
  • No arbitrary code execution vulnerabilities

Performance Considerations

Efficient implementation:

  • Label check is fast (single API call)
  • Reusable action avoids redundant API calls
  • No unnecessary workflow runs

Minor optimization: The check-full-ci-label action could cache results if called multiple times in the same workflow, but current usage doesn't require this.


📋 Summary & Recommendations

Priority Issues:

  1. 🔴 HIGH: Clarify label cleanup strategy (add workflow or update docs)
  2. 🟡 MEDIUM: Fix core.setFailed() usage in stop-run-skipped-ci.yml
  3. 🟡 MEDIUM: Clarify label-adding logic in run-skipped-ci.yml

Overall Assessment: This is a well-implemented feature that solves a real problem. The code quality is high, and the user experience is excellent. Addressing the label cleanup strategy would make this production-ready.


Positive Highlights

  • Clean, maintainable code following GitHub Actions best practices
  • Excellent user documentation in CONTRIBUTING.md
  • Good error handling and user feedback
  • Consistent implementation across all workflows
  • Security-conscious design with proper permission checks

Great work! 🚀

@claude
Copy link

claude bot commented Nov 13, 2025

Code Review

Overall Assessment

This is a well-designed improvement to the CI workflow that solves a real problem. The implementation is solid, but I've identified several areas for improvement.

✅ Strengths

  1. Clear Problem Statement: The PR effectively solves the issue where /run-skipped-ci would stop working after new commits.

  2. Consistent Implementation: The full-ci label check is consistently applied across all 5 workflow files.

  3. Good UX: Welcome message educates users, clear feedback with status comments, and visual reactions to commands.

  4. Proper Permissions: Both workflows correctly check for write access before allowing label manipulation.

🐛 Potential Issues

1. Label Persistence on Merge (Medium Priority)

Issue: The PR description states the label should persist as a "historical record" after merge, but there's no workflow to clean it up. This could cause issues if PRs are reopened or labels accumulate.

Recommendation: Add a cleanup workflow that removes the full-ci label when PRs are merged. I can provide the code if needed.

2. Error Handling Inconsistency (Low Priority)

File: .github/workflows/stop-run-skipped-ci.yml:124

The workflow uses core.setFailed() but doesn't import @actions/core. This will cause a runtime error. Replace with throw new Error() or let the error propagate naturally.

3. Race Condition in Label Addition (Low Priority)

File: .github/workflows/run-skipped-ci.yml:220-231

If /run-skipped-ci is triggered multiple times rapidly, there could be race conditions when adding the label. This is likely not a practical issue since GitHub API label operations are idempotent.

📝 Code Quality Suggestions

  1. DRY Violation: All 5 workflow files have nearly identical detect-changes logic. Consider extracting to a reusable composite action for future refactoring.

  2. Documentation Clarity: The note about label persistence in CONTRIBUTING.md seems contradictory. Clarify whether the label stays after merge or is removed.

🔒 Security Considerations

Good: Both workflows properly check for write access
Good: Label manipulation is scoped to the PR only
Good: No sensitive data exposure

🧪 Test Coverage

Missing: The PR mentions a test plan but doesn't include automated tests. Consider manual verification checklist at minimum.

📊 Performance Considerations

Good: The label check is efficient (single API call)
⚠️ Watch: On PRs with the label, ALL matrix configurations run. This is intentional but could be expensive for frequently-updated PRs.

🎯 Recommendations Priority

High Priority (Fix before merge):

  1. Fix core.setFailed() error in stop-run-skipped-ci.yml:124
  2. Clarify documentation about label persistence behavior

Medium Priority (Consider for this PR):

  1. Add workflow to clean up full-ci label on PR merge
  2. Update CONTRIBUTING.md to explain the label lifecycle

Low Priority (Future improvements):

  1. Extract common change detection logic to reusable composite action
  2. Add integration tests for the label workflows

✨ Final Verdict

Approve with minor fixes required. This PR significantly improves the developer experience by making full CI mode persistent. The implementation is sound, but needs the small fixes noted above before merging.

Great work on the comprehensive documentation updates and consistent implementation across all workflows! 🎉


Review generated by Claude Code

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants