In my company I follow the following workflow. (I think it can be defined a kind of 'Continuous Integration'.)
Workflow:
- We have 3 fixed branches (
staging
/master
/production
) - Every push to
staging
orproduction
automatically deploy to staging/production server.
We use git in the following way:
(suppose I'm working on the new functionality 'A')
- I create a new branch from Master (ex. branch 'A')
- If I want to show my changes to the client I merge A to staging and push it.
- once finish my work on A I merge back A on Master and push master
- to send changes live I merge Master in Production branch and push production
I find quite boring/time consuming to git checkout ...
git pull ..
bla bla every time I have to deploy live/staging my work.
So I have produced the following bash script, the aim is to simplify the process of deploying branch A into a single command deploy.sh live A
#!/bin/bash
function merge() {
SOURCE=1ドル
DEST=2ドル
echo ''
echo "--- Merging $SOURCE with $DEST ---"
echo "--> Checkout $DEST ..."
git checkout $DEST
echo "--> Pull $DEST ..."
git pull --ff-only origin $DEST
if [ $? -ne 0 ]
then
echo "ERROR: Could not PULL"
return 1
fi
echo "--> Merging $SOURCE with $DEST ..."
git merge --ff-only $SOURCE --no-edit # --ff-only trigger errors if merge/pull is not possible
if [ $? -ne 0 ]
then
echo "ERROR: Could not MERGE"
return 1
fi
echo "--> Push $DEST ..."
git push origin $DEST
return 0
}
function deploy() {
MODE=1ドル
SOURCE_BRANCH=2ドル
echo ''
echo "### START ###"
echo ''
echo "--- Pull changes from Master ---"
git checkout $SOURCE_BRANCH
git pull --progress --no-edit --no-stat -v --progress origin master
merge $SOURCE_BRANCH 'staging'
status=$?
if [ $status -ne 0 ]
then
echo "ERROR: STEP 1" >&2
exit 1
fi
if [ $MODE = "live" ]
then
merge $SOURCE_BRANCH 'master'
status=$?
if [ $status -ne 0 ]
then
echo "ERROR: STEP 2"
return 1
fi
merge 'master' 'production'
status=$?
if [ $status -ne 0 ]
then
echo "ERROR: STEP 3"
return 1
fi
fi
echo ''
echo "### END ###"
echo ''
}
MODE=1ドル;
SOURCE_BRANCH=2ドル;
if [ -z "$MODE" -o -z "$SOURCE_BRANCH" ]
then
echo "Usage:"
echo ""
echo "MODE BRANCH_NAME (MODE: live|staging)"
else
if git show-ref --verify --quiet "refs/heads/$SOURCE_BRANCH";
# if [ `git branch --list $SOURCE_BRANCH ` ]
then
deploy $MODE $SOURCE_BRANCH
else
echo ''
echo "Error: Branch $SOURCE_BRANCH not found"
fi
fi
The question:
I'm quite newby both on GIT and BASH scripting. So I would like to know if the above workflow/script is ok ? Any recommendation is welcome. (I'm happy to share this as resource.)
1 Answer 1
Use exit codes directly
Instead of this:
merge $SOURCE_BRANCH 'staging' status=$? if [ $status -ne 0 ] then echo "ERROR: STEP 1" >&2 exit 1 fi
You can use exit codes directly in conditions, like this:
if ! merge $SOURCE_BRANCH 'staging'
then
echo "ERROR: STEP 1" >&2
exit 1
fi
Use it this way everywhere.
Handle errors consistently
The error handling is inconsistent throughout the script:
- Sometimes you
exit 1
, sometimes youreturn 1
in functions. It would be better to do consistently - Sometimes you print the error message on stdout, sometimes on stderr. It would be better to print it consistently on stderr
Style
To print a blank line you can simply echo
without a parameter.
You can drop return 0
as the last statement of a function. The exit code of the last statement will be used as the exit code of the function.
A semicolon is unnecessary at the end of the line.
Long comments at the end of a line are generally hard to read. Move these to the previous line.
The indentation is not consistent. The code inside the functions looks nice, do the same way for the code outside.
Ex. ( edited by @WonderLand)
#!/bin/bash
function merge() {
SOURCE=1ドル
DEST=2ドル
echo
echo "---> Merging $SOURCE with $DEST"
echo
echo "---> ---> Checkout $DEST ..."
git checkout $DEST
echo
echo "---> ---> Pull $DEST ..."
if ! git pull --ff-only origin $DEST
then
exit 1
fi
echo
echo "---> ---> Merging $SOURCE with $DEST ..."
# --ff-only trigger errors if merge/pull is not possible
if ! git merge --ff-only $SOURCE --no-edit
then
exit 1
fi
echo
echo "---> ---> Push $DEST ..."
git push origin $DEST
}
function deploy() {
MODE=1ドル
SOURCE_BRANCH=2ドル
echo
echo "---> Pull changes from Master ..."
if ! git checkout $SOURCE_BRANCH
then
exit 1
fi
git pull --progress --no-edit --no-stat -v --progress origin master
if ! merge $SOURCE_BRANCH 'staging'
then
exit 1
fi
if [ $MODE = "live" ]
then
if ! merge $SOURCE_BRANCH 'master'
then
exit 1
fi
if ! merge 'master' 'production'
then
exit 1
fi
fi
}
MODE=1ドル
SOURCE_BRANCH=2ドル
if [ -z "$MODE" -o -z "$SOURCE_BRANCH" ]
then
echo "Usage:"
echo ""
echo "MODE BRANCH_NAME (MODE: live|staging)"
else
if git show-ref --verify --quiet "refs/heads/$SOURCE_BRANCH"
then
echo
echo "### START ###"
echo
deploy $MODE $SOURCE_BRANCH
echo
echo "### END ###"
echo
else
echo
echo "Error: Branch $SOURCE_BRANCH not found"
fi
fi