Skip Clone Optimization#
The skip-clone-no-changes feature prevents Atlantis from cloning a repository during autoplan when no configured Terraform projects were modified by the PR. This avoids the expensive git clone operation for busy repositories where most PRs don't touch infrastructure code.
How It Works#
The optimization is implemented in shouldSkipClone() inside project_command_builder.go. Before cloning, buildAllCommandsByCfg() calls shouldSkipClone() and returns an empty []command.ProjectContext{} immediately if the skip condition is met β preventing the WorkingDir.Clone() call at line 883.
shouldSkipClone() requires all of the following before it will skip :
SkipCloneNoChangesis enabled β the--skip-clone-no-changesflag (env:ATLANTIS_SKIP_CLONE_NO_CHANGES)- VCS supports single-file download β without this, Atlantis cannot fetch
atlantis.yamlto determine project membership without cloning atlantis.yamlexists in the repo β if there's no repo config file, Atlantis falls back to autodiscovery and must clone- Autodiscovery is disabled β if autodiscovery is active (
automode with no explicit projects, orenabledmode), the skip is suppressed because project detection requires the full working tree - No configured projects match modified files β
DetermineProjectsViaConfig()checks modified files against each project'swhen_modifiedpaths; if any project matches, the clone proceeds
The IncludeGitUntrackedFiles flag bypasses the skip entirely , since untracked files aren't visible without a clone.
Configuration#
| Flag | Env Var | Type | Default |
|---|---|---|---|
--skip-clone-no-changes | ATLANTIS_SKIP_CLONE_NO_CHANGES | bool | false |
Defined in server/user_config.go and registered as a CLI flag in cmd/server.go.
Interactions with Post-Workflow Hooks#
Even when skip-clone-no-changes determines that no projects were modified and skips the autoplan clone, post-workflow hooks still execute and perform their own clone β the optimization is bypassed downstream.
The Clone Gap#
RunPostHooks() in post_workflow_hooks_command_runner.go unconditionally calls WorkingDir.Clone() at line 65 after checking if hooks are configured . It has no knowledge of SkipCloneNoChanges. In production systems this causes unnecessary repository storage accumulation β reportedly up to ~500 GB in large multi-project setups.
The Autoplan Post-Hook Guard Gap#
In RunAutoplanCommand(), RunPostHooks is called unconditionally at line 247 , with no check for whether any projects were actually found or planned. This is asymmetric with RunCommentCommand(), which does check ctx.CommandSkipped before invoking post-hooks .
The result: when SkipCloneNoChanges causes an early return with zero projects, post-workflow hooks still run for every autoplan event β including hooks with real side effects (automerge scripts, Slack notifications, cost estimation).
Interaction with SilenceNoProjects / SilenceVCSStatusNoProjects#
--silence-no-projects (ATLANTIS_SILENCE_NO_PROJECTS) and --silence-vcs-status-no-projects (ATLANTIS_SILENCE_VCS_STATUS_NO_PROJECTS) suppress PR comments and VCS commit statuses when no projects are found, but they have a related gap with post-workflow hooks .
When SilenceVCSStatusNoProjects is set and no projects match, plan_command_runner.go and apply_command_runner.go skip their inline VCS status writes using a local silenceVCSStatusNoProjects field β but neither sets ctx.SuppressVCSStatus = true on the context. command_runner.go never checks ctx.SuppressVCSStatus before calling RunPostHooks, so post-workflow hooks still fire and create VCS check runs on the PR .
This is particularly disruptive in multi-instance setups where multiple Atlantis servers monitor the same repository: an instance with no relevant projects will still trigger post-hook GitHub checks on every PR, creating noise and interfering with automerge policies.
A fix was proposed in PR #6653:
- Set
ctx.SuppressVCSStatus = truein both command runners' 0-project silence paths - Add guards in
command_runner.gobefore all threeRunPostHookscall sites
The design question open for maintainers is whether to expand the semantics of --silence-vcs-status-no-projects (now suppressing hook execution, not just status posting) or introduce a new dedicated flag.
Key Source Files#
| File | Role |
|---|---|
server/events/project_command_builder.go | shouldSkipClone() β core skip decision logic |
server/events/command_runner.go | RunAutoplanCommand() β autoplan orchestration; unconditional RunPostHooks call |
server/events/post_workflow_hooks_command_runner.go | RunPostHooks() β unconditional clone at line 65 |
server/user_config.go | SkipCloneNoChanges field definition |
cmd/server.go | CLI flag registration for --skip-clone-no-changes |
Open issues: #6652 (post-hook VCS status suppression), #6712 (post-hook clone bypassing skip-clone-no-changes)