enhance: log task, job and run identifiers when a task starts (#1257)

Replace the `task N repo is ...` line with a structured `task started` entry carrying `task_id`, `job_id`, `run_id`, `run_number`, `repository` and the workflow's `job` key, so external supervisors can match runner activity to the job in Gitea. `job_id` is read from the runtime token's claims, tokens and secrets are never logged.

Closes https://gitea.com/gitea/runner/issues/752

---------

Co-authored-by: silverwind <2021+silverwind@noreply.gitea.com>
Co-authored-by: silverwind <me@silverwind.io>
Reviewed-on: https://gitea.com/gitea/runner/pulls/1257
Reviewed-by: silverwind <2021+silverwind@noreply.gitea.com>
This commit is contained in:
bircni
2026-09-30 19:42:52 +00:00
parent 78610b01f6
commit 07ca4bfa7f
2 changed files with 38 additions and 4 deletions

View File

@@ -7,6 +7,7 @@ import (
"bytes"
"cmp"
"context"
"encoding/base64"
"encoding/json/v2"
"errors"
"fmt"
@@ -424,6 +425,10 @@ func (r *Runner) run(ctx context.Context, task *runnerv1.Task, reporter *report.
if err != nil {
return err
}
log.WithFields(taskLogFields(task, jobID)).
WithField("actions_url", r.getDefaultActionsURL(task)).
WithField("address", r.client.Address()).
Info("task started")
plan, err := model.CombineWorkflowPlanner(workflow).PlanJob(jobID)
if err != nil {
@@ -464,10 +469,6 @@ func (r *Runner) run(ctx context.Context, task *runnerv1.Task, reporter *report.
}
telemetry.AddJobEnv(ctx, envs)
log.Infof("task %v repo is %v %v %v", task.Id, taskContext["repository"].GetStringValue(),
r.getDefaultActionsURL(task),
r.client.Address())
preset := model.GithubContextFromMap(task.Context.AsMap())
if t := task.Secrets["GITEA_TOKEN"]; t != "" {
preset.Token = t
@@ -896,3 +897,22 @@ func (r *Runner) detectIsolatedCacheContainer() string {
}
return cacheContainer
}
func taskLogFields(task *runnerv1.Task, job string) log.Fields {
taskContext := task.GetContext().GetFields()
fields := log.Fields{
"task_id": task.Id,
"job": job,
"repository": taskContext["repository"].GetStringValue(),
"run_id": taskContext["run_id"].GetStringValue(),
"run_number": taskContext["run_number"].GetStringValue(),
}
if parts := strings.Split(taskContext["gitea_runtime_token"].GetStringValue(), "."); len(parts) == 3 {
var claims struct{ JobID int64 } // Gitea's actionsClaims fields are untagged, so the claim key is "JobID"
payload, err := base64.RawURLEncoding.DecodeString(parts[1])
if err == nil && json.Unmarshal(payload, &claims) == nil && claims.JobID > 0 {
fields["job_id"] = claims.JobID
}
}
return fields
}

View File

@@ -5,6 +5,7 @@ package run
import (
"context"
"encoding/base64"
"io"
"net/http"
"net/http/httptest"
@@ -26,6 +27,7 @@ import (
"connectrpc.com/connect"
"gitea.dev/actionslib/pkg/model"
runnerv1 "gitea.dev/actionslib/runner/v1"
log "github.com/sirupsen/logrus"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
@@ -403,3 +405,15 @@ func TestRestoreCalledWorkflowContext(t *testing.T) {
assert.Equal(t, "workflow_call", task.Context.AsMap()["event_name"])
})
}
func TestTaskLogFields(t *testing.T) {
fields := func(token string) log.Fields {
taskContext, err := structpb.NewStruct(map[string]any{"repository": "owner/repo", "run_id": "159", "run_number": "14", "gitea_runtime_token": token})
require.NoError(t, err)
return taskLogFields(&runnerv1.Task{Id: 72, Context: taskContext}, "build")
}
want := log.Fields{"task_id": int64(72), "job": "build", "repository": "owner/repo", "run_id": "159", "run_number": "14"}
assert.Equal(t, want, fields("malformed"))
want["job_id"] = int64(221)
assert.Equal(t, want, fields("header."+base64.RawURLEncoding.EncodeToString([]byte(`{"TaskID":72,"JobID":221}`))+".signature"))
}