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:
@@ -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:
|
||||||
|
|||||||
@@ -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
@@ -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-----
|
||||||
|
|||||||
Reference in New Issue
Block a user