Repository navigation
ci: fix workflow bugs, bump actions, tighten permissions - #259
Merged
Merged
Conversation
- The md5srv-test job (the first job of the nightly card.binary HIL workflow) failed in "Setup Bats and bats libs" with "curl: (22) The requested URL returned error: 403". The card.binary hardware job needs md5srv-test, so it was skipped. - The workflow does not pass bats-version to bats-core/bats-action, so the action looks up the latest Bats release through api.github.com/repos/bats-core/bats-core/releases/latest. The BATS_VERSION env var in this workflow is not read by the action. - bats-action 3.0.0 makes that lookup without a token. Unauthenticated API calls share a 60 requests/hour limit per source IP, and GitHub answers with 403 once the limit is used up. curl -f hides the response body, so the log can't confirm the reason, but this is the likely one. - bats-action 3.0.1 sends the job's GITHUB_TOKEN with the lookup and the tarball download. That is the upstream fix for this lookup. Bump to 3.0.1. No other change: same inputs, same Bats version resolution, same libraries. - Checked locally: actionlint reports no issues in md5srv-tests.yml, and the 3.0.1 install logic resolves and installs Bats v1.14.0, after which the md5srv bats suite passes (14 tests, 0 failures).
- Pass bats-version: 1.14.0 to bats-core/bats-action. With an explicit version the action skips its api.github.com releases/latest lookup, so the install no longer depends on GitHub API rate limits at all. - 1.14.0 is the version the nightly has been installing as "latest", so this does not change which Bats the tests run on. - Remove the BATS_VERSION: 1.10.0 env var. The action never read it, and its value did not match the Bats version actually in use. - Keep bats-action 3.0.1. Its token on the tarball download stays as defense in depth.
Bug fixes: - check_architecture_docs: `! grep` skips errexit, so only the last pattern was ever enforced. Check grep's status explicitly and fail on a match or on a missing path. - publish_ci_image: a force_build dispatch from any branch pushed ghcr.io/blues/note_c_ci:latest. Gate on master and require every image-consuming job to pass, not just run_unit_tests. - Image-consuming jobs used `if: always()`, which runs even after cancellation and tests against the stale :latest image when the image build fails. Run only when the image build succeeded or was skipped. - md5srv "Re-run Tests" invoked $HOME/.local/bin/bats, which bats-action never installs, so the retry could not run. Use bats from PATH and only retry when the test step itself failed. - HIL route checks: `[ -n $route_uid ]` was always true and neither check caught jq's "null". Quote and reject "null". - Coveralls was pinned to the moving `master` branch; use v2 with `file`. Hygiene: - ci.yml concurrency: cancel superseded PR runs; master runs get a per-SHA group so a pending run is never cancelled. - timeout-minutes on every job; least-privilege permissions. - Drop the unused buildx setup from the load-ci-image composite action, and the unused ghcr login and redundant `load: true` from the image build. - Add dependabot for GitHub Actions (workflows and composite actions). Action bumps: checkout v7, setup-python v7, upload-artifact v7, download-artifact v8, paths-filter v4, docker login/setup-buildx v4, build-push v7, bats-action 4.0.0 (with github-token), tailscale v4, configure-aws-credentials v6, action-junit-report v6, actions-gh-pages v4. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Dependabot PR runs get no Actions secrets (only Dependabot secrets, and none are configured), so the Tailscale, Notehub and ngrok steps would fail. The secret-free md5srv tests still run. Re-runs keep github.actor, so they stay skipped; a maintainer can validate HIL changes on a Dependabot branch with workflow_dispatch. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Add a Continuous Integration subsection under Testing Strategy covering what runs where, the CI image publication policy, when the hardware tests run or are skipped, and why CI stays on GitHub-hosted runners. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
5 tasks done
…base ubuntu-latest starts moving to Ubuntu 26 on 2026-10-19. The host-run jobs (HIL apt packages including ngrok's buster repo, Python 3.11, the docs build's doxygen, the integration test's compiler) are exposed to that change, so pin every Linux job to ubuntu-24.04 (the image ubuntu-latest resolves to today) and move to 26.04 deliberately later. macOS stays on macos-latest. paths-filter ignores `base` on pull_request events and v4 warns about it. On push and dispatch an unset base falls back to the default branch (master), so removing it changes nothing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
bats-action defaults bats-support/bats-assert to /usr/lib, and the cache restore runs tar as the unprivileged runner user, so every run logged "Failed to restore ... tar exit code 2" and re-downloaded the libraries. bats-action's README documents this and recommends a path under $HOME. runner.temp qualifies and sits outside the workspace, so the later checkout isn't affected by the root-owned install. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
zfields
approved these changes
Oct 19, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes several CI bugs, moves every action to its latest major version, and adds least-privilege permissions, concurrency, timeouts, and Dependabot. What the tests check is unchanged. CI stays on GitHub-hosted runners (see the new ARCHITECTURE.md note on why Namespace wasn't adopted).
Note
This branch includes the two commits from #257 (@zakoverflow's Bats pin), because it bumps the same action again. If #257 merges first, rebasing this branch drops them. If this merges first, #257 can be closed.
Bug fixes
! grepdoesn't trigger errexit, and the loop only returned the last iteration's status. It now checks grep's status explicitly and fails on a match or on a missing path.force_builddispatched from any branch publishedghcr.io/blues/note_c_ci:latest. Publishing is now limited tomasterand waits for every job that uses the image. Before, it only waited forrun_unit_tests.if: always(). That ignores cancellation, and when the image build failed they silently tested against the old:latest. They now run only when the image build succeeded or was skipped.$HOME/.local/bin/bats, but bats-action installs to$HOME/.local/share/bats/binand adds that to PATH. It now callsbats, and only retries when the test step itself failed.[ -n $route_uid ]was always true, and neither route check caught jq's"null".masterbranch. It's now@v2withfile:.workflow_dispatch) on its branch.bats-supportandbats-assertunder/usr/libby default, which the unprivileged cache restore can't write to. Every run logged "Failed to restore … tar exit code 2" and downloaded the libraries again. They now install underrunner.temp, as bats-action's README recommends. I also deleted three 18-month-old master cache entries that reported a hit but couldn't be restored; nothing in the diff relies on that.Hygiene
ci.ymlconcurrency: superseded PR runs are cancelled. Master runs get a per-SHA group, so a pending master run is never cancelled.ubuntu-24.04.ubuntu-lateststarts moving to Ubuntu 26 on 2026-10-19, and the jobs that run directly on the runner depend on its packages: HIL's apt packages and ngrok'sbusterrepo, Python 3.11, doxygen, and the integration test's compiler.ubuntu-lateststill resolves to 24.04 today, so nothing changes yet. macOS stays onmacos-latest.base: 'master'. It's ignored on PR events, and v4 now warns about that. On push and dispatch an unset base already falls back to the default branch.timeout-minuteson every job, instead of the 6-hour default.permissions:contents: readby default,pull-requests: readfor paths-filter, andpackages: writeonly forpublish_ci_image.load-ci-imagecomposite action. Removed the unused ghcr login and the redundantload: truefrom the image build..github/dependabot.yml: GitHub Actions, weekly, with minor and patch bumps grouped. It covers the composite action too.Action versions
'3.x'for docs keeps today's resolution; HIL stays on 3.11)github-token, which is now passed)Test plan
bash -e: passes on the current tree, fails on a match in either pattern, fails on a missing path.publish_ci_imageis correctly skipped.force_build=true(run). The image built from today'sdebian:stable-slim, all six image-consuming jobs loaded it and passed,publish_ci_imagewas skipped because the run wasn't on master, and the 396 MB handoff artifact expires after 7 days. The new build-push version also runs BuildKit's Dockerfile checks, which flagFROM --platform=linux/amd64(FromPlatformFlagConstDisallowed). That's a warning only, and the constant platform looks deliberate since the image installs i386 multilib packages, so I left it.Docs
ARCHITECTURE.md: new Continuous Integration subsection under Testing Strategy.docs/architecture/architecture.html: unchanged. It's the component graph and has no CI content.source-research/: unaffected. Workflows are excluded, and no SDK symbols, dependencies, or APIs changed.Not changed
notecard-binary-tests.ymlignores anyfirmware_s3_urivalue other thannightly, even though the input's description says it takes an S3 URI. The HIL owner needs to decide whether to implement it or reword the description.🤖 Generated with Claude Code