<GitClone>
The <GitClone> block brings a git repository into a runbook, either by cloning it or by pointing at a checkout the user already has on disk. It works with any git upstream. When a GitHub token is available, it can also browse GitHub organizations, repositories, and branches.
Compared with cloning from a Command block, GitClone adds a form for the clone, search of the GitHub API for orgs, repos, branches, and tags, and the file workspace, which shows the contents of the repository and any changes to it.
Basic usage
Section titled “Basic usage”At its simplest, the block is a single text input for a git URL:
<GitClone id="clone-repo" title="Clone Repository" description="Enter a git URL to clone"/>With GitHub authentication
Section titled “With GitHub authentication”When paired with a <GitHubAuth> block, the GitClone block enables a “Browse GitHub repositories” dropdown for discovering repos by organization and name, and a ref selector for choosing a branch or tag to clone. The GitHub token is also used when cloning GitHub URLs, which gives access to private repositories.
<GitHubAuth id="gh-auth" title="Connect to GitHub" description="Authenticate to access private repos"/>
<GitClone id="clone-repo" githubAuthId="gh-auth" title="Clone a Repo" description="Browse or enter a git URL to clone"/>Using a local checkout
Section titled “Using a local checkout”Users often already have the repository cloned, such as a long-lived infrastructure-live checkout or a large monorepo. The block’s source picker lets them choose Use local checkout and select that directory.
Choosing a directory only inspects it. The block resolves the repository root, so any subdirectory of the checkout works. It then reads the repository’s remote and current branch and counts its tracked files. Nothing is fetched, pulled, modified, or registered at this point.
Confirming with Use This Repo registers the checkout and produces the block’s outputs, as a completed clone does. Until then, any later block referencing its outputs reports them as missing. To undo the choice, use Stop using this repo in the result panel (see Cancelling and starting over).
Inspecting a directory needs no credentials, so browsing works while a linked auth block is still pending. Confirming waits on the auth block, as cloning does, because the GitHub org_id and repo_id outputs are resolved from the session token at that moment.
<GitClone id="repo" title="Select Your Infrastructure Repo" prefilledRepoDir="~/dev/infrastructure-live"/>Setting prefilledRepoDir starts the block on the local source. Use source to choose the starting source explicitly, and hideSourceSelect to remove the choice altogether:
{/* Local checkouts only, with no cloning offered */}<GitClone id="repo" source="local" hideSourceSelect />
{/* Cloning only */}<GitClone id="repo" source="clone" hideSourceSelect prefilledUrl="https://github.com/acme/infra" />Later blocks behave the same with either source. They get the same clone_path, repo_owner, and repo_name outputs, the same $REPO_FILES variable, the same workspace file tree, and the same <GitPullRequest> integration. A pull request opens against the checkout’s remote and current branch.
Pre-filled values
Section titled “Pre-filled values”You can pre-fill the URL, ref, sparse checkout path, and local path fields. Users can still edit these values before cloning.
<GitClone id="clone-docs" title="Clone Runbooks Docs" prefilledUrl="https://github.com/gruntwork-io/runbooks" prefilledRef="v1.0.0" prefilledRepoPath="docs" prefilledLocalPath="./runbooks-docs"/>| Prop | Type | Required | Description |
|---|---|---|---|
id |
string |
Yes | Unique block identifier. Later blocks use it to reference outputs. |
title |
string |
No | Display title for the block header. Supports inline markdown. Defaults to “Clone Repository”. |
description |
string |
No | Description text below the title. Supports inline markdown. |
inputsId |
string | string[] |
No | ID of one or more <Inputs> blocks. title, description, and the prefilled* props resolve {{ .inputs.VarName }} expressions against them. |
githubAuthId |
string |
No | Reference to a <GitHubAuth> block. When set, the block waits for authentication to complete and uses the token for GitHub API access and clone authentication. |
gitAuthId |
string |
No | Reference to a <GitAuth>, <GitHubAuth> or <GitLabAuth> block, for either provider. When set, the block waits for authentication to complete and clones with that provider’s session token, including from a self-managed GitLab instance. |
prefilledUrl |
string |
No | Pre-fills the Git URL input field. The user can edit this value before cloning. |
prefilledRef |
string |
No | Pre-fills the ref (branch or tag) to clone. When set, the specified ref is passed to git clone --branch. Defaults to the repository’s default branch if empty. |
prefilledRepoPath |
string |
No | Pre-fills the sparse checkout path: a directory relative to the repository root, such as modules/vpc. When set, only that directory is checked out, plus the loose files above it such as a top-level README.md. Empty or . clones the whole repository. See Sparse checkout. |
prefilledLocalPath |
string |
No | Pre-fills the local path (relative to the current working directory) where files will be cloned. Defaults to the repository name if empty. |
showFileTree |
boolean |
No | Whether to show the cloned repository’s file tree in the workspace panel after cloning. Defaults to true. When enabled, the All files and Changed files tabs display the cloned files and any later modifications. |
source |
'clone' | 'local' |
No | Which source the block starts on: clone a remote repo, or use an existing local checkout. Defaults to local when prefilledRepoDir is set, otherwise clone. |
hideSourceSelect |
boolean |
No | Hides the source picker and locks the block to source. Defaults to false. |
prefilledRepoDir |
string |
No | Pre-fills the local checkout directory. Any directory inside the checkout works, because the repository root is resolved from it. |
Ref selection
Section titled “Ref selection”The “Ref” field lets users specify a branch or tag to clone in place of the default branch. There are two ways to set it:
-
GitHub browser. When a GitHub token is available and a repo is selected in the GitHub browser, a searchable “Ref” dropdown appears listing all branches and tags in that repo, with the default branch marked by a “default” badge. Picking a repo in the browser clears the “Ref” field and then selects that repo’s default branch (a repo with no commits yet has none, so the field stays empty). The repo the browser opens on from
prefilledUrlkeepsprefilledRef. -
Text input. The “Ref” field below the GitHub browser accepts any branch or tag name directly, independent of GitHub authentication. Use the
prefilledRefprop to set this in advance.
The ref is passed to git clone --branch, which accepts both branch names and tag names.
File workspace integration
Section titled “File workspace integration”When showFileTree is true (the default), the GitClone block registers the cloned repository with the workspace panel. After a successful clone:
- The All files tab shows the full file tree of the cloned repository. Click any file to view its contents.
- The Changed files tab shows a diff view, in the style of a GitHub pull request, of any files modified after cloning, for example by Command or Template blocks.
- If multiple
<GitClone>blocks are used in a single runbook, a dropdown in the workspace header lets the user switch between repositories.
Set showFileTree={false} to keep the cloned repository out of the workspace panel, for example for a helper repository the user doesn’t need to browse.
A local checkout registers with the workspace the same way. The Changed files tab then also shows any uncommitted changes the checkout already had.
Repositories with no commits
Section titled “Repositories with no commits”A repository that was created but never pushed to has no branches. No later block can open a pull request against it, because the base branch a pull request needs does not exist. The provider rejects the request as invalid, and only after the runbook has committed and pushed its work.
GitClone detects this case for both sources. When the repo has no commits, the block:
- renders in the warning color,
- withholds its outputs (including
clone_path) and does not register the repository with the workspace, so blocks that depend on it stay blocked, - offers a Create default branch button that pushes a single empty commit to the branch the remote advertises as its default. The name is editable before you press it.
Once the branch exists, the block releases its outputs and registers the workspace as it does for a repository that already had commits, and the runbook continues.
The seeded commit is empty. It gives the default branch something to point at, so the branch the runbook pushes later shares an ancestor with it and opens as a reviewable diff. Files already written into the work tree are left untracked.
Accepted git URL formats
Section titled “Accepted git URL formats”| Format | Example | Notes |
|---|---|---|
| HTTPS | https://github.com/org/repo.git |
Recommended. The token is used for URLs on the authenticated GitHub host. |
| HTTPS (no .git) | https://github.com/org/repo |
Also works without the .git suffix. |
| Any host | https://gitlab.com/org/repo.git |
Works with any git hosting provider. |
| SSH | git@github.com:org/repo.git |
Token auth does not apply to SSH URLs. Use HTTPS for token-based auth. |
| SSH (other user) | gitlab@gitlab.example.com:group/repo.git |
Any SSH user works, for self-managed instances whose SSH user isn’t git. |
| SSH, bracketed host | git@[2001:db8::1]:org/repo.git, git@[git.example.com:2222]:org/repo.git |
As in git, an IPv6 address, or a host with a non-default SSH port, goes in brackets. Without brackets, the text after the colon is always the repository path. |
GitHub authentication
Section titled “GitHub authentication”The GitClone block resolves GitHub credentials in this order:
githubAuthId. If set, the block uses theGITHUB_TOKENfrom the referenced GitHubAuth block’s outputs, for the host that block authenticated to.- The session environment. The block looks for a GitHub token bound to the host (see environment variables and hosts).
- No token. The “Browse GitHub repositories” section is hidden. The user can still clone public repos or use SSH URLs.
When a GitHub token is available and the user enters an HTTPS URL on the host that token belongs to, Runbooks authenticates the clone with the token.
GitHub Enterprise
Section titled “GitHub Enterprise”GitClone follows the GitHub host of the linked auth block (its GITHUB_HOST output, github.com by default). When the auth block authenticated to a GitHub Enterprise Server host such as github.example.com, or a GHE.com tenant such as acme.ghe.com:
- The Browse GitHub repositories dropdown lists organizations, repositories, and refs from that host’s API.
- Repositories picked in the browser are cloned from
https://<host>/<org>/<repo>, and the URL placeholder shows that host. - The token is only injected into clone URLs on that same host. A URL on any other host (including
github.com) is cloned without it.
<GitHubAuth id="gh-auth" title="Connect to GitHub Enterprise" host="github.example.com"/>
<GitClone id="clone-repo" githubAuthId="gh-auth" title="Clone a Repo" prefilledUrl="https://github.example.com/platform/infrastructure-live"/>A prefilledUrl on github.com, a *.ghe.com tenant, or the auth block’s host is recognized as a GitHub repository, so its organization and repository are pre-selected in the browser.
The token is passed to git only for the clone itself (through the environment, which requires git 2.31 or later), so it is never saved in the checkout’s .git/config or shown as part of its remote URL. A script that later runs git pull, git fetch, or git push in the checkout needs its own git credentials, such as a configured credential helper (gh auth setup-git), an SSH remote, or a one-off helper that reads the token from the environment:
git -c credential.helper= \ -c "credential.https://${GITHUB_HOST:-github.com}.helper="'!f() { echo username=x-access-token; echo "password=${GITHUB_TOKEN}"; }; f' \ pullThe helper is scoped to https:// on the token’s own host (GITHUB_HOST, set by the GitHub Auth block), so git never offers the token to another remote or over plain http://. For a GitLab checkout, scope it to your GitLab host, such as credential.https://gitlab.com.helper, and use username=oauth2 and ${GITLAB_TOKEN} in the helper.
Sparse checkout
Section titled “Sparse checkout”Use the prefilledRepoPath prop (or the “Repo Path” input field) to check out only one directory of a large repository:
<GitClone id="clone-vpc-module" title="Clone VPC Module" prefilledUrl="https://github.com/gruntwork-io/terraform-aws-vpc" prefilledRepoPath="modules/vpc-app" prefilledLocalPath="./vpc-module"/>This clones the history without file contents (git clone --filter=blob:none --no-checkout), then checks out the path with a cone-mode git sparse-checkout. File contents are downloaded only for the files that are checked out. Sparse checkout works together with prefilledRef.
Cone mode checks out more than the directory itself. It also includes the files directly inside each directory above it, up to the repository root. For modules/vpc-app, that is everything under modules/vpc-app/, plus the files (but not the subdirectories) in modules/ and at the root, such as a top-level README.md.
The path is relative to the repository root. An absolute path or one containing .. fails the clone, and an empty path or . clones the whole repository.
<GitPullRequest> commits every file that later blocks write in the checkout, including files outside the sparse checkout: new files, and changes to files the repository already has there. Files outside the sparse checkout that no block wrote stay out of the commit, and are not committed as deleted. Staging uses git add --sparse, which needs git 2.34 or later. With an older git, a pull request from a sparse checkout fails with a message that says so.
Custom local path
Section titled “Custom local path”The prefilledLocalPath prop (or the “Local Path” input field) controls where files are cloned, relative to the current working directory. If not set, the repository name is used.
The local path must be a subdirectory of the working directory, because “Delete & Clone” removes an existing directory there before cloning. The block shows an error instead of cloning when the path is the working directory itself (for example .), when it leads outside the working directory (including through a symlink), or when it contains the runbook.
The block shows the destination relative to the working directory, both under the “Local Path” field and once the clone or local checkout completes. Hover over the path to see the absolute path. The copy button next to it copies the absolute path. A local checkout outside the working directory has no shorter form, so it is shown by its absolute path.
Environment variables
Section titled “Environment variables”When a <GitClone> block registers a repository, Runbooks sets the $REPO_FILES environment variable for later Command and Check blocks. It points to the repository’s local path.
#!/bin/bash# In a Command or Check script after GitCloneecho "Cloned repo is at: $REPO_FILES"
# Modify files directly in the cloned repoecho "new_setting = true" >> "$REPO_FILES/config.hcl"Template and TemplateInline blocks can also write directly into the cloned repository by setting target="worktree":
<Template id="new-module" path="templates/module" target="worktree" />Block outputs
Section titled “Block outputs”After a successful clone, the GitClone block produces these outputs:
| Output | Description | Example |
|---|---|---|
clone_path |
Absolute path where files were cloned | /Users/josh/Code/my-repo |
repo_owner |
The organization or user that owns the repo, parsed from the repository URL | acme-corp |
repo_name |
The repository name, parsed from the repository URL | infrastructure-live |
org_id |
GitHub numeric ID of the owning org or user. Only for GitHub repositories, when a GitHub token is available | 12345678 |
repo_id |
GitHub numeric ID of the repository. Only for GitHub repositories, when a GitHub token is available | 87654321 |
repo_owner and repo_name are omitted when the URL can’t be parsed into an owner and a name. The numeric IDs don’t change when a repository is renamed or transferred.
For a local checkout, clone_path is the repository root the user selected, and repo_owner and repo_name come from its remote, origin when present, otherwise whichever remote the checkout has. They are omitted when the repo has no remote, and so are org_id and repo_id, which are looked up from the owner and name.
Because org_id and repo_id (and, for a checkout without a remote, repo_owner and repo_name) can be missing, read them behind a hasKey guard. Otherwise a block that references them waits until they exist, which without a GitHub token is never. See Outputs a block emits only sometimes.
{{ if hasKey .outputs.clone_repo "org_id" }}--org-id {{ .outputs.clone_repo.org_id }}{{ end }}Reference outputs in later blocks with template expressions:
<Command id="list-files" title="List Cloned Files" command='ls -la "{{ .outputs.clone_repo.clone_path }}"'/>Cancelling and starting over
Section titled “Cancelling and starting over”Cancel stops the running git process. A cancelled clone produces no outputs and is not added to the workspace. Once git has exited, the block removes the directory the clone created, including a sparse checkout stopped partway and a checkout that git had already finished. The block shows Cancelling… until that is done, or for at most about ten seconds, and then offers Clone again.
The block only removes a directory that the clone created. Delete & Clone deletes the old directory before the clone starts, so that directory is gone either way.
A directory can still be left behind. A cancel that arrives just as the clone completes is too late to undo it. The checkout stays and, as after any completed clone, $REPO_FILES may point at it. A directory that can’t be removed also stays, as can happen on Windows while a process still has a file in it open. Cloning to the same path again offers Delete & Clone to replace it.
Clone again (or Stop using this repo for a local checkout), next to the result’s heading, withdraws the block’s outputs and takes the repository out of the workspace panel until the next clone or checkout completes. Nothing on disk changes. For a local checkout, the block returns to its form with the same directory filled in, so the user can use it again or pick another one. Blocks that read this block’s outputs wait for that next clone rather than using the previous repository’s values. <GitPullRequest> stops targeting the previous repository too. It waits, or uses the repository of another <GitClone> block in the runbook until this one completes again. A repository with no commits chosen next is held back as described in Repositories with no commits.
$REPO_FILES and target="worktree" writes are not held back. When no other <GitClone> block has a repository in the workspace, they keep pointing at the previous repository until the next clone or checkout completes.
View logs
Section titled “View logs”The GitClone block has a collapsible View Logs section, like the Command and Check blocks. It streams the git clone output during the clone, including progress, transfer statistics, and error details.
Example: full workflow
Section titled “Example: full workflow”<GitHubAuth id="gh-auth" title="Authenticate to GitHub"/>
<GitClone id="clone-infra" githubAuthId="gh-auth" title="Clone Infrastructure Repo" description="Clone the infrastructure repository to make changes" prefilledUrl="https://github.com/acme-corp/infrastructure-live" prefilledRef="release/v2" prefilledLocalPath="./infra"/>
<Command id="apply-changes" githubAuthId="gh-auth" title="Apply OpenTofu Changes" command='cd "{{ .outputs.clone_infra.clone_path }}" && tofu apply -auto-approve'/>