git
Owns a git working tree on a remote host. Shells out to the system git binary over SSH — there is no libgit2 dependency. The provider takes no configuration block.
Kinds
git_repo
Clones a remote repository to a fixed path and keeps it pinned to a given ref. Producer kind: state captures the resolved commit_sha, which is what other steps (a docker_image rebuild, a ssh_exec post-deploy) can observe drift against.
resource "git_repo" "app" {
host = host.primary.addr
path = "/srv/app"
url = "https://github.com/example/app.git"
ref = "main"
}
| attr | required | type | default | description |
|---|---|---|---|---|
host | yes | string | — | SSH target. |
path | yes | string | — | Absolute destination path on the remote host. The directory is created by git clone. |
url | yes | string | — | Remote URL. Passed verbatim to git clone. Authentication uses whatever's on the host (~/.git-credentials, deploy key in ~/.ssh, etc.) — stratum does not inject credentials. |
ref | yes | string | — | A branch name, a tag, or a full 40-character lowercase hex SHA. See Refs below for the dispatch rules. |
depth | no | number | none | Shallow-clone depth, passed to --depth. Only honored when ref is a branch or tag; full SHAs always clone full (--depth + bare SHA is fragile). |
State shape
{
"host": "root@192.0.2.10",
"path": "/srv/app",
"url": "https://github.com/example/app.git",
"ref": "main",
"depth": null,
"commit_sha": "bfb77a6c1d808e04..."
}
commit_sha is the output of git rev-parse HEAD after the create / update. Stratum re-reads this on --refresh; a mismatch between the recorded SHA and what ref currently resolves to on the remote becomes drift, which update resolves with a fetch + reset.
Refs
The ref value dispatches at command-build time:
- Branch or tag (anything not matching a full SHA shape) →
git clone --branch <ref> [--depth N] <url> <path>. Updates rungit fetch origin && git reset --hard origin/<ref>. - Full 40-character hex SHA →
git clone <url> <path> && git -C <path> checkout <sha>. The--branchflag does not accept bare SHAs, so the clone-then-checkout shape is required.--depthis intentionally ignored for SHA refs. Updates rungit fetch origin && git checkout <sha>.
A short SHA (bfb77a6) is treated as a branch name — git will reject it as a missing branch at clone time. Use the full 40-char form if you need SHA-pinned behavior.
Recreate vs in-place update
| change | action |
|---|---|
url differs | rm -rf <path> then re-clone. State preserves the new url + sha. |
path differs | rm -rf <old-path> then re-clone at the new path. |
ref / depth only | git fetch origin + git reset --hard origin/<ref> (or git checkout <sha>). |
There is no git fetch --depth shrink / expand path — depth changes alone do not trigger any work today.
Drift detection
read runs a single-roundtrip probe:
if [ ! -d <path>/.git ]; then echo MISSING;
else printf '%s|' "$(git -C <path> rev-parse HEAD)";
git -C <path> remote get-url origin;
fi
<path>or<path>/.gitmissing →Absent.- Probe output
<sha>|<origin_url>→Present { host, path, url, ref, depth, commit_sha }. Theurlin the observed value is the actual remote URL — if it differs from the desiredurl, the plan flags drift onurland the next apply will re-clone. - Anything else →
Unknownwith the unparsed output.
Apply trace
[git] CLONE git_repo `app` -> root@192.0.2.10:/srv/app (ref=main)
[git] UPDATE git_repo `app` (root@192.0.2.10:/srv/app) ref=main
[git] DELETE git_repo `app` (root@192.0.2.10:/srv/app)
Notes
- Stratum does not manage SSH host keys for git remotes. If the remote is a private git server reached over SSH, the host running stratum's
ssh(the remote host, not your laptop) needs to have already accepted the remote's host key. - Credentials live on the host. For GitHub HTTPS, the common pattern is to drop
~/.git-credentialsvia asystem_secret_filesourcing a personal access token fromsecret { from_env = "GH_PAT" }. git_repodoes not run anything inside the cloned tree (nonpm install, nodocker build). Pair it with adocker_image(using the clone path ascontext) or anssh_execfor post-clone work.