diff options
author | Daniel Baumann <daniel@debian.org> | 2024-10-20 23:07:42 +0200 |
---|---|---|
committer | Daniel Baumann <daniel@debian.org> | 2024-11-09 15:38:42 +0100 |
commit | 714c83b2736d7e308bc33c49057952490eb98be2 (patch) | |
tree | 1d9ba7035798368569cd49056f4d596efc908cd8 /pkg/model/github_context.go | |
parent | Initial commit. (diff) | |
download | forgejo-act-debian.tar.xz forgejo-act-debian.zip |
Adding upstream version 1.21.4.HEADupstream/1.21.4upstreamdebian
Signed-off-by: Daniel Baumann <daniel@debian.org>
Diffstat (limited to 'pkg/model/github_context.go')
-rw-r--r-- | pkg/model/github_context.go | 213 |
1 files changed, 213 insertions, 0 deletions
diff --git a/pkg/model/github_context.go b/pkg/model/github_context.go new file mode 100644 index 0000000..71221a5 --- /dev/null +++ b/pkg/model/github_context.go @@ -0,0 +1,213 @@ +package model + +import ( + "context" + "fmt" + "strings" + + "github.com/nektos/act/pkg/common" + "github.com/nektos/act/pkg/common/git" +) + +type GithubContext struct { + Event map[string]interface{} `json:"event"` + EventPath string `json:"event_path"` + Workflow string `json:"workflow"` + RunID string `json:"run_id"` + RunNumber string `json:"run_number"` + Actor string `json:"actor"` + Repository string `json:"repository"` + EventName string `json:"event_name"` + Sha string `json:"sha"` + Ref string `json:"ref"` + RefName string `json:"ref_name"` + RefType string `json:"ref_type"` + HeadRef string `json:"head_ref"` + BaseRef string `json:"base_ref"` + Token string `json:"token"` + Workspace string `json:"workspace"` + Action string `json:"action"` + ActionPath string `json:"action_path"` + ActionRef string `json:"action_ref"` + ActionRepository string `json:"action_repository"` + Job string `json:"job"` + JobName string `json:"job_name"` + RepositoryOwner string `json:"repository_owner"` + RetentionDays string `json:"retention_days"` + RunnerPerflog string `json:"runner_perflog"` + RunnerTrackingID string `json:"runner_tracking_id"` + ServerURL string `json:"server_url"` + APIURL string `json:"api_url"` + GraphQLURL string `json:"graphql_url"` +} + +func asString(v interface{}) string { + if v == nil { + return "" + } else if s, ok := v.(string); ok { + return s + } + return "" +} + +func nestedMapLookup(m map[string]interface{}, ks ...string) (rval interface{}) { + var ok bool + + if len(ks) == 0 { // degenerate input + return nil + } + if rval, ok = m[ks[0]]; !ok { + return nil + } else if len(ks) == 1 { // we've reached the final key + return rval + } else if m, ok = rval.(map[string]interface{}); !ok { + return nil + } else { // 1+ more keys + return nestedMapLookup(m, ks[1:]...) + } +} + +func withDefaultBranch(ctx context.Context, b string, event map[string]interface{}) map[string]interface{} { + repoI, ok := event["repository"] + if !ok { + repoI = make(map[string]interface{}) + } + + repo, ok := repoI.(map[string]interface{}) + if !ok { + common.Logger(ctx).Warnf("unable to set default branch to %v", b) + return event + } + + // if the branch is already there return with no changes + if _, ok = repo["default_branch"]; ok { + return event + } + + repo["default_branch"] = b + event["repository"] = repo + + return event +} + +var findGitRef = git.FindGitRef +var findGitRevision = git.FindGitRevision + +func (ghc *GithubContext) SetRef(ctx context.Context, defaultBranch string, repoPath string) { + logger := common.Logger(ctx) + + // https://docs.github.com/en/actions/learn-github-actions/events-that-trigger-workflows + // https://docs.github.com/en/developers/webhooks-and-events/webhooks/webhook-events-and-payloads + switch ghc.EventName { + case "pull_request_target": + ghc.Ref = fmt.Sprintf("refs/heads/%s", ghc.BaseRef) + case "pull_request", "pull_request_review", "pull_request_review_comment": + ghc.Ref = fmt.Sprintf("refs/pull/%.0f/merge", ghc.Event["number"]) + case "deployment", "deployment_status": + ghc.Ref = asString(nestedMapLookup(ghc.Event, "deployment", "ref")) + case "release": + ghc.Ref = fmt.Sprintf("refs/tags/%s", asString(nestedMapLookup(ghc.Event, "release", "tag_name"))) + case "push", "create", "workflow_dispatch": + ghc.Ref = asString(ghc.Event["ref"]) + default: + defaultBranch := asString(nestedMapLookup(ghc.Event, "repository", "default_branch")) + if defaultBranch != "" { + ghc.Ref = fmt.Sprintf("refs/heads/%s", defaultBranch) + } + } + + if ghc.Ref == "" { + ref, err := findGitRef(ctx, repoPath) + if err != nil { + logger.Warningf("unable to get git ref: %v", err) + } else { + logger.Debugf("using github ref: %s", ref) + ghc.Ref = ref + } + + // set the branch in the event data + if defaultBranch != "" { + ghc.Event = withDefaultBranch(ctx, defaultBranch, ghc.Event) + } else { + ghc.Event = withDefaultBranch(ctx, "master", ghc.Event) + } + + if ghc.Ref == "" { + ghc.Ref = fmt.Sprintf("refs/heads/%s", asString(nestedMapLookup(ghc.Event, "repository", "default_branch"))) + } + } +} + +func (ghc *GithubContext) SetSha(ctx context.Context, repoPath string) { + logger := common.Logger(ctx) + + // https://docs.github.com/en/actions/learn-github-actions/events-that-trigger-workflows + // https://docs.github.com/en/developers/webhooks-and-events/webhooks/webhook-events-and-payloads + switch ghc.EventName { + case "pull_request_target": + ghc.Sha = asString(nestedMapLookup(ghc.Event, "pull_request", "base", "sha")) + case "deployment", "deployment_status": + ghc.Sha = asString(nestedMapLookup(ghc.Event, "deployment", "sha")) + case "push", "create", "workflow_dispatch": + if deleted, ok := ghc.Event["deleted"].(bool); ok && !deleted { + ghc.Sha = asString(ghc.Event["after"]) + } + } + + if ghc.Sha == "" { + _, sha, err := findGitRevision(ctx, repoPath) + if err != nil { + logger.Warningf("unable to get git revision: %v", err) + } else { + ghc.Sha = sha + } + } +} + +func (ghc *GithubContext) SetRepositoryAndOwner(ctx context.Context, githubInstance string, remoteName string, repoPath string) { + if ghc.Repository == "" { + repo, err := git.FindGithubRepo(ctx, repoPath, githubInstance, remoteName) + if err != nil { + common.Logger(ctx).Warningf("unable to get git repo (githubInstance: %v; remoteName: %v, repoPath: %v): %v", githubInstance, remoteName, repoPath, err) + return + } + ghc.Repository = repo + } + ghc.RepositoryOwner = strings.Split(ghc.Repository, "/")[0] +} + +func (ghc *GithubContext) SetRefTypeAndName() { + var refType, refName string + + // https://docs.github.com/en/actions/learn-github-actions/environment-variables + if strings.HasPrefix(ghc.Ref, "refs/tags/") { + refType = "tag" + refName = ghc.Ref[len("refs/tags/"):] + } else if strings.HasPrefix(ghc.Ref, "refs/heads/") { + refType = "branch" + refName = ghc.Ref[len("refs/heads/"):] + } else if strings.HasPrefix(ghc.Ref, "refs/pull/") { + refType = "" + refName = ghc.Ref[len("refs/pull/"):] + } + + if ghc.RefType == "" { + ghc.RefType = refType + } + + if ghc.RefName == "" { + ghc.RefName = refName + } +} + +func (ghc *GithubContext) SetBaseAndHeadRef() { + if ghc.EventName == "pull_request" || ghc.EventName == "pull_request_target" { + if ghc.BaseRef == "" { + ghc.BaseRef = asString(nestedMapLookup(ghc.Event, "pull_request", "base", "ref")) + } + + if ghc.HeadRef == "" { + ghc.HeadRef = asString(nestedMapLookup(ghc.Event, "pull_request", "head", "ref")) + } + } +} |