Configure Self-Updating¶
GTB's UpdateCmd feature lets your tool check for newer releases and replace its own binary. This guide covers how to wire it up with a release backend. Six built-in source types are available out of the box: github, gitlab, bitbucket, gitea, codeberg, and direct. For anything else, see Add a Custom Release Source.
The update system has two parts:
1. props.Tool.ReleaseSource โ tells the framework where to find releases at compile time
2. Config (provider-specific subtree) โ provides the API token and endpoint at runtime
Step 1: Populate props.Tool in main.go¶
The Tool struct is constructed once at startup and injected into Props. Fill in the ReleaseSource field:
import (
"gitlab.com/phpboyscout/go-tool-base/pkg/props"
)
tool := props.Tool{
Name: "mytool",
Summary: "My developer tool",
ReleaseSource: props.ReleaseSource{
Type: "github", // see supported types below
Owner: "my-org",
Repo: "mytool",
},
}
For private repositories, set Private: true โ the framework will require a token and error early if none is found:
ReleaseSource: props.ReleaseSource{
Type: "github",
Owner: "my-org",
Repo: "mytool",
Private: true,
},
Supported source types¶
Type |
Platform | Notes |
|---|---|---|
"github" |
GitHub / GitHub Enterprise | Set Host for GHE instances |
"gitlab" |
GitLab / self-managed | Set Host for self-managed GitLab |
"bitbucket" |
Bitbucket Cloud Downloads | Version inferred from asset filenames |
"gitea" |
Gitea / Forgejo | Host is required |
"codeberg" |
Codeberg (Forgejo) | Host defaults to https://codeberg.org |
"direct" |
Arbitrary HTTP / S3 / CDN | URL template required in Params |
For a self-managed GitLab instance, also set Host:
ReleaseSource: props.ReleaseSource{
Type: "gitlab",
Host: "gitlab.example.com",
Owner: "my-group",
Repo: "mytool",
},
For a Gitea instance:
ReleaseSource: props.ReleaseSource{
Type: "gitea",
Host: "https://git.example.com",
Owner: "my-org",
Repo: "mytool",
},
For a direct download server:
ReleaseSource: props.ReleaseSource{
Type: "direct",
Repo: "mytool",
Params: map[string]string{
"url_template": "https://dl.example.com/{tool}/{version}/{tool}_{os}_{arch}.{ext}",
"version_url": "https://dl.example.com/latest.json",
},
},
See the Release Provider component for a full Params reference for each provider.
Step 2: Ensure UpdateCmd is Enabled¶
UpdateCmd is enabled by default. If you previously disabled it, re-enable it via SetFeatures:
To disable it (e.g. for internal tools distributed another way):
Step 3: Configure the Token¶
The framework reads token configuration from the relevant subtree of your config file. Add defaults to your embedded config asset (e.g. assets/config/defaults.yaml):
For GitHub:
github:
url:
api: "" # leave empty for github.com; set for GitHub Enterprise
upload: ""
auth:
env: GITHUB_TOKEN # environment variable to read
value: "" # or set a literal token here (not recommended for public repos)
For GitLab:
gitlab:
url:
api: "" # leave empty for gitlab.com; set for self-managed
auth:
env: GITLAB_TOKEN
value: ""
Users then set the environment variable before running the update command:
Step 4: Build with ldflags Version Info¶
The update command compares the running version against the latest release tag. It needs Version to be set at build time via ldflags. In your goreleaser.yaml or Makefile:
In main.go, wire the version into Props:
var (
version = "dev"
commit = "none"
)
func main() {
p := &props.Props{
Tool: tool,
Version: props.Version{
Version: version,
Commit: commit,
},
}
// ...
}
When version == "dev", the update check is automatically skipped โ no API calls are made during local development.
Step 5: Verify¶
Build a release binary and run:
mytool update --check # check without applying
mytool update # check and apply if newer version found
Expected output when up to date:
Expected output when an update is available:
INFO Update available current=v1.2.3 latest=v1.3.0
INFO Downloading update...
INFO Update applied successfully. Restart to use the new version.
Throttling¶
By default, the update check runs at most once per 24 hours (stored in the tool's config directory). This prevents hammering the API on every command invocation. The throttle interval is configurable:
Air-Gapped / Offline Environments¶
For environments without network access, the update command supports installing from a local release archive. This workflow has three steps:
1. Download on a connected machine¶
Download the release archive and checksum from the GitHub/GitLab releases page:
# On a machine with internet access
curl -LO https://github.com/my-org/mytool/releases/download/v1.3.0/mytool_Linux_x86_64.tar.gz
curl -LO https://github.com/my-org/mytool/releases/download/v1.3.0/mytool_Linux_x86_64.tar.gz.sha256
2. Transfer to the target machine¶
Copy both files to the air-gapped machine via USB, SCP, or your internal artifact pipeline.
3. Install from file¶
The checksum sidecar is automatically detected and verified. No API token or network access is required.
The --from-file flag is mutually exclusive with --version. The --force flag has no effect on offline updates since no version comparison is performed.
Related Documentation¶
- Auto-Update Lifecycle โ how the update loop works
- Release Provider component โ all built-in providers, registry API, and
Paramsreference - Add a Custom Release Source โ register your own provider for any backend
- GitHub component โ
NewGitHubClientand token resolution - GitLab component โ
NewReleaseProviderfor GitLab - Configuring Built-in Features โ enabling and disabling UpdateCmd