11[[chapter_17_second_deploy]]
2- Deploying Our New Code
3- ----------------------
2+ == Deploying Our New Code
43
54((("deployment", "procedure for", id="Dpro17")))
65It's time to deploy our brilliant new validation code to our live servers.
76This will be a chance to see our automated deploy scripts in action for the
87second time.
98
9+ NOTE: At this point I always want to say a huge thanks to Andrew Godwin
10+ and the whole Django team.
11+ Up until Django 1.7, I used to have a whole long section,
12+ entirely devoted to migrations.
13+ Migrations now "just work", so I was able to drop it altogether.
14+ I mean yes this all happened nearly ten years ago,
15+ but still--open source software is a gift.
16+ We get such amazing things, entirely for free.
17+ It's worth taking a moment to be grateful, now and again.
1018
11- NOTE: At this point I want to say a huge thanks to Andrew Godwin and the whole
12- Django team. Up until Django 1.7, I used to have a whole long section,
13- entirely devoted to migrations. Migrations now "just work", so I was able to
14- drop it altogether. Thanks for all the great work, gang!
1519
16-
17- .🚧 Warning, Content not updated
20+ .🚧 Warning, Under construction
1821*******************************************************************************
1922
20- This chapter has not been rewritten as part of the third edition.
23+ This chapter has only just been rewritten as part of the third edition.
24+ Please send feedback!
2125
22- By all means refer back to <<chapter_11_ansible>>
23- and try and do a deployment,
24- but otherwise, go ahead and check out <<chapter_18_spiking_custom_au,the next chapter>>, which has been (mostly) updated.
26+ You can refer back to <<chapter_11_ansible>> for reminders on Ansible commands.
2527
2628*******************************************************************************
2729
2830
29- Staging Deploy
30- ~~~~~~~~~~~~~~
31+ === Staging Deploy
3132
3233
3334We start with the staging server:
3435
35- [role="against-server"]
36+ [role="against-server small-code "]
3637[subs="specialcharacters,macros"]
3738----
3839$ pass:quotes[*ansible-playbook --user=elspeth -i staging.ottg.co.uk, infra/ansible-provision.yaml -vv*]
3940[...]
40- Disconnecting from staging.ottg.co.uk... done.
41- ----
4241
43- Restart Gunicorn:
42+ PLAYBOOK: ansible-provision.yaml ***********************************************
43+ 1 plays in infra/ansible-provision.yaml
4444
45- [role="server-commands skipme"]
46- [subs="specialcharacters,quotes"]
47- ----
48- elspeth@server:$ *sudo systemctl restart gunicorn-staging.ottg.co.uk*
45+ PLAY [all] *********************************************************************
46+
47+ TASK [Gathering Facts] *********************************************************
48+ [...]
49+ ok: [staging.ottg.co.uk]
50+
51+ TASK [Install docker] **********************************************************
52+ [...]
53+ ok: [staging.ottg.co.uk] => {"cache_update_time": [...]
54+
55+ TASK [Build container image locally] *******************************************
56+ [...]
57+ ok: [staging.ottg.co.uk -> 127.0.0.1] => {"actions": ["Built image superlists:latest [...]
58+
59+ TASK [Export container image locally] ******************************************
60+ ok: [staging.ottg.co.uk -> 127.0.0.1] => {"actions": [], "changed": false, "image": [...]
61+
62+ TASK [Upload image to server] **************************************************
63+ ok: [staging.ottg.co.uk] => {"changed": false, "checksum": [...]
64+
65+ TASK [Import container image on server] ****************************************
66+ ok: [staging.ottg.co.uk] => {"actions": ["Loaded image superlists:latest [...]
67+
68+ TASK [Ensure .env file exists] *************************************************
69+ ok: [staging.ottg.co.uk] => {"changed": false, "dest": "/home/elspeth/superlists.env", [...]
70+
71+ TASK [Ensure db.sqlite3 file exists outside container] *************************
72+ changed: [staging.ottg.co.uk] => {"changed": true, "dest": "/home/elspeth/db.sqlite3", [...]
73+
74+ TASK [Run container] ***********************************************************
75+ changed: [staging.ottg.co.uk] => {"changed": true, "container": [...]
76+
77+ TASK [Run migration inside container] ******************************************
78+ changed: [staging.ottg.co.uk] => {"changed": true, "rc": 0, "stderr": "", [...]
79+
80+ PLAY RECAP *********************************************************************
81+ staging.ottg.co.uk : ok=10 changed=3 unreachable=0 failed=0
82+ skipped=0 rescued=0 ignored=0
83+ [...]
84+ Disconnecting from staging.ottg.co.uk... done.
4985----
5086
87+
5188And run the tests against staging:
5289
5390[role="small-code"]
5491[subs="specialcharacters,macros"]
5592----
56- $ pass:quotes[*STAGING_SERVER =staging.ottg.co.uk python manage.py test functional_tests*]
93+ $ pass:quotes[*TEST_SERVER =staging.ottg.co.uk python src/ manage.py test functional_tests*]
5794OK
5895----
5996
6097
98+ Hooray!
99+
100+
61101
62102[role="pagebreak-before less_space"]
63- Live Deploy
64- ~~~~~~~~~~~
103+ === Live Deploy
65104
66105
67106Assuming all is well, we then run our deploy against live:
@@ -70,33 +109,39 @@ Assuming all is well, we then run our deploy against live:
70109[role="against-server"]
71110[subs="specialcharacters,macros"]
72111----
73- $ pass:quotes[*fab deploy:host =elspeth@superlists .ottg.co.uk*]
112+ $ pass:quotes[*ansible-playbook --user =elspeth -i www .ottg.co.uk, infra/ansible-provision.yaml -vv *]
74113----
75114
76- [role="server-commands"]
77- [subs="specialcharacters,quotes"]
78- ----
79- elspeth@server:$ *sudo service gunicorn-superlists.ottg.co.uk restart*
80- ----
81115
82116
83- What to Do If You See a Database Error
84- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
117+ === What to Do If You See a Database Error
85118
86119
87120Because our migrations introduce a new integrity constraint, you may find
88121that it fails to apply because some existing data violates that constraint.
89122
90123At this point you have two choices:
91124
92- * Delete the database on the server and try again. After all, it's only a
93- toy project!
125+ 1. Delete the database on the server and try again.
126+ After all, it's only a toy project!
127+
128+ 2. Learn about data migrations. See <<data-migrations-appendix>>.
129+
130+
131+ Here's how you might do option (1):
132+
133+ [role="skipme"]
134+ ----
135+ ssh [email protected] rm db.sqlite3 136+ ----
137+
138+ The `ssh` command takes an arbitrary shell command to run as its last argument,
139+ so we pass in `rm db.sqlite3`.
140+ We don't need a full path because we keep the sqlite database in elspeth's home folder.
94141
95- * Learn about data migrations. See <<data-migrations-appendix>>.
96142
97143
98- Wrap-Up: git tag the New Release
99- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
144+ === Wrap-Up: git tag the New Release
100145
101146
102147The last thing to do is to tag the release in our VCS--it's important that
@@ -123,8 +168,8 @@ topics that comprise <<part3>>. Can't wait!
123168
124169We've done a couple of deploys now, so this is a good time for a little recap:
125170
126- * `git push` latest code
127- * Deploy to staging and run functional tests against staging
171+ * Deploy to staging first
172+ * Run our FTs against staging.
128173* Deploy to live
129174* Tag the release
130175
0 commit comments