diff --git a/cmd/input.go b/cmd/input.go index a6d70dd..36af6d8 100644 --- a/cmd/input.go +++ b/cmd/input.go @@ -55,6 +55,7 @@ type Input struct { replaceGheActionTokenWithGithubCom string matrix []string actionCachePath string + actionOfflineMode bool logPrefixJobID bool networkName string useNewActionCache bool diff --git a/cmd/root.go b/cmd/root.go index 0494b86..e595e52 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -97,6 +97,7 @@ func Execute(ctx context.Context, version string) { rootCmd.PersistentFlags().StringVarP(&input.cacheServerAddr, "cache-server-addr", "", common.GetOutboundIP().String(), "Defines the address to which the cache server binds.") rootCmd.PersistentFlags().Uint16VarP(&input.cacheServerPort, "cache-server-port", "", 0, "Defines the port where the artifact server listens. 0 means a randomly available port.") rootCmd.PersistentFlags().StringVarP(&input.actionCachePath, "action-cache-path", "", filepath.Join(CacheHomeDir, "act"), "Defines the path where the actions get cached and host workspaces created.") + rootCmd.PersistentFlags().BoolVarP(&input.actionOfflineMode, "action-offline-mode", "", false, "If action contents exists, it will not be fetch and pull again. If turn on this,will turn off force pull") rootCmd.PersistentFlags().StringVarP(&input.networkName, "network", "", "host", "Sets a docker network name. Defaults to host.") rootCmd.PersistentFlags().BoolVarP(&input.useNewActionCache, "use-new-action-cache", "", false, "Enable using the new Action Cache for storing Actions locally") rootCmd.SetArgs(args()) @@ -582,11 +583,12 @@ func newRunCommand(ctx context.Context, input *Input) func(*cobra.Command, []str EventName: eventName, EventPath: input.EventPath(), DefaultBranch: defaultbranch, - ForcePull: input.forcePull, + ForcePull: !input.actionOfflineMode && input.forcePull, ForceRebuild: input.forceRebuild, ReuseContainers: input.reuseContainers, Workdir: input.Workdir(), ActionCacheDir: input.actionCachePath, + ActionOfflineMode: input.actionOfflineMode, BindWorkdir: input.bindWorkdir, LogOutput: !input.noOutput, JSONLogger: input.jsonLogger, diff --git a/pkg/common/git/git.go b/pkg/common/git/git.go index bf77155..0a819b9 100644 --- a/pkg/common/git/git.go +++ b/pkg/common/git/git.go @@ -221,10 +221,11 @@ func findGitSlug(url string, githubInstance string) (string, string, error) { // NewGitCloneExecutorInput the input for the NewGitCloneExecutor type NewGitCloneExecutorInput struct { - URL string - Ref string - Dir string - Token string + URL string + Ref string + Dir string + Token string + OfflineMode bool } // CloneIfRequired ... @@ -302,12 +303,16 @@ func NewGitCloneExecutor(input NewGitCloneExecutorInput) common.Executor { return err } + isOfflineMode := input.OfflineMode + // fetch latest changes fetchOptions, pullOptions := gitOptions(input.Token) - err = r.Fetch(&fetchOptions) - if err != nil && !errors.Is(err, git.NoErrAlreadyUpToDate) { - return err + if !isOfflineMode { + err = r.Fetch(&fetchOptions) + if err != nil && !errors.Is(err, git.NoErrAlreadyUpToDate) { + return err + } } var hash *plumbing.Hash @@ -367,9 +372,10 @@ func NewGitCloneExecutor(input NewGitCloneExecutorInput) common.Executor { return err } } - - if err = w.Pull(&pullOptions); err != nil && err != git.NoErrAlreadyUpToDate { - logger.Debugf("Unable to pull %s: %v", refName, err) + if !isOfflineMode { + if err = w.Pull(&pullOptions); err != nil && err != git.NoErrAlreadyUpToDate { + logger.Debugf("Unable to pull %s: %v", refName, err) + } } logger.Debugf("Cloned %s to %s", input.URL, input.Dir) diff --git a/pkg/runner/reusable_workflow.go b/pkg/runner/reusable_workflow.go index b5e3d5b..7ce68e9 100644 --- a/pkg/runner/reusable_workflow.go +++ b/pkg/runner/reusable_workflow.go @@ -102,10 +102,11 @@ func cloneIfRequired(rc *RunContext, remoteReusableWorkflow remoteReusableWorkfl func(ctx context.Context) error { remoteReusableWorkflow.URL = rc.getGithubContext(ctx).ServerURL return git.NewGitCloneExecutor(git.NewGitCloneExecutorInput{ - URL: remoteReusableWorkflow.CloneURL(), - Ref: remoteReusableWorkflow.Ref, - Dir: targetDirectory, - Token: rc.Config.Token, + URL: remoteReusableWorkflow.CloneURL(), + Ref: remoteReusableWorkflow.Ref, + Dir: targetDirectory, + Token: rc.Config.Token, + OfflineMode: rc.Config.ActionOfflineMode, })(ctx) }, nil, diff --git a/pkg/runner/runner.go b/pkg/runner/runner.go index 5a7b1ad..dd8afe5 100644 --- a/pkg/runner/runner.go +++ b/pkg/runner/runner.go @@ -23,6 +23,7 @@ type Config struct { Actor string // the user that triggered the event Workdir string // path to working directory ActionCacheDir string // path used for caching action contents + ActionOfflineMode bool // when offline, use caching action contents BindWorkdir bool // bind the workdir to the job container EventName string // name of event to run EventPath string // path to JSON file to use for event.json in containers diff --git a/pkg/runner/step_action_remote.go b/pkg/runner/step_action_remote.go index 4019388..5c8a8f2 100644 --- a/pkg/runner/step_action_remote.go +++ b/pkg/runner/step_action_remote.go @@ -106,10 +106,11 @@ func (sar *stepActionRemote) prepareActionExecutor() common.Executor { actionDir := fmt.Sprintf("%s/%s", sar.RunContext.ActionCacheDir(), safeFilename(sar.Step.Uses)) gitClone := stepActionRemoteNewCloneExecutor(git.NewGitCloneExecutorInput{ - URL: sar.remoteAction.CloneURL(), - Ref: sar.remoteAction.Ref, - Dir: actionDir, - Token: github.Token, + URL: sar.remoteAction.CloneURL(), + Ref: sar.remoteAction.Ref, + Dir: actionDir, + Token: github.Token, + OfflineMode: sar.RunContext.Config.ActionOfflineMode, }) var ntErr common.Executor if err := gitClone(ctx); err != nil {