Skip to content

Merge pull request #7 from intercreate/ci/release-provenance-guard #49

Merge pull request #7 from intercreate/ci/release-provenance-guard

Merge pull request #7 from intercreate/ci/release-provenance-guard #49

Workflow file for this run

name: Build
on:
push:
branches: [main]
tags: ['*']
pull_request:
workflow_dispatch:
permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
check-script:
name: Lint + type-check + test the fixture collector + release validator
runs-on: ubuntu-24.04
env:
UV_PYTHON: '3.13' # match the script's requires-python and the build leg
steps:
- uses: actions/checkout@v6
with:
persist-credentials: false
- uses: astral-sh/setup-uv@v8.1.0
- name: Ruff, mypy (strict), pytest
working-directory: .github/scripts
run: |
uvx ruff check .
uvx ruff format --check .
uvx --with pytest mypy --strict \
collect_fixtures.py test_collect_fixtures.py \
validate_release.py test_validate_release.py
uvx pytest
build:
name: Build ${{ matrix.leg }} fixtures
needs: check-script
strategy:
fail-fast: false
matrix:
include:
# Host toolchain. native_sim is 32-bit (the 64-bit PTY UART RX is
# broken on v4.4.0), so it needs gcc-multilib.
- leg: native_sim
toolchains: ""
platforms: native_sim
# Zephyr SDK ARM toolchain: the runnable QEMU fixtures (qemu_cortex_m0
# DFU, mps2/an385 all-groups + shell + serial recovery) and the
# build-only hardware images.
- leg: arm
toolchains: arm-zephyr-eabi
platforms: qemu_cortex_m0 mps2/an385 nrf52840dk/nrf52840
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
with:
path: working_directory
persist-credentials: false
- name: Install 32-bit host toolchain for native_sim
if: matrix.leg == 'native_sim'
run: sudo apt-get update && sudo apt-get install -y gcc-multilib g++-multilib
- uses: actions/setup-python@v6
with:
python-version: '3.13'
- uses: zephyrproject-rtos/action-zephyr-setup@v1
with:
app-path: working_directory
toolchains: ${{ matrix.toolchains }}
ccache-cache-key: ${{ matrix.leg }}
- uses: astral-sh/setup-uv@v8.1.0
- name: Build fixtures (Twister, all configs for this leg)
working-directory: working_directory
run: |
args=""
for p in ${{ matrix.platforms }}; do args="$args -p $p"; done
west twister -T apps --build-only --inline-logs -O twister-out $args
- name: Collect fixtures with canonical names and a manifest
working-directory: working_directory
run: |
# Canonical names + manifest are produced by a typed, unit-tested
# script (.github/scripts/); the check-script job gates it on ruff +
# mypy --strict + pytest. west stays here: it must run in the workspace.
ver=$(west list zephyr --format='{revision}'); ver=${ver#v}
uv run .github/scripts/collect_fixtures.py \
--git-sha "$GITHUB_SHA" --zephyr-version "$ver" \
--leg "${{ matrix.leg }}" --twister-out twister-out --out-dir fixtures
- uses: actions/upload-artifact@v7
with:
name: fixtures-${{ matrix.leg }}
path: working_directory/fixtures/*
if-no-files-found: error
- name: Upload Twister logs on failure
if: failure()
uses: actions/upload-artifact@v7
with:
name: twister-logs-${{ matrix.leg }}
path: working_directory/twister-out/**/build.log
release:
name: Publish per-commit release (newest is the repo 'latest')
needs: build
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
runs-on: ubuntu-24.04
permissions:
contents: write
steps:
# Checkout is for the release validator script only; the assets come from
# the build artifacts, not the tree.
- uses: actions/checkout@v6
with:
persist-credentials: false
- uses: actions/download-artifact@v8
with:
path: artifacts
merge-multiple: true
- name: Merge per-leg manifests
working-directory: artifacts
run: |
jq -s 'add | sort_by(.target,.config)' manifest-*.json > manifest.json
rm -f manifest-*.json
- name: Checksums
working-directory: artifacts
run: sha256sum * > SHA256SUMS
- uses: astral-sh/setup-uv@v8.1.0
# Provenance + manifest guard (issue #4): fail before publishing if the
# gathered assets mix build SHAs or disagree with manifest.json, so a
# release can never silently accumulate stale, multi-SHA, manifest-less
# assets the way the retired rolling 'latest' tag did.
- name: Validate release provenance + manifest
env:
UV_PYTHON: '3.13'
run: |
uv run .github/scripts/validate_release.py \
--manifest artifacts/manifest.json --assets-dir artifacts \
--git-sha "$GITHUB_SHA"
- id: sha
run: echo "short=${GITHUB_SHA::8}" >> "$GITHUB_OUTPUT"
# Permanent, immutable per-commit release (build history), tagged by SHA.
# make_latest:true repoints GitHub's own /releases/latest at this build, so
# 'latest' is a symlink to the newest release (stable download URL) rather
# than a release that accumulates a copy of every build's assets.
- uses: softprops/action-gh-release@v3
with:
tag_name: ${{ steps.sha.outputs.short }}
name: SMP Server Fixtures ${{ steps.sha.outputs.short }}
body: Built from ${{ github.sha }}.
make_latest: true
target_commitish: ${{ github.sha }}
files: artifacts/*