Files
forgefirm/.github/workflows/forgetest-ci.yml
T
ScottW514 b0fa4ccaf5 A release publishes the source of the software it installs
The release build merges kas/source-bundle.yml, which turns on the Yocto
archiver: the upstream source of each recipe as upstream publishes it, the
patches with their series file, and the recipe with its includes. The
overlay adds tasks only, so the image manifest is unchanged and an
acceptance result still applies; proven on the build host, where the
archiver build and a plain rebuild of the same tree give the same
content_sha256.

scripts/source-bundle.py packs forgefirm-source-v<version>.tar.gz: the
archives, both license manifests, the license texts, the ForgeFIRM layers,
the kas configuration, the layer revisions and the build identity of the
image. What the bundle must hold comes from the image, not from a list in
the script: every recipe of license.manifest and image_license.manifest
whose license is in the include list must have an archive, or the release
stops with the recipe named. release.sh attaches the bundle and covers it
with sha256sums.txt; FORGEFIRM_SOURCE_SKIP=1 bypasses deliberately.

On the build host: 68 of the image's 111 recipes carry source, 313.7 MiB,
under the 2 GiB limit of a release asset.

No acceptance catalog consequence: the change is release tooling on the
build host and puts no file and no behavior on the machine. The host-side
proof is forgetest/tests/test_source_bundle.py, which holds the license
decision, the choice of archive and the refusal.
2026-09-07 09:49:18 -04:00

91 lines
3.4 KiB
YAML

# forgetest: the release acceptance tool's host-side proof.
#
# - unit tests: campaign rules, fingerprints, artifact build/verify (the
# release gate's decision, including the negative fixtures), runner +
# HTTP API end to end with a fake catalog and a fake bench tool, the
# suites replayed on the machine's own log lines, and the check that
# every log phrase the cloud suite greps for is one the pinned cloud
# app can log (it reads the app sources from the manifest cache)
# - the source bundle of a release: which recipe of the image needs
# source, which archive answers for it, and the refusal that stops a
# release with source missing
# - shared UI files: theme.css and the vendored Bootstrap the page
# carries are byte-identical to forgectrl's at its pinned revision
# - coverage lint: every source path of every component pinned by the
# recipes must be selected by some catalog test's coverage globs (the
# tree manifest is generated from the pins with git - no Yocto build);
# enforced: an uncovered path fails the job (https://docs.forgefirm.org/developers/acceptance/).
name: forgetest-ci
on:
push:
paths:
- 'forgetest/**'
- 'scripts/acceptance-gate.py'
- 'scripts/manifest-from-tree.py'
- 'scripts/source-bundle.py'
- 'kas/source-bundle.yml'
- 'meta-forgefirm/recipes-forgefirm/**'
- '.github/workflows/forgetest-ci.yml'
pull_request:
workflow_dispatch:
jobs:
test:
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- name: Checkout forgefirm
uses: actions/checkout@v4
with:
path: forgefirm
- name: Checkout meta-openglow (sibling)
uses: actions/checkout@v4
with:
repository: openglow-org/meta-openglow
ref: scarthgap
path: meta-openglow
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Tree manifest from the recipe pins (also fetches the pinned app sources the needle check reads)
working-directory: forgefirm
run: python scripts/manifest-from-tree.py --out tree-manifest.json
- name: Unit tests
working-directory: forgefirm/forgetest
# -B: no bytecode caches under the package directory (the recipe's fetch
# checksum would otherwise move without a source change)
run: python -B -m unittest discover -s tests -v
- name: No undefined names (the live drills never execute on the host)
working-directory: forgefirm/forgetest
run: |
pip install pyflakes
if python -B -m pyflakes forgetest tests | grep -E "undefined name"; then exit 1; fi
- name: Shared UI files match forgectrl at its pinned revision
working-directory: forgefirm
run: python scripts/check-ui-vendor.py
- name: Coverage lint (enforced)
working-directory: forgefirm/forgetest
run: python -B -m forgetest.coverage --manifest ../tree-manifest.json --enforce | tee "$GITHUB_STEP_SUMMARY"
- name: Gate self-check on the tree manifest
working-directory: forgefirm
run: |
# The gate must load the catalog and refuse a missing/unauthorized
# artifact cleanly (exit 1/2, never a traceback).
set +e
echo '{}' > empty.json
python scripts/acceptance-gate.py empty.json tree-manifest.json --quiet
rc=$?
set -e
test "$rc" -eq 1