<p>The updated deploy script in the question supports the following workflow (and requires this <a href="https://github.com/mayaculpa/veleda/blob/master/server_setup.md" rel="nofollow noreferrer">server setup</a>):</p>

<ol>
<li>Create a feature branch and push commits to it</li>
<li>Each push deploys the code to the staging server</li>
<li>Review the code with merge request (feature branch --> master)</li>
<li>After merging to master, create a new merge request (master --> production)</li>
</ol>

<p>Due to Github merge request errata, I rebase when merging to master but normal merges when merging to production. The reason behind this is that Github <a href="https://help.github.com/articles/about-pull-request-merges/" rel="nofollow noreferrer">creates new commits</a> (different SHA1) when rebasing.</p>

<blockquote>
  <p>The rebase and merge behavior on GitHub deviates slightly from git
  rebase. Rebase and merge on GitHub will always update the committer
  information and create new commit SHAs, whereas git rebase outside of
  GitHub does not change the committer information when the rebase
  happens on top of an ancestor commit.</p>
</blockquote>

<p>The main difference with this workflow to 030's answer is that a <em>production</em> branch is used instead of tags.</p>

<p>For bonus points use <em>staging</em> <a href="https://letsencrypt.org/docs/staging-environment/" rel="nofollow noreferrer">SSL certificates</a> from Let's Encrypt on your staging server. To enable it while using a <a href="https://github.com/JrCs/docker-letsencrypt-nginx-proxy-companion" rel="nofollow noreferrer">reverse proxy</a> in Docker, set <code>LETSENCRYPT_TEST=true</code></p>

CC BY-SA 3.0
2018-03-24T08:39:52.703Z
2018-03-24T08:39:52.703Z
Moritz
<p>One could use conditional builds <a href="https://docs.travis-ci.com/user/conditional-builds-stages-jobs/" rel="nofollow noreferrer">https://docs.travis-ci.com/user/conditional-builds-stages-jobs/</a></p>

<p>If code is merged into master one could decide to deploy code to production, but I personally prefer a human intervention by a Product Owner.</p>

<blockquote>
<pre><code>jobs:
  include:
      if: branch = master
</code></pre>
</blockquote>

<p>or</p>

<blockquote>
<pre><code>stages:
  - name: deploy
    # require the branch name to be master
    if: branch = master
</code></pre>
</blockquote>

<p>At other projects I preferred to deploy only tags to enforce the git flow (tags should be created otherwise no deployment to production).</p>

<blockquote>
<pre><code>stages:
  - name: deploy
    # require the tag name to match a regular expression
    if: tag =~ ^v1
</code></pre>
</blockquote>

<p>One could also try (I did not try it yet) whether the <code>if</code> works in combination with script sections:</p>

<p><a href="https://github.com/030/ansible-firefox/blob/master/.travis.yml" rel="nofollow noreferrer">https://github.com/030/ansible-firefox/blob/master/.travis.yml</a></p>

<p>Last remark: I would avoid creating such scripts (the ones you included in the question) as most CI tools contain condition checks.</p>

CC BY-SA 3.0
2018-03-18T14:30:01.107Z
In my case I decided to add another long-lived branch, production, and only after creating a merge request to that branch is it deployed to the production server. This means that changes can be reviewed on the feature branches without pushing to production. This was the case when the master branch was equivalent to the version on the production server.
Moritz
CC BY-SA 4.0
2018-07-17T11:58:32.183Z
If you use this method you need to use add a type clause to the condition if you don't want random pull requests to master to cause a deploy. E.g. `if: branch = master AND type = push`
Ryan Crichton
CC BY-SA 3.0
2018-03-16T17:38:06.857Z
2018-03-16T17:38:06.857Z
030
<p>I currently have continuous deployment set up with a Travis CI job. All pushes are sent to the staging server and merges to the master to the production server. The problem is that the deployment to the production server is done before the merge is accepted. The continuous integration tests have to all pass, but the deployment occurs before manual code review is done.</p>

<p>The question is, what is a lightweight method to ensure that a deployment to the production server only takes place after the merge request has been accepted?</p>

<p>As a reference, the following code is used for deployment:</p>

<pre><code>#!/bin/bash

# exit with nonzero exit code if anything fails
set -e

# Add the SSH login key
chmod 600 veleda-deploy-key
mv veleda-deploy-key ~/.ssh/id_rsa

# Register the Veleda staging and production server SSH keys
echo '|1|BqdQKtUnA/AtCT/p2M7wgMq3wlY=|lH39cRtAE64wd6EG3ry2J9ewXic= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBH3antqwy3D4NVVfHQX3SQc/g4wl/SAVC9w9QEry7hhQmB0SJIprwNAq8Hy2DzVCS7kTj/q7fCiiL7oAznrax+0=' &gt;&gt; $HOME/.ssh/known_hosts
echo '|1|+Z7oOsZ+zdL6u8o8VSWp+bRzd2g=|XMw2HyJIHoekOYlJYw1n75plL2E= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBCJ/fa/mr577/qCuRXqUNccfmhpUtmi46LSyE7nDbOgxv8kZFs7yQ/sh6TM5npR+ZIbe9I0qmdvA+cE1QfvN21E=' &gt;&gt; $HOME/.ssh/known_hosts

# Select the remote to push to depending on the branch
if [ $TRAVIS_BRANCH != 'production' ] ; then
    echo "Pushing to staging"
    export REMOTE=staging.veleda.io
else
    echo "Pushing to production"
    export REMOTE=veleda.io
fi

# Push to the remote server
git remote add deploy "deploy@$REMOTE:/home/deploy/repo/"
git push -f deploy $TRAVIS_BRANCH

# Unpack and update the Docker services
ssh -t deploy@"$REMOTE" "\
    mkdir -p veleda &amp;&amp;
    git --work-tree=./veleda --git-dir=./repo checkout -f $TRAVIS_BRANCH &amp;&amp;
    cd veleda &amp;&amp;
    ./start.sh"
</code></pre>

CC BY-SA 3.0
2018-03-15T22:43:40.557Z
IMHO the code review (and all other steps requiring human intervention) should be plugged into the pipeline somewhere before the commit to master stage to reduce head-of-the-line blocking for the rest of the team.
Dan Cornilescu
CC BY-SA 3.0
2018-03-15T22:52:30.000Z
Do you mean like feature branches? The review process happens during the pull request
Moritz
CC BY-SA 3.0
2018-03-15T22:57:40.127Z
I don't favour feature branches myself, but yes, at pull request - which I suppose shouldn't proceed with the commit until the review is approved, right?
Dan Cornilescu
CC BY-SA 3.0
2018-03-15T23:05:06.393Z
Let me verify that again
Moritz
CC BY-SA 3.0
2018-03-19T11:34:32.687Z
Moritz how about making your comment (on the answer) into a self-answer? For posterity?
Bookeater
<continuous-deployment><github><travis-ci>
Deploy to server after merge to master branch
Moritz
# Deploy to server after merge to master branch

(Asked by: username_0 on 2018-03-15)

I currently have continuous deployment set up with a Travis CI job. All pushes are sent to the staging server and merges to the master to the production server. The problem is that the deployment to the production server is done before the merge is accepted. The continuous integration tests have to all pass, but the deployment occurs before manual code review is done.
The question is, what is a lightweight method to ensure that a deployment to the production server only takes place after the merge request has been accepted?
As a reference, the following code is used for deployment:
#!/bin/bash

# exit with nonzero exit code if anything fails
set -e

# Add the SSH login key
chmod 600 veleda-deploy-key
mv veleda-deploy-key ~/.ssh/id_rsa

# Register the Veleda staging and production server SSH keys
echo '|1|BqdQKtUnA/AtCT/p2M7wgMq3wlY=|lH39cRtAE64wd6EG3ry2J9ewXic= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBH3antqwy3D4NVVfHQX3SQc/g4wl/SAVC9w9QEry7hhQmB0SJIprwNAq8Hy2DzVCS7kTj/q7fCiiL7oAznrax+0=' >> $HOME/.ssh/known_hosts
echo '|1|+Z7oOsZ+zdL6u8o8VSWp+bRzd2g=|XMw2HyJIHoekOYlJYw1n75plL2E= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBCJ/fa/mr577/qCuRXqUNccfmhpUtmi46LSyE7nDbOgxv8kZFs7yQ/sh6TM5npR+ZIbe9I0qmdvA+cE1QfvN21E=' >> $HOME/.ssh/known_hosts

# Select the remote to push to depending on the branch
if [ $TRAVIS_BRANCH != 'production' ] ; then
    echo "Pushing to staging"
    export REMOTE=staging.veleda.io
else
    echo "Pushing to production"
    export REMOTE=veleda.io
fi

# Push to the remote server
git remote add deploy "deploy@$REMOTE:/home/deploy/repo/"
git push -f deploy $TRAVIS_BRANCH

# Unpack and update the Docker services
ssh -t deploy@"$REMOTE" "\
    mkdir -p veleda &&
    git --work-tree=./veleda --git-dir=./repo checkout -f $TRAVIS_BRANCH &&
    cd veleda &&
    ./start.sh"

**Tags:** continuous-deployment, github, travis-ci

> **Comments:**
> **username_1**: IMHO the code review (and all other steps requiring human intervention) should be plugged into the pipeline somewhere before the commit to master stage to reduce head-of-the-line blocking for the rest of the team.  
> **username_0**: Do you mean like feature branches? The review process happens during the pull request  
> **username_1**: I don't favour feature branches myself, but yes, at pull request - which I suppose shouldn't proceed with the commit until the review is approved, right?  
> **username_0**: Let me verify that again  
> **username_2**: username_0 how about making your comment (on the answer) into a self-answer? For posterity?  

---

## 2 answers

### Answer by username_3 on 2018-03-16. Score: 4 | Accepted answer

One could use conditional builds https://docs.travis-ci.com/user/conditional-builds-stages-jobs/
If code is merged into master one could decide to deploy code to production, but I personally prefer a human intervention by a Product Owner.

jobs:
  include:
      if: branch = master


or

stages:
  - name: deploy
    # require the branch name to be master
    if: branch = master


At other projects I preferred to deploy only tags to enforce the git flow (tags should be created otherwise no deployment to production).

stages:
  - name: deploy
    # require the tag name to match a regular expression
    if: tag =~ ^v1


One could also try (I did not try it yet) whether the if works in combination with script sections:
https://github.com/username_3/ansible-firefox/blob/master/.travis.yml
Last remark: I would avoid creating such scripts (the ones you included in the question) as most CI tools contain condition checks.

> **Comments:**
> **username_0**: In my case I decided to add another long-lived branch, production, and only after creating a merge request to that branch is it deployed to the production server. This means that changes can be reviewed on the feature branches without pushing to production. This was the case when the master branch was equivalent to the version on the production server.  
> **username_4**: If you use this method you need to use add a type clause to the condition if you don't want random pull requests to master to cause a deploy. E.g. `if: branch = master AND type = push`  

---

### Answer by username_0 on 2018-03-24. Score: 2

The updated deploy script in the question supports the following workflow (and requires this [server setup](https://github.com/mayaculpa/veleda/blob/master/server_setup.md)):

1. Create a feature branch and push commits to it
2. Each push deploys the code to the staging server
3. Review the code with merge request (feature branch --> master)
4. After merging to master, create a new merge request (master --> production)

Due to Github merge request errata, I rebase when merging to master but normal merges when merging to production. The reason behind this is that Github [creates new commits](https://help.github.com/articles/about-pull-request-merges/) (different SHA1) when rebasing.

> The rebase and merge behavior on GitHub deviates slightly from git
> rebase. Rebase and merge on GitHub will always update the committer
> information and create new commit SHAs, whereas git rebase outside of
> GitHub does not change the committer information when the rebase
> happens on top of an ancestor commit.

The main difference with this workflow to username_3's answer is that a *production* branch is used instead of tags.

For bonus points use *staging* [SSL certificates](https://letsencrypt.org/docs/staging-environment/) from Let's Encrypt on your staging server. To enable it while using a [reverse proxy](https://github.com/JrCs/docker-letsencrypt-nginx-proxy-companion) in Docker, set `LETSENCRYPT_TEST=true`


---

