mirror of
https://github.com/juanfont/headscale.git
synced 2026-10-03 05:13:36 +09:00
tools/bump: add the version bump tool
Keeps the interlocked pins current and reports what it could not move. Areas apply, gate and commit one at a time, so a dependency that breaks the build costs one commit rather than the whole pull request.
This commit is contained in:
@@ -0,0 +1,147 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// lockNode is the slice of a flake.lock entry that identifies what an input is
|
||||
// pinned to.
|
||||
type lockNode struct {
|
||||
Locked struct {
|
||||
Rev string `json:"rev"`
|
||||
LastModified int64 `json:"lastModified"`
|
||||
} `json:"locked"`
|
||||
}
|
||||
|
||||
type flakeLock struct {
|
||||
Nodes map[string]lockNode `json:"nodes"`
|
||||
}
|
||||
|
||||
func readLock(r *repo) (flakeLock, error) {
|
||||
var lock flakeLock
|
||||
|
||||
b, err := r.readFile("flake.lock")
|
||||
if err != nil {
|
||||
return lock, err
|
||||
}
|
||||
|
||||
if err := json.Unmarshal([]byte(b), &lock); err != nil { //nolint:noinlineerr
|
||||
return lock, fmt.Errorf("parsing flake.lock: %w", err)
|
||||
}
|
||||
|
||||
return lock, nil
|
||||
}
|
||||
|
||||
// lockDiff reports the inputs whose revision moved: one detailed line each,
|
||||
// plus the bare names for the commit subject.
|
||||
func lockDiff(before, after flakeLock) ([]string, []string) {
|
||||
var detail, names []string
|
||||
|
||||
for name, post := range after.Nodes {
|
||||
pre, ok := before.Nodes[name]
|
||||
if !ok || post.Locked.Rev == "" || pre.Locked.Rev == post.Locked.Rev {
|
||||
continue
|
||||
}
|
||||
|
||||
detail = append(detail, fmt.Sprintf("%s %s -> %s", name, short(pre.Locked.Rev), short(post.Locked.Rev)))
|
||||
names = append(names, name)
|
||||
}
|
||||
|
||||
sort.Strings(detail)
|
||||
sort.Strings(names)
|
||||
|
||||
return detail, names
|
||||
}
|
||||
|
||||
func short(rev string) string {
|
||||
if len(rev) > 7 {
|
||||
return rev[:7]
|
||||
}
|
||||
|
||||
return rev
|
||||
}
|
||||
|
||||
// applyFlake refreshes every flake input. Because flake.nix asks for
|
||||
// buildGoLatestModule and go_latest, this is also how Go and every devShell
|
||||
// tool get a new version.
|
||||
func applyFlake(ctx context.Context, r *repo) (change, error) {
|
||||
before, err := readLock(r)
|
||||
if err != nil {
|
||||
return change{}, err
|
||||
}
|
||||
|
||||
if _, err := r.run(ctx, "nix", "flake", "update"); err != nil { //nolint:noinlineerr
|
||||
return change{}, err
|
||||
}
|
||||
|
||||
after, err := readLock(r)
|
||||
if err != nil {
|
||||
return change{}, err
|
||||
}
|
||||
|
||||
moved, names := lockDiff(before, after)
|
||||
if len(moved) == 0 {
|
||||
return change{Empty: true}, nil
|
||||
}
|
||||
|
||||
detail := moved
|
||||
|
||||
if tools, err := toolVersions(ctx, r); err == nil { //nolint:noinlineerr
|
||||
detail = append(detail, tools...)
|
||||
}
|
||||
|
||||
return change{
|
||||
Summary: shortList(names),
|
||||
Detail: detail,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// shortList keeps a commit subject readable when many inputs move at once.
|
||||
func shortList(names []string) string {
|
||||
const maxNamed = 3
|
||||
|
||||
if len(names) <= maxNamed {
|
||||
return strings.Join(names, ", ")
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%s and %d more", strings.Join(names[:maxNamed], ", "), len(names)-maxNamed)
|
||||
}
|
||||
|
||||
// gateFlake proves the flake still evaluates before anything expensive runs.
|
||||
func gateFlake(ctx context.Context, r *repo) error {
|
||||
_, err := r.run(ctx, "nix", "eval", "--raw",
|
||||
fmt.Sprintf(".#packages.%s.headscale.name", r.System))
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// goVersion is the Go the devShell now provides, without the "go" prefix.
|
||||
func goVersion(ctx context.Context, r *repo) (string, error) {
|
||||
out, err := r.nixRun(ctx, "go", "env", "GOVERSION")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return strings.TrimPrefix(strings.TrimSpace(out), "go"), nil
|
||||
}
|
||||
|
||||
// toolVersions reports the versions that most often decide whether a lock bump
|
||||
// turns the pull request red.
|
||||
func toolVersions(ctx context.Context, r *repo) ([]string, error) {
|
||||
goVer, err := goVersion(ctx, r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
versions := []string{"go " + goVer}
|
||||
|
||||
if out, err := r.nixRun(ctx, "golangci-lint", "version"); err == nil { //nolint:noinlineerr
|
||||
versions = append(versions, strings.TrimSpace(strings.SplitN(out, "\n", 2)[0]))
|
||||
}
|
||||
|
||||
return versions, nil
|
||||
}
|
||||
Reference in New Issue
Block a user