-
Notifications
You must be signed in to change notification settings - Fork 9
126 lines (116 loc) · 6.03 KB
/
Copy pathtest-pull-request.yml
File metadata and controls
126 lines (116 loc) · 6.03 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
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
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
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 -euo 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 }}
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' }}
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 repo-config/ruleset-*.json. Do not
# rename it without updating those in lockstep. Skips on a branch deletion (when the other jobs also skip), so
# the deletion push does not fail this required check.
check-workflow-status:
name: Check pull request workflow status job
runs-on: ubuntu-latest
needs: [changes, validate, smoke-build]
if: ${{ always() && !github.event.deleted }}
steps:
- name: Check workflow results step
run: |
set -euo 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 }}"