7 Commits

Author SHA1 Message Date
f58a6daa6c [汉化] 汉化测试用例、修复部分龙架构测试用例失效的问题
Some checks failed
checks / check and test (push) Has been cancelled
release-nightly / goreleaser (push) Has been cancelled
release-nightly / release-image (push) Has been cancelled
2025-05-09 15:17:16 +08:00
54308690d0 [冲突修复] 修复和上游的冲突文件
Some checks are pending
release-nightly / goreleaser (push) Waiting to run
release-nightly / release-image (push) Waiting to run
checks / check and test (push) Waiting to run
2025-05-09 11:05:26 +08:00
4b90fa4325 [汉化] 更新main 2025-05-09 10:46:03 +08:00
5302c25feb Add environment variables for OIDC token service (#674)
Some checks failed
checks / check and test (pull_request) Has been cancelled
Resurrecting [this PR](https://gitea.com/gitea/act_runner/pulls/272) (a dependency of [this one](https://github.com/go-gitea/gitea/pull/33945)) after the original author [lost motivation](https://github.com/go-gitea/gitea/pull/25664#issuecomment-2737099259) - though, to be clear, all credit belongs to them, and all blame for mistakes or misunderstandings to me.

Co-authored-by: Søren L. Hansen <sorenisanerd@gmail.com>
Reviewed-on: https://gitea.com/gitea/act_runner/pulls/674
Reviewed-by: ChristopherHX <christopherhx@noreply.gitea.com>
Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: Jack Jackson <scubbojj@gmail.com>
Co-committed-by: Jack Jackson <scubbojj@gmail.com>
2025-05-08 01:58:31 +00:00
a616ed1a10 feat: register interactive with values from cli (#682)
I used to be able to do something like `./act_runner register --instance https://gitea.com --token testdcff --name test` on GitHub Actions Runners, but act_runner always asked me to enter instance, token etc. again and requiring me to use `--no-interactive` including passing everything per cli.

My idea was to extract the preset input of some stages to skip the prompt for this value if it is a non empty string. Labels is the only question that has been asked more than once if validation failed, in this case the error path have to unset the values of the input structure to not end in a non-interactive loop.

_I have written this initially for my own gitea runner, might be useful to everyone using the official runner as well_

Reviewed-on: https://gitea.com/gitea/act_runner/pulls/682
Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: Christopher Homberger <christopher.homberger@web.de>
Co-committed-by: Christopher Homberger <christopher.homberger@web.de>
2025-05-08 01:57:53 +00:00
f0b5aff3bb fix: invalid label NoInteractive exit code (#683)
* add test
* return validation error not nil from function

Closes #665

Reviewed-on: https://gitea.com/gitea/act_runner/pulls/683
Reviewed-by: techknowlogick <techknowlogick@noreply.gitea.com>
Co-authored-by: Christopher Homberger <christopher.homberger@web.de>
Co-committed-by: Christopher Homberger <christopher.homberger@web.de>
2025-05-07 17:17:26 +00:00
44b4736703 feat: docker env vars for ephemeral and once (#685)
* GITEA_RUNNER_EPHEMERAL=1
* GITEA_RUNNER_ONCE=1

Related https://gitea.com/gitea/act_runner/issues/684

Reviewed-on: https://gitea.com/gitea/act_runner/pulls/685
Reviewed-by: techknowlogick <techknowlogick@noreply.gitea.com>
Co-authored-by: Christopher Homberger <christopher.homberger@web.de>
Co-committed-by: Christopher Homberger <christopher.homberger@web.de>
2025-05-07 15:43:05 +00:00
13 changed files with 242 additions and 157 deletions

View File

@ -103,7 +103,7 @@ fmt-check:
fi;
test: fmt-check
@$(GO) test -v -cover -coverprofile coverage.txt ./... && echo "\n==>\033[32m Ok\033[m\n" || exit 1
@$(GO) test -v -cover -coverprofile coverage.txt ./... && echo -e "\n===> \e[32mOk\e[m\n" || exit 1
.PHONY: vet
vet:

View File

@ -52,7 +52,7 @@ func runRegister(ctx context.Context, regArgs *registerArgs, configFile *string)
}
} else {
go func() {
if err := registerInteractive(ctx, *configFile); err != nil {
if err := registerInteractive(ctx, *configFile, regArgs); err != nil {
log.Fatal(err)
return
}
@ -127,6 +127,22 @@ func validateLabels(ls []string) error {
return nil
}
func (r *registerInputs) stageValue(stage registerStage) string {
switch stage {
case StageInputInstance:
return r.InstanceAddr
case StageInputToken:
return r.Token
case StageInputRunnerName:
return r.RunnerName
case StageInputLabels:
if len(r.Labels) > 0 {
return strings.Join(r.Labels, ",")
}
}
return ""
}
func (r *registerInputs) assignToNext(stage registerStage, value string, cfg *config.Config) registerStage {
// 必须设置实例地址和令牌。
// 如果为空,保持当前阶段。
@ -181,6 +197,7 @@ func (r *registerInputs) assignToNext(stage registerStage, value string, cfg *co
if validateLabels(r.Labels) != nil {
log.Infoln("无效的标签, 请重新输入, 留空以使用默认标签 (例如, debian-latest:lcr.loongnix.cn/library/debian:latest) ")
r.Labels = nil
return StageInputLabels
}
return StageWaitingForRegistration
@ -188,11 +205,25 @@ func (r *registerInputs) assignToNext(stage registerStage, value string, cfg *co
return StageUnknown
}
func registerInteractive(ctx context.Context, configFile string) error {
func initInputs(regArgs *registerArgs) *registerInputs {
inputs := &registerInputs{
InstanceAddr: regArgs.InstanceAddr,
Token: regArgs.Token,
RunnerName: regArgs.RunnerName,
Ephemeral: regArgs.Ephemeral,
}
regArgs.Labels = strings.TrimSpace(regArgs.Labels)
// command line flag.
if regArgs.Labels != "" {
inputs.Labels = strings.Split(regArgs.Labels, ",")
}
return inputs
}
func registerInteractive(ctx context.Context, configFile string, regArgs *registerArgs) error {
var (
reader = bufio.NewReader(os.Stdin)
stage = StageInputInstance
inputs = new(registerInputs)
)
cfg, err := config.LoadDefault(configFile)
@ -202,13 +233,17 @@ func registerInteractive(ctx context.Context, configFile string) error {
if f, err := os.Stat(cfg.Runner.File); err == nil && !f.IsDir() {
stage = StageOverwriteLocalConfig
}
inputs := initInputs(regArgs)
for {
printStageHelp(stage)
cmdString, err := reader.ReadString('\n')
if err != nil {
return err
cmdString := inputs.stageValue(stage)
if cmdString == "" {
printStageHelp(stage)
var err error
cmdString, err = reader.ReadString('\n')
if err != nil {
return err
}
}
stage = inputs.assignToNext(stage, strings.TrimSpace(cmdString), cfg)
@ -226,7 +261,7 @@ func registerInteractive(ctx context.Context, configFile string) error {
}
if stage <= StageUnknown {
log.Errorf("无效输入,请重新运行 act 命令。")
log.Errorf("无效输入,请重新运行命令。")
return nil
}
}
@ -255,18 +290,7 @@ func registerNoInteractive(ctx context.Context, configFile string, regArgs *regi
if err != nil {
return err
}
inputs := &registerInputs{
InstanceAddr: regArgs.InstanceAddr,
Token: regArgs.Token,
RunnerName: regArgs.RunnerName,
Labels: defaultLabels,
Ephemeral: regArgs.Ephemeral,
}
regArgs.Labels = strings.TrimSpace(regArgs.Labels)
// 命令行标志。
if regArgs.Labels != "" {
inputs.Labels = strings.Split(regArgs.Labels, ",")
}
inputs := initInputs(regArgs)
// 配置文件中指定的标签。
if len(cfg.Runner.Labels) > 0 {
if regArgs.Labels != "" {
@ -274,14 +298,17 @@ func registerNoInteractive(ctx context.Context, configFile string, regArgs *regi
}
inputs.Labels = cfg.Runner.Labels
}
if len(inputs.Labels) == 0 {
inputs.Labels = defaultLabels
}
if inputs.RunnerName == "" {
inputs.RunnerName, _ = os.Hostname()
log.Infof("运行器名称为空,使用主机名 '%s'。", inputs.RunnerName)
}
if err := inputs.validate(); err != nil {
log.WithError(err).Errorf("无效输入,请重新运行 act 命令。")
return nil
log.WithError(err).Errorf("无效输入,请重新运行命令。")
return err
}
if err := doRegister(ctx, cfg, inputs); err != nil {
return fmt.Errorf("注册运行器失败: %w", err)

View File

@ -0,0 +1,19 @@
// Copyright 2025 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package cmd
import (
"testing"
"gotest.tools/v3/assert"
)
func TestRegisterNonInteractiveReturnsLabelValidationError(t *testing.T) {
err := registerNoInteractive(t.Context(), "", &registerArgs{
Labels: "标签:无效",
Token: "token",
InstanceAddr: "http://localhost:3000",
})
assert.Error(t, err, "不支持的标签: 无效")
}

View File

@ -30,16 +30,16 @@ import (
// Runner 运行流水线
type Runner struct {
name string // Runner 名称
name string // Runner 名称
cfg *config.Config // 配置信息
client client.Client // Gitea 客户端
labels labels.Labels // 标签集合
envs map[string]string // 环境变量
// 正在运行的任务
runningTasks sync.Map // 使用 sync.Map 来存储正在运行的任务 ID
cfg *config.Config // 配置信息
client client.Client // Gitea 客户端
labels labels.Labels // 标签集合
envs map[string]string // 环境变量
// 正在运行的任务
runningTasks sync.Map // 使用 sync.Map 来存储正在运行的任务 ID
}
// NewRunner 使用提供的配置、注册信息和客户端创建一个新的 Runner 实例
@ -173,6 +173,12 @@ func (r *Runner) run(ctx context.Context, task *runnerv1.Task, reporter *report.
preset.Token = t
}
if actionsIdTokenRequestUrl := taskContext["actions_id_token_request_url"].GetStringValue(); actionsIdTokenRequestUrl != "" {
r.envs["ACTIONS_ID_TOKEN_REQUEST_URL"] = actionsIdTokenRequestUrl
r.envs["ACTIONS_ID_TOKEN_REQUEST_TOKEN"] = taskContext["actions_id_token_request_token"].GetStringValue()
task.Secrets["ACTIONS_ID_TOKEN_REQUEST_TOKEN"] = r.envs["ACTIONS_ID_TOKEN_REQUEST_TOKEN"]
}
giteaRuntimeToken := taskContext["gitea_runtime_token"].GetStringValue()
if giteaRuntimeToken == "" {
// 兼容旧版本 Gitea Server

View File

@ -12,7 +12,7 @@ import (
"gotest.tools/v3/assert"
)
func Test_generateWorkflow(t *testing.T) {
func Test_生成工作流(t *testing.T) {
type args struct {
task *runnerv1.Task
}
@ -24,32 +24,32 @@ func Test_generateWorkflow(t *testing.T) {
wantErr bool
}{
{
name: "has needs",
name: "有需求",
args: args{
task: &runnerv1.Task{
WorkflowPayload: []byte(`
name: Build and deploy
name: 构建部署测试
on: push
jobs:
job9:
needs: build
runs-on: ubuntu-latest
runs-on: linux-loong64
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- run: ./deploy --build ${{ needs.job1.outputs.output1 }}
- run: ./deploy --build ${{ needs.job2.outputs.output2 }}
`),
Needs: map[string]*runnerv1.TaskNeed{
"job1": {
Outputs: map[string]string{
"output1": "output1 value",
"output1": "输出1值",
},
Result: runnerv1.Result_RESULT_SUCCESS,
},
"job2": {
Outputs: map[string]string{
"output2": "output2 value",
"output2": "输出2值",
},
Result: runnerv1.Result_RESULT_SUCCESS,
},

View File

@ -6,6 +6,6 @@ package client
const (
UUIDHeader = "x-runner-uuid"
TokenHeader = "x-runner-token"
// Deprecated: could be removed after Gitea 1.20 released
// 已弃用: 可以在Gitea 1.20发布后删除
VersionHeader = "x-runner-version"
)

View File

@ -27,7 +27,7 @@ func getHTTPClient(endpoint string, insecure bool) *http.Client {
return http.DefaultClient
}
// New returns a new runner client.
// New返回一个新的runner客户端。
func New(endpoint string, insecure bool, uuid, token, version string, opts ...connect.ClientOption) *HTTPClient {
baseURL := strings.TrimRight(endpoint, "/") + "/api/actions"
@ -39,7 +39,7 @@ func New(endpoint string, insecure bool, uuid, token, version string, opts ...co
if token != "" {
req.Header().Set(TokenHeader, token)
}
// TODO: version will be removed from request header after Gitea 1.20 released.
// TODOversion将在Gitea 1.20发布后从请求标头中删除。
if version != "" {
req.Header().Set(VersionHeader, version)
}
@ -73,7 +73,7 @@ func (c *HTTPClient) Insecure() bool {
var _ Client = (*HTTPClient)(nil)
// An HTTPClient manages communication with the runner API.
// HTTPClient管理与runner API的通信。
type HTTPClient struct {
pingv1connect.PingServiceClient
runnerv1connect.RunnerServiceClient

View File

@ -36,7 +36,7 @@ func Parse(str string) (*Label, error) {
label.Arg = splits[2]
}
if label.Schema != SchemeHost && label.Schema != SchemeDocker {
return nil, fmt.Errorf("不支持的 schema: %s", label.Schema)
return nil, fmt.Errorf("不支持的标签: %s", label.Schema)
}
return label, nil
}

View File

@ -10,7 +10,7 @@ import (
"gotest.tools/v3/assert"
)
func TestParse(t *testing.T) {
func Test解析(t *testing.T) {
tests := []struct {
args string
want *Label

View File

@ -23,23 +23,23 @@ import (
)
type Reporter struct {
ctx context.Context // 上下文,用于控制生命周期
cancel context.CancelFunc // 取消函数
closed bool // 是否已关闭
client client.Client // Gitea 客户端
clientM sync.Mutex // 客户端访问互斥锁
ctx context.Context // 上下文,用于控制生命周期
cancel context.CancelFunc // 取消函数
closed bool // 是否已关闭
client client.Client // Gitea 客户端
clientM sync.Mutex // 客户端访问互斥锁
logOffset int // 日志偏移量
logRows []*runnerv1.LogRow // 日志行缓存
logReplacer *strings.Replacer // 日志内容替换器
oldnew []string // 需要替换的敏感信息
logOffset int // 日志偏移量
logRows []*runnerv1.LogRow // 日志行缓存
logReplacer *strings.Replacer // 日志内容替换器
oldnew []string // 需要替换的敏感信息
state *runnerv1.TaskState // 任务状态
stateMu sync.RWMutex // 状态访问读写锁
outputs sync.Map // 输出参数存储
state *runnerv1.TaskState // 任务状态
stateMu sync.RWMutex // 状态访问读写锁
outputs sync.Map // 输出参数存储
debugOutputEnabled bool // 是否启用调试输出
stopCommandEndToken string // 停止命令结束标记
debugOutputEnabled bool // 是否启用调试输出
stopCommandEndToken string // 停止命令结束标记
}
// NewReporter 构造函数 初始化日志脱敏规则、状态等信息
@ -110,7 +110,7 @@ func (r *Reporter) Fire(entry *log.Entry) error {
}
stage := entry.Data["stage"]
if stage != "Main" {
if v, ok := entry.Data["jobResult"]; ok {
if jobResult, ok := r.parseResult(v); ok {

View File

@ -19,122 +19,133 @@ import (
"git.whlug.cn/LAA/loong_runner/internal/pkg/client/mocks"
)
func TestReporter_parseLogRow(t *testing.T) {
func Test记录器_解析输出日志(t *testing.T) {
tests := []struct {
name string
debugOutputEnabled bool
args []string
want []string
name string // 测试用例名称
debugOutputEnabled bool // 是否启用调试输出
args []string // 输入的日志行
want []string // 期望的输出结果
}{
{
"No command", false,
[]string{"Hello, world!"},
[]string{"Hello, world!"},
name: "无命令",
debugOutputEnabled: false,
args: []string{"你好,世界!"},
want: []string{"你好,世界!"},
},
{
"Add-mask", false,
[]string{
"foo mysecret bar",
"::add-mask::mysecret",
"foo mysecret bar",
name: "添加掩码",
debugOutputEnabled: false,
args: []string{
"foo 我的密钥 bar", // 输入日志:普通日志行
"::add-mask::我的密钥", // 输入命令:添加掩码
"foo 我的密钥 bar", // 输入日志:再次普通日志行
},
[]string{
"foo mysecret bar",
"<nil>",
"foo *** bar",
want: []string{
"foo 我的密钥 bar", // 原始日志直接输出
"<nil>", // 添加掩码命令处理结果(无输出内容)
"foo *** bar", // 掩码替换后的日志行
},
},
{
"Debug enabled", true,
[]string{
"::debug::GitHub Actions runtime token access controls",
name: "启用调试",
debugOutputEnabled: true,
args: []string{
"::debug::GitHub Actions 运行时令牌访问控制",
},
[]string{
"GitHub Actions runtime token access controls",
want: []string{
"GitHub Actions 运行时令牌访问控制", // 调试信息直接输出
},
},
{
"Debug not enabled", false,
[]string{
"::debug::GitHub Actions runtime token access controls",
name: "禁用调试",
debugOutputEnabled: false,
args: []string{
"::debug::GitHub Actions 运行时令牌访问控制",
},
[]string{
"<nil>",
want: []string{
"<nil>", // 调试信息被忽略
},
},
{
"notice", false,
[]string{
"::notice file=file.name,line=42,endLine=48,title=Cool Title::Gosh, that's not going to work",
name: "通知",
debugOutputEnabled: false,
args: []string{
"::notice file=文件.name,line=42,endLine=48,title=酷标题::天啊,这行不通",
},
[]string{
"::notice file=file.name,line=42,endLine=48,title=Cool Title::Gosh, that's not going to work",
want: []string{
"::notice file=文件.name,line=42,endLine=48,title=酷标题::天啊,这行不通", // 通知日志原样输出
},
},
{
"warning", false,
[]string{
"::warning file=file.name,line=42,endLine=48,title=Cool Title::Gosh, that's not going to work",
name: "警告",
debugOutputEnabled: false,
args: []string{
"::warning file=文件.name,line=42,endLine=48,title=酷标题::天啊,这行不通",
},
[]string{
"::warning file=file.name,line=42,endLine=48,title=Cool Title::Gosh, that's not going to work",
want: []string{
"::warning file=文件.name,line=42,endLine=48,title=酷标题::天啊,这行不通", // 警告日志原样输出
},
},
{
"error", false,
[]string{
"::error file=file.name,line=42,endLine=48,title=Cool Title::Gosh, that's not going to work",
name: "错误",
debugOutputEnabled: false,
args: []string{
"::error file=文件.name,line=42,endLine=48,title=酷标题::天啊,这行不通",
},
[]string{
"::error file=file.name,line=42,endLine=48,title=Cool Title::Gosh, that's not going to work",
want: []string{
"::error file=文件.name,line=42,endLine=48,title=酷标题::天啊,这行不通", // 错误日志原样输出
},
},
{
"group", false,
[]string{
"::group::",
"::endgroup::",
name: "分组",
debugOutputEnabled: false,
args: []string{
"::group::", // 开始分组
"::endgroup::", // 结束分组
},
[]string{
"::group::",
"::endgroup::",
want: []string{
"::group::", // 分组开始标记原样输出
"::endgroup::", // 分组结束标记原样输出
},
},
{
"stop-commands", false,
[]string{
"::add-mask::foo",
"::stop-commands::myverycoolstoptoken",
"::add-mask::bar",
"::debug::Stuff",
"myverycoolstoptoken",
"::add-mask::baz",
"::myverycoolstoptoken::",
"::add-mask::wibble",
"foo bar baz wibble",
name: "停止命令",
debugOutputEnabled: false,
args: []string{
"::add-mask::foo", // 添加掩码命令
"::stop-commands::我的停止令牌", // 停止命令标记
"::add-mask::bar", // 被忽略的添加掩码命令
"::debug::调试信息", // 被忽略的调试信息
"我的停止令牌", // 停止命令标记结束
"::add-mask::baz", // 恢复处理的添加掩码命令
"::我的停止令牌::", // 另一种停止命令标记
"::add-mask::wibble", // 被忽略的添加掩码命令
"foo bar baz wibble", // 普通日志行
},
[]string{
"<nil>",
"<nil>",
"::add-mask::bar",
"::debug::Stuff",
"myverycoolstoptoken",
"::add-mask::baz",
"<nil>",
"<nil>",
"*** bar baz ***",
want: []string{
"<nil>", // 第一个添加掩码命令处理结果
"<nil>", // 停止命令标记处理结果
"::add-mask::bar", // 被忽略的命令原样输出
"::debug::调试信息", // 被忽略的调试信息原样输出
"我的停止令牌", // 停止标记结束原样输出
"::add-mask::baz", // 恢复处理的添加掩码命令
"<nil>", // 无效停止命令标记处理结果
"<nil>", // 被忽略的添加掩码命令处理结果
"*** bar baz ***", // 掩码替换后的日志行
},
},
{
"unknown command", false,
[]string{
"::set-mask::foo",
name: "未知命令",
debugOutputEnabled: false,
args: []string{
"::set-mask::foo", // 未知命令
},
[]string{
"::set-mask::foo",
want: []string{
"::set-mask::foo", // 未知命令原样输出
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
r := &Reporter{
@ -155,43 +166,58 @@ func TestReporter_parseLogRow(t *testing.T) {
}
}
func TestReporter_Fire(t *testing.T) {
t.Run("ignore command lines", func(t *testing.T) {
// 测试 ReporterFire 方法(验证命令行忽略逻辑)
func Test记录器_触发(t *testing.T) {
t.Run("忽略命令行", func(t *testing.T) { // 测试场景:验证是否正确处理需要忽略的命令行日志
// 创建模拟客户端
client := mocks.NewClient(t)
// 模拟 UpdateLog 接口调用,记录请求内容并返回响应
client.On("UpdateLog", mock.Anything, mock.Anything).Return(func(_ context.Context, req *connect_go.Request[runnerv1.UpdateLogRequest]) (*connect_go.Response[runnerv1.UpdateLogResponse], error) {
t.Logf("Received UpdateLog: %s", req.Msg.String())
t.Logf("收到 UpdateLog 请求:%s", req.Msg.String()) // 记录日志请求内容
return connect_go.NewResponse(&runnerv1.UpdateLogResponse{
AckIndex: req.Msg.Index + int64(len(req.Msg.Rows)),
AckIndex: req.Msg.Index + int64(len(req.Msg.Rows)), // 计算确认索引
}), nil
})
// 模拟 UpdateTask 接口调用
client.On("UpdateTask", mock.Anything, mock.Anything).Return(func(_ context.Context, req *connect_go.Request[runnerv1.UpdateTaskRequest]) (*connect_go.Response[runnerv1.UpdateTaskResponse], error) {
t.Logf("Received UpdateTask: %s", req.Msg.String())
t.Logf("收到 UpdateTask 请求:%s", req.Msg.String()) // 记录任务更新请求
return connect_go.NewResponse(&runnerv1.UpdateTaskResponse{}), nil
})
// 初始化上下文和任务
ctx, cancel := context.WithCancel(context.Background())
taskCtx, err := structpb.NewStruct(map[string]interface{}{})
taskCtx, err := structpb.NewStruct(map[string]interface{}{}) // 创建空任务上下文
require.NoError(t, err)
// 创建 Reporter 实例
reporter := NewReporter(ctx, cancel, client, &runnerv1.Task{
Context: taskCtx,
Context: taskCtx, // 注入任务上下文
})
defer func() {
assert.NoError(t, reporter.Close(""))
assert.NoError(t, reporter.Close("")) // 测试结束关闭 Reporter
}()
reporter.ResetSteps(5)
reporter.ResetSteps(5) // 初始化5个步骤的日志存储
// 定义步骤0的日志元数据
dataStep0 := map[string]interface{}{
"stage": "Main",
"stepNumber": 0,
"raw_output": true,
"stage": "Main", // 阶段名称
"stepNumber": 0, // 步骤编号
"raw_output": true, // 启用原始输出模式
}
assert.NoError(t, reporter.Fire(&log.Entry{Message: "regular log line", Data: dataStep0}))
assert.NoError(t, reporter.Fire(&log.Entry{Message: "::debug::debug log line", Data: dataStep0}))
assert.NoError(t, reporter.Fire(&log.Entry{Message: "regular log line", Data: dataStep0}))
assert.NoError(t, reporter.Fire(&log.Entry{Message: "::debug::debug log line", Data: dataStep0}))
assert.NoError(t, reporter.Fire(&log.Entry{Message: "::debug::debug log line", Data: dataStep0}))
assert.NoError(t, reporter.Fire(&log.Entry{Message: "regular log line", Data: dataStep0}))
// 发送混合类型的日志条目 ---------------------------------------------------
// 预期:普通日志被记录,调试日志被忽略
assert.NoError(t, reporter.Fire(&log.Entry{Message: "普通日志行", Data: dataStep0}))
assert.NoError(t, reporter.Fire(&log.Entry{Message: "::debug::调试日志行", Data: dataStep0})) // 应被忽略
assert.NoError(t, reporter.Fire(&log.Entry{Message: "普通日志行", Data: dataStep0}))
assert.NoError(t, reporter.Fire(&log.Entry{Message: "::debug::调试日志行", Data: dataStep0})) // 应被忽略
assert.NoError(t, reporter.Fire(&log.Entry{Message: "::debug::调试日志行", Data: dataStep0})) // 应被忽略
assert.NoError(t, reporter.Fire(&log.Entry{Message: "普通日志行", Data: dataStep0}))
assert.Equal(t, int64(3), reporter.state.Steps[0].LogLength)
// 验证结果:步骤0应只有3条普通日志(调试日志被过滤)
assert.Equal(t, int64(3), reporter.state.Steps[0].LogLength, "普通日志数量不符预期")
})
}

View File

@ -14,6 +14,6 @@ import (
func main() {
ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
defer stop()
// run the command
// 运行命令
cmd.Execute(ctx)
}

View File

@ -20,6 +20,13 @@ EXTRA_ARGS=""
if [[ ! -z "${GITEA_RUNNER_LABELS}" ]]; then
EXTRA_ARGS="${EXTRA_ARGS} --labels ${GITEA_RUNNER_LABELS}"
fi
if [[ ! -z "${GITEA_RUNNER_EPHEMERAL}" ]]; then
EXTRA_ARGS="${EXTRA_ARGS} --ephemeral"
fi
RUN_ARGS=""
if [[ ! -z "${GITEA_RUNNER_ONCE}" ]]; then
RUN_ARGS="${RUN_ARGS} --once"
fi
# 如果没有设置令牌,可以从文件中读取令牌,例如从 Docker Secret
if [[ -z "${GITEA_RUNNER_REGISTRATION_TOKEN}" ]] && [[ -f "${GITEA_RUNNER_REGISTRATION_TOKEN_FILE}" ]]; then
@ -60,4 +67,4 @@ unset GITEA_RUNNER_REGISTRATION_TOKEN
unset GITEA_RUNNER_REGISTRATION_TOKEN_FILE
# 启动 act_runner 守护进程
exec act_runner daemon ${CONFIG_ARG}
exec act_runner daemon ${CONFIG_ARG} ${RUN_ARGS}