1
1
[[chapter_17_second_deploy]]
2
- Deploying Our New Code
3
- ----------------------
2
+ == Deploying Our New Code
4
3
5
- ((("deployment", "procedure for", id="Dpro17"))) It's
6
- time to deploy our brilliant new validation code to our live servers.
4
+ ((("deployment", "procedure for", id="Dpro17")))
5
+ It's time to deploy our brilliant new validation code to our live servers.
7
6
This will be a chance to see our automated deploy scripts in action for the
8
7
second time.
9
8
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.
10
18
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!
15
19
16
-
17
- .🚧 Warning, Content not updated
20
+ .🚧 Warning, Under construction
18
21
*******************************************************************************
19
22
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!
21
25
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.
25
27
26
28
*******************************************************************************
27
29
28
30
29
- Staging Deploy
30
- ~~~~~~~~~~~~~~
31
+ === Staging Deploy
31
32
32
33
33
34
We start with the staging server:
34
35
35
- [role="against-server"]
36
+ [role="against-server small-code "]
36
37
[subs="specialcharacters,macros"]
37
38
----
38
- $ pass:quotes[*git push*]
39
- $ pass:quotes[*cd deploy_tools*]
40
- $ pass:quotes[*fab deploy:[email protected] *]
39
+ $ pass:quotes[*ansible-playbook --user=elspeth -i staging.ottg.co.uk, infra/ansible-provision.yaml -vv*]
41
40
[...]
42
- Disconnecting from staging.ottg.co.uk... done.
43
- ----
44
41
45
- Restart Gunicorn:
42
+ PLAYBOOK: ansible-provision.yaml ***********************************************
43
+ 1 plays in infra/ansible-provision.yaml
46
44
47
- [role="server-commands skipme"]
48
- [subs="specialcharacters,quotes"]
49
- ----
50
- 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.
51
85
----
52
86
87
+
53
88
And run the tests against staging:
54
89
55
90
[role="small-code"]
56
91
[subs="specialcharacters,macros"]
57
92
----
58
- $ 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*]
59
94
OK
60
95
----
61
96
62
97
98
+ Hooray!
99
+
100
+
63
101
64
102
[role="pagebreak-before less_space"]
65
- Live Deploy
66
- ~~~~~~~~~~~
103
+ === Live Deploy
67
104
68
105
69
106
Assuming all is well, we then run our deploy against live:
@@ -72,33 +109,39 @@ Assuming all is well, we then run our deploy against live:
72
109
[role="against-server"]
73
110
[subs="specialcharacters,macros"]
74
111
----
75
- $ 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 *]
76
113
----
77
114
78
- [role="server-commands"]
79
- [subs="specialcharacters,quotes"]
80
- ----
81
- elspeth@server:$ *sudo service gunicorn-superlists.ottg.co.uk restart*
82
- ----
83
115
84
116
85
- What to Do If You See a Database Error
86
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
117
+ === What to Do If You See a Database Error
87
118
88
119
89
120
Because our migrations introduce a new integrity constraint, you may find
90
121
that it fails to apply because some existing data violates that constraint.
91
122
92
123
At this point you have two choices:
93
124
94
- * Delete the database on the server and try again. After all, it's only a
95
- 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.
96
141
97
- * Learn about data migrations. See <<data-migrations-appendix>>.
98
142
99
143
100
- Wrap-Up: git tag the New Release
101
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
144
+ === Wrap-Up: git tag the New Release
102
145
103
146
104
147
The last thing to do is to tag the release in our VCS--it's important that
@@ -125,8 +168,8 @@ topics that comprise <<part3>>. Can't wait!
125
168
126
169
We've done a couple of deploys now, so this is a good time for a little recap:
127
170
128
- * `git push` latest code
129
- * Deploy to staging and run functional tests against staging
171
+ * Deploy to staging first
172
+ * Run our FTs against staging.
130
173
* Deploy to live
131
174
* Tag the release
132
175
0 commit comments