Skip to content

Commit 5243490

Browse files
committed
Enable the global workflow and require_action in org setting
Signed-off-by: Alex Lau(AvengerMoJo) <[email protected]>
1 parent d547b53 commit 5243490

File tree

17 files changed

+551
-1
lines changed

17 files changed

+551
-1
lines changed

models/actions/require_action.go

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
// Copyright 2024 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
// WIP RequireAction
5+
6+
package actions
7+
8+
import (
9+
"context"
10+
11+
"code.gitea.io/gitea/models/db"
12+
//"code.gitea.io/gitea/models/unit"
13+
"code.gitea.io/gitea/modules/timeutil"
14+
15+
"xorm.io/builder"
16+
)
17+
18+
type RequireAction struct {
19+
ID int64 `xorm:"pk autoincr"`
20+
OrgID int64 `xorm:"index"`
21+
RepoName string `xorm:"VARCHAR(255)"`
22+
WorkflowName string `xorm:"VARCHAR(255) UNIQUE(require_action) NOT NULL"`
23+
//Description string `xorm:"LONGTEXT NOT NULL"`
24+
CreatedUnix timeutil.TimeStamp `xorm:"created NOT NULL"`
25+
UpdatedUnix timeutil.TimeStamp `xorm:"updated"`
26+
// RepoRange string // glob match which repositories could use this runner
27+
}
28+
29+
type GlobalWorkflow struct {
30+
RepoName string
31+
Filename string
32+
}
33+
34+
func init() {
35+
db.RegisterModel(new(RequireAction))
36+
}
37+
38+
type FindRequireActionOptions struct {
39+
db.ListOptions
40+
RequireActionID int64
41+
OrgID int64
42+
RepoName string
43+
}
44+
45+
func (opts FindRequireActionOptions) ToConds() builder.Cond {
46+
cond := builder.NewCond()
47+
if opts.OrgID > 0 {
48+
cond = cond.And(builder.Eq{"org_id": opts.OrgID})
49+
}
50+
if opts.RequireActionID > 0 {
51+
cond = cond.And(builder.Eq{"id": opts.RequireActionID})
52+
}
53+
if opts.RepoName != "" {
54+
cond = cond.And(builder.Eq{"repo_name": opts.RepoName})
55+
}
56+
return cond
57+
}
58+
59+
// LoadAttributes loads the attributes of the require action
60+
func (r *RequireAction) LoadAttributes(ctx context.Context) error {
61+
// place holder for now.
62+
return nil
63+
}
64+
65+
// if the workflow is removable
66+
func (r *RequireAction) Removable(orgID int64) bool {
67+
// everyone can remove for now
68+
if r.OrgID == orgID {
69+
return true
70+
}
71+
return false
72+
}
73+
74+
75+
func AddRequireAction(ctx context.Context, orgID int64, repoName string, workflowName string) (*RequireAction, error) {
76+
ra := &RequireAction{
77+
OrgID: orgID,
78+
RepoName: repoName,
79+
WorkflowName: workflowName,
80+
}
81+
return ra, db.Insert(ctx, ra)
82+
}

models/migrations/migrations.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -576,7 +576,10 @@ var migrations = []Migration{
576576

577577
// Gitea 1.22.0 ends at 294
578578

579+
// v294 -> v295
579580
NewMigration("Add unique index for project issue table", v1_23.AddUniqueIndexForProjectIssue),
581+
// v295 -> v296
582+
NewMigration("Add RequireAction Global Workflow", v1_23.AddRequireActionTable),
580583
}
581584

582585
// GetCurrentDBVersion returns the current db version

models/migrations/v1_23/v295.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright 2023 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package v1_23 //nolint
5+
6+
import (
7+
"code.gitea.io/gitea/modules/timeutil"
8+
"xorm.io/xorm"
9+
)
10+
11+
func AddRequireActionTable(x *xorm.Engine) error {
12+
type RequireAction struct {
13+
ID int64 `xorm:"pk autoincr"`
14+
OrgID int64 `xorm:"index"`
15+
RepoName string `xorm:"VARCHAR(255)"`
16+
WorkflowName string `xorm:"VARCHAR(255) UNIQUE(require_action) NOT NULL"`
17+
CreatedUnix timeutil.TimeStamp `xorm:"created NOT NULL"`
18+
UpdatedUnix timeutil.TimeStamp `xorm:"updated"`
19+
}
20+
return x.Sync(new(RequireAction))
21+
}

