git¶
git keeps a checkout of a git repository at a revision: a tag, a branch
or a commit. The first apply clones the repository; later ones move the
checkout when the revision points somewhere else, such as a branch that
got new commits. Use it to deploy an application or a site from its
repository, or to keep a tool's source on a machine.
New in 0.2.0
Minimal example¶
package "git"
git "/opt/sadame", repository: "https://github.com/enderkus/sadame.git", revision: "v0.1.0"
Options¶
| Option | Type | Default | Description |
|---|---|---|---|
repository |
String | required | The URL to clone, as git clone takes it: HTTPS, SSH (git@github.com:example/app.git) or a local path. |
revision |
String | the remote's default branch | A tag, a branch or a full 40-character commit. |
user |
String | root | Run every git command as this user (through su), so the checkout belongs to them and their SSH keys and git configuration apply. |
state |
:present or :absent |
:present |
:absent removes the checkout with rm -rf. |
notifies |
[:action, "type[name]"], optionally with :immediately, or a list of them |
none | Actions to run on other resources when this one changes. See Notifications. |
subscribes |
[:action, "type[name]"], optionally with :immediately, or a list of them |
none | Actions to run on this resource when another one changes. |
tags |
Symbol, String, or an Array of them | none | Tags for running part of a recipe with --tags and --skip-tags. See Tags. |
How it works¶
- plan asks the remote which commit the revision names (
git ls-remote; tags first, then branches, as git resolves a name) and compares it with the checkout'sHEAD. A full commit needs no remote. This is whyplananddriftneed network access to the repository. - apply clones with
git clone --no-checkout, or fetches into an existing checkout, then runsgit checkout --force --detach COMMIT. The checkout is on that commit, not on a branch. - A checkout whose
originURL differs fromrepositorygets the new URL (git remote set-url) and is fetched from there. - An empty directory, such as one a directory resource created for the user, is cloned into. A directory with other files in it is an error.
git must be installed: declare package "git" before. On a machine where
it is not installed yet, plan shows the revision as you wrote it; apply
resolves it once the package is in.
Git never asks for a password or passphrase during a run
(GIT_TERMINAL_PROMPT=0). Private repositories need credentials that work
without a prompt, such as a deploy key in the user's ~/.ssh and the
server's host key in their ~/.ssh/known_hosts.
Scenarios¶
# The sadame source at its 0.1.0 tag, cloned by a deploy user who owns the
# files. Once the checkout is at the tag, apply has nothing to do; a new
# revision moves it.
package "git"
package "shadow" if platform.family == "alpine" # useradd, for the user resource
user "deploy", shell: "/bin/sh"
directory "/srv/sadame", owner: "deploy", mode: "0755"
git "/srv/sadame",
repository: "https://github.com/enderkus/sadame.git",
revision: "v0.1.0",
user: "deploy"
A tagged release, cloned by a deploy user¶
$ sudo sadame apply examples/resources/git
sadame 0.5.1 apply on local (Debian GNU/Linux 12 (bookworm))
changed package[git]
state: absent -> installed
changed user[deploy]
state: absent -> present
shell: /bin/sh
changed directory[/srv/sadame]
state: absent -> present
mode: 0755
owner: deploy
changed git[/srv/sadame]
state: absent -> present
repository: https://github.com/enderkus/sadame.git
revision: d082e432ecc99ef03cf8f30fa4ecebb80defb5c3
Summary
changed 4 package[git]
user[deploy]
directory[/srv/sadame]
git[/srv/sadame]
unchanged 0
failed 0
skipped 0
notified 0
Finished in 36.67s.
$ sudo sadame plan examples/resources/git
sadame 0.5.1 plan on local (Debian GNU/Linux 12 (bookworm))
Plan: 0 to create, 0 to update, 0 to remove, 0 to run, 4 unchanged.
$ sudo -u deploy git -C /srv/sadame describe --tags
v0.1.0
Following a branch, and restarting on a new commit¶
With a branch as the revision, every apply moves the checkout to the branch's latest commit, and a notification restarts the application only when it moved:
git "/srv/app",
repository: "https://github.com/example/app.git",
revision: "main",
user: "deploy",
notifies: [:restart, "service[app]"]
Pin a tag or a commit instead when every server must run the same code no matter when it was last applied.
Common mistakes¶
- Local changes in the checkout. Moving the checkout uses
checkout --force, which discards changes to tracked files. Files git does not track, such as uploads or a.env, are kept. Keep anything that must survive outside the checkout. - Credentials that need a prompt. A private HTTPS repository without
stored credentials, or an SSH host key that is not in
known_hosts, fails instead of waiting for an answer that never comes. - The wrong user for the key. Without
user:, git runs as root and uses root's~/.ssh. Withuser: "deploy", the key must be deploy's. - Submodules. They are not cloned or updated. Run
git submodule update --initfrom an exec resource that thegitresource notifies.