diff --git a/.gitea/workflows/rust-consumers.yml b/.gitea/workflows/rust-consumers.yml new file mode 100644 index 0000000..02eec69 --- /dev/null +++ b/.gitea/workflows/rust-consumers.yml @@ -0,0 +1,75 @@ +name: Rust consumers (L4T) + +# A contracts change can break a service that compiles contracts in (include_str! of +# ../contracts/...), and that service's own CI only runs when the service changes. +# So: on a change to what services compile in, build every one of them, at its master, +# against the pushed contracts. README, docs and checklists are not compiled into any +# service (checklists reach the app as a synced copy, which crosscheck watches). +on: + push: + branches: [ master ] + paths: + - 'schema/**' + - '.gitea/workflows/rust-consumers.yml' + workflow_dispatch: + +jobs: + consumers: + name: Clippy, test, build, glibc for every service that compiles contracts in + # The development Orin (host mode): the same checks as each service's rust.yml. + runs-on: l4t-rust + steps: + - name: Checkout contracts at the push, and every consumer at master + env: + SERVER: ${{ gitea.server_url }} + SHA: ${{ github.sha }} + run: | + set -euo pipefail + rm -rf ws && mkdir ws + git init -q ws/contracts + git -C ws/contracts fetch -q --depth 1 "$SERVER/yukart/contracts.git" "$SHA" + git -C ws/contracts checkout -q FETCH_HEAD + repos=$(curl -fsS "$SERVER/api/v1/orgs/yukart/repos?limit=50" \ + | python3 -c 'import json,sys; print(" ".join(r["name"] for r in json.load(sys.stdin) if not r["archived"]))') + consumers="" + for r in $repos; do + [ "$r" = contracts ] && continue + # Only Rust repos are cloned in full; the API says whether Cargo.toml exists. + curl -fsS -o /dev/null "$SERVER/api/v1/repos/yukart/$r/contents/Cargo.toml" 2>/dev/null || continue + git clone -q --depth 1 "$SERVER/yukart/$r.git" "ws/$r" + if grep -rqsF '../contracts/' "ws/$r/src" "ws/$r/build.rs"; then + consumers="$consumers $r" + else + rm -rf "ws/$r" + fi + done + [ -n "$consumers" ] || { echo "no Rust repo compiles contracts in"; exit 1; } + echo "CONSUMERS=$consumers" >> "$GITHUB_ENV" + echo "contracts $(git -C ws/contracts log --oneline -1); consumers:$consumers" + rustc --version; head -1 /etc/nv_tegra_release + + - name: Build each consumer + run: | + set -euo pipefail + failed="" + for r in $CONSUMERS; do + echo "::group::$r $(git -C ws/$r log --oneline -1)" + # Each repo's own cache, shared with its rust.yml: the runner runs one job at a time. + export CARGO_TARGET_DIR="$HOME/target/$r" + if ( cd "ws/$r" \ + && cargo clippy --release --all-targets --locked -- -D warnings \ + && cargo test --release --locked \ + && cargo build --release --locked \ + && for b in $(cargo metadata --format-version 1 --no-deps | python3 -c ' + import json, sys + for p in json.load(sys.stdin)["packages"]: + for t in p["targets"]: + if "bin" in t["kind"]: print(t["name"])'); do + scripts/check-glibc.sh "$CARGO_TARGET_DIR/release/$b" || exit 1 + done ); then + echo "::endgroup::"; echo "$r: ok" + else + echo "::endgroup::"; echo "$r: FAILED"; failed="$failed $r" + fi + done + [ -z "$failed" ] || { echo "failed:$failed"; exit 1; }