Skip to content

Commit 0534edd

Browse files
authored
Use run-name and evaluate workflow variables (#34301)
This addresses #34247 depends on https://gitea.com/gitea/act/pulls/137 I couldn't find any previous implementation for `run-name` support on workflows so I created one. Key points: All dispatched workflows, scheduled workflows and detected workflows (from different hooks) will use and evaluate `run-name` if exists, with the corresponding gitea context and variables. This will be used as the Action run title and replace the default commit message being used today. Had to change act package jobparser (see link above) and create two helpers https://github.com/go-gitea/gitea/blob/3a1320c70df82ae88e286612c1646cffb8e2c343/models/actions/utils.go#L86 and https://github.com/go-gitea/gitea/blob/3a1320c70df82ae88e286612c1646cffb8e2c343/services/actions/context.go#L169 to pass the correct types to [GenerateGiteaContext](https://github.com/go-gitea/gitea/pull/34301/files#diff-9c9c27cb61a33e55ad33dc2c2e6a3521957a3e5cc50ddf652fdcd1def87b044dR86) and [WithGitContext](https://gitea.com/gitea/act/src/commit/65c232c4a5a40e59e257ab5d956b32585f0405d7/pkg/jobparser/jobparser.go#L84) respectively. <img width="1336" alt="Screenshot 2025-04-28 at 17 13 01" src="https://github.com/user-attachments/assets/73cb03d0-23a0-4858-a466-bbf0748cea98" />
1 parent d06eb8d commit 0534edd

File tree

7 files changed

+293
-33
lines changed

7 files changed

+293
-33
lines changed

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,7 @@ replace github.com/hashicorp/go-version => github.com/6543/go-version v1.3.1
317317

318318
replace github.com/shurcooL/vfsgen => github.com/lunny/vfsgen v0.0.0-20220105142115-2c99e1ffdfa0
319319

320-
replace github.com/nektos/act => gitea.com/gitea/act v0.261.4
320+
replace github.com/nektos/act => gitea.com/gitea/act v0.261.6
321321

322322
// TODO: the only difference is in `PutObject`: the fork doesn't use `NewVerifyingReader(r, sha256.New(), oid, expectedSize)`, need to figure out why
323323
replace github.com/charmbracelet/git-lfs-transfer => gitea.com/gitea/git-lfs-transfer v0.2.0

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s=
1414
dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
1515
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
1616
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
17-
gitea.com/gitea/act v0.261.4 h1:Tf9eLlvsYFtKcpuxlMvf9yT3g4Hshb2Beqw6C1STuH8=
18-
gitea.com/gitea/act v0.261.4/go.mod h1:Pg5C9kQY1CEA3QjthjhlrqOC/QOT5NyWNjOjRHw23Ok=
17+
gitea.com/gitea/act v0.261.6 h1:CjZwKOyejonNFDmsXOw3wGm5Vet573hHM6VMLsxtvPY=
18+
gitea.com/gitea/act v0.261.6/go.mod h1:Pg5C9kQY1CEA3QjthjhlrqOC/QOT5NyWNjOjRHw23Ok=
1919
gitea.com/gitea/git-lfs-transfer v0.2.0 h1:baHaNoBSRaeq/xKayEXwiDQtlIjps4Ac/Ll4KqLMB40=
2020
gitea.com/gitea/git-lfs-transfer v0.2.0/go.mod h1:UrXUCm3xLQkq15fu7qlXHUMlrhdlXHoi13KH2Dfiits=
2121
gitea.com/gitea/go-xsd-duration v0.0.0-20220703122237-02e73435a078 h1:BAFmdZpRW7zMQZQDClaCWobRj9uL1MR3MzpCVJvc5s4=

models/actions/utils.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,3 +82,22 @@ func calculateDuration(started, stopped timeutil.TimeStamp, status Status) time.
8282
}
8383
return timeSince(s).Truncate(time.Second)
8484
}
85+
86+
// best effort function to convert an action schedule to action run, to be used in GenerateGiteaContext
87+
func (s *ActionSchedule) ToActionRun() *ActionRun {
88+
return &ActionRun{
89+
Title: s.Title,
90+
RepoID: s.RepoID,
91+
Repo: s.Repo,
92+
OwnerID: s.OwnerID,
93+
WorkflowID: s.WorkflowID,
94+
TriggerUserID: s.TriggerUserID,
95+
TriggerUser: s.TriggerUser,
96+
Ref: s.Ref,
97+
CommitSHA: s.CommitSHA,
98+
Event: s.Event,
99+
EventPayload: s.EventPayload,
100+
Created: s.Created,
101+
Updated: s.Updated,
102+
}
103+
}

services/actions/context.go

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,15 @@ import (
1515
"code.gitea.io/gitea/modules/git"
1616
"code.gitea.io/gitea/modules/json"
1717
"code.gitea.io/gitea/modules/setting"
18+
19+
"github.com/nektos/act/pkg/model"
1820
)
1921

22+
type GiteaContext map[string]any
23+
2024
// GenerateGiteaContext generate the gitea context without token and gitea_runtime_token
2125
// job can be nil when generating a context for parsing workflow-level expressions
22-
func GenerateGiteaContext(run *actions_model.ActionRun, job *actions_model.ActionRunJob) map[string]any {
26+
func GenerateGiteaContext(run *actions_model.ActionRun, job *actions_model.ActionRunJob) GiteaContext {
2327
event := map[string]any{}
2428
_ = json.Unmarshal([]byte(run.EventPayload), &event)
2529

@@ -42,7 +46,7 @@ func GenerateGiteaContext(run *actions_model.ActionRun, job *actions_model.Actio
4246

4347
refName := git.RefName(ref)
4448

45-
gitContext := map[string]any{
49+
gitContext := GiteaContext{
4650
// standard contexts, see https://docs.github.com/en/actions/learn-github-actions/contexts#github-context
4751
"action": "", // string, The name of the action currently running, or the id of a step. GitHub removes special characters, and uses the name __run when the current step runs a script without an id. If you use the same action more than once in the same job, the name will include a suffix with the sequence number with underscore before it. For example, the first script you run will have the name __run, and the second script will be named __run_2. Similarly, the second invocation of actions/checkout will be actionscheckout2.
4852
"action_path": "", // string, The path where an action is located. This property is only supported in composite actions. You can use this path to access files located in the same repository as the action.
@@ -160,3 +164,37 @@ func mergeTwoOutputs(o1, o2 map[string]string) map[string]string {
160164
}
161165
return ret
162166
}
167+
168+
func (g *GiteaContext) ToGitHubContext() *model.GithubContext {
169+
return &model.GithubContext{
170+
Event: (*g)["event"].(map[string]any),
171+
EventPath: (*g)["event_path"].(string),
172+
Workflow: (*g)["workflow"].(string),
173+
RunID: (*g)["run_id"].(string),
174+
RunNumber: (*g)["run_number"].(string),
175+
Actor: (*g)["actor"].(string),
176+
Repository: (*g)["repository"].(string),
177+
EventName: (*g)["event_name"].(string),
178+
Sha: (*g)["sha"].(string),
179+
Ref: (*g)["ref"].(string),
180+
RefName: (*g)["ref_name"].(string),
181+
RefType: (*g)["ref_type"].(string),
182+
HeadRef: (*g)["head_ref"].(string),
183+
BaseRef: (*g)["base_ref"].(string),
184+
Token: "", // deliberately omitted for security
185+
Workspace: (*g)["workspace"].(string),
186+
Action: (*g)["action"].(string),
187+
ActionPath: (*g)["action_path"].(string),
188+
ActionRef: (*g)["action_ref"].(string),
189+
ActionRepository: (*g)["action_repository"].(string),
190+
Job: (*g)["job"].(string),
191+
JobName: "", // not present in GiteaContext
192+
RepositoryOwner: (*g)["repository_owner"].(string),
193+
RetentionDays: (*g)["retention_days"].(string),
194+
RunnerPerflog: "", // not present in GiteaContext
195+
RunnerTrackingID: "", // not present in GiteaContext
196+
ServerURL: (*g)["server_url"].(string),
197+
APIURL: (*g)["api_url"].(string),
198+
GraphQLURL: (*g)["graphql_url"].(string),
199+
}
200+
}

services/actions/notifier_helper.go

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -302,9 +302,11 @@ func handleWorkflows(
302302
run := &actions_model.ActionRun{
303303
Title: strings.SplitN(commit.CommitMessage, "\n", 2)[0],
304304
RepoID: input.Repo.ID,
305+
Repo: input.Repo,
305306
OwnerID: input.Repo.OwnerID,
306307
WorkflowID: dwf.EntryName,
307308
TriggerUserID: input.Doer.ID,
309+
TriggerUser: input.Doer,
308310
Ref: ref,
309311
CommitSHA: commit.ID.String(),
310312
IsForkPullRequest: isForkPullRequest,
@@ -333,12 +335,18 @@ func handleWorkflows(
333335
continue
334336
}
335337

336-
jobs, err := jobparser.Parse(dwf.Content, jobparser.WithVars(vars))
338+
giteaCtx := GenerateGiteaContext(run, nil)
339+
340+
jobs, err := jobparser.Parse(dwf.Content, jobparser.WithVars(vars), jobparser.WithGitContext(giteaCtx.ToGitHubContext()))
337341
if err != nil {
338342
log.Error("jobparser.Parse: %v", err)
339343
continue
340344
}
341345

346+
if len(jobs) > 0 && jobs[0].RunName != "" {
347+
run.Title = jobs[0].RunName
348+
}
349+
342350
// cancel running jobs if the event is push or pull_request_sync
343351
if run.Event == webhook_module.HookEventPush ||
344352
run.Event == webhook_module.HookEventPullRequestSync {
@@ -508,16 +516,37 @@ func handleSchedules(
508516
run := &actions_model.ActionSchedule{
509517
Title: strings.SplitN(commit.CommitMessage, "\n", 2)[0],
510518
RepoID: input.Repo.ID,
519+
Repo: input.Repo,
511520
OwnerID: input.Repo.OwnerID,
512521
WorkflowID: dwf.EntryName,
513522
TriggerUserID: user_model.ActionsUserID,
523+
TriggerUser: user_model.NewActionsUser(),
514524
Ref: ref,
515525
CommitSHA: commit.ID.String(),
516526
Event: input.Event,
517527
EventPayload: string(p),
518528
Specs: schedules,
519529
Content: dwf.Content,
520530
}
531+
532+
vars, err := actions_model.GetVariablesOfRun(ctx, run.ToActionRun())
533+
if err != nil {
534+
log.Error("GetVariablesOfRun: %v", err)
535+
continue
536+
}
537+
538+
giteaCtx := GenerateGiteaContext(run.ToActionRun(), nil)
539+
540+
jobs, err := jobparser.Parse(dwf.Content, jobparser.WithVars(vars), jobparser.WithGitContext(giteaCtx.ToGitHubContext()))
541+
if err != nil {
542+
log.Error("jobparser.Parse: %v", err)
543+
continue
544+
}
545+
546+
if len(jobs) > 0 && jobs[0].RunName != "" {
547+
run.Title = jobs[0].RunName
548+
}
549+
521550
crons = append(crons, run)
522551
}
523552

services/actions/workflow.go

Lines changed: 46 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -192,22 +192,55 @@ func DispatchActionWorkflow(ctx reqctx.RequestContext, doer *user_model.User, re
192192

193193
// find workflow from commit
194194
var workflows []*jobparser.SingleWorkflow
195-
for _, entry := range entries {
196-
if entry.Name() != workflowID {
197-
continue
198-
}
195+
var entry *git.TreeEntry
199196

200-
content, err := actions.GetContentFromEntry(entry)
201-
if err != nil {
202-
return err
203-
}
204-
workflows, err = jobparser.Parse(content)
205-
if err != nil {
206-
return err
197+
run := &actions_model.ActionRun{
198+
Title: strings.SplitN(runTargetCommit.CommitMessage, "\n", 2)[0],
199+
RepoID: repo.ID,
200+
Repo: repo,
201+
OwnerID: repo.OwnerID,
202+
WorkflowID: workflowID,
203+
TriggerUserID: doer.ID,
204+
TriggerUser: doer,
205+
Ref: string(refName),
206+
CommitSHA: runTargetCommit.ID.String(),
207+
IsForkPullRequest: false,
208+
Event: "workflow_dispatch",
209+
TriggerEvent: "workflow_dispatch",
210+
Status: actions_model.StatusWaiting,
211+
}
212+
213+
for _, e := range entries {
214+
if e.Name() != workflowID {
215+
continue
207216
}
217+
entry = e
208218
break
209219
}
210220

221+
if entry == nil {
222+
return util.ErrorWrapLocale(
223+
util.NewNotExistErrorf("workflow %q doesn't exist", workflowID),
224+
"actions.workflow.not_found", workflowID,
225+
)
226+
}
227+
228+
content, err := actions.GetContentFromEntry(entry)
229+
if err != nil {
230+
return err
231+
}
232+
233+
giteaCtx := GenerateGiteaContext(run, nil)
234+
235+
workflows, err = jobparser.Parse(content, jobparser.WithGitContext(giteaCtx.ToGitHubContext()))
236+
if err != nil {
237+
return err
238+
}
239+
240+
if len(workflows) > 0 && workflows[0].RunName != "" {
241+
run.Title = workflows[0].RunName
242+
}
243+
211244
if len(workflows) == 0 {
212245
return util.ErrorWrapLocale(
213246
util.NewNotExistErrorf("workflow %q doesn't exist", workflowID),
@@ -236,25 +269,12 @@ func DispatchActionWorkflow(ctx reqctx.RequestContext, doer *user_model.User, re
236269
Inputs: inputsWithDefaults,
237270
Sender: convert.ToUserWithAccessMode(ctx, doer, perm.AccessModeNone),
238271
}
272+
239273
var eventPayload []byte
240274
if eventPayload, err = workflowDispatchPayload.JSONPayload(); err != nil {
241275
return fmt.Errorf("JSONPayload: %w", err)
242276
}
243-
244-
run := &actions_model.ActionRun{
245-
Title: strings.SplitN(runTargetCommit.CommitMessage, "\n", 2)[0],
246-
RepoID: repo.ID,
247-
OwnerID: repo.OwnerID,
248-
WorkflowID: workflowID,
249-
TriggerUserID: doer.ID,
250-
Ref: string(refName),
251-
CommitSHA: runTargetCommit.ID.String(),
252-
IsForkPullRequest: false,
253-
Event: "workflow_dispatch",
254-
TriggerEvent: "workflow_dispatch",
255-
EventPayload: string(eventPayload),
256-
Status: actions_model.StatusWaiting,
257-
}
277+
run.EventPayload = string(eventPayload)
258278

259279
// cancel running jobs of the same workflow
260280
if err := CancelPreviousJobs(
@@ -280,6 +300,5 @@ func DispatchActionWorkflow(ctx reqctx.RequestContext, doer *user_model.User, re
280300
for _, job := range allJobs {
281301
notify_service.WorkflowJobStatusUpdate(ctx, repo, doer, job, nil)
282302
}
283-
284303
return nil
285304
}

0 commit comments

Comments
 (0)