Bläddra i källkod

add disable workflow feature (#26413)

As title, that's simmilar with github.


![image](https://github.com/go-gitea/gitea/assets/25342410/9e8b2444-63e0-4e87-80da-730c1e4d09d6)



![image](https://github.com/go-gitea/gitea/assets/25342410/6c3a3345-3ba7-48c9-9acd-3e621632491b)

---------

Signed-off-by: a101211279 <1012112796@qq.com>
Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: Jason Song <i@wolfogre.com>
tags/v1.21.0-rc0
a1012112796 9 månader sedan
förälder
incheckning
19872063a3
Inget konto är kopplat till bidragsgivarens mejladress

+ 6
- 0
models/repo/repo.go Visa fil

@@ -391,7 +391,13 @@ func (repo *Repository) MustGetUnit(ctx context.Context, tp unit.Type) *RepoUnit
Type: tp,
Config: new(IssuesConfig),
}
} else if tp == unit.TypeActions {
return &RepoUnit{
Type: tp,
Config: new(ActionsConfig),
}
}

return &RepoUnit{
Type: tp,
Config: new(UnitConfig),

+ 45
- 1
models/repo/repo_unit.go Visa fil

@@ -6,6 +6,7 @@ package repo
import (
"context"
"fmt"
"strings"

"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/models/unit"
@@ -162,6 +163,42 @@ func (cfg *PullRequestsConfig) GetDefaultMergeStyle() MergeStyle {
return MergeStyleMerge
}

type ActionsConfig struct {
DisabledWorkflows []string
}

func (cfg *ActionsConfig) EnableWorkflow(file string) {
cfg.DisabledWorkflows = util.SliceRemoveAll(cfg.DisabledWorkflows, file)
}

func (cfg *ActionsConfig) ToString() string {
return strings.Join(cfg.DisabledWorkflows, ",")
}

func (cfg *ActionsConfig) IsWorkflowDisabled(file string) bool {
return util.SliceContains(cfg.DisabledWorkflows, file)
}

func (cfg *ActionsConfig) DisableWorkflow(file string) {
for _, workflow := range cfg.DisabledWorkflows {
if file == workflow {
return
}
}

cfg.DisabledWorkflows = append(cfg.DisabledWorkflows, file)
}

// FromDB fills up a ActionsConfig from serialized format.
func (cfg *ActionsConfig) FromDB(bs []byte) error {
return json.UnmarshalHandleDoubleEncode(bs, &cfg)
}

// ToDB exports a ActionsConfig to a serialized format.
func (cfg *ActionsConfig) ToDB() ([]byte, error) {
return json.Marshal(cfg)
}

// BeforeSet is invoked from XORM before setting the value of a field of this object.
func (r *RepoUnit) BeforeSet(colName string, val xorm.Cell) {
switch colName {
@@ -175,7 +212,9 @@ func (r *RepoUnit) BeforeSet(colName string, val xorm.Cell) {
r.Config = new(PullRequestsConfig)
case unit.TypeIssues:
r.Config = new(IssuesConfig)
case unit.TypeCode, unit.TypeReleases, unit.TypeWiki, unit.TypeProjects, unit.TypePackages, unit.TypeActions:
case unit.TypeActions:
r.Config = new(ActionsConfig)
case unit.TypeCode, unit.TypeReleases, unit.TypeWiki, unit.TypeProjects, unit.TypePackages:
fallthrough
default:
r.Config = new(UnitConfig)
@@ -218,6 +257,11 @@ func (r *RepoUnit) ExternalTrackerConfig() *ExternalTrackerConfig {
return r.Config.(*ExternalTrackerConfig)
}

// ActionsConfig returns config for unit.ActionsConfig
func (r *RepoUnit) ActionsConfig() *ActionsConfig {
return r.Config.(*ActionsConfig)
}

func getUnitsByRepoID(ctx context.Context, repoID int64) (units []*RepoUnit, err error) {
var tmpUnits []*RepoUnit
if err := db.GetEngine(ctx).Where("repo_id = ?", repoID).Find(&tmpUnits); err != nil {

+ 30
- 0
models/repo/repo_unit_test.go Visa fil

@@ -0,0 +1,30 @@
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT

package repo

import (
"testing"

"github.com/stretchr/testify/assert"
)

func TestActionsConfig(t *testing.T) {
cfg := &ActionsConfig{}
cfg.DisableWorkflow("test1.yaml")
assert.EqualValues(t, []string{"test1.yaml"}, cfg.DisabledWorkflows)

cfg.DisableWorkflow("test1.yaml")
assert.EqualValues(t, []string{"test1.yaml"}, cfg.DisabledWorkflows)

cfg.EnableWorkflow("test1.yaml")
assert.EqualValues(t, []string{}, cfg.DisabledWorkflows)

cfg.EnableWorkflow("test1.yaml")
assert.EqualValues(t, []string{}, cfg.DisabledWorkflows)

cfg.DisableWorkflow("test1.yaml")
cfg.DisableWorkflow("test2.yaml")
cfg.DisableWorkflow("test3.yaml")
assert.EqualValues(t, "test1.yaml,test2.yaml,test3.yaml", cfg.ToString())
}

+ 5
- 0
options/locale/locale_en-US.ini Visa fil

@@ -3491,6 +3491,11 @@ runs.status_no_select = All status
runs.no_results = No results matched.
runs.no_runs = The workflow has no runs yet.

workflow.disable = Disable Workflow
workflow.disable_success = Workflow '%s' disabled successfully.
workflow.enable = Enable Workflow
workflow.enable_success = Workflow '%s' enabled successfully.

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

variables = Variables

+ 9
- 0
routers/web/repo/actions/actions.go Visa fil

@@ -137,6 +137,15 @@ func List(ctx *context.Context) {
actorID := ctx.FormInt64("actor")
status := ctx.FormInt("status")
ctx.Data["CurWorkflow"] = workflow

actionsConfig := ctx.Repo.Repository.MustGetUnit(ctx, unit.TypeActions).ActionsConfig()
ctx.Data["ActionsConfig"] = actionsConfig

if len(workflow) > 0 && ctx.Repo.IsAdmin() {
ctx.Data["AllowDisableOrEnableWorkflow"] = true
ctx.Data["CurWorkflowDisabled"] = actionsConfig.IsWorkflowDisabled(workflow)
}

// if status or actor query param is not given to frontend href, (href="/<repoLink>/actions")
// they will be 0 by default, which indicates get all status or actors
ctx.Data["CurActor"] = actorID

+ 41
- 0
routers/web/repo/actions/view.go Visa fil

@@ -17,6 +17,7 @@ import (

actions_model "code.gitea.io/gitea/models/actions"
"code.gitea.io/gitea/models/db"
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unit"
"code.gitea.io/gitea/modules/actions"
"code.gitea.io/gitea/modules/base"
@@ -572,3 +573,43 @@ func ArtifactsDownloadView(ctx *context_module.Context) {
}
}
}

func DisableWorkflowFile(ctx *context_module.Context) {
disableOrEnableWorkflowFile(ctx, false)
}

func EnableWorkflowFile(ctx *context_module.Context) {
disableOrEnableWorkflowFile(ctx, true)
}

func disableOrEnableWorkflowFile(ctx *context_module.Context, isEnable bool) {
workflow := ctx.FormString("workflow")
if len(workflow) == 0 {
ctx.ServerError("workflow", nil)
return
}

cfgUnit := ctx.Repo.Repository.MustGetUnit(ctx, unit.TypeActions)
cfg := cfgUnit.ActionsConfig()

if isEnable {
cfg.EnableWorkflow(workflow)
} else {
cfg.DisableWorkflow(workflow)
}

if err := repo_model.UpdateRepoUnit(cfgUnit); err != nil {
ctx.ServerError("UpdateRepoUnit", err)
return
}

if isEnable {
ctx.Flash.Success(ctx.Tr("actions.workflow.enable_success", workflow))
} else {
ctx.Flash.Success(ctx.Tr("actions.workflow.disable_success", workflow))
}

redirectURL := fmt.Sprintf("%s/actions?workflow=%s&actor=%s&status=%s", ctx.Repo.RepoLink, url.QueryEscape(workflow),
url.QueryEscape(ctx.FormString("actor")), url.QueryEscape(ctx.FormString("status")))
ctx.JSONRedirect(redirectURL)
}

+ 2
- 0
routers/web/web.go Visa fil

@@ -1200,6 +1200,8 @@ func registerRoutes(m *web.Route) {

m.Group("/actions", func() {
m.Get("", actions.List)
m.Post("/disable", reqRepoAdmin, actions.DisableWorkflowFile)
m.Post("/enable", reqRepoAdmin, actions.EnableWorkflowFile)

m.Group("/runs/{run}", func() {
m.Combo("").

+ 7
- 0
services/actions/notifier_helper.go Visa fil

@@ -150,7 +150,14 @@ func notify(ctx context.Context, input *notifyInput) error {
if len(workflows) == 0 {
log.Trace("repo %s with commit %s couldn't find workflows", input.Repo.RepoPath(), commit.ID)
} else {
actionsConfig := input.Repo.MustGetUnit(ctx, unit_model.TypeActions).ActionsConfig()

for _, wf := range workflows {
if actionsConfig.IsWorkflowDisabled(wf.EntryName) {
log.Trace("repo %s has disable workflows %s", input.Repo.RepoPath(), wf.EntryName)
continue
}

if wf.TriggerEvent != actions_module.GithubEventPullRequestTarget {
detectedWorkflows = append(detectedWorkflows, wf)
}

+ 18
- 1
templates/repo/actions/list.tmpl Visa fil

@@ -2,6 +2,8 @@
<div class="page-content repository actions">
{{template "repo/header" .}}
<div class="ui container">
{{template "base/alert" .}}

<div class="ui stackable grid">
<div class="four wide column">
<div class="ui fluid vertical menu">
@@ -13,12 +15,16 @@
{{svg "octicon-alert" 16 "text red"}}
</span>
{{end}}

{{if $.ActionsConfig.IsWorkflowDisabled .Entry.Name}}
<div class="ui red label">{{$.locale.Tr "disabled"}}</div>
{{end}}
</a>
{{end}}
</div>
</div>
<div class="twelve wide column content">
<div class="ui secondary filter stackable menu gt-je">
<div class="ui secondary filter menu gt-je gt-df gt-ac">
<!-- Actor -->
<div class="ui{{if not .Actors}} disabled{{end}} dropdown jump item">
<span class="text">{{.locale.Tr "actions.runs.actor"}}</span>
@@ -57,6 +63,17 @@
{{end}}
</div>
</div>

{{if .AllowDisableOrEnableWorkflow}}
<button class="ui jump dropdown btn interact-bg gt-p-3">
{{svg "octicon-kebab-horizontal"}}
<div class="menu">
<a class="item link-action" data-url="{{$.Link}}/{{if .CurWorkflowDisabled}}enable{{else}}disable{{end}}?workflow={{$.CurWorkflow}}&actor={{.CurActor}}&status={{$.CurStatus}}">
{{if .CurWorkflowDisabled}}{{.locale.Tr "actions.workflow.enable"}}{{else}}{{.locale.Tr "actions.workflow.disable"}}{{end}}
</a>
</div>
</button>
{{end}}
</div>
{{template "repo/actions/runs_list" .}}
</div>

+ 17
- 0
web_src/css/base.css Visa fil

@@ -653,6 +653,18 @@ a.label,
color: var(--color-text);
}

/* replace item margin on secondary menu items with gap and remove both the
negative margins on the menu as well as margin on the items */
.ui.secondary.menu {
margin-left: 0;
margin-right: 0;
gap: .35714286em;
}
.ui.secondary.menu .item {
margin-left: 0;
margin-right: 0;
}

.ui.secondary.menu .dropdown.item:hover,
.ui.secondary.menu a.item:hover {
color: var(--color-text);
@@ -670,6 +682,11 @@ a.label,
padding-right: 0.85714286em;
}

/* remove the menu clearfix so that it won't add undesired gaps when using "gap" */
.ui.menu::after {
content: normal;
}

.ui.menu .dropdown.item .menu {
background: var(--color-body);
}

Laddar…
Avbryt
Spara