models/repo/repo_unit.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,10 +168,27 @@ func (cfg *PullRequestsConfig) GetDefaultMergeStyle() MergeStyle {
168168

169169
type ActionsConfig struct {
170170
DisabledWorkflows []string
171+
EnabledGlobalWorkflows []string
171172
}
172173

173174
func (cfg *ActionsConfig) EnableWorkflow(file string) {
174175
cfg.DisabledWorkflows = util.SliceRemoveAll(cfg.DisabledWorkflows, file)
176+
}
177+
178+
func (cfg *ActionsConfig) DisableGlobalWorkflow(file string) {
179+
cfg.EnabledGlobalWorkflows = util.SliceRemoveAll(cfg.EnabledGlobalWorkflows, file)
180+
}
181+
182+
func (cfg *ActionsConfig) IsGlobalWorkflowEnabled(file string) bool {
183+
return slices.Contains(cfg.EnabledGlobalWorkflows, file)
184+
}
185+
186+
func (cfg *ActionsConfig) EnableGlobalWorkflow(file string) {
187+
cfg.EnabledGlobalWorkflows = append(cfg.EnabledGlobalWorkflows, file)
188+
}
189+
190+
func (cfg *ActionsConfig) GetGlobalWorkflow() []string {
191+
return cfg.EnabledGlobalWorkflows
175192
}
176193

177194
func (cfg *ActionsConfig) ToString() string {

options/locale/locale_en-US.ini

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3640,11 +3640,34 @@ runs.no_workflows.documentation = For more information on Gitea Actions, see <a
36403640
runs.no_runs = The workflow has no runs yet.
36413641
runs.empty_commit_message = (empty commit message)
36423642
3643+
require_action = Require Actions
3644+
require_action.require_action_manage_panel = Require Actions Management Panel
3645+
require_action.enable_global_workflow = How to Enable Global Workflow
3646+
require_action.id = ID
3647+
require_action.add = Add Global Workflow
3648+
require_action.add_require_action = Enable selected Workflow
3649+
require_action.new = Create New
3650+
require_action.status = Status
3651+
require_action.version = Version
3652+
require_action.repo = Repo Name
3653+
require_action.workflow = Workflow Filename
3654+
require_action.link = Link
3655+
require_action.remove = Remove
3656+
require_action.none = No Require Actions Available.
3657+
require_action.creation.failed = Create Global Require Action %s Failed.
3658+
require_action.creation.success = Create Global Require Action %s successfully.
3659+
36433660
workflow.disable = Disable Workflow
36443661
workflow.disable_success = Workflow '%s' disabled successfully.
36453662
workflow.enable = Enable Workflow
36463663
workflow.enable_success = Workflow '%s' enabled successfully.
36473664
workflow.disabled = Workflow is disabled.
3665+
workflow.global = Global
3666+
workflow.global_disable = Disable Global Require
3667+
workflow.global_disable_success = Global Require '%s' disabled successfully.
3668+
workflow.global_enable = Enable Global Require
3669+
workflow.global_enable_success = Global Require '%s' enabled successfully.
3670+
workflow.global_enabled = Global Require is disabled.
36483671
36493672
need_approval_desc = Need approval to run workflows for fork pull request.
36503673
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Copyright 2024 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
// WIP RequireAction
5+
6+
package setting
7+
8+
import (
9+
"code.gitea.io/gitea/services/context"
10+
)
11+
12+
func RedirectToRepoSetting(ctx *context.Context) {
13+
ctx.Redirect(ctx.Org.OrgLink + "/settings/actions/require_action")
14+
}

routers/web/repo/actions/actions.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ func List(ctx *context.Context) {
145145
workflow := ctx.FormString("workflow")
146146
actorID := ctx.FormInt64("actor")
147147
status := ctx.FormInt("status")
148+
isGlobal := false
148149
ctx.Data["CurWorkflow"] = workflow
149150

150151
actionsConfig := ctx.Repo.Repository.MustGetUnit(ctx, unit.TypeActions).ActionsConfig()
@@ -153,6 +154,8 @@ func List(ctx *context.Context) {
153154
if len(workflow) > 0 && ctx.Repo.IsAdmin() {
154155
ctx.Data["AllowDisableOrEnableWorkflow"] = true
155156
ctx.Data["CurWorkflowDisabled"] = actionsConfig.IsWorkflowDisabled(workflow)
157+
ctx.Data["CurGlobalWorkflowEnable"] = actionsConfig.IsGlobalWorkflowEnabled(workflow)
158+
isGlobal = actionsConfig.IsGlobalWorkflowEnabled(workflow)
156159
}
157160

158161
// if status or actor query param is not given to frontend href, (href="/<repoLink>/actions")
@@ -209,6 +212,9 @@ func List(ctx *context.Context) {
209212
pager.AddParamString("workflow", workflow)
210213
pager.AddParamString("actor", fmt.Sprint(actorID))
211214
pager.AddParamString("status", fmt.Sprint(status))
215+
if isGlobal {
216+
pager.AddParamString("global", fmt.Sprint(isGlobal))
217+
}
212218
ctx.Data["Page"] = pager
213219
ctx.Data["HasWorkflowsOrRuns"] = len(workflows) > 0 || len(runs) > 0
214220

routers/web/repo/actions/view.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -714,3 +714,38 @@ func disableOrEnableWorkflowFile(ctx *context_module.Context, isEnable bool) {
714714
url.QueryEscape(ctx.FormString("actor")), url.QueryEscape(ctx.FormString("status")))
715715
ctx.JSONRedirect(redirectURL)
716716
}
717+
718+
func DisableGlobalWorkflowFile(ctx *context_module.Context) {
719+
disableOrEnableGlobalWorkflowFile(ctx, true)
720+
}
721+
722+
func EnableGlobalWorkflowFile(ctx *context_module.Context) {
723+
disableOrEnableGlobalWorkflowFile(ctx, false)
724+
}
725+
726+
func disableOrEnableGlobalWorkflowFile(ctx *context_module.Context, isGlobalEnable bool) {
727+
workflow := ctx.FormString("workflow")
728+
if len(workflow) == 0 {
729+
ctx.ServerError("workflow", nil)
730+
return
731+
}
732+
cfgUnit := ctx.Repo.Repository.MustGetUnit(ctx, unit.TypeActions)
733+
cfg := cfgUnit.ActionsConfig()
734+
if isGlobalEnable {
735+
cfg.DisableGlobalWorkflow(workflow)
736+
} else {
737+
cfg.EnableGlobalWorkflow(workflow)
738+
}
739+
if err := repo_model.UpdateRepoUnit(ctx, cfgUnit); err != nil {
740+
ctx.ServerError("UpdateRepoUnit", err)
741+
return
742+
}
743+
if isGlobalEnable {
744+
ctx.Flash.Success(ctx.Tr("actions.workflow.global_disable_success", workflow))
745+
} else {
746+
ctx.Flash.Success(ctx.Tr("actions.workflow.global_enable_success", workflow))
747+
}
748+
redirectURL := fmt.Sprintf("%s/actions?workflow=%s&actor=%s&status=%s", ctx.Repo.RepoLink, url.QueryEscape(workflow),
749+
url.QueryEscape(ctx.FormString("actor")), url.QueryEscape(ctx.FormString("status")))
750+
ctx.JSONRedirect(redirectURL)
751+
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
// Copyright 2024 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
// WIP RequireAction
5+
6+
package setting
7+
8+
import (
9+
"errors"
10+
"net/http"
11+
12+
"code.gitea.io/gitea/models/db"
13+
"code.gitea.io/gitea/modules/base"
14+
// "code.gitea.io/gitea/modules/log"
15+
16+
"code.gitea.io/gitea/services/context"
17+
18+
//"code.gitea.io/gitea/modules/setting"
19+
shared "code.gitea.io/gitea/routers/web/shared/actions"
20+
actions_model "code.gitea.io/gitea/models/actions"
21+
)
22+
23+
const (
24+
// let start with org WIP
25+
tplOrgRequireAction base.TplName = "org/settings/actions"
26+
)
27+
28+
type requireActionsCtx struct {
29+
OrgID int64
30+
IsOrg bool
31+
RequireActionTemplate base.TplName
32+
RedirectLink string
33+
}
34+
35+
func getRequireActionCtx(ctx *context.Context) (*requireActionsCtx, error) {
36+
if ctx.Data["PageIsOrgSettings"] == true {
37+
return &requireActionsCtx{
38+
OrgID: ctx.Org.Organization.ID,
39+
IsOrg: true,
40+
RequireActionTemplate: tplOrgRequireAction,
41+
RedirectLink: ctx.Org.OrgLink + "/settings/actions/require_action",
42+
}, nil
43+
}
44+
return nil, errors.New("unable to set Require Actions context")
45+
}
46+
47+
// Listing all RequireAction
48+
func RequireAction(ctx *context.Context) {
49+
ctx.Data["ActionsTitle"] = ctx.Tr("actions.requires")
50+
ctx.Data["PageType"] = "require_action"
51+
ctx.Data["PageIsSharedSettingsRequireAction"] = true
52+
53+
vCtx, err := getRequireActionCtx(ctx)
54+
if err != nil {
55+
ctx.ServerError("getRequireActionCtx", err)
56+
return
57+
}
58+
59+
page := ctx.FormInt("page")
60+
if page <= 1 { page = 1 }
61+
opts := actions_model.FindRequireActionOptions{
62+
ListOptions: db.ListOptions{
63+
Page: page,
64+
PageSize: 10,
65+
},
66+
}
67+
shared.SetRequireActionContext(ctx, opts)
68+
ctx.Data["Link"] = vCtx.RedirectLink
69+
shared.GlobalEnableWorkflow(ctx, ctx.Org.Organization.ID)
70+
ctx.HTML(http.StatusOK, vCtx.RequireActionTemplate)
71+
}
72+
73+
func RequireActionCreate(ctx *context.Context) {
74+
vCtx, err := getRequireActionCtx(ctx)
75+
if err != nil {
76+
ctx.ServerError("getRequireActionCtx", err)
77+
return
78+
}
79+
shared.CreateRequireAction(ctx, vCtx.OrgID, vCtx.RedirectLink)
80+
}

0 commit comments

Comments
 (0)