-
Notifications
You must be signed in to change notification settings - Fork 8
248 lines (232 loc) · 11.9 KB
/
Copy pathreusable-dist-ai-tests.yml
File metadata and controls
248 lines (232 loc) · 11.9 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
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
## Copyright (C) 2026 - 2026 ENCRYPTED SUPPORT LLC <adrelanos@whonix.org>
## See the file COPYING for copying conditions.
## AI-Assisted
## Reusable workflow: run this component's dist-ai regression suites.
##
## The comprehensive test suites for several derivative-maker packages
## are too high-volume for in-tree human review, so they live in the
## AI-maintained dist-ai repo (org-ai-assisted/dist-ai) rather than in
## each package. This workflow wires them back to the package's own PRs:
## it checks out the caller repo (the code under test) and dist-ai (the
## suites), then runs dist-ai-tests-all against the caller checkout via
## the standalone-component entry point (--component / --component-root).
## The component name is derived from the caller's repo name, so the
## consumer wrapper is byte-identical and needs no per-repo config.
##
## Runs in a debian:trixie-slim container (Python 3.13), NOT bare
## ubuntu-24.04 (Python 3.12): the packages under test target current
## Debian/Python (e.g. helper-scripts' stcat uses Path.read_text(newline=)
## which is 3.13+). Same container choice as reusable-pre-push-static.yml.
##
## Checkout layout: the caller repo and dist-ai are checked out as
## SIBLING subdirectories of GITHUB_WORKSPACE
## (component/, dist-ai/), NOT the caller at the workspace root
## with dist-ai nested inside it. This is deliberate: a suite that runs
## pytest (e.g. privleap-tests) derives the test module name from the
## test file's path relative to pytest's rootdir; if the dist-ai suites
## sit under a dot-prefixed dir inside the caller checkout (.dist-ai),
## pytest builds a module name with a leading dot and fails collection
## with "the 'package' argument is required to perform a relative
## import". Sibling dirs keep the suite path out of the caller tree and
## free of dot components. Do not "simplify" this back to a single
## workspace-root checkout.
##
## Per-repo values come from the caller's .github/dm-consumer.yml
## (read at runtime, same pattern as reusable-coverity.yml):
## dist-ai-tests:
## apt-packages: "python3 python3-pytest python3-hypothesis ..."
## helper-scripts: true # also check out helper-scripts (for suites
## # that drive sanitize-string, e.g.
## # open-link-confirmation)
## Both are optional; a repo needing only the default testing stack ships
## no dm-consumer.yml at all.
##
## See developer-meta-files agents/github-actions.md and each package's
## AGENTS.md "Tests" section.
##
## No 'concurrency:' block: github.workflow inside a reusable resolves to
## the caller's workflow name, so a group declared here would deadlock
## with the caller's cancellable group (same precedent as
## reusable-pre-push-static.yml).
name: dist-ai tests (reusable)
on:
workflow_call:
inputs:
categories:
description: 'dist-ai-tests-all category flags. Default: --core (fast, PR-suitable).'
required: false
type: string
default: '--core'
dist-ai-ref:
description: 'Ref of org-ai-assisted/dist-ai to check out.'
required: false
type: string
default: 'master'
permissions:
contents: read
jobs:
dist-ai-tests:
name: dist-ai tests
runs-on: ubuntu-24.04
container:
image: debian:trixie-slim
## Mount capability, for suites whose subject is mount-handling code
## (dm-help-steps: umount_kill.sh, unmount-tree). Without it the
## container can neither mount nor create a user namespace, so those
## assertions cannot run at all.
##
## Both halves are required and neither alone suffices: CAP_SYS_ADMIN
## carries the privilege, and Docker's default AppArmor profile denies
## mount(2) regardless of capabilities. Measured on debian:trixie-slim
## -- default, '--cap-add=SYS_ADMIN' alone and
## '--security-opt=apparmor=unconfined' alone all fail; the pair
## succeeds. Narrower than '--privileged', which also grants every
## other capability plus raw device access.
##
## Scope: the fork-PR guard below means only same-repo code reaches
## this job, so no untrusted contributor payload runs with it.
options: --cap-add=SYS_ADMIN --security-opt=apparmor=unconfined
timeout-minutes: 20
## Fork-PR guard: forked PRs need maintainer review before consuming
## CI time. Same guard as the other reusables (agents/security.md).
## CI runs only where we enabled it. In a CALLED reusable the vars
## context resolves against the CALLER's repository and org, so this
## one condition gates every consumer -- upstream and forks skip with
## no runner allocated and the run stays green, rather than taking a
## red X for a lane they never opted into. A fork that WANTS the lane
## sets the same variable in its own repo; no patch to our files.
##
## ANDed with the fork-PR guard, which stays.
if: >-
vars.CI_ENABLED_ORG_AI_ASSISTED == 'true'
&& (github.event.pull_request.head.repo.full_name == github.repository || github.event_name != 'pull_request')
permissions:
contents: read
env:
COMPONENT: ${{ github.event.repository.name }}
CATEGORIES: ${{ inputs.categories }}
steps:
- name: Install checkout + config dependencies (apt only)
run: |
apt-get update --quiet
apt-get install --yes --no-install-recommends \
ca-certificates file git rsync yq
git config --global --add safe.directory '*'
- name: Checkout component (code under test)
## https://github.com/actions/checkout/releases/tag/v6.0.2
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
path: component
persist-credentials: false
- name: Checkout dist-ai (test suites)
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: org-ai-assisted/dist-ai
ref: ${{ inputs.dist-ai-ref }}
path: dist-ai
persist-credentials: false
- name: Load per-repo config (.github/dm-consumer.yml)
id: cfg
## Runtime read of the caller's per-repo config (reusable-coverity.yml
## pattern). All logic lives in the committed dist-ai/ci script, not
## inline here (no embedded shell scripts in CI files).
run: dist-ai/ci/dist-ai-tests-ci-config.sh component/.github/dm-consumer.yml
## Opt-in per repo (dm-consumer.yml 'submodules: true'). Some suites assert
## on files that live in a SUBMODULE -- derivative-maker's
## dm-grub-smbios-tests compares the disk-side SMBIOS reader in
## vm-config-dist against the ISO-side copy in the main tree. Without them
## the suite cannot resolve its subject and exits 77, which correctly fails
## the run as an unauthorized skip. Must run AFTER the config step, which
## is what reads the opt-in.
- name: Initialize component submodules
if: steps.cfg.outputs.submodules == 'true'
working-directory: component
env:
REPOSITORY_OWNER: ${{ github.repository_owner }}
run: |
## A component may pin submodule commits that exist only in THIS org's
## forks while .gitmodules still points at upstream, so a plain init
## cannot find them. That mapping belongs to the component; run its own
## helper when it ships one, exactly as its build lane does.
if [ -x ./ci/configure-fork-mirror ]; then
./ci/configure-fork-mirror "${REPOSITORY_OWNER}" "${REPOSITORY_OWNER}"
fi
## Not --recursive: the suites assert on the component's OWN
## submodules, and recursing multiplies the checkout for no coverage.
git submodule update --init
- name: Checkout helper-scripts (for suites that drive its tools)
if: steps.cfg.outputs.helper_scripts == 'true'
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: org-ai-assisted/helper-scripts
ref: master
path: helper-scripts
persist-credentials: false
- name: Provide helper-scripts runtime at the system path
if: steps.cfg.outputs.helper_scripts == 'true'
## Some tools source helper-scripts via an absolute /usr/libexec path
## (genmkfile make-helper, git-meld). Logic lives in the committed
## dist-ai/ci script, not inline (no embedded shell in CI files).
run: dist-ai/ci/dist-ai-tests-ci-hs-runtime.sh "${GITHUB_WORKSPACE}/helper-scripts"
- name: Checkout terminal-poc-corpus (for suites that drive the PoC corpus)
if: steps.cfg.outputs.terminal_poc_corpus == 'true'
## The adversarial PoC corpus lives in its own repo, so a suite that drives
## it (terminal-poc-corpus-tests) cannot resolve one here otherwise: it
## exits 77, which is reported SKIP and counted green -- the gate then looks
## wired when it never ran. Opt-in per repo via .github/dm-consumer.yml
## (dist-ai-tests.terminal-poc-corpus: true) so the clone is not imposed on
## every consumer. Sibling dir, matching component/ and dist-ai/ above.
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: secure-terminal/terminal-poc-corpus
ref: master
path: terminal-poc-corpus
persist-credentials: false
- name: Install test dependencies (apt only)
env:
APT_PACKAGES: ${{ steps.cfg.outputs.apt_packages }}
run: |
# shellcheck disable=SC2086 # APT_PACKAGES is an intentional word list
# (single '#', not the house '##': shellcheck only recognizes a
# directive written with one hash, so a '##' form is silently inert
# and actionlint's shellcheck pass reports SC2086 anyway.)
apt-get install --yes --no-install-recommends ${APT_PACKAGES}
- name: Run dist-ai suites for this component
env:
HS_ARG: ${{ steps.cfg.outputs.hs_arg }}
SKIP_ARGS: ${{ steps.cfg.outputs.skip_args }}
## Suites this repo has authorized to exit 77 without failing the run.
## An unauthorized skip is a FAILURE: a suite that could not resolve its
## target must not report the same green exit 0 as one that ran.
ALLOW_SKIP_ARGS: ${{ steps.cfg.outputs.allow_skip_args }}
## dist-ai-tests-all's wire() resolves the corpus from this; harmless when
## the checkout was not requested (the suite then SKIPs as before).
TERMINAL_POC_CORPUS_REPO: ${{ steps.cfg.outputs.terminal_poc_corpus == 'true' && format('{0}/terminal-poc-corpus', github.workspace) || '' }}
run: |
# shellcheck disable=SC2086 # CATEGORIES / HS_ARG / SKIP_ARGS / ALLOW_SKIP_ARGS are intentional flag lists
# Must live INSIDE the run: script, with a single '#'. As a YAML
# comment above 'run:' it never reached shellcheck at all, so the
# suppression looked deliberate while doing nothing.
dist-ai/usr/bin/dist-ai-tests-all ${CATEGORIES} \
--component "${COMPONENT}" \
--component-root "${GITHUB_WORKSPACE}/component" \
--timeout-core 600 \
${HS_ARG} \
${SKIP_ARGS} \
${ALLOW_SKIP_ARGS}
- name: Emit step summary
if: always()
## Per-suite detail is printed inline by dist-ai-tests-all on a
## FAIL/TIMEOUT; this panel surfaces the headline result,
## component, and categories in the PR Checks tab. job.status is
## routed through env: per the org-wide convention (CodeQL flags
## inline ${{ }} in run:).
env:
JOB_STATUS: ${{ job.status }}
run: |
dist-ai/usr/bin/step-summary-emit \
--tool 'dist-ai tests' \
--column-header field \
--row "outcome=${JOB_STATUS}" \
--row "component=${COMPONENT}" \
--row "categories=${CATEGORIES}"