-
Notifications
You must be signed in to change notification settings - Fork 33
433 lines (428 loc) · 19.2 KB
/
Copy pathtest_and_docs.yml
File metadata and controls
433 lines (428 loc) · 19.2 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
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
# *******************************************************************************
# Copyright (c) 2025 Contributors to the Eclipse Foundation
#
# See the NOTICE file(s) distributed with this work for additional
# information regarding copyright ownership.
#
# This program and the accompanying materials are made available under the
# terms of the Apache License Version 2.0 which is available at
# https://www.apache.org/licenses/LICENSE-2.0
#
# SPDX-License-Identifier: Apache-2.0
# *******************************************************************************
# Two-stage quality workflow aligned with DR-008 Option 4.
#
# Stage 1 (stage1_integration): build the integrated platform, run Feature
# Integration Tests, and publish the resolved dependency set (MODULE.bazel.lock
# + generated git_override files) as the stage1-resolved-deps artifact.
#
# prepare_matrix: derive the Stage 2 module list dynamically from known_good.json
# (target_sw group) so it is never hardcoded.
#
# Stage 2 (stage2_module_validation): per-module matrix. For each module: check it
# out at its known_good commit, overwrite its MODULE.bazel with the Stage-1
# resolved dependency set (downloaded artifact, via ResolvedDependencies), and run
# the module's unit tests + coverage *inside the module* (bazel root //...). This
# is the DR-008 Option 4 "overwrite deps from resolved deps and execute UTs +
# coverage directly in the modules" flow. Injection is ephemeral (CI only).
#
# Aggregate (aggregate): downloads all Stage 2 reports, renders a consolidated
# quality report to the GitHub Step Summary, and (on tags) creates the
# combined test-report ZIP for the GitHub Release.
#
# Docs / docs-deploy: unchanged from the previous workflow; depends on
# stage1_integration which builds and uploads the pages artifact.
name: Code Quality & Documentation
permissions:
contents: write
pages: write
pull-requests: write
id-token: write
on:
pull_request_target: # Allow forks to access secrets
types: [opened, reopened, synchronize]
push:
branches:
- main
- Subramanian-K812_update_test_workflow_dr8 # TEMP: remove after CI verified
merge_group:
types: [checks_requested]
release:
types: [created]
workflow_dispatch: # Manual trigger — used to test this workflow from a feature branch
# (pull_request_target always runs the base-branch workflow, so workflow_dispatch
# is the only way to exercise the new structure before it merges to main)
# Do not flood CI with unneeded previous runs in PR
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
cancel-in-progress: ${{ github.ref_name != 'main' && !startsWith(github.ref_name, 'release/') }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
jobs:
# ---------------------------------------------------------------------------
# Stage 1 — Integration-Scoped
# Builds the integrated platform and runs Feature Integration Tests.
# Publishes the Bazel-resolved dependency set (MODULE.bazel.lock +
# generated score_modules_*.MODULE.bazel) as the stage1-resolved-deps
# artifact, satisfying the "resolve complete dependency set incl. transitive
# deps" requirement of DR-008 Option 4.
# Documentation is built in a separate parallel job (docs_build) so that
# a Sphinx warning does not block Stage 2 validation.
# ---------------------------------------------------------------------------
stage1_integration:
name: "Stage 1 — Platform Build & Feature Integration Tests"
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
steps:
- name: Clean disk space
uses: eclipse-score/more-disk-space@v1.1
with:
level: 4
- name: Setup Bazel
uses: bazel-contrib/setup-bazel@0.18.0
with:
bazelisk-cache: true
disk-cache: ${{ github.workflow }}-stage1
repository-cache: true
cache-save: ${{ github.event_name == 'push' }}
- name: Set up Python 3
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Checkout repository (pull_request_target via workflow_call)
if: ${{ github.event_name == 'pull_request_target' }}
uses: actions/checkout@v4
with:
ref: ${{ github.head_ref || github.event.pull_request.head.ref || github.ref }}
repository: ${{ github.event.pull_request.head.repo.full_name || github.repository }}
- name: Checkout repository
if: ${{ github.event_name != 'pull_request_target' }}
uses: actions/checkout@v4
- name: Execute Feature Integration Tests
run: |
bazel test --lockfile_mode=error --config=linux-x86_64 //feature_integration_tests/test_cases:fit
- name: Export resolved dependency manifest
if: always()
run: |
mkdir -p artifacts/stage1-resolved-deps
# Resolve the full graph (registry versions) against the committed lock, then merge
# with ref_int's own override directives (git_override for score_*/trlc/..., plus
# any single_version_override) into the single Stage 1 -> Stage 2 handoff manifest.
bazel mod graph --output=json --lockfile_mode=error > resolved_graph.json
python scripts/known_good/resolved_dependencies.py \
--mod-graph resolved_graph.json \
--export artifacts/stage1-resolved-deps/resolved_versions.json
cp MODULE.bazel.lock artifacts/stage1-resolved-deps/ # evidence of full resolution
- name: Upload resolved dependency set artifact
if: always()
uses: actions/upload-artifact@v4.4.0
with:
name: stage1-resolved-deps
path: artifacts/stage1-resolved-deps/
retention-days: 14
if-no-files-found: warn
# ---------------------------------------------------------------------------
# Documentation build — runs in parallel with Stage 1 so Sphinx warnings
# never block Stage 2. docs-deploy depends on this job, not stage1_integration.
# ---------------------------------------------------------------------------
docs_build:
name: "Build Documentation"
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
steps:
- name: Clean disk space
uses: eclipse-score/more-disk-space@v1
- name: Setup Bazel
uses: bazel-contrib/setup-bazel@0.18.0
with:
bazelisk-cache: true
disk-cache: ${{ github.workflow }}-docs
repository-cache: true
cache-save: ${{ github.event_name == 'push' }}
- name: Set up Python 3
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Checkout repository (pull_request_target)
if: ${{ github.event_name == 'pull_request_target' }}
uses: actions/checkout@v4
with:
ref: ${{ github.head_ref || github.event.pull_request.head.ref || github.ref }}
repository: ${{ github.event.pull_request.head.repo.full_name || github.repository }}
- name: Checkout repository
if: ${{ github.event_name != 'pull_request_target' }}
uses: actions/checkout@v4
- name: Install Graphviz
uses: eclipse-score/apt-install@main
with:
packages: graphviz
cache: false
- name: Build documentation
run: |
bazel --output_base="/home/runner/.cache/bazel/output_base" run \
--lockfile_mode=error \
--repo_contents_cache="/home/runner/.cache/bazel/repo_contents" \
--repository_cache="/home/runner/.cache/bazel/repo" \
--disk_cache="/home/runner/.cache/bazel/disk" \
//:docs_combo_experimental -- \
--github_user=${{ github.repository_owner }} \
--github_repo=${{ github.event.repository.name }}
CURRENT=$(realpath .)
bazel run //scripts/tooling -- misc html_report --output ${CURRENT}/_build/status_dashboard.html
tar -cf github-pages.tar _build
- name: Upload documentation artifact
uses: actions/upload-artifact@v4.4.0
with:
name: github-pages-${{ github.event.pull_request.head.sha || github.sha }}
path: github-pages.tar
retention-days: 3
if-no-files-found: error
# ---------------------------------------------------------------------------
# Prepare the Stage 2 matrix dynamically from known_good.json's target_sw group.
# The module list is NEVER hardcoded in this workflow (reviewer R1: "we need to
# take it from know_good always"). Each matrix entry carries {name, repo, slug,
# commit, branch} so Stage 2 can check the module out at its resolved commit.
# ---------------------------------------------------------------------------
prepare_matrix:
name: "Prepare Stage 2 module matrix"
needs: stage1_integration
runs-on: ubuntu-latest
outputs:
modules: ${{ steps.list.outputs.modules }}
steps:
- name: Checkout repository (pull_request_target)
if: ${{ github.event_name == 'pull_request_target' }}
uses: actions/checkout@v4
with:
ref: ${{ github.head_ref || github.event.pull_request.head.ref || github.ref }}
repository: ${{ github.event.pull_request.head.repo.full_name || github.repository }}
- name: Checkout repository
if: ${{ github.event_name != 'pull_request_target' }}
uses: actions/checkout@v4
- name: Set up Python 3
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: List target_sw modules from known_good.json
id: list
run: |
echo "modules=$(python scripts/known_good/list_modules.py --group target_sw)" >> "$GITHUB_OUTPUT"
# ---------------------------------------------------------------------------
# Stage 2 — Module-Scoped (DR-008 Option 4)
# For each target_sw module: check the module out at its known_good commit,
# overwrite its MODULE.bazel with the dependency set ref_int RESOLVED in Stage 1
# (downloaded stage1-resolved-deps artifact), and run the module's own unit tests
# + coverage *inside the module* (bazel root //...), not through ref_int's graph.
# This is the "overwrite deps from resolved deps in ref_int and execute UTs and
# coverage directly in the modules" flow the reviewer described (R2/R3/R4).
#
# The injection is ephemeral (CI checkout only) — released module sources are
# never modified. Each matrix job is isolated; fail-fast: false ensures one
# module's failure does not hide the results of others.
# ---------------------------------------------------------------------------
stage2_module_validation:
name: "Stage 2 — Module UT & Coverage (${{ matrix.module.name }})"
needs: [stage1_integration, prepare_matrix]
strategy:
fail-fast: false
matrix:
module: ${{ fromJSON(needs.prepare_matrix.outputs.modules) }}
runs-on: ubuntu-latest
steps:
- name: Clean disk space
uses: eclipse-score/more-disk-space@v1
- name: Setup Bazel
uses: bazel-contrib/setup-bazel@0.18.0
with:
bazelisk-cache: true
disk-cache: ${{ github.workflow }}-stage2-${{ matrix.module.name }}
repository-cache: true
cache-save: ${{ github.event_name == 'push' }}
- name: Set up Python 3
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install lcov
run: |
sudo apt-get update
sudo apt-get install -y lcov
# ref_int checkout — provides the scripts (quality_runners.py, ResolvedDependencies).
- name: Checkout reference_integration (pull_request_target)
if: ${{ github.event_name == 'pull_request_target' }}
uses: actions/checkout@v4
with:
ref: ${{ github.head_ref || github.event.pull_request.head.ref || github.ref }}
repository: ${{ github.event.pull_request.head.repo.full_name || github.repository }}
- name: Checkout reference_integration
if: ${{ github.event_name != 'pull_request_target' }}
uses: actions/checkout@v4
# The module under test, checked out at its Stage-1 known_good commit (R4).
- name: Checkout module under test
uses: actions/checkout@v4
with:
repository: ${{ matrix.module.slug }}
ref: ${{ matrix.module.commit }}
path: _module
# Consume the Stage-1 resolved dependency set (R2).
- name: Download Stage 1 resolved dependency set
uses: actions/download-artifact@v4.1.8
with:
name: stage1-resolved-deps
path: _resolved_deps/
- name: Execute Unit Tests with Coverage Analysis (in module context)
run: |
python ./scripts/quality_runners.py \
--modules-to-test ${{ matrix.module.name }} \
--module-dir _module \
--resolved-deps _resolved_deps
- name: Upload module quality report
if: always()
uses: actions/upload-artifact@v4.4.0
with:
name: stage2-report-${{ matrix.module.name }}
path: docs/verification_report/
retention-days: 14
if-no-files-found: warn
- name: Upload module test logs and coverage
if: always()
uses: actions/upload-artifact@v4.4.0
with:
name: stage2-testlogs-${{ matrix.module.name }}
path: |
_module/bazel-testlogs/
artifacts/coverage/
retention-days: 14
if-no-files-found: warn
# ---------------------------------------------------------------------------
# Aggregate — consolidate Stage 1 + Stage 2 results into one quality report.
# Also handles the release-tag test-report ZIP (formerly in test_and_docs).
# ---------------------------------------------------------------------------
aggregate:
name: "Aggregate Quality Report"
needs: [stage1_integration, stage2_module_validation]
if: always()
runs-on: ubuntu-latest
steps:
- name: Checkout repository (pull_request_target via workflow_call)
if: ${{ github.event_name == 'pull_request_target' }}
uses: actions/checkout@v4
with:
ref: ${{ github.head_ref || github.event.pull_request.head.ref || github.ref }}
repository: ${{ github.event.pull_request.head.repo.full_name || github.repository }}
- name: Checkout repository
if: ${{ github.event_name != 'pull_request_target' }}
uses: actions/checkout@v4
- name: Set up Python 3
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Download Stage 2 quality reports
uses: actions/download-artifact@v4.1.8
with:
pattern: stage2-report-*
path: _stage2_reports/
- name: Create archive of test reports
if: github.ref_type == 'tag'
run: |
mkdir -p artifacts/test-reports
find _stage2_reports -name 'test.xml' -print0 | \
xargs -0 -I{} cp --parents {} artifacts/test-reports/ 2>/dev/null || true
zip -r ${{ github.event.repository.name }}_test_reports.zip artifacts/test-reports/
shell: bash
- name: Upload release asset (attach ZIP to GitHub Release)
uses: softprops/action-gh-release@v2.5.0
if: github.ref_type == 'tag'
with:
files: ${{ github.event.repository.name }}_test_reports.zip
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Publish consolidated quality report
if: always()
run: |
python3 scripts/aggregate_quality_report.py \
--stage1-result "${{ needs.stage1_integration.result }}" \
--stage2-result "${{ needs.stage2_module_validation.result }}" \
--stage2-dir "_stage2_reports/" \
>> "$GITHUB_STEP_SUMMARY"
# ---------------------------------------------------------------------------
# Docs deploy — depends on docs_build (separate parallel job) which uploads
# the github-pages artifact.
# ---------------------------------------------------------------------------
docs-deploy:
name: Deploy Documentation to GitHub Pages
runs-on: ${{ vars.REPO_RUNNER_LABELS && fromJSON(vars.REPO_RUNNER_LABELS) || 'ubuntu-latest' }}
needs: docs_build
environment:
name: github-pages
permissions:
pages: write
id-token: write
contents: write
pull-requests: write
steps:
- name: Ensure gh-pages branch exists with initial files
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
REPO: ${{ github.repository }}
run: |
set -e
if ! git ls-remote --exit-code --heads "https://x-access-token:${GH_TOKEN}@github.com/${REPO}.git" gh-pages; then
echo "gh-pages branch does not exist. Creating it..."
git clone --depth=1 "https://x-access-token:${GH_TOKEN}@github.com/${REPO}.git" repo
cd repo
git fetch origin main --depth=1
AUTHOR_NAME=$(git log origin/main -1 --pretty=format:'%an')
AUTHOR_EMAIL=$(git log origin/main -1 --pretty=format:'%ae')
git config user.name "$AUTHOR_NAME"
git config user.email "$AUTHOR_EMAIL"
echo "Using commit identity: $AUTHOR_NAME <$AUTHOR_EMAIL>"
git checkout --orphan gh-pages
git rm -rf . || true
REPO_NAME=$(basename "${REPO}")
OWNER_NAME="${REPO%%/*}"
touch versions.json
echo "[" > versions.json
echo " {" >> versions.json
echo " \"version\": \"main\"," >> versions.json
echo " \"url\": \"https://${OWNER_NAME}.github.io/${REPO_NAME}/main/\"" >> versions.json
echo " }" >> versions.json
echo "]" >> versions.json
touch index.html
echo '<!DOCTYPE html>' > index.html
echo '<html lang="en">' >> index.html
echo '<head>' >> index.html
echo ' <meta charset="UTF-8">' >> index.html
echo ' <meta http-equiv="refresh" content="0; URL=main/">' >> index.html
echo ' <title>Redirecting...</title>' >> index.html
echo '</head>' >> index.html
echo '<body>' >> index.html
echo ' <p>If you are not redirected, <a href="main/">click here</a>.</p>' >> index.html
echo '</body>' >> index.html
echo '</html>' >> index.html
touch .nojekyll
git add versions.json index.html .nojekyll
git commit -m "Initialize gh-pages branch with versions.json and index.html"
git push origin gh-pages
cd ..
rm -rf repo
else
echo "gh-pages branch exists. Skipping creation."
fi
- name: Checkout repository
uses: actions/checkout@v4.2.2
- name: Download documentation artifact
uses: actions/download-artifact@v4.1.8
with:
name: github-pages-${{ github.event.pull_request.head.sha || github.sha }}
- name: Untar documentation artifact
run: mkdir -p extracted_docs && tar -xf github-pages.tar -C extracted_docs
- name: Deploy 🚀
id: pages-deployment
uses: eclipse-score/cicd-workflows/.github/actions/deploy-versioned-pages@main
with:
source_folder: extracted_docs/_build
deployment_type: workflow