-
Notifications
You must be signed in to change notification settings - Fork 207
182 lines (168 loc) · 7.41 KB
/
Copy pathexamples.yml
File metadata and controls
182 lines (168 loc) · 7.41 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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
name: Examples
# Builds and runs the host-tier examples against a wolfSSL built per profile.
#
# Deliberately carries NO `github.repository_owner == 'wolfssl'` guard. That
# convention exists to stop *scheduled* runs on forks (see nightly.yml, which
# does guard). Applying it here would make every fork run 100% skips and remove
# any way to validate a CI change before it reaches master.
# START OF COMMON SECTION
on:
push:
branches: [ '**' ]
paths-ignore:
- 'Arduino/**'
- '.github/workflows/arduino*.yml'
- '**.md'
pull_request:
types: [opened, synchronize, reopened, ready_for_review]
branches: [ '*' ]
workflow_call:
inputs:
caller_run_id:
description: 'run id of the calling workflow; keeps a called run in its own concurrency group'
type: string
default: ''
wolfssl_refs:
description: 'comma-separated wolfSSL refs'
type: string
default: 'master'
# A reusable workflow must NOT self-cancel: when nightly.yml calls it the group
# would collide with the caller's own run and cancel it.
# In a reusable workflow github.event_name is the CALLER's event (schedule, push,
# ...) and is never 'workflow_call', so it cannot detect being called: keying off
# it left cancel-in-progress permanently true and let a nightly cancel its own
# attempt-2 retry. inputs is null unless we were called, so key off that instead.
concurrency:
group: ${{ inputs.caller_run_id && format('{0}-call-{1}', github.workflow, inputs.caller_run_id) || format('{0}-{1}', github.workflow, github.ref) }}
cancel-in-progress: ${{ !inputs.caller_run_id }}
# END OF COMMON SECTION
permissions:
contents: read
jobs:
# Fails when a dir holding buildable source has no manifest entry. This is what
# keeps "test every example" true a year from now rather than only on day one.
coverage:
name: Coverage gate
runs-on: ubuntu-24.04
timeout-minutes: 5
if: github.event_name != 'pull_request' || github.event.pull_request.draft == false
steps:
- uses: actions/checkout@v5
- run: pip install --quiet pyyaml
- run: python3 .github/scripts/manifest.py check
# PRs test master AND the latest stable tag. Testing only master would let a
# break against the released version reach users unnoticed until nightly.
refs:
uses: ./.github/workflows/_resolve-wolfssl.yml
with:
refs: ${{ inputs.wolfssl_refs || '' }}
stable_count: 1
matrix:
name: Resolve matrix
needs: [refs]
runs-on: ubuntu-24.04
timeout-minutes: 5
if: github.event_name != 'pull_request' || github.event.pull_request.draft == false
outputs:
examples: ${{ steps.gen.outputs.examples }}
wolfssl: ${{ steps.gen.outputs.wolfssl }}
steps:
- uses: actions/checkout@v5
- run: pip install --quiet pyyaml
- id: gen
run: |
set -euo pipefail
refs='${{ needs.refs.outputs.refs }}'
shas='${{ needs.refs.outputs.shas }}'
m() { python3 .github/scripts/manifest.py "$1" --refs "$refs" --shas "$shas"; }
echo "examples=$(m matrix)" >> "$GITHUB_OUTPUT"
echo "wolfssl=$(m wolfssl-matrix)" >> "$GITHUB_OUTPUT"
n=$(m matrix | python3 -c 'import json,sys;print(len(json.load(sys.stdin)))')
w=$(m wolfssl-matrix | python3 -c 'import json,sys;print(len(json.load(sys.stdin)))')
echo "$n example jobs against $w wolfSSL build(s)"
echo "$n example jobs against $w cached wolfSSL build(s)" >> "$GITHUB_STEP_SUMMARY"
# Build each wolfSSL profile ONCE and let the cache fan out to the per-example
# jobs. Without this, every example pays a full wolfSSL build.
build-wolfssl:
name: wolfSSL ${{ matrix.profile }} (${{ matrix.wolfssl_ref }})
needs: [matrix]
runs-on: ubuntu-24.04
timeout-minutes: 25
strategy:
fail-fast: false
matrix:
include: ${{ fromJson(needs.matrix.outputs.wolfssl) }}
steps:
- uses: actions/checkout@v5
- name: Install build deps
run: sudo apt-get update && sudo apt-get install -y --no-install-recommends autoconf automake libtool
- name: Setup wolfSSL (${{ matrix.profile }})
uses: ./.github/actions/setup-wolfssl
with:
# the pinned commit, not the branch name: every job must build and
# cache the same wolfSSL
ref: ${{ matrix.wolfssl_sha }}
flags: ${{ matrix.flags }}
cflags: ${{ matrix.cflags }}
# One job per example, so a red tile names the example that broke.
examples:
name: ${{ matrix.mode_label }} / ${{ matrix.id }} (${{ matrix.wolfssl_ref }})
needs: [matrix, build-wolfssl]
# Run even if a build-wolfssl leg failed. Plain `needs` would skip ALL 124
# example jobs because one profile did not configure -- so a single bad flag
# hides every real result. Examples on a healthy profile hit the cache;
# examples on the broken one fail on their own tile, which is the point.
if: ${{ !cancelled() && needs.matrix.result == 'success' }}
runs-on: ubuntu-24.04
timeout-minutes: 30
strategy:
fail-fast: false
matrix:
include: ${{ fromJson(needs.matrix.outputs.examples) }}
steps:
- uses: actions/checkout@v5
- name: Install deps
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends autoconf automake libtool ${{ matrix.deps }}
pip install --quiet pyyaml
# Cache hit from build-wolfssl above: restores and installs, does not rebuild.
- name: Setup wolfSSL (${{ matrix.profile }})
id: wolfssl
uses: ./.github/actions/setup-wolfssl
with:
# the pinned commit, not the branch name: every job must build and
# cache the same wolfSSL
ref: ${{ matrix.wolfssl_sha }}
flags: ${{ matrix.flags }}
cflags: ${{ matrix.cflags }}
# The harness needs a netns per pair because port 11111 sits in TIME_WAIT
# (the servers have no SO_REUSEADDR). Probe the EXACT invocation it uses:
# `unshare --user --net` succeeds with no uid mapping and proves nothing --
# --map-root-user is the part that needs the capability.
- name: Enable unprivileged user namespaces
run: |
if ! unshare --user --map-root-user --net -- true 2>/dev/null; then
echo "userns with uid mapping blocked; relaxing the apparmor restriction"
sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0 || true
fi
unshare --user --map-root-user --net -- true 2>/dev/null \
&& echo "userns ok" \
|| echo "userns still blocked; harness will fall back to sudo unshare --net"
- name: Build and run ${{ matrix.id }}
run: |
python3 .github/scripts/run_example.py \
--only '${{ matrix.id }}' \
--expect-sha '${{ steps.wolfssl.outputs.sha256 }}' \
--wolfssl-ref '${{ matrix.wolfssl_ref }}' \
--results "results-${{ matrix.id }}-${{ matrix.ref_slug }}.json"
# run_attempt in the name: a rerun (attempt 2) must not collide with the
# attempt-1 artifact, and triage merges attempt 2 over attempt 1 per dir.
- name: Upload results
if: always()
uses: actions/upload-artifact@v4
with:
name: results-${{ matrix.id }}-${{ matrix.ref_slug }}-attempt${{ github.run_attempt }}
path: results-*.json
retention-days: 5
if-no-files-found: ignore