Skip to content

feat: follow the decdn and sponsord release lines, not one release - #160

Merged
thiras merged 2 commits into
mainfrom
feat/float-upstream-pins
Oct 14, 2026
Merged

thiras merged 2 commits into
mainfrom
feat/float-upstream-pins

Conversation

@thiras

@thiras thiras commented Oct 14, 2026

Copy link
Copy Markdown
Contributor

The roles and the chart now pin the decdn/decdn and decdn/sponsord release line (0.1) instead of one release, so an upstream patch release reaches deployments without a release of the collections or the chart. An exact X.Y.Z still pins one release.

Roles (decdn_node, sponsord, sponsord_onramp)

  • decdn_node_version, sponsord_version and sponsord_onramp_version default to "0.1". Every release-mode run resolves the line through tasks/resolve-release.yml, which is copied into all three roles; make test-scripts keeps the copies identical. The resolver picks the highest vX.Y.N in GitHub's release list that is not a draft or a prerelease and has a SHA256SUMS.asc. The list only chooses the tag: the download is GPG-verified as before, and the install stamp and the exact --version backstop hold the resolved version. Check mode reads the list too, so make check shows the upgrade a run would make.
  • Outages: if the list can't be read (GitHub down, or the 60-requests-an-hour unauthenticated limit), a host already on a release of the line keeps it with a warning. A host with no release of the line fails. A rate limit (403/429) is not retried.
  • The pins must be quoted strings matching X.Y or X.Y.Z[-pre]. v0.1, 0.1.x and an unquoted 0.1 are refused.
  • The onramp's installer pin (sponsord_onramp_decdn_release) defaults to the line v0.1. The role reads that release's SHA256SUMS from where the installers fetch it and verifies it against a vendored copy of decdn's KEYS (roles/sponsord_onramp/files/decdn-release-KEYS.asc, kept identical to decdn_node's). It then serves the release's digest. An exact tag still takes the operator's digest, and preflight refuses a tag without a digest or a line with one.
  • The onramp reuses sponsord's resolution of the same line on the host, so a release published between the two plays can't put the two binaries on different releases.

Chart

appVersion: "0.1": the default image tag is the floating line tag upstream promotes. A new decdn-node.pullPolicy helper picks Always for a line tag and IfNotPresent for an exact tag or a digest; an explicit image.pullPolicy wins. scripts/fetch-decdn-cli.sh resolves the line, so CI's helm job (now with the job token) validates against the line's newest decdn.

Compose, bumps and drift

  • Compose stays pinned by digest; it names the line's newest release.
  • bump_decdn.py (new synced and kind subcommands) and open-decdn-bump.sh now tell two cases apart:
    • A patch: repo-only. It moves the Compose digests and the onramp env pin, the chart's example digest, the exact-pin examples and the generated mirrors. It flags a mirror change, which would need a release.
    • A new line: it also moves the role defaults, appVersion and AGENTS.md.
  • upstream-drift resolves each line the way the roles do, checks the exact copies and mirrors against that release, and flags only a new line.
  • sync-network-profiles.py defaults --ref to the checkout's newest tag in the line.

