diff --git a/go.mod b/go.mod index f0b99e8..7efe23e 100644 --- a/go.mod +++ b/go.mod @@ -13,6 +13,7 @@ require ( github.com/gobwas/glob v0.2.3 github.com/json-iterator/go v1.1.12 github.com/klauspost/cpuid/v2 v2.2.6 + github.com/nektos/act v0.2.52 github.com/shurcooL/vfsgen v0.0.0-20230704071429-0000e147ea92 github.com/urfave/cli/v2 v2.25.7 golang.org/x/net v0.18.0 @@ -186,7 +187,6 @@ require ( github.com/mrjones/oauth v0.0.0-20190623134757-126b35219450 // indirect github.com/mschoch/smat v0.2.0 // indirect github.com/msteinert/pam v1.2.0 // indirect - github.com/nektos/act v0.2.52 // indirect github.com/niklasfasching/go-org v1.7.0 // indirect github.com/nwaples/rardecode v1.1.3 // indirect github.com/nxadm/tail v1.4.8 // indirect diff --git a/main.go b/main.go index 1e74a9b..7e5d252 100644 --- a/main.go +++ b/main.go @@ -22,7 +22,7 @@ import ( ) var ( - Version = "v2.2, by v1.21.0 " + Version = "v2.3, by v1.21.0 " Tags = "" MakeVersion = "" ) diff --git a/routers/hat/hat.go b/routers/hat/hat.go index fa3eecc..e62506b 100644 --- a/routers/hat/hat.go +++ b/routers/hat/hat.go @@ -131,6 +131,7 @@ func Routers() *web.Route { m.Post("/runs/{run}/jobs/{job}/rerun", reqRepoWriter(unit_model.TypeActions), actions.Rerun) m.Get("/runs/{run}/jobs/{job}/logs", actions.Logs) m.Post("/runs/{run}/rerun", reqRepoWriter(unit_model.TypeActions), actions.Rerun) + m.Post("/runs", context.ReferencesGitRepo(), reqRepoWriter(unit_model.TypeActions), actions.Run) }, reqRepoReader(unit_model.TypeActions)) m.Post("/transfer", reqOwner(), bind(gitea_api.TransferRepoOption{}), repo.Transfer) m.Get("/branch_name_set", context.ReferencesGitRepo(), repo.BranchNameSet) diff --git a/routers/hat/repo/actions/actions.go b/routers/hat/repo/actions/actions.go index 337d851..32bf949 100644 --- a/routers/hat/repo/actions/actions.go +++ b/routers/hat/repo/actions/actions.go @@ -16,20 +16,116 @@ import ( "code.gitea.io/gitea/models/unit" "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/actions" + actions_module "code.gitea.io/gitea/modules/actions" "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/container" - hat_actions_model "code.gitlink.org.cn/Gitlink/gitea_hat.git/models/actions" - "code.gitea.io/gitea/modules/context" + "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/web/repo" actions_service "code.gitea.io/gitea/services/actions" "code.gitea.io/gitea/services/convert" + hat_actions_model "code.gitlink.org.cn/Gitlink/gitea_hat.git/models/actions" + jobparser "github.com/nektos/act/pkg/jobparser" "github.com/nektos/act/pkg/model" "xorm.io/builder" ) +func Run(ctx *context.APIContext) { + workflow := ctx.FormString("workflow") + ref := ctx.FormString("ref") + + if ref == "" { + ref = ctx.Repo.Repository.DefaultBranch + } + + commit, err := ctx.Repo.GitRepo.GetCommit(ref) + if err != nil { + ctx.Error(http.StatusInternalServerError, "GetCommit", err.Error()) + return + } + + entries, err := ListWorkflowsByWorkflow(commit, workflow) + if err != nil { + ctx.Error(http.StatusInternalServerError, "ListWorkflowsByWorkflow", err.Error()) + return + } + + workflows := make([]*actions_module.DetectedWorkflow, 0, len(entries)) + for _, entry := range entries { + content, err := actions_module.GetContentFromEntry(entry) + if err != nil { + ctx.Error(http.StatusInternalServerError, "GetContentFromEntry", err.Error()) + return + } + dwf := &actions_module.DetectedWorkflow{ + EntryName: entry.Name(), + Content: content, + } + workflows = append(workflows, dwf) + } + + for _, dwf := range workflows { + run := &actions_model.ActionRun{ + Title: strings.SplitN(commit.CommitMessage, "\n", 2)[0], + RepoID: ctx.Repo.Repository.ID, + OwnerID: ctx.Repo.Repository.OwnerID, + WorkflowID: dwf.EntryName, + TriggerUserID: ctx.Doer.ID, + Ref: ref, + CommitSHA: commit.ID.String(), + Status: actions_model.StatusWaiting, + } + + jobs, err := jobparser.Parse(dwf.Content) + if err != nil { + ctx.Error(http.StatusInternalServerError, "jobparser.Parse", err.Error()) + return + } + + if err := actions_model.InsertRun(ctx, run, jobs); err != nil { + ctx.Error(http.StatusInternalServerError, "InsertRun", err.Error()) + return + } + + alljobs, _, err := actions_model.FindRunJobs(ctx, actions_model.FindRunJobOptions{RunID: run.ID}) + if err != nil { + ctx.Error(http.StatusInternalServerError, "FindRunJobs", err.Error()) + return + } + actions_service.CreateCommitStatus(ctx, alljobs...) + } + + ctx.Status(http.StatusNoContent) +} + +func ListWorkflowsByWorkflow(commit *git.Commit, workflow string) (git.Entries, error) { + tree, err := commit.SubTree(".gitea/workflows") + if _, ok := err.(git.ErrNotExist); ok { + tree, err = commit.SubTree(".github/workflows") + } + if _, ok := err.(git.ErrNotExist); ok { + return nil, nil + } + if err != nil { + return nil, err + } + + entries, err := tree.ListEntriesRecursiveFast() + if err != nil { + return nil, err + } + + ret := make(git.Entries, 0, len(entries)) + for _, entry := range entries { + if workflow == entry.Name() && (strings.HasSuffix(entry.Name(), ".yml") || strings.HasSuffix(entry.Name(), ".yaml")) { + ret = append(ret, entry) + } + } + return ret, nil +} + type Workflow struct { Name string ErrMsg string