Skip to content

fix(ansible): keep locked apt pins reachable via a dated Ubuntu snapshot (verification only) - #232

Closed
youtalk wants to merge 5 commits into
mainfrom
verify/locked-ci-ubuntu-snapshot
Closed

youtalk wants to merge 5 commits into
mainfrom
verify/locked-ci-ubuntu-snapshot

Conversation

@youtalk

@youtalk youtalk commented Aug 24, 2026

Copy link
Copy Markdown
Owner

Description

Verification-only fork PR. It stacks two things on top of the four commits already in #229 (= autowarefoundation#7238):

  1. fix(ansible): keep locked apt pins reachable via a dated Ubuntu snapshot — the blocker xmfcx raised on #7238. Both locked=true cells are red there because Ubuntu superseded the pinned wget build on each distro and dropped the old one from the pockets, so the APT preference matches nothing and the drift assert fires. A snapshot.ubuntu.com source at the lockfile's own date makes every pinned build downloadable again.
  2. ci: address review on the locked base bake lane — the four validate-lockfiles.yaml points from the same review: the missing run-condition on the require-label call site, the paths: filter that served both an 8-second lint and two cold container builds, the missing matrix aggregator, and setup-buildx-action on v3.

The purpose of this PR is to show install-dev-env (ubuntu:22.04, true) and (ubuntu:24.04, true) green. Nothing here is meant to merge into the fork's main.

Local verification, before pushing

install_dev_env --skip-tags artifacts -e use_locked_versions=true was run in a bare ubuntu:22.04 and ubuntu:24.04 container — the same command the CI cell runs:

jammy noble
PLAY RECAP ok=146 changed=66 failed=0 ok=138 changed=62 failed=0
drift assert All 71 pinned packages match the lockfile All 71 pinned packages match the lockfile
ROS closure assert matches the 2026-05-14 snapshot matches the 2026-04-13 snapshot
pin completeness all newly-installed Ubuntu packages covered all newly-installed Ubuntu packages covered

apt-cache policy wget inside the finished jammy container shows the mechanism directly:

wget:
  Installed: 1.21.2-2ubuntu1.4
  Candidate: 1.21.2-2ubuntu1.4
  Version table:
     1.21.2-2ubuntu1.5 500
        500 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 Packages
        500 http://security.ubuntu.com/ubuntu jammy-security/main amd64 Packages
 *** 1.21.2-2ubuntu1.4 1001

The live archive still offers only .5; the pinned .4 comes from the snapshot at priority 1001. noble is identical with 1.21.4-1ubuntu4.4 / .5.

Reachability was also checked against the live services before any code was written: at 20260805T000000Z, the date the current lockfiles were taken, snapshot.ubuntu.com serves 25/25 apt_pins for jammy and 25/25 for noble, on both amd64 and arm64.

Design note: added alongside, not in place of

The review proposed pointing apt at a dated Ubuntu archive. This implementation adds the snapshot source next to the distribution's own sources rather than replacing them:

  • The pins stay the contract. At Pin-Priority: 1001 they select the locked build wherever it is served, so the snapshot only has to keep that build reachable — it does not have to win on its own.
  • install_dev_env is the documented bare-metal installation path, so it runs on developer machines. Rewriting a user's /etc/apt/sources.list is not this role's to do.
  • Packages outside apt_pins keep resolving exactly as they do today, which keeps the regression surface at zero. A newly introduced Ubuntu-archive package that nobody pinned is already a hard failure via check_pin_completeness.py.

Cost: the first apt-get update in locked mode also fetches the snapshot indices, roughly 48 MB on jammy and 32 MB on noble. Subsequent updates are cheap because a dated snapshot never changes.

Related links

Tests performed

See "Local verification" above. Fork CI is the remaining evidence this PR exists to collect.

Notes for reviewers

Not for merge.

