Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Continuous Deployment using GitHub, CircleCI, a...

Continuous Deployment using GitHub, CircleCI, and Heroku

Continuous Deployment workshop slides from Beer City Code 2017 in Grand Rapids, MI.

Sample: https://github.com/jacebrowning/webcalc

Demo: https://webcalc.herokuapp.com/

Jace Browning

June 09, 2017
Tweet

More Decks by Jace Browning

Other Decks in Programming

Transcript

  1. Let’s meet each other • About me • About you

    ◦ Name ◦ Interest in this topic ◦ Operating system • Comfort levels ◦ Programming, Terminals ◦ Version Control, Git, GitHub ▪ Pull Requests (PRs), Code Reviews ◦ Continuous Integration (CI), CircleCI, YAML ◦ Continuous Deployment (CD), Heroku ▪ The Platform, Review Apps, Pipelines, Heroku Flow ◦ Python, Flask, MongoDB http://tiny.cc/beercitycode-slack
  2. Outline for the day • Machine setup ◦ Installation ◦

    Accounts • Start project • Manual deployment to Heroku • Continuous Integration via CircleCI • Continuous Deployment to Heroku • Using GitHub Pull Requests for code review • Provisioning external resources on Heroku • Using Heroku Review Apps to enable manual testing • Advanced topics as time allows
  3. How to use these slides … print(“Hello, world”) … $

    echo “Hello, world!” http://tiny.cc/beercitycode-slides
  4. Install dependencies 1. Git command-line a. Optional: GitHub desktop client

    2. Any code editor a. Recommendation: Atom 3. Heroku CLI 4. Python 3.6 5. Pipenv 6. MongoDB a. Optional: MongoDB client (e.g. Robomongo) Instructions continue on the next slide....
  5. Install dependencies $ git --version $ heroku --version $ python

    --version $ pipenv --version $ mongo --version
  6. Create accounts • GitHub ◦ https://github.com/join • CircleCI (log in

    with GitHub) ◦ https://circleci.com/signup/ • Heroku ◦ https://signup.heroku.com/
  7. Project Overview • “webcalc” ◦ /4/+/5 produces “9” • Technologies

    ◦ Python, virtual environments, pipenv ◦ Flask ◦ MongoDB ◦ Heroku ◦ CircleCI
  8. Initial Flask app 1. Create repository on GitHub 2. Clone

    it to your computer 3. Add a README.md 4. Define requirements in Pipfile 5. Create application file 6. Push files to GitHub Instructions continue on the next slide....
  9. New repository (create new repository on GitHub) $ git clone

    <URL> https://help.github.com/articles/create-a-repo/
  10. New file: README.md # webcalc Demo project for the 2017

    Beer City Code workshop on Continuous Delivery. https://guides.github.com/features/mastering-markdown
  11. New file: Pipfile [[source]] url = "https://pypi.python.org/simple" verify_ssl = true

    [requires] python_version = "3.6" https://github.com/pypa/pipfile#pipfile
  12. New file: webcalc.py from flask import Flask app = Flask(__name__)

    @app.route('/') def index(): return "Hello, world!" if __name__ == '__main__': app.run(debug=True)
  13. Deployment Options • Servers • “Cloud” ◦ Virtual machines ◦

    Containers • Platforms • “Serverless”
  14. Heroku • Developer friendly • First-class language/framework support • Heroku

    CLI • Free tier • On-demand scaling • Add-ons marketplace
  15. Create Heroku app 1. Create new app on Heroku 2.

    Explore each tab 3. Connect app to GitHub repository 4. Attempt deploy
  16. Configure project for Heroku 1. Add gunicorn as a production

    web server 2. Create Procfile 3. Redeploy to Heroku 4. View site Instructions continue on the next slide....
  17. Push files and deploy 1. Commit and push code 2.

    Manually deploy on Heroku 3. View site
  18. Continuous Integration • “Continuous” • “Integration” • Running tests gives

    us confidence in our code • CI services do this automatically
  19. Add tests 1. Install testing tools 2. Run tests (no

    results) 3. Add new test 4. Run tests (results) Instructions continue on the next slide....
  20. Install pytest and run it $ pipenv install --dev pytest

    $ pipenv install --dev pytest-describe $ pipenv install --dev pytest-expecter $ pipenv run pytest $ pipenv lock https://docs.pytest.org
  21. New file: test_webcalc.py import pytest from expecter import expect from

    webcalc import app @pytest.fixture def client(): return app.test_client() def describe_index(): def it_says_hello(client): response = client.get('/') expect(response.data).contains(b"Hello, world!")
  22. CI Services • Types ◦ Self-hosted ◦ Cloud-based • Configurations

    ◦ File-based ◦ Interface-driven • Target audiences ◦ Private teams ◦ Libraries ◦ Build farms ◦ General-purpose
  23. Enable CircleCI 1. Add project to CircleCI 2. Attempt to

    build project 3. Add configuration file 4. Add status badge Instructions continue on the next slide....
  24. New file: circle.yml machine: python: version: 3.6.1 dependencies: pre: -

    pip install pipenv override: - pipenv install --dev test: override: - pipenv run pytest https://circleci.com/docs/1.0/language-python/
  25. Enable Continuous Deployment 1. Enable automatic deploys on Heroku 2.

    Push a bad change to webcalc.py 3. Watch build fail on CircleCI 4. Confirm no deployment on Heroku 5. Fix tests 6. Push again
  26. Benefits of Pull Requests • We don’t always want to

    deploy right away • Team consensus • Code reviews • View CI status for each change • Prioritize changes and detect conflicts
  27. Create a Pull Request 1. Create a new branch 2.

    Add test for new functionality 3. Add new route for calculation 4. Push branch and create PR 5. Add collaborator and request review Instructions continue on the next slide....
  28. Update file: test_webcalc.py … def describe_calc(): def when_plus(client): response =

    client.get('/4/+/5') expect(response.data).contains(b"9") …
  29. Create Pull Request 1. Commit and push changes 2. Open

    Pull Request on GitHub 3. Add a collaborator on the Settings tab 4. Assign them for review https://help.github.com/articles/about-pull-requests/
  30. Review Pull Request 1. Review changes on PR assigned to

    you 2. Approve changes 3. Merge your own PR after review 4. Watch for automatic deploy
  31. Heroku add-ons • First-party: ◦ PostgreSQL ◦ Redis • 3rd-party:

    ◦ Data storage ◦ Monitoring ◦ Logging ◦ Email ◦ Caching ◦ etc.
  32. Load math patterns from MongoDB 1. Create a new branch

    2. Add test for new functionality 3. Load patterns from MongoDB 4. Push branch and create PR 5. Request review then merge PR Instructions continue on the next slide....
  33. Install MongoDB adapter $ git checkout master $ git pull

    $ git checkout -b load-from-db $ pipenv install flask-pymongo --lock
  34. Update file: test_webcalc.py from webcalc import app, mongo @pytest.fixture def

    pattern(): with app.app_context(): mongo.db.operations.drop() mongo.db.operations.insert( dict( name="x", pattern="{{ a * b }}" ) ) … def describe_calc(): … def from_db(client, pattern): response = client.get('/4/x/5') expect(response.data).contains(b"20")
  35. Update file: webcalc.py import os from flask import Flask from

    flask_pymongo import PyMongo from jinja2 import Template app = Flask(__name__) if os.getenv('MONGODB_URI'): app.config['MONGO_URI'] = os.getenv('MONGODB_URI') mongo = PyMongo(app) …
  36. Replace ‘calc’ function: webcalc.py … @app.route('/<int:a>/<op>/<int:b>') def calc(a, op, b):

    operation = mongo.db.operations.find_one({'name': op}) if operation: return Template(operation['pattern']).render(a=a, b=b) elif op == '+': return f"Result: {a} {op} {b} = {a + b}" else: return f"Result: {a} {op} {b} = ???" …
  37. Create Pull Request 1. Create PR 2. Wait for review

    app to deploy 3. Request review from your collaborator 4. As the collaborator, review the code 5. Merge PR
  38. Provision MongoDB on Heroku 1. Add free-tier MongoDB as resource

    2. Open database editor 3. Create operations collection 4. Insert document: {"name": "x", "pattern": "{{ a * b }}"} 5. Try out the live app on production
  39. Enable Heroku Review Apps 1. Create a Heroku pipeline 2.

    Add app.json to define resources 3. Add a seeds script 4. Create PR to see review app 5. Test feature on review app Instructions continue on the next slide....
  40. Enable review apps 1. Enable review apps in the pipeline

    2. Remove MONGODB_URI from the generated app.json 3. Allow Heroku to commit app.json to the repository 4. Pull down the latest master branch from GitHub https://devcenter.heroku.com/articles/github-integration-review-apps
  41. New file: seeds.py from webcalc import app, mongo with app.app_context():

    mongo.db.operations.insert( dict( name="+", pattern="{{ a + b }}" ) ) mongo.db.operations.insert( dict( name="x", pattern="{{ a * b }}" ) )
  42. Create Pull Request 1. Create PR 2. Wait for review

    app to deploy 3. Request review from your collaborator 4. As the collaborator, review the code and test the review app 5. Merge PR