Add various GitHub environment variables (#604)

* define GITHUB_ACTION_PATH #603

* Add more environment variables

* Add job name

Note: the job name gets a suffix for matrix builds, but this is not part of the env var

* fix: remove unnecessary variables

* feat: add `RepositoryOwner`

credit: @KnisterPeter

* feat: add test for `getGithubContext()`

Co-authored-by: Ryan (hackercat) <me@hackerc.at>
This commit is contained in:
Josh Soref 2021-05-06 16:02:29 -04:00 committed by GitHub
parent a07cb440c2
commit a144e71a1b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 132 additions and 41 deletions

View file

@ -33,6 +33,7 @@ type RunContext struct {
ExprEval ExpressionEvaluator ExprEval ExpressionEvaluator
JobContainer container.Container JobContainer container.Container
OutputMappings map[MappableOutput]MappableOutput OutputMappings map[MappableOutput]MappableOutput
JobName string
} }
type MappableOutput struct { type MappableOutput struct {
@ -454,50 +455,67 @@ func (rc *RunContext) getStepsContext() map[string]*stepResult {
} }
type githubContext struct { type githubContext struct {
Event map[string]interface{} `json:"event"` Event map[string]interface{} `json:"event"`
EventPath string `json:"event_path"` EventPath string `json:"event_path"`
Workflow string `json:"workflow"` Workflow string `json:"workflow"`
RunID string `json:"run_id"` RunID string `json:"run_id"`
RunNumber string `json:"run_number"` RunNumber string `json:"run_number"`
Actor string `json:"actor"` Actor string `json:"actor"`
Repository string `json:"repository"` Repository string `json:"repository"`
EventName string `json:"event_name"` EventName string `json:"event_name"`
Sha string `json:"sha"` Sha string `json:"sha"`
Ref string `json:"ref"` Ref string `json:"ref"`
HeadRef string `json:"head_ref"` HeadRef string `json:"head_ref"`
BaseRef string `json:"base_ref"` BaseRef string `json:"base_ref"`
Token string `json:"token"` Token string `json:"token"`
Workspace string `json:"workspace"` Workspace string `json:"workspace"`
Action string `json:"action"` 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"`
} }
func (rc *RunContext) getGithubContext() *githubContext { func (rc *RunContext) getGithubContext() *githubContext {
token, ok := rc.Config.Secrets["GITHUB_TOKEN"]
if !ok {
token = os.Getenv("GITHUB_TOKEN")
}
runID := rc.Config.Env["GITHUB_RUN_ID"]
if runID == "" {
runID = "1"
}
runNumber := rc.Config.Env["GITHUB_RUN_NUMBER"]
if runNumber == "" {
runNumber = "1"
}
ghc := &githubContext{ ghc := &githubContext{
Event: make(map[string]interface{}), Event: make(map[string]interface{}),
EventPath: "/tmp/workflow/event.json", EventPath: "/tmp/workflow/event.json",
Workflow: rc.Run.Workflow.Name, Workflow: rc.Run.Workflow.Name,
RunID: runID, RunID: rc.Config.Env["GITHUB_RUN_ID"],
RunNumber: runNumber, RunNumber: rc.Config.Env["GITHUB_RUN_NUMBER"],
Actor: rc.Config.Actor, Actor: rc.Config.Actor,
EventName: rc.Config.EventName, EventName: rc.Config.EventName,
Token: token, Workspace: rc.Config.ContainerWorkdir(),
Workspace: rc.Config.ContainerWorkdir(), Action: rc.CurrentStep,
Action: rc.CurrentStep, Token: rc.Config.Secrets["GITHUB_TOKEN"],
ActionPath: rc.Config.Env["GITHUB_ACTION_PATH"],
ActionRef: rc.Config.Env["RUNNER_ACTION_REF"],
ActionRepository: rc.Config.Env["RUNNER_ACTION_REPOSITORY"],
RepositoryOwner: rc.Config.Env["GITHUB_REPOSITORY_OWNER"],
RetentionDays: rc.Config.Env["GITHUB_RETENTION_DAYS"],
RunnerPerflog: rc.Config.Env["RUNNER_PERFLOG"],
RunnerTrackingID: rc.Config.Env["RUNNER_TRACKING_ID"],
}
if ghc.RunID == "" {
ghc.RunID = "1"
}
if ghc.RunNumber == "" {
ghc.RunNumber = "1"
}
if ghc.RetentionDays == "" {
ghc.RetentionDays = "0"
}
if ghc.RunnerPerflog == "" {
ghc.RunnerPerflog = "/dev/null"
} }
// Backwards compatibility for configs that require // Backwards compatibility for configs that require
@ -512,6 +530,9 @@ func (rc *RunContext) getGithubContext() *githubContext {
log.Warningf("unable to get git repo: %v", err) log.Warningf("unable to get git repo: %v", err)
} else { } else {
ghc.Repository = repo ghc.Repository = repo
if ghc.RepositoryOwner == "" {
ghc.RepositoryOwner = strings.Split(repo, "/")[0]
}
} }
_, sha, err := common.FindGitRevision(repoPath) _, sha, err := common.FindGitRevision(repoPath)
@ -637,6 +658,9 @@ func (rc *RunContext) withGithubEnv(env map[string]string) map[string]string {
env["GITHUB_RUN_ID"] = github.RunID env["GITHUB_RUN_ID"] = github.RunID
env["GITHUB_RUN_NUMBER"] = github.RunNumber env["GITHUB_RUN_NUMBER"] = github.RunNumber
env["GITHUB_ACTION"] = github.Action env["GITHUB_ACTION"] = github.Action
if github.ActionPath != "" {
env["GITHUB_ACTION_PATH"] = github.ActionPath
}
env["GITHUB_ACTIONS"] = "true" env["GITHUB_ACTIONS"] = "true"
env["GITHUB_ACTOR"] = github.Actor env["GITHUB_ACTOR"] = github.Actor
env["GITHUB_REPOSITORY"] = github.Repository env["GITHUB_REPOSITORY"] = github.Repository
@ -649,6 +673,15 @@ func (rc *RunContext) withGithubEnv(env map[string]string) map[string]string {
env["GITHUB_SERVER_URL"] = "https://github.com" env["GITHUB_SERVER_URL"] = "https://github.com"
env["GITHUB_API_URL"] = "https://api.github.com" env["GITHUB_API_URL"] = "https://api.github.com"
env["GITHUB_GRAPHQL_URL"] = "https://api.github.com/graphql" env["GITHUB_GRAPHQL_URL"] = "https://api.github.com/graphql"
env["GITHUB_ACTION_REF"] = github.ActionRef
env["GITHUB_ACTION_REPOSITORY"] = github.ActionRepository
env["GITHUB_BASE_REF"] = github.BaseRef
env["GITHUB_HEAD_REF"] = github.HeadRef
env["GITHUB_JOB"] = rc.JobName
env["GITHUB_REPOSITORY_OWNER"] = github.RepositoryOwner
env["GITHUB_RETENTION_DAYS"] = github.RetentionDays
env["RUNNER_PERFLOG"] = github.RunnerPerflog
env["RUNNER_TRACKING_ID"] = github.RunnerTrackingID
if rc.Config.GitHubInstance != "github.com" { if rc.Config.GitHubInstance != "github.com" {
env["GITHUB_SERVER_URL"] = fmt.Sprintf("https://%s", rc.Config.GitHubInstance) env["GITHUB_SERVER_URL"] = fmt.Sprintf("https://%s", rc.Config.GitHubInstance)
env["GITHUB_API_URL"] = fmt.Sprintf("https://%s/api/v3", rc.Config.GitHubInstance) env["GITHUB_API_URL"] = fmt.Sprintf("https://%s/api/v3", rc.Config.GitHubInstance)

View file

@ -11,7 +11,9 @@ import (
"github.com/nektos/act/pkg/model" "github.com/nektos/act/pkg/model"
a "github.com/stretchr/testify/assert" a "github.com/stretchr/testify/assert"
"gotest.tools/v3/assert"
log "github.com/sirupsen/logrus"
"github.com/sirupsen/logrus/hooks/test" "github.com/sirupsen/logrus/hooks/test"
) )
@ -277,3 +279,44 @@ func TestRunContext_GetBindsAndMounts(t *testing.T) {
} }
} }
} }
func TestGetGitHubContext(t *testing.T) {
log.SetLevel(log.DebugLevel)
cwd, err := os.Getwd()
assert.NilError(t, err)
rc := &RunContext{
Config: &Config{
EventName: "push",
Workdir: cwd,
},
Run: &model.Run{
Workflow: &model.Workflow{
Name: "GitHubContextTest",
},
},
Name: "GitHubContextTest",
CurrentStep: "step",
Matrix: map[string]interface{}{},
Env: map[string]string{},
ExtraPath: []string{},
StepResults: map[string]*stepResult{},
OutputMappings: map[MappableOutput]MappableOutput{},
}
ghc := rc.getGithubContext()
log.Debugf("%v", ghc)
assert.Equal(t, ghc.RunID, "1")
assert.Equal(t, ghc.Workspace, cwd)
assert.Equal(t, ghc.RunNumber, "1")
assert.Equal(t, ghc.RetentionDays, "0")
assert.Equal(t, ghc.Actor, "nektos/act")
assert.Equal(t, ghc.Repository, "nektos/act")
assert.Equal(t, ghc.RepositoryOwner, "nektos")
assert.Equal(t, ghc.RunnerPerflog, "/dev/null")
assert.Equal(t, ghc.EventPath, "/tmp/workflow/event.json")
assert.Equal(t, ghc.Token, rc.Config.Secrets["GITHUB_TOKEN"])
}

View file

@ -116,6 +116,7 @@ func (runner *runnerImpl) NewPlanExecutor(plan *model.Plan) common.Executor {
for i, matrix := range matrixes { for i, matrix := range matrixes {
rc := runner.newRunContext(run, matrix) rc := runner.newRunContext(run, matrix)
rc.JobName = rc.Name
if len(matrixes) > 1 { if len(matrixes) > 1 {
rc.Name = fmt.Sprintf("%s-%d", rc.Name, i+1) rc.Name = fmt.Sprintf("%s-%d", rc.Name, i+1)
} }

View file

@ -557,7 +557,12 @@ func (sc *StepContext) execAsComposite(ctx context.Context, step *model.Step, _
} }
} }
stepClone.Run = strings.ReplaceAll(stepClone.Run, "${{ github.action_path }}", filepath.Join(containerActionDir, actionName)) if stepClone.Env == nil {
stepClone.Env = make(map[string]string)
}
actionPath := filepath.Join(containerActionDir, actionName)
stepClone.Env["GITHUB_ACTION_PATH"] = actionPath
stepClone.Run = strings.ReplaceAll(stepClone.Run, "${{ github.action_path }}", actionPath)
stepContext := StepContext{ stepContext := StepContext{
RunContext: rcClone, RunContext: rcClone,

View file

@ -41,6 +41,15 @@ runs:
fi fi
shell: bash shell: bash
- run: |
if [ -z "$GITHUB_ACTION_PATH" ]; then
exit 1
fi
if [ -z "${{ github.action_path }}" ]; then
exit 2
fi
shell: bash
# Let's send up an output to test # Let's send up an output to test
- run: echo "::set-output name=test_output::test_output_value" - run: echo "::set-output name=test_output::test_output_value"
shell: bash shell: bash