fix: do not save .runner unless it is modified (#1006)

Resolves forgejo/runner#548

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- bug fixes
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1006): <!--number 1006 --><!--line 0 --><!--description Zml4OiBkbyBub3Qgc2F2ZSAucnVubmVyIHVubGVzcyBpdCBpcyBtb2RpZmllZA==-->fix: do not save .runner unless it is modified<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/1006
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
Co-authored-by: Earl Warren <contact@earl-warren.org>
Co-committed-by: Earl Warren <contact@earl-warren.org>
This commit is contained in:
Earl Warren 2025-09-17 12:48:52 +00:00 committed by earl-warren
parent e1e7d0e85a
commit aaf9dea44a
No known key found for this signature in database
GPG key ID: F128CBE6AB3A7201
3 changed files with 85 additions and 3 deletions

2
go.mod
View file

@ -19,6 +19,7 @@ require (
github.com/go-git/go-billy/v5 v5.6.2
github.com/go-git/go-git/v5 v5.16.2
github.com/gobwas/glob v0.2.3
github.com/google/go-cmp v0.7.0
github.com/google/uuid v1.6.0
github.com/joho/godotenv v1.5.1
github.com/julienschmidt/httprouter v1.3.0
@ -62,7 +63,6 @@ require (
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
github.com/google/go-cmp v0.7.0 // indirect
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect

View file

@ -1,3 +1,4 @@
// Copyright 2025 The Forgejo Authors. All rights reserved.
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
@ -6,6 +7,8 @@ package config
import (
"encoding/json"
"os"
"github.com/google/go-cmp/cmp"
)
const registrationWarning = "This file is automatically generated by act-runner. Do not edit it manually unless you know what you are doing. Removing this file will cause act runner to re-register as a new runner."
@ -34,12 +37,28 @@ func LoadRegistration(file string) (*Registration, error) {
return nil, err
}
reg.Warning = ""
return &reg, nil
}
func isEqualRegistration(file string, reg *Registration) (bool, error) {
existing, err := LoadRegistration(file)
if err != nil {
if os.IsNotExist(err) {
return false, nil
}
return false, err
}
return cmp.Equal(*reg, *existing), nil
}
func SaveRegistration(file string, reg *Registration) error {
equal, err := isEqualRegistration(file, reg)
if err != nil {
return err
}
if equal {
return nil
}
f, err := os.Create(file)
if err != nil {
return err

View file

@ -0,0 +1,63 @@
// Copyright 2025 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: GPL-3.0-or-later
package config
import (
"os"
"path/filepath"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestConfig_Registration(t *testing.T) {
reg := Registration{
Warning: registrationWarning,
ID: 1234,
UUID: "UUID",
Name: "NAME",
Token: "TOKEN",
Address: "ADDRESS",
Labels: []string{"LABEL1", "LABEL2"},
}
file := filepath.Join(t.TempDir(), ".runner")
// when the file does not exist, it is never equal
equal, err := isEqualRegistration(file, &reg)
require.NoError(t, err)
assert.False(t, equal)
require.NoError(t, SaveRegistration(file, &reg))
regReloaded, err := LoadRegistration(file)
require.NoError(t, err)
assert.Equal(t, reg, *regReloaded)
equal, err = isEqualRegistration(file, &reg)
require.NoError(t, err)
assert.True(t, equal)
// if the registration is not modified, it is not saved
time.Sleep(2 * time.Second) // file system precision on modification time is one second
before, err := os.Stat(file)
require.NoError(t, err)
require.NoError(t, SaveRegistration(file, &reg))
after, err := os.Stat(file)
require.NoError(t, err)
assert.Equal(t, before.ModTime(), after.ModTime())
reg.Labels = []string{"LABEL3"}
equal, err = isEqualRegistration(file, &reg)
require.NoError(t, err)
assert.False(t, equal)
// if the registration is modified, it is saved
require.NoError(t, SaveRegistration(file, &reg))
after, err = os.Stat(file)
require.NoError(t, err)
assert.NotEqual(t, before.ModTime(), after.ModTime())
}