Skip to content
Author with AI

<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.

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"
/>

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"
/>

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.

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.

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:

  1. 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 prefilledUrl keeps prefilledRef.

  2. Text input. The “Ref” field below the GitHub browser accepts any branch or tag name directly, independent of GitHub authentication. Use the prefilledRef prop to set this in advance.

The ref is passed to git clone --branch, which accepts both branch names and tag names.

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.

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.

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.

The GitClone block resolves GitHub credentials in this order:

  1. githubAuthId. If set, the block uses the GITHUB_TOKEN from the referenced GitHubAuth block’s outputs, for the host that block authenticated to.
  2. The session environment. The block looks for a GitHub token bound to the host (see environment variables and hosts).
  3. 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.

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:

Terminal window
git -c credential.helper= \
-c "credential.https://${GITHUB_HOST:-github.com}.helper="'!f() { echo username=x-access-token; echo "password=${GITHUB_TOKEN}"; }; f' \
pull

The 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.

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.

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.

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 GitClone
echo "Cloned repo is at: $REPO_FILES"
# Modify files directly in the cloned repo
echo "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" />

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 }}"'
/>

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.

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.

<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'
/>