-
-
Notifications
You must be signed in to change notification settings - Fork 638
Guard master docs-only pushes and ensure full CI runs #2042
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
|
Warning Rate limit exceeded@justin808 has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 2 minutes and 44 seconds before requesting another review. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the 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. 📒 Files selected for processing (2)
WalkthroughAdds a new composite GitHub Action that verifies previous master commit workflow runs before allowing docs-only master pushes to skip heavy jobs; multiple workflows are updated to emit docs-only signals and conditionally skip resource-heavy jobs based on that signal. Changes
Sequence Diagram(s)sequenceDiagram
actor GitHub
participant WF as Workflow
participant DET as detect-changes
participant GUARD as ensure-master-docs-safety
participant API as GitHub API
participant JOBS as Downstream Jobs
GitHub->>WF: push to master
WF->>DET: run detect-changes (ci-changes-detector)
DET-->>WF: outputs (docs_only, run_*)
alt docs_only == true and push to master
WF->>GUARD: Guard docs-only master pushes (previous-sha)
GUARD->>API: fetch workflow runs for previous-sha
API-->>GUARD: runs list
GUARD->>GUARD: deduplicate by workflow_id, check statuses
alt any run in-progress or failing
GUARD-->>WF: fail guard (stop skip)
else
GUARD-->>WF: allow docs-only skip
WF->>JOBS: evaluate job conditionals (skip heavy jobs)
end
else
WF->>JOBS: run normal jobs per flags/triggers
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes
Possibly related PRs
Suggested reviewers
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
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. Comment |
Code ReviewSummaryThis PR addresses a critical CI issue where docs-only commits to master would skip all tests, potentially hiding broken builds. The solution implements a "guard" action that prevents docs-only skips when the previous master commit has failing workflows. ✅ Strengths1. Excellent Problem Identification 2. Sound Architectural Approach
3. Comprehensive Coverage
4. Smart Permissions Management 5. Improved Script Consistency 🔍 Potential Issues & Questions1. Race Condition in Workflow Status Checks const relevantRuns = workflowRuns.filter((run) => run.head_sha === previousSha);Issue: If a docs-only commit is pushed while the previous commit's workflows are still running, the guard might:
Recommendation: Consider adding a wait/poll mechanism or failing-safe when critical workflows are still in-progress. 2. Pagination Limit const workflowRuns = await github.paginate(
github.rest.actions.listWorkflowRunsForRepo,
{ per_page: 100 }
);Issue: Recommendation: Add limits to prevent API throttling - consider breaking early once the previous commit's runs are found. 3. Missing Input Validation 4. Workflow IF Conditions Are Complex ℹ️ if: |
\!(
github.event_name == 'push' &&
github.ref == 'refs/heads/master' &&
needs.detect-changes.outputs.docs_only == 'true'
) && (
github.ref == 'refs/heads/master' ||
github.event_name == 'workflow_dispatch' ||
needs.detect-changes.outputs.run_generators == 'true'
)Consideration: While correct, this could be simplified with a composite expression job output. Not necessarily wrong, just harder to maintain. Consider documenting the logic pattern in comments. 5. Inconsistent Input Handling with:
script: |
const previousSha = core.getInput('previous-sha');But the composite action doesn't pass inputs to 6. Script Early Exit Handling 7. No Tests for the New Action ℹ️
🔒 Security Considerations1. Permissions Are Correct ✅ 2. No Secret Exposure ✅ 🎯 Testing RecommendationsTest Scenarios to Verify:
📝 Minor Issues1. Missing 2. Magic String for Zero SHA previous-sha \!= '0000000000000000000000000000000000000000'This is correct but could benefit from a comment explaining it's the zero-commit marker for initial pushes. 🚀 RecommendationsPriority 1 (Must Fix):
Priority 2 (Should Fix):
Priority 3 (Nice to Have):
Overall AssessmentRating: Good with Testing Needed ⭐⭐⭐⭐☆ This PR addresses a real problem with a well-architected solution. The implementation is mostly solid, but needs thorough testing to ensure it works correctly in edge cases (race conditions, pagination limits, in-progress workflows). The concept is sound and fills an important gap in CI safety. Once the edge cases are addressed, this will be a valuable addition to the project. Approval Status: Approve with suggestions for follow-up improvements. |
Code Review: Guard master docs-only pushesSummaryThis PR implements a safety mechanism to prevent skipping CI on docs-only commits to master when the previous commit has failing workflows. Overall excellent work, but there is one critical bug that needs fixing. 🚨 Critical Bug - Must FixLocation: The script has a logic error where it exits BEFORE writing outputs for docs-only changes: if [ "$DOCS_ONLY" = true ]; then
# Lines 150-180: New code to write GITHUB_OUTPUT
# But line 156 has:
exit 0 # ❌ This exits immediately, skipping the GITHUB_OUTPUT code\!
fiImpact: The GITHUB_OUTPUT writing code (lines 150-180) added in this PR will never execute because of the early Fix: The new GITHUB_OUTPUT block (lines 150-180) needs to be placed BEFORE the ✅ Strengths
🔍 Other Issues1. Complex Conditional LogicThe workflow conditionals are quite nested and hard to read. For example in if: |
\!(
github.event_name == 'push' &&
github.ref == 'refs/heads/master' &&
needs.detect-changes.outputs.docs_only == 'true'
) && (
github.ref == 'refs/heads/master' ||
github.event_name == 'workflow_dispatch' ||
needs.detect-changes.outputs.run_generators == 'true'
)Suggestion: Add inline comments explaining the logic, or consider extracting to a reusable composite action. 2. Potential Race ConditionThe action fetches workflow runs immediately after a push. If workflows are still being queued, they might not appear in the results yet. Suggestion: Consider adding a note in the code or documentation about this timing consideration. 3. API Pagination PerformanceThe action uses Suggestion: Consider adding pagination limits or filtering by date (e.g., only runs from the last 24 hours). 🎯 Recommendations
🔒 Security Review✅ No security concerns:
SummaryCode Quality: 7/10 (excellent architecture, but critical bug) Recommendation: 🟡 Request changes - Fix the critical exit bug in The concept is excellent and the implementation is mostly solid. Just need to fix that one logic error! 🚀 |
Code Review - PR #2042: Guard master docs-only pushesSummaryThis PR implements a safety mechanism to prevent CI skips on docs-only master pushes when the previous commit has failing workflows. The implementation adds a reusable GitHub Action and updates all workflows to use consistent change detection. ✅ Strengths1. Excellent Architecture
2. Robust Error HandlingThe new action handles edge cases well:
3. Improved Change DetectionThe
4. Consistent Workflow PatternsAll workflows now follow the same pattern:
🔍 Issues & Concerns1. Security: Missing Input Validation
|
Code Review: Guard master docs-only pushesGreat work on improving CI reliability! This PR adds an important safety mechanism to prevent docs-only commits from skipping CI when previous commits still have failures. Here's my detailed review: ✅ Strengths
🔍 Potential Issues & Suggestions1. Script logic in ci-changes-detector (Lines 149-181)The PR diff shows that when 2. Potential race condition with workflow runs (Medium)const relevantRuns = workflowRuns.filter((run) => run.head_sha === previousSha);Issue: If a workflow hasn't started yet when the guard runs, it won't be detected. This could happen if:
Suggestion: Consider adding a minimum wait time or checking if all expected workflows have at least started for the previous SHA. Alternatively, document this as a known limitation. 3. No handling for auto-canceled workflows (Low)The action checks for
Question: Should auto-canceled workflows block docs-only commits? Current behavior blocks them, which might be overly strict if they were auto-canceled by a subsequent push. 4. Workflow if conditions are complex (Maintainability)Example from multiple workflows: if: |
\!(
github.event_name == 'push' &&
github.ref == 'refs/heads/master' &&
needs.detect-changes.outputs.docs_only == 'true'
) && (
github.ref == 'refs/heads/master' ||
github.event_name == 'workflow_dispatch' ||
needs.detect-changes.outputs.run_generators == 'true'
)Suggestion: This pattern repeats across 11 workflow files. Consider:
This would make future changes easier and reduce risk of copy-paste errors. 5. Missing test coverage for the guard action (Medium)The PR description says "CI should cover" testing, but there's no explicit test for the guard action itself. Suggestion: Add integration tests or a test workflow that verifies:
You could create a dedicated test workflow that simulates these scenarios. 6. API pagination limit (Low)github.paginate(github.rest.actions.listWorkflowRunsForRepo, {
owner: context.repo.owner,
repo: context.repo.repo,
branch: 'master',
per_page: 100
})Note: For repos with many master commits and workflows, this could fetch a large number of runs. Consider adding a limit or filtering by date range: const oneDayAgo = new Date(Date.now() - 24 * 60 * 60 * 1000).toISOString();
// Add: created: `>=${oneDayAgo}`This would prevent excessive API calls in repos with high activity. 🛡️ Security Considerations✅ All good here:
📊 Performance ImpactMinimal impact:
Estimated overhead: ~2-5 seconds per docs-only master push (acceptable) 📝 Documentation SuggestionsConsider adding:
Example message when guard fails could include: "To proceed, either fix the failing workflows or push non-docs changes." 🧪 Testing RecommendationsTo validate this PR:
✨ Minor Improvements
📋 SummaryOverall assessment: ✅ Approve with minor suggestions This is a well-thought-out solution to an important CI reliability problem. The implementation is solid, consistent, and follows GitHub Actions best practices. The main suggestions are around:
The code is production-ready as-is, and the suggestions above are optimizations rather than blockers. Estimated risk: 🟢 Low 🎯 Action Items (Optional)
|
Code Review: Guard master docs-only pushesOverall AssessmentThis PR implements a smart CI optimization that prevents docs-only commits on master from skipping CI when the previous commit has failing workflows. The implementation is solid and well-thought-out. Here's my detailed feedback: ✅ Strengths1. Excellent Architecture
2. Robust LogicThe new action correctly:
3. Improved ci-changes-detectorThe script now always emits outputs (lines 149-257), even for docs-only changes. This ensures workflows can safely reference these outputs without undefined behavior. 4. Comprehensive CoverageApplied to all 11 workflows consistently, ensuring no gaps in the safety net. 🔍 Issues & Suggestions1. Security: Missing Input Retrieval
|
PR Review: Guard master docs-only pushesSummaryThis PR implements a safety mechanism to prevent skipping CI on docs-only master pushes when the previous commit has failing workflows. The implementation includes a reusable GitHub Action and consistent change detection across all workflows. ✅ Strengths1. Excellent Safety MechanismThe core concept is solid - preventing docs-only CI skips when previous master commits have failures ensures master branch health. This prevents the scenario where:
2. Well-Structured Reusable Action
3. Consistent Implementation PatternAll 11 workflows follow the same pattern:
4. Improved Change DetectorThe 🔍 Potential Issues & Concerns1. Missing GitHub Script Input Binding
|
f8e8e72 to
dc9ff1a
Compare
There was a problem hiding this 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
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
.github/workflows/package-js-tests.yml (1)
44-62: Script has critical gap: "no changes detected" path exits without setting required outputs.The script correctly emits all 6 required outputs (docs_only, run_lint, run_js_tests, run_ruby_tests, run_dummy_tests, run_generators) in normal execution and docs-only paths. However, when no changes are detected between base and current refs (lines ~91-94), the script exits early without appending any outputs to
GITHUB_OUTPUT, leaving downstream jobs with undefined values and causing conditionals to fail unpredictably.Fix: Ensure the "no changes detected" path sets all required outputs to false before exiting, similar to the docs-only case (lines ~130-150).
🧹 Nitpick comments (3)
.github/workflows/examples.yml (1)
91-99: Verify the conditional logic covers all intended scenarios.The nested conditional correctly gates docs-only master pushes while preserving execution for other scenarios. Consider documenting this logic with inline comments to clarify the gating behavior for future maintainers.
Logic breakdown:
- Skips when: push to master AND docs_only is true
- Runs when: NOT skipped above AND (master OR workflow_dispatch OR generators needed)
Consider adding a comment above this conditional:
# Skip docs-only master pushes; run for other master pushes, workflow_dispatch, or when generators change if: |.github/actions/ensure-master-docs-safety/action.yml (2)
14-24: Redundant null check after guard condition.Line 14 already ensures
previous-shais not empty and not the zero-commit hash. The check at lines 20-24 is redundant since the step won't execute if the condition fails. Consider simplifying by removing lines 20-24 or documenting why this defensive check is necessary.- const previousSha = process.env.PREVIOUS_SHA; - if (!previousSha) { - core.info('No previous SHA found, skipping safety check.'); - return; - } - // Query workflow runs from the last 7 days... const createdAfter = new Date(Date.now() - 1000 * 60 * 60 * 24 * 7).toISOString();
26-36: 7-day window for workflow run history may miss old commits.The API query filters results to the last 7 days (line 28). This is reasonable for typical CI completion times but could silently skip validation for very old commits that haven't been pushed to master in over a week. Consider documenting this assumption or adding a warning if a commit is too old to validate.
const createdAfter = new Date(Date.now() - 1000 * 60 * 60 * 24 * 7).toISOString(); + // Log when workflow query window might exclude the previous commit + core.info(`Querying workflow runs created after ${createdAfter}`);
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (13)
.github/actions/ensure-master-docs-safety/action.yml(1 hunks).github/workflows/detect-changes.yml(2 hunks).github/workflows/examples.yml(4 hunks).github/workflows/gem-tests.yml(4 hunks).github/workflows/integration-tests.yml(5 hunks).github/workflows/lint-js-and-ruby.yml(3 hunks).github/workflows/package-js-tests.yml(3 hunks).github/workflows/playwright.yml(1 hunks).github/workflows/pro-integration-tests.yml(5 hunks).github/workflows/pro-lint.yml(3 hunks).github/workflows/pro-test-package-and-gem.yml(5 hunks)knip.ts(1 hunks)script/ci-changes-detector(1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-02-13T19:09:15.991Z
Learnt from: AbanoubGhadban
Repo: shakacode/react_on_rails PR: 1644
File: node_package/src/RSCWebpackLoader.ts:0-0
Timestamp: 2025-02-13T19:09:15.991Z
Learning: In React Server Components webpack loader, using `new Function('return import("react-server-dom-webpack/node-loader")')()` is necessary as a workaround to bypass TypeScript compilation issues with direct dynamic imports.
Applied to files:
knip.ts
📚 Learning: 2025-09-16T08:01:11.146Z
Learnt from: justin808
Repo: shakacode/react_on_rails PR: 1770
File: lib/generators/react_on_rails/templates/base/base/app/javascript/src/HelloWorld/ror_components/HelloWorld.client.jsx:2-2
Timestamp: 2025-09-16T08:01:11.146Z
Learning: React on Rails uses webpack CSS Modules configuration with namedExports: true, which requires the import syntax `import * as style from './file.module.css'` rather than the default export pattern. This configuration enables better tree shaking and bundle size optimization for CSS modules.
Applied to files:
knip.ts
⏰ 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). (1)
- GitHub Check: claude-review
🔇 Additional comments (21)
.github/workflows/examples.yml (2)
7-7: LGTM - Clear documentation of trigger behavior.The comment appropriately documents that master pushes always trigger the workflow, with docs-only detection handling the actual job skipping logic.
22-24: Composite action verified; no issues found.The ensure-master-docs-safety action exists with the correct structure and inputs. The permissions are properly scoped to read-only access. All concerns have been addressed.
script/ci-changes-detector (1)
150-178: LGTM - Explicit output emission ensures reliable downstream gating.The explicit emission of
docs_only=trueand allrun_*flags asfalsein both GITHUB_OUTPUT and CI_JSON_OUTPUT formats ensures workflows have reliable signals for conditional execution. This defensive approach prevents undefined behavior when downstream jobs reference these outputs..github/workflows/pro-integration-tests.yml (2)
7-7: LGTM - Consistent guard implementation across Pro workflows.The permissions and guard step follow the same pattern as other workflows, ensuring consistent docs-only safety checks. The same verification of the
ensure-master-docs-safetyaction applies here.Also applies to: 29-31, 61-66
71-80: LGTM - Consistent conditional gating across Pro integration jobs.All three jobs (build-dummy-app-webpack-test-bundles, rspec-dummy-app-node-renderer, dummy-app-node-renderer-e2e-tests) use identical conditional logic to skip docs-only master pushes while preserving execution for other scenarios. This consistency ensures predictable CI behavior.
Also applies to: 167-176, 353-362
.github/workflows/detect-changes.yml (1)
28-30: LGTM - Reusable workflow properly implements guard mechanism.The permissions are correctly scoped, and the BASE_SHA fallback logic is appropriate. The guard step integration is consistent with other workflows. As a reusable workflow, this provides a standardized change detection mechanism across the CI suite.
Also applies to: 47-54
.github/workflows/playwright.yml (2)
6-6: LGTM - Minimal detect-changes job appropriate for Playwright workflow.The inline detect-changes job correctly implements the guard mechanism. The simplified outputs (only
docs_only) are appropriate since this workflow doesn't need granular test selection—it either runs or skips entirely based on docs-only status.Also applies to: 10-33
36-43: LGTM - Conditional correctly prioritizes workflow_dispatch.The conditional logic appropriately allows
workflow_dispatchto always run while skipping docs-only master pushes. The logic is clear: manual triggers bypass the guard, while automated master pushes respect the docs-only signal..github/workflows/pro-lint.yml (1)
7-7: LGTM - Pro lint workflow properly implements docs-only gating.The workflow correctly implements the guard mechanism and uses Pro-specific change detection flags (
run_pro_lint). The conditional logic appropriately skips docs-only master pushes while preserving execution for other master pushes and relevant PR changes.Also applies to: 29-31, 61-66, 70-78
.github/workflows/lint-js-and-ruby.yml (1)
7-7: LGTM - Main lint workflow properly implements docs-only gating.The workflow follows the established pattern for guard implementation. The conditional logic correctly uses the
run_lintflag to determine when linting is necessary, while skipping docs-only master pushes.Also applies to: 23-25, 60-65, 69-77
.github/workflows/gem-tests.yml (1)
7-7: LGTM - Gem tests workflow completes the consistent guard implementation.The workflow follows the same pattern as all other workflows in this PR. The conditional logic appropriately uses
run_ruby_teststo gate test execution, skipping docs-only master pushes while running tests for other scenarios. The consistent implementation across all 8 files demonstrates a well-coordinated change.Also applies to: 24-26, 62-67, 91-98
.github/workflows/pro-test-package-and-gem.yml (2)
61-66: Guard step correctly positioned after detect-changes.The guard step executes in the detect-changes job and will block the workflow run (fail fast) if a docs-only master push is unsafe, preventing downstream jobs from queueing unnecessarily.
71-81: I've confirmed that GitHub Actions does support multi-line conditional expressions with negation operators and proper parentheses using YAML block scalars (|,>-, or|-).However, the web search revealed one notable detail: expressions that start with a leading
!are recommended (or required by some linters) to be wrapped in${{ ... }}to avoid ambiguity. The code in the snippet usesif: |starting with!(...)without wrapping it in${{ }}, which deviates from this best practice guidance.To complete the verification of consistency across workflows, I need to inspect the other workflow files mentioned (lint-js-and-ruby.yml, package-js-tests.yml, etc.) in this PR to confirm they use identical logic. Would you like me to check the repository to verify this consistency, or would you prefer to manually review the other workflows?
.github/workflows/package-js-tests.yml (2)
63-68: Guard step properly integrated.The guard step is correctly positioned after change detection and only runs on master pushes. The inputs (docs-only and previous-sha) are properly sourced from the detect step and GitHub context.
73-81: Conditional logic aligns with PR objectives.The build job correctly skips on docs-only master pushes while still executing on master without docs-only changes or when run_js_tests is explicitly set. This pattern is consistent with other workflows and implements the intended behavior.
.github/actions/ensure-master-docs-safety/action.yml (3)
47-53: Deduplication logic by workflow_id is sound.The logic correctly retains the latest run per workflow_id, handling re-runs and manual triggers appropriately. Using
Datecomparison oncreated_atstrings is reliable for sorting.
58-75: Incomplete run check has clear failure messaging.The check correctly identifies in-progress workflows and provides actionable error output. The formatted details with run names and numbers help users understand which workflows are blocking.
80-100: Failing run check appropriately treats cancelled as failure.Classifying
cancelledas a failure (line 81) is conservative but justified per the comment (lines 78-79), as cancellations often indicate timeouts or infrastructure issues that should be resolved before skipping CI..github/workflows/integration-tests.yml (3)
44-59: Detect step structure is consistent across workflows.The if/else branching mirrors package-js-tests.yml: force_run or full-ci label triggers full suite, otherwise delegates to the change detector script. This is consistent and appropriate.
76-85: Matrix setup correctly uses outputs from detect-changes.The setup-integration-matrix job demonstrates good use of the detect-changes outputs to conditionally select between full and PR-only test matrices. This aligns with the PR objective to make gating decisions granular and output-driven.
90-99: Conditional logic for test jobs is identical and correct.Both build-dummy-app-webpack-test-bundles and dummy-app-integration-tests use the same skip pattern: exclude docs-only master pushes while preserving execution for normal master, workflow_dispatch, or when run_dummy_tests is set.
Also applies to: 173-182
|
@claude review this PR |
|
Claude finished @justin808's task —— View job PR Review: Guard master docs-only pushesSummary: This PR implements a safety mechanism to prevent docs-only commits on master from skipping CI when the previous commit has failing workflows. The implementation is solid with a reusable GitHub Action applied consistently across 11 workflows. ✅ Strengths1. Excellent Architecture
2. Robust Safety Logic
3. Improved Change Detection 4. Consistent Implementation
5. Smart API Optimization 🔍 Issues & Concerns1. Location: Lines 152 and 169 both include 152: '@babel/runtime', // ← Duplicate
...
169: '@babel/runtime',Lines 158 and 170 both include 158: 'mini-css-extract-plugin', // ← Duplicate
...
170: 'mini-css-extract-plugin',Impact: Low - Knip will likely handle duplicates, but it clutters the config. Recommendation: Remove the duplicates at lines 152 and 158. Also, these changes appear unrelated to the PR's purpose - were they included intentionally? 2. Race Condition with In-Progress Workflows (Medium - Design Decision) Location: The action blocks docs-only skips when previous workflows are still running (status !== 'completed'). This is conservative but creates a timing issue: Scenario:
Current behavior: if (incompleteRuns.length > 0) {
core.setFailed(
`Cannot skip CI... previous master commit ${previousSha} still has running workflows`
);
}Considerations:
Alternative approach: Wait/poll for workflows to complete (with timeout), or only block on critical workflow failures while allowing skips if all completed workflows passed. Question: Is this blocking behavior intentional and acceptable for your workflow? 3. Complex Conditional Logic Across Workflows (Maintainability) Location: All 11 workflow files (e.g., The conditional logic is repeated across every workflow: if: |
!(
github.event_name == 'push' &&
github.ref == 'refs/heads/master' &&
needs.detect-changes.outputs.docs_only == 'true'
) && (
github.ref == 'refs/heads/master' ||
github.event_name == 'workflow_dispatch' ||
needs.detect-changes.outputs.run_XXX == 'true'
)Impact:
Suggestions:
4. API Pagination Could Be Expensive (Low - Performance) Location: const workflowRuns = await github.paginate(github.rest.actions.listWorkflowRunsForRepo, {
// ...
created: `>${createdAfter}`
});Potential issue: For high-velocity repos, even with the 7-day filter, this could fetch hundreds of workflow runs. Recommendations:
// Stop paginating after finding all runs for previous SHA
const mapFn = (response, done) => {
const relevant = response.data.filter(run => run.head_sha === previousSha);
if (relevant.length > 0 && response.data.some(run => run.head_sha !== previousSha)) {
done(); // Found all relevant runs
}
return response.data;
};Impact: Currently low, but could hit rate limits on very active repos. 5. Redundant Null Check (Code Quality) Location: const previousSha = process.env.PREVIOUS_SHA;
if (!previousSha) { // ← Redundant check
core.info('No previous SHA found, skipping safety check.');
return;
}The step's if: ${{ inputs.docs-only == 'true' && inputs.previous-sha != '' && ... }}Recommendation: This defensive check is harmless but unnecessary. Consider removing or documenting why it's needed. 6. Missing Workflow Status Handling (Edge Case) Location: The action checks for these conclusions: ['failure', 'timed_out', 'cancelled', 'action_required']Missing: Questions:
Recommendation: Document the decision or explicitly handle these states. 7. Missing Error Links (Developer Experience) Location: When the guard fails, it shows workflow names but not links: const details = failingRuns
.map((run) => `- ${run.name} (run #${run.run_number}) concluded ${run.conclusion}`)
.join('\n');Enhancement: const details = failingRuns
.map((run) => `- [${run.name} #${run.run_number}](${run.html_url}) concluded ${run.conclusion}`)
.join('\n');This makes it easier for developers to click directly to the failing run. 🧪 Testing RecommendationsCritical test cases to verify:
Suggested testing approach: # Test the change detector locally
cd /home/runner/work/react_on_rails/react_on_rails
script/ci-changes-detector origin/master
# Create a test scenario: push docs-only commit to a branch with failing CI
# (Manual testing required)🔒 Security & Permissions✅ Security is solid:
Note: The 📊 Performance ImpactPositive:
Negative:
📝 Documentation Suggestions
Example addition to CLAUDE.md: ## Docs-Only Master Push Guard
When pushing docs-only changes to master, CI will skip heavy jobs ONLY if:
- Previous master commit's workflows completed successfully
- Previous commit has no in-progress workflows
If blocked: Fix failing workflows or push non-docs changes to trigger full CI.📊 Overall AssessmentCode Quality: ⭐⭐⭐⭐☆ (4/5)
Implementation: ⭐⭐⭐⭐⭐ (5/5)
Testing: ⭐⭐⭐☆☆ (3/5)
Security: ⭐⭐⭐⭐⭐ (5/5)
✅ Recommendation: Approve with Minor FixesThis is a well-designed solution to an important CI reliability problem. The implementation is solid and the architecture is clean. Before merging:
After merging:
🎯 Key TakeawaysWhat this PR does well:
What could be improved:
Risk level: 🟢 Low - Well-contained changes with clear failure modes Great work on improving CI reliability! 🚀 |
Improvements to .github/actions/ensure-master-docs-safety/action.yml: - Remove redundant null check (already handled by step condition) - Add comprehensive documentation for 7-day lookback window - Optimize API pagination with early exit strategy - Reduce per_page from 100 to 30 for efficiency - Improve deduplication to use run_number instead of created_at - Add clickable markdown links to failing workflows in error messages - Document handling of 'skipped' and 'neutral' workflow conclusions Workflow improvements: - Add clear inline comments explaining conditional logic in gem-tests.yml, integration-tests.yml, and lint-js-and-ruby.yml - Clarify "Skip only if: master push AND docs-only changes" pattern Code quality: - Remove duplicate dependencies in knip.ts (@babel/runtime, mini-css-extract-plugin) - Improve comment explaining runtime-injected dependencies All changes verified with RuboCop and Prettier checks passing. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
♻️ Duplicate comments (1)
.github/workflows/gem-tests.yml (1)
62-67: Input parameter naming is correct here; verify consistency with lint-js-and-ruby.yml.This file correctly passes
docs-only:as the input name (line 66), matching the action definition. However,.github/workflows/lint-js-and-ruby.ymlappears to usedocs_only:(with underscore) on line 64. Ensure both workflows use the kebab-case formdocs-only:consistently.
🧹 Nitpick comments (2)
.github/workflows/lint-js-and-ruby.yml (1)
69-80: Clarify the build job conditional logic for maintainability.The conditional is logically correct but deeply nested:
if: | !( github.event_name == 'push' && github.ref == 'refs/heads/master' && needs.detect-changes.outputs.docs_only == 'true' ) && ( github.ref == 'refs/heads/master' || needs.detect-changes.outputs.run_lint == 'true' )This works, but consider adding a comment explaining the intent: "Run unless this is a docs-only master push, and run if on master or lint is required." This will help maintainers quickly understand the skip heuristic.
Consider refactoring with intermediate variables or a clearer comment for readability, though the current form is functionally sound.
.github/actions/ensure-master-docs-safety/action.yml (1)
1-126: Overall action structure and messaging is solid; consider documenting the 7-day window in action metadata.The composite action is well-structured with clear error messaging that guides users on remediation. The 7-day window for querying is intentionally conservative (as documented in lines 22-27), but consider adding this context to the action description or as a comment in the metadata section for operators/maintainers who might tune this later.
Consider adding a comment in the action metadata section (near the description) that notes: "Skips validation for commits older than 7 days; see script logic for rationale." This helps future maintainers understand the design intent without diving into the script.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
.github/actions/ensure-master-docs-safety/action.yml(1 hunks).github/workflows/gem-tests.yml(4 hunks).github/workflows/integration-tests.yml(5 hunks).github/workflows/lint-js-and-ruby.yml(3 hunks)knip.ts(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- .github/workflows/integration-tests.yml
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: 2025-01-23T18:20:45.824Z
Learnt from: alexeyr-ci
Repo: shakacode/react_on_rails PR: 1687
File: spec/dummy/package.json:0-0
Timestamp: 2025-01-23T18:20:45.824Z
Learning: When adding or updating dependencies in spec/dummy/package.json, maintain version consistency with other package.json files in the codebase to avoid potential version conflicts.
Applied to files:
knip.ts
📚 Learning: 2025-02-13T19:09:15.991Z
Learnt from: AbanoubGhadban
Repo: shakacode/react_on_rails PR: 1644
File: node_package/src/RSCWebpackLoader.ts:0-0
Timestamp: 2025-02-13T19:09:15.991Z
Learning: In React Server Components webpack loader, using `new Function('return import("react-server-dom-webpack/node-loader")')()` is necessary as a workaround to bypass TypeScript compilation issues with direct dynamic imports.
Applied to files:
knip.ts
📚 Learning: 2025-09-16T08:01:11.146Z
Learnt from: justin808
Repo: shakacode/react_on_rails PR: 1770
File: lib/generators/react_on_rails/templates/base/base/app/javascript/src/HelloWorld/ror_components/HelloWorld.client.jsx:2-2
Timestamp: 2025-09-16T08:01:11.146Z
Learning: React on Rails uses webpack CSS Modules configuration with namedExports: true, which requires the import syntax `import * as style from './file.module.css'` rather than the default export pattern. This configuration enables better tree shaking and bundle size optimization for CSS modules.
Applied to files:
knip.ts
⏰ 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). (11)
- GitHub Check: build-dummy-app-webpack-test-bundles (3.4, 22, latest)
- GitHub Check: build-dummy-app-webpack-test-bundles (3.2, 20, minimum)
- GitHub Check: rspec-package-tests (3.2, minimum)
- GitHub Check: rspec-package-tests (3.4, latest)
- GitHub Check: examples (3.2, minimum)
- GitHub Check: examples (3.4, latest)
- GitHub Check: build-dummy-app-webpack-test-bundles
- GitHub Check: build
- GitHub Check: pro-lint-js-and-ruby
- GitHub Check: build-dummy-app-webpack-test-bundles
- GitHub Check: claude-review
🔇 Additional comments (6)
knip.ts (1)
165-165: Verify this change is intentional for this PR.This comment update appears unrelated to the PR's objective of guarding docs-only master pushes via GitHub Actions. The change is cosmetic (comment-only) and doesn't affect the workflow logic being introduced.
If this change was included unintentionally, consider removing it to keep the PR focused. If intentional, briefly clarify the connection to the PR objectives.
.github/workflows/lint-js-and-ruby.yml (1)
60-65: Verify action input parameter naming.The guard step passes input
docs_only(line 64), but.github/actions/ensure-master-docs-safety/action.ymldefines the input asdocs-only(line 4). GitHub Actions uses kebab-case for input names, so the caller must use the kebab-case form in thewith:block.Confirm whether the correct form is
docs-only:ordocs_only:. Reference the action definition to ensure consistency across both workflow files (lint-js-and-ruby.yml and gem-tests.yml)..github/actions/ensure-master-docs-safety/action.yml (4)
65-74: Deduplication logic is correct; run_number tiebreaker is a good choice.The deduplication using
run_numberas the tiebreaker (line 71) correctly handles rapid reruns that might share the samecreated_attimestamp. This ensures the latest attempt is evaluated, not a stale earlier run.
98-113: Conclusion filtering logic is well-reasoned and comprehensive.The explicit treatment of conclusions—failures, timeouts, cancellations, and action_required as blocking; skipped and neutral as allowed—is documented with clear comments. This nuanced approach correctly handles the different failure modes without being overly strict.
76-96: Status check is correct; verification complete.GitHub API confirms "completed" is the only terminal status value for workflow runs, with incomplete workflows having statuses like
in_progress,queued,waiting, orpending. The code correctly filters forstatus !== 'completed'to identify running workflows. The error messaging with direct links is actionable and appropriate.
14-14: Code is correct—the condition is comprehensive.Based on GitHub's webhook documentation,
github.event.beforeis always either a valid 40-character commit SHA or the all-zero SHA (0000000000000000000000000000000000000000) for newly created refs. The code already handles both cases: the empty string check covers malformed inputs, and the all-zero check covers new refs. No other placeholder values exist for this field in GitHub's push event payload. Edge cases like initial commits (new refs) and force pushes are properly handled.
Explicitly sort workflow runs by created date in descending order to ensure early exit optimization works correctly. This makes the assumption that newer runs appear first more explicit and reliable. - Add sort: 'created' parameter - Add direction: 'desc' parameter This ensures the early exit logic (stopping when we see SHAs different from the previous commit) works as intended.
Code Review for PR #2042: Guard master docs-only pushesOverall, this is a well-designed and thoroughly implemented PR that adds an important safety mechanism to the CI pipeline. The code quality is high, with excellent documentation and defensive programming practices. ✅ Strengths1. Excellent Code Quality
2. Strong Documentation
3. Well-Considered Design
4. Security & Permissions
🔍 Potential Issues & Suggestions1. Race Condition with Rapid Pushes (Low Severity)If a developer pushes two commits to master in rapid succession (within seconds), the second push might check the first commit status before its workflows have even started. However, this is likely acceptable given GitHub Actions typically creates workflow runs within seconds and this is an edge case requiring sub-minute timing. Verdict: Document this edge case or add a note that rapid pushes may need manual verification. 2. Workflow Conditional Complexity (Medium Severity - Readability)The skip conditionals are complex and repeated across 11 files. Consider extracting this logic into a reusable composite action that outputs a single should_run boolean for better maintainability. This would be a good follow-up refactoring. 3. Missing Test Cases (Medium Severity)The PR description shows manual test cases are still pending. Before merging, test at least these critical scenarios:
🎯 Best Practices Observed
🔒 Security Considerations✅ No security concerns identified Recommendation: Consider pinning actions/github-script to a specific SHA for supply chain security. 📊 Performance Considerations✅ Well-optimized Estimated impact: Should save approximately 5-10 CI minutes per docs-only commit, which adds up over time. 🎬 Summary & RecommendationOverall Assessment: ✅ APPROVED with minor suggestionsThis PR demonstrates excellent software engineering practices with well-designed safety mechanisms, comprehensive implementation, excellent documentation, and thoughtful edge case handling. Before Merging:
Risk Assessment: LOW
Confidence Level: High confidence this will work as intended. The implementation is solid, defensive, and well-documented. Great work on this PR! The attention to detail and defensive programming approach is excellent. 🚀 |
Address code review feedback: - Clarify API rate limit constraints in 7-day window comment - Document run_number tiebreaker behavior for out-of-order reruns - Explain why 'cancelled' workflows block docs-only skips - Eliminate duplication in ci-changes-detector using CI_FLAGS array 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
Summary
This PR adds a safety mechanism to prevent docs-only commits on master from showing a misleading green checkmark when the previous commit has failing or incomplete CI workflows. Docs-only commits can still be pushed and will skip heavy CI jobs, but the guard action will fail if the previous commit wasn't fully validated.
Key Features
.github/actions/ensure-master-docs-safety) that validates previous master commit status before allowing docs-only CI skips to show greenci-changes-detectorscript now always emits outputs for docs-only casesHow It Works
The Problem This Solves
Before: Pushing a docs-only commit to master would skip all CI and show a green checkmark, even if the previous commit had failing tests. This created a false sense of security.
After: Docs-only commits still skip heavy CI jobs (saving resources), but the guard action fails if the previous commit wasn't validated, preventing a misleading green checkmark.
Improvements from Code Review
GitHub Action enhancements:
run_numberinstead ofcreated_atfor accurate re-run handlingScript improvements:
ci-changes-detectorby using single CI_FLAGS array for both GITHUB_OUTPUT and JSON outputWorkflow improvements:
Code quality:
Testing
Automated Tests
ci-changes-detectorscript tested locally with JSON outputManual Testing Scenarios
Impact
For developers:
For CI/CD:
Example Scenarios
Scenario 1: Safe docs-only commit
Scenario 2: Unsafe docs-only commit (prevented)
Developer must fix Commit A's failures before Commit B will show green.
Scenario 3: Code change (always full CI)
Summary by CodeRabbit