all: upgrade to Go 1.26rc2 and modernize codebase
This commit upgrades the codebase from Go 1.25.5 to Go 1.26rc2 and adopts new language features. Toolchain updates: - go.mod: go 1.25.5 → go 1.26rc2 - flake.nix: buildGo125Module → buildGo126Module, go_1_25 → go_1_26 - flake.nix: build golangci-lint from source with Go 1.26 - Dockerfile.integration: golang:1.25-trixie → golang:1.26rc2-trixie - Dockerfile.tailscale-HEAD: golang:1.25-alpine → golang:1.26rc2-alpine - Dockerfile.derper: golang:alpine → golang:1.26rc2-alpine - .goreleaser.yml: go mod tidy -compat=1.25 → -compat=1.26 - cmd/hi/run.go: fallback Go version 1.25 → 1.26rc2 - .pre-commit-config.yaml: simplify golangci-lint hook entry Code modernization using Go 1.26 features: - Replace tsaddr.SortPrefixes with slices.SortFunc + netip.Prefix.Compare - Replace ptr.To(x) with new(x) syntax - Replace errors.As with errors.AsType[T] Lint rule updates: - Add forbidigo rules to prevent regression to old patterns
This commit is contained in:
parent
20dff82f95
commit
0f6d312ada
50 changed files with 508 additions and 521 deletions
|
|
@ -8,7 +8,6 @@ import (
|
|||
"github.com/juanfont/headscale/hscontrol/types"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"tailscale.com/types/ptr"
|
||||
)
|
||||
|
||||
// TestEphemeralNodeDeleteWithConcurrentUpdate tests the race condition where UpdateNode and DeleteNode
|
||||
|
|
@ -55,7 +54,7 @@ func TestEphemeralNodeDeleteWithConcurrentUpdate(t *testing.T) {
|
|||
|
||||
go func() {
|
||||
updatedNode, updateOk = store.UpdateNode(node.ID, func(n *types.Node) {
|
||||
n.LastSeen = ptr.To(time.Now())
|
||||
n.LastSeen = new(time.Now())
|
||||
})
|
||||
|
||||
done <- true
|
||||
|
|
@ -114,7 +113,7 @@ func TestUpdateNodeReturnsInvalidWhenDeletedInSameBatch(t *testing.T) {
|
|||
// Start UpdateNode in goroutine - it will queue and wait for batch
|
||||
go func() {
|
||||
node, ok := store.UpdateNode(node.ID, func(n *types.Node) {
|
||||
n.LastSeen = ptr.To(time.Now())
|
||||
n.LastSeen = new(time.Now())
|
||||
})
|
||||
resultChan <- struct {
|
||||
node types.NodeView
|
||||
|
|
@ -165,7 +164,7 @@ func TestPersistNodeToDBPreventsRaceCondition(t *testing.T) {
|
|||
|
||||
// Simulate UpdateNode being called
|
||||
updatedNode, ok := store.UpdateNode(node.ID, func(n *types.Node) {
|
||||
n.LastSeen = ptr.To(time.Now())
|
||||
n.LastSeen = new(time.Now())
|
||||
})
|
||||
require.True(t, ok, "UpdateNode should succeed")
|
||||
require.True(t, updatedNode.Valid(), "UpdateNode should return valid node")
|
||||
|
|
@ -234,7 +233,7 @@ func TestEphemeralNodeLogoutRaceCondition(t *testing.T) {
|
|||
// Goroutine 1: UpdateNode (simulates UpdateNodeFromMapRequest)
|
||||
go func() {
|
||||
updatedNode, updateOk = store.UpdateNode(ephemeralNode.ID, func(n *types.Node) {
|
||||
n.LastSeen = ptr.To(time.Now())
|
||||
n.LastSeen = new(time.Now())
|
||||
})
|
||||
|
||||
done <- true
|
||||
|
|
@ -310,7 +309,7 @@ func TestUpdateNodeFromMapRequestEphemeralLogoutSequence(t *testing.T) {
|
|||
|
||||
go func() {
|
||||
node, ok := store.UpdateNode(ephemeralNode.ID, func(n *types.Node) {
|
||||
n.LastSeen = ptr.To(time.Now())
|
||||
n.LastSeen = new(time.Now())
|
||||
endpoint := netip.MustParseAddrPort("10.0.0.1:41641")
|
||||
n.Endpoints = []netip.AddrPort{endpoint}
|
||||
})
|
||||
|
|
@ -380,7 +379,7 @@ func TestUpdateNodeDeletedInSameBatchReturnsInvalid(t *testing.T) {
|
|||
|
||||
go func() {
|
||||
updatedNode, ok := store.UpdateNode(node.ID, func(n *types.Node) {
|
||||
n.LastSeen = ptr.To(time.Now())
|
||||
n.LastSeen = new(time.Now())
|
||||
})
|
||||
updateDone <- struct {
|
||||
node types.NodeView
|
||||
|
|
@ -435,7 +434,7 @@ func TestPersistNodeToDBChecksNodeStoreBeforePersist(t *testing.T) {
|
|||
|
||||
// UpdateNode returns a node
|
||||
updatedNode, ok := store.UpdateNode(ephemeralNode.ID, func(n *types.Node) {
|
||||
n.LastSeen = ptr.To(time.Now())
|
||||
n.LastSeen = new(time.Now())
|
||||
})
|
||||
require.True(t, ok, "UpdateNode should succeed")
|
||||
require.True(t, updatedNode.Valid(), "updated node should be valid")
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ import (
|
|||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"tailscale.com/types/key"
|
||||
"tailscale.com/types/ptr"
|
||||
)
|
||||
|
||||
func TestSnapshotFromNodes(t *testing.T) {
|
||||
|
|
@ -175,7 +174,7 @@ func createTestNode(nodeID types.NodeID, userID uint, username, hostname string)
|
|||
DiscoKey: discoKey.Public(),
|
||||
Hostname: hostname,
|
||||
GivenName: hostname,
|
||||
UserID: ptr.To(userID),
|
||||
UserID: new(userID),
|
||||
User: &types.User{
|
||||
Name: username,
|
||||
DisplayName: username,
|
||||
|
|
@ -883,7 +882,7 @@ func createConcurrentTestNode(id types.NodeID, hostname string) types.Node {
|
|||
Hostname: hostname,
|
||||
MachineKey: machineKey.Public(),
|
||||
NodeKey: nodeKey.Public(),
|
||||
UserID: ptr.To(uint(1)),
|
||||
UserID: new(uint(1)),
|
||||
User: &types.User{
|
||||
Name: "concurrent-test-user",
|
||||
},
|
||||
|
|
|
|||
|
|
@ -27,10 +27,8 @@ import (
|
|||
"github.com/rs/zerolog/log"
|
||||
"golang.org/x/sync/errgroup"
|
||||
"gorm.io/gorm"
|
||||
"tailscale.com/net/tsaddr"
|
||||
"tailscale.com/tailcfg"
|
||||
"tailscale.com/types/key"
|
||||
"tailscale.com/types/ptr"
|
||||
"tailscale.com/types/views"
|
||||
zcache "zgo.at/zcache/v2"
|
||||
)
|
||||
|
|
@ -135,7 +133,7 @@ func NewState(cfg *types.Config) (*State, error) {
|
|||
// On startup, all nodes should be marked as offline until they reconnect
|
||||
// This ensures we don't have stale online status from previous runs
|
||||
for _, node := range nodes {
|
||||
node.IsOnline = ptr.To(false)
|
||||
node.IsOnline = new(false)
|
||||
}
|
||||
|
||||
users, err := db.ListUsers()
|
||||
|
|
@ -479,7 +477,7 @@ func (s *State) Connect(id types.NodeID) []change.Change {
|
|||
// the NodeStore already reflects the correct online status for full map generation.
|
||||
// now := time.Now()
|
||||
node, ok := s.nodeStore.UpdateNode(id, func(n *types.Node) {
|
||||
n.IsOnline = ptr.To(true)
|
||||
n.IsOnline = new(true)
|
||||
// n.LastSeen = ptr.To(now)
|
||||
})
|
||||
if !ok {
|
||||
|
|
@ -507,9 +505,9 @@ func (s *State) Disconnect(id types.NodeID) ([]change.Change, error) {
|
|||
now := time.Now()
|
||||
|
||||
node, ok := s.nodeStore.UpdateNode(id, func(n *types.Node) {
|
||||
n.LastSeen = ptr.To(now)
|
||||
n.LastSeen = new(now)
|
||||
// NodeStore is the source of truth for all node state including online status.
|
||||
n.IsOnline = ptr.To(false)
|
||||
n.IsOnline = new(false)
|
||||
})
|
||||
|
||||
if !ok {
|
||||
|
|
@ -805,7 +803,7 @@ func (s *State) BackfillNodeIPs() ([]string, error) {
|
|||
// Preserve online status and NetInfo when refreshing from database
|
||||
existingNode, exists := s.nodeStore.GetNode(node.ID)
|
||||
if exists && existingNode.Valid() {
|
||||
node.IsOnline = ptr.To(existingNode.IsOnline().Get())
|
||||
node.IsOnline = new(existingNode.IsOnline().Get())
|
||||
|
||||
// TODO(kradalby): We should ensure we use the same hostinfo and node merge semantics
|
||||
// when a node re-registers as we do when it sends a map request (UpdateNodeFromMapRequest).
|
||||
|
|
@ -1183,8 +1181,8 @@ func (s *State) applyAuthNodeUpdate(params authNodeUpdateParams) (types.NodeView
|
|||
)
|
||||
|
||||
node.Endpoints = params.RegEntry.Node.Endpoints
|
||||
node.IsOnline = ptr.To(false)
|
||||
node.LastSeen = ptr.To(time.Now())
|
||||
node.IsOnline = new(false)
|
||||
node.LastSeen = new(time.Now())
|
||||
|
||||
// Set RegisterMethod - for conversion this is the new method,
|
||||
// for reauth we preserve the existing one from regEntry
|
||||
|
|
@ -1286,7 +1284,7 @@ func (s *State) createAndSaveNewNode(params newNodeParams) (types.NodeView, erro
|
|||
DiscoKey: params.DiscoKey,
|
||||
Hostinfo: params.Hostinfo,
|
||||
Endpoints: params.Endpoints,
|
||||
LastSeen: ptr.To(time.Now()),
|
||||
LastSeen: new(time.Now()),
|
||||
RegisterMethod: params.RegisterMethod,
|
||||
Expiry: params.Expiry,
|
||||
}
|
||||
|
|
@ -1822,8 +1820,8 @@ func (s *State) HandleNodeFromPreAuthKey(
|
|||
// Only update AuthKey reference
|
||||
node.AuthKey = pak
|
||||
node.AuthKeyID = &pak.ID
|
||||
node.IsOnline = ptr.To(false)
|
||||
node.LastSeen = ptr.To(time.Now())
|
||||
node.IsOnline = new(false)
|
||||
node.LastSeen = new(time.Now())
|
||||
|
||||
// Tagged nodes keep their existing expiry (disabled).
|
||||
// User-owned nodes update expiry from the client request.
|
||||
|
|
@ -2281,8 +2279,8 @@ func routesChanged(oldNode types.NodeView, newHI *tailcfg.Hostinfo) bool {
|
|||
newRoutes = []netip.Prefix{}
|
||||
}
|
||||
|
||||
tsaddr.SortPrefixes(oldRoutes)
|
||||
tsaddr.SortPrefixes(newRoutes)
|
||||
slices.SortFunc(oldRoutes, netip.Prefix.Compare)
|
||||
slices.SortFunc(newRoutes, netip.Prefix.Compare)
|
||||
|
||||
return !slices.Equal(oldRoutes, newRoutes)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue