Skip to content

fix: address all High and Medium follow-up review items#22

Merged
c4po merged 1 commit into
mainfrom
chore/medium-priority-fixes
May 5, 2026
Merged

fix: address all High and Medium follow-up review items#22
c4po merged 1 commit into
mainfrom
chore/medium-priority-fixes

Conversation

@c4po

@c4po c4po commented May 5, 2026

Copy link
Copy Markdown
Contributor

Bundles the remaining High and Medium items from the latest review, plus the README typos and Go-version bump.

High

  • H-A getTerraformVersionConstraints no longer fails on parse errors in parent directories. A broken .tf in ~/scratch/foo previously bricked the wrapper everywhere under ~; now only the user's actual cwd is a hard failure, ancestors get logged and walked past.

Medium

  • M-A Forward SIGHUP/SIGQUIT on Unix via a build-tagged forwardedSignals slice — without SIGHUP, a closing terminal would orphan the child terraform process.
  • M-B Return 128 + signum when the child is killed by a signal (shell/terraform convention), instead of -1 from exec.ExitError.ExitCode(). Implemented as a build-tagged exitCodeFromError so Windows stays portable.
  • M-C zip.NewReader now reads size from zipFile.Stat(), not response.ContentLength (which is -1 for chunked responses).
  • M-D If os.Chmod fails after atomic.WriteFile succeeds, the partial file is removed so the next invocation re-downloads instead of forever cache-hitting a non-executable binary.
  • M-E Per-binary flock around the download path serializes concurrent invocations so they don't both re-download the same archive. Uses github.com/gofrs/flock.
  • M-F New TF_DEMUX_CACHE_HOME env var explicitly overrides the cache directory. os.UserCacheDir() ignores XDG_CACHE_HOME on macOS, so the integration suite has been writing into the real user cache; test.sh now sets TF_DEMUX_CACHE_HOME instead.
  • M-G Strip TF_DEMUX_* env vars before exec'ing terraform. Otherwise a one-shot TF_DEMUX_ALLOW_STATE_COMMANDS=true would silently extend through any nested terraform-demux invocation.
  • M-H Cache the parsed release index locally with a 5-minute TTL so rapid-fire invocations (shell completion, scripts) don't each pay an HTTP round-trip.

Polish

  • L-D Bump go.mod's go directive and both workflows' go-version to 1.24 (1.21 is past EOL).
  • L-F README typos: CompatabilityCompatibility, recommentrecommend (x3), and the three instead \terraform state mv` commandbullets reworded to active voice withof` inserted where the verb was missing.

Tests added

  • TestGetTerraformVersionConstraints_TolerantOfParentParseErrors — covers H-A regression.
  • TestFilterDemuxEnv_StripsTFDemuxKeys — covers M-G.
  • TestEnsureCacheDirectory_HonorsOverrideEnv — covers M-F.
  • TestListReleases_UsesLocalIndexTTL — covers M-H by closing the upstream test server between two calls and asserting the second one still succeeds.

Test plan

  • go test ./... clean
  • gofmt -l . clean
  • go vet ./... exit 0
  • Cross-platform build: GOOS=windows go build ./... clean
  • End-to-end smoke: `TF_DEMUX_ARCH=amd64 go run ./cmd/... -- -version` resolves correctly under testdata/terraform-pessimistic/

@c4po
c4po force-pushed the chore/medium-priority-fixes branch 3 times, most recently from 814c5b3 to acea145 Compare May 5, 2026 21:20
@c4po
c4po requested a review from Copilot May 5, 2026 21:22

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.

Pull request overview

This PR bundles follow-up items from the latest review by improving wrapper robustness (constraint parsing, signal/exit-code behavior, env isolation), strengthening and de-duplicating release download/caching logic, and updating docs/tests/CI to match the new behavior.

Changes:

  • Wrapper: tolerate parent-directory .tf parse errors, forward additional Unix signals, map signaled exits to 128+signum, and strip TF_DEMUX_* env vars before exec’ing Terraform.
  • Release client: add a 5-minute local TTL cache for the parsed index, fix zip size handling, remove partially-installed binaries on chmod failure, and serialize downloads with per-binary flock.
  • Tooling/polish: add targeted regression tests, introduce buffered logging helper, update README/test script, and bump Go version in module/workflows.

Reviewed changes

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

