Skip to content

Commit

Permalink
Combined all RequestActions implementation and merge upstream
Browse files Browse the repository at this point in the history
Update all formating issues

Signed-off-by: Alex Lau(AvengerMoJo) <[email protected]>
  • Loading branch information
AvengerMoJo committed Aug 23, 2024
1 parent e0c27e5 commit c0d50fd
Show file tree
Hide file tree
Showing 19 changed files with 695 additions and 15 deletions.
82 changes: 82 additions & 0 deletions models/actions/require_action.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
// Copyright 2024 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT

// WIP RequireAction

package actions

import (
"context"

"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/modules/timeutil"

"xorm.io/builder"
)

type RequireAction struct {
ID int64 `xorm:"pk autoincr"`
OrgID int64 `xorm:"INDEX"`
RepoName string `xorm:"VARCHAR(255)"`
WorkflowName string `xorm:"VARCHAR(255) UNIQUE(require_action) NOT NULL"`
CreatedUnix timeutil.TimeStamp `xorm:"created NOT NULL"`
UpdatedUnix timeutil.TimeStamp `xorm:"updated"`
}

type GlobalWorkflow struct {
RepoName string
Filename string
}

func init() {
db.RegisterModel(new(RequireAction))
}

type FindRequireActionOptions struct {
db.ListOptions
RequireActionID int64
OrgID int64
RepoName string
}

func (opts FindRequireActionOptions) ToConds() builder.Cond {
cond := builder.NewCond()
if opts.OrgID > 0 {
cond = cond.And(builder.Eq{"org_id": opts.OrgID})
}
if opts.RequireActionID > 0 {
cond = cond.And(builder.Eq{"id": opts.RequireActionID})
}
if opts.RepoName != "" {
cond = cond.And(builder.Eq{"repo_name": opts.RepoName})
}
return cond
}

// LoadAttributes loads the attributes of the require action
func (r *RequireAction) LoadAttributes(ctx context.Context) error {
// place holder for now.
return nil
}

// if the workflow is removable
func (r *RequireAction) Removable(orgID int64) bool {
// everyone can remove for now
return r.OrgID == orgID
}

func AddRequireAction(ctx context.Context, orgID int64, repoName, workflowName string) (*RequireAction, error) {
ra := &RequireAction{
OrgID: orgID,
RepoName: repoName,
WorkflowName: workflowName,
}
return ra, db.Insert(ctx, ra)
}

func DeleteRequireAction(ctx context.Context, requireActionID int64) error {
if _, err := db.DeleteByID[RequireAction](ctx, requireActionID); err != nil {
return err
}
return nil
}
19 changes: 18 additions & 1 deletion models/repo/repo_unit.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,21 +169,34 @@ func (cfg *PullRequestsConfig) GetDefaultMergeStyle() MergeStyle {
}

type ActionsConfig struct {
DisabledWorkflows []string
DisabledWorkflows []string
EnabledGlobalWorkflows []string
}

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

func (cfg *ActionsConfig) EnableGlobalWorkflow(file string) {
cfg.EnabledGlobalWorkflows = append(cfg.EnabledGlobalWorkflows, file)
}

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

func (cfg *ActionsConfig) GetGlobalWorkflow() []string {
return cfg.EnabledGlobalWorkflows
}

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

func (cfg *ActionsConfig) IsGlobalWorkflowEnabled(file string) bool {
return slices.Contains(cfg.EnabledGlobalWorkflows, file)
}

