Skip to content

Commit 9e6e3e6

Browse files
committed
Guard master docs-only pushes and ensure full CI runs
1 parent a166ddb commit 9e6e3e6

File tree

12 files changed

+341
-37
lines changed

12 files changed

+341
-37
lines changed
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
name: Ensure master docs-only skips are safe
2+
description: Fails if the previous master commit still has failing workflow runs when current push is docs-only
3+
inputs:
4+
docs-only:
5+
description: 'String output from ci-changes-detector ("true" or "false")'
6+
required: true
7+
previous-sha:
8+
description: 'SHA of the previous commit on master (github.event.before)'
9+
required: true
10+
runs:
11+
using: composite
12+
steps:
13+
- name: Check previous master commit status
14+
if: ${{ inputs.docs-only == 'true' && inputs.previous-sha != '' && inputs.previous-sha != '0000000000000000000000000000000000000000' }}
15+
uses: actions/github-script@v7
16+
with:
17+
script: |
18+
const previousSha = core.getInput('previous-sha');
19+
const workflowRuns = await github.paginate(
20+
github.rest.actions.listWorkflowRunsForRepo,
21+
{
22+
owner: context.repo.owner,
23+
repo: context.repo.repo,
24+
branch: 'master',
25+
per_page: 100
26+
}
27+
);
28+
29+
const relevantRuns = workflowRuns.filter((run) => run.head_sha === previousSha);
30+
31+
if (relevantRuns.length === 0) {
32+
core.info(`No workflow runs found for ${previousSha}. Nothing to enforce.`);
33+
return;
34+
}
35+
36+
const latestByWorkflow = new Map();
37+
for (const run of relevantRuns) {
38+
const existing = latestByWorkflow.get(run.workflow_id);
39+
if (!existing || new Date(run.created_at) > new Date(existing.created_at)) {
40+
latestByWorkflow.set(run.workflow_id, run);
41+
}
42+
}
43+
44+
const failingRuns = Array.from(latestByWorkflow.values()).filter((run) => {
45+
if (run.status !== 'completed') {
46+
core.info(`Workflow ${run.name} (#${run.id}) is still ${run.status}; ignoring for enforcement.`);
47+
return false;
48+
}
49+
return ['failure', 'timed_out', 'cancelled', 'action_required'].includes(run.conclusion);
50+
});
51+
52+
if (failingRuns.length === 0) {
53+
core.info(`Previous master commit ${previousSha} completed without failures. Docs-only skip allowed.`);
54+
return;
55+
}
56+
57+
const details = failingRuns
58+
.map((run) => `- ${run.name} (run #${run.run_number}) concluded ${run.conclusion}`)
59+
.join('\n');
60+
61+
core.setFailed(
62+
[
63+
`Cannot skip CI for docs-only commit because previous master commit ${previousSha} still has failing workflows:`,
64+
details
65+
].join('\n')
66+
);

.github/workflows/detect-changes.yml

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ on:
2525
jobs:
2626
detect:
2727
runs-on: ubuntu-22.04
28+
permissions:
29+
contents: read
30+
actions: read
2831
outputs:
2932
docs_only: ${{ steps.changes.outputs.docs_only }}
3033
run_lint: ${{ steps.changes.outputs.run_lint }}
@@ -41,17 +44,11 @@ jobs:
4144
- name: Detect changes
4245
id: changes
4346
run: |
44-
# For master branch, always run everything
45-
if [ "${{ github.ref }}" = "refs/heads/master" ]; then
46-
echo "docs_only=false" >> "$GITHUB_OUTPUT"
47-
echo "run_lint=true" >> "$GITHUB_OUTPUT"
48-
echo "run_ruby_tests=true" >> "$GITHUB_OUTPUT"
49-
echo "run_js_tests=true" >> "$GITHUB_OUTPUT"
50-
echo "run_dummy_tests=true" >> "$GITHUB_OUTPUT"
51-
echo "run_generators=true" >> "$GITHUB_OUTPUT"
52-
exit 0
53-
fi
54-
55-
# For PRs, analyze changes
56-
BASE_SHA="${{ github.event.pull_request.base.sha || github.event.before }}"
47+
BASE_SHA="${{ github.event.pull_request.base.sha || github.event.before || 'origin/master' }}"
5748
script/ci-changes-detector "$BASE_SHA"
49+
- name: Guard docs-only master pushes
50+
if: github.event_name == 'push' && github.ref == 'refs/heads/master'
51+
uses: ./.github/actions/ensure-master-docs-safety
52+
with:
53+
docs-only: ${{ steps.changes.outputs.docs_only }}
54+
previous-sha: ${{ github.event.before }}

