Reputation: 5552
I'm trying to read version control information from my Go binaries, but the build info doesn't seem to contain any VCS info.
From the Go 1.18 release notes:
The go command now embeds version control information in binaries. It includes the currently checked-out revision, commit time, and a flag indicating whether edited or untracked files are present. Version control information is embedded if the go command is invoked in a directory within a Git, Mercurial, Fossil, or Bazaar repository, and the main package and its containing main module are in the same repository. This information may be omitted using the flag -buildvcs=false.
Sample program:
package main
import (
"fmt"
"runtime/debug"
)
func main() {
if bi, ok := debug.ReadBuildInfo(); ok {
fmt.Printf("%+v\n", bi)
}
}
Using this code, here's my output:
go go1.18 path [redacted] mod [redacted] (devel) dep [redacted] v1.2.3 build -compiler=gc build CGO_ENABLED=1 build CGO_CFLAGS= build CGO_CPPFLAGS= build CGO_CXXFLAGS= build CGO_LDFLAGS= build GOARCH=amd64 build GOOS=windows build GOAMD64=v1
I expected to see this included, but didn't:
build vcs=git build vcs.revision=[sha] build vcs.time=2022-03-28T03:11:12Z build vcs.modified=true
I'm running the go
command from the root directory of a git repo, and the repo has commits. The program I'm building is in a subdirectory of the repo.
I have tried a number of different variations for building the binary, but none of them worked:
go run client/main.go
go build -o client.exe client/main.go && ./client.exe
go build -o client.exe client/main.go && ./client.exe
go build -o client.exe -buildvcs=true client/main.go && ./client.exe
To be clear, the program builds and executes, but doesn't contain embedded VCS information.
I also tried using go version -m client.exe
to see if that could read something that the binary couldn't read about itself, but the results were the same.
I'm using the first release of Go 1.18, so -buildvcs
should still default to true
as far as I know. I saw on the issue tracker that a future minor release will likely change the default to -buildvcs=auto
.
As far as I can tell, both conditions listed in the release notes (go
is invoked in a directory inside a git repo, and the main package is in the same repo) should both be satisfied when building from the project root. What might I be doing wrong?
Upvotes: 9
Views: 5958
Reputation: 1028
I was facing an issue where debug.ReadBuildInfo()
didn't have vcs.revision
set for a binary built within Docker, based off an alpine
image.
Git needs to be available for this info to be added to the build. Installing git
resolved the issue.
Before
FROM golang:1.22-alpine as builder
# some commands...
# build
RUN go build -v -o /usr/local/bin/my_app some.domain.dev/cmd/api
# Another stage with only the binary...
After
FROM golang:1.22-alpine as builder
# some commands...
# install Git
RUN apk add git
# build
RUN go build -v -o /usr/local/bin/my_app some.domain.dev/cmd/api
# Another stage with only the binary...
Upvotes: 0
Reputation: 5552
I believe my issue was due to incorrect usage of the go run
and go build
commands. I was running and building against file patterns because I had originally tried go build client
from the project root and gotten an error of "package is not in GOROOT", so I was building file patterns instead without understanding the difference (because it compiled and ran successfully).
I found that if I change directories into the subdirectory with the program I want to build (rather than build from the project root) the build command will embed the version information as expected.
e.g.:
cd client/ && go build
As @JimB pointed out in the comments, the go
command is meant to operate on packages.
When building from the project root, this is the command I should have been using that will properly embed VCS version info inside the binary:
go build ./client
This behavior around relative path names is still confusing behavior to me, since I had expected go build client
and go build ./client
to be equivalent (which they are apparently not). Behavior around relative paths seems to be documented here: https://pkg.go.dev/cmd/[email protected]#hdr-Relative_import_paths
Upvotes: 7