Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support tagged releases in Travis, Ansible #656

Merged
merged 1 commit into from
Dec 28, 2017

Conversation

ddohler
Copy link
Contributor

@ddohler ddohler commented Dec 19, 2017

Overview

This configures Travis to deploy Docker images with tags matching
the built tag on the master branch. It also adds an Ansible variable
called app_version that can be used to specify which Docker image
gets pulled onto host machines.

The general scheme here is as follows: Previously, merges to develop would deploy Docker images with the latest tag, and all deployments of DRIVER currently are hard-coded to pull and run the latest image. Merges to master had essentially no effect. Now, merges to develop continue to behave the same way, but adding new tags to master also deploys images which are tagged to match the git tag. In this way, we can have deployments that are pinned to specific versions which will be unaffected by subsequent merges to master.

Tagged images can be pulled and run by our deployment scripts by specifying the app_version parameter in group_vars. If app_version is development, then the latest docker tag will be pulled. Otherwise, the value of app_version will be used. app_version is ignored in Vagrant because there we build Docker images based on the application source, rather than pulling from Quay.

Because the behavior of merging to develop is unchanged, this should be backwards-compatible with existing deployments (although I don't think we were relying on this specific behavior anyway).

Testing instructions

  • This isn't easily testable locally since it affects production deployments, but local provisioning should still work.
  • In order to fully test this, we will need to:
    • Merge this
    • Cut a 1.0 (or some other number) release to master
    • Confirm that we get properly tagged images in quay.
    • Attempt to deploy or update one of our instances with the new version number and confirm that it succeeds.

Notes

  • This still doesn't support forks because only tags to master result in new docker images. This is by design in order to be conservative about how much fragmentation we encourage in the ecosystem until we have more people using this in production. If it becomes necessary in the future, it's easy to remove this restriction; it should be as simple as changing branch: master in .travis.yml to all_branches: true. This would then deploy images for all tags, regardless of the branch, which would in theory allow us to run several parallel branches with very different features (e.g. master-br, master-ph, master-sa, etc.).
  • The 1.0.0 placeholder in all.example should be changed to the actual first version number we want to use before we merge to master.
  • I think that these Travis changes should be adaptable to the other deployment options we have been considering, such as whether to switch to a docker-compose based setup for easier local development.

Copy link
Member

@kshepard kshepard left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good, and I think will work, logically. I was able to provision locally, but a test deployment will need to be done after merging to fully verify.

- name: Build application Docker image
command: >
docker build
-f {{ root_app_dir }}/Dockerfile.development
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is Dockerfile.development no longer used? If so, we should remove it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, I see a reference to driver-app:latest a few lines down (line 25), that may need to be modified, but I'm not certain.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I think it needs to reference docker_image_tag.

on:
repo: WorldBank-Transport/DRIVER
branch: master
tags: true
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This may lead to two deployments that race, at least if we use git-flow. I think that the completion of a release branch will trigger a build for the merge into master, but also a build for the tagged commit.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My understanding from the docs is that branch and tags are AND-ed together such that a build is only kicked off if it satisfies both conditions:

When all conditions specified in the on: section are met, your build will deploy.

https://docs.travis-ci.com/user/deployment#Conditional-Releases-with-on%3A

But I have no experience with this aspect of travis so it's definitely possible that that's not quite how it works.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm. This may be true then. I was basing my understanding off of visually seeing builds get triggered for master and tagged commits whenever a release gets finalized (merges into master, develop, and tagged commit). It is possible that at the end of a build it ANDs these conditions together to make a decision.

docker push "quay.io/azavea/driver-${image}:${TRAVIS_COMMIT:0:7}"
docker tag "quay.io/azavea/driver-${image}:${TRAVIS_COMMIT:0:7}" "quay.io/azavea/driver-${image}:latest"
docker push "quay.io/azavea/driver-${image}:latest"
docker push "quay.io/azavea/driver-${image}:${TRAVIS_TAG}"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that if we remove on: master above, this will work. Otherwise, I think the TRAVIS_TAG environment variable will be unset when a build is triggered due to changes to master.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See above; my understanding from the docs is that tags: true will prevent this from running if TRAVIS_TAG is unset.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, this seems to back that up too:

tags: true: deployment is triggered if and only if $TRAVIS_TAG is set. Depending on your workflow, you may set $TRAVIS_TAG explicitly, even if this is a non-tag build when it was initiated. This causes the branch condition to be ignored.

@@ -28,9 +28,11 @@ Each of these servers also includes:

## Deploying updates

Deploying updates to production is done using [Ansible](https://www.ansible.com/) (version must be at minimum 1.8). An `ansible-playbook` command is run, which uses the local configuration of the application files in the `deployment` directory to deploy updates to the remote servers. It is not necessary to have the application running locally, but it is necessary to have the latest source code, so make sure to pull down the latest version via `git pull`. In addition to the latest source code, there are four files not checked in to the repository that are needed in order to successfully deploy. These files are as follows
Deploying updates to production is done using [Ansible](https://www.ansible.com/) (version must be at minimum 1.8). An `ansible-playbook` command is run, which uses the local configuration of the application files in the `deployment` directory to deploy updates to the remote servers. It is not necessary to have the application running locally, but it is necessary to have the source code for the version you want to deploy, so make sure to pull down the latest version via `git pull` and then `git checkout tags/<version>. In addition to the latest source code, there are four files not checked in to the repository that are needed in order to successfully deploy. These files are as follows
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that there is a missing backtick toward the bottom of this paragraph:

...so make sure to pull down the latest version via git pull and then git checkout tags/<version>. In a...

- name: Build application Docker image
command: >
docker build
-f {{ root_app_dir }}/Dockerfile.development
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I think it needs to reference docker_image_tag.

@@ -9,6 +12,8 @@ production: "{{ 'production' in group_names }}"
docker_version: "1.10.*"
docker_py_version: "1.2.3"
docker_options: "--storage-driver=aufs"
# meta-variable used to translate app_version into docker container tag
docker_image_tag: "{% if app_version == 'development' %}latest{% else %}{{app_version}}{% endif %}"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it expected that app_version will always be development when you're developing locally?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No; app_version is ignored completely if developing locally. I'll make that clearer in the comment up top.

This configures Travis to deploy Docker containers with tags matching
the built tag on the master branch. It also adds an Ansible variable
called `app_version` that can be used to specify which Docker container
gets deployed when running production deployments. In development, tags
are not used, only `latest` is used.
@ddohler ddohler force-pushed the feature/versioned-containers branch from ba6bdf2 to 327cefa Compare December 21, 2017 02:51
@ddohler
Copy link
Contributor Author

ddohler commented Dec 21, 2017

Thanks for the comments; they made me realize that I hadn't fully thought through how this would interact with local development (e.g. scripts/grunt.sh). I've modified things so that app_version truly has no effect in development, which allows things like scripts.grunt.sh and the Docker image Makefile to remain unchanged. The production deployment approach hasn't changed. @kshepard this might be worth another once-over, but should be basically ready to go, I think, so feel free to merge since I'll be out for the next few days.

@kshepard
Copy link
Member

Cool, this looks good, I'll merge it.

@kshepard kshepard merged commit cc9b102 into develop Dec 28, 2017
@kshepard kshepard deleted the feature/versioned-containers branch December 28, 2017 17:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants