Skip to content

Commit

Permalink
feat: try to read ref and sha from event payload if available
Browse files Browse the repository at this point in the history
With this change `act` will try to populate the `githubContext.ref` and
`githubContext.sha` with values read from the event payload.

Caveats:
- `page_build` should not have a ref
- `status` should not have a ref
- `registry_package` should set the ref to the branch/tag but the
  payload isn't documented
- `workflow_call` should set ref to the same value as its caller but the
  payload isn't documented
- most of the events should set the sha to the last commit on the ref
  but unfortunately the sha is not always included in the payload,
  therefore we use the sha from the local git checkout
  • Loading branch information
ZauberNerd committed Jan 3, 2022
1 parent 4e6cddf commit bd015ab
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 51 deletions.
106 changes: 106 additions & 0 deletions pkg/model/github_context.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
package model

import (
"fmt"

"github.com/nektos/act/pkg/common"
log "github.com/sirupsen/logrus"
)

type GithubContext struct {
Event map[string]interface{} `json:"event"`
EventPath string `json:"event_path"`
Expand All @@ -26,3 +33,102 @@ type GithubContext struct {
RunnerPerflog string `json:"runner_perflog"`
RunnerTrackingID string `json:"runner_tracking_id"`
}

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(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 {
log.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
}

func (ghc *GithubContext) SetRefAndSha(defaultBranch string, repoPath string) {
// 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 = ghc.BaseRef
ghc.Sha = asString(nestedMapLookup(ghc.Event, "pull_request", "base", "sha"))
case "pull_request", "pull_request_review", "pull_request_review_comment":
ghc.Ref = fmt.Sprintf("refs/pull/%s/merge", ghc.Event["number"])
case "deployment", "deployment_status":
ghc.Ref = asString(nestedMapLookup(ghc.Event, "deployment", "ref"))
ghc.Sha = asString(nestedMapLookup(ghc.Event, "deployment", "sha"))
case "release":
ghc.Ref = asString(nestedMapLookup(ghc.Event, "release", "tag_name"))
case "push", "create", "workflow_dispatch":
ghc.Ref = asString(ghc.Event["ref"])
if deleted, ok := ghc.Event["deleted"].(bool); ok && !deleted {
ghc.Sha = asString(ghc.Event["after"])
}
default:
ghc.Ref = asString(nestedMapLookup(ghc.Event, "repository", "default_branch"))
}

if ghc.Ref == "" {
ref, err := common.FindGitRef(repoPath)
if err != nil {
log.Warningf("unable to get git ref: %v", err)
} else {
log.Debugf("using github ref: %s", ref)
ghc.Ref = ref
}

// set the branch in the event data
if defaultBranch != "" {
ghc.Event = withDefaultBranch(defaultBranch, ghc.Event)
} else {
ghc.Event = withDefaultBranch("master", ghc.Event)
}
}

if ghc.Sha == "" {
_, sha, err := common.FindGitRevision(repoPath)
if err != nil {
log.Warningf("unable to get git revision: %v", err)
} else {
ghc.Sha = sha
}
}
}
53 changes: 2 additions & 51 deletions pkg/runner/run_context.go
Original file line number Diff line number Diff line change
Expand Up @@ -564,46 +564,20 @@ func (rc *RunContext) getGithubContext() *model.GithubContext {
}
}

_, sha, err := common.FindGitRevision(repoPath)
if err != nil {
log.Warningf("unable to get git revision: %v", err)
} else {
ghc.Sha = sha
}

if rc.EventJSON != "" {
err = json.Unmarshal([]byte(rc.EventJSON), &ghc.Event)
if err != nil {
log.Errorf("Unable to Unmarshal event '%s': %v", rc.EventJSON, err)
}
}

maybeRef := nestedMapLookup(ghc.Event, ghc.EventName, "ref")
if maybeRef != nil {
log.Debugf("using github ref from event: %s", maybeRef)
ghc.Ref = maybeRef.(string)
} else {
ref, err := common.FindGitRef(repoPath)
if err != nil {
log.Warningf("unable to get git ref: %v", err)
} else {
log.Debugf("using github ref: %s", ref)
ghc.Ref = ref
}

// set the branch in the event data
if rc.Config.DefaultBranch != "" {
ghc.Event = withDefaultBranch(rc.Config.DefaultBranch, ghc.Event)
} else {
ghc.Event = withDefaultBranch("master", ghc.Event)
}
}

if ghc.EventName == "pull_request" {
ghc.BaseRef = asString(nestedMapLookup(ghc.Event, "pull_request", "base", "ref"))
ghc.HeadRef = asString(nestedMapLookup(ghc.Event, "pull_request", "head", "ref"))
}

ghc.SetRefAndSha(rc.Config.DefaultBranch, repoPath)

return ghc
}

Expand Down Expand Up @@ -659,29 +633,6 @@ func nestedMapLookup(m map[string]interface{}, ks ...string) (rval interface{})
}
}

func withDefaultBranch(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 {
log.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
}

func (rc *RunContext) withGithubEnv(env map[string]string) map[string]string {
github := rc.getGithubContext()
env["CI"] = "true"
Expand Down

0 comments on commit bd015ab

Please sign in to comment.