From 38e7e9e939a91449bc5ef36cfebdd98197a33680 Mon Sep 17 00:00:00 2001 From: Jason Song Date: Tue, 24 Sep 2024 06:53:41 +0000 Subject: [PATCH] Use hashed `uses` string as cache dir name (#117) Reviewed-on: https://gitea.com/gitea/act/pulls/117 Reviewed-by: Lunny Xiao --- pkg/model/workflow.go | 10 +++++++++- pkg/model/workflow_test.go | 34 ++++++++++++++++++++++++++++++++ pkg/runner/action.go | 6 +++--- pkg/runner/step_action_remote.go | 6 +++--- 4 files changed, 49 insertions(+), 7 deletions(-) diff --git a/pkg/model/workflow.go b/pkg/model/workflow.go index 692fe89..be1652a 100644 --- a/pkg/model/workflow.go +++ b/pkg/model/workflow.go @@ -1,6 +1,7 @@ package model import ( + "crypto/sha256" "fmt" "io" "reflect" @@ -8,9 +9,10 @@ import ( "strconv" "strings" - "github.com/nektos/act/pkg/common" log "github.com/sirupsen/logrus" "gopkg.in/yaml.v3" + + "github.com/nektos/act/pkg/common" ) // Workflow is the structure of the files in .github/workflows @@ -716,6 +718,12 @@ func (s *Step) Type() StepType { return StepTypeUsesActionRemote } +// UsesHash returns a hash of the uses string. +// For Gitea. +func (s *Step) UsesHash() string { + return fmt.Sprintf("%x", sha256.Sum256([]byte(s.Uses))) +} + // ReadWorkflow returns a list of jobs for a given workflow file reader func ReadWorkflow(in io.Reader) (*Workflow, error) { w := new(Workflow) diff --git a/pkg/model/workflow_test.go b/pkg/model/workflow_test.go index 9f219ee..7e4f975 100644 --- a/pkg/model/workflow_test.go +++ b/pkg/model/workflow_test.go @@ -603,3 +603,37 @@ func TestReadWorkflow_WorkflowDispatchConfig(t *testing.T) { Type: "choice", }, workflowDispatch.Inputs["logLevel"]) } + +func TestStep_UsesHash(t *testing.T) { + type fields struct { + Uses string + } + tests := []struct { + name string + fields fields + want string + }{ + { + name: "regular", + fields: fields{ + Uses: "https://gitea.com/testa/testb@v3", + }, + want: "ae437878e9f285bd7518c58664f9fabbb12d05feddd7169c01702a2a14322aa8", + }, + { + name: "empty", + fields: fields{ + Uses: "", + }, + want: "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + s := &Step{ + Uses: tt.fields.Uses, + } + assert.Equalf(t, tt.want, s.UsesHash(), "UsesHash()") + }) + } +} diff --git a/pkg/runner/action.go b/pkg/runner/action.go index ce38787..170b465 100644 --- a/pkg/runner/action.go +++ b/pkg/runner/action.go @@ -535,7 +535,7 @@ func runPreStep(step actionStep) common.Executor { var actionPath string if _, ok := step.(*stepActionRemote); ok { actionPath = newRemoteAction(stepModel.Uses).Path - actionDir = fmt.Sprintf("%s/%s", rc.ActionCacheDir(), safeFilename(stepModel.Uses)) + actionDir = fmt.Sprintf("%s/%s", rc.ActionCacheDir(), stepModel.UsesHash()) } else { actionDir = filepath.Join(rc.Config.Workdir, stepModel.Uses) actionPath = "" @@ -579,7 +579,7 @@ func runPreStep(step actionStep) common.Executor { var actionPath string if _, ok := step.(*stepActionRemote); ok { actionPath = newRemoteAction(stepModel.Uses).Path - actionDir = fmt.Sprintf("%s/%s", rc.ActionCacheDir(), safeFilename(stepModel.Uses)) + actionDir = fmt.Sprintf("%s/%s", rc.ActionCacheDir(), stepModel.UsesHash()) } else { actionDir = filepath.Join(rc.Config.Workdir, stepModel.Uses) actionPath = "" @@ -665,7 +665,7 @@ func runPostStep(step actionStep) common.Executor { var actionPath string if _, ok := step.(*stepActionRemote); ok { actionPath = newRemoteAction(stepModel.Uses).Path - actionDir = fmt.Sprintf("%s/%s", rc.ActionCacheDir(), safeFilename(stepModel.Uses)) + actionDir = fmt.Sprintf("%s/%s", rc.ActionCacheDir(), stepModel.UsesHash()) } else { actionDir = filepath.Join(rc.Config.Workdir, stepModel.Uses) actionPath = "" diff --git a/pkg/runner/step_action_remote.go b/pkg/runner/step_action_remote.go index ed4d94e..b23ca19 100644 --- a/pkg/runner/step_action_remote.go +++ b/pkg/runner/step_action_remote.go @@ -108,7 +108,7 @@ func (sar *stepActionRemote) prepareActionExecutor() common.Executor { return err } - actionDir := fmt.Sprintf("%s/%s", sar.RunContext.ActionCacheDir(), safeFilename(sar.Step.Uses)) + actionDir := fmt.Sprintf("%s/%s", sar.RunContext.ActionCacheDir(), sar.Step.UsesHash()) gitClone := stepActionRemoteNewCloneExecutor(git.NewGitCloneExecutorInput{ URL: sar.remoteAction.CloneURL(sar.RunContext.Config.DefaultActionInstance), Ref: sar.remoteAction.Ref, @@ -177,7 +177,7 @@ func (sar *stepActionRemote) main() common.Executor { return sar.RunContext.JobContainer.CopyDir(copyToPath, sar.RunContext.Config.Workdir+string(filepath.Separator)+".", sar.RunContext.Config.UseGitIgnore)(ctx) } - actionDir := fmt.Sprintf("%s/%s", sar.RunContext.ActionCacheDir(), safeFilename(sar.Step.Uses)) + actionDir := fmt.Sprintf("%s/%s", sar.RunContext.ActionCacheDir(), sar.Step.UsesHash()) return sar.runAction(sar, actionDir, sar.remoteAction)(ctx) }), @@ -236,7 +236,7 @@ func (sar *stepActionRemote) getActionModel() *model.Action { func (sar *stepActionRemote) getCompositeRunContext(ctx context.Context) *RunContext { if sar.compositeRunContext == nil { - actionDir := fmt.Sprintf("%s/%s", sar.RunContext.ActionCacheDir(), safeFilename(sar.Step.Uses)) + actionDir := fmt.Sprintf("%s/%s", sar.RunContext.ActionCacheDir(), sar.Step.UsesHash()) actionLocation := path.Join(actionDir, sar.remoteAction.Path) _, containerActionDir := getContainerActionPaths(sar.getStepModel(), actionLocation, sar.RunContext)