Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 1028 lines (811 sloc) 31.667 kB
e5a7224 @theory Start sqitchtutorial.
authored
1 =head1 Name
2
3 sqitchtutorial - A tutorial introduction to Sqitch
4
5 =head1 Synopsis
6
7 sqitch *
8
9 =head1 Description
10
11 This tutorial explains how to create a sqitch-enabled project, use a VCS for
12 deployment planning, and work with other developers to make sure changes
13 remain in sync and in the proper order.
14
abfa9e7 @theory Use `sqitch status` throughout.
authored
15 We'll start by creating new project from scratch, the database for a fictional
16 antisocial networking site called Flipr. All examples use
17 L<Git|http://git-scm.com/> as the VCS and
18 L<PostgreSQL|http://www.postgresql.org/> as the storage engine, but for the
19 most part you can substitute other VCSes and database engines in the examples
20 as appropriate.
e5a7224 @theory Start sqitchtutorial.
authored
21
22 =head1 Starting a New Project
23
24 Usually the first thing to do when starting a new project is to create a
25 source code repository. So let's do that with Git:
26
27 > mkdir flipr
28 > cd flipr
29 > git init .
30 Initialized empty Git repository in /flipr/.git/
31 > touch README.md
32 > git add .
33 > git commit -am 'Fist post!'
34
35 If you're a Git user and want to follow along the history, the repository
36 used in these examples is L<on GitHub|https://github.com/theory/sqitch-intro>.
37
38 Now that we have a repository, let's get started with Sqitch.
39
40 > sqitch init --engine pg
41 Created sqitch.ini
42 Created sql/deploy
43 Created sql/revert
44
45 Let's have a look at F<sqitch.ini>:
46
47 [core]
48 engine = pg
49 # sql_dir = sql
50 # extension = sql
51
52 Pretty simple. It picked up on the fact that we're creating changes for the
53 PostgreSQL engine, thanks to the C<--engine pg> option, and saved it to the
54 file. By default, Sqitch will read F<sqitch.ini> in the current directory for
55 settings. But it will also read F<~/.sqitch/config.ini> for global settings.
56 Since PostgreSQL's C<psql> client is not in the path on my system, let's go
57 ahead an tell it globally where to find the client:
58
59 sqitch config --global core.pg.client /var/lib/pgsql/bin/psql
60
61 Have a look at F<~/.sqitch/config.ini> and you'll see this:
62
63 [core.pg]
64 client = /var/lib/pgsql/bin/psql
65
66 Back to the repository. Let's commit these changes and start creating the
67 database changes.
68
e41bc5e @theory Add example of first deployment to tutorial.
authored
69 > git add .
70 > git commit -am 'Initialize Sqitch configuration.'
71
abfa9e7 @theory Use `sqitch status` throughout.
authored
72 =head1 Our First Deployment
e41bc5e @theory Add example of first deployment to tutorial.
authored
73
74 First, our project will need a database user. This is the application user,
75 who will have only limited access to objects in the database. Run this command:
76
77 > sqitch add-step appuser
78 Adding sql/deploy/appuser.sql
79 Adding sql/revert/appuser.sql
80
abfa9e7 @theory Use `sqitch status` throughout.
authored
81 The C<add-step> command creates deploy and revert scripts that represent a new
82 change step. Now we edit these files. The C<deploy> script's job is to create
83 the user. So we add this to F<sql/deploy/appuser.sql>:
e41bc5e @theory Add example of first deployment to tutorial.
authored
84
85 CREATE ROLE flipr WITH LOGIN;
86
b67fb66 @theory Use `status` and `log` commands instead of table output.
authored
87 The C<revert> script's job is to precisely revert the change to the deploy
abfa9e7 @theory Use `sqitch status` throughout.
authored
88 script, so we add this to F<sql/revert/appuser.sql>:
e41bc5e @theory Add example of first deployment to tutorial.
authored
89
90 DROP ROLE flipr;
91
92 Now we can try deploying this change:
93
54bf216 @theory Better empty tags; show status and log.
authored
94 > sqitch --db-name flipr_test deploy --untracked
abfa9e7 @theory Use `sqitch status` throughout.
authored
95 Adding metadata tables to flipr_test
54bf216 @theory Better empty tags; show status and log.
authored
96 Deploying HEAD+ to flipr_test
e41bc5e @theory Add example of first deployment to tutorial.
authored
97 - appuser
98
abfa9e7 @theory Use `sqitch status` throughout.
authored
99 First Sqitch created the metadata tables used to track database changes. The
100 structure and name of the metadata tables varies between databases (PostgreSQL
101 uses a schema to namespace its metadata; MySQL and SQLite use a prefix). Next,
102 Sqitch deploys changes. Here it is deploying something called C<HEAD+>.
b67fb66 @theory Use `status` and `log` commands instead of table output.
authored
103 Normally you would see a tag here, but since we've just added the files and
104 they are not yet committed to Git, there is no tag. C<HEAD+> is a special tag
105 reserved for use by Sqitch. It's enabled only by the use of the C<--untracked>
106 option, which allows Sqitch to find an deploy untracked changes.
107
108 With this change deployed, if you connect to the database, you'll be able to
109 see the role:
e41bc5e @theory Add example of first deployment to tutorial.
authored
110
abfa9e7 @theory Use `sqitch status` throughout.
authored
111 > psql -d flipr_test -c '\du flipr'
112 List of roles
113 Role name | Attributes | Member of
114 -----------+------------+-----------
115 flipr | | {}
e41bc5e @theory Add example of first deployment to tutorial.
authored
116
b67fb66 @theory Use `status` and `log` commands instead of table output.
authored
117 And we can also see how the deployment was recorded via the C<status> command,
118 which reads the metadata tables from the database:
54bf216 @theory Better empty tags; show status and log.
authored
119
120 > sqitch -d flipr_test status
abfa9e7 @theory Use `sqitch status` throughout.
authored
121 # On database flipr_test
122 # Tag: HEAD+
b67fb66 @theory Use `status` and `log` commands instead of table output.
authored
123 # Step: appuser
124 # Date: 2012-04-09 18:43:45
54bf216 @theory Better empty tags; show status and log.
authored
125 #
126 Nothing to deploy (up-to-date)
e41bc5e @theory Add example of first deployment to tutorial.
authored
127
abfa9e7 @theory Use `sqitch status` throughout.
authored
128 Let's make sure that we can revert the change:
e41bc5e @theory Add example of first deployment to tutorial.
authored
129
130 > sqitch --db-name flipr_test revert
54bf216 @theory Better empty tags; show status and log.
authored
131 Reverting all changes from flipr_test
b67fb66 @theory Use `status` and `log` commands instead of table output.
authored
132 - appuser
e41bc5e @theory Add example of first deployment to tutorial.
authored
133
134 And now the user should be gone:
135
abfa9e7 @theory Use `sqitch status` throughout.
authored
136 > psql -d flipr_test -c '\du flipr'
e41bc5e @theory Add example of first deployment to tutorial.
authored
137 List of roles
abfa9e7 @theory Use `sqitch status` throughout.
authored
138 Role name | Attributes | Member of
139 -----------+------------+-----------
e41bc5e @theory Add example of first deployment to tutorial.
authored
140
b67fb66 @theory Use `status` and `log` commands instead of table output.
authored
141 And the status message should reflect as much:
e41bc5e @theory Add example of first deployment to tutorial.
authored
142
b67fb66 @theory Use `status` and `log` commands instead of table output.
authored
143 > sqitch -d flipr_test status --untracked
abfa9e7 @theory Use `sqitch status` throughout.
authored
144 # On database flipr_test
54bf216 @theory Better empty tags; show status and log.
authored
145 # Nothing deployed.
146 #
147 # Changes not yet deployed:
148 # * HEAD+
149 # appuser
150 #
abfa9e7 @theory Use `sqitch status` throughout.
authored
151 Use "sqitch deploy --untracked" to deploy these changes
54bf216 @theory Better empty tags; show status and log.
authored
152
b67fb66 @theory Use `status` and `log` commands instead of table output.
authored
153 We've again used the C<--untracked> option, otherwise the C<appuser> step would
9359a6e @theory Pod and spelling errors fixed.
authored
154 not appear in the list of "Changes not yet deployed."
e41bc5e @theory Add example of first deployment to tutorial.
authored
155
07542be @arhuman Fix (very few) typos in documentation
arhuman authored
156 We still have a record that the change happened, visible via the C<log>
b67fb66 @theory Use `status` and `log` commands instead of table output.
authored
157 command:
54bf216 @theory Better empty tags; show status and log.
authored
158
159 > sqitch -d flipr_test log
160 step appuser reverted
abfa9e7 @theory Use `sqitch status` throughout.
authored
161 By: david
162 Date: 2012-04-09 18:45:47
163 Tag: HEAD+
54bf216 @theory Better empty tags; show status and log.
authored
164
165 step appuser deployed
abfa9e7 @theory Use `sqitch status` throughout.
authored
166 By: david
167 Date: 2012-04-09 18:43:45
168 Tag: HEAD+
b72f83a @theory Add a second deployment.
authored
169
54bf216 @theory Better empty tags; show status and log.
authored
170 Cool. Now let's commit it.
b72f83a @theory Add a second deployment.
authored
171
172 > git add .
173 > git commit -m 'Add app user.'
174 [master 36acafd] Add app user.
175 2 files changed, 2 insertions(+)
176 create mode 100644 sql/deploy/appuser.sql
177 create mode 100644 sql/revert/appuser.sql
178
179 And then deploy again:
180
181 > sqitch --db-name flipr_test deploy
54bf216 @theory Better empty tags; show status and log.
authored
182 Deploying 36acafd to flipr_test
b72f83a @theory Add a second deployment.
authored
183 - appuser
184
abfa9e7 @theory Use `sqitch status` throughout.
authored
185 Notice we no longer need the C<--untracked> option. That's because we've
186 committed the step to Git, so Sqitch can read it from the Git history. And now
187 the user should be back:
b72f83a @theory Add a second deployment.
authored
188
abfa9e7 @theory Use `sqitch status` throughout.
authored
189 > psql -d flipr_test -c '\du flipr'
190 List of roles
191 Role name | Attributes | Member of
192 -----------+------------+-----------
193 flipr | | {}
b72f83a @theory Add a second deployment.
authored
194
b67fb66 @theory Use `status` and `log` commands instead of table output.
authored
195 When we look at the status, the deployment is tagged with the SHA1 of the
b72f83a @theory Add a second deployment.
authored
196 commit:
197
b67fb66 @theory Use `status` and `log` commands instead of table output.
authored
198 > sqitch -d flipr_test status
abfa9e7 @theory Use `sqitch status` throughout.
authored
199 # On database flipr_test
200 # Tag: 36acafd
b67fb66 @theory Use `status` and `log` commands instead of table output.
authored
201 # Step: appuser
202 # Date: 2012-04-09 18:52:42
203 #
204 Nothing to deploy (up-to-date)
b72f83a @theory Add a second deployment.
authored
205
abfa9e7 @theory Use `sqitch status` throughout.
authored
206 =head1 More Configuration
207
208 I'm getting a little tired of always having to type C<--db-name flipr_test>,
209 aren't you? Let's just make that the default, shall we?
210
211 sqitch config core.pg.db_name flipr_test
212
213 Now we can leave it out, unless we need to deploy to another database. Which
214 we will, eventually, but at least our examples will be simpler from here on
215 in, e.g.:
216
217 > sqitch status
218 # On database flipr_test
219 # Tag: 36acafd
220 # Step: appuser
221 # Date: 2012-04-09 18:52:42
222 #
223 Nothing to deploy (up-to-date)
224
225 Yay, that allows things to be a little more concise. Let's make some more
226 changes!
227
54bf216 @theory Better empty tags; show status and log.
authored
228 =head1 Deploy with Dependency
b72f83a @theory Add a second deployment.
authored
229
230 Let's add another deployment, this time to create a table. Our app will need
b67fb66 @theory Use `status` and `log` commands instead of table output.
authored
231 users, of course, so we'll create a table for them. First, add the new step:
b72f83a @theory Add a second deployment.
authored
232
233 > sqitch add-step users
234 Adding sql/deploy/users.sql
235 Adding sql/revert/users.sql
236
237 Now edit the scripts. In C<sql/deploy/users.sql>, we put:
238
239 -- requires: appuser
240 BEGIN;
241 SET client_min_messages = 'warning';
242
243 CREATE TABLE users (
244 nickname TEXT PRIMARY KEY,
245 password TEXT NOT NULL,
246 timestamp TIMESTAMPTZ NOT NULL DEFAULT NOW()
247 );
248
249 GRANT SELECT ON users TO flipr;
250 COMMIT;
251
252 A few things to notice here. On the first line, we've declared a dependency on
abfa9e7 @theory Use `sqitch status` throughout.
authored
253 the C<appuser> step. Although that step has already been added and committed,
54bf216 @theory Better empty tags; show status and log.
authored
254 and therefore should always be applied before the C<users> step, it's a good
abfa9e7 @theory Use `sqitch status` throughout.
authored
255 idea to be explicit about dependencies. This becomes especially important when
256 committing a number of steps at one time, such as when merging a patch or a
257 branch.
b72f83a @theory Add a second deployment.
authored
258
259 The syntax of the dependency declaration is simple: Before any other lines,
260 create an SQL C<--> comment that simply uses the word "requires" followed by a
261 colon and then a comma-delimited list of required steps. The requirements may
262 also be listed on separate lines, providing they all start with
263 C<-- requires:>.
264
265 Notice that all of the SQL code is wrapped in a transaction. This is handy for
266 PostgreSQL deployments, because DDLs are transactional. The upshot is that if
54bf216 @theory Better empty tags; show status and log.
authored
267 any part of the deployment fails, the whole step fails. Such may work
268 less-well for database engines that don't support transactional DDLs.
b72f83a @theory Add a second deployment.
authored
269
54bf216 @theory Better empty tags; show status and log.
authored
270 Just before the commit, the C<GRANT> command grants C<SELECT> access on the
abfa9e7 @theory Use `sqitch status` throughout.
authored
271 table to the C<flipr> user created by the C<appuser> step. This is why we
272 need the dependency.
b72f83a @theory Add a second deployment.
authored
273
274 Now for the revert script. Add this to C<sql/revert/users.sql>:
275
276 DROP TABLE users;
277
278 Couldn't be much simpler, right? Let's deploy this bad boy:
279
abfa9e7 @theory Use `sqitch status` throughout.
authored
280 > sqitch deploy --untracked
54bf216 @theory Better empty tags; show status and log.
authored
281 Deploying HEAD+ to flipr_test
b72f83a @theory Add a second deployment.
authored
282 - users
283
284 The C<users> table should have been created:
285
286 > psql -d flipr_test -c '\d users'
287 Table "public.users"
288 Column | Type | Modifiers
289 -----------+--------------------------+------------------------
290 nickname | text | not null
291 password | text | not null
292 timestamp | timestamp with time zone | not null default now()
293 Indexes:
294 "users_pkey" PRIMARY KEY, btree (nickname)
295
b67fb66 @theory Use `status` and `log` commands instead of table output.
authored
296 Now have a look at the status:
b72f83a @theory Add a second deployment.
authored
297
b67fb66 @theory Use `status` and `log` commands instead of table output.
authored
298 > sqitch -d flipr_test status
abfa9e7 @theory Use `sqitch status` throughout.
authored
299 # On database flipr_test
300 # Tag: HEAD+
b67fb66 @theory Use `status` and `log` commands instead of table output.
authored
301 # Step: users
abfa9e7 @theory Use `sqitch status` throughout.
authored
302 # Date: 2012-04-09 20:41:31
b67fb66 @theory Use `status` and `log` commands instead of table output.
authored
303 #
304 Nothing to deploy (up-to-date)
b72f83a @theory Add a second deployment.
authored
305
07542be @arhuman Fix (very few) typos in documentation
arhuman authored
306 Success! However, we've once again deployed an untracked change with no tags.
b67fb66 @theory Use `status` and `log` commands instead of table output.
authored
307 In general, we want tags, so let's revert the change:
b72f83a @theory Add a second deployment.
authored
308
abfa9e7 @theory Use `sqitch status` throughout.
authored
309 > sqitch revert --to 36acafd
54bf216 @theory Better empty tags; show status and log.
authored
310 Reverting HEAD+ from flipr_test
b72f83a @theory Add a second deployment.
authored
311 - users
312
b67fb66 @theory Use `status` and `log` commands instead of table output.
authored
313 Note that we've used the C<--to> option to revert only to the C<36acafd> tag,
abfa9e7 @theory Use `sqitch status` throughout.
authored
314 which represents the deployment of the C<appuser> step. (You can see this tag
315 by running C<sqitch log>, in case you don't have your SHA1 hashes memorized).
316 Now commit and deploy again:
0ef5586 @theory Add more deploys and bundle.
authored
317
b72f83a @theory Add a second deployment.
authored
318 > git add .
319 > git commit -am 'Add users table.'
320 [master fa650af] Add users table.
321 2 files changed, 16 insertions(+)
322 create mode 100644 sql/deploy/users.sql
323 create mode 100644 sql/revert/users.sql
abfa9e7 @theory Use `sqitch status` throughout.
authored
324 > sqitch deploy
b67fb66 @theory Use `status` and `log` commands instead of table output.
authored
325 Deploying fa650af to flipr_test
b72f83a @theory Add a second deployment.
authored
326 - users
327
b67fb66 @theory Use `status` and `log` commands instead of table output.
authored
328 Looks good. Check the status:
329
80764e6 @theory Add options to the `status` command.
authored
330 > sqitch status --show tags
abfa9e7 @theory Use `sqitch status` throughout.
authored
331 # On database flipr_test
332 # Tag: fa650af
b67fb66 @theory Use `status` and `log` commands instead of table output.
authored
333 # Step: users
abfa9e7 @theory Use `sqitch status` throughout.
authored
334 # Date: 2012-04-09 20:45:23
b67fb66 @theory Use `status` and `log` commands instead of table output.
authored
335 #
80764e6 @theory Add options to the `status` command.
authored
336 # Tags:
337 # fa650af - 2012-04-09 20:45:23 - david
338 # 36acafd - 2012-04-09 19:04:50 - david
339 #
b67fb66 @theory Use `status` and `log` commands instead of table output.
authored
340 Nothing to deploy (up-to-date)
b72f83a @theory Add a second deployment.
authored
341
80764e6 @theory Add options to the `status` command.
authored
342 Note the use of C<--show tags>, which adds the "Tags" section to the output,
9359a6e @theory Pod and spelling errors fixed.
authored
343 so that we can use a list of what tags were deployed, when, and by whom.
54bf216 @theory Better empty tags; show status and log.
authored
344
345 =head1 Add Two at Once
346
abfa9e7 @theory Use `sqitch status` throughout.
authored
347 Let's add a couple more steps to add functions for managing users.
b72f83a @theory Add a second deployment.
authored
348
0ef5586 @theory Add more deploys and bundle.
authored
349 > sqitch add-step insert_user --requires users --requires appuser
350 Adding sql/deploy/insert_user.sql
351 -- requires: users, appuser
352 Adding sql/revert/insert_user.sql
353
354 > sqitch add-step change_pass --requires users --requires appuser
355 Adding sql/deploy/change_pass.sql
356 -- requires: users, appuser
357 Adding sql/revert/change_pass.sql
358
54bf216 @theory Better empty tags; show status and log.
authored
359 Here we've taken advantage of the C<--requires> option to have Sqitch write
abfa9e7 @theory Use `sqitch status` throughout.
authored
360 the stubbed C<deploy> file with the C<-- requires:> line already filled in.
361 Have a look:
0ef5586 @theory Add more deploys and bundle.
authored
362
363 > cat sql/deploy/insert_user.sql
364 -- requires: users, appuser
365
366
abfa9e7 @theory Use `sqitch status` throughout.
authored
367 Nice, huh? Yeah, okay, so it's a little thing. Little things matter, am I
368 right? Let's write the code. Here's what C<sql/deploy/insert_user.sql> should
369 look like:
0ef5586 @theory Add more deploys and bundle.
authored
370
371 -- requires: users, appuser
372
54bf216 @theory Better empty tags; show status and log.
authored
373 BEGIN;
374
0ef5586 @theory Add more deploys and bundle.
authored
375 CREATE OR REPLACE FUNCTION insert_user(
376 nickname TEXT,
377 password TEXT
54bf216 @theory Better empty tags; show status and log.
authored
378 ) RETURNS VOID LANGUAGE SQL SECURITY DEFINER AS $$
0ef5586 @theory Add more deploys and bundle.
authored
379 INSERT INTO users values($1, md5($2));
380 $$;
381
d987aa2 @theory Add a branch, some more changes.
authored
382 GRANT EXECUTE ON FUNCTION insert_user(TEXT, TEXT) to flipr;
54bf216 @theory Better empty tags; show status and log.
authored
383 COMMIT;
384
0ef5586 @theory Add more deploys and bundle.
authored
385 And C<sql/revert/insert_user.sql> should look something like this:
386
387 DROP FUNCTION insert_user(TEXT, TEXT);
388
389 Now for C<change_pass>; C<sql/deploy/change_pass.sql> might look like this:
390
391 -- requires: users, appuser
392
54bf216 @theory Better empty tags; show status and log.
authored
393 BEGIN;
394
0ef5586 @theory Add more deploys and bundle.
authored
395 CREATE OR REPLACE FUNCTION change_pass(
396 nick TEXT,
397 oldpass TEXT,
398 newpass TEXT
abfa9e7 @theory Use `sqitch status` throughout.
authored
399 ) RETURNS BOOLEAN LANGUAGE plpgsql SECURITY DEFINER AS $$
0ef5586 @theory Add more deploys and bundle.
authored
400 BEGIN
401 UPDATE users
402 SET password = md5($3)
403 WHERE nickname = $1
404 AND password = md5($2);
405 RETURN FOUND;
406 END;
407 $$;
408
d987aa2 @theory Add a branch, some more changes.
authored
409 GRANT EXECUTE ON FUNCTION change_pass(TEXT, TEXT, TEXT) to flipr;
54bf216 @theory Better empty tags; show status and log.
authored
410 COMMIT;
411
abfa9e7 @theory Use `sqitch status` throughout.
authored
412 And of course, its C<revert> script, C<sql/revert/change_pass.sql>, should look
0ef5586 @theory Add more deploys and bundle.
authored
413 something like:
414
415 DROP FUNCTION change_pass(TEXT, TEXT, TEXT);
416
417 Test em out!
418
abfa9e7 @theory Use `sqitch status` throughout.
authored
419 > sqitch deploy --untracked
54bf216 @theory Better empty tags; show status and log.
authored
420 Deploying HEAD+ to flipr_test
0ef5586 @theory Add more deploys and bundle.
authored
421 - change_pass
422 - insert_user
423
424 Do we have the functions?
425
426 > psql -d flipr_test -c '\df'
427 List of functions
428 Schema | Name | Result data type | Argument data types | Type
429 --------+-------------+------------------+---------------------------------------+--------
430 public | change_pass | boolean | nick text, oldpass text, newpass text | normal
431 public | insert_user | void | nickname text, password text | normal
432
abfa9e7 @theory Use `sqitch status` throughout.
authored
433 And what's the status?
0ef5586 @theory Add more deploys and bundle.
authored
434
abfa9e7 @theory Use `sqitch status` throughout.
authored
435 > sqitch status --show tags
436 # On database flipr_test
437 # Tag: HEAD+
438 # Step: insert_user
439 # Date: 2012-04-09 20:45:23
440 #
441 # Tags:
442 # HEAD+ - 2012-04-09 20:45:23 - david
443 # fa650af - 2012-04-09 20:45:23 - david
444 # 36acafd - 2012-04-09 19:04:50 - david
445 #
446 Nothing to deploy (up-to-date)
0ef5586 @theory Add more deploys and bundle.
authored
447
448 Looks good. Let's revert, commit, and re-deploy, as usual.
449
abfa9e7 @theory Use `sqitch status` throughout.
authored
450 > sqitch revert --to HEAD
54bf216 @theory Better empty tags; show status and log.
authored
451 Reverting HEAD+ from flipr_test
0ef5586 @theory Add more deploys and bundle.
authored
452 - insert_user
453 - change_pass
454
abfa9e7 @theory Use `sqitch status` throughout.
authored
455 Note the use of C<--to HEAD> to revert untracked changes. We also could have
456 explicitly used C<--to fa650af> to revert to that tag, but C<HEAD> is a nice
457 shortcut. Let's do the commit and re-deploy dance:
0ef5586 @theory Add more deploys and bundle.
authored
458
459 > git add .
460 > git ci -m 'Add `insert_user()` and `change_pass()`.'
461 [master 803e6b8] Add `insert_user()` and `change_pass()`.
462 4 files changed, 25 insertions(+)
463 create mode 100644 sql/deploy/change_pass.sql
464 create mode 100644 sql/deploy/insert_user.sql
465 create mode 100644 sql/revert/change_pass.sql
466 create mode 100644 sql/revert/insert_user.sql
467
abfa9e7 @theory Use `sqitch status` throughout.
authored
468 > sqitch deploy
54bf216 @theory Better empty tags; show status and log.
authored
469 Deploying 803e6b8 to flipr_test
0ef5586 @theory Add more deploys and bundle.
authored
470 - change_pass
471 - insert_user
472
abfa9e7 @theory Use `sqitch status` throughout.
authored
473 > sqitch status --show tags
474 # On database flipr_test
475 # Tag: HEAD+
476 # Step: insert_user
477 # Date: 2012-04-09 20:45:23
478 #
479 # Tags:
480 # 803e6b8 - 2012-04-09 21:33:32 - david
481 # fa650af - 2012-04-09 20:45:23 - david
482 # 36acafd - 2012-04-09 19:04:50 - david
483 #
484 Nothing to deploy (up-to-date)
485
486 Great, we're fully up-to-date!
0ef5586 @theory Add more deploys and bundle.
authored
487
488 =head1 Ship It!
489
490 Let's do a first release of our app. Let's call it C<1.0.0-dev1> Since we want
491 to have it go out with deployments tied to the release, let's tag it:
492
493 > git tag v1.0.0-dev1 -am 'Tag v1.0.0-dev1'
494
495 We can test deployment to make sure the tag gets picked up like so:
496
497 > createdb flipr_dev
498 > sqitch --db-name flipr_dev deploy
abfa9e7 @theory Use `sqitch status` throughout.
authored
499 Deploying 36acafd to flipr_dev
0ef5586 @theory Add more deploys and bundle.
authored
500 - appuser
abfa9e7 @theory Use `sqitch status` throughout.
authored
501 Deploying fa650af to flipr_dev
0ef5586 @theory Add more deploys and bundle.
authored
502 - users
54bf216 @theory Better empty tags; show status and log.
authored
503 Deploying 803e6b8/v1.0.0-dev1 to flipr_dev
0ef5586 @theory Add more deploys and bundle.
authored
504 - insert_user
505 - change_pass
506
507 All four steps were deployed, great! Let's have a look at the state:
508
abfa9e7 @theory Use `sqitch status` throughout.
authored
509 > sqitch --db-name flipr_dev status --show tags
510 # On database flipr_dev
511 # Tags: 803e6b8, v1.0.0-dev1
512 # Step: change_pass
513 # Date: 2012-04-09 22:14:00
514 #
515 # Tags:
516 # 803e6b8, v1.0.0-dev1 - 2012-04-09 22:14:00 - david
517 # fa650af - 2012-04-09 22:13:55 - david
518 # 36acafd - 2012-04-09 22:13:53 - david
519 #
520 Nothing to deploy (up-to-date)
0ef5586 @theory Add more deploys and bundle.
authored
521
abfa9e7 @theory Use `sqitch status` throughout.
authored
522 Note that all the tags are included, and that the two tags C<803e6b8> and
523 C<v1.0.0-dev1> actually represent the same point in time. This is handy for
524 development, but is a bit over-the-top for production deployments. We can get
525 around this by bundling up all the steps with the explicit tag, leaving out
526 the individual commit SHA1s:
0ef5586 @theory Add more deploys and bundle.
authored
527
528 > sqitch bundle --tags-only
abfa9e7 @theory Use `sqitch status` throughout.
authored
529 Bundling in bundle/
530 Config written to bundle/sqitch.ini
54bf216 @theory Better empty tags; show status and log.
authored
531 Bundling v1.0.0-dev1
532 - appuser
533 - users
534 - change_pass
535 - insert_user
0ef5586 @theory Add more deploys and bundle.
authored
536 Plan written to bundle/sqitch.plan
537
abfa9e7 @theory Use `sqitch status` throughout.
authored
538 Now we can package up the C<bundle> directory and distribute it. When it gets
539 installed somewhere, users can use Sqitch to deploy to the database. Of
540 course, the Git history is no longer available, so Sqitch will use the
541 C<sqitch.plan> file to figure things out. Let's have a look at it:
0ef5586 @theory Add more deploys and bundle.
authored
542
543 cat bundle/sqitch.plan
544
545 [v1.0.0-dev1]
546 appuser
547 users
548 change_pass
549 insert_user
550
551 Pretty simple. It shows the tag being deployed and the steps that constitute
54bf216 @theory Better empty tags; show status and log.
authored
552 it as a simple list. Notice that the SHA1s for each step are not present; the
0ef5586 @theory Add more deploys and bundle.
authored
553 C<--tags-only> option to the C<bundle> command limits the plan only to tags.
554
555 Let's test deploying it:
556
557 > cd bundle
558 > createdb flipr_prod
559 > sqitch --db-name flipr_prod deploy
54bf216 @theory Better empty tags; show status and log.
authored
560 Deploying v1.0.0-dev1 to flipr_prod
0ef5586 @theory Add more deploys and bundle.
authored
561 - appuser
562 - users
563 - insert_user
564 - change_pass
565
abfa9e7 @theory Use `sqitch status` throughout.
authored
566 Looks much the same as before, eh? But have a look at the status:
0ef5586 @theory Add more deploys and bundle.
authored
567
abfa9e7 @theory Use `sqitch status` throughout.
authored
568 > sqitch --db-name flipr_prod status --show tags
569 # On database flipr_prod
570 # Tag: v1.0.0-dev1
571 # Step: change_pass
572 # Date: 2012-04-09 22:17:38
573 #
574 # Tags:
575 # v1.0.0-dev1 - 2012-04-09 22:17:38 - david
576 #
577 Nothing to deploy (up-to-date)
0ef5586 @theory Add more deploys and bundle.
authored
578
abfa9e7 @theory Use `sqitch status` throughout.
authored
579 No commit SHA1s, just C<v1.0.0-dev1>.
d987aa2 @theory Add a branch, some more changes.
authored
580
581 =head1 Flip Out
582
583 Now that we've got the basics of user management done, let's get to work on
584 the core of our product, the "flip." Since other folks are working on other
585 tasks in the repository, we'll work on a branch, so we can all stay out of
586 each other's way. So let's branch:
587
588 > git checkout -b flips
589 Switched to a new branch 'flips'
590
591 Now we can add a new step to create a table for our flips.
592
593 > sqitch add-step flips --requires users
594 Adding sql/deploy/flips.sql
595 -- requires: users
596 Adding sql/revert/flips.sql
597
598 You know the drill by now. Edit F<sql/deploy/flips.sql>:
599
600 -- requires: users
601 BEGIN;
602 SET client_min_messages = 'warning';
603
604 CREATE TABLE flips (
605 id BIGSERIAL PRIMARY KEY,
606 nickname TEXT NOT NULL REFERENCES users(nickname),
607 body TEXT NOT NULL DEFAULT '' CHECK ( length(body) <= 180 ),
608 timestamp TIMESTAMPTZ NOT NULL DEFAULT clock_timestamp()
609 );
610
611 GRANT SELECT ON flips TO flipr;
612 COMMIT;
613
614 And edit F<sql/revert/flips.sql>:
615
616 DROP TABLE flips;
617
618 And give it a whirl:
619
620 > sqitch deploy --untracked
621 Deploying HEAD+ to flipr_test
622 - flips
623
624 Look good?
625
626 > sqitch status --show tags
627 # On database flipr_test
628 # Tag: HEAD+
629 # Step: flips
630 # Date: 2012-04-10 22:30:02
631 #
632 # Tags:
633 # HEAD+ - 2012-04-10 22:30:02 - david
634 # 803e6b8 - 2012-04-09 21:33:32 - david
635 # fa650af - 2012-04-09 20:45:23 - david
636 # 36acafd - 2012-04-09 19:04:50 - david
637 #
638 Nothing to deploy (up-to-date)
639
640 Yep. Make it so!
641
642 > git add .
643 > git commit -am 'Add flipr table.'
644 [flips 4aa888e] Add flipr table.
645 2 files changed, 18 insertions(+)
646 create mode 100644 sql/deploy/flips.sql
647 create mode 100644 sql/revert/flips.sql
648
649 Ooh, but wait, we forgot to revert the change before committing! Well,
650 no worries, we can update all the tags.
651
652 > sqitch retag
653 Retagging flipr_test
654 . 36acafd
655 . fa650af
656 . 803e6b8
657 + v1.0.0-dev1
658 - HEAD+
659 + 4aa888e
660 Tags: 4 (1 removed, 1 added).
661
662 In the list of tags, C<.> means no change, C<+> means added, and C<-> means
663 removed.
664
665 Oh, it added the C<v1.0.0-dev1> tag. Recall that we never deployed it to the
666 test database before. That's cool, forgot about that. Then it removed the
667 C<HEAD+> tag and added C<4aa888e>. Let's examine the status:
668
669 > sqitch status --show tags
670 # On database flipr_test
671 # Tag: 4aa888e
672 # Step: flips
673 # Date: 2012-04-10 22:30:02
674 #
675 # Tags:
676 # 4aa888e - 2012-04-10 22:30:02 - david
677 # 803e6b8, v1.0.0-dev1 - 2012-04-09 21:33:32 - david
678 # fa650af - 2012-04-09 20:45:23 - david
679 # 36acafd - 2012-04-09 19:04:50 - david
680 #
681 Nothing to deploy (up-to-date)
682
683 Great, looks like the tags are all in sync. That's handy. Of course, it's
684 still a good idea to test C<sqitch revert> and C<sqitch deploy> a few times,
685 just to make sure the changes are always carried out properly, but it's nice
686 to know we don't have to take extra steps just to commit untracked changes.
687
688 =head1 Wash, Rinse, Repeat
689
690 Now comes the time to add functions to manage flips. I'm sure you have things
691 nailed down now. Go ahead and add C<insert_flip> and C<delete_flip> steps
692 and commit them. The C<insert_flip> deploy script might look something like:
693
694 -- requires: flips, appuser
695 BEGIN;
696 CREATE OR REPLACE FUNCTION insert_flip(
697 nickname TEXT,
698 body TEXT
699 ) RETURNS BIGINT LANGUAGE sql SECURITY DEFINER AS $$
700 INSERT INTO flips (body, nickname)
701 VALUES ($1, $2)
702 RETURNING id;
703 $$;
704 GRANT EXECUTE ON FUNCTION insert_flip(TEXT, TEXT) to flipr;
705 COMMIT;
706
707 And the C<delete_flip> deploy script might look something like:
708
709 -- requires: flips, appuser
710 BEGIN;
711 CREATE OR REPLACE FUNCTION delete_flip(
712 flip_id BIGINT
713 ) RETURNS BOOLEAN LANGUAGE plpgsql SECURITY DEFINER AS $$
714 BEGIN
715 DELETE FROM flips WHERE id = flip_id;
716 RETURN FOUND;
717 END;
718 $$;
719 GRANT EXECUTE ON FUNCTION delete_flip(BIGINT) to flipr;
720 COMMIT;
721
722 The C<revert> scripts are:
723
724 DROP FUNCTION insert_flip(TEXT, TEXT);
725
726 And:
727
728 DROP FUNCTION delete_flip(BIGINT);
729
730 Check the L<example git repository|https://github.com/theory/sqitch-intro> for
f195721 @theory Fix spelling errors.
authored
731 the complete details. Test C<deploy> and C<revert>, commit, and C<retag>. The
732 status should end up looking something like this:
d987aa2 @theory Add a branch, some more changes.
authored
733
734 > sqitch status --show tags
735 # On database flipr_test
736 # Tag: 74c49ef
737 # Step: insert_flip
738 # Date: 2012-04-10 23:00:29
739 #
740 # Tags:
741 # 74c49ef - 2012-04-10 23:00:29 - david
742 # 4aa888e - 2012-04-10 22:30:02 - david
743 # 803e6b8, v1.0.0-dev1 - 2012-04-09 21:33:32 - david
744 # fa650af - 2012-04-09 20:45:23 - david
745 # 36acafd - 2012-04-09 19:04:50 - david
746 #
747 Nothing to deploy (up-to-date)
748
749 Good, we've finished this feature. Time to merge back into C<master>.
750
3f66ce0 @theory Handle merge ordering issue.
authored
751 =head2 Emergency
d987aa2 @theory Add a branch, some more changes.
authored
752
4d27feb @theory Add merge conflict example.
authored
753 Let's do it:
754
755 > git checkout master
756 Switched to branch 'master'
757 > git pull
758 Updating 803e6b8..2fae0b3
759 Fast-forward
760 sql/deploy/delete_list.sql | 15 +++++++++++++++
761 sql/deploy/insert_list.sql | 12 ++++++++++++
762 sql/deploy/lists.sql | 16 ++++++++++++++++
763 sql/revert/delete_list.sql | 1 +
764 sql/revert/insert_list.sql | 1 +
765 sql/revert/lists.sql | 2 ++
766 12 files changed, 91 insertions(+)
767 create mode 100644 sql/deploy/delete_list.sql
768 create mode 100644 sql/deploy/insert_list.sql
769 create mode 100644 sql/deploy/lists.sql
770 create mode 100644 sql/revert/delete_list.sql
771 create mode 100644 sql/revert/insert_list.sql
772 create mode 100644 sql/revert/lists.sql
773
774 Hrm, that's interesting. Looks like someone made some changes to C<master>.
775 Looks like some list support was added. Well, let's see what happens when we
776 merge our changes.
777
778 > git merge --no-ff flips
779 Merge made by the 'recursive' strategy.
780 sql/deploy/delete_flip.sql | 12 ++++++++++++
781 sql/deploy/flips.sql | 16 ++++++++++++++++
782 sql/deploy/insert_flip.sql | 12 ++++++++++++
783 sql/revert/delete_flip.sql | 1 +
784 sql/revert/flips.sql | 2 ++
785 sql/revert/insert_flip.sql | 1 +
786 6 files changed, 44 insertions(+)
787 create mode 100644 sql/deploy/delete_flip.sql
788 create mode 100644 sql/deploy/flips.sql
789 create mode 100644 sql/deploy/insert_flip.sql
790 create mode 100644 sql/revert/delete_flip.sql
791 create mode 100644 sql/revert/flips.sql
792 create mode 100644 sql/revert/insert_flip.sql
793
794 Hey, looks good, everything merged cleanly. Let's have a look at our Git history:
795
796 > git log --oneline
797 5e30f38 Merge branch 'flips'
798 2fae0b3 Merge tag 'lists'
799 2a84155 Merge branch 'lists'
800 9703969 Add `insert_flip()` and `delete_flip()`.
801 675f78d Add `insert_list()` and `delete_list()`.
802 faaa4d0 Add flipr table.
803 591e388 Add `lists` table.
804 803e6b8 Add `insert_user()` and `change_pass()`.
805 fa650af Add users table.
806 36acafd Add app user.
807 e076e84 Initialize Sqitch configuration.
808 9ccc485 Add README text.
809 7b8dd19 First post!
810
8a9890e @theory I kant spel.
authored
811 Whoa, wait, what? Recall that we left off at commit C<803e6b8>. After that we
812 should have our two commits to the "flips" branch and end with a merge commit.
4d27feb @theory Add merge conflict example.
authored
813 But notice here we have some other stuff interleaved. Commit C<591e388> adds a
814 "lists" table before our C<faaa4d0> commit adds the "flips" table. Then there
815 is another interloper commit, C<675f78d>, which adds some functions to insert
816 and delete lists, before our C<9703969> commit adds functions to insert and
817 delete flips. And there, second from the top, is the explanation,
818 C<2fae0b3 Merge branch 'lists'>. Why, someone else was working on another
819 branch and merged stuff into master before we did! Now things are all mixed
820 up.
821
822 Well, the truth is, we got lazy. Those changes when we pulled master from the
823 origin should have raised a red flag. In truth, it's considered a bad practice
824 not to look at what's changed in C<master> before merging in a branch. What one
825 I<should> do is either:
826
827 =over
828
829 =item *
830
831 Rebase the branch from on master before merging. This "rewinds" the branch
832 changes, pulls from C<master>, and then replays the changes back on top of
833 C<master>.
834
835 =item *
836
837 Create a patch and apply I<that> to master. This is the sort of thing you
838 might have to do if you're sending changes to another user, especially if the
839 VCS is not Git.
840
841 =back
842
843 So let's restore things to how they were at master:
844
845 > git reset --hard origin/master
846 HEAD is now at 2fae0b3 Merge tag 'lists'
847
848 That throws out our merge, which thankfully we have not yet pushed. Now let's
849 go back to our branch and rebase it on C<master>:
850
851 > git checkout flips
852 Switched to branch 'flips'
853 > git rebase master
854 First, rewinding head to replay your work on top of it...
855 Applying: Add flipr table.
856 Applying: Add `insert_flip()` and `delete_flip()`.
857
858 Notice that it rewinds the changes since we branched from C<master>, pulls
859 from C<master>, and then re-applies our commits. Look at the Git log to make
860 sure things were applied properly:
861
862 > git log --oneline
863 54d680f Add `insert_flip()` and `delete_flip()`.
864 d07f3dc Add flipr table.
865 2fae0b3 Merge tag 'lists'
866 2a84155 Merge branch 'lists'
867 675f78d Add `insert_list()` and `delete_list()`.
868 591e388 Add `lists` table.
869 803e6b8 Add `insert_user()` and `change_pass()`.
870 fa650af Add users table.
871 36acafd Add app user.
872 e076e84 Initialize Sqitch configuration.
873 9ccc485 Add README text.
874 7b8dd19 Fist post!
875
876 Much better. Now all of our "flips" changes come after the "lists" changes.
877 But wait, we can't merge into C<master> quite yet. Or, at least, it's not a
878 good idea. We need to first make sure that Sqitch deployments still work
3f66ce0 @theory Handle merge ordering issue.
authored
879 properly. Why? Have a look at this:
4d27feb @theory Add merge conflict example.
authored
880
3f66ce0 @theory Handle merge ordering issue.
authored
881 > sqitch status
882 # On database flipr_test
883 # Tag: 74c49ef (unknown)
884 # Step: insert_flip
885 # Date: 2012-04-10 23:00:29
886 #
887 # Unknown tags:
888 # (use "sqitch retag" to fix)
889 # 74c49ef
890 # 28df2ve
891 #
892 # Undeployed changes:
893 # (no conflicts detected; use "sqitch deploy" to deploy the changes)
894 #
895 # 591e388
896 # - lists
897 # 675f78d
898 # - insert_list
899 # - delete_list
900
901 Uh-oh. First of all, the second line tells us that the current tag, C<74c49ef>,
902 is unknown. That's because we rebased from master, so our local commits got
903 new SHA1s. Fortunately, we can fix that problem by re-tagging:
904
905 > sqitch retag
906 Retagging flipr_test
907 . 36acafd
908 . fa650af
909 . 803e6b8
910 . v1.0.0-dev1
911 . 4aa888e
912 - 28df2ve
913 + d07f3dc
914 - 74c49ef
915 + 54d680f
916
917 Tags: 7 (2 removed, 2 added).
4d27feb @theory Add merge conflict example.
authored
918
3f66ce0 @theory Handle merge ordering issue.
authored
919 Looks like it made some important updates. Let's see:
920
921 > sqitch status
922 # On database flipr_test
923 # Tag: 54d680f
924 # Step: insert_flip
925 # Date: 2012-04-10 23:00:29
926 #
927 # Undeployed changes:
928 # (no conflicts detected; use "sqitch deploy" to deploy the changes)
929 #
930 # 591e388
931 # - lists
932 # 675f78d
933 # - insert_list
934 # - delete_list
935
936 Great, now the tag looks right. But we still have undeployed changes. This is
937 because the rebase from C<master> added the "lists" branch changes. They come
c897855 @theory I kant spel.
authored
938 I<before> our "flips" changes in the repository history, which means that,
3f66ce0 @theory Handle merge ordering issue.
authored
939 technically, the the "flips" changes have been applied out-of-order.
940 Fortunately for us, however, there appear to be no conflicts (no mutual
941 dependencies between the "flips" and "lists" changes to muck things up). So we
942 can just take its advice and run C<sqitch deploy>:
943
944 > sqitch deploy --untracked
945 Deploying 591e388 to flipr_test
946 - lists
947 Deploying 675f78d to flipr_test
948 - delete_list
949 - insert_list
950
951 So where does that leave us?
952
953 > sqitch status
954 # On database flipr_test
955 # Tag: 54d680f
956 # Step: insert_flip
957 # Date: 2012-04-10 23:32:43
958 #
959
960 Note that we are still on the C<54d680f> tag but the date has been updated.
961 Sqitch has successfully merged the "lists" changes into the database.
962
c897855 @theory I kant spel.
authored
963 What would have happened if there had been a conflict? In that case, we would
3f66ce0 @theory Handle merge ordering issue.
authored
964 have had to revert the "flips" changes and deployed again, so that the changes
c897855 @theory I kant spel.
authored
965 could be re-applied in the proper order. The commands to do that would have
966 been:
3f66ce0 @theory Handle merge ordering issue.
authored
967
968 > sqitch revert 54d680f^
969 > sqitch deploy
970
971 Note the use of C<^> at the end of C<54d680f^>. That means, "the tag just
972 before C<54d680f>", and is a nice shortcut so that we don't have to troll the
973 history to find that tag. So it would revert to that tag, and them the call to
974 C<sqitch deploy> would have deployed the "lists" changes, followed by the
975 "flips" changes, so that everything would be in the proper order
976
977 Of course, this is the sort of thing you want to avoid in a production
978 context. When doing development, you can muck with your change history in any
979 number of ways. But you really want to get things nailed down before you do a
980 release, which should have a set plan that does not change -- until the next
981 release adds new steps -- but never mixes things in.
982
983 =head2 Merges Mastered
984
985 And now, finally, we can merge into C<master>:
4d27feb @theory Add merge conflict example.
authored
986
987 > git checkout master
988 Switched to branch 'master'
989 > git merge --no-ff flips
990 Merge made by the 'recursive' strategy.
991 sql/deploy/delete_flip.sql | 12 ++++++++++++
992 sql/deploy/flips.sql | 16 ++++++++++++++++
993 sql/deploy/insert_flip.sql | 12 ++++++++++++
994 sql/revert/delete_flip.sql | 1 +
995 sql/revert/flips.sql | 2 ++
996 sql/revert/insert_flip.sql | 1 +
997 6 files changed, 44 insertions(+)
998 create mode 100644 sql/deploy/delete_flip.sql
999 create mode 100644 sql/deploy/flips.sql
1000 create mode 100644 sql/deploy/insert_flip.sql
1001 create mode 100644 sql/revert/delete_flip.sql
1002 create mode 100644 sql/revert/flips.sql
1003 create mode 100644 sql/revert/insert_flip.sql
1004
1005 And double-check our work:
1006
1007 > git log --oneline
1008 e161a90 Merge branch 'flips'
1009 54d680f Add `insert_flip()` and `delete_flip()`.
1010 d07f3dc Add flipr table.
1011 2fae0b3 Merge tag 'lists'
1012 2a84155 Merge branch 'lists'
1013 675f78d Add `insert_list()` and `delete_list()`.
1014 591e388 Add `lists` table.
1015 803e6b8 Add `insert_user()` and `change_pass()`.
1016 fa650af Add users table.
1017 36acafd Add app user.
1018 e076e84 Initialize Sqitch configuration.
1019 9ccc485 Add README text.
1020 7b8dd19 Fist post!
1021
3f66ce0 @theory Handle merge ordering issue.
authored
1022 Much much better, a nice clean master now. And because it is now identical to
1023 the "flips" branch, we can just carry on. Tag it so that we can use real tags
1024 for bundling a release later:
1025
1026 > git tag flips -am 'Tag flips merge.'
1027
Something went wrong with that request. Please try again.