-
Notifications
You must be signed in to change notification settings - Fork 9
137 lines (126 loc) · 6.33 KB
/
Copy pathtest-pull-request.yml
File metadata and controls
137 lines (126 loc) · 6.33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
name: Test pull request action
# CI for every branch. Runs on push so the reusable tasks resolve from the pushed head: a PR that edits a
# workflow tests its own copy, and the aggregator (the ruleset required check) is produced on the head SHA by
# the sole producing run. validate (unit tests + lint) runs on every push. The image smoke build runs only
# when image files changed (inline git diff change-gate), since a full product smoke is heavier than a
# doc-only push warrants. CI never publishes (the publisher runs on schedule/push-on-Matrix.json/dispatch).
#
# There is deliberately no pull_request trigger: a fork PR cannot push to this repo, so it produces no run and
# cannot satisfy the required check. A maintainer lands such a contribution on an in-repo branch (which
# pushes, and so validates) before merging. This is the documented exception (see WORKFLOW.md).
on:
# All branches, but not tags: release tags must not re-run CI.
push:
branches: ['**']
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
# Deny by default: every job below grants only what its own steps need.
# A job added later inherits nothing rather than the repository default, which is write on this repo.
permissions: {}
jobs:
# Inline change-gate (no third-party action): diff the push against its before-commit to decide whether the
# image smoke build is needed. image => any Docker/Matrix/Version file changed. Base => a base Dockerfile
# changed. On a non-push event (workflow_dispatch) or a new branch (no before-commit), build everything.
# !github.event.deleted skips a branch-deletion push (github.sha is all-zeros, so checkout would fail).
changes:
name: Detect image changes job
if: ${{ !github.event.deleted }}
runs-on: ubuntu-latest
permissions:
contents: read
outputs:
image: ${{ steps.filter.outputs.image }}
base: ${{ steps.filter.outputs.base }}
steps:
- name: Checkout step
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
- name: Filter changed paths step
id: filter
env:
BEFORE: ${{ github.event.before }}
AFTER: ${{ github.sha }}
run: |
set -Eeuo pipefail
# A new branch or non-push event has no usable before-commit (all-zeros or empty). Build everything.
if [[ "$BEFORE" =~ ^0+$ || -z "$BEFORE" || "${{ github.event_name }}" != "push" ]]; then
echo "image=true" >> "$GITHUB_OUTPUT"
echo "base=true" >> "$GITHUB_OUTPUT"
exit 0
fi
if ! DIFF=$(git diff --name-only "$BEFORE" "$AFTER" 2>/dev/null); then
# BEFORE is not in the fetched history (e.g. a force-push that rewrote it). Build everything.
echo "image=true" >> "$GITHUB_OUTPUT"
echo "base=true" >> "$GITHUB_OUTPUT"
exit 0
fi
if grep -qE '^(Docker/|Make/Matrix\.json$|Make/Version\.json$)' <<<"$DIFF"; then
echo "image=true" >> "$GITHUB_OUTPUT"
else
echo "image=false" >> "$GITHUB_OUTPUT"
fi
if grep -qE '^Docker/(NxBase\.Dockerfile|NxBase-LSIO\.Dockerfile)$' <<<"$DIFF"; then
echo "base=true" >> "$GITHUB_OUTPUT"
else
echo "base=false" >> "$GITHUB_OUTPUT"
fi
# The same unit-test + lint gate the publisher runs, so the PR gate and the publish gate are identical.
validate:
name: Validate job
if: ${{ !github.event.deleted }}
permissions:
contents: read
uses: ./.github/workflows/validate-task.yml
secrets: inherit
# Fast smoke build in place of the full matrix: only runs when image files changed, and builds just NxMeta +
# NxMeta-LSIO on amd64 (no push). branch targets the pushed branch so a push to develop validates the develop
# image rows and a push to main validates the main rows. ref is left unset so checkout uses the pushed head.
# build_base is enabled only when a base Dockerfile changed (otherwise the product smoke pulls the published
# base from Docker Hub). It also `needs: validate`, and the `if` carries no `always()`, so an unsuccessful
# validate skips this job via GitHub's implicit needs-success rule - the smoke build is not spent when
# validation already failed.
smoke-build:
name: Smoke build job
needs: [changes, validate]
if: ${{ !github.event.deleted && needs.changes.outputs.image == 'true' }}
permissions:
contents: read
uses: ./.github/workflows/build-docker-task.yml
secrets: inherit
with:
push: false
smoke: true
# Map the push ref to a Matrix.json .Branch value: a main push checks main's rows. Every other branch
# (develop, and feature branches that merge via develop) FALLS BACK to develop's rows. Passing
# github.ref_name directly would be a feature-branch name matching no .Branch row -> empty smoke matrix.
branch: ${{ github.ref_name == 'main' && 'main' || 'develop' }}
build_base: ${{ needs.changes.outputs.base == 'true' }}
# Single required status check. Its name is the ruleset-bound context in the live branch ruleset.
# Do not rename it without updating the ruleset in lockstep.
# Skips on a branch deletion, when the other jobs also skip, so the deletion push does not fail it.
check-workflow-status:
name: Check pull request workflow status job
runs-on: ubuntu-latest
permissions: {}
needs: [changes, validate, smoke-build]
if: ${{ always() && !github.event.deleted }}
steps:
- name: Check workflow results step
run: |
set -Eeuo pipefail
exit_on_result() {
# Pass on success or skipped (smoke-build is skipped when no image files changed). Fail only on
# failure/cancelled.
if [[ "$2" == "failure" || "$2" == "cancelled" ]]; then
echo "::error::Job '$1' failed or was cancelled."
exit 1
fi
}
# changes must succeed: if it fails, smoke-build is skipped (not run), and treating that skip as a
# pass would let an image-changing PR merge without the smoke build.
exit_on_result "changes" "${{ needs.changes.result }}"
exit_on_result "validate" "${{ needs.validate.result }}"
exit_on_result "smoke-build" "${{ needs.smoke-build.result }}"