Skip to content

feat(updates): add release discovery engine - #841

Merged
mcharles-square merged 7 commits into
mainfrom
codex/release-updates-01-discovery
Jul 31, 2026
Merged

feat(updates): add release discovery engine#841
mcharles-square merged 7 commits into
mainfrom
codex/release-updates-01-discovery

Conversation

@mcharles-square

@mcharles-square mcharles-square commented Jul 30, 2026

Copy link
Copy Markdown
Collaborator

Reviewable diff: +1537/-2 across 13 files (excludes generated, test, and story files).

Summary

Adds a dormant GitHub release-discovery engine that identifies the newest canonical stable and release-candidate builds. Production discovery is fixed to the Proto Fleet repository, runs at most hourly with subtract-only jitter, and exposes no operator experience until downstream PRs wire it into fleetd.

Stack: #841#842#843#844#845#835#836#837#838#839#840. This is 1/5 of phase one, relative to main. Contract/storage, backend delivery, client surfaces, and host execution remain downstream.

How it works

Each cycle makes two baseline requests to the fixed /releases/latest endpoint and page 1 of /releases?per_page=100&page=1. Responses are capped at 8 MiB and the list is stream-decoded, rejecting the 101st entry. Exact tag grammar and semver validation select the maximum stable and RC candidates; prerelease metadata and release-note links are derived from that classification and the fixed repository rather than upstream body fields.

Baseline responses are cached by ETag and reused on 304; an optional GitHub token makes unchanged authenticated polls quota-free. A reported rate limit suppresses requests until reset. If a higher cached candidate ages out of the bounded responses, the checker conditionally revalidates it through /releases/tags/{tag} before keeping it eligible. A 404 or channel reclassification drops it; a transient, malformed, or mismatched response retains the data for retry but marks only that channel unavailable, with one warning after three consecutive failures.

Stable and RC availability are exposed through invariant-preserving accessors, allowing a fresh RC-only snapshot to remain useful to Stable+RC operators. Startup checks immediately, then repeats every configured hour minus 10–20% jitter (48–54 minutes). Each polling iteration contains panics so a defect in this best-effort feature cannot crash fleetd, and the next scheduled cycle still runs.

flowchart LR
  G["Fixed Proto Fleet GitHub endpoints"] --> B["Two bounded baseline response readers"]
  B --> V["Canonical stable and RC validation"]
  V --> S["Snapshot: releases, fetched-at, per-channel availability"]
  S --> R["Conditional exact-tag revalidation for aged-out cached candidates"]
  R --> S
  S --> D["Dormant until backend wiring"]
Loading

Areas of the code involved

Area / package / file What changed Why it matters for review
server/internal/domain/updates/github.go Fixed baseline client, authenticated ETag caching, rate-limit suppression, body/count bounds, strict JSON handling Network, quota, withdrawal, and allocation boundary
server/internal/domain/updates/checker.go Hourly jitter, semver selection, snapshot accessors, cache revalidation visibility, panic containment Release eligibility and outage semantics
server/internal/domain/updates/config.go Hourly default, optional GitHub token, and allowlisted download origin Configuration and command trust boundary
server/internal/domain/updates/*_test.go, testdata/ Hostile payload, grammar, ETag/auth, rate-limit, panic, withdrawal, outage, and lifecycle coverage Tests/fixtures
plugin/asicrs/Dockerfile.build Package-aware cleanup of the dummy dependency-warmup artifact Ensures Cargo rebuilds the real plugin across nightly toolchain changes
docs/plans/...release-update-notifications-plan.md Updated end-to-end design Review context; no runtime effect

Key technical decisions & trade-offs

  • Use two fixed baseline requests and at most one conditional exact-tag lookup per aged-out channel candidate, chosen over unbounded historical pagination.
  • Treat 404 or channel reclassification as confirmed withdrawal; treat transient or malformed revalidation as unknown and suppress only that channel until retry.
  • Keep the 8 MiB and 100-entry guards even with a trusted host, because the remote response remains outside fleetd’s control.
  • Use subtract-only jitter so simultaneous restarts spread out without exceeding the one-hour maximum interval.
  • Reject negative and sub-five-minute nonzero overrides so jitter cannot truncate into a busy loop.
  • Retain cached release data on failure for later retry, but exclude unverified candidates from downstream offers.
  • Warn once after three failed exact-tag revalidations instead of dropping a candidate that has not been confirmed withdrawn.
  • Cache baseline responses by ETag and support optional authentication; unauthenticated polling remains functional for zero-config installs.
  • Derive RC classification and release-note links from canonical tags and the fixed repository rather than trusting upstream presentation fields.
  • Recover per polling iteration so the next cycle continues; recovered programming defects log at Error with a stack trace while ordinary fetch failures remain Debug-only.
  • Emit generic configuration errors and strip request URLs from transport errors so rejected configuration cannot leak.
  • Use cargo clean --release -p asicrs-plugin after dependency warmup so Cargo owns package invalidation while retaining the warmed dependency graph.

Testing & validation

  • go test -race ./internal/domain/updates -count=1
  • golangci-lint run ./internal/domain/updates
  • Exact-tag tests cover confirmed withdrawal, reclassification, transient failure, tag mismatch, and trailing JSON.
  • Cache tests cover authenticated 304 reuse, stable/RC preservation, rate-limit reset suppression, and independent channel degradation.
  • Lifecycle tests cover per-cycle panic containment and continuation.
  • Required GitHub checks pass for the updated head.

@github-actions github-actions Bot added documentation Improvements or additions to documentation dependencies Pull requests that update a dependency file server labels Jul 30, 2026
@github-actions

github-actions Bot commented Jul 30, 2026

Copy link
Copy Markdown

🔐 Codex Security Review

Note: This is an automated security-focused code review generated by Codex.
It should be used as a supplementary check alongside human review.
False positives are possible - use your judgment.

Scope summary

  • Reviewed pull request diff only (6bb5518d56884c6ca78b48d6649629efaea10993...5cbabe85a095da9516c6b3007371f92dfb2362ad, exact PR three-dot diff)
  • Model: gpt-5.5

💡 Click "edited" above to see previous reviews for this PR.


Review Summary

Overall Risk: NONE

Findings

No security, correctness, or reliability findings were identified in the scoped diff.

Notes

Reviewed only .git/codex-review.diff for commit 5cbabe85a095da9516c6b3007371f92dfb2362ad. The implementation changes are limited to the release checker package and tests, a go.mod dependency promotion, release test fixtures, the planning document, and a Rust ASIC plugin Docker build cleanup adjustment. I did not run the test suite because the review environment is read-only.


Generated by Codex Security Review |
Triggered by: @mcharles-square |
Review workflow run

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds a new server/internal/domain/updates package that periodically discovers the newest canonical stable and RC releases from the GitHub Releases API, with bounded streaming JSON decoding and strict tag/url validation. This lays the groundwork for later update-status RPCs and operator UX (stacked PRs), without wiring this engine into fleetd yet.

Changes:

  • Introduce a bounded GitHub Releases client with ETag caching, pagination caps, and streaming decode guards.
  • Add a checker lifecycle job that selects latest stable + latest RC via strict tag grammar and semver ordering, and publishes an immutable snapshot.
  • Add config validation for the Releases API URL and an allowlisted download origin, plus fixtures and extensive unit tests.

Reviewed changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
server/internal/domain/updates/github.go Streaming, bounded GitHub Releases API client with ETag caching and strict decode limits
server/internal/domain/updates/checker.go Release selection logic (stable + RC), snapshot caching, lifecycle + jittered polling
server/internal/domain/updates/config.go Checker configuration and validation (HTTPS API URL + allowlisted download base)
server/internal/domain/updates/config_test.go Config validation tests, including hostile download-base inputs
server/internal/domain/updates/checker_test.go End-to-end unit tests for paging, ETag, malformed/oversized payloads, selection invariants, and lifecycle
server/internal/domain/updates/testdata/releases.json Mixed release list fixture (nightlies, PR builds, drafts, RCs, stable)
server/internal/domain/updates/testdata/releases_rc_order.json RC ordering fixture to ensure numeric semver prerelease comparison
server/internal/domain/updates/testdata/releases_nightlies.json Fixture ensuring RC discovery behind many nightly entries
server/internal/domain/updates/testdata/releases_malformed_entry.json Fixture validating malformed entries are skipped without failing the cycle
server/internal/domain/updates/testdata/latest_stable.json /releases/latest stable fixture
server/internal/domain/updates/testdata/latest_misflagged_rc.json Fixture ensuring prerelease-tag grammar blocks “stable” offer even if misflagged
server/internal/domain/updates/testdata/latest_invalid_tag.json Fixture ensuring invalid/non-semver latest tags are rejected
server/go.mod Promote semver dependency (golang.org/x/mod) (and otel/trace) to direct requirements
docs/plans/2026-07-27-001-feat-release-update-notifications-plan.md Phase plan documenting constraints, sequencing, and security boundaries

Comment thread server/go.mod
Comment thread server/internal/domain/updates/github.go

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c3d2063451

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread server/internal/domain/updates/github.go Outdated
@mcharles-square
mcharles-square force-pushed the codex/release-updates-01-discovery branch from c3d2063 to 8b608b3 Compare July 30, 2026 15:25

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8b608b3786

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread server/internal/domain/updates/checker.go Outdated
Comment thread server/internal/domain/updates/checker.go Outdated
@mcharles-square
mcharles-square force-pushed the codex/release-updates-01-discovery branch from 8b608b3 to 4b10f2e Compare July 30, 2026 16:56

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4b10f2e7bc

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread server/internal/domain/updates/github.go Outdated
@mcharles-square
mcharles-square force-pushed the codex/release-updates-01-discovery branch 2 times, most recently from e3bb148 to f9ef184 Compare July 30, 2026 17:40
@mcharles-square
mcharles-square force-pushed the codex/release-updates-01-discovery branch 3 times, most recently from 563e62c to 642aeff Compare July 30, 2026 17:58
Comment thread docs/plans/2026-07-27-001-feat-release-update-notifications-plan.md Outdated
Comment thread docs/plans/2026-07-27-001-feat-release-update-notifications-plan.md Outdated
Comment thread docs/plans/2026-07-27-001-feat-release-update-notifications-plan.md Outdated
Comment thread docs/plans/2026-07-27-001-feat-release-update-notifications-plan.md Outdated
@mcharles-square
mcharles-square force-pushed the codex/release-updates-01-discovery branch from 642aeff to ef0efbf Compare July 31, 2026 04:53

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ef0efbf8e5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread server/internal/domain/updates/checker.go Outdated
Comment thread server/internal/domain/updates/config.go
@mcharles-square
mcharles-square force-pushed the codex/release-updates-01-discovery branch from ef0efbf to 66db0f5 Compare July 31, 2026 05:03

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 66db0f5577

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread server/internal/domain/updates/checker.go

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2896f97f82

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread server/internal/domain/updates/checker.go
@mcharles-square
mcharles-square force-pushed the codex/release-updates-01-discovery branch from 2896f97 to dc9f7ea Compare July 31, 2026 07:39

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: dc9f7ea4cf

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread server/internal/domain/updates/checker.go Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 04031bed7e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread server/internal/domain/updates/checker.go Outdated
Comment thread server/internal/domain/updates/checker.go
Comment thread server/internal/domain/updates/checker.go
Comment thread server/internal/domain/updates/checker.go
Comment thread server/internal/domain/updates/checker.go
Comment thread server/internal/domain/updates/checker.go Outdated
Comment thread server/internal/domain/updates/checker.go
Comment thread server/internal/domain/updates/checker.go Outdated
@github-actions github-actions Bot added review-policy: human-approved Managed by the Review Policy workflow. and removed review-policy: needs-review Managed by the Review Policy workflow. labels Jul 31, 2026
@github-actions github-actions Bot added review-policy: needs-review Managed by the Review Policy workflow. and removed review-policy: human-approved Managed by the Review Policy workflow. labels Jul 31, 2026
@mcharles-square
mcharles-square merged commit 6d0beee into main Jul 31, 2026
131 of 138 checks passed
@mcharles-square
mcharles-square deleted the codex/release-updates-01-discovery branch July 31, 2026 15:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file documentation Improvements or additions to documentation review-policy: needs-review Managed by the Review Policy workflow. server

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants