name: CI
on:
push:
branches: [main]
pull_request:
permissions:
contents: read
concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
env:
CARGO_INCREMENTAL: "0"
jobs:
lint:
name: Rust lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 - uses: dtolnay/rust-toolchain@d1031067263f94b142dd6c0ce24c5eb9d02d52a0 with:
toolchain: stable
components: clippy, rustfmt
targets: wasm32-unknown-unknown
- uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 with:
prefix-key: oci-zero-v2
shared-key: ci-lint
cache-bin: false
- run: cargo fmt --all --check
- run: cargo clippy --workspace --exclude oci-zero-no-std-extract --exclude oci-zero-matter-qr --all-targets --all-features -- -D warnings
- name: WebAssembly and Chrome extension checks
run: |
cargo check -p oci-zero-web --target wasm32-unknown-unknown
node --check web/app.js
node --check web/background.js
node --check web/build-flash.mjs
node --check web/flash.js
node --check web/playwright.config.mjs
node --check web/scan-worker.js
node --check web/tests/browser.spec.mjs
node --check web/tests/firmware-fixture.mjs
node --check web/tests/flash.spec.mjs
node --check web/tests/server.mjs
python3 -m json.tool web/manifest.json > /dev/null
sh -n tools/build-firmware-artifact.sh
tools/test-build-firmware-artifact.sh
# bash, not sh: the walk over a nested index recurses and uses arrays.
bash -n tools/publish-static-registry.sh
unit:
name: Rust tests
runs-on: ubuntu-latest
env:
CARGO_PROFILE_DEV_PANIC: unwind
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 - uses: dtolnay/rust-toolchain@d1031067263f94b142dd6c0ce24c5eb9d02d52a0 with:
toolchain: stable
- uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 with:
prefix-key: oci-zero-v2
shared-key: ci-unit
cache-bin: false
- run: cargo test --workspace --exclude oci-zero-no-std-extract --exclude oci-zero-matter-qr --all-features
onboarding-lint:
name: Matter onboarding lint
runs-on: ubuntu-latest
env:
CARGO_PROFILE_DEV_PANIC: unwind
CARGO_PROFILE_DEV_DEBUG: "0"
CARGO_PROFILE_TEST_DEBUG: "0"
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 - uses: dtolnay/rust-toolchain@d1031067263f94b142dd6c0ce24c5eb9d02d52a0 with:
toolchain: stable
components: clippy
- uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 with:
prefix-key: oci-zero-v2
shared-key: ci-onboarding-lint
cache-bin: false
- run: cargo clippy -p oci-zero-matter-qr --all-targets --all-features -- -D warnings
- run: cargo doc -p oci-zero-matter-qr --no-deps --all-features
env:
RUSTDOCFLAGS: -D warnings
onboarding:
name: Matter onboarding
runs-on: ubuntu-latest
env:
CARGO_PROFILE_DEV_PANIC: unwind
CARGO_PROFILE_DEV_DEBUG: "0"
CARGO_PROFILE_TEST_DEBUG: "0"
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 - uses: dtolnay/rust-toolchain@d1031067263f94b142dd6c0ce24c5eb9d02d52a0 with:
toolchain: stable
- uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 with:
prefix-key: oci-zero-v2
shared-key: ci-onboarding
cache-bin: false
- run: cargo test -p oci-zero-matter-qr --all-features
- name: Committed Matter onboarding data is current
run: |
cargo run -q -p oci-zero-matter-qr
git diff --exit-code -- examples/esp32c3-ota/onboarding-qr.svg \
examples/esp32c3-ota/onboarding-qr.txt \
examples/esp32c3-ota/onboarding.txt
native:
name: Native TLS smoke tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 - uses: dtolnay/rust-toolchain@d1031067263f94b142dd6c0ce24c5eb9d02d52a0 with:
toolchain: stable
components: clippy
- uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 with:
prefix-key: oci-zero-v2
shared-key: ci-native
cache-bin: false
- run: cargo clippy --release -p oci-zero-no-std-extract -- -D warnings
- name: Public OCI artifact metadata smoke tests
run: cargo test --release --test metadata_smoke inspects_public_registry_fixtures -- --ignored --nocapture
- name: no_std MbedTLS streamed extraction smoke test
run: |
cargo build --release -p oci-zero-no-std-extract
target/release/oci-zero-no-std-extract \
'https://install.datadoghq.com/v2/agent-package/blobs/sha256:bc219703080f03ad836d51bf7f72cc3ced34f5ba440a49f450d6a5dea98ceff4' \
application_monitoring.yaml.example > /dev/null
conformance:
name: Zstd conformance
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 - uses: dtolnay/rust-toolchain@d1031067263f94b142dd6c0ce24c5eb9d02d52a0 with:
toolchain: stable
- uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 with:
prefix-key: oci-zero-v2
shared-key: ci-conformance
cache-bin: false
- name: Official zstd decodeCorpus conformance
run: |
curl -fsSLo /tmp/zstd-1.5.7.tar.gz https://github.com/facebook/zstd/releases/download/v1.5.7/zstd-1.5.7.tar.gz
echo "eb33e51f49a15e023950cd7825ca74a4a2b43db8354825ac24fc1b7ee09e6fa3 /tmp/zstd-1.5.7.tar.gz" | sha256sum --check
tar -xzf /tmp/zstd-1.5.7.tar.gz -C /tmp
make -C /tmp/zstd-1.5.7/tests decodecorpus
DECODECORPUS=/tmp/zstd-1.5.7/tests/decodecorpus cargo test -p zstd-zero --test conformance decodes_official_decodecorpus_frames -- --ignored
docs:
name: Rust documentation
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 - uses: dtolnay/rust-toolchain@d1031067263f94b142dd6c0ce24c5eb9d02d52a0 with:
toolchain: stable
- uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 with:
prefix-key: oci-zero-v2
shared-key: ci-docs
cache-bin: false
- run: cargo doc --workspace --exclude oci-zero-no-std-extract --exclude oci-zero-matter-qr --no-deps --all-features
env:
RUSTDOCFLAGS: -D warnings
package:
name: Package verification
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 - uses: dtolnay/rust-toolchain@d1031067263f94b142dd6c0ce24c5eb9d02d52a0 with:
toolchain: stable
- uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 with:
prefix-key: oci-zero-v2
shared-key: ci-package
cache-bin: false
- name: Verify delegated Cargo publisher
run: python3 -m unittest discover -s tools -p test_runnerless_cargo_publish.py
- name: Package published crates
run: cargo package --locked -p gzip-zero -p zstd-zero -p oci-zero
quality:
name: Stable Rust
if: always()
needs: [lint, unit, onboarding-lint, onboarding, native, conformance, docs, package]
runs-on: ubuntu-latest
steps:
- name: All Rust checks passed
env:
RESULTS: ${{ toJSON(needs) }}
run: |
python3 - <<'PYCODE'
import json, os
results = json.loads(os.environ["RESULTS"])
failed = [name for name, job in results.items() if job["result"] != "success"]
if failed:
raise SystemExit("Rust checks did not succeed: " + ", ".join(failed))
PYCODE
supply-chain:
name: Advisories
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 - uses: dtolnay/rust-toolchain@d1031067263f94b142dd6c0ce24c5eb9d02d52a0 with:
toolchain: stable
- uses: taiki-e/install-action@d438492cf8a250514fa2d34b30bc3c0dc37c65ff with:
tool: cargo-deny
- name: Advisories in published dependencies
run: cargo deny check advisories
- name: Advisories in dev-dependencies (informational)
continue-on-error: true
run: cargo deny --config deny-dev.toml check advisories
browser:
name: Browser end-to-end
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 - uses: dtolnay/rust-toolchain@d1031067263f94b142dd6c0ce24c5eb9d02d52a0 with:
toolchain: stable
targets: wasm32-unknown-unknown
- uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 with:
prefix-key: oci-zero-v2
shared-key: wasm-release
cache-bin: false
cache-directories: ~/.cache/.wasm-pack
- uses: taiki-e/install-action@d438492cf8a250514fa2d34b30bc3c0dc37c65ff with:
tool: wasm-pack@0.15.0
- uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 with:
node-version: "24"
cache: npm
cache-dependency-path: web/package-lock.json
- name: Build WebAssembly package
run: web/build.sh
- run: npm ci
working-directory: web
- run: npx playwright install --with-deps chromium
working-directory: web
- name: Build a firmware layout tar with the real script
run: |
set -eu
# A stand-in for an espflash image: enough of an esp_app_desc_t for the
# page's version readback, which is all the layout builder cares about.
python3 - <<'PY'
import struct
image = bytearray(8192)
image[0:2] = b"\xe9\x01"
struct.pack_into("<I", image, 0x20, 0xABCD5432)
image[0x30:0x30 + len("0.0.0-ci")] = b"0.0.0-ci"
open("firmware.bin", "wb").write(image)
PY
./tools/build-firmware-artifact.sh \
--image firmware.bin:0x10000 \
--version 0.0.0-ci \
--revision "$GITHUB_SHA" \
--output /tmp/ci-layout
tar -cf /tmp/ci-firmware.oci.tar -C /tmp/ci-layout .
- run: npm run test:e2e
working-directory: web
env:
OCI_ZERO_FIRMWARE_TAR: /tmp/ci-firmware.oci.tar
OCI_ZERO_FIRMWARE_VERSION: 0.0.0-ci
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a if: failure()
with:
name: playwright-report
path: web/playwright-report
retention-days: 7
registry-demo:
name: In-memory OCI Worker and explorer
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 - uses: dtolnay/rust-toolchain@d1031067263f94b142dd6c0ce24c5eb9d02d52a0 with:
toolchain: stable
targets: wasm32-unknown-unknown, thumbv7em-none-eabi
- uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 with:
prefix-key: oci-zero-v2
shared-key: registry-demo
cache-bin: false
cache-directories: ~/.cache/.wasm-pack
- uses: taiki-e/install-action@d438492cf8a250514fa2d34b30bc3c0dc37c65ff with:
tool: wasm-pack@0.15.0
- uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 with:
node-version: "24"
cache: npm
cache-dependency-path: |
examples/registry-demo/package-lock.json
web/package-lock.json
- name: Check the ROM-backed demo without std
run: cargo check -p oci-zero-registry-demo --lib --target thumbv7em-none-eabi
- run: npm ci
working-directory: examples/registry-demo
- run: npm test
working-directory: examples/registry-demo
- name: Verify the native registry over HTTP
run: |
cargo build -p oci-zero-registry-demo --features local
target/debug/oci-zero-registry-demo 127.0.0.1:8788 > /tmp/oci-native.log 2>&1 &
native_pid=$!
trap 'kill "$native_pid"' EXIT
for attempt in $(seq 1 30); do
if curl -fsS http://127.0.0.1:8788/v2/ > /dev/null; then break; fi
sleep 1
done
node examples/registry-demo/tests/smoke.mjs http://127.0.0.1:8788
- name: Build explorer WebAssembly
run: web/build.sh
- run: npm ci
working-directory: web
- run: npx playwright install --with-deps chromium
working-directory: web
- name: Verify the Worker and browser across origins
run: |
cd examples/registry-demo
npm run dev -- --ip 127.0.0.1 > /tmp/oci-worker.log 2>&1 &
worker_pid=$!
trap 'kill "$worker_pid"' EXIT
for attempt in $(seq 1 120); do
if curl -fsS http://127.0.0.1:8787/v2/ > /dev/null; then break; fi
sleep 1
done
node tests/smoke.mjs http://127.0.0.1:8787
OCI_ZERO_DEMO_REGISTRY_URL=http://127.0.0.1:8787 cargo test -p oci-zero-registry-demo --features local --test roundtrip -- --include-ignored
cd ../../web
OCI_ZERO_DEMO_REGISTRY_URL=http://127.0.0.1:8787 npx playwright test tests/registry-demo.spec.mjs
- name: Upload registry demo failure evidence
if: failure()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a with:
name: registry-demo-failures
path: |
/tmp/oci-native.log
/tmp/oci-worker.log
web/playwright-report
web/test-results
retention-days: 7
msrv:
name: Rust 1.75 / no_std
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 - uses: dtolnay/rust-toolchain@d1031067263f94b142dd6c0ce24c5eb9d02d52a0 with:
toolchain: "1.75.0"
targets: thumbv7em-none-eabi
- uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 with:
prefix-key: oci-zero-v2
shared-key: msrv-thumb
cache-bin: false
- run: cargo check -p oci-zero -p gzip-zero -p zstd-zero --lib --no-default-features --target thumbv7em-none-eabi
- run: cargo check -p oci-zero --lib --no-default-features --features gzip,zstd --target thumbv7em-none-eabi