Skip to content

v1.226.0-rc.8

Pre-release
Pre-release

Choose a tag to compare

@cloudposse-releaser cloudposse-releaser released this 15 Aug 00:36
6f30e1a
feat(toolchain): add update command, fix version-pinning bugs Erik Osterman (Cloud Posse) (@osterman) (#2894) ## what
  • Adds atmos toolchain update [tool...] to move a pinned tool to its newest available version and reinstall it, with --dry-run and bounded --max-concurrency. Tools pinned to pr:/sha:/ref: are skipped with an explanation instead of silently left alone.
  • Fixes which/exec resolving the wrong version (last token instead of the default first token) on a multi-version .tool-versions line, which caused false "not installed" errors.
  • Fixes set appending instead of replacing the default version, contradicting its documented behavior.
  • Fixes add/install silently accepting SemVer range syntax (^1.2.0, ~>1.0.0) and only failing later with a raw HTTP 404; now rejected immediately with a hint toward dependencies.tools/atmos version track.
  • Fixes atmos version track add/set corrupting any value containing <, >, or & (a json.Marshal HTML-escaping bug), which broke the exact ~>/>= constraint syntax the toolchain docs recommend.
  • Fixes atmos toolchain versions --help silently rendering the wrong command's help and exiting 0 instead of erroring; fixed globally in root help routing (atmos <cmd> <bogus-subcommand> --help now errors for every command tree). Removes the stale toolchain-versions and toolchain-aliases docs/casts for commands that were never implemented.
  • Implements six previously documented-but-missing flags: list --format/--installed-only/--pending-only, clean --dry-run/--cache-only/--force, exec --dry-run.
  • Fixes updateToolVersionsFile writing to the hardcoded default .tool-versions path instead of the configured one.
  • Adds a changelog post and roadmap entry for the new update command.

why

  • A field test of atmos toolchain surfaced that there was no way to update a pinned tool to a newer version, and no clear signal for why range/constraint syntax (^1.2.0, ~>1.0.0) didn't work when the docs implied it should.
  • Live-testing the closest existing workaround (add <tool>@latest + install --reinstall) reproduced a real crash in which/exec, which led to finding the rest of the bugs above along the way — a documented set behavior that didn't match reality, a JSON-escaping bug corrupting exactly the constraint syntax the toolchain skill doc recommends, and a help-routing bug that let atmos toolchain versions --help silently succeed for a command that doesn't exist (which is also why its docs page and cast looked legitimate despite documenting nothing real).
  • Together these close the gap between what atmos toolchain's docs promised and what the CLI actually did, and give users a real, safe way to move a pinned tool forward.

references

  • Field test and fix session: this branch (osterman/toolchain-update-pinning-field-test)

Summary by CodeRabbit

  • New Features

    • Added toolchain update for selected or all tools, with dry-run and concurrency controls.
    • Added toolchain lock to verify artifacts and create lock entries without installation.
    • Added dry-run, filtering, format, cache-only, force, and default-version options across toolchain commands.
    • Added JSON, plain-text, and table output for tool listings.
    • Added toolchain uninstall --all.
    • Added support for multiple tool versions in lockfiles.
  • Bug Fixes

    • Improved help validation, version handling, lockfile migration, and checksum verification.
    • Prevented tool references from rendering as email links.
  • Documentation

    • Updated toolchain guidance and added update and lock documentation.
feat(scaffold): add --merge-driver flag to force text-based merging Jorrit Elfferich (@jorrite) (#2925) ## what
  • Adds a --merge-driver flag (auto / text) to atmos scaffold generate --update and atmos init --update, alongside the existing --merge-strategy flag.
  • auto (default) is today's existing behavior: pick the merger by file extension (YAML-aware for .yaml/.yml, line-oriented text otherwise).
  • text forces every file — YAML included — through the line-oriented diff3 merger, bypassing the YAML-aware re-encode that has no concept of blank lines between blocks and silently drops them on every update, even when nothing meaningful changed.
  • Adds a changelog post and roadmap entry for the new flag.

why

Structure-aware YAML merging is the right default for most files, but it re-encodes the whole document through a YAML parser/serializer, and formatting like blank lines between top-level blocks isn't part of what a YAML parser models. Templates that bundle CI pipeline YAML (a common convention uses blank lines to visually separate jobs/stages) lost that formatting on every --update, whether or not the file actually changed. --merge-driver=text gives users an explicit opt-out, mirroring git's own merge driver concept (auto/text), so this class of file can go through the same merge algorithm git merge itself uses on ordinary text files.

references

Closes #2886.

Summary by CodeRabbit

  • New Features

    • Added --merge-driver to initialization and scaffold generation commands.
    • Choose auto for YAML-aware merging or text for line-oriented merging that preserves formatting.
    • Invalid values now return a clear error.
  • Documentation

    • Documented the option, supported modes, and usage examples.
    • Added the feature to the shipped product roadmap and published a related blog post.
  • Chores

    • Added a new contributor profile to the website.
ci(test): make macOS k3s reliable by fixing the colima timeout budget Michael Pursifull (@arcaven) (#2936) ## Why

[k3s-macos] is a required check (via [k3s] demo-helmfile) and flakes on unrelated PRs, costing the full step budget each time and blocking merge. The failure is entirely in CI setup: the job dies at "Start Docker-compatible runtime on macOS" without running a single helm test. Closes #2935.

What

The colima setup ladder was longer than the step cap that contained it, so the step was guillotined before the ladder could finish, and a status-propagation bug hid which rung actually failed. This PR makes the ladder shorter than its cap instead of growing the cap:

  • vz only; the qemu fallback is removed. docs/fixes/2026-07-01-macos-k3s-runner-research.md already selected vz for macos-15-intel and records qemu failing there on usernet unable to resolve IP for SSH forwarding before any test ran, and a green run (31723563772) confirms vz starting on attempt 1 with the whole setup step under 6 minutes. The qemu rung (plus its 7-minute brew install qemu cap) was a dead rung that only added minutes to the failure path. Two bounded vz attempts remain as the half-started-VM mitigation.
  • Fix failure propagation in start_colima. status=$? ran after the completed if, which reads the if statement's own zero when no branch executes, so the function returned success after every attempt had failed and the job died later at docker version with a misleading error. The status is now captured in the else branch.
  • docker pull rancher/k3s:latest moves out of the start/retry loop and retries on its own (two independent 5-minute attempts). In the loop, a slow or rate-limited Docker Hub pull counted as a runtime-start failure and forced a full VM delete + rebuild, so registry flakiness masqueraded as hypervisor flakiness.
  • Diagnostics are kept after every failed attempt, including the last, and bounded (colima status and limactl list capped at 30s so they cannot hang the step). Teardown and backoff run only between attempts; after the final failure the runner is discarded, so cleanup is dead time.
  • Step cap 40 minutes; the job-level 60-minute cap is unchanged, preserving fail-fast behavior; the observed healthy setup leaves ample time for both 15-minute test attempts.

Timeout arithmetic

Caps on the setup path: brew installs 7m + initial cleanup 1.5m + two vz start/info attempts 10m each + bounded diagnostics and intermediate cleanup ~3m + docker verify 1m + two 5-minute pull attempts with backoff. Every cap hit simultaneously sums to ~43 minutes; the 40-minute cap deliberately undercuts that. The recovery path fits when the final image pull completes normally; anything past 40 is treated as pathological. The observed healthy path is under 6 minutes.

Cost of merge

CI-only; no product code changes. The failure mode changes shape: instead of a slow crawl through a dead qemu rung, a runner where vz cannot start now fails hard after two bounded attempts, with diagnostics captured both times.

Out of scope (raised in #2935)

Pinning the k3s image would need a change to pkg/emulator/driver/k3s.go (the ref is hardcoded there), so this PR keeps :latest to stay CI-only. And macos-15-intel is on GitHub's deprecation path; a longer-term plan for [k3s-macos] is noted in the issue.