.github/workflows/examples.yml

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ on:
44
push:
55
branches:
66
- 'master'
7-
# Never skip on master - always run full test suite
7+
# Always trigger on master; docs-only detection handles skipping heavy jobs
88
pull_request:
99
paths-ignore:
1010
- '**.md'
@@ -19,6 +19,9 @@ on:
1919

2020
jobs:
2121
detect-changes:
22+
permissions:
23+
contents: read
24+
actions: read
2225
runs-on: ubuntu-22.04
2326
outputs:
2427
docs_only: ${{ steps.detect.outputs.docs_only }}
@@ -54,6 +57,12 @@ jobs:
5457
BASE_REF="${{ github.event.pull_request.base.sha || github.event.before || 'origin/master' }}"
5558
script/ci-changes-detector "$BASE_REF"
5659
shell: bash
60+
- name: Guard docs-only master pushes
61+
if: github.event_name == 'push' && github.ref == 'refs/heads/master'
62+
uses: ./.github/actions/ensure-master-docs-safety
63+
with:
64+
docs-only: ${{ steps.detect.outputs.docs_only }}
65+
previous-sha: ${{ github.event.before }}
5766

5867
setup-matrix:
5968
needs: detect-changes
@@ -79,7 +88,15 @@ jobs:
7988
needs: [detect-changes, setup-matrix]
8089
# Run on master, workflow_dispatch, OR when generators needed
8190
if: |
82-
github.ref == 'refs/heads/master' || github.event_name == 'workflow_dispatch' || needs.detect-changes.outputs.run_generators == 'true'
91+
!(
92+
github.event_name == 'push' &&
93+
github.ref == 'refs/heads/master' &&
94+
needs.detect-changes.outputs.docs_only == 'true'
95+
) && (
96+
github.ref == 'refs/heads/master' ||
97+
github.event_name == 'workflow_dispatch' ||
98+
needs.detect-changes.outputs.run_generators == 'true'
99+
)
83100
strategy:
84101
fail-fast: false
85102
matrix: ${{ fromJson(needs.setup-matrix.outputs.matrix) }}

.github/workflows/gem-tests.yml

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ on:
44
push:
55
branches:
66
- 'master'
7-
# Never skip on master - always run full test suite
7+
# Always trigger on master; docs-only detection handles skipping heavy jobs
88
pull_request:
99
paths-ignore:
1010
- '**.md'
@@ -21,6 +21,9 @@ on:
2121

2222
jobs:
2323
detect-changes:
24+
permissions:
25+
contents: read
26+
actions: read
2427
runs-on: ubuntu-22.04
2528
outputs:
2629
docs_only: ${{ steps.detect.outputs.docs_only }}
@@ -56,6 +59,12 @@ jobs:
5659
BASE_REF="${{ github.event.pull_request.base.sha || github.event.before || 'origin/master' }}"
5760
script/ci-changes-detector "$BASE_REF"
5861
shell: bash
62+
- name: Guard docs-only master pushes
63+
if: github.event_name == 'push' && github.ref == 'refs/heads/master'
64+
uses: ./.github/actions/ensure-master-docs-safety
65+
with:
66+
docs-only: ${{ steps.detect.outputs.docs_only }}
67+
previous-sha: ${{ github.event.before }}
5968

