From bbc1f7e55fcab135963fcd2d6aaae4f1ca1da34b Mon Sep 17 00:00:00 2001 From: wucm667 Date: Tue, 5 May 2026 20:30:18 +0800 Subject: [PATCH 1/2] fix(agent): persist agent ID after auth to prevent crashloop duplicates When the agent crashes before completing registration, it loses its assigned ID. On restart, it authenticates as a new agent (ID 0) and gets a fresh server entry, leading to infinite agent entries during crashloop. Persist the agent ID immediately after successful authentication so subsequent restarts reuse the same server-side entry. Closes #6527 Signed-off-by: wucm667 --- agent/rpc/auth_client_grpc.go | 4 ++++ cmd/agent/core/agent.go | 9 +++++++++ 2 files changed, 13 insertions(+) diff --git a/agent/rpc/auth_client_grpc.go b/agent/rpc/auth_client_grpc.go index 92eb1cb98bd..6ac03dc2519 100644 --- a/agent/rpc/auth_client_grpc.go +++ b/agent/rpc/auth_client_grpc.go @@ -41,6 +41,10 @@ func NewAuthGrpcClient(conn *grpc.ClientConn, agentToken string, agentID int64) return client } +func (c *AuthClient) AgentID() int64 { + return c.agentID +} + func (c *AuthClient) Auth(ctx context.Context) (string, int64, error) { ctx, cancel := context.WithTimeout(ctx, authClientTimeout) defer cancel() diff --git a/cmd/agent/core/agent.go b/cmd/agent/core/agent.go index 1b7ddbccd8f..7d668ac88dc 100644 --- a/cmd/agent/core/agent.go +++ b/cmd/agent/core/agent.go @@ -137,6 +137,15 @@ func run(ctx context.Context, c *cli.Command, backends []types.Backend) error { return fmt.Errorf("agent could not auth: %w", err) } + // Persist the agent ID received during auth so that crashloops reuse the + // same server-side entry instead of creating a new one on every restart. + if agentConfigPath != "" { + agentConfig.AgentID = authClient.AgentID() + if err := writeAgentConfig(agentConfig, agentConfigPath); err == nil { + log.Debug().Msgf("persisted agent ID %d after auth", agentConfig.AgentID) + } + } + conn, err := grpc.NewClient( c.String("server"), transport, From 0724e741c181776261a5f32ac041c8fbffdbfd22 Mon Sep 17 00:00:00 2001 From: wucm667 Date: Wed, 6 May 2026 10:06:16 +0800 Subject: [PATCH 2/2] test(agent): add test for AuthClient.AgentID() --- agent/rpc/auth_client_grpc_test.go | 32 ++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 agent/rpc/auth_client_grpc_test.go diff --git a/agent/rpc/auth_client_grpc_test.go b/agent/rpc/auth_client_grpc_test.go new file mode 100644 index 00000000000..fd9c4ed5f9e --- /dev/null +++ b/agent/rpc/auth_client_grpc_test.go @@ -0,0 +1,32 @@ +// Copyright 2024 Woodpecker Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package rpc + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" +) + +func TestAuthClientAgentID(t *testing.T) { + conn, err := grpc.NewClient("localhost:0", grpc.WithTransportCredentials(insecure.NewCredentials())) + assert.NoError(t, err) + defer conn.Close() + + client := NewAuthGrpcClient(conn, "test-token", 42) + assert.Equal(t, int64(42), client.AgentID()) +}