We moved one Go variable and every copy of our new CLI was told to upgrade
We publish a command line tool that our partners use to book collections and download labels from our API. Version 2.7.0 went out on a Tuesday in September. By Wednesday afternoon support had forty tickets, all saying the same thing: every command answered with a message telling them their client was too old and to upgrade. They had all just upgraded. The tool learns its own version at build…
Version 2.7.0 of the command line tool was released on a Tuesday in September. However, by Wednesday afternoon, support was overwhelmed with forty tickets all citing the same issue: commands responded with messages demanding users upgrade their client as it was deemed too old. The tool inherently learns its version during the build process.
The release workflow compiles the tool using the 'go build' command and an 'ldflags' option that sets a version string in the package main. This variable was moved to a package named 'internal/buildinfo' in version 2.7.0, and the ldflags line in the workflow still referenced 'main.version'. Despite the build process passing without errors, every signed and published binary perceived itself as 'dev'.
This misidentification persisted because the Go linker ignored undefined symbols, including the newly placed version string. The tool included its version in a header on every request, and the API gateway started refusing clients older than version 2.4.0 due to the removal of a dependent endpoint. The gateway's handling of unreadable versions improved, allowing them through but logging them for review.
A default version resembling a real one could bypass all tests and reach production undetected. The release workflow now verifies the binary's version command against the release tag before signing, preventing the inadvertent distribution of outdated software.
Written by urgent.news from Dev.to's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.