Skip to content

Commit 7f38f00

Browse files
justin808claude
andauthored
Make /run-skipped-ci persistent using full-ci label (#2007)
## 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 ```bash # 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](https://claude.com/claude-code) <!-- Reviewable:start --> - - - This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/shakacode/react_on_rails/2007) <!-- Reviewable:end --> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## 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. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent c07dbd6 commit 7f38f00

File tree

10 files changed

+310
-24
lines changed

10 files changed

+310
-24
lines changed
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
name: Check for full-ci label
2+
description: Checks if the PR has the full-ci label to enable full CI mode
3+
outputs:
4+
result:
5+
description: 'Whether the full-ci label is present (string: "true" or "false")'
6+
value: ${{ steps.check.outputs.result }}
7+
runs:
8+
using: composite
9+
steps:
10+
- name: Check for full-ci label
11+
id: check
12+
uses: actions/github-script@v7
13+
with:
14+
result-encoding: string
15+
script: |
16+
// Only check labels on pull requests
17+
if (!context.payload.pull_request) {
18+
return 'false';
19+
}
20+
21+
const { data: labels } = await github.rest.issues.listLabelsOnIssue({
22+
owner: context.repo.owner,
23+
repo: context.repo.repo,
24+
issue_number: context.payload.pull_request.number
25+
});
26+
27+
const hasLabel = labels.some(label => label.name === 'full-ci');
28+
console.log(`full-ci label present: ${hasLabel}`);
29+
return hasLabel ? 'true' : 'false';

.github/workflows/examples.yml

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,17 +29,21 @@ jobs:
2929
run_ruby_tests: ${{ steps.detect.outputs.run_ruby_tests }}
3030
run_dummy_tests: ${{ steps.detect.outputs.run_dummy_tests }}
3131
run_generators: ${{ steps.detect.outputs.run_generators }}
32+
has_full_ci_label: ${{ steps.check-label.outputs.result }}
3233
steps:
3334
- uses: actions/checkout@v4
3435
with:
3536
# Fetch enough history for change detection (50 commits is usually sufficient for PRs)
3637
fetch-depth: 50
3738
persist-credentials: false
39+
- name: Check for full-ci label
40+
id: check-label
41+
uses: ./.github/actions/check-full-ci-label
3842
- name: Detect relevant changes
3943
id: detect
4044
run: |
41-
# If force_run is true, run everything
42-
if [ "${{ inputs.force_run }}" = "true" ]; then
45+
# If force_run is true OR full-ci label is present, run everything
46+
if [ "${{ inputs.force_run }}" = "true" ] || [ "${{ steps.check-label.outputs.result }}" = "true" ]; then
4347
echo "run_lint=true" >> "$GITHUB_OUTPUT"
4448
echo "run_js_tests=true" >> "$GITHUB_OUTPUT"
4549
echo "run_ruby_tests=true" >> "$GITHUB_OUTPUT"
@@ -69,9 +73,9 @@ jobs:
6973
- ruby-version: '3.2'
7074
dependency-level: 'minimum'
7175
exclude:
72-
# Skip minimum dependency matrix on regular PRs (run only on master/workflow_dispatch/force_run)
73-
- ruby-version: ${{ github.event_name == 'pull_request' && github.ref != 'refs/heads/master' && inputs.force_run != true && '3.2' || '' }}
74-
dependency-level: ${{ github.event_name == 'pull_request' && github.ref != 'refs/heads/master' && inputs.force_run != true && 'minimum' || '' }}
76+
# Skip minimum dependency matrix on regular PRs (run only on master/workflow_dispatch/force_run/full-ci label)
77+
- ruby-version: ${{ github.event_name == 'pull_request' && github.ref != 'refs/heads/master' && inputs.force_run != true && needs.detect-changes.outputs.has_full_ci_label != 'true' && '3.2' || '' }}
78+
dependency-level: ${{ github.event_name == 'pull_request' && github.ref != 'refs/heads/master' && inputs.force_run != true && needs.detect-changes.outputs.has_full_ci_label != 'true' && 'minimum' || '' }}
7579
env:
7680
SKIP_YARN_COREPACK_CHECK: 0
7781
BUNDLE_FROZEN: ${{ matrix.dependency-level == 'minimum' && 'false' || 'true' }}

.github/workflows/main.yml

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -29,17 +29,21 @@ jobs:
2929
run_ruby_tests: ${{ steps.detect.outputs.run_ruby_tests }}
3030
run_dummy_tests: ${{ steps.detect.outputs.run_dummy_tests }}
3131
run_generators: ${{ steps.detect.outputs.run_generators }}
32+
has_full_ci_label: ${{ steps.check-label.outputs.result }}
3233
steps:
3334
- uses: actions/checkout@v4
3435
with:
3536
# Fetch enough history for change detection (50 commits is usually sufficient for PRs)
3637
fetch-depth: 50
3738
persist-credentials: false
39+
- name: Check for full-ci label
40+
id: check-label
41+
uses: ./.github/actions/check-full-ci-label
3842
- name: Detect relevant changes
3943
id: detect
4044
run: |
41-
# If force_run is true, run everything
42-
if [ "${{ inputs.force_run }}" = "true" ]; then
45+
# If force_run is true OR full-ci label is present, run everything
46+
if [ "${{ inputs.force_run }}" = "true" ] || [ "${{ steps.check-label.outputs.result }}" = "true" ]; then
4347
echo "run_lint=true" >> "$GITHUB_OUTPUT"
4448
echo "run_js_tests=true" >> "$GITHUB_OUTPUT"
4549
echo "run_ruby_tests=true" >> "$GITHUB_OUTPUT"
@@ -70,10 +74,10 @@ jobs:
7074
node-version: '20'
7175
dependency-level: 'minimum'
7276
exclude:
73-
# Skip minimum dependency matrix on regular PRs (run only on master/workflow_dispatch/force_run)
74-
- ruby-version: ${{ github.event_name == 'pull_request' && github.ref != 'refs/heads/master' && inputs.force_run != true && '3.2' || '' }}
75-
node-version: ${{ github.event_name == 'pull_request' && github.ref != 'refs/heads/master' && inputs.force_run != true && '20' || '' }}
76-
dependency-level: ${{ github.event_name == 'pull_request' && github.ref != 'refs/heads/master' && inputs.force_run != true && 'minimum' || '' }}
77+
# Skip minimum dependency matrix on regular PRs (run only on master/workflow_dispatch/force_run/full-ci label)
78+
- ruby-version: ${{ github.event_name == 'pull_request' && github.ref != 'refs/heads/master' && inputs.force_run != true && needs.detect-changes.outputs.has_full_ci_label != 'true' && '3.2' || '' }}
79+
node-version: ${{ github.event_name == 'pull_request' && github.ref != 'refs/heads/master' && inputs.force_run != true && needs.detect-changes.outputs.has_full_ci_label != 'true' && '20' || '' }}
80+
dependency-level: ${{ github.event_name == 'pull_request' && github.ref != 'refs/heads/master' && inputs.force_run != true && needs.detect-changes.outputs.has_full_ci_label != 'true' && 'minimum' || '' }}
7781
runs-on: ubuntu-22.04
7882
steps:
7983
- uses: actions/checkout@v4
@@ -160,10 +164,10 @@ jobs:
160164
node-version: '20'
161165
dependency-level: 'minimum'
162166
exclude:
163-
# Skip minimum dependency matrix on regular PRs (run only on master/workflow_dispatch/force_run)
164-
- ruby-version: ${{ github.event_name == 'pull_request' && github.ref != 'refs/heads/master' && inputs.force_run != true && '3.2' || '' }}
165-
node-version: ${{ github.event_name == 'pull_request' && github.ref != 'refs/heads/master' && inputs.force_run != true && '20' || '' }}
166-
dependency-level: ${{ github.event_name == 'pull_request' && github.ref != 'refs/heads/master' && inputs.force_run != true && 'minimum' || '' }}
167+
# Skip minimum dependency matrix on regular PRs (run only on master/workflow_dispatch/force_run/full-ci label)
168+
- ruby-version: ${{ github.event_name == 'pull_request' && github.ref != 'refs/heads/master' && inputs.force_run != true && needs.detect-changes.outputs.has_full_ci_label != 'true' && '3.2' || '' }}
169+
node-version: ${{ github.event_name == 'pull_request' && github.ref != 'refs/heads/master' && inputs.force_run != true && needs.detect-changes.outputs.has_full_ci_label != 'true' && '20' || '' }}
170+
dependency-level: ${{ github.event_name == 'pull_request' && github.ref != 'refs/heads/master' && inputs.force_run != true && needs.detect-changes.outputs.has_full_ci_label != 'true' && 'minimum' || '' }}
167171
runs-on: ubuntu-22.04
168172
steps:
169173
- uses: actions/checkout@v4
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
name: PR Welcome Message
2+
3+
on:
4+
pull_request:
5+
types: [opened]
6+
7+
jobs:
8+
welcome:
9+
runs-on: ubuntu-22.04
10+
permissions:
11+
issues: write
12+
pull-requests: write
13+
steps:
14+
- name: Post welcome message
15+
uses: actions/github-script@v7
16+
with:
17+
script: |
18+
const welcomeMessage = [
19+
'👋 **Thanks for your contribution!**',
20+
'',
21+
'This PR will run CI tests based on the files you changed. If some tests are skipped and you want to run the full test suite (including minimum dependency tests), you can use these commands:',
22+
'',
23+
'### CI Control Commands',
24+
'',
25+
'- **`/run-skipped-ci`** - Runs all skipped CI checks and enables full CI mode for this PR',
26+
' - Adds the `full-ci` label to ensure future commits also run the full test suite',
27+
' - Useful when you want comprehensive testing across all configurations',
28+
'',
29+
'- **`/stop-run-skipped-ci`** - Disables full CI mode and returns to standard CI',
30+
' - Removes the `full-ci` label',
31+
' - Future commits will only run tests for changed files',
32+
'',
33+
'**Note:**',
34+
'- These commands require write access to the repository',
35+
'- The `full-ci` label is preserved on merged PRs as a historical record',
36+
'',
37+
'View CI progress in the [Actions tab](${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions).'
38+
].join('\n');
39+
40+
await github.rest.issues.createComment({
41+
owner: context.repo.owner,
42+
repo: context.repo.repo,
43+
issue_number: context.issue.number,
44+
body: welcomeMessage
45+
});
46+
47+
console.log('✅ Posted welcome message to PR');

.github/workflows/pro-integration-tests.yml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,17 +24,21 @@ jobs:
2424
docs_only: ${{ steps.detect.outputs.docs_only }}
2525
run_pro_lint: ${{ steps.detect.outputs.run_pro_lint }}
2626
run_pro_tests: ${{ steps.detect.outputs.run_pro_tests }}
27+
has_full_ci_label: ${{ steps.check-label.outputs.result }}
2728
steps:
2829
- uses: actions/checkout@v4
2930
with:
3031
fetch-depth: 0
3132
persist-credentials: false
33+
- name: Check for full-ci label
34+
id: check-label
35+
uses: ./.github/actions/check-full-ci-label
3236
- name: Detect relevant changes
3337
id: detect
3438
working-directory: .
3539
run: |
36-
# If force_run is true, run everything
37-
if [ "${{ inputs.force_run }}" = "true" ]; then
40+
# If force_run is true OR full-ci label is present, run everything
41+
if [ "${{ inputs.force_run }}" = "true" ] || [ "${{ steps.check-label.outputs.result }}" = "true" ]; then
3842
echo "run_pro_lint=true" >> "$GITHUB_OUTPUT"
3943
echo "run_pro_tests=true" >> "$GITHUB_OUTPUT"
4044
echo "docs_only=false" >> "$GITHUB_OUTPUT"

.github/workflows/pro-lint.yml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,17 +24,21 @@ jobs:
2424
docs_only: ${{ steps.detect.outputs.docs_only }}
2525
run_pro_lint: ${{ steps.detect.outputs.run_pro_lint }}
2626
run_pro_tests: ${{ steps.detect.outputs.run_pro_tests }}
27+
has_full_ci_label: ${{ steps.check-label.outputs.result }}
2728
steps:
2829
- uses: actions/checkout@v4
2930
with:
3031
fetch-depth: 0
3132
persist-credentials: false
33+
- name: Check for full-ci label
34+
id: check-label
35+
uses: ./.github/actions/check-full-ci-label
3236
- name: Detect relevant changes
3337
id: detect
3438
working-directory: .
3539
run: |
36-
# If force_run is true, run everything
37-
if [ "${{ inputs.force_run }}" = "true" ]; then
40+
# If force_run is true OR full-ci label is present, run everything
41+
if [ "${{ inputs.force_run }}" = "true" ] || [ "${{ steps.check-label.outputs.result }}" = "true" ]; then
3842
echo "run_pro_lint=true" >> "$GITHUB_OUTPUT"
3943
echo "run_pro_tests=true" >> "$GITHUB_OUTPUT"
4044
echo "docs_only=false" >> "$GITHUB_OUTPUT"

.github/workflows/pro-package-tests.yml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,17 +24,21 @@ jobs:
2424
docs_only: ${{ steps.detect.outputs.docs_only }}
2525
run_pro_lint: ${{ steps.detect.outputs.run_pro_lint }}
2626
run_pro_tests: ${{ steps.detect.outputs.run_pro_tests }}
27+
has_full_ci_label: ${{ steps.check-label.outputs.result }}
2728
steps:
2829
- uses: actions/checkout@v4
2930
with:
3031
fetch-depth: 0
3132
persist-credentials: false
33+
- name: Check for full-ci label
34+
id: check-label
35+
uses: ./.github/actions/check-full-ci-label
3236
- name: Detect relevant changes
3337
id: detect
3438
working-directory: .
3539
run: |
36-
# If force_run is true, run everything
37-
if [ "${{ inputs.force_run }}" = "true" ]; then
40+
# If force_run is true OR full-ci label is present, run everything
41+
if [ "${{ inputs.force_run }}" = "true" ] || [ "${{ steps.check-label.outputs.result }}" = "true" ]; then
3842
echo "run_pro_lint=true" >> "$GITHUB_OUTPUT"
3943
echo "run_pro_tests=true" >> "$GITHUB_OUTPUT"
4044
echo "docs_only=false" >> "$GITHUB_OUTPUT"

.github/workflows/run-skipped-ci.yml

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -216,17 +216,34 @@ jobs:
216216
const notFoundList = notFound.length > 0 ? `\n\n**Triggered but not yet queued (may still start):**\n${notFound.map(w => `- ⏳ ${w.name}`).join('\n')}` : '';
217217
const failedList = failed.length > 0 ? `\n\n**Failed to trigger:**\n${failed.map(f => `- ❌ ${f.workflow}: ${f.error}`).join('\n')}` : '';
218218
219-
const body = `🚀 **Skipped CI Checks - Trigger Results**
219+
// Add full-ci label only if we actually triggered workflows or if checks are already running
220+
let labelAdded = false;
221+
try {
222+
await github.rest.issues.addLabels({
223+
owner: context.repo.owner,
224+
repo: context.repo.repo,
225+
issue_number: context.issue.number,
226+
labels: ['full-ci']
227+
});
228+
labelAdded = true;
229+
console.log('✅ Added full-ci label to PR');
230+
} catch (error) {
231+
console.error('⚠️ Failed to add label:', error.message);
232+
}
233+
234+
const body = `🚀 **Full CI Mode Enabled**
220235
221236
${status}
222237
${skippedChecksList}
223238
${verifiedList}${notFoundList}${failedList}
224239
225-
${verified.length > 0 ? `\n**Note:** These workflows will run with \`force_run: true\` to bypass detect-changes logic that caused them to skip.
240+
${labelAdded && verified.length > 0 ? `\n**Note:** Added the \`full-ci\` label to this PR. All future commits will run the full CI suite (including minimum dependency tests) until the label is removed.
241+
242+
To disable full CI mode, use the \`/stop-run-skipped-ci\` command.
226243
227244
View progress in the [Actions tab](${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions).` : ''}
228245
229-
${notApplicable.length > 0 ? `\nAll CI checks are already running on this PR. Use this command when you see skipped checks that you want to run.` : ''}`;
246+
${labelAdded && notApplicable.length > 0 ? `\nAll CI checks are already running on this PR. Added the \`full-ci\` label - future commits will run the full CI suite.` : ''}`;
230247
231248
// Post the comment
232249
await github.rest.issues.createComment({

0 commit comments

Comments
 (0)