Use buildinfo to set the client version in the user agent (#13)

* Use go:generate to set the user agent version and sha

* regenerate

* buildinfo

* remove unused

* use init to source buildinfo
This commit is contained in:
Nikola Jokic
2025-11-21 14:38:55 +00:00
committed by GitHub
parent c2f0a53402
commit 16a9c915cb
3 changed files with 103 additions and 7 deletions
+13
View File
@@ -29,6 +29,19 @@ jobs:
- name: Check diff - name: Check diff
run: git diff --exit-code run: git diff --exit-code
generate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/setup-go@v6
with:
go-version-file: "go.mod"
cache: false
- name: go generate
run: go generate ./...
- name: Check diff
run: git diff --exit-code
lint: lint:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
+84 -3
View File
@@ -15,7 +15,9 @@ import (
"math/rand" "math/rand"
"net/http" "net/http"
"net/url" "net/url"
"runtime/debug"
"strconv" "strconv"
"strings"
"sync" "sync"
"sync/atomic" "sync/atomic"
"time" "time"
@@ -30,6 +32,15 @@ const (
scaleSetEndpoint = "_apis/runtime/runnerscalesets" scaleSetEndpoint = "_apis/runtime/runnerscalesets"
) )
var (
packageVersion string
commitSHA string
)
func init() {
packageVersion, commitSHA = detectModuleVersionAndCommit()
}
type atomicValue[T any] struct { type atomicValue[T any] struct {
v atomic.Value v atomic.Value
} }
@@ -129,7 +140,16 @@ func (u UserAgentInfo) String() string {
scaleSetID = strconv.Itoa(u.ScaleSetID) scaleSetID = strconv.Itoa(u.ScaleSetID)
} }
return fmt.Sprintf("%s/%s (%s; %s) ScaleSetID/%s", u.System, u.Version, u.CommitSHA, u.Subsystem, scaleSetID) return fmt.Sprintf(
"%s/%s (%s; %s) ScaleSetID/%s; client (%s; %s)",
u.System,
u.Version,
u.CommitSHA,
u.Subsystem,
scaleSetID,
packageVersion,
commitSHA,
)
} }
func WithLogger(logger slog.Logger) Option { func WithLogger(logger slog.Logger) Option {
@@ -184,11 +204,13 @@ func NewClient(githubConfigURL string, creds *ActionsAuth, options ...Option) (*
retryWaitMax: 30 * time.Second, retryWaitMax: 30 * time.Second,
} }
version, sha := detectModuleVersionAndCommit()
ac.userAgent.Store( ac.userAgent.Store(
UserAgentInfo{ UserAgentInfo{
System: "scaleset-client", System: "scaleset-client",
Version: "NA", Version: version,
CommitSHA: "NA", CommitSHA: sha,
Subsystem: "NA", Subsystem: "NA",
ScaleSetID: 0, ScaleSetID: 0,
}.String()) }.String())
@@ -1170,3 +1192,62 @@ func (c *Client) updateTokenIfNeeded(ctx context.Context) error {
return nil return nil
} }
func detectModuleVersionAndCommit() (version string, commit string) {
const modulePath = "github.com/actions/scaleset"
bi, ok := debug.ReadBuildInfo()
if !ok {
return "unknown", "unknown"
}
// If we are the main module (built from source in this repo), use vcs settings.
if bi.Main.Path == modulePath {
version = bi.Main.Version
commit = "unknown"
for _, s := range bi.Settings {
switch s.Key {
case "vcs.revision":
commit = s.Value
case "vcs.modified":
// Optionally append a marker if the tree was dirty.
if s.Value == "true" && commit != "unknown" {
commit = commit + "-dirty"
}
}
}
if version == "" || version == "(devel)" {
version = "devel"
}
if commit == "" {
commit = "unknown"
}
return version, commit
}
// Otherwise search dependency list for our module.
for _, dep := range bi.Deps {
if dep.Path == modulePath {
version = dep.Version
commit = extractCommitFromVersion(version)
return version, commit
}
}
return "unknown", "unknown"
}
// new: parse commit from a pseudo-version (e.g. v0.0.0-20251031142550-8104f571eba7)
func extractCommitFromVersion(v string) string {
// Semantic versions without pseudo part can't yield commit; return v directly.
// Pseudo format: <base>-<timestamp>-<commit>
parts := strings.Split(v, "-")
if len(parts) < 3 {
return v
}
commit := parts[len(parts)-1]
if len(commit) >= 7 {
return commit
}
return v
}
+5 -3
View File
@@ -1673,10 +1673,12 @@ func TestUserAgentInfoString(t *testing.T) {
} }
userAgent := userAgentInfo.String() userAgent := userAgentInfo.String()
expectedProduct := "actions-runner-controller/0.1.0 (1234567890abcdef; test)" expectedProduct := fmt.Sprintf(
"actions-runner-controller/0.1.0 (1234567890abcdef; test) ScaleSetID/10; client (%s; %s)",
packageVersion,
commitSHA,
)
assert.Contains(t, userAgent, expectedProduct) assert.Contains(t, userAgent, expectedProduct)
expectedScaleSet := "ScaleSetID/10"
assert.Contains(t, userAgent, expectedScaleSet)
} }
const samplePrivateKey = `-----BEGIN PRIVATE KEY----- const samplePrivateKey = `-----BEGIN PRIVATE KEY-----