6069
setup-gem-tests-matrix:
6170
needs: detect-changes
@@ -79,7 +88,14 @@ jobs:
7988
needs: [detect-changes, setup-gem-tests-matrix]
8089
# Run on master OR when Ruby tests needed on PR
8190
if: |
82-
(github.ref == 'refs/heads/master' || needs.detect-changes.outputs.run_ruby_tests == 'true')
91+
!(
92+
github.event_name == 'push' &&
93+
github.ref == 'refs/heads/master' &&
94+
needs.detect-changes.outputs.docs_only == 'true'
95+
) && (
96+
github.ref == 'refs/heads/master' ||
97+
needs.detect-changes.outputs.run_ruby_tests == 'true'
98+
)
8399
strategy:
84100
fail-fast: false
85101
matrix: ${{ fromJson(needs.setup-gem-tests-matrix.outputs.matrix) }}

.github/workflows/integration-tests.yml

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ on:
44
push:
55
branches:
66
- 'master'
7-
# Never skip on master - always run full test suite
7+
# Always trigger on master; docs-only detection handles skipping heavy jobs
88
pull_request:
99
paths-ignore:
1010
- '**.md'
@@ -20,6 +20,9 @@ on:
2020

2121
jobs:
2222
detect-changes:
23+
permissions:
24+
contents: read
25+
actions: read
2326
runs-on: ubuntu-22.04
2427
outputs:
2528
docs_only: ${{ steps.detect.outputs.docs_only }}
@@ -51,9 +54,15 @@ jobs:
5154
echo "docs_only=false" >> "$GITHUB_OUTPUT"
5255
else
5356
BASE_REF="${{ github.event.pull_request.base.sha || github.event.before || 'origin/master' }}"
54-
script/ci-changes-detector "$BASE_REF"
57+
script/ci-changes-detector "$BASE_REF"
5558
fi
5659
shell: bash
60+
- name: Guard docs-only master pushes
61+
if: github.event_name == 'push' && github.ref == 'refs/heads/master'
62+
uses: ./.github/actions/ensure-master-docs-safety
63+
with:
64+
docs-only: ${{ steps.detect.outputs.docs_only }}
65+
previous-sha: ${{ github.event.before }}
5766

5867
setup-integration-matrix:
5968
needs: detect-changes
@@ -79,7 +88,15 @@ jobs:
7988
needs: [detect-changes, setup-integration-matrix]
8089
# Run on master, workflow_dispatch, OR when tests needed on PR
8190
if: |
82-
github.ref == 'refs/heads/master' || github.event_name == 'workflow_dispatch' || needs.detect-changes.outputs.run_dummy_tests == 'true'
91+
!(
92+
github.event_name == 'push' &&
93+
github.ref == 'refs/heads/master' &&
94+
needs.detect-changes.outputs.docs_only == 'true'
95+
) && (
96+
github.ref == 'refs/heads/master' ||
97+
github.event_name == 'workflow_dispatch' ||
98+
needs.detect-changes.outputs.run_dummy_tests == 'true'
99+
)
83100
strategy:
84101
matrix: ${{ fromJson(needs.setup-integration-matrix.outputs.matrix) }}
85102
runs-on: ubuntu-22.04
@@ -154,7 +171,15 @@ jobs:
154171
needs: [detect-changes, setup-integration-matrix, build-dummy-app-webpack-test-bundles]
155172
# Run on master, workflow_dispatch, OR when tests needed on PR
156173
if: |
157-
github.ref == 'refs/heads/master' || github.event_name == 'workflow_dispatch' || needs.detect-changes.outputs.run_dummy_tests == 'true'
174+
!(
175+
github.event_name == 'push' &&
176+
github.ref == 'refs/heads/master' &&
177+
needs.detect-changes.outputs.docs_only == 'true'
178+
) && (
179+
github.ref == 'refs/heads/master' ||
180+
github.event_name == 'workflow_dispatch' ||
181+
needs.detect-changes.outputs.run_dummy_tests == 'true'
182+
)
158183
strategy:
159184
matrix: ${{ fromJson(needs.setup-integration-matrix.outputs.matrix) }}
160185
runs-on: ubuntu-22.04

