Skip to content
Find file
Fetching contributors…
Cannot retrieve contributors at this time
483 lines (362 sloc) 18.5 KB
NAME
git-deploy - automate the git steps required for a deploying code from a
git repository
SYNOPSIS
git deploy [deploy-options] [action [prefix]] [action-options]
git deploy --man
actions:
start|sync|finish|abort # normal manual rollout sequence (finish is automatic if sync succeeds)
start|release|abort # normal git-production env sequence
hotfix # Roll out the site with a hotfix
revert # revert site to previous rollout (interactive select)
show # show list of tags
show-tag # show the current tag (if it exists)
tag # create a tag for this commit (restricted to certain environments)
log # during a rollout show log of changes since the last rollout
diff # during a rollout show differences between previous rollout
status # show rollout status of current repository
OPTIONS
Use git-deploy --man to see complete set of options and details of use.
--force Force the action, and bypass most sanity checks. Do not use
unless you know what you are doing.
--verbose
Emits progress information to STDERR during processing.
--help Print a brief help message and exits. (You are probably reading
what this outputs right now.)
--man Uses perldoc/man to output far far more than you ever realized
there was to know about using this tool.
OTHER OPTIONS
--show-step
Print out the step log if one exists. If nothing is printed out
then there is no rollout underway.
--date-fmt=FORMAT
Perl strfime() format to use in datestamped tags. Defaults to
'%Y%m%d-%H%M'. Please do not change this wantonly. Various
features of the deploy process expect to be able to parse the
date stamp and require it to be in more or less this format.
--message=STRING
Message to use when creating a tag. Required when creating a new
tag. Since you cant know the name of the newly created tag when
writing the message you can use the special sequence %TAG as a
replacement.
--show-prefix
Print to STDOUT whatever prefix would be used given the current
arguments and then exit. Throw an error if there would be no
prefix.
--to-mail=STRING
Address to use to send announcement mails to. Defaults to
'live@somewhere.com'
--show-deploy-file
Prints to STDOUT the current deploy file if and only if the
commit it contains corresponds to HEAD. Otherwise prints
nothing. Exits immeditately afterward.
--deploy-file-name
Set the deploy file name. If this option is not provided the
deploy file defaults to "./lib/.deploy" if a directory named
"./lib" exists, and otherwise to "./.deploy"
--list
--list-all
Instead of printing out a single tagname for the current commits
tag print out a verbose list of tags, sorted by the date that
they contain in order of most recent to oldest. The output will
be structured like this:
7e25a770901c.. *tag: sheep-20080827-1419
2806eb24c3c2.. tag: cows-20080827-1240
d6af6e1ad6f1.. tag: goats_20080826-1458
889f65216880.. tag: goats_20080826-1034
90318602f8d2.. tag: cows_20080826-1005
6bd340c67bdb.. tag: sheep-20080825-2245
19587c195a8b.. tag: sheep-20080825-2116 -> sheep-20080825-2105
19587c195a8b.. tag: sheep-20080825-2105
The first column is the abbreviated commit SHA1 (abbreviation
can be disabled with the "--long-digest" option), Followed by
either "<space><space>" or by "<space><star>". The starred items
correspond to HEAD. The arrow indicates that there are two
different tags to the same commit, and points to the oldest
equivalent tag. This is then followed by either 'tag:' or
'branch:' (depending on whether "--include-branches" is invoked)
and then the item name. This may then be followed by space and
then an arrow and then a second name, which indicates that the
item is a duplicate and shows the oldest displayed item (undated
items like branches go last in an alphabetic order with some
special exceptions for trunk or master).
When used with just "--list" mode, only starred items
corresponding to HEAD are displayed, --list-all shows unstarred
items that do not correspond to HEAD as well.
--include-branches
Show information about branches as well when in "--list" mode
--long-digest
Show full SHA1's when in "--list" mode.
--ignore-older-than=YYYYMMDD
Totally ignore tags which are from before this date. Defaults to
20080101.
Checking *every* tag to see if it corresponds to HEAD can be
expensive. This options makes it possible to filter old tags by
date to avoid checking them when you know they wont match.
--make-tag
Make a tag. This is the same as the "tag" action except the tag
will not be automatically pushed.
Note: that you cannot use this function in/for all environments.
If you think your environment should be allowed contact the
author.
--no-check-clean
Do not check that the working directory is clean before doing
things.
--no-remote
Skip any actions that involve talking to a remote repository.
--remote-site=STRING
Name of remote site to access when pushing, pulling or fetching.
Defaults to 'origin'.
Using an remote site name of 'none' is the same as using
--no-remote
--remote-branch=STRING
Name of remote branch to access when pushing, pulling or
fetching. Defaults to the current branch just like git pull or
git push would.
Actions
start
Used to start a multi step rollout procedure. Remembers (and if
necessary tags) start position as well as create locks to prevent
two people from doing a procedure at the same time. See "hotfix"
below for rollout out a hotfix on top of a previous rollout tag.
sync
Used to declare that the current commit is ready for sync. At some
point in the future this will automatically call the appropriate
sync command, however currently the sync is done manually as a
separate step.
abort
A command which can be used any time prior to the manual
syncronization step which will automatically rollback the current
state to the start position. Note this is NOT the way to "rollback a
rollout", it is the way to abort a rollout prior to its completion.
I.e. if someone else has started a rollout and gone away you can do:
git-deploy --force abort
And the state of the rollout machine will be reset back to what it
was before they ran "git-deploy start".
Note that the "abort" command used to be called "rollback" but that
term lead to a lot of confusion and we are trying to avoid it going
forward.
finish
Used to declare that the rollout session is finished, push any new
commits or tags, create the final emails of what changed and related
functions.
release
Used in the "two step" rollout process for boxes where there is no
manual syncronization step.
tag Used in the "one step" rollout process to tag a commit and push it
to the remote.
revert
This is used to do an interactive "revert" of the site to a previous
rollout. It combines the steps "start/git reset .../sync/finish"
into one process, with interactive selection of the commit to revert
to. If sync hooks and deploy hooks are provided then they will be
automatically run as normal. If they arent a manual sync/finish is
required.
show-tag
Show the tag for the current commit if there is one.
status
Show the status of the deploy procedure. Can be used to check what
step you are on.
hotfix
Here's how you can do a hotfix rollout. I.e. when you have an
existing rollout tag that you want to apply a hotfix on.
First, instead of "git-deploy start" do:
git-deploy hotfix
That'll start "git-deploy" without doing the normal "git pull"
operation. Then you cherry-pick your hotfix:
git cherry-pick SHA1_OF_HOTFIX
Then note the sha1 of your cherry-picked commit. This is your
"NEW_SHA1"
git --no-pager log -1 --pretty=%H
Then do a:
git pull
Followed by:
git push
To push your hotfix to the Git server. But now you're not at what
you want to roll out, so do:
git reset --hard NEW_SHA1
git checkout -f
This will ensure that you are on your hotfix commit, and that any
git hooks are executed. You should then TEST the code. On a
webserver this normally involves
prodctl restart
and then some manual testing of the relevant web site.
When you are satisfied that things are ok you can do execute the
sync:
git-deploy sync
TODO: The last 3 pull/push/reset steps are busywork that should be
merged into "git-deploy sync".
DESCRIPTION
git deploy provides tools for managing a git based roll out process.
The basic idea is that the process is divided into basically three
stages, each one starting with the execution of this tool.
The steps are as follows:
$ git deploy start
# perfom tests
$ git deploy sync
# perfom syncronization
$ git deploy finish
If there is a problem in general the tool will detect it, and advise you
of what it is and how to deal with it.
This will ensure that tags are created which you can roll back to, and
ensure that they are pushed afterwards, amongst various other things.
git deploy will fetch all tags from the remote repository configured in
the current repository before processing. You can disable this behaviour
by using --no-remote which overrides all remote actions.
In the case of an unclean working directory an error message will be
produced and a git status will be output. Note: This includes untracked
files, which must be either deleted or added to the repositories
.gitignore (which itself must then be committed) before you can proceed
with using git deploy. You can disable this with --no-check.
Additionally git deploy contains a number of utilities for reviewing the
state of the repository from the point of view of the tags it contains.
Specifically "--list" and "--list-all" are good ways of viewing the
rollout history and checking what commit you are on. See the
documentation for these options for details
Git Production Environments
Some environment use a git checkout as their working directory. In this
case the three step rollout is overkill. As a replacement there is a
simpler two step process:
git-deploy start
git-deploy release
If you want to abort you can say:
git-deploy abort
instead. To use this option you need to configure the repository by
setting
git config deploy.can_make_tags true
Deploy Files
A deploy file consists of a set of keys and values followed by a newline
followed by the deployment message use to create the deployment tag. For
instance
commit: 7e25a770901c9b1eb75ad1511580a98acff4ad60
tag: sheep-20080827-1419
deploy-date: 2008-08-27 14:19:58
deployed-from: bountiful.farm.com
deployed-by: rafael
rollout of sheep
<EOF>
If new key/values are added they will always be added before the blank
line.
Deploy Hooks
At various points in the deployment process git-deploy will execute
user-supplied deployment hooks.
The idea of this is to provide a mechanism by which actions and tests
will be automatically executed, and if necessary can prevent the
syncronization from occuring.
Deploy hooks can be specific at the generic level, that is for all
applications, and on an application specific basis.
Structure of the deploy hooks
The pre-deploy framework is expected to reside in the
$GIT_WORK_DIR/deploy directory (i.e. the deploy directory of the
repository that's being rolled out). This directory has the following
tree:
$GIT_WORK_DIR/deploy/ # deploy directory
/apps/ # Directory per application + 'common'
/common/ # deploy scripts that apply to all apps
/$app/ # deploy scripts for a specific $app
/sync/ # sync
/$app.sync
The $app in deploy/{apps,sync}/$app is the server prefix that you'd see
in the rollout tag. E.g. A company might have multiple environments
which they roll out, for instance "sheep", "cows" and "goats". Here is a
practical example of the deployment hooks that might be used in the
"sheep" environment:
$ tree deploy/apps/{sheep,common}/ deploy/sync/
deploy/apps/sheep/
|-- post-pull.010_httpd_configtest.sh
|-- post-pull.020_restart_httpd.sh
|-- pre-pull.010_nobranch_rollout.sh
|-- pre-pull.020_check_that_we_are_in_the_load_balancer.pl
|-- pre-pull.021_take_us_out_of_the_load_balancer.pl
`-- pre-pull.022_check_that_we_are_not_in_the_load_balancer.pl -> pre-pull.020_check_that_we_are_in_the_load_balancer.pl
deploy/apps/common/
|-- pre-sync.001_setup_affiliate_symlink.pl
`-- pre-sync.002_check_permissions.pl
deploy/sync/
|-- sheep.sync
All the hooks in deploy/apps are prefixed by a "phase" in which
"git-deploy" will execute them (e.g. "pre-pull" just before a pull).
During these phases "git-deploy" will "glob" in all the
deploy/apps/{common,$app}/$phase.* hooks and execute them in "sort"
order, first the "common" hooks and then the $app specific hooks. Note
that the hooks MUST have their executable bit set.
Available phase hooks
Currently, these are the hooks that will be executed. These all
correspond to specific git-deploy actions:
* pre-start
The first hook to be executed. Will be run before the deployment tag
is created (but obviously, after we do "git fetch").
* pre-pull
Executed before we update the working tree with "git pull". This is
where hooks that e.g. take the deployment machine out of the load
balancer should be executed.
* post-pull
Just after the pull in the "start" phase.
* pre-sync
Just before we create the tag we're about to sync out and execute
the deploy/sync/$app.sync hook.
* post-sync
After we've synced. Here you could e.g. send custom E-Mails
indicating that the deployment was a success.
* post-rollback
Hooks executed after a rollback, either via "rollback" or "revert".
Most of the time you want to use "post-tree-update" hooks instead,
but this is useful e.g. for putting a staging server back into a
load balancer.
These hooks will be executed in one or more action, depending on some
general condition:
* post-tree-update
Executed after we update the working tree to a new revisions,
whether that's after the "pull" in the "start" phase, after "git
reset --hard" in the "rollback" phase, or after a "revert".
Here's where hooks that e.g. restart the webserver and run any
critical tests (e.g. config tests) should be run.
The exit code from these hooks is ignored in actions like "rollback"
and "revert". We don't want the abort or revert to fail just because
some webserver didn't restart.
Return values
Each script is expected to return a nonzero exit code on failure, and a
zero exit code on success (in other words standard unix shell return
semantics). Any script that "fails" will cause "git-deploy" to abort at
that point.
More granular failure codes are planned in the future. E.g. "failed but
should try again", "failed but should ask the user if trying again" etc.
But this hasn't yet been implemented.
Sync Hooks
A special case for a hook that really should be just a regular phase
hook. But isn't yet because it would have required more major surgery on
"git-deploy" at the time phase hooks were written, as well as access by
the author to all deployment environments (which wasn't the case).
The only notable difference is that there is only one phase hook for
each $app, and it's located in deploy/sync/$app.sync.
Testing code on a single server
For debugging purposes, it can be necessary to have a branch running on
a single server in production. Here's a sequence that can allow you to
do that:
cd /usr/local/git_tree/main
git-deploy hotfix
lb <single host> rollout
git checkout <your branch>
deployme --hosts=<single host> --no-activate --tag=debugging-<date+time>
lb <single host> ok
Check everything works ok on that host, usually logging in through ssh,
then restore it to its former state lb <single host> rollout
git checkout trunk
deployme --no-sync --host=<single host>
lb <single host> ok
git-deploy rollback
config options
deploy.block_file
deploy.can_make_tags
deploy.config_file
deploy.deploy_file
deploy.hook_dir
deploy.mail_tool ( "/usr/sbin/sendmail -f" )
deploy.restrict_umask
deploy.send_mail_on_ACTION
deploy.support_email
deploy.tag_prefix
user.name (Mandatory)
user.email (Mandatory)
Future thoughts: use gitconfig to replace most of the other config or
environment vars.
Jump to Line
Something went wrong with that request. Please try again.