From 12545a66fc91cb779be4152f36260666075f1427 Mon Sep 17 00:00:00 2001 From: Kuan Yong Date: Thu, 22 Jun 2023 19:05:25 +0800 Subject: [PATCH] fix: fail to find local subworkflow of remote workflow --- cmd/root.go | 2 +- pkg/artifacts/server_test.go | 2 +- pkg/model/planner.go | 10 ++++++++-- pkg/model/planner_test.go | 3 +-- pkg/model/workflow.go | 1 + pkg/model/workflow_test.go | 2 +- pkg/runner/reusable_workflow.go | 12 +++++++++--- pkg/runner/runner_test.go | 15 ++++++++------- .../caller-workflow.yml | 7 +++++++ 9 files changed, 37 insertions(+), 17 deletions(-) create mode 100644 pkg/runner/testdata/issue-1875-uses-workflow-with-sub-workflow/caller-workflow.yml diff --git a/cmd/root.go b/cmd/root.go index 59a571e2b23..cc6bd028e6a 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -428,7 +428,7 @@ func newRunCommand(ctx context.Context, input *Input) func(*cobra.Command, []str matrixes := parseMatrix(input.matrix) log.Debugf("Evaluated matrix inclusions: %v", matrixes) - planner, err := model.NewWorkflowPlanner(input.WorkflowsPath(), input.noWorkflowRecurse) + planner, err := model.NewWorkflowPlanner("", input.WorkflowsPath(), input.noWorkflowRecurse) if err != nil { return err } diff --git a/pkg/artifacts/server_test.go b/pkg/artifacts/server_test.go index aeeb0598a4d..a0d91a04f36 100644 --- a/pkg/artifacts/server_test.go +++ b/pkg/artifacts/server_test.go @@ -297,7 +297,7 @@ func runTestJobFile(ctx context.Context, t *testing.T, tjfi TestJobFileInfo) { runner, err := runner.New(runnerConfig) assert.Nil(t, err, tjfi.workflowPath) - planner, err := model.NewWorkflowPlanner(fullWorkflowPath, true) + planner, err := model.NewWorkflowPlanner(workdir, tjfi.workflowPath, true) assert.Nil(t, err, fullWorkflowPath) plan, err := planner.PlanEvent(tjfi.eventName) diff --git a/pkg/model/planner.go b/pkg/model/planner.go index 1769b73212e..e8e8504216e 100644 --- a/pkg/model/planner.go +++ b/pkg/model/planner.go @@ -58,7 +58,13 @@ type WorkflowFiles struct { // NewWorkflowPlanner will load a specific workflow, all workflows from a directory or all workflows from a directory and its subdirectories // //nolint:gocyclo -func NewWorkflowPlanner(path string, noWorkflowRecurse bool) (WorkflowPlanner, error) { +func NewWorkflowPlanner(directory string, workflow string, noWorkflowRecurse bool) (WorkflowPlanner, error) { + path := "" + if directory == "" || workflow == "" { + path = directory + workflow + } else { + path = filepath.Join(directory, workflow) + } path, err := filepath.Abs(path) if err != nil { return nil, err @@ -142,7 +148,7 @@ func NewWorkflowPlanner(path string, noWorkflowRecurse bool) (WorkflowPlanner, e _ = f.Close() return nil, fmt.Errorf("error occurring when resetting io pointer in '%s': %w", wf.workflowDirEntry.Name(), err) } - + workflow.RepoPath = directory workflow.File = wf.workflowDirEntry.Name() if workflow.Name == "" { workflow.Name = wf.workflowDirEntry.Name() diff --git a/pkg/model/planner_test.go b/pkg/model/planner_test.go index 551b7b379c0..fb967eaf863 100644 --- a/pkg/model/planner_test.go +++ b/pkg/model/planner_test.go @@ -30,8 +30,7 @@ func TestPlanner(t *testing.T) { workdir, err := filepath.Abs("testdata") assert.NoError(t, err, workdir) for _, table := range tables { - fullWorkflowPath := filepath.Join(workdir, table.workflowPath) - _, err = NewWorkflowPlanner(fullWorkflowPath, table.noWorkflowRecurse) + _, err = NewWorkflowPlanner(workdir, table.workflowPath, table.noWorkflowRecurse) if table.errorMessage == "" { assert.NoError(t, err, "WorkflowPlanner should exit without any error") } else { diff --git a/pkg/model/workflow.go b/pkg/model/workflow.go index 19edfb43db7..ac029fff8af 100644 --- a/pkg/model/workflow.go +++ b/pkg/model/workflow.go @@ -15,6 +15,7 @@ import ( // Workflow is the structure of the files in .github/workflows type Workflow struct { + RepoPath string File string Name string `yaml:"name"` RawOn yaml.Node `yaml:"on"` diff --git a/pkg/model/workflow_test.go b/pkg/model/workflow_test.go index 8f8b7a9e4b3..a3753bcf0c1 100644 --- a/pkg/model/workflow_test.go +++ b/pkg/model/workflow_test.go @@ -238,7 +238,7 @@ jobs: } func TestReadWorkflow_Strategy(t *testing.T) { - w, err := NewWorkflowPlanner("testdata/strategy/push.yml", true) + w, err := NewWorkflowPlanner("testdata/strategy", "push.yml", true) assert.NoError(t, err) p, err := w.PlanJob("strategy-only-max-parallel") diff --git a/pkg/runner/reusable_workflow.go b/pkg/runner/reusable_workflow.go index 67e04037701..3c8a99cc73c 100644 --- a/pkg/runner/reusable_workflow.go +++ b/pkg/runner/reusable_workflow.go @@ -6,8 +6,8 @@ import ( "fmt" "io/fs" "os" - "path" "regexp" + "strings" "sync" "github.com/nektos/act/pkg/common" @@ -16,7 +16,13 @@ import ( ) func newLocalReusableWorkflowExecutor(rc *RunContext) common.Executor { - return newReusableWorkflowExecutor(rc, rc.Config.Workdir, rc.Run.Job().Uses) + job := rc.Run.Job() + if strings.Index(job.Uses, "./") == 0 { + // relative path + return newReusableWorkflowExecutor(rc, rc.Run.Workflow.RepoPath, job.Uses) + } else { + return newReusableWorkflowExecutor(rc, rc.Config.Workdir, job.Uses) + } } func newRemoteReusableWorkflowExecutor(rc *RunContext) common.Executor { @@ -74,7 +80,7 @@ func cloneIfRequired(rc *RunContext, remoteReusableWorkflow remoteReusableWorkfl func newReusableWorkflowExecutor(rc *RunContext, directory string, workflow string) common.Executor { return func(ctx context.Context) error { - planner, err := model.NewWorkflowPlanner(path.Join(directory, workflow), true) + planner, err := model.NewWorkflowPlanner(directory, workflow, true) if err != nil { return err } diff --git a/pkg/runner/runner_test.go b/pkg/runner/runner_test.go index db63fb94b27..902867ba6b7 100644 --- a/pkg/runner/runner_test.go +++ b/pkg/runner/runner_test.go @@ -50,7 +50,7 @@ func init() { } func TestNoWorkflowsFoundByPlanner(t *testing.T) { - planner, err := model.NewWorkflowPlanner("res", true) + planner, err := model.NewWorkflowPlanner("res", "", true) assert.NoError(t, err) out := log.StandardLogger().Out @@ -70,7 +70,7 @@ func TestNoWorkflowsFoundByPlanner(t *testing.T) { } func TestGraphMissingEvent(t *testing.T) { - planner, err := model.NewWorkflowPlanner("testdata/issue-1595/no-event.yml", true) + planner, err := model.NewWorkflowPlanner("testdata/issue-1595", "no-event.yml", true) assert.NoError(t, err) out := log.StandardLogger().Out @@ -88,7 +88,7 @@ func TestGraphMissingEvent(t *testing.T) { } func TestGraphMissingFirst(t *testing.T) { - planner, err := model.NewWorkflowPlanner("testdata/issue-1595/no-first.yml", true) + planner, err := model.NewWorkflowPlanner("testdata/issue-1595", "no-first.yml", true) assert.NoError(t, err) plan, err := planner.PlanEvent("push") @@ -98,7 +98,7 @@ func TestGraphMissingFirst(t *testing.T) { } func TestGraphWithMissing(t *testing.T) { - planner, err := model.NewWorkflowPlanner("testdata/issue-1595/missing.yml", true) + planner, err := model.NewWorkflowPlanner("testdata/issue-1595", "missing.yml", true) assert.NoError(t, err) out := log.StandardLogger().Out @@ -117,7 +117,7 @@ func TestGraphWithMissing(t *testing.T) { func TestGraphWithSomeMissing(t *testing.T) { log.SetLevel(log.DebugLevel) - planner, err := model.NewWorkflowPlanner("testdata/issue-1595/", true) + planner, err := model.NewWorkflowPlanner("testdata/issue-1595", "", true) assert.NoError(t, err) out := log.StandardLogger().Out @@ -135,7 +135,7 @@ func TestGraphWithSomeMissing(t *testing.T) { } func TestGraphEvent(t *testing.T) { - planner, err := model.NewWorkflowPlanner("testdata/basic", true) + planner, err := model.NewWorkflowPlanner("testdata/basic", "", true) assert.NoError(t, err) plan, err := planner.PlanEvent("push") @@ -192,7 +192,7 @@ func (j *TestJobFileInfo) runTest(ctx context.Context, t *testing.T, cfg *Config runner, err := New(runnerConfig) assert.Nil(t, err, j.workflowPath) - planner, err := model.NewWorkflowPlanner(fullWorkflowPath, true) + planner, err := model.NewWorkflowPlanner(workdir, j.workflowPath, true) assert.Nil(t, err, fullWorkflowPath) plan, err := planner.PlanEvent(j.eventName) @@ -241,6 +241,7 @@ func TestRunEvent(t *testing.T) { {workdir, "uses-workflow", "pull_request", "", platforms, map[string]string{"secret": "keep_it_private"}}, {workdir, "uses-docker-url", "push", "", platforms, secrets}, {workdir, "act-composite-env-test", "push", "", platforms, secrets}, + {workdir, "issue-1875-uses-workflow-with-sub-workflow", "dispatch", "", platforms, secrets}, // Eval {workdir, "evalmatrix", "push", "", platforms, secrets}, diff --git a/pkg/runner/testdata/issue-1875-uses-workflow-with-sub-workflow/caller-workflow.yml b/pkg/runner/testdata/issue-1875-uses-workflow-with-sub-workflow/caller-workflow.yml new file mode 100644 index 00000000000..1f9e37fe7b4 --- /dev/null +++ b/pkg/runner/testdata/issue-1875-uses-workflow-with-sub-workflow/caller-workflow.yml @@ -0,0 +1,7 @@ +name: Call Reusable Workflow +on: + push: + +jobs: + call-reusable-workflow-with-sub: + uses: wildsheepz/TestReusableWorkflow/.github/workflows/main.yaml@ubuntu_platform \ No newline at end of file