.github/workflows/lint-js-and-ruby.yml

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ on:
44
push:
55
branches:
66
- 'master'
7-
# Never skip on master - always run full test suite
7+
# Always trigger on master; docs-only detection handles skipping heavy jobs
88
pull_request:
99
paths-ignore:
1010
- '**.md'
@@ -20,6 +20,9 @@ on:
2020

2121
jobs:
2222
detect-changes:
23+
permissions:
24+
contents: read
25+
actions: read
2326
runs-on: ubuntu-22.04
2427
outputs:
2528
docs_only: ${{ steps.detect.outputs.docs_only }}
@@ -54,10 +57,24 @@ jobs:
5457
BASE_REF="${{ github.event.pull_request.base.sha || github.event.before || 'origin/master' }}"
5558
script/ci-changes-detector "$BASE_REF"
5659
shell: bash
60+
- name: Guard docs-only master pushes
61+
if: github.event_name == 'push' && github.ref == 'refs/heads/master'
62+
uses: ./.github/actions/ensure-master-docs-safety
63+
with:
64+
docs-only: ${{ steps.detect.outputs.docs_only }}
65+
previous-sha: ${{ github.event.before }}
5766

5867
build:
5968
needs: detect-changes
60-
if: github.ref == 'refs/heads/master' || needs.detect-changes.outputs.run_lint == 'true'
69+
if: |
70+
!(
71+
github.event_name == 'push' &&
72+
github.ref == 'refs/heads/master' &&
73+
needs.detect-changes.outputs.docs_only == 'true'
74+
) && (
75+
github.ref == 'refs/heads/master' ||
76+
needs.detect-changes.outputs.run_lint == 'true'
77+
)
6178
env:
6279
BUNDLE_FROZEN: true
6380
runs-on: ubuntu-22.04

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

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ on:
44
push:
55
branches:
66
- 'master'
7-
# Never skip on master - always run full test suite
7+
# Always trigger on master; docs-only detection handles skipping heavy jobs
88
pull_request:
99
paths-ignore:
1010
- '**.md'
@@ -22,6 +22,9 @@ on:
2222

2323
jobs:
2424
detect-changes:
25+
permissions:
26+
contents: read
27+
actions: read
2528
runs-on: ubuntu-22.04
2629
outputs:
2730
docs_only: ${{ steps.detect.outputs.docs_only }}
@@ -57,12 +60,25 @@ jobs:
5760
BASE_REF="${{ github.event.pull_request.base.sha || github.event.before || 'origin/master' }}"
5861
script/ci-changes-detector "$BASE_REF"
5962
shell: bash
63+
- name: Guard docs-only master pushes
64+
if: github.event_name == 'push' && github.ref == 'refs/heads/master'
65+
uses: ./.github/actions/ensure-master-docs-safety
66+
with:
67+
docs-only: ${{ steps.detect.outputs.docs_only }}
68+
previous-sha: ${{ github.event.before }}
6069

6170
build:
6271
needs: detect-changes
6372
# Run on master OR when JS tests needed on PR
6473
if: |
65-
(github.ref == 'refs/heads/master' || needs.detect-changes.outputs.run_js_tests == 'true')
74+
!(
75+
github.event_name == 'push' &&
76+
github.ref == 'refs/heads/master' &&
77+
needs.detect-changes.outputs.docs_only == 'true'
78+
) && (
79+
github.ref == 'refs/heads/master' ||
80+
needs.detect-changes.outputs.run_js_tests == 'true'
81+
)
6682
strategy:
6783
matrix:
6884
include:

0 commit comments

Comments
 (0)