No workflow ran with use_locked_versions/USE_LOCKFILE before, so a
locked-mode regression (or an unresolvable package like
ros-build-essential) was invisible to CI. Add a locked axis to the
health-check-ansible matrix and a locked base bake (both distros) to
validate-lockfiles, whose trigger paths now include ansible/** and
docker/** so role and Dockerfile changes exercise the locked build too.

Signed-off-by: Yutaka Kondo <yutaka.kondo@youtalk.jp>
(cherry picked from commit 6a42085)
The previous commit put build-locked-base on ansible/** and docker/**, with
no label gate, no cache and no timeout. Both READMEs this stack touches live
under those prefixes, as does docker/examples, so a docs-only PR burned two
cold container builds.

Narrow the trigger to the paths that can actually change what a locked build
resolves to, and require run:health-check before the bake runs — the same
reusable require-label workflow and the same label health-check-ansible,
health-check-pr, and health-check-ansible-artifacts already use for their
expensive lanes. The cheap validate-lockfiles job keeps running ungated.

ansible/vars/locked-versions-*.yaml is dropped from the path list: the
ansible/vars/** entry covers it.

Signed-off-by: Yutaka Kondo <yutaka.kondo@youtalk.jp>
(cherry picked from commit 2a12167)
The narrowed trigger paths left ansible/scripts/** out, so a PR that
edits validate_lockfiles.sh never started the job that executes it. The
same directory holds the lockfile generators, whose output the job
validates. Add it to the paths list.

Signed-off-by: Yutaka Kondo <yutaka.kondo@youtalk.jp>
(cherry picked from commit 8f60853)
Four points from the review of autowarefoundation#7238, all in validate-lockfiles.yaml.

The require-label call site had no run-condition, unlike the three that
already exist in health-check-ansible.yaml,
health-check-ansible-artifacts.yaml and health-check-pr.yaml. All four
publish the same required `require-label / require-label` context, and
without run-condition this one reports red -- not skipped -- on a PR that
reaches the workflow without touching a bake input. Add a changed-files
job and wire it in.

Scoping that job to the bake's own inputs also settles the trigger
argument the review raised: one `paths:` filter was serving both an
eight-second lint and two cold container builds, which want opposite
filters. It now only has to be wide enough for whichever job could be
affected, and each job narrows from there. Markdown is excluded outright,
since 19 READMEs live under ansible/roles/** and the previous comment
claimed they were already outside the filter. ansible-galaxy-requirements
is added: base.Dockerfile bind-mounts it and it decides which collection
the playbook resolves, so both sibling health-check workflows watch it.

The matrix emitted `build-locked-base (humble)` and `(jazzy)` with no
aggregator, so no stable name existed for a branch ruleset to require.
Add one, mirroring install-dev-env-required.

setup-buildx-action moves to v4, matching the three other call sites in
this repository.

Signed-off-by: Yutaka Kondo <yutaka.kondo@youtalk.jp>
(cherry picked from commit 7138684)
@github-actions

Copy link
Copy Markdown

Thank you for contributing to the Autoware project!

🚧 If your pull request is in progress, switch it to draft mode.

Please ensure:

An exact-version APT pin only binds a version apt can still reach. Ubuntu
drops a superseded build from <suite>-updates and <suite>-security as soon
as it publishes the replacement, and a preference naming a version no
configured source serves matches nothing at all -- so apt installs the
current candidate and version_lock's drift assert fails the play.

This decays on its own, with no change to the repository. Seventeen days
after the lockfiles were last regenerated, wget had moved on both distros
(1.21.2-2ubuntu1.4 -> .5 on jammy, 1.21.4-1ubuntu4.4 -> .5 on noble) and
took every locked install with it.

Add a dated snapshot.ubuntu.com apt source, the Ubuntu-archive counterpart
of the dated snapshots.ros.org source the ros2 role already configures.
It republishes the pockets as they stood at the lockfile's own
ubuntu_snapshot_date, so every apt_pins build stays downloadable after the
live pockets move past it. One tree serves both amd64 and arm64, and it is
signed by the stock ubuntu-archive-keyring, so no extra key is installed.

The source is added alongside the distribution's own sources, not in place
of them. The pins remain the contract: at priority 1001 they select the
locked build wherever it is served, so this source only has to keep that
build reachable. install_dev_env also runs on developer machines, where
rewriting /etc/apt/sources.list is not this role's to do, and packages
outside apt_pins keep resolving exactly as they do today.

Verified against the live services before wiring: at 20260805T000000Z --
the date the current lockfiles were taken -- snapshot.ubuntu.com serves
25/25 apt_pins for jammy and 25/25 for noble, on both amd64 and arm64,
while the live archive serves neither pinned wget.

Signed-off-by: Yutaka Kondo <yutaka.kondo@youtalk.jp>
(cherry picked from commit c8734cc46293449bcdc6acf3576b5b4d501161b2)
Signed-off-by: Yutaka Kondo <yutaka.kondo@youtalk.jp>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant