ETag-aware conditional poll + Go 1.26 bump#76
Merged
Conversation
3 tasks
franklinkim
approved these changes
Apr 29, 2026
Updates go.mod from 1.25.4 to 1.26.0. Tests pass under the new toolchain. The bump enables Go 1.26 runtime improvements for downstream users (notably Green Tea GC via GOEXPERIMENT=greentea at build time). Fixes two format-string errors that Go 1.26's stricter vet now catches: - responses/error.go: use %d for int Status/Code fields (was %q) - pkg/repo/loader.go: use %d for http.StatusOK int argument (was %q)
When --poll=true is enabled, the loader now sends If-None-Match with the last-seen ETag on each poll request. On 304 Not Modified the body fetch is skipped entirely. Behavior is fully backward compatible: if the upstream server does not send ETag headers, lastETag stays empty, no If-None-Match header is ever sent, and the existing URL-in-body comparison continues to work unchanged. The two skip mechanisms (ETag and URL-in-body) coexist: ETag short-circuits earliest (no body read), URL-in-body remains the fallback for servers without ETag support. Adds test coverage for: no-ETag backward compat, ETag-then-304 skip, ETag value change handling, and absent If-None-Match on first call.
Test file picked up four lint categories that CI rejected: goconst (extract /poll and /repo paths to constants), gofmt (collapse stray double-space before nolint comment), gosec G705 (test-server response writes flagged as XSS-via-taint; nolint with rationale since r.Host is the test server's own address), and testifylint (assert.Empty replaces assert.Equal-with-empty-string for clarity). Also bump .golangci.yml's go directive from 1.24.3 to 1.26.0 so the linter analyses code under the same Go version go.mod now declares.
9922251 to
8b438cc
Compare
This was referenced Apr 29, 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.
Hey — small PR to add ETag-aware conditional polling to the loader, plus the Go bump that makes Green Tea GC reachable for downstream services.
What this is for
We've been hitting a sharp edge with
--poll=true: the URL-in-body skip works great when the upstream returns a stable URL, but the moment the upstream uses signed URLs (which change every request) every poll downloads and re-applies the whole repo even when nothing has changed. ETag is the standard HTTP fix for exactly this — server tags responses with a stable revision, client sendsIf-None-Match, server returns304 Not Modifiedif unchanged, and we skip the body entirely.Importantly: this change is purely additive. If your upstream doesn't speak ETag, nothing changes.
How the loader behaves now
If-None-Match(we haven't seen an ETag yet). Same wire as today.ETagon a 200: we remember it. Same response handling otherwise.If-None-Match: <last seen>. If the server replies304 Not Modifiedwe skip the body read entirely. If it replies200with a new ETag, we update our copy and proceed.What's in the diff
Test plan
A note on the Go bump
Some downstream services (us included) want to enable Green Tea GC via `GOEXPERIMENT=greentea`, which is a build-time experiment that Go 1.25+ understands. Bumping the toolchain here unblocks that without forcing every downstream to also fork. Happy to split the bump into a separate PR if you'd prefer.
Let me know if anything in the design rubs you wrong — happy to iterate.
Rolled-in dependency bumps
To ship a single secure, up-to-date PR rather than three serialized ones, this branch also rolls up the open Dependabot bumps. The same upgrades land here at the highest (newest) version from each:
3.22.0→3.22.2inbuild/buildx.Dockerfile(supersedes chore(deps): bump alpine from 3.22.0 to 3.22.2 in /build in the docker-update group #69)foomo/keel 0.22.0→0.22.1,cobra 1.10.1→1.10.2,gocloud.dev 0.43.0→0.44.0(supersedes chore(deps): bump the gomod-update group across 1 directory with 5 updates #73)golang.org/x/net 0.47→0.52,golang.org/x/sync 0.18→0.20,go-jose/v4 4.1.3→4.1.4(GHSA-78h2-9frx-2jm8 — JWE decryption panic), AWS SDK + otel bumps (supersedes chore(deps): bump the gomod-security group across 1 directory with 5 updates #77)go test ./... -raceandgolangci-lint run ./...(v2.11.4) both clean against the rolled-upgo.mod.PRs #69, #73, #77 will be closed once this merges.