Repository navigation
145 lines (134 loc) · 6.95 KB
/
Copy pathtest-pull-request.yml
File metadata and controls
145 lines (134 loc) · 6.95 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
138
139
140
141
142
143
144
145
name: Test pull request action
# CI for every branch. Runs on push so 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, Docker hook, or workflow changed, the last
# covering a hub pin bump, whose tasks a pull request otherwise never exercises. Base => a base
# Dockerfile or the base hook 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$|\.github/actions/docker-|\.github/workflows/)' <<<"$DIFF"; then
echo "image=true" >> "$GITHUB_OUTPUT"
else
echo "image=false" >> "$GITHUB_OUTPUT"
fi
if grep -qE '^(Docker/(NxBase\.Dockerfile|NxBase-LSIO\.Dockerfile)$|\.github/actions/docker-build-base/)' <<<"$DIFF"; then
echo "base=true" >> "$GITHUB_OUTPUT"
else
echo "base=false" >> "$GITHUB_OUTPUT"
fi
# The hub's reusable gate, the same one the publisher runs, so the push gate and the publish gate are identical.
validate:
name: Validate job
if: ${{ !github.event.deleted }}
uses: ptr727/ProjectTemplate/.github/workflows/validate-task.yml@ab9d050b55e246c8e5563ac1264709d1c33b5552 # 2.0.1198
permissions:
contents: read
secrets:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
# Fast smoke build in place of the full matrix, only when image files changed, through the hub's release chain with smoke set, which never pushes.
# It builds one NxMeta and one NxMeta-LSIO row on amd64, the image input naming them as the docker-prepare hook's filter.
# The base images build first only when a base Dockerfile changed, and otherwise the product smoke pulls the published base from Docker Hub.
# It needs validate with no always() in its if, so an unsuccessful validate skips it through the implicit needs-success rule.
# The Docker Hub secrets are mapped even on smoke, since the hub task logs in on every build for the higher rate limit.
smoke-build:
name: Smoke build job
needs: [changes, validate]
if: ${{ !github.event.deleted && needs.changes.outputs.image == 'true' }}
uses: ptr727/ProjectTemplate/.github/workflows/build-release-task.yml@ab9d050b55e246c8e5563ac1264709d1c33b5552 # 2.0.1198
permissions:
contents: read
secrets:
DOCKER_HUB_USERNAME: ${{ secrets.DOCKER_HUB_USERNAME }}
DOCKER_HUB_ACCESS_TOKEN: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
with:
smoke: true
github: false
dockerhub: false
enable_docker: true
enable_dotnet_publish: false
enable_nuget: false
enable_pypi: false
expect_release_assets: false
docker_image: NxMeta,NxMeta-LSIO
docker_build_base: ${{ needs.changes.outputs.base == 'true' }}
# Map the push ref to a Make/Matrix.json Branch value: a main push checks main's rows.
# Every other branch, develop and the feature branches that merge through it, falls back to develop's rows.
# Passing github.ref_name directly would name a feature branch that matches no row, an empty smoke matrix.
branch: ${{ github.ref_name == 'main' && 'main' || 'develop' }}
# 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 }}"