diff --git a/pkg/model/github_context.go b/pkg/model/github_context.go new file mode 100644 index 0000000..199a9c6 --- /dev/null +++ b/pkg/model/github_context.go @@ -0,0 +1,28 @@ +package model + +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"` + 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"` +} diff --git a/pkg/model/job_context.go b/pkg/model/job_context.go new file mode 100644 index 0000000..1d27e49 --- /dev/null +++ b/pkg/model/job_context.go @@ -0,0 +1,12 @@ +package model + +type JobContext struct { + Status string `json:"status"` + Container struct { + ID string `json:"id"` + Network string `json:"network"` + } `json:"container"` + Services map[string]struct { + ID string `json:"id"` + } `json:"services"` +} diff --git a/pkg/model/step_result.go b/pkg/model/step_result.go new file mode 100644 index 0000000..cc44ee6 --- /dev/null +++ b/pkg/model/step_result.go @@ -0,0 +1,43 @@ +package model + +import "fmt" + +type stepStatus int + +const ( + StepStatusSuccess stepStatus = iota + StepStatusFailure +) + +var stepStatusStrings = [...]string{ + "success", + "failure", +} + +func (s stepStatus) MarshalText() ([]byte, error) { + return []byte(s.String()), nil +} + +func (s *stepStatus) UnmarshalText(b []byte) error { + str := string(b) + for i, name := range stepStatusStrings { + if name == str { + *s = stepStatus(i) + return nil + } + } + return fmt.Errorf("invalid step status %q", str) +} + +func (s stepStatus) String() string { + if int(s) >= len(stepStatusStrings) { + return "" + } + return stepStatusStrings[s] +} + +type StepResult struct { + Outputs map[string]string `json:"outputs"` + Conclusion stepStatus `json:"conclusion"` + Outcome stepStatus `json:"outcome"` +} diff --git a/pkg/runner/command_test.go b/pkg/runner/command_test.go index 4d6c548..95e05db 100644 --- a/pkg/runner/command_test.go +++ b/pkg/runner/command_test.go @@ -8,6 +8,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/nektos/act/pkg/common" + "github.com/nektos/act/pkg/model" ) func TestSetEnv(t *testing.T) { @@ -24,11 +25,11 @@ func TestSetOutput(t *testing.T) { a := assert.New(t) ctx := context.Background() rc := new(RunContext) - rc.StepResults = make(map[string]*stepResult) + rc.StepResults = make(map[string]*model.StepResult) handler := rc.commandHandler(ctx) rc.CurrentStep = "my-step" - rc.StepResults[rc.CurrentStep] = &stepResult{ + rc.StepResults[rc.CurrentStep] = &model.StepResult{ Outputs: make(map[string]string), } handler("::set-output name=x::valz\n") diff --git a/pkg/runner/expression_test.go b/pkg/runner/expression_test.go index be9bb46..d343208 100644 --- a/pkg/runner/expression_test.go +++ b/pkg/runner/expression_test.go @@ -47,24 +47,24 @@ func TestEvaluate(t *testing.T) { "os": "Linux", "foo": "bar", }, - StepResults: map[string]*stepResult{ + StepResults: map[string]*model.StepResult{ "idwithnothing": { - Conclusion: stepStatusSuccess, - Outcome: stepStatusFailure, + Conclusion: model.StepStatusSuccess, + Outcome: model.StepStatusFailure, Outputs: map[string]string{ "foowithnothing": "barwithnothing", }, }, "id-with-hyphens": { - Conclusion: stepStatusSuccess, - Outcome: stepStatusFailure, + Conclusion: model.StepStatusSuccess, + Outcome: model.StepStatusFailure, Outputs: map[string]string{ "foo-with-hyphens": "bar-with-hyphens", }, }, "id_with_underscores": { - Conclusion: stepStatusSuccess, - Outcome: stepStatusFailure, + Conclusion: model.StepStatusSuccess, + Outcome: model.StepStatusFailure, Outputs: map[string]string{ "foo_with_underscores": "bar_with_underscores", }, @@ -232,6 +232,7 @@ func updateTestExpressionWorkflow(t *testing.T, tables []struct { envs += fmt.Sprintf(" %s: %s\n", k, rc.Env[k]) } + // editorconfig-checker-disable workflow := fmt.Sprintf(` name: "Test how expressions are handled on GitHub" on: push @@ -244,6 +245,7 @@ jobs: runs-on: ubuntu-latest steps: `, envs) + // editorconfig-checker-enable for _, table := range tables { expressionPattern = regexp.MustCompile(`\${{\s*(.+?)\s*}}`) diff --git a/pkg/runner/run_context.go b/pkg/runner/run_context.go index fb9ae3e..63afd58 100644 --- a/pkg/runner/run_context.go +++ b/pkg/runner/run_context.go @@ -35,7 +35,7 @@ type RunContext struct { Env map[string]string ExtraPath []string CurrentStep string - StepResults map[string]*stepResult + StepResults map[string]*model.StepResult ExprEval ExpressionEvaluator JobContainer container.Container OutputMappings map[MappableOutput]MappableOutput @@ -53,7 +53,7 @@ func (rc *RunContext) Clone() *RunContext { clone.CurrentStep = "" clone.Composite = nil clone.Inputs = nil - clone.StepResults = make(map[string]*stepResult) + clone.StepResults = make(map[string]*model.StepResult) clone.Parent = rc return &clone } @@ -67,46 +67,6 @@ func (rc *RunContext) String() string { return fmt.Sprintf("%s/%s", rc.Run.Workflow.Name, rc.Name) } -type stepStatus int - -const ( - stepStatusSuccess stepStatus = iota - stepStatusFailure -) - -var stepStatusStrings = [...]string{ - "success", - "failure", -} - -func (s stepStatus) MarshalText() ([]byte, error) { - return []byte(s.String()), nil -} - -func (s *stepStatus) UnmarshalText(b []byte) error { - str := string(b) - for i, name := range stepStatusStrings { - if name == str { - *s = stepStatus(i) - return nil - } - } - return fmt.Errorf("invalid step status %q", str) -} - -func (s stepStatus) String() string { - if int(s) >= len(stepStatusStrings) { - return "" - } - return stepStatusStrings[s] -} - -type stepResult struct { - Outputs map[string]string `json:"outputs"` - Conclusion stepStatus `json:"conclusion"` - Outcome stepStatus `json:"outcome"` -} - // GetEnv returns the env for the context func (rc *RunContext) GetEnv() map[string]string { if rc.Env == nil { @@ -349,16 +309,16 @@ func (rc *RunContext) newStepExecutor(step *model.Step) common.Executor { } return func(ctx context.Context) error { rc.CurrentStep = sc.Step.ID - rc.StepResults[rc.CurrentStep] = &stepResult{ - Outcome: stepStatusSuccess, - Conclusion: stepStatusSuccess, + rc.StepResults[rc.CurrentStep] = &model.StepResult{ + Outcome: model.StepStatusSuccess, + Conclusion: model.StepStatusSuccess, Outputs: make(map[string]string), } runStep, err := sc.isEnabled(ctx) if err != nil { - rc.StepResults[rc.CurrentStep].Conclusion = stepStatusFailure - rc.StepResults[rc.CurrentStep].Outcome = stepStatusFailure + rc.StepResults[rc.CurrentStep].Conclusion = model.StepStatusFailure + rc.StepResults[rc.CurrentStep].Outcome = model.StepStatusFailure return err } @@ -380,13 +340,13 @@ func (rc *RunContext) newStepExecutor(step *model.Step) common.Executor { } else { common.Logger(ctx).Errorf(" \u274C Failure - %s", sc.Step) - rc.StepResults[rc.CurrentStep].Outcome = stepStatusFailure + rc.StepResults[rc.CurrentStep].Outcome = model.StepStatusFailure if sc.Step.ContinueOnError { common.Logger(ctx).Infof("Failed but continue next step") err = nil - rc.StepResults[rc.CurrentStep].Conclusion = stepStatusSuccess + rc.StepResults[rc.CurrentStep].Conclusion = model.StepStatusSuccess } else { - rc.StepResults[rc.CurrentStep].Conclusion = stepStatusFailure + rc.StepResults[rc.CurrentStep].Conclusion = model.StepStatusFailure } } return err @@ -522,31 +482,20 @@ func trimToLen(s string, l int) string { return s } -type jobContext struct { - Status string `json:"status"` - Container struct { - ID string `json:"id"` - Network string `json:"network"` - } `json:"container"` - Services map[string]struct { - ID string `json:"id"` - } `json:"services"` -} - -func (rc *RunContext) getJobContext() *jobContext { +func (rc *RunContext) getJobContext() *model.JobContext { jobStatus := "success" for _, stepStatus := range rc.StepResults { - if stepStatus.Conclusion == stepStatusFailure { + if stepStatus.Conclusion == model.StepStatusFailure { jobStatus = "failure" break } } - return &jobContext{ + return &model.JobContext{ Status: jobStatus, } } -func (rc *RunContext) getStepsContext() map[string]*stepResult { +func (rc *RunContext) getStepsContext() map[string]*model.StepResult { return rc.StepResults } @@ -561,35 +510,8 @@ func (rc *RunContext) getNeedsTransitive(job *model.Job) []string { return needs } -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"` - 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"` -} - -func (rc *RunContext) getGithubContext() *githubContext { - ghc := &githubContext{ +func (rc *RunContext) getGithubContext() *model.GithubContext { + ghc := &model.GithubContext{ Event: make(map[string]interface{}), EventPath: ActPath + "/workflow/event.json", Workflow: rc.Run.Workflow.Name, @@ -685,7 +607,7 @@ func (rc *RunContext) getGithubContext() *githubContext { return ghc } -func (ghc *githubContext) isLocalCheckout(step *model.Step) bool { +func isLocalCheckout(ghc *model.GithubContext, step *model.Step) bool { if step.Type() == model.StepTypeInvalid { // This will be errored out by the executor later, we need this here to avoid a null panic though return false @@ -839,7 +761,7 @@ func setActionRuntimeVars(rc *RunContext, env map[string]string) { func (rc *RunContext) localCheckoutPath() (string, bool) { ghContext := rc.getGithubContext() for _, step := range rc.Run.Job().Steps { - if ghContext.isLocalCheckout(step) { + if isLocalCheckout(ghContext, step) { return step.With["path"], true } } diff --git a/pkg/runner/run_context_test.go b/pkg/runner/run_context_test.go index 610b037..b0b9c76 100644 --- a/pkg/runner/run_context_test.go +++ b/pkg/runner/run_context_test.go @@ -53,10 +53,10 @@ func TestRunContext_EvalBool(t *testing.T) { "os": "Linux", "foo": "bar", }, - StepResults: map[string]*stepResult{ + StepResults: map[string]*model.StepResult{ "id1": { - Conclusion: stepStatusSuccess, - Outcome: stepStatusFailure, + Conclusion: model.StepStatusSuccess, + Outcome: model.StepStatusFailure, Outputs: map[string]string{ "foo": "bar", }, @@ -312,7 +312,7 @@ func TestGetGitHubContext(t *testing.T) { Matrix: map[string]interface{}{}, Env: map[string]string{}, ExtraPath: []string{}, - StepResults: map[string]*stepResult{}, + StepResults: map[string]*model.StepResult{}, OutputMappings: map[MappableOutput]MappableOutput{}, } diff --git a/pkg/runner/runner.go b/pkg/runner/runner.go index 72c6341..8a43623 100644 --- a/pkg/runner/runner.go +++ b/pkg/runner/runner.go @@ -188,7 +188,7 @@ func (runner *runnerImpl) newRunContext(run *model.Run, matrix map[string]interf Config: runner.config, Run: run, EventJSON: runner.eventJSON, - StepResults: make(map[string]*stepResult), + StepResults: make(map[string]*model.StepResult), Matrix: matrix, } rc.ExprEval = rc.NewExpressionEvaluator() diff --git a/pkg/runner/step_context.go b/pkg/runner/step_context.go index 0da1c68..f7ba353 100644 --- a/pkg/runner/step_context.go +++ b/pkg/runner/step_context.go @@ -77,7 +77,7 @@ func (sc *StepContext) Executor(ctx context.Context) common.Executor { remoteAction.URL = rc.Config.GitHubInstance github := rc.getGithubContext() - if remoteAction.IsCheckout() && github.isLocalCheckout(step) { + if remoteAction.IsCheckout() && isLocalCheckout(github, step) { return func(ctx context.Context) error { common.Logger(ctx).Debugf("Skipping local actions/checkout because workdir was already copied") return nil diff --git a/pkg/runner/step_context_test.go b/pkg/runner/step_context_test.go index 7f5d32a..f3d6dc8 100644 --- a/pkg/runner/step_context_test.go +++ b/pkg/runner/step_context_test.go @@ -46,7 +46,7 @@ func createIfTestStepContext(t *testing.T, input string) *StepContext { "ubuntu-latest": "ubuntu-latest", }, }, - StepResults: map[string]*stepResult{}, + StepResults: map[string]*model.StepResult{}, Env: map[string]string{}, Run: &model.Run{ JobID: "job1", @@ -71,14 +71,14 @@ func TestStepContextIsEnabled(t *testing.T) { assertObject.True(sc.isEnabled(context.Background())) sc = createIfTestStepContext(t, "if: success()") - sc.RunContext.StepResults["a"] = &stepResult{ - Conclusion: stepStatusSuccess, + sc.RunContext.StepResults["a"] = &model.StepResult{ + Conclusion: model.StepStatusSuccess, } assertObject.True(sc.isEnabled(context.Background())) sc = createIfTestStepContext(t, "if: success()") - sc.RunContext.StepResults["a"] = &stepResult{ - Conclusion: stepStatusFailure, + sc.RunContext.StepResults["a"] = &model.StepResult{ + Conclusion: model.StepStatusFailure, } assertObject.False(sc.isEnabled(context.Background())) @@ -87,14 +87,14 @@ func TestStepContextIsEnabled(t *testing.T) { assertObject.False(sc.isEnabled(context.Background())) sc = createIfTestStepContext(t, "if: failure()") - sc.RunContext.StepResults["a"] = &stepResult{ - Conclusion: stepStatusSuccess, + sc.RunContext.StepResults["a"] = &model.StepResult{ + Conclusion: model.StepStatusSuccess, } assertObject.False(sc.isEnabled(context.Background())) sc = createIfTestStepContext(t, "if: failure()") - sc.RunContext.StepResults["a"] = &stepResult{ - Conclusion: stepStatusFailure, + sc.RunContext.StepResults["a"] = &model.StepResult{ + Conclusion: model.StepStatusFailure, } assertObject.True(sc.isEnabled(context.Background())) @@ -103,14 +103,14 @@ func TestStepContextIsEnabled(t *testing.T) { assertObject.True(sc.isEnabled(context.Background())) sc = createIfTestStepContext(t, "if: always()") - sc.RunContext.StepResults["a"] = &stepResult{ - Conclusion: stepStatusSuccess, + sc.RunContext.StepResults["a"] = &model.StepResult{ + Conclusion: model.StepStatusSuccess, } assertObject.True(sc.isEnabled(context.Background())) sc = createIfTestStepContext(t, "if: always()") - sc.RunContext.StepResults["a"] = &stepResult{ - Conclusion: stepStatusFailure, + sc.RunContext.StepResults["a"] = &model.StepResult{ + Conclusion: model.StepStatusFailure, } assertObject.True(sc.isEnabled(context.Background())) }