Skip to content

Commit 17fe70a

Browse files
committed
Merge remote-tracking branch 'giteaofficial/main'
* giteaofficial/main: add CfTurnstileSitekey context data to all captcha templates (go-gitea#31874) Add tag name in the commits list (go-gitea#31082) Fix actions notify bug (go-gitea#31866) Actions support workflow dispatch event (go-gitea#28163)
2 parents 8de67cb + 0d24c9f commit 17fe70a

File tree

23 files changed

+666
-35
lines changed

23 files changed

+666
-35
lines changed

models/migrations/migrations.go

+2
Original file line numberDiff line numberDiff line change
@@ -599,6 +599,8 @@ var migrations = []Migration{
599599
NewMigration("Add index to action_task stopped log_expired", v1_23.AddIndexToActionTaskStoppedLogExpired),
600600
// v303 -> v304
601601
NewMigration("Add metadata column for comment table", v1_23.AddCommentMetaDataColumn),
602+
// v304 -> v305
603+
NewMigration("Add index for release sha1", v1_23.AddIndexForReleaseSha1),
602604
}
603605

604606
// GetCurrentDBVersion returns the current db version

models/migrations/v1_23/v304.go

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Copyright 2024 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package v1_23 //nolint
5+
6+
import "xorm.io/xorm"
7+
8+
func AddIndexForReleaseSha1(x *xorm.Engine) error {
9+
type Release struct {
10+
Sha1 string `xorm:"INDEX VARCHAR(64)"`
11+
}
12+
return x.Sync(new(Release))
13+
}

models/repo/release.go

+15-1
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ type Release struct {
7777
Target string
7878
TargetBehind string `xorm:"-"` // to handle non-existing or empty target
7979
Title string
80-
Sha1 string `xorm:"VARCHAR(64)"`
80+
Sha1 string `xorm:"INDEX VARCHAR(64)"`
8181
NumCommits int64
8282
NumCommitsBehind int64 `xorm:"-"`
8383
Note string `xorm:"TEXT"`
@@ -537,3 +537,17 @@ func InsertReleases(ctx context.Context, rels ...*Release) error {
537537

538538
return committer.Commit()
539539
}
540+
541+
func FindTagsByCommitIDs(ctx context.Context, repoID int64, commitIDs ...string) (map[string][]*Release, error) {
542+
releases := make([]*Release, 0, len(commitIDs))
543+
if err := db.GetEngine(ctx).Where("repo_id=?", repoID).
544+
In("sha1", commitIDs).
545+
Find(&releases); err != nil {
546+
return nil, err
547+
}
548+
res := make(map[string][]*Release, len(releases))
549+
for _, r := range releases {
550+
res[r.Sha1] = append(res[r.Sha1], r)
551+
}
552+
return res, nil
553+
}

models/repo/release_test.go

+13
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,16 @@ func TestMigrate_InsertReleases(t *testing.T) {
2525
err := InsertReleases(db.DefaultContext, r)
2626
assert.NoError(t, err)
2727
}
28+
29+
func Test_FindTagsByCommitIDs(t *testing.T) {
30+
assert.NoError(t, unittest.PrepareTestDatabase())
31+
32+
sha1Rels, err := FindTagsByCommitIDs(db.DefaultContext, 1, "65f1bf27bc3bf70f64657658635e66094edbcb4d")
33+
assert.NoError(t, err)
34+
assert.Len(t, sha1Rels, 1)
35+
rels := sha1Rels["65f1bf27bc3bf70f64657658635e66094edbcb4d"]
36+
assert.Len(t, rels, 3)
37+
assert.Equal(t, "v1.1", rels[0].TagName)
38+
assert.Equal(t, "delete-tag", rels[1].TagName)
39+
assert.Equal(t, "v1.0", rels[2].TagName)
40+
}

modules/structs/hook.go

+14
Original file line numberDiff line numberDiff line change
@@ -494,3 +494,17 @@ type PackagePayload struct {
494494
func (p *PackagePayload) JSONPayload() ([]byte, error) {
495495
return json.MarshalIndent(p, "", " ")
496496
}
497+
498+
// WorkflowDispatchPayload represents a workflow dispatch payload
499+
type WorkflowDispatchPayload struct {
500+
Workflow string `json:"workflow"`
501+
Ref string `json:"ref"`
502+
Inputs map[string]any `json:"inputs"`
503+
Repository *Repository `json:"repository"`
504+
Sender *User `json:"sender"`
505+
}
506+
507+
// JSONPayload implements Payload
508+
func (p *WorkflowDispatchPayload) JSONPayload() ([]byte, error) {
509+
return json.MarshalIndent(p, "", " ")
510+
}

options/locale/locale_en-US.ini

+7
Original file line numberDiff line numberDiff line change
@@ -628,6 +628,7 @@ org_still_own_repo = "This organization still owns one or more repositories, del
628628
org_still_own_packages = "This organization still owns one or more packages, delete them first."
629629
630630
target_branch_not_exist = Target branch does not exist.
631+
target_ref_not_exist = Target ref does not exist %s
631632
632633
admin_cannot_delete_self = You cannot delete yourself when you are an admin. Please remove your admin privileges first.
633634
@@ -1273,6 +1274,7 @@ commit_graph.color = Color
12731274
commit.contained_in = This commit is contained in:
12741275
commit.contained_in_default_branch = This commit is part of the default branch
12751276
commit.load_referencing_branches_and_tags = Load branches and tags referencing this commit
1277+
commit.load_tags_failed = Load tags failed because of internal error
12761278
blame = Blame
12771279
download_file = Download file
12781280
normal_view = Normal View
@@ -3701,6 +3703,11 @@ workflow.disable_success = Workflow '%s' disabled successfully.
37013703
workflow.enable = Enable Workflow
37023704
workflow.enable_success = Workflow '%s' enabled successfully.
37033705
workflow.disabled = Workflow is disabled.
3706+
workflow.run = Run Workflow
3707+
workflow.not_found = Workflow '%s' not found.
3708+
workflow.run_success = Workflow '%s' run successfully.
3709+
workflow.from_ref = Use workflow from
3710+
workflow.has_workflow_dispatch = This workflow has a workflow_dispatch event trigger.
37043711

37053712
need_approval_desc = Need approval to run workflows for fork pull request.
37063713

routers/web/auth/linkaccount.go

+3
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ func LinkAccount(ctx *context.Context) {
4040
ctx.Data["HcaptchaSitekey"] = setting.Service.HcaptchaSitekey
4141
ctx.Data["McaptchaSitekey"] = setting.Service.McaptchaSitekey
4242
ctx.Data["McaptchaURL"] = setting.Service.McaptchaURL
43+
ctx.Data["CfTurnstileSitekey"] = setting.Service.CfTurnstileSitekey
4344
ctx.Data["DisableRegistration"] = setting.Service.DisableRegistration
4445
ctx.Data["AllowOnlyInternalRegistration"] = setting.Service.AllowOnlyInternalRegistration
4546
ctx.Data["ShowRegistrationButton"] = false
@@ -132,6 +133,7 @@ func LinkAccountPostSignIn(ctx *context.Context) {
132133
ctx.Data["HcaptchaSitekey"] = setting.Service.HcaptchaSitekey
133134
ctx.Data["McaptchaSitekey"] = setting.Service.McaptchaSitekey
134135
ctx.Data["McaptchaURL"] = setting.Service.McaptchaURL
136+
ctx.Data["CfTurnstileSitekey"] = setting.Service.CfTurnstileSitekey
135137
ctx.Data["DisableRegistration"] = setting.Service.DisableRegistration
136138
ctx.Data["ShowRegistrationButton"] = false
137139

@@ -219,6 +221,7 @@ func LinkAccountPostRegister(ctx *context.Context) {
219221
ctx.Data["HcaptchaSitekey"] = setting.Service.HcaptchaSitekey
220222
ctx.Data["McaptchaSitekey"] = setting.Service.McaptchaSitekey
221223
ctx.Data["McaptchaURL"] = setting.Service.McaptchaURL
224+
ctx.Data["CfTurnstileSitekey"] = setting.Service.CfTurnstileSitekey
222225
ctx.Data["DisableRegistration"] = setting.Service.DisableRegistration
223226
ctx.Data["ShowRegistrationButton"] = false
224227

routers/web/auth/openid.go

+1
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,7 @@ func RegisterOpenID(ctx *context.Context) {
307307
ctx.Data["RecaptchaURL"] = setting.Service.RecaptchaURL
308308
ctx.Data["McaptchaSitekey"] = setting.Service.McaptchaSitekey
309309
ctx.Data["McaptchaURL"] = setting.Service.McaptchaURL
310+
ctx.Data["CfTurnstileSitekey"] = setting.Service.CfTurnstileSitekey
310311
ctx.Data["OpenID"] = oid
311312
userName, _ := ctx.Session.Get("openid_determined_username").(string)
312313
if userName != "" {

routers/web/repo/actions/actions.go

+136-9
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,28 @@ import (
77
"bytes"
88
"fmt"
99
"net/http"
10+
"slices"
1011
"strings"
1112

1213
actions_model "code.gitea.io/gitea/models/actions"
1314
"code.gitea.io/gitea/models/db"
15+
git_model "code.gitea.io/gitea/models/git"
16+
repo_model "code.gitea.io/gitea/models/repo"
1417
"code.gitea.io/gitea/models/unit"
1518
"code.gitea.io/gitea/modules/actions"
1619
"code.gitea.io/gitea/modules/base"
1720
"code.gitea.io/gitea/modules/container"
1821
"code.gitea.io/gitea/modules/git"
22+
"code.gitea.io/gitea/modules/log"
1923
"code.gitea.io/gitea/modules/optional"
2024
"code.gitea.io/gitea/modules/setting"
25+
"code.gitea.io/gitea/modules/util"
2126
"code.gitea.io/gitea/routers/web/repo"
2227
"code.gitea.io/gitea/services/context"
2328
"code.gitea.io/gitea/services/convert"
2429

2530
"github.com/nektos/act/pkg/model"
31+
"gopkg.in/yaml.v3"
2632
)
2733

2834
const (
@@ -58,8 +64,13 @@ func MustEnableActions(ctx *context.Context) {
5864
func List(ctx *context.Context) {
5965
ctx.Data["Title"] = ctx.Tr("actions.actions")
6066
ctx.Data["PageIsActions"] = true
67+
workflowID := ctx.FormString("workflow")
68+
actorID := ctx.FormInt64("actor")
69+
status := ctx.FormInt("status")
70+
ctx.Data["CurWorkflow"] = workflowID
6171

6272
var workflows []Workflow
73+
var curWorkflow *model.Workflow
6374
if empty, err := ctx.Repo.GitRepo.IsEmpty(); err != nil {
6475
ctx.ServerError("IsEmpty", err)
6576
return
@@ -140,6 +151,10 @@ func List(ctx *context.Context) {
140151
workflow.ErrMsg = ctx.Locale.TrString("actions.runs.no_job")
141152
}
142153
workflows = append(workflows, workflow)
154+
155+
if workflow.Entry.Name() == workflowID {
156+
curWorkflow = wf
157+
}
143158
}
144159
}
145160
ctx.Data["workflows"] = workflows
@@ -150,17 +165,46 @@ func List(ctx *context.Context) {
150165
page = 1
151166
}
152167

153-
workflow := ctx.FormString("workflow")
154-
actorID := ctx.FormInt64("actor")
155-
status := ctx.FormInt("status")
156-
ctx.Data["CurWorkflow"] = workflow
157-
158168
actionsConfig := ctx.Repo.Repository.MustGetUnit(ctx, unit.TypeActions).ActionsConfig()
159169
ctx.Data["ActionsConfig"] = actionsConfig
160170

161-
if len(workflow) > 0 && ctx.Repo.IsAdmin() {
171+
if len(workflowID) > 0 && ctx.Repo.IsAdmin() {
162172
ctx.Data["AllowDisableOrEnableWorkflow"] = true
163-
ctx.Data["CurWorkflowDisabled"] = actionsConfig.IsWorkflowDisabled(workflow)
173+
isWorkflowDisabled := actionsConfig.IsWorkflowDisabled(workflowID)
174+
ctx.Data["CurWorkflowDisabled"] = isWorkflowDisabled
175+
176+
if !isWorkflowDisabled && curWorkflow != nil {
177+
workflowDispatchConfig := workflowDispatchConfig(curWorkflow)
178+
if workflowDispatchConfig != nil {
179+
ctx.Data["WorkflowDispatchConfig"] = workflowDispatchConfig
180+
181+
branchOpts := git_model.FindBranchOptions{
182+
RepoID: ctx.Repo.Repository.ID,
183+
IsDeletedBranch: optional.Some(false),
184+
ListOptions: db.ListOptions{
185+
ListAll: true,
186+
},
187+
}
188+
branches, err := git_model.FindBranchNames(ctx, branchOpts)
189+
if err != nil {
190+
ctx.ServerError("FindBranchNames", err)
191+
return
192+
}
193+
// always put default branch on the top if it exists
194+
if slices.Contains(branches, ctx.Repo.Repository.DefaultBranch) {
195+
branches = util.SliceRemoveAll(branches, ctx.Repo.Repository.DefaultBranch)
196+
branches = append([]string{ctx.Repo.Repository.DefaultBranch}, branches...)
197+
}
198+
ctx.Data["Branches"] = branches
199+
200+
tags, err := repo_model.GetTagNamesByRepoID(ctx, ctx.Repo.Repository.ID)
201+
if err != nil {
202+
ctx.ServerError("GetTagNamesByRepoID", err)
203+
return
204+
}
205+
ctx.Data["Tags"] = tags
206+
}
207+
}
164208
}
165209

166210
// if status or actor query param is not given to frontend href, (href="/<repoLink>/actions")
@@ -177,7 +221,7 @@ func List(ctx *context.Context) {
177221
PageSize: convert.ToCorrectPageSize(ctx.FormInt("limit")),
178222
},
179223
RepoID: ctx.Repo.Repository.ID,
180-
WorkflowID: workflow,
224+
WorkflowID: workflowID,
181225
TriggerUserID: actorID,
182226
}
183227

@@ -214,11 +258,94 @@ func List(ctx *context.Context) {
214258

215259
pager := context.NewPagination(int(total), opts.PageSize, opts.Page, 5)
216260
pager.SetDefaultParams(ctx)
217-
pager.AddParamString("workflow", workflow)
261+
pager.AddParamString("workflow", workflowID)
218262
pager.AddParamString("actor", fmt.Sprint(actorID))
219263
pager.AddParamString("status", fmt.Sprint(status))
220264
ctx.Data["Page"] = pager
221265
ctx.Data["HasWorkflowsOrRuns"] = len(workflows) > 0 || len(runs) > 0
222266

223267
ctx.HTML(http.StatusOK, tplListActions)
224268
}
269+
270+
type WorkflowDispatchInput struct {
271+
Name string `yaml:"name"`
272+
Description string `yaml:"description"`
273+
Required bool `yaml:"required"`
274+
Default string `yaml:"default"`
275+
Type string `yaml:"type"`
276+
Options []string `yaml:"options"`
277+
}
278+
279+
type WorkflowDispatch struct {
280+
Inputs []WorkflowDispatchInput
281+
}
282+
283+
func workflowDispatchConfig(w *model.Workflow) *WorkflowDispatch {
284+
switch w.RawOn.Kind {
285+
case yaml.ScalarNode:
286+
var val string
287+
if !decodeNode(w.RawOn, &val) {
288+
return nil
289+
}
290+
if val == "workflow_dispatch" {
291+
return &WorkflowDispatch{}
292+
}
293+
case yaml.SequenceNode:
294+
var val []string
295+
if !decodeNode(w.RawOn, &val) {
296+
return nil
297+
}
298+
for _, v := range val {
299+
if v == "workflow_dispatch" {
300+
return &WorkflowDispatch{}
301+
}
302+
}
303+
case yaml.MappingNode:
304+
var val map[string]yaml.Node
305+
if !decodeNode(w.RawOn, &val) {
306+
return nil
307+
}
308+
309+
workflowDispatchNode, found := val["workflow_dispatch"]
310+
if !found {
311+
return nil
312+
}
313+
314+
var workflowDispatch WorkflowDispatch
315+
var workflowDispatchVal map[string]yaml.Node
316+
if !decodeNode(workflowDispatchNode, &workflowDispatchVal) {
317+
return &workflowDispatch
318+
}
319+
320+
inputsNode, found := workflowDispatchVal["inputs"]
321+
if !found || inputsNode.Kind != yaml.MappingNode {
322+
return &workflowDispatch
323+
}
324+
325+
i := 0
326+
for {
327+
if i+1 >= len(inputsNode.Content) {
328+
break
329+
}
330+
var input WorkflowDispatchInput
331+
if decodeNode(*inputsNode.Content[i+1], &input) {
332+
input.Name = inputsNode.Content[i].Value
333+
workflowDispatch.Inputs = append(workflowDispatch.Inputs, input)
334+
}
335+
i += 2
336+
}
337+
return &workflowDispatch
338+
339+
default:
340+
return nil
341+
}
342+
return nil
343+
}
344+
345+
func decodeNode(node yaml.Node, out any) bool {
346+
if err := node.Decode(out); err != nil {
347+
log.Warn("Failed to decode node %v into %T: %v", node, out, err)
348+
return false
349+
}
350+
return true
351+
}

0 commit comments

Comments
 (0)