Testing

  • Lints: make test-scripts, lint, lint-ansible (production), lint-compose, lint-cloud-init, and lint-helm with DECDN_CLI fetched by resolving 0.1 → 0.1.0 against the real release.
  • Molecule: cloud-init, cloud-init-publisher, sponsord-install, sponsord-onramp, validation, validation-sponsord, default and sponsord all pass. The test mirror now serves a GitHub-shaped releases.json, and these cases are new:
    • line 0.7 → 0.7.10, skipping a newer prerelease, a draft and a release without .asc, and 0.7.10 vs 0.7.2 ordered numerically;
    • the list unreachable: 0.7.10 is kept, and a line with nothing installed fails;
    • sponsord's line 0.3 → 0.3.4;
    • the onramp serves v0.0.5 with the mirror's SHA256SUMS digest;
    • malformed pins are refused.
  • Not run locally: make galaxy-check (galaxy-importer isn't installed here). Both collections build and carry the new files.

Trade-offs

Each release-mode deploy makes a GitHub API call per pin: up to 4 per publisher host. A large fleet behind one address should pin exact versions or serve the list from a mirror (the *_release_index variables). With Always, a Kubernetes pod can't start while ghcr.io is unreachable, even with the image cached. Both are documented in the role and chart READMEs.

After merging, release decdn.node, decdn.publisher and the chart (RELEASING.md): from then on, 0.1.x patches need only the repo-only bump PR.

🤖 Generated with Claude Code

decdn_node_version, sponsord_version and sponsord_onramp_version default to a
release line ("0.1"), and every run installs its newest finished vX.Y.N
(tasks/resolve-release.yml, copied into all three roles): the highest release
in GitHub's release list that is not a draft or a prerelease and has a
SHA256SUMS.asc. The list only chooses the tag; the download is verified as
before, and the stamp and the --version backstop hold the resolved version. An
exact "X.Y.Z" still pins one release, with no lookup.

The onramp's installer pin follows decdn's line too (v0.1): the role reads the
resolved release's SHA256SUMS from where the installers fetch it, verifies it
against a vendored copy of decdn's KEYS and serves its digest. A tag still
takes the operator's digest.

The chart's appVersion is the line and its default image tag the line's
floating tag, pulled Always (decdn-node.pullPolicy); fetch-decdn-cli.sh
resolves the line for CI's config validation.

Compose stays pinned by digest. bump_decdn.py and open-decdn-bump.sh now tell
a patch release (repo-only: Compose, the example digests and pins, the
mirrors) from a new line, and upstream-drift checks the exact copies against
each line's newest release and flags only a new line.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings October 14, 2026 18:36

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Custom release indexes can receive the GitHub token, and stale onramp state can select an older installer release during an outage.

4 open findings
What changed in this PR

Moves deCDN and sponsord deployments from exact release pins to floating release lines while retaining exact-version overrides.

Changes:

  • Adds signed release-line resolution and outage fallback to Ansible roles.
  • Updates Helm image policy, bump/drift automation, and Compose synchronization.
  • Expands validation, Molecule coverage, and operator documentation.
File Description
tests/​scripts-test.sh Tests release-line invariants and CLI resolution.
scripts/​bump_decdn.py Distinguishes patch and release-line bumps.
scripts/​tests/​test_bump_decdn.py Tests revised bump behavior.
scripts/​sync-network-profiles.py Selects the newest tag in a line.
scripts/​open-decdn-bump.sh Generates patch- or line-specific bumps.
scripts/​fetch-decdn-cli.sh Resolves chart release lines.
RELEASING.md Documents release-line publishing.
examples/​collection-fleet/​inventory/​host_vars/​origin-1/​main.yml Updates origin pin guidance.
examples/​collection-fleet/​inventory/​host_vars/​decdn-node-1/​main.yml Updates node pin guidance.
examples/​collection-fleet/​inventory/​group_vars/​sponsord_onramp_hosts.yml Documents installer-line behavior.
examples/​collection-fleet/​inventory/​group_vars/​sponsord_hosts.yml Documents sponsord lines.
docs/​publishers.md Adds publisher upgrade guidance.
docs/​node-operators.md Adds per-deployment-path upgrade guidance.
CONTRIBUTING.md Updates mirror-generation instructions.
compose/​sponsord-onramp.env.example Clarifies Compose’s exact installer pin.
compose/​README.md Explains digest versus line behavior.
compose/​.env.example Documents exact Compose release digests.
cloud-init/​user-data-publisher.yaml Documents publisher release lines and mirrors.
cloud-init/​user-data-node.yaml Documents node release lines and mirrors.
cloud-init/​tests/​lint.py Validates line/tag installer pin combinations.
cloud-init/​README.md Updates cloud-init upgrade procedures.
charts/​decdn-node/​values.yaml Adds automatic pull-policy semantics.
charts/​decdn-node/​values.schema.json Allows automatic pull-policy selection.
charts/​decdn-node/​tests/​render-test.sh Tests image and pull-policy selection.
charts/​decdn-node/​templates/​statefulset.yaml Uses the pull-policy helper.
charts/​decdn-node/​templates/​_helpers.tpl Implements line-aware pull policy.
charts/​decdn-node/​README.md Documents floating image behavior.
charts/​decdn-node/​Chart.yaml Changes appVersion to release line 0.1.
ansible/​roles/​sponsord/​tasks/​resolve-release.yml Adds shared line resolution.
ansible/​roles/​sponsord/​tasks/​main.yml Validates line or exact pins.
ansible/​roles/​sponsord/​tasks/​install.yml Installs resolved sponsord releases.
ansible/​roles/​sponsord/​README.md Documents sponsord release lines.
ansible/​roles/​sponsord/​defaults/​main.yml Defaults sponsord to line 0.1.
ansible/​roles/​sponsord_onramp/​templates/​sponsord-onramp.env.j2 Renders resolved installer values.
ansible/​roles/​sponsord_onramp/​tasks/​resolve-release.yml Adds shared line resolution.
ansible/​roles/​sponsord_onramp/​tasks/​main.yml Validates and resolves installer pins.
ansible/​roles/​sponsord_onramp/​tasks/​install.yml Installs the resolved onramp release.
ansible/​roles/​sponsord_onramp/​tasks/​decdn-release.yml Verifies the installer release manifest.
ansible/​roles/​sponsord_onramp/​README.md Documents binary and installer lines.
ansible/​roles/​sponsord_onramp/​files/​decdn-release-KEYS.asc Adds trusted deCDN signing keys.
ansible/​roles/​sponsord_onramp/​defaults/​main.yml Adds line indexes and verification defaults.
ansible/​roles/​decdn_node/​tasks/​resolve-release.yml Adds shared line resolution.
ansible/​roles/​decdn_node/​tasks/​main.yml Validates line or exact node pins.
ansible/​roles/​decdn_node/​tasks/​install.yml Installs resolved node releases.
ansible/​roles/​decdn_node/​README.md Documents release-line operation.
ansible/​roles/​decdn_node/​defaults/​main.yml Defaults nodes to line 0.1.
ansible/​README.md Updates deployment guidance.
ansible/​molecule/​validation/​converge.yml Tests malformed node pins.
ansible/​molecule/​validation-sponsord/​converge.yml Tests sponsord and onramp pins.
ansible/​molecule/​sponsord-install/​side_effect.yml Tests sponsord line resolution.
ansible/​molecule/​sponsord-install/​prepare.yml Builds release-list fixtures.
ansible/​molecule/​schema/​README.md Updates schema synchronization guidance.
ansible/​molecule/​schema/​files/​schema-keys.txt Updates generated-file instructions.
ansible/​molecule/​schema/​files/​gen-schema-keys.py Generates revised instructions.
ansible/​molecule/​cloud-init/​verify.yml Tests resolution and outage fallback.
ansible/​molecule/​cloud-init/​prepare.yml Adds line-resolution fixtures.
ansible/​molecule/​cloud-init/​includes/​mirror.yml Generates GitHub-shaped release indexes.
ansible/​molecule/​cloud-init-publisher/​verify.yml Verifies resolved installer output.
ansible/​molecule/​cloud-init-publisher/​prepare.yml Adds publisher release fixtures.
ansible/​molecule/​cloud-init-publisher/​converge.yml Configures the mirrored installer line.
ansible/​inventory/​host_vars/​origin-1/​main.yml Updates origin pin guidance.
ansible/​inventory/​host_vars/​decdn-node-1/​main.yml Updates node pin guidance.
ansible/​inventory/​group_vars/​sponsord_onramp_hosts.yml Documents installer-line behavior.
ansible/​inventory/​group_vars/​sponsord_hosts.yml Documents sponsord lines.
ansible/​galaxy/​node/​README.md Updates collection guidance.
AGENTS.md Defines repository-wide release-line conventions.
.github/​workflows/​upstream-drift.yml Resolves lines before drift checks.
.github/​workflows/​ci.yml Authenticates chart CLI resolution.

🧠 Review effort: Balanced


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread ansible/roles/sponsord_onramp/tasks/decdn-release.yml
Comment thread scripts/fetch-decdn-cli.sh
Comment thread ansible/roles/sponsord/tasks/main.yml
Comment thread ansible/roles/sponsord_onramp/tasks/main.yml
- fetch-decdn-cli.sh sends GITHUB_TOKEN to GitHub's API only, never to a
  DECDN_RELEASE_INDEX override; a loopback index in make test-scripts asserts
  no Authorization header arrives.
- The onramp records the decdn release it serves on both paths, exact pins
  included, so a later release-line lookup that cannot read GitHub falls back
  to the release actually served, never an older one. The record path is a
  role var (vars/main/decdn-release.yml); sponsord-onramp and
  cloud-init-publisher assert it.
- The release-version failure messages of sponsord and sponsord_onramp (and
  decdn_node's wording) describe both accepted forms, quoting and the index.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Mirror documentation omits required release-index overrides, causing documented offline or rate-limited deployments to fail.

0 open findings

4 resolved since last review
Previously missed (3)

In code that hasn't changed since last review

Low severity Mirror instructions omit the release-index override

ansible/​roles/​sponsord_onramp/​README.md:30

This now says a line is resolved through sponsord_onramp_release_index, but the mirror instruction names only sponsord_onramp_release_base. Standalone users following it still contact GitHub to resolve the line and can fail before reaching the mirrored downloads; document that both variables must point at the mirror.

Low severity Document required release-index overrides for offline mirrors

cloud-init/​README.md:213

For a release-line deployment, overriding these download bases alone does not make the documented mirror self-contained: sponsord_release_index still defaults to GitHub (and the installers' decdn line separately uses sponsord_onramp_decdn_release_index). Name the required index overrides so an offline or rate-limited cloud-init host can actually resolve from its mirror.

Low severity Mirror example omits the release-list endpoint override

cloud-init/​user-data-publisher.yaml:112

The default is now a release line, but the mirror example below overrides only the download base. Resolution still calls the default GitHub sponsord_release_index, so an offline or rate-limited cloud-init deployment configured from this example fails before using its mirror. Add the mirrored release-list endpoint too.

🧠 Review effort: Balanced

@thiras
thiras merged commit eb0be4b into main Oct 14, 2026
56 checks passed
@thiras
thiras deleted the feat/float-upstream-pins branch October 14, 2026 19:24
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.

2 participants