summaryrefslogtreecommitdiffstats
path: root/pkg/runner/step_action_local_test.go
diff options
context:
space:
mode:
authorDaniel Baumann <daniel@debian.org>2024-10-20 23:07:42 +0200
committerDaniel Baumann <daniel@debian.org>2024-11-09 15:38:42 +0100
commit714c83b2736d7e308bc33c49057952490eb98be2 (patch)
tree1d9ba7035798368569cd49056f4d596efc908cd8 /pkg/runner/step_action_local_test.go
parentInitial commit. (diff)
downloadforgejo-act-upstream/1.21.4.tar.xz
forgejo-act-upstream/1.21.4.zip
Adding upstream version 1.21.4.HEADupstream/1.21.4upstreamdebian
Signed-off-by: Daniel Baumann <daniel@debian.org>
Diffstat (limited to 'pkg/runner/step_action_local_test.go')
-rw-r--r--pkg/runner/step_action_local_test.go293
1 files changed, 293 insertions, 0 deletions
diff --git a/pkg/runner/step_action_local_test.go b/pkg/runner/step_action_local_test.go
new file mode 100644
index 0000000..c4b6345
--- /dev/null
+++ b/pkg/runner/step_action_local_test.go
@@ -0,0 +1,293 @@
+package runner
+
+import (
+ "bytes"
+ "context"
+ "io"
+ "path/filepath"
+ "strings"
+ "testing"
+
+ "github.com/nektos/act/pkg/common"
+ "github.com/nektos/act/pkg/model"
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/mock"
+ "gopkg.in/yaml.v3"
+)
+
+type stepActionLocalMocks struct {
+ mock.Mock
+}
+
+func (salm *stepActionLocalMocks) runAction(step actionStep, actionDir string, remoteAction *remoteAction) common.Executor {
+ args := salm.Called(step, actionDir, remoteAction)
+ return args.Get(0).(func(context.Context) error)
+}
+
+func (salm *stepActionLocalMocks) readAction(_ context.Context, step *model.Step, actionDir string, actionPath string, readFile actionYamlReader, writeFile fileWriter) (*model.Action, error) {
+ args := salm.Called(step, actionDir, actionPath, readFile, writeFile)
+ return args.Get(0).(*model.Action), args.Error(1)
+}
+
+func TestStepActionLocalTest(t *testing.T) {
+ ctx := context.Background()
+
+ cm := &containerMock{}
+ salm := &stepActionLocalMocks{}
+
+ sal := &stepActionLocal{
+ readAction: salm.readAction,
+ runAction: salm.runAction,
+ RunContext: &RunContext{
+ StepResults: map[string]*model.StepResult{},
+ ExprEval: &expressionEvaluator{},
+ Config: &Config{
+ Workdir: "/tmp",
+ },
+ Run: &model.Run{
+ JobID: "1",
+ Workflow: &model.Workflow{
+ Jobs: map[string]*model.Job{
+ "1": {
+ Defaults: model.Defaults{
+ Run: model.RunDefaults{
+ Shell: "bash",
+ },
+ },
+ },
+ },
+ },
+ },
+ JobContainer: cm,
+ },
+ Step: &model.Step{
+ ID: "1",
+ Uses: "./path/to/action",
+ },
+ }
+
+ salm.On("readAction", sal.Step, filepath.Clean("/tmp/path/to/action"), "", mock.Anything, mock.Anything).
+ Return(&model.Action{}, nil)
+
+ cm.On("Copy", "/var/run/act", mock.AnythingOfType("[]*container.FileEntry")).Return(func(ctx context.Context) error {
+ return nil
+ })
+
+ cm.On("UpdateFromEnv", "/var/run/act/workflow/envs.txt", mock.AnythingOfType("*map[string]string")).Return(func(ctx context.Context) error {
+ return nil
+ })
+
+ cm.On("UpdateFromEnv", "/var/run/act/workflow/statecmd.txt", mock.AnythingOfType("*map[string]string")).Return(func(ctx context.Context) error {
+ return nil
+ })
+
+ cm.On("UpdateFromEnv", "/var/run/act/workflow/outputcmd.txt", mock.AnythingOfType("*map[string]string")).Return(func(ctx context.Context) error {
+ return nil
+ })
+
+ cm.On("GetContainerArchive", ctx, "/var/run/act/workflow/pathcmd.txt").Return(io.NopCloser(&bytes.Buffer{}), nil)
+
+ salm.On("runAction", sal, filepath.Clean("/tmp/path/to/action"), (*remoteAction)(nil)).Return(func(ctx context.Context) error {
+ return nil
+ })
+
+ err := sal.pre()(ctx)
+ assert.Nil(t, err)
+
+ err = sal.main()(ctx)
+ assert.Nil(t, err)
+
+ cm.AssertExpectations(t)
+ salm.AssertExpectations(t)
+}
+
+func TestStepActionLocalPost(t *testing.T) {
+ table := []struct {
+ name string
+ stepModel *model.Step
+ actionModel *model.Action
+ initialStepResults map[string]*model.StepResult
+ err error
+ mocks struct {
+ env bool
+ exec bool
+ }
+ }{
+ {
+ name: "main-success",
+ stepModel: &model.Step{
+ ID: "step",
+ Uses: "./local/action",
+ },
+ actionModel: &model.Action{
+ Runs: model.ActionRuns{
+ Using: "node16",
+ Post: "post.js",
+ PostIf: "always()",
+ },
+ },
+ initialStepResults: map[string]*model.StepResult{
+ "step": {
+ Conclusion: model.StepStatusSuccess,
+ Outcome: model.StepStatusSuccess,
+ Outputs: map[string]string{},
+ },
+ },
+ mocks: struct {
+ env bool
+ exec bool
+ }{
+ env: true,
+ exec: true,
+ },
+ },
+ {
+ name: "main-failed",
+ stepModel: &model.Step{
+ ID: "step",
+ Uses: "./local/action",
+ },
+ actionModel: &model.Action{
+ Runs: model.ActionRuns{
+ Using: "node16",
+ Post: "post.js",
+ PostIf: "always()",
+ },
+ },
+ initialStepResults: map[string]*model.StepResult{
+ "step": {
+ Conclusion: model.StepStatusFailure,
+ Outcome: model.StepStatusFailure,
+ Outputs: map[string]string{},
+ },
+ },
+ mocks: struct {
+ env bool
+ exec bool
+ }{
+ env: true,
+ exec: true,
+ },
+ },
+ {
+ name: "skip-if-failed",
+ stepModel: &model.Step{
+ ID: "step",
+ Uses: "./local/action",
+ },
+ actionModel: &model.Action{
+ Runs: model.ActionRuns{
+ Using: "node16",
+ Post: "post.js",
+ PostIf: "success()",
+ },
+ },
+ initialStepResults: map[string]*model.StepResult{
+ "step": {
+ Conclusion: model.StepStatusFailure,
+ Outcome: model.StepStatusFailure,
+ Outputs: map[string]string{},
+ },
+ },
+ mocks: struct {
+ env bool
+ exec bool
+ }{
+ env: false,
+ exec: false,
+ },
+ },
+ {
+ name: "skip-if-main-skipped",
+ stepModel: &model.Step{
+ ID: "step",
+ If: yaml.Node{Value: "failure()"},
+ Uses: "./local/action",
+ },
+ actionModel: &model.Action{
+ Runs: model.ActionRuns{
+ Using: "node16",
+ Post: "post.js",
+ PostIf: "always()",
+ },
+ },
+ initialStepResults: map[string]*model.StepResult{
+ "step": {
+ Conclusion: model.StepStatusSkipped,
+ Outcome: model.StepStatusSkipped,
+ Outputs: map[string]string{},
+ },
+ },
+ mocks: struct {
+ env bool
+ exec bool
+ }{
+ env: false,
+ exec: false,
+ },
+ },
+ }
+
+ for _, tt := range table {
+ t.Run(tt.name, func(t *testing.T) {
+ ctx := context.Background()
+
+ cm := &containerMock{}
+
+ sal := &stepActionLocal{
+ env: map[string]string{},
+ RunContext: &RunContext{
+ Config: &Config{
+ GitHubInstance: "https://github.com",
+ },
+ JobContainer: cm,
+ Run: &model.Run{
+ JobID: "1",
+ Workflow: &model.Workflow{
+ Jobs: map[string]*model.Job{
+ "1": {},
+ },
+ },
+ },
+ StepResults: tt.initialStepResults,
+ },
+ Step: tt.stepModel,
+ action: tt.actionModel,
+ }
+ sal.RunContext.ExprEval = sal.RunContext.NewExpressionEvaluator(ctx)
+
+ if tt.mocks.exec {
+ suffixMatcher := func(suffix string) interface{} {
+ return mock.MatchedBy(func(array []string) bool {
+ return strings.HasSuffix(array[1], suffix)
+ })
+ }
+ cm.On("Exec", suffixMatcher("pkg/runner/local/action/post.js"), sal.env, "", "").Return(func(ctx context.Context) error { return tt.err })
+
+ cm.On("Copy", "/var/run/act", mock.AnythingOfType("[]*container.FileEntry")).Return(func(ctx context.Context) error {
+ return nil
+ })
+
+ cm.On("UpdateFromEnv", "/var/run/act/workflow/envs.txt", mock.AnythingOfType("*map[string]string")).Return(func(ctx context.Context) error {
+ return nil
+ })
+
+ cm.On("UpdateFromEnv", "/var/run/act/workflow/statecmd.txt", mock.AnythingOfType("*map[string]string")).Return(func(ctx context.Context) error {
+ return nil
+ })
+
+ cm.On("UpdateFromEnv", "/var/run/act/workflow/outputcmd.txt", mock.AnythingOfType("*map[string]string")).Return(func(ctx context.Context) error {
+ return nil
+ })
+
+ cm.On("GetContainerArchive", ctx, "/var/run/act/workflow/pathcmd.txt").Return(io.NopCloser(&bytes.Buffer{}), nil)
+ }
+
+ err := sal.post()(ctx)
+
+ assert.Equal(t, tt.err, err)
+ assert.Equal(t, sal.RunContext.StepResults["post-step"], (*model.StepResult)(nil))
+ cm.AssertExpectations(t)
+ })
+ }
+}