Upgrading
autocom checks for new versions in the background after every command and can replace its own binary in place. This page covers the user-facing flow, the version-check cache, and how releases are produced.
TL;DR
autocom upgrade --check # see what's available
autocom upgrade # update to latest
autocom upgrade --target 1.2.3 # specific version
brew upgrade autocom # if installed via Homebrew
How the version check works
- After every successful command, the CLI starts an async goroutine that polls the GitLab Releases API at
/api/v4/projects/autocommerce%2Fcli/releases?per_page=10. - The result is cached at
~/.autocom/upgrade-check.jsonwith a 24-hour TTL — repeat invocations within the window don't poll the network. - If a newer release is found, the CLI prints a one-line nudge to stderr after subsequent commands:
↑ autocom 1.1.0 available (you're on 1.0.0)
Run `autocom upgrade` to update — or `autocom upgrade --check` to see what's new.
- The nudge is throttled to once every 6 hours so you don't see it on every command.
The check is fully best-effort. Network failures, offline laptops, and corp proxies are all silent — the CLI never blocks on it.
Opting out
Three ways to disable the background check:
| Mechanism | Scope |
|---|---|
autocom config set no_telemetry true |
Permanent, all invocations |
AUTOCOM_NO_UPGRADE_CHECK=1 |
Per-shell or per-command env var |
Pipe to cat, jq, etc. (non-TTY stdout) |
Per-command — the nudge is TTY-only |
The dev build (run via go run . or go install without -ldflags) skips the check unconditionally, since version comparisons against dev always fail.
autocom upgrade — running the update
autocom upgrade [--check] [--force] [--target <ver>] [--dry-run] [--allow-homebrew]
What happens, step by step:
- Resolve target release — fetch the matching release from GitLab Releases.
- Homebrew guard — refuse if the running binary path looks like a Homebrew install (
/Cellar/,/homebrew/,/.linuxbrew/). Override with--allow-homebrewif you really mean it. - Find asset — match
autocom_<version>_<os>_<arch>{.tar.gz,.zip}against the release's asset list (built fromcli/.goreleaser.yaml). - Download + verify SHA256 — pull both the archive and the
SHA256SUMS.txtpublished with the release; compute the archive's SHA256 and compare. Mismatch aborts with no changes to disk. - Extract — pull
autocom(orautocom.exeon Windows) out of the archive. - Atomic replace — write the new binary to a sibling temp file,
chmod 0755,os.Renameover the running binary. On Windows, the running.execan't be renamed-over, so the old file is moved aside to<bin>.oldfirst.
If the SHA256 check fails or the download is interrupted, the original binary is untouched.
Flags
| Flag | Effect |
|---|---|
--check |
Read-only — print version comparison + release notes excerpt, don't install |
--force |
Reinstall even when already on latest (useful after a corrupted binary) |
--target 1.2.3 |
Install a specific version instead of latest. Useful for downgrades and pinning. |
--dry-run |
Download + verify the asset, but skip the binary replace |
--allow-homebrew |
Bypass the Homebrew guard. Don't — brew upgrade autocom is what you want |
Exit codes
Same as the rest of the CLI — see Troubleshooting → Exit codes. The most common ones for upgrade are 5 (network), 6 (server / SHA mismatch / asset not found), and 1 (file-system errors during the swap).
Versioning
The CLI follows SemVer 2.0. Tags use the cli/v<semver> prefix so the same Git repo can host other release tracks later (e.g. theme/v1.0.0).
| Bump | When |
|---|---|
Patch (1.0.0 → 1.0.1) |
Bug fixes, no behavior change for end users |
Minor (1.0.0 → 1.1.0) |
New commands, new flags — backward compatible |
Major (1.x.x → 2.0.0) |
Breaking change — flag removed, exit code repurposed, output schema changed |
The current version lives at cli/VERSION in the source tree and is injected into the binary at link time:
go build -ldflags="-X gitlab.wexron.io/autocommerce/cli/internal/version.Version=$(cat cli/VERSION) ..."
autocom version prints both the version and the git short-SHA the build came from.
Release pipeline
Releases are produced by goreleaser running in CI on v* tag pushes. The pipeline is defined in two places:
- In the monorepo:
ci/templates/cli-tests.ymlruns vet + tests + snapshot-build on every MR / main push that touchescli/**. Snapshot mode skips the publish step — CI verifies that a release WOULD work, but doesn't actually create one. - In the standalone mirror repo (
autocommerce/core/cli, populated by the existingmodule-splitmechanism):cli/.gitlab-ci.ymlruns goreleaser onv*tags, publishes to:- GitLab Generic Package Registry —
autocommerce/core/cli/-/packages - Homebrew tap —
autocommerce/homebrew-tap - GitLab Release entry — with
SHA256SUMS.txt,MANIFEST.json, and the 5 OS/arch archives
- GitLab Generic Package Registry —
CI gates on every CLI MR
| Job | When | Blocks merge? |
|---|---|---|
cli:vet-and-test |
MR / main push touching cli/** |
✓ Yes |
cli:version-check |
Same | Advisory — warns if cli/VERSION didn't bump |
cli:lint (staticcheck) |
Same | Advisory |
cli:build-snapshot |
Same | Advisory — verifies cross-compile |
Path filtering: if your MR doesn't touch cli/** or ci/templates/cli-tests.yml, none of these jobs fire. A backend-only or docs-only MR pays zero CLI CI cost.
Cutting a release
# 1. Bump cli/VERSION in a normal MR, get it reviewed + merged
echo "1.1.0" > cli/VERSION
git add cli/VERSION cli/CHANGELOG.md
git commit -m "chore(cli): bump to 1.1.0"
# 2. After merge, tag main
git tag cli/v1.1.0
git push gitlab-main cli/v1.1.0
# 3. Pipeline does the rest — goreleaser builds, publishes,
# creates the GitLab Release entry, updates Homebrew tap.
The first time you cut a release, you also need to:
- Pre-create the
autocommerce/core/cliGitLab project (it's the subtree-split mirror target). - Pre-create the
autocommerce/homebrew-tapGitHub or GitLab project. - Set
HOMEBREW_TAP_TOKENas a CI/CD variable on the mirror project.
After that, every tag push is hands-off.
Self-hosted forks
If you deploy AutoCom yourself and want self-update to work against your own GitLab instance:
# Build with your own registry endpoints baked in
go build -trimpath -ldflags="\
-X gitlab.wexron.io/autocommerce/cli/internal/version.Version=1.1.0 \
-X gitlab.wexron.io/autocommerce/cli/internal/upgrade.APIBaseURL=https://gitlab.your-co.io \
-X gitlab.wexron.io/autocommerce/cli/internal/upgrade.ProjectPath=your-group%2Fcli \
-s -w" \
-o autocom ./
The CLI doesn't ship a runtime override flag for the registry URL — by design, so a malicious env var can't redirect the user to a hostile binary source.
Quick reference
# Inspect
autocom version # what version is this binary
autocom upgrade --check # what's available
cat ~/.autocom/upgrade-check.json # cached check result
# Apply
autocom upgrade # latest
autocom upgrade --target 1.0.5 # specific
autocom upgrade --dry-run # verify only
# Disable the nudge
export AUTOCOM_NO_UPGRADE_CHECK=1 # per-shell
autocom config set no_telemetry true # permanent