Show a summary per file
File Description
test.sh Uses TF_DEMUX_CACHE_HOME for integration tests to avoid macOS cache pollution.
README.md Fixes typos and documents TF_DEMUX_CACHE_HOME cache override.
internal/wrapper/wrapper.go Implements cache override, tolerant constraint loading, signal forwarding via build tags, exit-code normalization, and env filtering.
internal/wrapper/wrapper_test.go Adds regression coverage for tolerant parent parse errors, env filtering, and cache override.
internal/wrapper/signals_unix.go Adds SIGHUP/SIGQUIT forwarding on Unix.
internal/wrapper/signals_windows.go Defines Windows signal-forwarding set.
internal/wrapper/exitcode_unix.go Returns 128+signum when Terraform is killed by a signal.
internal/wrapper/exitcode_windows.go Keeps Windows exit-code behavior portable.
internal/wrapper/checkargs.go Moves state-command version constraints to package-level pre-parsed constants.
internal/wrapper/checkargs_test.go Updates tests to reuse shared mustVersion helper.
internal/wrapper/logging.go Introduces SetupLogging to buffer logs until flushed on error.
internal/wrapper/logging_test.go Adds tests for buffered vs verbose logging behavior.
internal/releaseapi/client.go Adds local index TTL caching, build selection helper, zip size fix, chmod cleanup, and per-binary download lock.
internal/releaseapi/client_test.go Refactors server fixtures and adds TTL cache test.
cmd/terraform-demux/main.go Switches to wrapper.SetupLogging and uses flush-on-error flow.
go.mod Bumps Go directive and adds gofrs/flock.
go.sum Updates sums for newly added/updated dependencies.
.goreleaser.yaml Injects release tag into main.version via ldflags.
.github/workflows/release.yaml Bumps Go version for release workflow.
.github/workflows/ci.yaml Expands unit test OS matrix and bumps Go version; adds integration job.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread go.mod
Comment thread README.md Outdated
(Updated to fold the code-quality review's High/Medium findings into
this PR.)

High
- H-A: getTerraformVersionConstraints tolerates parse errors in
  parent dirs.
- H1: client_test.go consolidates "stand up a fake release server"
  into a single serveRelease(t, version, zipBytes, shasumsBody) helper
  shared by all four download-related tests, plus a tiny newTestClient
  fixture for the happy-path cases.
- H2: getTerraformVersionConstraints split into a thin walk loop +
  loadConstraintsAt helper that returns (constraints, found, err).
- H3: DownloadRelease's match-build + nil-version-fallback logic
  extracted into findBuild(r, goos, arch) (Build, error).

Medium
- M-A: Forward SIGHUP / SIGQUIT (build-tagged forwardedSignals).
- M-B: 128+signum on signaled child (build-tagged exitCodeFromError).
- M-C: zip.NewReader uses zipFile.Stat().Size() instead of
  response.ContentLength.
- M-D: Cached binary is removed if Chmod fails post-write.
- M-E: Per-binary flock (gofrs/flock) serializes parallel downloads.
- M-F: TF_DEMUX_CACHE_HOME env override; test.sh uses it instead of
  XDG_CACHE_HOME.
- M-G: Strip TF_DEMUX_* from the env passed to the child terraform.
- M-H: 5-minute local TTL on the parsed release index.
- M1: Buffered-log-replay logic moved out of main.go into
  wrapper.SetupLogging(verbose, errSink) -> flush, with tests.
- M2: readIndexCache logs on corrupt-cache JSON unmarshal failure
  instead of silently re-fetching.
- M3: downloadBuild's unzip+install loop extracted into
  extractTerraformBinary; checksum and zip-reader setup also pulled
  into helpers, leaving downloadBuild as a linear five-step recipe.
- M4: Dedup mustVer/mustVersion test helpers (kept mustVersion).
- M5: GoDoc on package, ReleaseIndex, Release (incl. clarifying that
  Shasums is a *filename*, not a sum), Build, Client, NewClient,
  ListReleases, DownloadRelease, ShaSumsURL.

Polish
- L7: Renamed DownloadRelease's `os` parameter to `goos` (was
  shadowing the os package).
- L12: writeIndexCache uses atomic.WriteFile.
- L13: Documented TF_DEMUX_CACHE_HOME in README.
- L-D: Bump go.mod's go directive and CI go-version to 1.24.
- L-F: README typos fixed.

Tests
- New: TestSetupLogging_BuffersUntilFlush,
  TestSetupLogging_VerboseStreamsImmediately, parent-walk parse error
  tolerance, env filter, cache override, index TTL.
@c4po
c4po force-pushed the chore/medium-priority-fixes branch from acea145 to 7b208ad Compare May 5, 2026 21:29
@c4po
c4po merged commit 201e74f into main May 5, 2026
11 checks passed
@c4po
c4po deleted the chore/medium-priority-fixes branch May 5, 2026 22:21
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.

3 participants