Skip to content

Add apt-sources parameter for GPG-signed third-party repositories#189

Open
robtaylor wants to merge 6 commits intoawalsh128:masterfrom
robtaylor:feat/apt-sources
Open

Add apt-sources parameter for GPG-signed third-party repositories#189
robtaylor wants to merge 6 commits intoawalsh128:masterfrom
robtaylor:feat/apt-sources

Conversation

@robtaylor
Copy link
Copy Markdown

@robtaylor robtaylor commented Mar 10, 2026

Summary

Add a new apt-sources parameter for GPG-signed third-party repository sources (NVIDIA, Docker, GitHub CLI, etc.) that require downloading a signing key and configuring signed-by= in the source entry.

Depends on: #192 — merge that PR first, then rebase this one onto master.

Features

  • Downloads GPG keys, auto-detects armored vs binary format
  • Supports both URL-based source files and inline deb lines
  • Auto-detects deb822 (.sources) vs traditional (.list) format
  • Injects signed-by= into source entries when not already present
  • Removes conflicting pre-existing source files referencing the same repo URL
  • Includes apt-sources content in cache key hash
  • Validates HTTPS-only key URLs and proper line format
  • Forces apt update when apt-sources is specified

Test plan

  • apt_sources_empty — empty parameter has no effect
  • apt_sources_inline_deb — inline deb line with GitHub CLI repo
  • apt_sources_cached — cache round-trip for apt-sources packages
  • apt_sources_bad_key_url — invalid key URL returns error
  • apt_sources_bad_format — missing pipe separator returns error
  • apt_sources_conflicting_source — pre-existing conflicting source is removed
  • apt_sources_force_update — forces apt update even when lists are fresh

@robtaylor robtaylor force-pushed the feat/apt-sources branch 6 times, most recently from 5d58a28 to 6136674 Compare March 10, 2026 21:22
After cache restore, dpkg had no record of the installed packages because:
1. Only preinst/postinst scripts were cached from /var/lib/dpkg/info/,
   missing .list, .md5sums, .conffiles, and other metadata files
2. The dpkg status database (/var/lib/dpkg/status) was never updated

This meant dpkg -s, apt list --installed, and anything checking package
state would not see the restored packages.

Fix:
- Cache all /var/lib/dpkg/info/<package>.* files (not just install scripts)
- Save each package's dpkg status entry to a .dpkg-status file
- On restore, append status entries to /var/lib/dpkg/status (skipping
  packages that are already registered)

Additionally:
- Include directories in tar archives so that tar preserves their ownership
  and permissions on restore (prevents 0077 umask issues on GPU runners)
- Include architecture qualifier (e.g., :i386) from apt's Unpacking log
  in get_installed_packages, so multi-arch variants get separate cache
  entries instead of being deduplicated
- When registering restored packages with dpkg, compare cached vs installed
  versions and handle upgrades by replacing the old status entry

Co-developed-by: Claude Code v2.1.58 (claude-opus-4-6)
Hash the list of pre-installed package names (dpkg-query -W) into the
cache key. This prevents cache collisions when different runners (e.g.,
GPU runners with CUDA pre-installed vs plain Ubuntu) request the same
packages — a cache built where packages were already present won't be
restored on a runner where they're missing.

Also adds a ::notice annotation so users can see the fingerprint in
the workflow summary and understand why different runners produce
different cache keys.

Co-developed-by: Claude Code v2.1.58 (claude-opus-4-6)
- Use tee instead of redirect so install output is visible in the
  workflow log while still being captured to the install log file
- Check PIPESTATUS[0] for the actual apt-fast exit code (since tee
  always succeeds) and exit with a clear error message on failure
- Remove the redundant installed package list logging — the full
  install output is now visible via tee, and the individual cache
  lines already show each package being processed

Co-developed-by: Claude Code v2.1.58 (claude-opus-4-6)
Add comprehensive integration test workflow that exercises the action's
install, cache, and restore paths with real packages on GitHub Actions
runners. Tests cover:

- Basic install and cache round-trip (xdot, libxml2-dev)
- Cache hit and version pinning verification
- Custom apt repository support (ppa:savoury1/ffmpeg6)
- Multiple package installs with dependencies
- Support for apt-mark'd packages and version-pinned packages
- ARM64 architecture support
- Package with conflicts (default-jdk replacing default-jre-headless)
- Invalid inputs (bad version, empty packages, bad repo)
- dpkg registration verification after cache restore

Co-developed-by: Claude Code v2.1.58 (claude-opus-4-6)
The existing add-repository parameter only supports apt-add-repository
(PPAs and simple repo formats). Many third-party repos (NVIDIA, Docker,
GitHub CLI, etc.) require downloading a GPG signing key and adding a
sources list entry with signed-by= referencing that keyring.

The new apt-sources input accepts multi-line entries in the format:
  key_url | source_spec

Features:
- Downloads GPG keys, auto-detects armored vs binary format
- Supports both URL-based source files and inline deb lines
- Auto-detects deb822 (.sources) vs traditional (.list) format
- Injects signed-by= into source entries when not already present
- Removes conflicting pre-existing source files that reference the
  same repo URL with a different keyring path
- Includes apt-sources content in cache key hash
- Validates HTTPS-only key URLs and proper line format
- Forces apt update when apt-sources is specified (bypasses staleness check)

Co-developed-by: Claude Code v2.1.58 (claude-opus-4-6)
Tests cover:
- apt_sources_empty: Empty apt-sources has no effect (backward compat)
- apt_sources_inline_deb: Inline deb line with GitHub CLI repo
- apt_sources_cached: Cache round-trip for apt-sources packages
- apt_sources_bad_key_url: Invalid key URL returns error
- apt_sources_bad_format: Missing pipe separator returns error
- apt_sources_conflicting_source: Pre-existing conflicting source is removed
- apt_sources_force_update: Forces apt update even when lists are fresh

Co-developed-by: Claude Code v2.1.58 (claude-opus-4-6)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant