Slide 1

Slide 1 text

Continuous Deployment using GitHub, CircleCI, and Heroku Jace Browning

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

How to use these slides … print(“Hello, world”) … $ echo “Hello, world!” http://tiny.cc/beercitycode-slides

Slide 5

Slide 5 text

Machine Setup

Slide 6

Slide 6 text

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....

Slide 7

Slide 7 text

Install dependencies $ git --version $ heroku --version $ python --version $ pipenv --version $ mongo --version

Slide 8

Slide 8 text

Create accounts ● GitHub ○ https://github.com/join ● CircleCI (log in with GitHub) ○ https://circleci.com/signup/ ● Heroku ○ https://signup.heroku.com/

Slide 9

Slide 9 text

Start Project

Slide 10

Slide 10 text

Project Overview ● “webcalc” ○ /4/+/5 produces “9” ● Technologies ○ Python, virtual environments, pipenv ○ Flask ○ MongoDB ○ Heroku ○ CircleCI

Slide 11

Slide 11 text

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....

Slide 12

Slide 12 text

New repository (create new repository on GitHub) $ git clone https://help.github.com/articles/create-a-repo/

Slide 13

Slide 13 text

New file: README.md # webcalc Demo project for the 2017 Beer City Code workshop on Continuous Delivery. https://guides.github.com/features/mastering-markdown

Slide 14

Slide 14 text

New file: .gitignore /.venv/ .cache/ __pycache__/ https://git-scm.com/docs/gitignore

Slide 15

Slide 15 text

New file: Pipfile [[source]] url = "https://pypi.python.org/simple" verify_ssl = true [requires] python_version = "3.6" https://github.com/pypa/pipfile#pipfile

Slide 16

Slide 16 text

Install Flask $ pipenv install flask http://flask.pocoo.org/

Slide 17

Slide 17 text

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)

Slide 18

Slide 18 text

Run app $ pipenv run python webcalc.py $ pipenv lock

Slide 19

Slide 19 text

Push files $ git status $ git add . $ git commit $ git push

Slide 20

Slide 20 text

Manual deployment to Heroku

Slide 21

Slide 21 text

Deployment Options ● Servers ● “Cloud” ○ Virtual machines ○ Containers ● Platforms ● “Serverless”

Slide 22

Slide 22 text

Heroku ● Developer friendly ● First-class language/framework support ● Heroku CLI ● Free tier ● On-demand scaling ● Add-ons marketplace

Slide 23

Slide 23 text

Create Heroku app 1. Create new app on Heroku 2. Explore each tab 3. Connect app to GitHub repository 4. Attempt deploy

Slide 24

Slide 24 text

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....

Slide 25

Slide 25 text

Install gunicorn $ pipenv install gunicorn --lock http://gunicorn.org/

Slide 26

Slide 26 text

New file: Procfile web: gunicorn webcalc:app https://devcenter.heroku.com/articles/procfile

Slide 27

Slide 27 text

Push files and deploy 1. Commit and push code 2. Manually deploy on Heroku 3. View site

Slide 28

Slide 28 text

View production logs $ heroku git:remote --app $ heroku logs --tail

Slide 29

Slide 29 text

Continuous Integration via CircleCI

Slide 30

Slide 30 text

Continuous Integration ● “Continuous” ● “Integration” ● Running tests gives us confidence in our code ● CI services do this automatically

Slide 31

Slide 31 text

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....

Slide 32

Slide 32 text

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

Slide 33

Slide 33 text

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!")

Slide 34

Slide 34 text

Run tests and see results $ pipenv run pytest (commit and push changes)

Slide 35

Slide 35 text

CI Services ● Types ○ Self-hosted ○ Cloud-based ● Configurations ○ File-based ○ Interface-driven ● Target audiences ○ Private teams ○ Libraries ○ Build farms ○ General-purpose

Slide 36

Slide 36 text

CircleCI ● Configuration-based ● Parallel builds ● Builds with/without cache ● SSH debugging ● Free tier

Slide 37

Slide 37 text

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....

Slide 38

Slide 38 text

Click on “Add project” 1. https://circleci.com/projects 2. Watch build run

Slide 39

Slide 39 text

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/

Slide 40

Slide 40 text

Build automatically on pushes 1. Commit and push changes 2. View status of build on CircleCI

Slide 41

Slide 41 text

Continuous Deployment to Heroku

Slide 42

Slide 42 text

No content

Slide 43

Slide 43 text

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

Slide 44

Slide 44 text

Using GitHub Pull Request for Code Review

Slide 45

Slide 45 text

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

Slide 46

Slide 46 text

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....

Slide 47

Slide 47 text

Start a new branch $ git checkout -b add-calc-route

Slide 48

Slide 48 text

Update file: test_webcalc.py … def describe_calc(): def when_plus(client): response = client.get('/4/+/5') expect(response.data).contains(b"9") …

Slide 49

Slide 49 text

Run tests and see them fail $ pipenv run pytest

Slide 50

Slide 50 text

Update file: webcalc.py … @app.route('///') def calc(a, op, b): return f"Result: {a} {op} {b} = {a + b}" …

Slide 51

Slide 51 text

Run tests $ pipenv run pytest

Slide 52

Slide 52 text

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/

Slide 53

Slide 53 text

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

Slide 54

Slide 54 text

Provisioning External Resources on Heroku

Slide 55

Slide 55 text

Heroku add-ons ● First-party: ○ PostgreSQL ○ Redis ● 3rd-party: ○ Data storage ○ Monitoring ○ Logging ○ Email ○ Caching ○ etc.

Slide 56

Slide 56 text

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....

Slide 57

Slide 57 text

Install MongoDB adapter $ git checkout master $ git pull $ git checkout -b load-from-db $ pipenv install flask-pymongo --lock

Slide 58

Slide 58 text

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")

Slide 59

Slide 59 text

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) …

Slide 60

Slide 60 text

Replace ‘calc’ function: webcalc.py … @app.route('///') 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} = ???" …

Slide 61

Slide 61 text

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

Slide 62

Slide 62 text

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

Slide 63

Slide 63 text

Using Heroku Review Apps for Manual Testing

Slide 64

Slide 64 text

Heroku Pipelines ● Group related Heroku apps ● Stages ○ Production ○ Staging ○ Review

Slide 65

Slide 65 text

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....

Slide 66

Slide 66 text

Create Heroku pipeline 1. https://devcenter.heroku.com/articles/pipelines 2. Add existing app to pipeline

Slide 67

Slide 67 text

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

Slide 68

Slide 68 text

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 }}" ) )

Slide 69

Slide 69 text

Update file: app.json … "scripts": { "postdeploy": "python seeds.py" }, …

Slide 70

Slide 70 text

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

Slide 71

Slide 71 text

Advanced Topics

Slide 72

Slide 72 text

CI Status Badges

Slide 73

Slide 73 text

Tracking Issues with GitHub

Slide 74

Slide 74 text

Continuous Delivery vs. Continuous Deployment

Slide 75

Slide 75 text

Multiple environments: dev qa/test staging

Slide 76

Slide 76 text

Heroku Flow

Slide 77

Slide 77 text

https://twitter.com/jacebrowning https://beercitycode.slack.com/messages/G5QBA85DZ https://github.com/jacebrowning