func (cfg *ActionsConfig) DisableWorkflow(file string) {
for _, workflow := range cfg.DisabledWorkflows {
if file == workflow {
Expand All @@ -194,6 +207,10 @@ func (cfg *ActionsConfig) DisableWorkflow(file string) {
cfg.DisabledWorkflows = append(cfg.DisabledWorkflows, file)
}

func (cfg *ActionsConfig) DisableGlobalWorkflow(file string) {
cfg.EnabledGlobalWorkflows = util.SliceRemoveAll(cfg.EnabledGlobalWorkflows, file)
}

// FromDB fills up a ActionsConfig from serialized format.
func (cfg *ActionsConfig) FromDB(bs []byte) error {
return json.UnmarshalHandleDoubleEncode(bs, &cfg)
Expand Down
42 changes: 42 additions & 0 deletions modules/actions/workflows.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,14 @@ func ListWorkflows(commit *git.Commit) (git.Entries, error) {
return ret, nil
}

/*
func ListGlobalWorkflows() (git.Entries, error) {
tree, err := global.SubTree(".gitea/workflows")
ret := make(git.Entries, 0, len(entries))
return ret, nil
}
*/

func GetContentFromEntry(entry *git.TreeEntry) ([]byte, error) {
f, err := entry.Blob().DataAsync()
if err != nil {
Expand All @@ -95,6 +103,17 @@ func GetEventsFromContent(content []byte) ([]*jobparser.Event, error) {
return events, nil
}

func DetectGlobalWorkflows(
gitRepo *git.Repository,
commit *git.Commit,
triggedEvent webhook_module.HookEventType,
payload api.Payloader,
detectSchedule bool,
entries git.Entries,
) ([]*DetectedWorkflow, []*DetectedWorkflow, error) {
return _DetectWorkflows(gitRepo, commit, triggedEvent, payload, detectSchedule, entries)
}

func DetectWorkflows(
gitRepo *git.Repository,
commit *git.Commit,
Expand All @@ -106,7 +125,17 @@ func DetectWorkflows(
if err != nil {
return nil, nil, err
}
return _DetectWorkflows(gitRepo, commit, triggedEvent, payload, detectSchedule, entries)
}

func _DetectWorkflows(
gitRepo *git.Repository,
commit *git.Commit,
triggedEvent webhook_module.HookEventType,
payload api.Payloader,
detectSchedule bool,
entries git.Entries,
) ([]*DetectedWorkflow, []*DetectedWorkflow, error) {
workflows := make([]*DetectedWorkflow, 0, len(entries))
schedules := make([]*DetectedWorkflow, 0, len(entries))
for _, entry := range entries {
Expand Down Expand Up @@ -146,12 +175,25 @@ func DetectWorkflows(
return workflows, schedules, nil
}

func DetectScheduledGlobalWorkflows(gitRepo *git.Repository, commit *git.Commit, entries git.Entries) ([]*DetectedWorkflow, error) {
return _DetectScheduledWorkflows(gitRepo, commit, entries)
}

func DetectScheduledWorkflows(gitRepo *git.Repository, commit *git.Commit) ([]*DetectedWorkflow, error) {
entries, err := ListWorkflows(commit)
if err != nil {
return nil, err
}
return _DetectScheduledWorkflows(gitRepo, commit, entries)
}

func _DetectScheduledWorkflows(gitRepo *git.Repository, commit *git.Commit, entries git.Entries) ([]*DetectedWorkflow, error) {
if gitRepo != nil {
log.Trace("detect scheduled workflow for gitRepo.Path: %q", gitRepo.Path)
}
if commit != nil {
log.Trace("detect scheduled commit for commit ID: %q", commit.ID)
}
wfs := make([]*DetectedWorkflow, 0, len(entries))
for _, entry := range entries {
content, err := GetContentFromEntry(entry)
Expand Down
28 changes: 28 additions & 0 deletions options/locale/locale_en-US.ini
Original file line number Diff line number Diff line change
Expand Up @@ -3698,6 +3698,27 @@ runs.no_runs = The workflow has no runs yet.
runs.empty_commit_message = (empty commit message)
runs.expire_log_message = Logs have been purged because they were too old.

require_action = Require Action
require_action.require_action_manage_panel = Require Action Management Panel
require_action.enable_global_workflow = How to Enable Global Workflow
require_action.id = ID
require_action.add = Add Global Workflow
require_action.add_require_action = Enable selected Workflow
require_action.new = Create New
require_action.status = Status
require_action.search = Search...
require_action.version = Version
require_action.repo = Repo Name
require_action.workflow = Workflow Filename
require_action.link = Link
require_action.remove = Remove
require_action.none = No Require Action Available.
require_action.creation.failed = Create Global Require Action %s Failed.
require_action.creation.success = Create Global Require Action %s successfully.
require_action.deletion = Delete
require_action.deletion.description = Removing the Global Require Action is permanent and cannot be undone. Continue?
require_action.deletion.success = The Global Require Action has been removed.

workflow.disable = Disable Workflow
workflow.disable_success = Workflow '%s' disabled successfully.
workflow.enable = Enable Workflow
Expand All @@ -3709,6 +3730,13 @@ workflow.run_success = Workflow '%s' run successfully.
workflow.from_ref = Use workflow from
workflow.has_workflow_dispatch = This workflow has a workflow_dispatch event trigger.

workflow.global = Global
workflow.global_disable = Disable Global Require
workflow.global_disable_success = Global Require '%s' disabled successfully.
workflow.global_enable = Enable Global Require
workflow.global_enable_success = Global Require '%s' enabled successfully.
workflow.global_enabled = Global Require is disabled.

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

variables = Variables
Expand Down
14 changes: 14 additions & 0 deletions routers/web/org/setting/require_action.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Copyright 2024 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT

// WIP RequireAction

package setting

import (
"code.gitea.io/gitea/services/context"
)

func RedirectToRepoSetting(ctx *context.Context) {
ctx.Redirect(ctx.Org.OrgLink + "/settings/actions/require_action")
}
50 changes: 48 additions & 2 deletions routers/web/repo/actions/actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/container"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/gitrepo"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
Expand All @@ -38,6 +39,7 @@ const (

type Workflow struct {
Entry git.TreeEntry
Global bool
ErrMsg string
}

Expand Down Expand Up @@ -71,9 +73,19 @@ func List(ctx *context.Context) {

var workflows []Workflow
var curWorkflow *model.Workflow
var globalEntries []*git.TreeEntry
globalWorkflow, err := db.Find[actions_model.RequireAction](ctx, actions_model.FindRequireActionOptions{
OrgID: ctx.Repo.Repository.Owner.ID,
})
if err != nil {
ctx.ServerError("Global Workflow DB find fail", err)
return
}
if empty, err := ctx.Repo.GitRepo.IsEmpty(); err != nil {
ctx.ServerError("IsEmpty", err)
return
if len(globalWorkflow) < 1 {
return
}
} else if !empty {
commit, err := ctx.Repo.GitRepo.GetBranchCommit(ctx.Repo.Repository.DefaultBranch)
if err != nil {
Expand All @@ -85,6 +97,23 @@ func List(ctx *context.Context) {
ctx.ServerError("ListWorkflows", err)
return
}
for _, gEntry := range globalWorkflow {
if gEntry.RepoName == ctx.Repo.Repository.Name {
log.Trace("Same Repo conflict: %s\n", gEntry.RepoName)
continue
}
gRepo, _ := repo_model.GetRepositoryByName(ctx, gEntry.OrgID, gEntry.RepoName)
gGitRepo, _ := gitrepo.OpenRepository(git.DefaultContext, gRepo)
// it may be a hack for now..... not sure any better way to do this
gCommit, _ := gGitRepo.GetBranchCommit(gRepo.DefaultBranch)
gEntries, _ := actions.ListWorkflows(gCommit)
for _, entry := range gEntries {
if gEntry.WorkflowName == entry.Name() {
globalEntries = append(globalEntries, entry)
entries = append(entries, entry)
}
}
}

// Get all runner labels
runners, err := db.Find[actions_model.ActionRunner](ctx, actions_model.FindRunnerOptions{
Expand All @@ -103,7 +132,14 @@ func List(ctx *context.Context) {

workflows = make([]Workflow, 0, len(entries))
for _, entry := range entries {
workflow := Workflow{Entry: *entry}
var workflowIsGlobal bool
workflowIsGlobal = false
for i := range globalEntries {
if globalEntries[i] == entry {
workflowIsGlobal = true
}
}
workflow := Workflow{Entry: *entry, Global: workflowIsGlobal}
content, err := actions.GetContentFromEntry(entry)
if err != nil {
ctx.ServerError("GetContentFromEntry", err)
Expand Down Expand Up @@ -165,6 +201,10 @@ func List(ctx *context.Context) {
page = 1
}

workflow := ctx.FormString("workflow")
isGlobal := false
ctx.Data["CurWorkflow"] = workflow

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

Expand Down Expand Up @@ -205,6 +245,9 @@ func List(ctx *context.Context) {
ctx.Data["Tags"] = tags
}
}
ctx.Data["CurWorkflowDisabled"] = actionsConfig.IsWorkflowDisabled(workflow)
ctx.Data["CurGlobalWorkflowEnable"] = actionsConfig.IsGlobalWorkflowEnabled(workflow)
isGlobal = actionsConfig.IsGlobalWorkflowEnabled(workflow)
}

// if status or actor query param is not given to frontend href, (href="/<repoLink>/actions")
Expand Down Expand Up @@ -261,6 +304,9 @@ func List(ctx *context.Context) {
pager.AddParamString("workflow", workflowID)
pager.AddParamString("actor", fmt.Sprint(actorID))
pager.AddParamString("status", fmt.Sprint(status))
if isGlobal {
pager.AddParamString("global", fmt.Sprint(isGlobal))
}
ctx.Data["Page"] = pager
ctx.Data["HasWorkflowsOrRuns"] = len(workflows) > 0 || len(runs) > 0

Expand Down
Loading

0 comments on commit c0d50fd

Please sign in to comment.