HiveBrain v1.2.0
Get Started
← Back to all entries
patternbashgitModerate

Bash script to simplify Git deployment workflow

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
scriptworkflowsimplifygitdeploymentbash

Problem

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 or production 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

Solution

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 you return 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

Code Snippets

merge $SOURCE_BRANCH 'staging'
status=$?
if [ $status -ne 0 ]
then
  echo "ERROR: STEP 1" >&2
  exit 1
fi
if ! merge $SOURCE_BRANCH 'staging'
then
  echo "ERROR: STEP 1" >&2
  exit 1
fi
#!/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

Context

StackExchange Code Review Q#131281, answer score: 13

Revisions (0)

No revisions yet.