Slide 1

Slide 1 text

Agile Database Development David E. Wheeler Text: Attribution-Noncommercial-Share Alike 3.0 United States: http:/ /creativecommons.org/licenses/by-nc-sa/3.0/us/ Images licensed independently and © Their respective owners. sqitch.org iovation January 28, 2016

Slide 2

Slide 2 text

Agile Database Development David E. Wheeler Text: Attribution-Noncommercial-Share Alike 3.0 United States: http:/ /creativecommons.org/licenses/by-nc-sa/3.0/us/ Images licensed independently and © Their respective owners. ✘ sqitch.org iovation January 28, 2016

Slide 3

Slide 3 text

David E. Wheeler Text: Attribution-Noncommercial-Share Alike 3.0 United States: http:/ /creativecommons.org/licenses/by-nc-sa/3.0/us/ Images licensed independently and © Their respective owners.

Slide 4

Slide 4 text

David E. Wheeler License: Attribution-Noncommercial-Share Alike 3.0 United States: http:/ /creativecommons.org/licenses/by-nc-sa/3.0/us/

Slide 5

Slide 5 text

Build My VC-Funded App for Me for Free David E. Wheeler License: Attribution-Noncommercial-Share Alike 3.0 United States: http:/ /creativecommons.org/licenses/by-nc-sa/3.0/us/ ✔ CEO, Data Architect Agile Archapelago, Inc.

Slide 6

Slide 6 text

This is Genius

Slide 7

Slide 7 text

This is Genius I had this idea

Slide 8

Slide 8 text

This is Genius I had this idea Social networking is HAWT

Slide 9

Slide 9 text

This is Genius I had this idea Social networking is HAWT Has been for waaaay too long

Slide 10

Slide 10 text

This is Genius I had this idea Social networking is HAWT Has been for waaaay too long The backlash is long overdue

Slide 11

Slide 11 text

This is Genius I had this idea Social networking is HAWT Has been for waaaay too long The backlash is long overdue Getting ahead of the curve

Slide 12

Slide 12 text

This is Genius I had this idea Social networking is HAWT Has been for waaaay too long The backlash is long overdue Getting ahead of the curve Introducing…

Slide 13

Slide 13 text

http:/ /flic.kr/p/8j5gG8 © 2010 Strongrrl. All rights reserved. Used with permission.

Slide 14

Slide 14 text

antisocial network http:/ /flic.kr/p/8j5gG8 © 2010 Strongrrl. All rights reserved. Used with permission.

Slide 15

Slide 15 text

How it Works antisocial network

Slide 16

Slide 16 text

How it Works Microblogging platform antisocial network

Slide 17

Slide 17 text

How it Works Microblogging platform Everyone follows you antisocial network

Slide 18

Slide 18 text

How it Works Microblogging platform Everyone follows you New users follow everyone antisocial network

Slide 19

Slide 19 text

How it Works Microblogging platform Everyone follows you New users follow everyone Goal: Alienate your followers antisocial network

Slide 20

Slide 20 text

How it Works Microblogging platform Everyone follows you New users follow everyone Goal: Alienate your followers Get them to unfollow you antisocial network

Slide 21

Slide 21 text

How it Works Microblogging platform Everyone follows you New users follow everyone Goal: Alienate your followers Get them to unfollow you Leaderboard: Those with fewest followers antisocial network

Slide 22

Slide 22 text

Your Task antisocial network

Slide 23

Slide 23 text

Your Task Create the database antisocial network

Slide 24

Slide 24 text

Your Task Create the database Use agile development to make it right antisocial network

Slide 25

Slide 25 text

Your Task Create the database Use agile development to make it right Contribute to VC-funded Corp antisocial network

Slide 26

Slide 26 text

Your Task Create the database Use agile development to make it right Contribute to VC-funded Corp Profit! antisocial network

Slide 27

Slide 27 text

Your Task Create the database Use agile development to make it right Contribute to VC-funded Corp Profit! For VC-funded Corp antisocial network

Slide 28

Slide 28 text

http:/ /flic.kr/p/2honiQ © 2007 James Duncan Davidson. All rights reserved. Used with permission.

Slide 29

Slide 29 text

But first… antisocial network

Slide 30

Slide 30 text

NDA antisocial network

Slide 31

Slide 31 text

Job Requirements antisocial network

Slide 32

Slide 32 text

Job Requirements PostgreSQL Should be installed antisocial network

Slide 33

Slide 33 text

Job Requirements PostgreSQL Should be installed Git Should be installed antisocial network

Slide 34

Slide 34 text

Job Requirements PostgreSQL Should be installed Git Should be installed Sqitch sudo yum install sqitch-pg antisocial network

Slide 35

Slide 35 text

Job Requirements PostgreSQL Should be installed Git Should be installed Sqitch sudo yum install sqitch-pg pgTAP sudo yum install pgtap94 antisocial network

Slide 36

Slide 36 text

Job Requirements PostgreSQL Should be installed Git Should be installed Sqitch sudo yum install sqitch-pg pgTAP sudo yum install pgtap94 pg_prove yum install perl-TAP-Parser-SourceHandler-pgTAP antisocial network

Slide 37

Slide 37 text

We good? antisocial network

Slide 38

Slide 38 text

Let’s do this thang. antisocial network

Slide 39

Slide 39 text

> Who Am I?

Slide 40

Slide 40 text

git config --global user.name 'David E. Wheeler' > > Who Am I?

Slide 41

Slide 41 text

git config --global user.name 'David E. Wheeler' > > Who Am I?

Slide 42

Slide 42 text

git config --global user.name 'David E. Wheeler' > git config --global user.email [email protected] > > Who Am I?

Slide 43

Slide 43 text

git config --global user.name 'David E. Wheeler' > git config --global user.email [email protected] > > Who Am I?

Slide 44

Slide 44 text

git config --global user.name 'David E. Wheeler' > git config --global user.email [email protected] > > Who Am I? Please use your own name and email.

Slide 45

Slide 45 text

git config --global user.name 'David E. Wheeler' > git config --global user.email [email protected] > > Who Am I? emacs ~/.gitconfig >

Slide 46

Slide 46 text

~/.gitconfig ~/ .gitconfig [user] name = David E. Wheeler email = [email protected]

Slide 47

Slide 47 text

~/.gitconfig ~/ .gitconfig [user] name = David E. Wheeler email = [email protected] Good for all projects

Slide 48

Slide 48 text

Create a Remote

Slide 49

Slide 49 text

Create a Remote Create Git project in Stash

Slide 50

Slide 50 text

Create a Remote Create Git project in Stash Or GitHub or BitBucket

Slide 51

Slide 51 text

Create a Remote Create Git project in Stash Or GitHub or BitBucket Wherever you like

Slide 52

Slide 52 text

Create a Remote Create Git project in Stash Or GitHub or BitBucket Wherever you like Record remote URL

Slide 53

Slide 53 text

Create a Remote Create Git project in Stash Or GitHub or BitBucket Wherever you like Record remote URL

Slide 54

Slide 54 text

Gitiup >

Slide 55

Slide 55 text

mkdir flipr-db > cd flipr-db > git init Initialized empty Git repository in flipr-db/.git/ > Gitiup >

Slide 56

Slide 56 text

mkdir flipr-db > cd flipr-db > git init Initialized empty Git repository in flipr-db/.git/ > Gitiup >

Slide 57

Slide 57 text

mkdir flipr-db > cd flipr-db > git init Initialized empty Git repository in flipr-db/.git/ > Gitiup > echo Flipr Database Project > README.md >

Slide 58

Slide 58 text

mkdir flipr-db > cd flipr-db > git init Initialized empty Git repository in flipr-db/.git/ > Gitiup > echo Flipr Database Project > README.md > git add . >

Slide 59

Slide 59 text

mkdir flipr-db > cd flipr-db > git init Initialized empty Git repository in flipr-db/.git/ > Gitiup > echo Flipr Database Project > README.md > git add . > git commit -m 'Initialize repo, add README.' [master (root-commit) 9531fab] Initialize repo, add README. 1 file changed, 1 insertion(+) create mode 100644 README.md >

Slide 60

Slide 60 text

mkdir flipr-db > cd flipr-db > git init Initialized empty Git repository in flipr-db/.git/ > Gitiup > echo Flipr Database Project > README.md > git add . > git commit -m 'Initialize repo, add README.' [master (root-commit) 9531fab] Initialize repo, add README. 1 file changed, 1 insertion(+) create mode 100644 README.md >

Slide 61

Slide 61 text

mkdir flipr-db > cd flipr-db > git init Initialized empty Git repository in flipr-db/.git/ > Gitiup > echo Flipr Database Project > README.md > git add . > git commit -m 'Initialize repo, add README.' [master (root-commit) 9531fab] Initialize repo, add README. 1 file changed, 1 insertion(+) create mode 100644 README.md > We have a Git repo.

Slide 62

Slide 62 text

> Origin

Slide 63

Slide 63 text

git remote add origin ssh://[email protected]:7999 > > Origin

Slide 64

Slide 64 text

git push origin --set-upstream master Counting objects: 3, done. Writing objects: 100% (3/3), 260 bytes, done. Total 3 (delta 0), reused 0 (delta 0) To ssh://[email protected]:7999/~david.wheeler/ agile-flipr.git * [new branch] master -> master Branch master set up to track remote branch master from origin. > git remote add origin ssh://[email protected]:7999 > > Origin

Slide 65

Slide 65 text

git push origin --set-upstream master Counting objects: 3, done. Writing objects: 100% (3/3), 260 bytes, done. Total 3 (delta 0), reused 0 (delta 0) To ssh://[email protected]:7999/~david.wheeler/ agile-flipr.git * [new branch] master -> master Branch master set up to track remote branch master from origin. > git remote add origin ssh://[email protected]:7999 > > Origin

Slide 66

Slide 66 text

git push origin --set-upstream master Counting objects: 3, done. Writing objects: 100% (3/3), 260 bytes, done. Total 3 (delta 0), reused 0 (delta 0) To ssh://[email protected]:7999/~david.wheeler/ agile-flipr.git * [new branch] master -> master Branch master set up to track remote branch master from origin. > git remote add origin ssh://[email protected]:7999 > > Origin

Slide 67

Slide 67 text

git push origin --set-upstream master Counting objects: 3, done. Writing objects: 100% (3/3), 260 bytes, done. Total 3 (delta 0), reused 0 (delta 0) To ssh://[email protected]:7999/~david.wheeler/ agile-flipr.git * [new branch] master -> master Branch master set up to track remote branch master from origin. > git remote add origin ssh://[email protected]:7999 > > Origin

Slide 68

Slide 68 text

Swimming Upstream >

Slide 69

Slide 69 text

git remote add upstream \ https://github.com/theory/agile-flipr.git > Swimming Upstream >

Slide 70

Slide 70 text

git remote add upstream \ https://github.com/theory/agile-flipr.git > Swimming Upstream > git fetch upstream From https://github.com/theory/agile-flipr * [new branch] appschema -> upstream/appschema * [new branch] change_pass -> upstream/change_pass * [new branch] flips -> upstream/flips * [new branch] insert_user -> upstream/insert_user * [new branch] insert_user2 -> upstream/insert_user2 * [new branch] master -> upstream/master * [new branch] reltag -> upstream/reltag * [new branch] userfuncs -> upstream/userfuncs * [new branch] users -> upstream/users >

Slide 71

Slide 71 text

git remote add upstream \ https://github.com/theory/agile-flipr.git > Swimming Upstream > git fetch upstream From https://github.com/theory/agile-flipr * [new branch] appschema -> upstream/appschema * [new branch] change_pass -> upstream/change_pass * [new branch] flips -> upstream/flips * [new branch] insert_user -> upstream/insert_user * [new branch] insert_user2 -> upstream/insert_user2 * [new branch] master -> upstream/master * [new branch] reltag -> upstream/reltag * [new branch] userfuncs -> upstream/userfuncs * [new branch] users -> upstream/users > For resetting later

Slide 72

Slide 72 text

Git? antisocial network

Slide 73

Slide 73 text

Git? Manage tree of files over time antisocial network

Slide 74

Slide 74 text

Git? Manage tree of files over time Distributed development antisocial network

Slide 75

Slide 75 text

Git? Manage tree of files over time Distributed development Commit changes locally antisocial network

Slide 76

Slide 76 text

Git? Manage tree of files over time Distributed development Commit changes locally Push to remote (origin, upstream) antisocial network

Slide 77

Slide 77 text

Git? Manage tree of files over time Distributed development Commit changes locally Push to remote (origin, upstream) Speedy, responsive antisocial network

Slide 78

Slide 78 text

Git? Manage tree of files over time Distributed development Commit changes locally Push to remote (origin, upstream) Speedy, responsive Flexible, robust antisocial network

Slide 79

Slide 79 text

Why Git? antisocial network

Slide 80

Slide 80 text

Why Git? Anyone can clone antisocial network

Slide 81

Slide 81 text

Why Git? Anyone can clone Complete repository copy antisocial network

Slide 82

Slide 82 text

Why Git? Anyone can clone Complete repository copy Cheap branching antisocial network

Slide 83

Slide 83 text

Why Git? Anyone can clone Complete repository copy Cheap branching Make and test local changes antisocial network

Slide 84

Slide 84 text

Why Git? Anyone can clone Complete repository copy Cheap branching Make and test local changes Submit patches, pull requests antisocial network

Slide 85

Slide 85 text

Why Git? Anyone can clone Complete repository copy Cheap branching Make and test local changes Submit patches, pull requests Pull from upstream antisocial network

Slide 86

Slide 86 text

PiSHA1 antisocial network

Slide 87

Slide 87 text

PiSHA1 SHA1 ID for every object antisocial network

Slide 88

Slide 88 text

PiSHA1 SHA1 ID for every object commit, tag, tree, blob antisocial network

Slide 89

Slide 89 text

PiSHA1 SHA1 ID for every object commit, tag, tree, blob Hashed commit text includes: antisocial network

Slide 90

Slide 90 text

PiSHA1 SHA1 ID for every object commit, tag, tree, blob Hashed commit text includes: tree ID antisocial network

Slide 91

Slide 91 text

PiSHA1 SHA1 ID for every object commit, tag, tree, blob Hashed commit text includes: tree ID parent ID antisocial network

Slide 92

Slide 92 text

PiSHA1 SHA1 ID for every object commit, tag, tree, blob Hashed commit text includes: tree ID parent ID author antisocial network

Slide 93

Slide 93 text

PiSHA1 SHA1 ID for every object commit, tag, tree, blob Hashed commit text includes: tree ID parent ID author committer antisocial network

Slide 94

Slide 94 text

PiSHA1 SHA1 ID for every object commit, tag, tree, blob Hashed commit text includes: tree ID parent ID author committer message antisocial network

Slide 95

Slide 95 text

> Making a hash of it

Slide 96

Slide 96 text

> git cat-file commit HEAD tree 8b0955fd015782a26953e20d41db5fadbb347c14 parent 0f38581c4d19313d910c2080b3470cae07f3694e author David Wheeler 1453941938 -0800 committer David Wheeler 1453941938 -0800 Get through "Ship it!". > Making a hash of it

Slide 97

Slide 97 text

> git cat-file commit HEAD tree 8b0955fd015782a26953e20d41db5fadbb347c14 parent 0f38581c4d19313d910c2080b3470cae07f3694e author David Wheeler 1453941938 -0800 committer David Wheeler 1453941938 -0800 Get through "Ship it!". > Making a hash of it

Slide 98

Slide 98 text

> git cat-file commit HEAD tree 8b0955fd015782a26953e20d41db5fadbb347c14 parent 0f38581c4d19313d910c2080b3470cae07f3694e author David Wheeler 1453941938 -0800 committer David Wheeler 1453941938 -0800 Get through "Ship it!". > Making a hash of it

Slide 99

Slide 99 text

> git cat-file commit HEAD tree 8b0955fd015782a26953e20d41db5fadbb347c14 parent 0f38581c4d19313d910c2080b3470cae07f3694e author David Wheeler 1453941938 -0800 committer David Wheeler 1453941938 -0800 Get through "Ship it!". > Making a hash of it

Slide 100

Slide 100 text

> git cat-file commit HEAD tree 8b0955fd015782a26953e20d41db5fadbb347c14 parent 0f38581c4d19313d910c2080b3470cae07f3694e author David Wheeler 1453941938 -0800 committer David Wheeler 1453941938 -0800 Get through "Ship it!". > Making a hash of it

Slide 101

Slide 101 text

> git cat-file commit HEAD tree 8b0955fd015782a26953e20d41db5fadbb347c14 parent 0f38581c4d19313d910c2080b3470cae07f3694e author David Wheeler 1453941938 -0800 committer David Wheeler 1453941938 -0800 Get through "Ship it!". > Making a hash of it

Slide 102

Slide 102 text

SHAzam! antisocial network

Slide 103

Slide 103 text

SHAzam! Each commit (except root) includes parent antisocial network

Slide 104

Slide 104 text

SHAzam! Each commit (except root) includes parent Can trace from any commit to the beginning antisocial network

Slide 105

Slide 105 text

SHAzam! Each commit (except root) includes parent Can trace from any commit to the beginning Tampering (corruption) detectable antisocial network

Slide 106

Slide 106 text

SHAzam! Each commit (except root) includes parent Can trace from any commit to the beginning Tampering (corruption) detectable Because the hash will be wrong antisocial network

Slide 107

Slide 107 text

SHAzam! Each commit (except root) includes parent Can trace from any commit to the beginning Tampering (corruption) detectable Because the hash will be wrong Linus Torvalds’s “greatest invention” http:/ /perl.plover.com/yak/git/ antisocial network

Slide 108

Slide 108 text

SHAzam! Each commit (except root) includes parent Can trace from any commit to the beginning Tampering (corruption) detectable Because the hash will be wrong Linus Torvalds’s “greatest invention” http:/ /perl.plover.com/yak/git/ Also: Bitcoin Blockchain antisocial network

Slide 109

Slide 109 text

antisocial network Your Turn

Slide 110

Slide 110 text

antisocial network Your Turn Configure Git

Slide 111

Slide 111 text

antisocial network Your Turn Configure Git Initialize repository

Slide 112

Slide 112 text

antisocial network Your Turn Configure Git Initialize repository Add origin remote

Slide 113

Slide 113 text

antisocial network Your Turn Configure Git Initialize repository Add origin remote Add upstream remote

Slide 114

Slide 114 text

antisocial network Your Turn Configure Git Initialize repository Add origin remote Add upstream remote https:/ /github.com/ theory/agile-flipr.git

Slide 115

Slide 115 text

antisocial network Your Turn Configure Git Initialize repository Add origin remote Add upstream remote https:/ /github.com/ theory/agile-flipr.git Go!

Slide 116

Slide 116 text

Who am I again? >

Slide 117

Slide 117 text

Who am I again? > sqitch config --user user.name 'David E. Wheeler' >

Slide 118

Slide 118 text

Who am I again? > sqitch config --user user.name 'David E. Wheeler' >

Slide 119

Slide 119 text

sqitch config --user user.email [email protected] > Who am I again? > sqitch config --user user.name 'David E. Wheeler' >

Slide 120

Slide 120 text

sqitch config --user user.email [email protected] > > Who am I again? > sqitch config --user user.name 'David E. Wheeler' > emacs ~/.sqitch/sqitch.conf >

Slide 121

Slide 121 text

~/.sqitch/sqitc ~/ .sqitch/sqitch.conf [core "pg"] client = /opt/local/pgsql/bin/psql [user] name = David E. Wheeler email = [email protected]

Slide 122

Slide 122 text

~/.sqitch/sqitc ~/ .sqitch/sqitch.conf [core "pg"] client = /opt/local/pgsql/bin/psql [user] name = David E. Wheeler email = [email protected] Good for all projects

Slide 123

Slide 123 text

> Scratch that Sqitch

Slide 124

Slide 124 text

> sqitch init flipr --engine pg \ --uri file://../flipr-remote Created sqitch.conf Created sqitch.plan Created deploy/ Created revert/ Created verify/ > > Scratch that Sqitch

Slide 125

Slide 125 text

> sqitch init flipr --engine pg \ --uri file://../flipr-remote Created sqitch.conf Created sqitch.plan Created deploy/ Created revert/ Created verify/ > > Scratch that Sqitch

Slide 126

Slide 126 text

> sqitch init flipr --engine pg \ --uri file://../flipr-remote Created sqitch.conf Created sqitch.plan Created deploy/ Created revert/ Created verify/ > > Scratch that Sqitch Use remote URL

Slide 127

Slide 127 text

> sqitch init flipr --engine pg \ --uri file://../flipr-remote Created sqitch.conf Created sqitch.plan Created deploy/ Created revert/ Created verify/ > > Scratch that Sqitch

Slide 128

Slide 128 text

> sqitch init flipr --engine pg \ --uri file://../flipr-remote Created sqitch.conf Created sqitch.plan Created deploy/ Created revert/ Created verify/ > > Scratch that Sqitch

Slide 129

Slide 129 text

> sqitch init flipr --engine pg \ --uri file://../flipr-remote Created sqitch.conf Created sqitch.plan Created deploy/ Created revert/ Created verify/ > > Scratch that Sqitch

Slide 130

Slide 130 text

> sqitch init flipr --engine pg \ --uri file://../flipr-remote Created sqitch.conf Created sqitch.plan Created deploy/ Created revert/ Created verify/ > > Scratch that Sqitch

Slide 131

Slide 131 text

> sqitch init flipr --engine pg \ --uri file://../flipr-remote Created sqitch.conf Created sqitch.plan Created deploy/ Created revert/ Created verify/ > > Scratch that Sqitch

Slide 132

Slide 132 text

> sqitch init flipr --engine pg \ --uri file://../flipr-remote Created sqitch.conf Created sqitch.plan Created deploy/ Created revert/ Created verify/ > > Scratch that Sqitch emacs sqitch.conf >

Slide 133

Slide 133 text

sqitch.conf sqitch.conf [core] engine = pg # plan_file = sqitch.plan # top_dir = . # [engine "pg"] # target = db:pg: # registry = sqitch # client = /usr/local/pgsql/bin/psql

Slide 134

Slide 134 text

sqitch.conf sqitch.conf [core] engine = pg # plan_file = sqitch.plan # top_dir = . # [engine "pg"] # target = db:pg: # registry = sqitch # client = /usr/local/pgsql/bin/psql --engine pg

Slide 135

Slide 135 text

What’s the Plan Man? >

Slide 136

Slide 136 text

What’s the Plan Man? emacs sqitch.plan > >

Slide 137

Slide 137 text

sqitch.plan sqitch.plan %syntax-version=1.0.0 %project=flipr %uri=file://../flipr-remote

Slide 138

Slide 138 text

sqitch.plan sqitch.plan %syntax-version=1.0.0 %project=flipr %uri=file://../flipr-remote Identified

Slide 139

Slide 139 text

Make It So >

Slide 140

Slide 140 text

Make It So > git add . > git commit -m 'Initialize Sqitch configuration.' [master 297c07d] Initialize Sqitch configuration. 2 files changed, 20 insertions(+) create mode 100644 sqitch.conf create mode 100644 sqitch.plan >

Slide 141

Slide 141 text

Make It So > git add . > git commit -m 'Initialize Sqitch configuration.' [master 297c07d] Initialize Sqitch configuration. 2 files changed, 20 insertions(+) create mode 100644 sqitch.conf create mode 100644 sqitch.plan >

Slide 142

Slide 142 text

Make It So > git add . > git commit -m 'Initialize Sqitch configuration.' [master 297c07d] Initialize Sqitch configuration. 2 files changed, 20 insertions(+) create mode 100644 sqitch.conf create mode 100644 sqitch.plan >

Slide 143

Slide 143 text

Make It So > git add . > git commit -m 'Initialize Sqitch configuration.' [master 297c07d] Initialize Sqitch configuration. 2 files changed, 20 insertions(+) create mode 100644 sqitch.conf create mode 100644 sqitch.plan > git push Counting objects: 5, done. Delta compression using up to 4 threads. Compressing objects: 100% (4/4), done. Writing objects: 100% (4/4), 564 bytes, done. Total 4 (delta 0), reused 0 (delta 0) To ../flipr-remote 7d28be0..297c07d master -> master >

Slide 144

Slide 144 text

Make It So > git add . > git commit -m 'Initialize Sqitch configuration.' [master 297c07d] Initialize Sqitch configuration. 2 files changed, 20 insertions(+) create mode 100644 sqitch.conf create mode 100644 sqitch.plan > git push Counting objects: 5, done. Delta compression using up to 4 threads. Compressing objects: 100% (4/4), done. Writing objects: 100% (4/4), 564 bytes, done. Total 4 (delta 0), reused 0 (delta 0) To ../flipr-remote 7d28be0..297c07d master -> master >

Slide 145

Slide 145 text

Make It So > git add . > git commit -m 'Initialize Sqitch configuration.' [master 297c07d] Initialize Sqitch configuration. 2 files changed, 20 insertions(+) create mode 100644 sqitch.conf create mode 100644 sqitch.plan > git push Counting objects: 5, done. Delta compression using up to 4 threads. Compressing objects: 100% (4/4), done. Writing objects: 100% (4/4), 564 bytes, done. Total 4 (delta 0), reused 0 (delta 0) To ../flipr-remote 7d28be0..297c07d master -> master >

Slide 146

Slide 146 text

Where’ve We Been? >

Slide 147

Slide 147 text

git log commit a4f765f88c1875ffe9427e73f72a6b66c297c07d Author: David E. Wheeler Date: Tue Jan 26 14:34:01 2016 -0800 Initialize Sqitch configuration. commit 2c4b51017929634a30f4a74e20268c05e7d28be0 Author: David E. Wheeler Date: Tue Jan 26 13:28:09 2016 -0800 Initialize repo, add README. > Where’ve We Been? >

Slide 148

Slide 148 text

git log commit a4f765f88c1875ffe9427e73f72a6b66c297c07d Author: David E. Wheeler Date: Tue Jan 26 14:34:01 2016 -0800 Initialize Sqitch configuration. commit 2c4b51017929634a30f4a74e20268c05e7d28be0 Author: David E. Wheeler Date: Tue Jan 26 13:28:09 2016 -0800 Initialize repo, add README. > Where’ve We Been? >

Slide 149

Slide 149 text

git log commit a4f765f88c1875ffe9427e73f72a6b66c297c07d Author: David E. Wheeler Date: Tue Jan 26 14:34:01 2016 -0800 Initialize Sqitch configuration. commit 2c4b51017929634a30f4a74e20268c05e7d28be0 Author: David E. Wheeler Date: Tue Jan 26 13:28:09 2016 -0800 Initialize repo, add README. > Where’ve We Been? >

Slide 150

Slide 150 text

First Change >

Slide 151

Slide 151 text

First Change > sqitch add appschema -n 'Adds flipr app schema.' Created deploy/appschema.sql Created revert/appschema.sql Created verify/appschema.sql Added "appschema" to sqitch.plan > >

Slide 152

Slide 152 text

First Change > sqitch add appschema -n 'Adds flipr app schema.' Created deploy/appschema.sql Created revert/appschema.sql Created verify/appschema.sql Added "appschema" to sqitch.plan > >

Slide 153

Slide 153 text

First Change > sqitch add appschema -n 'Adds flipr app schema.' Created deploy/appschema.sql Created revert/appschema.sql Created verify/appschema.sql Added "appschema" to sqitch.plan > >

Slide 154

Slide 154 text

First Change > sqitch add appschema -n 'Adds flipr app schema.' Created deploy/appschema.sql Created revert/appschema.sql Created verify/appschema.sql Added "appschema" to sqitch.plan > > emacs deploy/appschema.sql >

Slide 155

Slide 155 text

deploy/appschem deploy/appschema.sql -- Deploy flipr:appschema to pg BEGIN; COMMIT; -- XXX Add DDLs here.

Slide 156

Slide 156 text

deploy/appschem deploy/appschema.sql -- Deploy flipr:appschema to pg BEGIN; COMMIT; CREATE SCHEMA flipr;

Slide 157

Slide 157 text

> sqitch add appschema -n 'Adds flipr app schema.' Created deploy/appschema.sql Created revert/appschema.sql Created verify/appschema.sql Added "appschema" to sqitch.plan > First Change > emacs deploy/appschema.sql >

Slide 158

Slide 158 text

> sqitch add appschema -n 'Adds flipr app schema.' Created deploy/appschema.sql Created revert/appschema.sql Created verify/appschema.sql Added "appschema" to sqitch.plan > First Change > emacs deploy/appschema.sql > emacs revert/appschema.sql >

Slide 159

Slide 159 text

revert/appschem revert/appschema.sql -- Revert flipr:appschema from pg BEGIN; COMMIT; -- XXX Add DDLs here.

Slide 160

Slide 160 text

revert/appschem revert/appschema.sql -- Revert flipr:appschema from pg BEGIN; COMMIT; DROP SCHEMA flipr;

Slide 161

Slide 161 text

Make it So! >

Slide 162

Slide 162 text

createdb flipr_test > sqitch deploy db:pg:flipr_test Adding registry tables to db:pg:flipr_test Deploying to db:pg:flipr_test + appschema .. ok > Make it So! >

Slide 163

Slide 163 text

createdb flipr_test > sqitch deploy db:pg:flipr_test Adding registry tables to db:pg:flipr_test Deploying to db:pg:flipr_test + appschema .. ok > Make it So! > Might need -U postgres

Slide 164

Slide 164 text

createdb flipr_test > sqitch deploy db:pg:flipr_test Adding registry tables to db:pg:flipr_test Deploying to db:pg:flipr_test + appschema .. ok > Make it So! >

Slide 165

Slide 165 text

createdb flipr_test > sqitch deploy db:pg:flipr_test Adding registry tables to db:pg:flipr_test Deploying to db:pg:flipr_test + appschema .. ok > Make it So! >

Slide 166

Slide 166 text

createdb flipr_test > sqitch deploy db:pg:flipr_test Adding registry tables to db:pg:flipr_test Deploying to db:pg:flipr_test + appschema .. ok > Make it So! >

Slide 167

Slide 167 text

createdb flipr_test > sqitch deploy db:pg:flipr_test Adding registry tables to db:pg:flipr_test Deploying to db:pg:flipr_test + appschema .. ok > Make it So! >

Slide 168

Slide 168 text

createdb flipr_test > sqitch deploy db:pg:flipr_test Adding registry tables to db:pg:flipr_test Deploying to db:pg:flipr_test + appschema .. ok > Make it So! > psql -d flipr_test -c '\dn flipr' List of schemas Name | Owner -------+------- flipr | david >

Slide 169

Slide 169 text

createdb flipr_test > sqitch deploy db:pg:flipr_test Adding registry tables to db:pg:flipr_test Deploying to db:pg:flipr_test + appschema .. ok > Make it So! > psql -d flipr_test -c '\dn flipr' List of schemas Name | Owner -------+------- flipr | david > Trust, but verify

Slide 170

Slide 170 text

createdb flipr_test > sqitch deploy db:pg:flipr_test Adding registry tables to db:pg:flipr_test Deploying to db:pg:flipr_test + appschema .. ok > Make it So! > psql -d flipr_test -c '\dn flipr' List of schemas Name | Owner -------+------- flipr | david > emacs verify/appschema.sql

Slide 171

Slide 171 text

-- Verify flipr:appschema on pg BEGIN; ROLLBACK; verify/appschem verify/appschema.sql -- XXX Add verifications here.

Slide 172

Slide 172 text

-- Verify flipr:appschema on pg BEGIN; ROLLBACK; SELECT pg_catalog.has_schema_privilege('nada', 'usage'); verify/appschem verify/appschema.sql

Slide 173

Slide 173 text

-- Verify flipr:appschema on pg BEGIN; ROLLBACK; SELECT pg_catalog.has_schema_privilege('nada', 'usage'); verify/appschem verify/appschema.sql Let’s try it, first

Slide 174

Slide 174 text

Trust, But Verify > emacs verify/appschema.sql >

Slide 175

Slide 175 text

Trust, But Verify > emacs verify/appschema.sql > sqitch verify db:pg:flipr_test Verifying db:pg:flipr_test * appschema .. psql:verify/appschema.sql:5: ERROR: schema "nada" does not exist # Verify script "verify/appschema.sql" failed. not ok Verify Summary Report --------------------- Changes: 1 Errors: 1 Verify failed >

Slide 176

Slide 176 text

Trust, But Verify > emacs verify/appschema.sql > sqitch verify db:pg:flipr_test Verifying db:pg:flipr_test * appschema .. psql:verify/appschema.sql:5: ERROR: schema "nada" does not exist # Verify script "verify/appschema.sql" failed. not ok Verify Summary Report --------------------- Changes: 1 Errors: 1 Verify failed >

Slide 177

Slide 177 text

Trust, But Verify > emacs verify/appschema.sql > sqitch verify db:pg:flipr_test Verifying db:pg:flipr_test * appschema .. psql:verify/appschema.sql:5: ERROR: schema "nada" does not exist # Verify script "verify/appschema.sql" failed. not ok Verify Summary Report --------------------- Changes: 1 Errors: 1 Verify failed >

Slide 178

Slide 178 text

Trust, But Verify > emacs verify/appschema.sql > sqitch verify db:pg:flipr_test Verifying db:pg:flipr_test * appschema .. psql:verify/appschema.sql:5: ERROR: schema "nada" does not exist # Verify script "verify/appschema.sql" failed. not ok Verify Summary Report --------------------- Changes: 1 Errors: 1 Verify failed >

Slide 179

Slide 179 text

Trust, But Verify >

Slide 180

Slide 180 text

perl -i -pe 's/nada/flipr/' verify/appschema.sql > Trust, But Verify >

Slide 181

Slide 181 text

sqitch verify db:pg:flipr_test Verifying db:pg:flipr_test * appschema .. ok Verify successful > perl -i -pe 's/nada/flipr/' verify/appschema.sql > Trust, But Verify > Mo betta.

Slide 182

Slide 182 text

> How’s it Look?

Slide 183

Slide 183 text

> How’s it Look? > sqitch status db:pg:flipr_test # On database db:pg:flipr_test # Project: flipr # Change: 748346dfe73cf2af32a8b7088fd75ad8d7aecda3 # Name: appschema # Deployed: 2016-01-26 14:49:54 -0800 # By: David E. Wheeler # Nothing to deploy (up-to-date) >

Slide 184

Slide 184 text

> How’s it Look? > sqitch status db:pg:flipr_test # On database db:pg:flipr_test # Project: flipr # Change: 748346dfe73cf2af32a8b7088fd75ad8d7aecda3 # Name: appschema # Deployed: 2016-01-26 14:49:54 -0800 # By: David E. Wheeler # Nothing to deploy (up-to-date) >

Slide 185

Slide 185 text

> How’s it Look? > sqitch status db:pg:flipr_test # On database db:pg:flipr_test # Project: flipr # Change: 748346dfe73cf2af32a8b7088fd75ad8d7aecda3 # Name: appschema # Deployed: 2016-01-26 14:49:54 -0800 # By: David E. Wheeler # Nothing to deploy (up-to-date) >

Slide 186

Slide 186 text

> How’s it Look? > sqitch status db:pg:flipr_test # On database db:pg:flipr_test # Project: flipr # Change: 748346dfe73cf2af32a8b7088fd75ad8d7aecda3 # Name: appschema # Deployed: 2016-01-26 14:49:54 -0800 # By: David E. Wheeler # Nothing to deploy (up-to-date) >

Slide 187

Slide 187 text

> How’s it Look? > sqitch status db:pg:flipr_test # On database db:pg:flipr_test # Project: flipr # Change: 748346dfe73cf2af32a8b7088fd75ad8d7aecda3 # Name: appschema # Deployed: 2016-01-26 14:49:54 -0800 # By: David E. Wheeler # Nothing to deploy (up-to-date) >

Slide 188

Slide 188 text

> How’s it Look? > sqitch status db:pg:flipr_test # On database db:pg:flipr_test # Project: flipr # Change: 748346dfe73cf2af32a8b7088fd75ad8d7aecda3 # Name: appschema # Deployed: 2016-01-26 14:49:54 -0800 # By: David E. Wheeler # Nothing to deploy (up-to-date) >

Slide 189

Slide 189 text

Go Back >

Slide 190

Slide 190 text

> sqitch revert db:pg:flipr_test Revert all changes from db:pg:flipr_test? [Yes] Go Back > ▮

Slide 191

Slide 191 text

> sqitch revert db:pg:flipr_test Revert all changes from db:pg:flipr_test? [Yes] Go Back > ▮

Slide 192

Slide 192 text

> sqitch revert db:pg:flipr_test Revert all changes from db:pg:flipr_test? [Yes] Go Back > - appschema .. ok >

Slide 193

Slide 193 text

> sqitch revert db:pg:flipr_test Revert all changes from db:pg:flipr_test? [Yes] Go Back > psql -d flipr_test -c '\dn flipr' List of roles List of schemas Name | Owner ------+------- > - appschema .. ok >

Slide 194

Slide 194 text

> sqitch revert db:pg:flipr_test Revert all changes from db:pg:flipr_test? [Yes] Go Back > psql -d flipr_test -c '\dn flipr' List of roles List of schemas Name | Owner ------+------- > - appschema .. ok > sqitch status db:pg:flipr_test # On database db:pg:flipr_test No changes deployed >

Slide 195

Slide 195 text

History >

Slide 196

Slide 196 text

History > > sqitch log db:pg:flipr_test On database db:pg:flipr_test Revert 748346dfe73cf2af32a8b7088fd75ad8d7aecda3 Name: appschema Committer: David E. Wheeler Date: 2016-01-26 15:35:04 -0800 Adds flipr app schema. Deploy 748346dfe73cf2af32a8b7088fd75ad8d7aecda3 Name: appschema Committer: David E. Wheeler Date: 2016-01-26 14:49:54 -0800 Adds flipr app schema.

Slide 197

Slide 197 text

History > > sqitch log db:pg:flipr_test On database db:pg:flipr_test Revert 748346dfe73cf2af32a8b7088fd75ad8d7aecda3 Name: appschema Committer: David E. Wheeler Date: 2016-01-26 15:35:04 -0800 Adds flipr app schema. Deploy 748346dfe73cf2af32a8b7088fd75ad8d7aecda3 Name: appschema Committer: David E. Wheeler Date: 2016-01-26 14:49:54 -0800 Adds flipr app schema.

Slide 198

Slide 198 text

History > > sqitch log db:pg:flipr_test On database db:pg:flipr_test Revert 748346dfe73cf2af32a8b7088fd75ad8d7aecda3 Name: appschema Committer: David E. Wheeler Date: 2016-01-26 15:35:04 -0800 Adds flipr app schema. Deploy 748346dfe73cf2af32a8b7088fd75ad8d7aecda3 Name: appschema Committer: David E. Wheeler Date: 2016-01-26 14:49:54 -0800 Adds flipr app schema.

Slide 199

Slide 199 text

Commit It! >

Slide 200

Slide 200 text

Commit It! > git add . > git commit -m 'Add flipr schema.' [master dc23038] Add flipr schema. 4 files changed, 22 insertions(+) create mode 100644 deploy/appschema.sql create mode 100644 revert/appschema.sql create mode 100644 verify/appschema.sql >

Slide 201

Slide 201 text

Commit It! > git add . > git commit -m 'Add flipr schema.' [master dc23038] Add flipr schema. 4 files changed, 22 insertions(+) create mode 100644 deploy/appschema.sql create mode 100644 revert/appschema.sql create mode 100644 verify/appschema.sql >

Slide 202

Slide 202 text

Commit It! > git add . > git commit -m 'Add flipr schema.' [master dc23038] Add flipr schema. 4 files changed, 22 insertions(+) create mode 100644 deploy/appschema.sql create mode 100644 revert/appschema.sql create mode 100644 verify/appschema.sql >

Slide 203

Slide 203 text

Commit It! > git add . > git commit -m 'Add flipr schema.' [master dc23038] Add flipr schema. 4 files changed, 22 insertions(+) create mode 100644 deploy/appschema.sql create mode 100644 revert/appschema.sql create mode 100644 verify/appschema.sql > git push Counting objects: 11, done. Delta compression using up to 4 threads. Compressing objects: 100% (6/6), done. Writing objects: 100% (9/9), 943 bytes, done. Total 9 (delta 0), reused 0 (delta 0) To ../flipr-remote a4f765f..dc23038 master -> master

Slide 204

Slide 204 text

Commit It! > git add . > git commit -m 'Add flipr schema.' [master dc23038] Add flipr schema. 4 files changed, 22 insertions(+) create mode 100644 deploy/appschema.sql create mode 100644 revert/appschema.sql create mode 100644 verify/appschema.sql > git push Counting objects: 11, done. Delta compression using up to 4 threads. Compressing objects: 100% (6/6), done. Writing objects: 100% (9/9), 943 bytes, done. Total 9 (delta 0), reused 0 (delta 0) To ../flipr-remote a4f765f..dc23038 master -> master

Slide 205

Slide 205 text

Redeploy >

Slide 206

Slide 206 text

> sqitch deploy db:pg:flipr_test --verify Deploying changes to db:pg:flipr_test + appschema .. ok > Redeploy >

Slide 207

Slide 207 text

> sqitch deploy db:pg:flipr_test --verify Deploying changes to db:pg:flipr_test + appschema .. ok > Redeploy > Integrated!

Slide 208

Slide 208 text

> sqitch deploy db:pg:flipr_test --verify Deploying changes to db:pg:flipr_test + appschema .. ok > Redeploy >

Slide 209

Slide 209 text

> sqitch deploy db:pg:flipr_test --verify Deploying changes to db:pg:flipr_test + appschema .. ok > Redeploy > psql -d flipr_test -c '\dn flipr' List of schemas Name | Owner -------+------- flipr | david >

Slide 210

Slide 210 text

Status Update >

Slide 211

Slide 211 text

> sqitch status db:pg:flipr_test # On database db:pg:flipr_test # Project: flipr # Change: 748346dfe73cf2af32a8b7088fd75ad8d7aecda3 # Name: appschema # Deployed: 2016-01-26 15:39:31 -0800 # By: David E. Wheeler # Nothing to deploy (up-to-date) > Status Update >

Slide 212

Slide 212 text

Save My Fingers >

Slide 213

Slide 213 text

Save My Fingers > sqitch config core.target db:pg:flipr_test >

Slide 214

Slide 214 text

Save My Fingers > sqitch config core.target db:pg:flipr_test > sqitch status # On database db:pg:flipr_test # Project: flipr # Change: 748346dfe73cf2af32a8b7088fd75ad8d7aecda3 # Name: appschema # Deployed: 2016-01-26 15:39:31 -0800 # By: David E. Wheeler # Nothing to deploy (up-to-date) > No URI

Slide 215

Slide 215 text

Save My Fingers > sqitch config core.target db:pg:flipr_test > sqitch status # On database db:pg:flipr_test # Project: flipr # Change: 748346dfe73cf2af32a8b7088fd75ad8d7aecda3 # Name: appschema # Deployed: 2016-01-26 15:39:31 -0800 # By: David E. Wheeler # Nothing to deploy (up-to-date) > No URI > sqitch config --bool deploy.verify true > sqitch config --bool rebase.verify true > Always verify.

Slide 216

Slide 216 text

Commit Config >

Slide 217

Slide 217 text

Commit Config > git add . > git commit -m 'Add db_name and verify to config.' [master 795697f] Add db_name and verify to config. 1 file changed, 6 insertions(+) >

Slide 218

Slide 218 text

Commit Config > git add . > git commit -m 'Add db_name and verify to config.' [master 795697f] Add db_name and verify to config. 1 file changed, 6 insertions(+) >

Slide 219

Slide 219 text

Commit Config > git push Counting objects: 5, done. Delta compression using up to 4 threads. Compressing objects: 100% (3/3), done. Writing objects: 100% (3/3), 376 bytes, done. Total 3 (delta 2), reused 0 (delta 0) To ../flipr-remote dc23038..795697f master -> master > git add . > git commit -m 'Add db_name and verify to config.' [master 795697f] Add db_name and verify to config. 1 file changed, 6 insertions(+) >

Slide 220

Slide 220 text

Not Migrations? antisocial network

Slide 221

Slide 221 text

Not Migrations? Incomplete mini-language antisocial network

Slide 222

Slide 222 text

Not Migrations? Incomplete mini-language No logical replication integration antisocial network

Slide 223

Slide 223 text

Not Migrations? Incomplete mini-language No logical replication integration Numbered scripts difficult to track antisocial network

Slide 224

Slide 224 text

Not Migrations? Incomplete mini-language No logical replication integration Numbered scripts difficult to track No SCM awareness antisocial network

Slide 225

Slide 225 text

SQL Migrations? Incomplete mini-language No logical replication integration Numbered scripts hard to track No VCS awareness antisocial network

Slide 226

Slide 226 text

SQL Migrations? Incomplete mini-language No logical replication integration Numbered scripts hard to track No VCS awareness ——————————————— antisocial network

Slide 227

Slide 227 text

SQL Migrations? Incomplete mini-language No logical replication integration Numbered scripts hard to track No VCS awareness ——————————————— ——————————————————— antisocial network

Slide 228

Slide 228 text

SQL Migrations? Incomplete mini-language No logical replication integration Numbered scripts hard to track No VCS awareness ——————————————— ——————————————————— Managing procedures is a PITA antisocial network

Slide 229

Slide 229 text

Sq—what? sql anges ch antisocial network

Slide 230

Slide 230 text

Sq—what? sq ch antisocial network

Slide 231

Slide 231 text

it Sq—what? sq ch antisocial network

Slide 232

Slide 232 text

it Sq—what? sq ch There is no “u” antisocial network

Slide 233

Slide 233 text

Sqitch Philosophy antisocial network

Slide 234

Slide 234 text

Sqitch Philosophy No opinions antisocial network

Slide 235

Slide 235 text

Sqitch Philosophy No opinions Native scripting (psql, sqlite3, SQL*Plus) antisocial network

Slide 236

Slide 236 text

Sqitch Philosophy No opinions Native scripting (psql, sqlite3, SQL*Plus) Cross-project dependency resolution antisocial network

Slide 237

Slide 237 text

Sqitch Philosophy No opinions Native scripting (psql, sqlite3, SQL*Plus) Cross-project dependency resolution Distribution bundling antisocial network

Slide 238

Slide 238 text

Sqitch Philosophy No opinions Native scripting (psql, sqlite3, SQL*Plus) Cross-project dependency resolution Distribution bundling Integrated verification testing antisocial network

Slide 239

Slide 239 text

Sqitch Philosophy No opinions Native scripting (psql, sqlite3, SQL*Plus) Cross-project dependency resolution Distribution bundling Integrated verification testing No numbering antisocial network

Slide 240

Slide 240 text

Sqitch Philosophy No opinions Native scripting (psql, sqlite3, SQL*Plus) Cross-project dependency resolution Distribution bundling Integrated verification testing No numbering Reliable sequential deployment ordering antisocial network

Slide 241

Slide 241 text

SHAzbat antisocial network

Slide 242

Slide 242 text

SHAzbat SHA1 ID for every object antisocial network

Slide 243

Slide 243 text

SHAzbat SHA1 ID for every object Stolen from Git antisocial network

Slide 244

Slide 244 text

SHAzbat SHA1 ID for every object Stolen from Git change, tag, deploy, revert, verify antisocial network

Slide 245

Slide 245 text

SHAzbat SHA1 ID for every object Stolen from Git change, tag, deploy, revert, verify Hashed change text includes: antisocial network

Slide 246

Slide 246 text

SHAzbat SHA1 ID for every object Stolen from Git change, tag, deploy, revert, verify Hashed change text includes: Project antisocial network

Slide 247

Slide 247 text

SHAzbat SHA1 ID for every object Stolen from Git change, tag, deploy, revert, verify Hashed change text includes: Project Name antisocial network

Slide 248

Slide 248 text

SHAzbat SHA1 ID for every object Stolen from Git change, tag, deploy, revert, verify Hashed change text includes: Project Name Parent ID antisocial network

Slide 249

Slide 249 text

SHAzbat SHA1 ID for every object Stolen from Git change, tag, deploy, revert, verify Hashed change text includes: Project Name Parent ID Planner… antisocial network

Slide 250

Slide 250 text

SHAsome >

Slide 251

Slide 251 text

SHAsome > sqitch show change @HEAD project pgxn_manager uri https://github.com/pgxn/pgxn-manager.git change distview parent 39d7e105cb00e1798cfabb45f4b74cbc14a82513 planner David E. Wheeler date 2013-02-08T23:51:19Z requires + roles + pgxn_core:types + distributions + extensions Adds the filters table. >

Slide 252

Slide 252 text

SHAsome > sqitch show change @HEAD project pgxn_manager uri https://github.com/pgxn/pgxn-manager.git change distview parent 39d7e105cb00e1798cfabb45f4b74cbc14a82513 planner David E. Wheeler date 2013-02-08T23:51:19Z requires + roles + pgxn_core:types + distributions + extensions Adds the filters table. > Symbolic Sqitch tag

Slide 253

Slide 253 text

SHAsome > sqitch show change @HEAD project pgxn_manager uri https://github.com/pgxn/pgxn-manager.git change distview parent 39d7e105cb00e1798cfabb45f4b74cbc14a82513 planner David E. Wheeler date 2013-02-08T23:51:19Z requires + roles + pgxn_core:types + distributions + extensions Adds the filters table. >

Slide 254

Slide 254 text

SHAsome > sqitch show change @HEAD project pgxn_manager uri https://github.com/pgxn/pgxn-manager.git change distview parent 39d7e105cb00e1798cfabb45f4b74cbc14a82513 planner David E. Wheeler date 2013-02-08T23:51:19Z requires + roles + pgxn_core:types + distributions + extensions Adds the filters table. >

Slide 255

Slide 255 text

SHAsome > sqitch show change @HEAD project pgxn_manager uri https://github.com/pgxn/pgxn-manager.git change distview parent 39d7e105cb00e1798cfabb45f4b74cbc14a82513 planner David E. Wheeler date 2013-02-08T23:51:19Z requires + roles + pgxn_core:types + distributions + extensions Adds the filters table. >

Slide 256

Slide 256 text

SHAsome > sqitch show change @HEAD project pgxn_manager uri https://github.com/pgxn/pgxn-manager.git change distview parent 39d7e105cb00e1798cfabb45f4b74cbc14a82513 planner David E. Wheeler date 2013-02-08T23:51:19Z requires + roles + pgxn_core:types + distributions + extensions Adds the filters table. >

Slide 257

Slide 257 text

SHAsome > sqitch show change @HEAD project pgxn_manager uri https://github.com/pgxn/pgxn-manager.git change distview parent 39d7e105cb00e1798cfabb45f4b74cbc14a82513 planner David E. Wheeler date 2013-02-08T23:51:19Z requires + roles + pgxn_core:types + distributions + extensions Adds the filters table. >

Slide 258

Slide 258 text

SHAsome > sqitch show change @HEAD project pgxn_manager uri https://github.com/pgxn/pgxn-manager.git change distview parent 39d7e105cb00e1798cfabb45f4b74cbc14a82513 planner David E. Wheeler date 2013-02-08T23:51:19Z requires + roles + pgxn_core:types + distributions + extensions Adds the filters table. >

Slide 259

Slide 259 text

SHAsome > sqitch show change @HEAD project pgxn_manager uri https://github.com/pgxn/pgxn-manager.git change distview parent 39d7e105cb00e1798cfabb45f4b74cbc14a82513 planner David E. Wheeler date 2013-02-08T23:51:19Z requires + roles + pgxn_core:types + distributions + extensions Adds the filters table. >

Slide 260

Slide 260 text

SHAsome > sqitch show change @HEAD project pgxn_manager uri https://github.com/pgxn/pgxn-manager.git change distview parent 39d7e105cb00e1798cfabb45f4b74cbc14a82513 planner David E. Wheeler date 2013-02-08T23:51:19Z requires + roles + pgxn_core:types + distributions + extensions Adds the filters table. >

Slide 261

Slide 261 text

SHAsome > sqitch show change @HEAD project pgxn_manager uri https://github.com/pgxn/pgxn-manager.git change distview parent 39d7e105cb00e1798cfabb45f4b74cbc14a82513 planner David E. Wheeler date 2013-02-08T23:51:19Z requires + roles + pgxn_core:types + distributions + extensions Adds the filters table. >

Slide 262

Slide 262 text

SHApay! antisocial network

Slide 263

Slide 263 text

SHApay! Each change (except first) includes parent antisocial network

Slide 264

Slide 264 text

SHApay! Each change (except first) includes parent Can trace from any change to the beginning antisocial network

Slide 265

Slide 265 text

SHApay! Each change (except first) includes parent Can trace from any change to the beginning Change tampering (corruption) detectable antisocial network

Slide 266

Slide 266 text

SHApay! Each change (except first) includes parent Can trace from any change to the beginning Change tampering (corruption) detectable Because the hash will be wrong antisocial network

Slide 267

Slide 267 text

SHApay! Each change (except first) includes parent Can trace from any change to the beginning Change tampering (corruption) detectable Because the hash will be wrong Stole Linus Torvalds’s “greatest invention” antisocial network

Slide 268

Slide 268 text

Sqitch Features antisocial network

Slide 269

Slide 269 text

Sqitch Features Git-style interface antisocial network

Slide 270

Slide 270 text

Sqitch Features Git-style interface Reduced duplication antisocial network

Slide 271

Slide 271 text

Sqitch Features Git-style interface Reduced duplication Built-in configuration antisocial network

Slide 272

Slide 272 text

Sqitch Features Git-style interface Reduced duplication Built-in configuration Iterative development antisocial network

Slide 273

Slide 273 text

Sqitch Features Git-style interface Reduced duplication Built-in configuration Iterative development Deployment planning antisocial network

Slide 274

Slide 274 text

Sqitch Features Git-style interface Reduced duplication Built-in configuration Iterative development Deployment planning Release tagging antisocial network

Slide 275

Slide 275 text

antisocial network Your Turn

Slide 276

Slide 276 text

antisocial network Your Turn Configure Sqitch

Slide 277

Slide 277 text

antisocial network Your Turn Configure Sqitch Initialize project

Slide 278

Slide 278 text

antisocial network Your Turn Configure Sqitch Initialize project Add appschema change

Slide 279

Slide 279 text

antisocial network Your Turn Configure Sqitch Initialize project Add appschema change Deploy/Revert

Slide 280

Slide 280 text

antisocial network Your Turn Configure Sqitch Initialize project Add appschema change Deploy/Revert Commit/push

Slide 281

Slide 281 text

antisocial network Your Turn Configure Sqitch Initialize project Add appschema change Deploy/Revert Commit/push https:/ /github.com/ theory/agile-flipr.git

Slide 282

Slide 282 text

Add Tests >

Slide 283

Slide 283 text

Add Tests > mkdir test >

Slide 284

Slide 284 text

Add Tests > mkdir test > emacs test/appschema.sql >

Slide 285

Slide 285 text

test/appschema. pgTAP Basics

Slide 286

Slide 286 text

test/appschema. pgTAP Basics SET client_min_messages TO warning; CREATE EXTENSION IF NOT EXISTS pgtap; RESET client_min_messages; BEGIN; -- Plan the tests. SELECT plan(1); SELECT has_schema('nada'); -- Clean up. SELECT finish(); ROLLBACK;

Slide 287

Slide 287 text

test/appschema. pgTAP Basics SET client_min_messages TO warning; CREATE EXTENSION IF NOT EXISTS pgtap; RESET client_min_messages; BEGIN; -- Plan the tests. SELECT plan(1); SELECT has_schema('nada'); -- Clean up. SELECT finish(); ROLLBACK;

Slide 288

Slide 288 text

test/appschema. pgTAP Basics SET client_min_messages TO warning; CREATE EXTENSION IF NOT EXISTS pgtap; RESET client_min_messages; BEGIN; -- Plan the tests. SELECT plan(1); SELECT has_schema('nada'); -- Clean up. SELECT finish(); ROLLBACK;

Slide 289

Slide 289 text

test/appschema. pgTAP Basics SET client_min_messages TO warning; CREATE EXTENSION IF NOT EXISTS pgtap; RESET client_min_messages; BEGIN; -- Plan the tests. SELECT plan(1); SELECT has_schema('nada'); -- Clean up. SELECT finish(); ROLLBACK;

Slide 290

Slide 290 text

test/appschema. pgTAP Basics SET client_min_messages TO warning; CREATE EXTENSION IF NOT EXISTS pgtap; RESET client_min_messages; BEGIN; -- Plan the tests. SELECT plan(1); SELECT has_schema('nada'); -- Clean up. SELECT finish(); ROLLBACK;

Slide 291

Slide 291 text

test/appschema. pgTAP Basics SET client_min_messages TO warning; CREATE EXTENSION IF NOT EXISTS pgtap; RESET client_min_messages; BEGIN; -- Plan the tests. SELECT plan(1); SELECT has_schema('nada'); -- Clean up. SELECT finish(); ROLLBACK;

Slide 292

Slide 292 text

test/appschema. pgTAP Basics SET client_min_messages TO warning; CREATE EXTENSION IF NOT EXISTS pgtap; RESET client_min_messages; BEGIN; -- Plan the tests. SELECT plan(1); SELECT has_schema('nada'); -- Clean up. SELECT finish(); ROLLBACK;

Slide 293

Slide 293 text

> Run the Test

Slide 294

Slide 294 text

> Run the Test pg_prove -v -d flipr_test test/appschema.sql test/appschema.sql .. 1..1 not ok 1 - Schema nada should exist # Failed test 1: "Schema nada should exist" # Looks like you failed 1 test of 1 Failed 1/1 subtests Test Summary Report ------------------- test/appschema.sql (Wstat: 0 Tests: 1 Failed: 1) Failed test: 1 Files=1, Tests=1, 0 wallclock secs Result: FAIL

Slide 295

Slide 295 text

> Run the Test pg_prove -v -d flipr_test test/appschema.sql test/appschema.sql .. 1..1 not ok 1 - Schema nada should exist # Failed test 1: "Schema nada should exist" # Looks like you failed 1 test of 1 Failed 1/1 subtests Test Summary Report ------------------- test/appschema.sql (Wstat: 0 Tests: 1 Failed: 1) Failed test: 1 Files=1, Tests=1, 0 wallclock secs Result: FAIL

Slide 296

Slide 296 text

> Run the Test pg_prove -v -d flipr_test test/appschema.sql test/appschema.sql .. 1..1 not ok 1 - Schema nada should exist # Failed test 1: "Schema nada should exist" # Looks like you failed 1 test of 1 Failed 1/1 subtests Test Summary Report ------------------- test/appschema.sql (Wstat: 0 Tests: 1 Failed: 1) Failed test: 1 Files=1, Tests=1, 0 wallclock secs Result: FAIL

Slide 297

Slide 297 text

First Pass >

Slide 298

Slide 298 text

perl -i -pe 's/nada/flipr/' test/appschema.sql > First Pass >

Slide 299

Slide 299 text

perl -i -pe 's/nada/flipr/' test/appschema.sql > First Pass > > pg_prove -v -d flipr_test test/appschema.sql test/appschema.sql .. 1..1 ok 1 - Schema flipr should exist ok All tests successful. Files=1, Tests=1, 0 wallclock secs Result: PASS

Slide 300

Slide 300 text

perl -i -pe 's/nada/flipr/' test/appschema.sql > First Pass W00t! > > pg_prove -v -d flipr_test test/appschema.sql test/appschema.sql .. 1..1 ok 1 - Schema flipr should exist ok All tests successful. Files=1, Tests=1, 0 wallclock secs Result: PASS

Slide 301

Slide 301 text

Pass it On >

Slide 302

Slide 302 text

git add . > Pass it On >

Slide 303

Slide 303 text

git add . > git commit -m 'Add appschema test.' [master e46bdf9] Add appschema test. 1 file changed, 14 insertions(+) create mode 100644 test/appschema.sql > Pass it On >

Slide 304

Slide 304 text

git add . > git commit -m 'Add appschema test.' [master e46bdf9] Add appschema test. 1 file changed, 14 insertions(+) create mode 100644 test/appschema.sql > Pass it On > git push Counting objects: 5, done. Delta compression using up to 4 threads. Compressing objects: 100% (3/3), done. Writing objects: 100% (4/4), 487 bytes, done. Total 4 (delta 1), reused 0 (delta 0) To ../flipr-remote 795697f..e46bdf9 master -> master >

Slide 305

Slide 305 text

OMG TAP WTF? The Test Anything Protocol (TAP) is a protocol to allow communication between unit tests and a test harness. It allows individual tests (TAP producers) to communicate test results to the testing harness in a language-agnostic way. —Wikipedia

Slide 306

Slide 306 text

What is TAP? antisocial network

Slide 307

Slide 307 text

What does that mean in practice? What is TAP? antisocial network

Slide 308

Slide 308 text

What does that mean in practice? Test output easy to interpret What is TAP? antisocial network

Slide 309

Slide 309 text

What does that mean in practice? Test output easy to interpret By humans What is TAP? antisocial network

Slide 310

Slide 310 text

What does that mean in practice? Test output easy to interpret By humans By computers What is TAP? antisocial network

Slide 311

Slide 311 text

What does that mean in practice? Test output easy to interpret By humans By computers pg_prove (the harness) What is TAP? antisocial network

Slide 312

Slide 312 text

What does that mean in practice? Test output easy to interpret By humans By computers pg_prove (the harness) By aliens What is TAP? antisocial network

Slide 313

Slide 313 text

What does that mean in practice? Test output easy to interpret By humans By computers pg_prove (the harness) By aliens By gum! What is TAP? antisocial network

Slide 314

Slide 314 text

What’s the plan, man? antisocial network

Slide 315

Slide 315 text

What’s the plan, man? Includes Test controls: antisocial network

Slide 316

Slide 316 text

What’s the plan, man? Includes Test controls: plan() — How many tests? antisocial network

Slide 317

Slide 317 text

What’s the plan, man? Includes Test controls: plan() — How many tests? no_plan() — Unknown number of tests antisocial network

Slide 318

Slide 318 text

What’s the plan, man? Includes Test controls: plan() — How many tests? no_plan() — Unknown number of tests diag() — Diagnostic output antisocial network

Slide 319

Slide 319 text

What’s the plan, man? Includes Test controls: plan() — How many tests? no_plan() — Unknown number of tests diag() — Diagnostic output finish() — Test finished, report! antisocial network

Slide 320

Slide 320 text

Scalarly antisocial network

Slide 321

Slide 321 text

Scalarly Includes simple scalar test functions: antisocial network

Slide 322

Slide 322 text

Scalarly Includes simple scalar test functions: ok() — Boolean antisocial network

Slide 323

Slide 323 text

Scalarly Includes simple scalar test functions: ok() — Boolean is() — Value comparison antisocial network

Slide 324

Slide 324 text

Scalarly Includes simple scalar test functions: ok() — Boolean is() — Value comparison isnt() — NOT is() antisocial network

Slide 325

Slide 325 text

Scalarly Includes simple scalar test functions: ok() — Boolean is() — Value comparison isnt() — NOT is() cmp_ok() — Compare with specific operator antisocial network

Slide 326

Slide 326 text

Scalarly Includes simple scalar test functions: ok() — Boolean is() — Value comparison isnt() — NOT is() cmp_ok() — Compare with specific operator matches() — Regex comparison antisocial network

Slide 327

Slide 327 text

Scalarly Includes simple scalar test functions: ok() — Boolean is() — Value comparison isnt() — NOT is() cmp_ok() — Compare with specific operator matches() — Regex comparison imatches() — Case-insensitive regex comparison antisocial network

Slide 328

Slide 328 text

It’s All Relative antisocial network

Slide 329

Slide 329 text

It’s All Relative Includes functions for testing relations: antisocial network

Slide 330

Slide 330 text

It’s All Relative Includes functions for testing relations: results_eq() — Ordered results antisocial network

Slide 331

Slide 331 text

It’s All Relative Includes functions for testing relations: results_eq() — Ordered results set_eq() — Set of values antisocial network

Slide 332

Slide 332 text

It’s All Relative Includes functions for testing relations: results_eq() — Ordered results set_eq() — Set of values bag_eq() — Bag of values antisocial network

Slide 333

Slide 333 text

It’s All Relative Includes functions for testing relations: results_eq() — Ordered results set_eq() — Set of values bag_eq() — Bag of values row_eq() — Single row antisocial network

Slide 334

Slide 334 text

It’s All Relative Includes functions for testing relations: results_eq() — Ordered results set_eq() — Set of values bag_eq() — Bag of values row_eq() — Single row is_empty() — No results antisocial network

Slide 335

Slide 335 text

I’m Okay, You’re Okay antisocial network

Slide 336

Slide 336 text

I’m Okay, You’re Okay throws_ok() — Throws an exception antisocial network

Slide 337

Slide 337 text

I’m Okay, You’re Okay throws_ok() — Throws an exception throws_like() — Exception matches regex antisocial network

Slide 338

Slide 338 text

I’m Okay, You’re Okay throws_ok() — Throws an exception throws_like() — Exception matches regex skip() — Skip a subset of tests antisocial network

Slide 339

Slide 339 text

I’m Okay, You’re Okay throws_ok() — Throws an exception throws_like() — Exception matches regex skip() — Skip a subset of tests todo() — Expect subset of tests to fail antisocial network

Slide 340

Slide 340 text

Schematics antisocial network

Slide 341

Slide 341 text

Schematics has_table(), has_view(), has_function(), etc. antisocial network

Slide 342

Slide 342 text

Schematics has_table(), has_view(), has_function(), etc. columns_are(), has_pk(), fk_ok(), etc. antisocial network

Slide 343

Slide 343 text

Schematics has_table(), has_view(), has_function(), etc. columns_are(), has_pk(), fk_ok(), etc. col_type_is(), col_not_null(), col_default_is() antisocial network

Slide 344

Slide 344 text

Schematics has_table(), has_view(), has_function(), etc. columns_are(), has_pk(), fk_ok(), etc. col_type_is(), col_not_null(), col_default_is() So, so much more… antisocial network

Slide 345

Slide 345 text

Other Features and Topics antisocial network

Slide 346

Slide 346 text

Other Features and Topics xUnit-Style testing antisocial network

Slide 347

Slide 347 text

Other Features and Topics xUnit-Style testing Test-Driven development antisocial network

Slide 348

Slide 348 text

Other Features and Topics xUnit-Style testing Test-Driven development Integration with Perl unit tests antisocial network

Slide 349

Slide 349 text

Other Features and Topics xUnit-Style testing Test-Driven development Integration with Perl unit tests Integration with pg_regress antisocial network

Slide 350

Slide 350 text

Other Features and Topics xUnit-Style testing Test-Driven development Integration with Perl unit tests Integration with pg_regress Negative assertions antisocial network

Slide 351

Slide 351 text

Other Features and Topics xUnit-Style testing Test-Driven development Integration with Perl unit tests Integration with pg_regress Negative assertions Roles and privileges assertions antisocial network

Slide 352

Slide 352 text

Other Features and Topics xUnit-Style testing Test-Driven development Integration with Perl unit tests Integration with pg_regress Negative assertions Roles and privileges assertions http:/ /pgtap.org/ antisocial network

Slide 353

Slide 353 text

Other Features and Topics xUnit-Style testing Test-Driven development Integration with Perl unit tests Integration with pg_regress Negative assertions Roles and privileges assertions http:/ /pgtap.org/ http:/ /pgxn.org/extension/pgtap/ antisocial network

Slide 354

Slide 354 text

Other Features and Topics xUnit-Style testing Test-Driven development Integration with Perl unit tests Integration with pg_regress Negative assertions Roles and privileges assertions http:/ /pgtap.org/ http:/ /pgxn.org/extension/pgtap/ antisocial network

Slide 355

Slide 355 text

antisocial network Let’s do it!

Slide 356

Slide 356 text

antisocial network Let’s do it! Create appschema test

Slide 357

Slide 357 text

antisocial network Let’s do it! Create appschema test Use pgTAP

Slide 358

Slide 358 text

antisocial network Let’s do it! Create appschema test Use pgTAP Run test with pg_prove

Slide 359

Slide 359 text

antisocial network Let’s do it! Create appschema test Use pgTAP Run test with pg_prove Make it fail

Slide 360

Slide 360 text

antisocial network Let’s do it! Create appschema test Use pgTAP Run test with pg_prove Make it fail Make it pass!

Slide 361

Slide 361 text

antisocial network Let’s do it! Create appschema test Use pgTAP Run test with pg_prove Make it fail Make it pass! Commit/Push

Slide 362

Slide 362 text

antisocial network Let’s do it! Create appschema test Use pgTAP Run test with pg_prove Make it fail Make it pass! Commit/Push https:/ /github.com/ theory/agile-flipr.git

Slide 363

Slide 363 text

Let’s talk about… antisocial network antisocial network antisocial network

Slide 364

Slide 364 text

antisocial network antisocial network

Slide 365

Slide 365 text

TDD antisocial network antisocial network

Slide 366

Slide 366 text

No content

Slide 367

Slide 367 text

“The act of writing a unit test is more an act of design than of verification. It is also more an act of documentation than of verification. The act of writing a unit test closes a remarkable number of feedback loops, the least of which is the one per– taining to the verification of function.” —Robert C. Martin

Slide 368

Slide 368 text

antisocial network

Slide 369

Slide 369 text

TDD is an act of design. antisocial network

Slide 370

Slide 370 text

antisocial network

Slide 371

Slide 371 text

TDD is an act of documentation. antisocial network

Slide 372

Slide 372 text

antisocial network

Slide 373

Slide 373 text

Okay. antisocial network

Slide 374

Slide 374 text

antisocial network

Slide 375

Slide 375 text

But… antisocial network

Slide 376

Slide 376 text

Database Design antisocial network

Slide 377

Slide 377 text

Database Design Specify requirements antisocial network

Slide 378

Slide 378 text

Database Design Specify requirements Implement schema design antisocial network

Slide 379

Slide 379 text

Database Design Specify requirements Implement schema design Program applications antisocial network

Slide 380

Slide 380 text

Database Design Specify requirements Implement schema design Program applications QA antisocial network

Slide 381

Slide 381 text

Database Design Specify requirements Implement schema design Program applications QA Big jump! antisocial network

Slide 382

Slide 382 text

Database Design Specify requirements Implement schema design Program applications QA Pricy to fix antisocial network

Slide 383

Slide 383 text

Database Design Specify requirements Implement schema design Program applications QA antisocial network

Slide 384

Slide 384 text

Why TDDD antisocial network

Slide 385

Slide 385 text

Why TDDD Ensure data quality antisocial network

Slide 386

Slide 386 text

Why TDDD Ensure data quality Data is a core asset antisocial network

Slide 387

Slide 387 text

Why TDDD Ensure data quality Data is a core asset Validate business rules antisocial network

Slide 388

Slide 388 text

Why TDDD Ensure data quality Data is a core asset Validate business rules Stored procedures antisocial network

Slide 389

Slide 389 text

Why TDDD Ensure data quality Data is a core asset Validate business rules Stored procedures Triggers antisocial network

Slide 390

Slide 390 text

Why TDDD Ensure data quality Data is a core asset Validate business rules Stored procedures Triggers Views antisocial network

Slide 391

Slide 391 text

Why TDDD antisocial network

Slide 392

Slide 392 text

Why TDDD Identify defects early antisocial network

Slide 393

Slide 393 text

Why TDDD Identify defects early …and often! antisocial network

Slide 394

Slide 394 text

Why TDDD Identify defects early …and often! Create design iteratively antisocial network

Slide 395

Slide 395 text

Why TDDD Identify defects early …and often! Create design iteratively Evolutionarily antisocial network

Slide 396

Slide 396 text

Why TDDD Identify defects early …and often! Create design iteratively Evolutionarily Validate refactorings antisocial network

Slide 397

Slide 397 text

Why TDDD Identify defects early …and often! Create design iteratively Evolutionarily Validate refactorings Make sure nothing breaks antisocial network

Slide 398

Slide 398 text

Three Questions for Database Professionals from Scott Ambler antisocial network

Slide 399

Slide 399 text

No content

Slide 400

Slide 400 text

“If you’re implementing code in the DB in the form of stored procedures, triggers... shouldn’t you test that code to the same level that you test your app code?”

Slide 401

Slide 401 text

No content

Slide 402

Slide 402 text

“Think of all the data quality problems you’ve run into over the years. Wouldn't it have been nice if someone had originally tested and discovered those problems before you did?”

Slide 403

Slide 403 text

No content

Slide 404

Slide 404 text

“Wouldn’t it be nice to have a test suite to run so that you could determine how (and if) the DB actually works?”

Slide 405

Slide 405 text

antisocial network

Slide 406

Slide 406 text

Okay. antisocial network

Slide 407

Slide 407 text

antisocial network

Slide 408

Slide 408 text

How? antisocial network

Slide 409

Slide 409 text

TDD How antisocial network

Slide 410

Slide 410 text

TDD How Ideally separate from app tests antisocial network

Slide 411

Slide 411 text

TDD How Ideally separate from app tests May be many apps antisocial network

Slide 412

Slide 412 text

TDD How Ideally separate from app tests May be many apps DB should present interface to all antisocial network

Slide 413

Slide 413 text

TDD How Ideally separate from app tests May be many apps DB should present interface to all Apps may use different permissions antisocial network

Slide 414

Slide 414 text

TDD How Ideally separate from app tests May be many apps DB should present interface to all Apps may use different permissions Ideally use DB test Framework antisocial network

Slide 415

Slide 415 text

TDD How Ideally separate from app tests May be many apps DB should present interface to all Apps may use different permissions Ideally use DB test Framework Like…pgTAP! antisocial network

Slide 416

Slide 416 text

Branching Out >

Slide 417

Slide 417 text

git checkout -b users master Switched to a new branch 'users' > Branching Out >

Slide 418

Slide 418 text

git checkout -b users master Switched to a new branch 'users' > Branching Out > Branched off from others

Slide 419

Slide 419 text

git checkout -b users master Switched to a new branch 'users' > Branching Out > > emacs test/users.sql >

Slide 420

Slide 420 text

test/users.sql Table For One

Slide 421

Slide 421 text

SET client_min_messages TO warning; CREATE EXTENSION IF NOT EXISTS pgtap; RESET client_min_messages; BEGIN; SELECT no_plan(); SET search_path TO flipr,public; SELECT has_table( 'users' ); SELECT finish(); ROLLBACK; test/users.sql Table For One

Slide 422

Slide 422 text

SET client_min_messages TO warning; CREATE EXTENSION IF NOT EXISTS pgtap; RESET client_min_messages; BEGIN; SELECT no_plan(); SET search_path TO flipr,public; SELECT has_table( 'users' ); SELECT finish(); ROLLBACK; test/users.sql Table For One

Slide 423

Slide 423 text

SET client_min_messages TO warning; CREATE EXTENSION IF NOT EXISTS pgtap; RESET client_min_messages; BEGIN; SELECT no_plan(); SET search_path TO flipr,public; SELECT has_table( 'users' ); SELECT finish(); ROLLBACK; test/users.sql Table For One

Slide 424

Slide 424 text

SET client_min_messages TO warning; CREATE EXTENSION IF NOT EXISTS pgtap; RESET client_min_messages; BEGIN; SELECT no_plan(); SET search_path TO flipr,public; SELECT has_table( 'users' ); SELECT finish(); ROLLBACK; test/users.sql Table For One

Slide 425

Slide 425 text

Run ’Em >

Slide 426

Slide 426 text

pg_prove -d flipr_test -v test/users.sql test/users.sql .. not ok 1 - Table users should exist # Failed test 1: "Table users should exist" 1..1 # Looks like you failed 1 test of 1 Failed 1/1 subtests Test Summary Report ------------------- test/users.sql (Wstat: 0 Tests: 1 Failed: 1) Failed test: 1 Files=1, Tests=1, 0 wallclock secs Result: FAIL > Run ’Em >

Slide 427

Slide 427 text

pg_prove -d flipr_test -v test/users.sql test/users.sql .. not ok 1 - Table users should exist # Failed test 1: "Table users should exist" 1..1 # Looks like you failed 1 test of 1 Failed 1/1 subtests Test Summary Report ------------------- test/users.sql (Wstat: 0 Tests: 1 Failed: 1) Failed test: 1 Files=1, Tests=1, 0 wallclock secs Result: FAIL > Run ’Em >

Slide 428

Slide 428 text

pg_prove -d flipr_test -v test/users.sql test/users.sql .. not ok 1 - Table users should exist # Failed test 1: "Table users should exist" 1..1 # Looks like you failed 1 test of 1 Failed 1/1 subtests Test Summary Report ------------------- test/users.sql (Wstat: 0 Tests: 1 Failed: 1) Failed test: 1 Files=1, Tests=1, 0 wallclock secs Result: FAIL > Run ’Em As expected. >

Slide 429

Slide 429 text

Sqitch Dependencies! >

Slide 430

Slide 430 text

Sqitch Dependencies! > > sqitch add users --requires appschema \ -n 'Creates table to track our users.' Created deploy/users.sql Created revert/users.sql Created verify/users.sql Added "users [appschema]" to sqitch.plan >

Slide 431

Slide 431 text

Sqitch Dependencies! > > sqitch add users --requires appschema \ -n 'Creates table to track our users.' Created deploy/users.sql Created revert/users.sql Created verify/users.sql Added "users [appschema]" to sqitch.plan >

Slide 432

Slide 432 text

Sqitch Dependencies! > > sqitch add users --requires appschema \ -n 'Creates table to track our users.' Created deploy/users.sql Created revert/users.sql Created verify/users.sql Added "users [appschema]" to sqitch.plan > emacs deploy/users.sql >

Slide 433

Slide 433 text

deploy/users.sq deploy/users.sql -- XXX Add DDLs here. COMMIT; -- Deploy flipr:users to pg -- requires: appschema BEGIN; 


Slide 434

Slide 434 text

deploy/users.sq deploy/users.sql -- XXX Add DDLs here. COMMIT; -- Deploy flipr:users to pg -- requires: appschema BEGIN; 


Slide 435

Slide 435 text

SET client_min_messages = 'warning'; CREATE TABLE flipr.users ( nickname TEXT ); deploy/users.sq deploy/users.sql COMMIT; -- Deploy flipr:users to pg -- requires: appschema BEGIN; 


Slide 436

Slide 436 text

SET client_min_messages = 'warning'; CREATE TABLE flipr.users ( nickname TEXT ); deploy/users.sq deploy/users.sql COMMIT; -- Deploy flipr:users to pg -- requires: appschema BEGIN; 
 Bare Minimum

Slide 437

Slide 437 text

Verily, Users > > sqitch add users --requires appschema \ -n 'Creates table to track our users.' Created deploy/users.sql Created revert/users.sql Created verify/users.sql Added "users [appschema]" to sqitch.plan > emacs deploy/users.sql >

Slide 438

Slide 438 text

Verily, Users > > sqitch add users --requires appschema \ -n 'Creates table to track our users.' Created deploy/users.sql Created revert/users.sql Created verify/users.sql Added "users [appschema]" to sqitch.plan > emacs deploy/users.sql > emacs verify/users.sql

Slide 439

Slide 439 text

-- Verify flipr:users on pg BEGIN; verify/users.sq verify/users.sql -- XXX Add verifications here. ROLLBACK;

Slide 440

Slide 440 text

-- Verify flipr:users on pg BEGIN; SELECT nickname FROM flipr.users WHERE FALSE; verify/users.sq verify/users.sql ROLLBACK;

Slide 441

Slide 441 text

Unusered > > sqitch add users --requires appschema \ -n 'Creates table to track our users.' Created deploy/users.sql Created revert/users.sql Created verify/users.sql Added "users [appschema]" to sqitch.plan > emacs deploy/users.sql > emacs verify/users.sql >

Slide 442

Slide 442 text

Unusered > > sqitch add users --requires appschema \ -n 'Creates table to track our users.' Created deploy/users.sql Created revert/users.sql Created verify/users.sql Added "users [appschema]" to sqitch.plan > emacs deploy/users.sql > emacs verify/users.sql > > emacs revert/users.sql

Slide 443

Slide 443 text

revert/users.sq revert/users.sql -- Revert flipr:users from pg BEGIN; COMMIT; -- XXX Add DDLs here.

Slide 444

Slide 444 text

revert/users.sq revert/users.sql -- Revert flipr:users from pg BEGIN; COMMIT; DROP TABLE flipr.users;

Slide 445

Slide 445 text

Make Users >

Slide 446

Slide 446 text

sqitch deploy Deploying changes to db:pg:flipr_test + users .. ok > Make Users >

Slide 447

Slide 447 text

sqitch deploy Deploying changes to db:pg:flipr_test + users .. ok > Make Users >

Slide 448

Slide 448 text

sqitch deploy Deploying changes to db:pg:flipr_test + users .. ok > Make Users > psql -d flipr_test -c '\d flipr.users' Table "flipr.users" Column | Type | Modifiers ----------+------+----------- nickname | text | >

Slide 449

Slide 449 text

sqitch deploy Deploying changes to db:pg:flipr_test + users .. ok > Make Users > psql -d flipr_test -c '\d flipr.users' Table "flipr.users" Column | Type | Modifiers ----------+------+----------- nickname | text | > sqitch verify Verifying db:pg:flipr_test * appschema .. ok * users ...... ok Verify successful >

Slide 450

Slide 450 text

Make Users >

Slide 451

Slide 451 text

pg_prove -d flipr_test -v test/users.sql test/users.sql .. ok 1 - Table users should exist 1..1 ok All tests successful. Files=1, Tests=1, 1 wallclock secs Result: PASS > Make Users >

Slide 452

Slide 452 text

pg_prove -d flipr_test -v test/users.sql test/users.sql .. ok 1 - Table users should exist 1..1 ok All tests successful. Files=1, Tests=1, 1 wallclock secs Result: PASS > Make Users >

Slide 453

Slide 453 text

pg_prove -d flipr_test -v test/users.sql test/users.sql .. ok 1 - Table users should exist 1..1 ok All tests successful. Files=1, Tests=1, 1 wallclock secs Result: PASS > Make Users > Woohoo!

Slide 454

Slide 454 text

pg_prove -d flipr_test -v test/users.sql test/users.sql .. ok 1 - Table users should exist 1..1 ok All tests successful. Files=1, Tests=1, 1 wallclock secs Result: PASS > Make Users > emacs test/users.sql >

Slide 455

Slide 455 text

SET client_min_messages TO warning; CREATE EXTENSION IF NOT EXISTS pgtap; RESET client_min_messages; BEGIN; SELECT no_plan(); SET search_path TO flipr,public; SELECT has_table( 'users' ); test/users.sql Columnist SELECT finish(); ROLLBACK;

Slide 456

Slide 456 text

SELECT has_column( 'users', 'nickname' ); SELECT has_column( 'users', 'password' ); SELECT has_column( 'users', 'timestamp' ); SET client_min_messages TO warning; CREATE EXTENSION IF NOT EXISTS pgtap; RESET client_min_messages; BEGIN; SELECT no_plan(); SET search_path TO flipr,public; SELECT has_table( 'users' ); test/users.sql Columnist SELECT finish(); ROLLBACK;

Slide 457

Slide 457 text

Dead Again >

Slide 458

Slide 458 text

pg_prove -d flipr_test -v test/users.sql test/users.sql .. ok 1 - Table users should exist ok 2 - Column users.nickname should exist not ok 3 - Column users.password should exist # Failed test 3: "Column users.password should exist" not ok 4 - Column users."timestamp" should exist # Failed test 4: "Column users."timestamp" should exist" 1..4 # Looks like you failed 2 tests of 4 Failed 2/4 subtests Test Summary Report ------------------- test/users.sql (Wstat: 0 Tests: 4 Failed: 2) Failed tests: 3-4 Files=1, Tests=4, 0 wallclock secs Result: FAIL Dead Again >

Slide 459

Slide 459 text

pg_prove -d flipr_test -v test/users.sql test/users.sql .. ok 1 - Table users should exist ok 2 - Column users.nickname should exist not ok 3 - Column users.password should exist # Failed test 3: "Column users.password should exist" not ok 4 - Column users."timestamp" should exist # Failed test 4: "Column users."timestamp" should exist" 1..4 # Looks like you failed 2 tests of 4 Failed 2/4 subtests Test Summary Report ------------------- test/users.sql (Wstat: 0 Tests: 4 Failed: 2) Failed tests: 3-4 Files=1, Tests=4, 0 wallclock secs Result: FAIL Dead Again > Guess we should add them.

Slide 460

Slide 460 text

MOAR Deploy >

Slide 461

Slide 461 text

> emacs deploy/users.sql > MOAR Deploy >

Slide 462

Slide 462 text

-- Deploy flipr:users to pg -- requires: appschema BEGIN; SET client_min_messages = 'warning'; CREATE TABLE flipr.users ( nickname TEXT deploy/users.sq deploy/users.sql ); COMMIT;

Slide 463

Slide 463 text

-- Deploy flipr:users to pg -- requires: appschema BEGIN; SET client_min_messages = 'warning'; CREATE TABLE flipr.users ( nickname TEXT , password TEXT, timestamp TIMESTAMPTZ deploy/users.sq deploy/users.sql ); COMMIT;

Slide 464

Slide 464 text

> emacs deploy/users.sql > Update Verify >

Slide 465

Slide 465 text

> emacs deploy/users.sql > Update Verify > emacs verify/users.sql >

Slide 466

Slide 466 text

-- Verify flipr:users on pg BEGIN; SELECT nickname FROM flipr.users WHERE FALSE; COMMIT; verify/users.sq verify/users.sql

Slide 467

Slide 467 text

-- Verify flipr:users on pg BEGIN; SELECT nickname FROM flipr.users WHERE FALSE; COMMIT; , password, timestamp verify/users.sq verify/users.sql

Slide 468

Slide 468 text

Revert Overhead > emacs deploy/users.sql > emacs verify/users.sql >

Slide 469

Slide 469 text

Revert Overhead sqitch revert --to @HEAD^ -y Reverting changes to appschema from db:pg:flipr_test - users .. ok > > emacs deploy/users.sql > emacs verify/users.sql >

Slide 470

Slide 470 text

Revert Overhead sqitch revert --to @HEAD^ -y Reverting changes to appschema from db:pg:flipr_test - users .. ok > Yes, really. > emacs deploy/users.sql > emacs verify/users.sql >

Slide 471

Slide 471 text

Revert Overhead sqitch revert --to @HEAD^ -y Reverting changes to appschema from db:pg:flipr_test - users .. ok > > emacs deploy/users.sql > emacs verify/users.sql >

Slide 472

Slide 472 text

Revert Overhead sqitch revert --to @HEAD^ -y Reverting changes to appschema from db:pg:flipr_test - users .. ok > Remove > emacs deploy/users.sql > emacs verify/users.sql >

Slide 473

Slide 473 text

Revert Overhead sqitch revert --to @HEAD^ -y Reverting changes to appschema from db:pg:flipr_test - users .. ok > > emacs deploy/users.sql > emacs verify/users.sql > What’s that?

Slide 474

Slide 474 text

Sqitch Tags antisocial network

Slide 475

Slide 475 text

Sqitch Tags Start with @ antisocial network

Slide 476

Slide 476 text

Sqitch Tags Start with @ To distinguish from changes antisocial network

Slide 477

Slide 477 text

Sqitch Tags Start with @ To distinguish from changes Two symbolic tags: antisocial network

Slide 478

Slide 478 text

Sqitch Tags Start with @ To distinguish from changes Two symbolic tags: @HEAD Last change antisocial network

Slide 479

Slide 479 text

Sqitch Tags Start with @ To distinguish from changes Two symbolic tags: @HEAD Last change @ROOT First change antisocial network

Slide 480

Slide 480 text

Sqitch Tags Start with @ To distinguish from changes Two symbolic tags: @HEAD Last change @ROOT First change Two modifiers: antisocial network

Slide 481

Slide 481 text

Sqitch Tags Start with @ To distinguish from changes Two symbolic tags: @HEAD Last change @ROOT First change Two modifiers: ^ Previous change antisocial network

Slide 482

Slide 482 text

Sqitch Tags Start with @ To distinguish from changes Two symbolic tags: @HEAD Last change @ROOT First change Two modifiers: ^ Previous change ~ Following change antisocial network

Slide 483

Slide 483 text

Specifying Changes antisocial network

Slide 484

Slide 484 text

Specifying Changes users Change named “users” antisocial network

Slide 485

Slide 485 text

Specifying Changes users Change named “users” @HEAD^ Second to last change antisocial network

Slide 486

Slide 486 text

Specifying Changes users Change named “users” @HEAD^ Second to last change users^ Change before users antisocial network

Slide 487

Slide 487 text

Specifying Changes users Change named “users” @HEAD^ Second to last change users^ Change before users @ROOT~ Second change antisocial network

Slide 488

Slide 488 text

Specifying Changes users Change named “users” @HEAD^ Second to last change users^ Change before users @ROOT~ Second change appschema~ Change after appschema antisocial network

Slide 489

Slide 489 text

Specifying Changes users Change named “users” @HEAD^ Second to last change users^ Change before users @ROOT~ Second change appschema~ Change after appschema @HEAD^^ Third to last change antisocial network

Slide 490

Slide 490 text

Specifying Changes users Change named “users” @HEAD^ Second to last change users^ Change before users @ROOT~ Second change appschema~ Change after appschema @HEAD^^ Third to last change users~4 4th change after users antisocial network

Slide 491

Slide 491 text

> sqitch revert --to @HEAD^ -y Reverting changes to appschema from db:pg:flipr_test - users .. ok > Whither Users >

Slide 492

Slide 492 text

> sqitch revert --to @HEAD^ -y Reverting changes to appschema from db:pg:flipr_test - users .. ok > Whither Users > > psql -d flipr_test -c '\d flipr.users' Did not find any relation named "flipr.users". >

Slide 493

Slide 493 text

> sqitch revert --to @HEAD^ -y Reverting changes to appschema from db:pg:flipr_test - users .. ok > sqitch status # On database db:pg:flipr_test # Project: flipr # Change: 748346dfe73cf2af32a8b7088fd75ad8d7aecda3 # Name: appschema # Deployed: 2016-01-26 15:39:31 -0800 # By: David E. Wheeler # Undeployed change: * users Whither Users > > psql -d flipr_test -c '\d flipr.users' Did not find any relation named "flipr.users". >

Slide 494

Slide 494 text

Whither Users >

Slide 495

Slide 495 text

> sqitch verify Verifying db:pg:flipr_test * appschema .. ok Undeployed change: * users Verify successful > Whither Users >

Slide 496

Slide 496 text

Back At It >

Slide 497

Slide 497 text

sqitch deploy Deploying changes to db:pg:flipr_test + users .. ok > Back At It >

Slide 498

Slide 498 text

sqitch deploy Deploying changes to db:pg:flipr_test + users .. ok > Back At It > Add

Slide 499

Slide 499 text

sqitch deploy Deploying changes to db:pg:flipr_test + users .. ok > Back At It > pg_prove -d flipr_test -v test/users.sql test/users.sql .. ok 1 - Table users should exist ok 2 - Column users.nickname should exist ok 3 - Column users.password should exist ok 4 - Column users."timestamp" should exist 1..4 ok All tests successful. Files=1, Tests=4, 0 wallclock secs Result: PASS >

Slide 500

Slide 500 text

sqitch deploy Deploying changes to db:pg:flipr_test + users .. ok > Back At It > pg_prove -d flipr_test -v test/users.sql test/users.sql .. ok 1 - Table users should exist ok 2 - Column users.nickname should exist ok 3 - Column users.password should exist ok 4 - Column users."timestamp" should exist 1..4 ok All tests successful. Files=1, Tests=4, 0 wallclock secs Result: PASS > Woot!

Slide 501

Slide 501 text

sqitch deploy Deploying changes to db:pg:flipr_test + users .. ok > Back At It > pg_prove -d flipr_test -v test/users.sql test/users.sql .. ok 1 - Table users should exist ok 2 - Column users.nickname should exist ok 3 - Column users.password should exist ok 4 - Column users."timestamp" should exist 1..4 ok All tests successful. Files=1, Tests=4, 0 wallclock secs Result: PASS > emacs test/users.sql

Slide 502

Slide 502 text

SET search_path = public,tap; BEGIN; SELECT * FROM no_plan(); SELECT has_table( 'users' ); SELECT has_column( 'users', 'timestamp' ); test/users.sql SELECT has_column( 'users', 'nickname' ); SELECT has_column( 'users', 'password' ); SELECT finish(); ROLLBACK;

Slide 503

Slide 503 text

SET search_path = public,tap; BEGIN; SELECT * FROM no_plan(); SELECT has_table( 'users' ); SELECT has_column( 'users', 'timestamp' ); test/users.sql SELECT has_column( 'users', 'nickname' ); SELECT has_column( 'users', 'password' ); SELECT has_pk( 'users' ); SELECT finish(); ROLLBACK;

Slide 504

Slide 504 text

SELECT col_type_is( 'users', 'nickname', 'text' ); SELECT col_hasnt_default( 'users', 'nickname' ); SELECT col_is_pk( 'users', 'nickname' ); SET search_path = public,tap; BEGIN; SELECT * FROM no_plan(); SELECT has_table( 'users' ); SELECT has_column( 'users', 'timestamp' ); test/users.sql SELECT has_column( 'users', 'nickname' ); SELECT has_column( 'users', 'password' ); SELECT has_pk( 'users' ); SELECT finish(); ROLLBACK;

Slide 505

Slide 505 text

SELECT col_type_is( 'users', 'nickname', 'text' ); SELECT col_hasnt_default( 'users', 'nickname' ); SELECT col_is_pk( 'users', 'nickname' ); SET search_path = public,tap; BEGIN; SELECT * FROM no_plan(); SELECT has_table( 'users' ); SELECT has_column( 'users', 'timestamp' ); test/users.sql SELECT has_column( 'users', 'nickname' ); SELECT has_column( 'users', 'password' ); SELECT has_pk( 'users' ); SELECT col_type_is( 'users', 'password', 'text' ); SELECT col_not_null( 'users', 'password' ); SELECT col_hasnt_default( 'users', 'password' ); SELECT finish(); ROLLBACK;

Slide 506

Slide 506 text

SELECT col_type_is( 'users', 'nickname', 'text' ); SELECT col_hasnt_default( 'users', 'nickname' ); SELECT col_is_pk( 'users', 'nickname' ); SET search_path = public,tap; BEGIN; SELECT * FROM no_plan(); SELECT has_table( 'users' ); SELECT has_column( 'users', 'timestamp' ); test/users.sql SELECT has_column( 'users', 'nickname' ); SELECT has_column( 'users', 'password' ); SELECT has_pk( 'users' ); SELECT col_type_is('users', 'timestamp', 'timestamp with time zone'); SELECT col_not_null( 'users', 'timestamp' ); SELECT col_has_default( 'users', 'timestamp' ); SELECT col_default_is( 'users', 'timestamp', 'now()' ); SELECT col_type_is( 'users', 'password', 'text' ); SELECT col_not_null( 'users', 'password' ); SELECT col_hasnt_default( 'users', 'password' ); SELECT finish(); ROLLBACK;

Slide 507

Slide 507 text

Columny >

Slide 508

Slide 508 text

> pg_prove -d flipr_test test/users.sql test/users.sql .. 1/? # Failed test 2: "Table users should have a primary key" # Failed test 6: "Column users(nickname) should be a primary key" # have: NULL # want: {nickname} # Failed test 9: "Column users.password should be NOT NULL" # Failed test 13: "Column users."timestamp" should be NOT NULL" # Failed test 14: "Column users."timestamp" should have a default" # Failed test 15: "Column users."timestamp" should default to 'now()'" # Column users."timestamp" has no default # Looks like you failed 6 tests of 15 test/users.sql .. Failed 6/15 subtests Test Summary Report ------------------- test/users.sql (Wstat: 0 Tests: 15 Failed: 6) Failed tests: 2, 6, 9, 13-15 Files=1, Tests=15, 0 wallclock secs Result: FAIL Columny >

Slide 509

Slide 509 text

> pg_prove -d flipr_test test/users.sql test/users.sql .. 1/? # Failed test 2: "Table users should have a primary key" # Failed test 6: "Column users(nickname) should be a primary key" # have: NULL # want: {nickname} # Failed test 9: "Column users.password should be NOT NULL" # Failed test 13: "Column users."timestamp" should be NOT NULL" # Failed test 14: "Column users."timestamp" should have a default" # Failed test 15: "Column users."timestamp" should default to 'now()'" # Column users."timestamp" has no default # Looks like you failed 6 tests of 15 test/users.sql .. Failed 6/15 subtests Test Summary Report ------------------- test/users.sql (Wstat: 0 Tests: 15 Failed: 6) Failed tests: 2, 6, 9, 13-15 Files=1, Tests=15, 0 wallclock secs Result: FAIL Columny > Let’s make it so.

Slide 510

Slide 510 text

User Typography >

Slide 511

Slide 511 text

emacs deploy/users.sql > User Typography >

Slide 512

Slide 512 text

-- Deploy flipr:users to pg -- requires: appschema BEGIN; SET client_min_messages = 'warning'; CREATE TABLE flipr.users ( nickname TEXT password TEXT timestamp TIMESTAMPTZ ); COMMIT; deploy/users.sq deploy/users.sql , ,

Slide 513

Slide 513 text

-- Deploy flipr:users to pg -- requires: appschema BEGIN; SET client_min_messages = 'warning'; CREATE TABLE flipr.users ( nickname TEXT password TEXT timestamp TIMESTAMPTZ ); COMMIT; deploy/users.sq deploy/users.sql , PRIMARY KEY,

Slide 514

Slide 514 text

-- Deploy flipr:users to pg -- requires: appschema BEGIN; SET client_min_messages = 'warning'; CREATE TABLE flipr.users ( nickname TEXT password TEXT timestamp TIMESTAMPTZ ); COMMIT; deploy/users.sq deploy/users.sql PRIMARY KEY, NOT NULL,

Slide 515

Slide 515 text

-- Deploy flipr:users to pg -- requires: appschema BEGIN; SET client_min_messages = 'warning'; CREATE TABLE flipr.users ( nickname TEXT password TEXT timestamp TIMESTAMPTZ ); COMMIT; deploy/users.sq deploy/users.sql PRIMARY KEY, NOT NULL, NOT NULL DEFAULT NOW()

Slide 516

Slide 516 text

User Typography > emacs deploy/users.sql >

Slide 517

Slide 517 text

sqitch rebase @HEAD^ -y Reverting changes to appschema from db:pg:flipr_test - users .. ok Deploying changes to db:pg:flipr_test + users .. ok > User Typography > emacs deploy/users.sql >

Slide 518

Slide 518 text

sqitch rebase @HEAD^ -y Reverting changes to appschema from db:pg:flipr_test - users .. ok Deploying changes to db:pg:flipr_test + users .. ok > User Typography > emacs deploy/users.sql >

Slide 519

Slide 519 text

sqitch rebase @HEAD^ -y Reverting changes to appschema from db:pg:flipr_test - users .. ok Deploying changes to db:pg:flipr_test + users .. ok > User Typography > emacs deploy/users.sql >

Slide 520

Slide 520 text

sqitch rebase @HEAD^ -y Reverting changes to appschema from db:pg:flipr_test - users .. ok Deploying changes to db:pg:flipr_test + users .. ok > User Typography > emacs deploy/users.sql > pg_prove -d flipr_test test/users.sql test/users.sql .. ok All tests successful. Files=1, Tests=15, 0 wallclock secs Result: PASS >

Slide 521

Slide 521 text

sqitch rebase @HEAD^ -y Reverting changes to appschema from db:pg:flipr_test - users .. ok Deploying changes to db:pg:flipr_test + users .. ok > User Typography > emacs deploy/users.sql > pg_prove -d flipr_test test/users.sql test/users.sql .. ok All tests successful. Files=1, Tests=15, 0 wallclock secs Result: PASS > Boom.

Slide 522

Slide 522 text

Additives >

Slide 523

Slide 523 text

Additives > git add . >

Slide 524

Slide 524 text

Additives > git add . > git commit -am 'Add users table.' [users 610b318] Add users table. 5 files changed, 59 insertions(+) create mode 100644 deploy/users.sql create mode 100644 revert/users.sql create mode 100644 test/users.sql create mode 100644 verify/users.sql >

Slide 525

Slide 525 text

Pushers >

Slide 526

Slide 526 text

Pushers > git push --set-upstream origin users Counting objects: 17, done. Delta compression using up to 4 threads. Compressing objects: 100% (11/11), done. Writing objects: 100% (11/11), 1.53 KiB, done. Total 11 (delta 1), reused 0 (delta 0) To ../flipr-remote * [new branch] users -> users Branch users set up to track remote branch users from origin. >

Slide 527

Slide 527 text

Pushers > git push --set-upstream origin users Counting objects: 17, done. Delta compression using up to 4 threads. Compressing objects: 100% (11/11), done. Writing objects: 100% (11/11), 1.53 KiB, done. Total 11 (delta 1), reused 0 (delta 0) To ../flipr-remote * [new branch] users -> users Branch users set up to track remote branch users from origin. >

Slide 528

Slide 528 text

Pushers > git push --set-upstream origin users Counting objects: 17, done. Delta compression using up to 4 threads. Compressing objects: 100% (11/11), done. Writing objects: 100% (11/11), 1.53 KiB, done. Total 11 (delta 1), reused 0 (delta 0) To ../flipr-remote * [new branch] users -> users Branch users set up to track remote branch users from origin. >

Slide 529

Slide 529 text

Wash, Rinse, Repeat antisocial network

Slide 530

Slide 530 text

Wash, Rinse, Repeat Add simple failing test antisocial network

Slide 531

Slide 531 text

Wash, Rinse, Repeat Add simple failing test Add and deploy change antisocial network

Slide 532

Slide 532 text

Wash, Rinse, Repeat Add simple failing test Add and deploy change Revise test antisocial network

Slide 533

Slide 533 text

Wash, Rinse, Repeat Add simple failing test Add and deploy change Revise test Revise and rebase change antisocial network

Slide 534

Slide 534 text

Wash, Rinse, Repeat Add simple failing test Add and deploy change Revise test Revise and rebase change Wash, Rinse, Repeat antisocial network

Slide 535

Slide 535 text

Wash, Rinse, Repeat Add simple failing test Add and deploy change Revise test Revise and rebase change Wash, Rinse, Repeat Commit/Push when done antisocial network

Slide 536

Slide 536 text

Wash, Rinse, Repeat Add simple failing test Add and deploy change Revise test Revise and rebase change Wash, Rinse, Repeat Commit/Push when done Breathe in, breathe out antisocial network

Slide 537

Slide 537 text

Caution: Hard Reset Ahead

Slide 538

Slide 538 text

Caution: Hard Reset Ahead A rare destructive Git command

Slide 539

Slide 539 text

Caution: Hard Reset Ahead A rare destructive Git command Deletes HEAD snapshot

Slide 540

Slide 540 text

Caution: Hard Reset Ahead A rare destructive Git command Deletes HEAD snapshot Replaces it with new snapshot

Slide 541

Slide 541 text

Caution: Hard Reset Ahead A rare destructive Git command Deletes HEAD snapshot Replaces it with new snapshot Almost un-reversible

Slide 542

Slide 542 text

Caution: Hard Reset Ahead A rare destructive Git command Deletes HEAD snapshot Replaces it with new snapshot Almost un-reversible Useful for starting from known point

Slide 543

Slide 543 text

Caution: Hard Reset Ahead A rare destructive Git command Deletes HEAD snapshot Replaces it with new snapshot Almost un-reversible Useful for starting from known point USE WITH CAUTION!

Slide 544

Slide 544 text

Time to Work! antisocial network

Slide 545

Slide 545 text

Time to Work! Prepare to hack! antisocial network

Slide 546

Slide 546 text

Time to Work! Prepare to hack! git checkout master antisocial network

Slide 547

Slide 547 text

Time to Work! Prepare to hack! git checkout master git branch -D users antisocial network

Slide 548

Slide 548 text

Time to Work! Prepare to hack! git checkout master git branch -D users git checkout -b users antisocial network

Slide 549

Slide 549 text

Time to Work! Prepare to hack! git checkout master git branch -D users git checkout -b users git reset --hard upstream/users antisocial network

Slide 550

Slide 550 text

Time to Work! Prepare to hack! git checkout master git branch -D users git checkout -b users git reset --hard upstream/users git log antisocial network

Slide 551

Slide 551 text

Time to Work! Prepare to hack! git checkout master git branch -D users git checkout -b users git reset --hard upstream/users git log Should be at “Add users table.” antisocial network

Slide 552

Slide 552 text

antisocial network Flip Out

Slide 553

Slide 553 text

antisocial network Flip Out Create flips branch

Slide 554

Slide 554 text

antisocial network Flip Out Create flips branch Create flips table

Slide 555

Slide 555 text

antisocial network Flip Out Create flips branch Create flips table flip_id SERIAL PK

Slide 556

Slide 556 text

antisocial network Flip Out Create flips branch Create flips table flip_id SERIAL PK nickname FK

Slide 557

Slide 557 text

antisocial network Flip Out Create flips branch Create flips table flip_id SERIAL PK nickname FK body TEXT

Slide 558

Slide 558 text

antisocial network Flip Out Create flips branch Create flips table flip_id SERIAL PK nickname FK body TEXT timestamptz

Slide 559

Slide 559 text

antisocial network Flip Out Create flips branch Create flips table flip_id SERIAL PK nickname FK body TEXT timestamptz Use TDDD

Slide 560

Slide 560 text

antisocial network Flip Out Create flips branch Create flips table flip_id SERIAL PK nickname FK body TEXT timestamptz Use TDDD https:/ /github.com/ theory/agile-flipr.git

Slide 561

Slide 561 text

Functional Testing >

Slide 562

Slide 562 text

Functional Testing git checkout -b userfuncs users Switched to a new branch 'userfuncs' > > Branches from users

Slide 563

Slide 563 text

Functional Testing git checkout -b userfuncs users Switched to a new branch 'userfuncs' > > sqitch add insert_user -r appschema -r users \ -n 'Creates a function to insert a user.' Created deploy/insert_user.sql Created revert/insert_user.sql Created verify/insert_user.sql Added "insert_user [appschema users]" to sqitch.plan >

Slide 564

Slide 564 text

Functional Testing git checkout -b userfuncs users Switched to a new branch 'userfuncs' > > sqitch add insert_user -r appschema -r users \ -n 'Creates a function to insert a user.' Created deploy/insert_user.sql Created revert/insert_user.sql Created verify/insert_user.sql Added "insert_user [appschema users]" to sqitch.plan > emacs test/insert_user.sql >

Slide 565

Slide 565 text

test/insert_use test/insert_user.sql

Slide 566

Slide 566 text

test/insert_use test/insert_user.sql SET client_min_messages TO warning; CREATE EXTENSION IF NOT EXISTS pgtap; RESET client_min_messages; SET search_path TO flipr,public;

Slide 567

Slide 567 text

test/insert_use test/insert_user.sql SET client_min_messages TO warning; CREATE EXTENSION IF NOT EXISTS pgtap; RESET client_min_messages; SET search_path TO flipr,public;

Slide 568

Slide 568 text

test/insert_use test/insert_user.sql SET client_min_messages TO warning; CREATE EXTENSION IF NOT EXISTS pgtap; RESET client_min_messages; SET search_path TO flipr,public; -- Plan the tests. BEGIN; SELECT plan(11);

Slide 569

Slide 569 text

test/insert_use test/insert_user.sql SET client_min_messages TO warning; CREATE EXTENSION IF NOT EXISTS pgtap; RESET client_min_messages; SET search_path TO flipr,public; -- Plan the tests. BEGIN; SELECT plan(11);

Slide 570

Slide 570 text

test/insert_use SELECT plan(11);

Slide 571

Slide 571 text

test/insert_use SELECT plan(11); SELECT has_function( 'insert_user' ); SELECT has_function( 'insert_user', ARRAY['text', 'text'] ); SELECT function_lang_is( 'insert_user', ARRAY['text', 'text'], 'sql' ); SELECT function_returns( 'insert_user', ARRAY['text', 'text'], 'void' ); SELECT volatility_is( 'insert_user', ARRAY['text', 'text'], 'volatile' );

Slide 572

Slide 572 text

test/insert_use SELECT plan(11); SELECT has_function( 'insert_user' ); SELECT has_function( 'insert_user', ARRAY['text', 'text'] ); SELECT function_lang_is( 'insert_user', ARRAY['text', 'text'], 'sql' ); SELECT function_returns( 'insert_user', ARRAY['text', 'text'], 'void' ); SELECT volatility_is( 'insert_user', ARRAY['text', 'text'], 'volatile' );

Slide 573

Slide 573 text

test/insert_use SELECT plan(11); SELECT has_function( 'insert_user' ); SELECT has_function( 'insert_user', ARRAY['text', 'text'] ); SELECT function_lang_is( 'insert_user', ARRAY['text', 'text'], 'sql' ); SELECT function_returns( 'insert_user', ARRAY['text', 'text'], 'void' ); SELECT volatility_is( 'insert_user', ARRAY['text', 'text'], 'volatile' );

Slide 574

Slide 574 text

test/insert_use SELECT plan(11); SELECT has_function( 'insert_user' ); SELECT has_function( 'insert_user', ARRAY['text', 'text'] ); SELECT function_lang_is( 'insert_user', ARRAY['text', 'text'], 'sql' ); SELECT function_returns( 'insert_user', ARRAY['text', 'text'], 'void' ); SELECT volatility_is( 'insert_user', ARRAY['text', 'text'], 'volatile' );

Slide 575

Slide 575 text

test/insert_use SELECT plan(11); SELECT has_function( 'insert_user' ); SELECT has_function( 'insert_user', ARRAY['text', 'text'] ); SELECT function_lang_is( 'insert_user', ARRAY['text', 'text'], 'sql' ); SELECT function_returns( 'insert_user', ARRAY['text', 'text'], 'void' ); SELECT volatility_is( 'insert_user', ARRAY['text', 'text'], 'volatile' );

Slide 576

Slide 576 text

test/insert_use test/insert_user.sql 'volatile' );

Slide 577

Slide 577 text

test/insert_use test/insert_user.sql 'volatile' ); SELECT lives_ok( $$ SELECT insert_user('theory', 'foo') $$, 'Insert a user' ); SELECT row_eq( 'SELECT * FROM users', ROW('theory', md5('foo'), NOW())::users, 'The user should have been inserted' );

Slide 578

Slide 578 text

test/insert_use test/insert_user.sql 'volatile' ); SELECT lives_ok( $$ SELECT insert_user('theory', 'foo') $$, 'Insert a user' ); SELECT row_eq( 'SELECT * FROM users', ROW('theory', md5('foo'), NOW())::users, 'The user should have been inserted' );

Slide 579

Slide 579 text

test/insert_use test/insert_user.sql 'volatile' ); SELECT lives_ok( $$ SELECT insert_user('theory', 'foo') $$, 'Insert a user' ); SELECT row_eq( 'SELECT * FROM users', ROW('theory', md5('foo'), NOW())::users, 'The user should have been inserted' );

Slide 580

Slide 580 text

test/insert_use test/insert_user.sql 'volatile' ); SELECT lives_ok( $$ SELECT insert_user('theory', 'foo') $$, 'Insert a user' ); SELECT row_eq( 'SELECT * FROM users', ROW('theory', md5('foo'), NOW())::users, 'The user should have been inserted' );

Slide 581

Slide 581 text

test/insert_use test/insert_user.sql 'volatile' ); SELECT lives_ok( $$ SELECT insert_user('theory', 'foo') $$, 'Insert a user' ); SELECT row_eq( 'SELECT * FROM users', ROW('theory', md5('foo'), NOW())::users, 'The user should have been inserted' );

Slide 582

Slide 582 text

test/insert_use test/insert_user.sql 'The user should have been inserted' );

Slide 583

Slide 583 text

test/insert_use test/insert_user.sql 'The user should have been inserted' ); SELECT lives_ok( $$ SELECT insert_user('strongrrl', 'w00t') $$, 'Insert another user' ); SELECT bag_eq( 'SELECT * FROM users', $$ VALUES ('theory', md5('foo'), NOW()), ('strongrrl', md5('w00t'), NOW()) $$, 'Both users should be present' );

Slide 584

Slide 584 text

test/insert_use test/insert_user.sql 'The user should have been inserted' ); SELECT lives_ok( $$ SELECT insert_user('strongrrl', 'w00t') $$, 'Insert another user' ); SELECT bag_eq( 'SELECT * FROM users', $$ VALUES ('theory', md5('foo'), NOW()), ('strongrrl', md5('w00t'), NOW()) $$, 'Both users should be present' );

Slide 585

Slide 585 text

test/insert_use test/insert_user.sql 'The user should have been inserted' ); SELECT lives_ok( $$ SELECT insert_user('strongrrl', 'w00t') $$, 'Insert another user' ); SELECT bag_eq( 'SELECT * FROM users', $$ VALUES ('theory', md5('foo'), NOW()), ('strongrrl', md5('w00t'), NOW()) $$, 'Both users should be present' ); Includes dupes

Slide 586

Slide 586 text

test/insert_use test/insert_user.sql 'The user should have been inserted' ); SELECT lives_ok( $$ SELECT insert_user('strongrrl', 'w00t') $$, 'Insert another user' ); SELECT bag_eq( 'SELECT * FROM users', $$ VALUES ('theory', md5('foo'), NOW()), ('strongrrl', md5('w00t'), NOW()) $$, 'Both users should be present' );

Slide 587

Slide 587 text

test/insert_use test/insert_user.sql 'The user should have been inserted' ); SELECT lives_ok( $$ SELECT insert_user('strongrrl', 'w00t') $$, 'Insert another user' ); SELECT bag_eq( 'SELECT * FROM users', $$ VALUES ('theory', md5('foo'), NOW()), ('strongrrl', md5('w00t'), NOW()) $$, 'Both users should be present' );

Slide 588

Slide 588 text

test/insert_use 'Both users should be present' );

Slide 589

Slide 589 text

SELECT throws_ok( $$ SELECT insert_user('theory', 'ha-ha') $$, 23505, -- duplicate key violation NULL, -- localized error message 'Should get an error for duplicate nickname' ); SELECT bag_eq( 'SELECT * FROM users', $$ VALUES ('theory', md5('foo'), NOW()), ('strongrrl', md5('w00t'), NOW()) $$, 'Should still have just the two users' ); test/insert_use 'Both users should be present' );

Slide 590

Slide 590 text

SELECT throws_ok( $$ SELECT insert_user('theory', 'ha-ha') $$, 23505, -- duplicate key violation NULL, -- localized error message 'Should get an error for duplicate nickname' ); SELECT bag_eq( 'SELECT * FROM users', $$ VALUES ('theory', md5('foo'), NOW()), ('strongrrl', md5('w00t'), NOW()) $$, 'Should still have just the two users' ); test/insert_use 'Both users should be present' );

Slide 591

Slide 591 text

SELECT throws_ok( $$ SELECT insert_user('theory', 'ha-ha') $$, 23505, -- duplicate key violation NULL, -- localized error message 'Should get an error for duplicate nickname' ); SELECT bag_eq( 'SELECT * FROM users', $$ VALUES ('theory', md5('foo'), NOW()), ('strongrrl', md5('w00t'), NOW()) $$, 'Should still have just the two users' ); test/insert_use 'Both users should be present' ); Appendix A

Slide 592

Slide 592 text

SELECT throws_ok( $$ SELECT insert_user('theory', 'ha-ha') $$, 23505, -- duplicate key violation NULL, -- localized error message 'Should get an error for duplicate nickname' ); SELECT bag_eq( 'SELECT * FROM users', $$ VALUES ('theory', md5('foo'), NOW()), ('strongrrl', md5('w00t'), NOW()) $$, 'Should still have just the two users' ); test/insert_use 'Both users should be present' );

Slide 593

Slide 593 text

SELECT throws_ok( $$ SELECT insert_user('theory', 'ha-ha') $$, 23505, -- duplicate key violation NULL, -- localized error message 'Should get an error for duplicate nickname' ); SELECT bag_eq( 'SELECT * FROM users', $$ VALUES ('theory', md5('foo'), NOW()), ('strongrrl', md5('w00t'), NOW()) $$, 'Should still have just the two users' ); test/insert_use 'Both users should be present' );

Slide 594

Slide 594 text

SELECT throws_ok( $$ SELECT insert_user('theory', 'ha-ha') $$, 23505, -- duplicate key violation NULL, -- localized error message 'Should get an error for duplicate nickname' ); SELECT bag_eq( 'SELECT * FROM users', $$ VALUES ('theory', md5('foo'), NOW()), ('strongrrl', md5('w00t'), NOW()) $$, 'Should still have just the two users' ); test/insert_use 'Both users should be present' );

Slide 595

Slide 595 text

SELECT throws_ok( $$ SELECT insert_user('theory', 'ha-ha') $$, 23505, -- duplicate key violation NULL, -- localized error message 'Should get an error for duplicate nickname' ); SELECT bag_eq( 'SELECT * FROM users', $$ VALUES ('theory', md5('foo'), NOW()), ('strongrrl', md5('w00t'), NOW()) $$, 'Should still have just the two users' ); test/insert_use 'Both users should be present' ); SELECT finish(); ROLLBACK;

Slide 596

Slide 596 text

Functional Testing emacs test/insert_user.sql > >

Slide 597

Slide 597 text

Functional Testing emacs test/insert_user.sql > > emacs deploy/insert_user.sql >

Slide 598

Slide 598 text

deploy/insert_u deploy/insert_user.sql -- Deploy flipr:insert_user to pg -- requires: appschema -- requires: users BEGIN; -- XXX Add DDLs here. COMMIT;

Slide 599

Slide 599 text

deploy/insert_u deploy/insert_user.sql -- Deploy flipr:insert_user to pg -- requires: appschema -- requires: users BEGIN; CREATE OR REPLACE FUNCTION flipr.insert_user( nickname TEXT, password TEXT ) RETURNS VOID LANGUAGE SQL SECURITY DEFINER AS $$ INSERT INTO flipr.users VALUES($1, md5($2)); $$; COMMIT;

Slide 600

Slide 600 text

Functional Testing emacs deploy/insert_user.sql > >

Slide 601

Slide 601 text

Functional Testing emacs deploy/insert_user.sql > > emacs revert/insert_user.sql >

Slide 602

Slide 602 text

revert/insert_u revert/insert_user.sql -- Revert flipr:insert_user to pg BEGIN; COMMIT; -- XXX Add DDLs here.

Slide 603

Slide 603 text

revert/insert_u revert/insert_user.sql -- Revert flipr:insert_user to pg BEGIN; COMMIT; DROP FUNCTION flipr.insert_user(TEXT, TEXT);

Slide 604

Slide 604 text

Functional Testing emacs revert/insert_user.sql > >

Slide 605

Slide 605 text

Functional Testing emacs revert/insert_user.sql > > emacs verify/insert_user.sql >

Slide 606

Slide 606 text

verify/insert_u verify/insert_user.sql -- Verify flipr:insert_user to pg BEGIN; -- XXX Add DDLs here. ROLLBACK;

Slide 607

Slide 607 text

verify/insert_u verify/insert_user.sql -- Verify flipr:insert_user to pg BEGIN; SELECT has_function_privilege( 'flipr.insert_user(text, text)', 'execute' ); ROLLBACK;

Slide 608

Slide 608 text

verify/insert_u verify/insert_user.sql -- Verify flipr:insert_user to pg BEGIN; SELECT has_function_privilege( 'flipr.insert_user(text, text)', 'execute' ); ROLLBACK; Convenient!

Slide 609

Slide 609 text

We Good? emacs verify/insert_user.sql > >

Slide 610

Slide 610 text

We Good? emacs verify/insert_user.sql > > pg_prove -d flipr_test test/*.sql test/appschema.sql .... ok test/insert_user.sql .. 1/11 # Failed test 1: "Function insert_user() should exis # Failed test 2: "Function insert_user(text, text) s # Failed test 3: "Function insert_user(text, text) s # Function insert_user(text, text) does not exis # Failed test 4: "Function insert_user(text, text) s # Function insert_user(text, text) does not exis # Failed test 6: "Insert a user" # died: 42883: function insert_user(unknown, # Failed test 7: "The user should have been inserted # have: NULL # want: (theory,acbd18db4cc2f85cedef654fccc4

Slide 611

Slide 611 text

We Good? emacs verify/insert_user.sql > > pg_prove -d flipr_test test/*.sql test/appschema.sql .... ok test/insert_user.sql .. 1/11 # Failed test 1: "Function insert_user() should exis # Failed test 2: "Function insert_user(text, text) s # Failed test 3: "Function insert_user(text, text) s # Function insert_user(text, text) does not exis # Failed test 4: "Function insert_user(text, text) s # Function insert_user(text, text) does not exis # Failed test 6: "Insert a user" # died: 42883: function insert_user(unknown, # Failed test 7: "The user should have been inserted # have: NULL # want: (theory,acbd18db4cc2f85cedef654fccc4 Yay!

Slide 612

Slide 612 text

We Good? test/insert_user.sql Failed tests: 1-11 Files=3, Tests=27, 0 wallclock secs Result: FAIL >

Slide 613

Slide 613 text

We Good? test/insert_user.sql Failed tests: 1-11 Files=3, Tests=27, 0 wallclock secs Result: FAIL > sqitch deploy Deploying changes to db:pg:flipr_test + insert_user .. ok >

Slide 614

Slide 614 text

We Good? test/insert_user.sql Failed tests: 1-11 Files=3, Tests=27, 0 wallclock secs Result: FAIL > pg_prove -d flipr_test test/*.sql test/appschema.sql .... ok test/insert_user.sql .. ok test/users.sql ........ ok All tests successful. Files=3, Tests=27, 0 wallclock secs Result: PASS > sqitch deploy Deploying changes to db:pg:flipr_test + insert_user .. ok >

Slide 615

Slide 615 text

Commitment >

Slide 616

Slide 616 text

git add . > git commit -m 'Add `insert_user()`.' [userfuncs 40eabe1] Add `insert_user()`. 6 files changed, 101 insertions(+) create mode 100644 -n create mode 100644 deploy/insert_user.sql create mode 100644 revert/insert_user.sql create mode 100644 test/insert_user.sql create mode 100644 verify/insert_user.sql > Commitment >

Slide 617

Slide 617 text

Push It Real Good… >

Slide 618

Slide 618 text

git push origin --set-upstream userfuncs Counting objects: 18, done. Delta compression using up to 4 threads. Compressing objects: 100% (11/11), done. Writing objects: 100% (12/12), 1.96 KiB, done. Total 12 (delta 1), reused 0 (delta 0) To ../flipr-remote * [new branch] userfuncs -> userfuncs Branch userfuncs set up to track remote branch userfuncs from origin. > Push It Real Good… >

Slide 619

Slide 619 text

git push origin --set-upstream userfuncs Counting objects: 18, done. Delta compression using up to 4 threads. Compressing objects: 100% (11/11), done. Writing objects: 100% (12/12), 1.96 KiB, done. Total 12 (delta 1), reused 0 (delta 0) To ../flipr-remote * [new branch] userfuncs -> userfuncs Branch userfuncs set up to track remote branch userfuncs from origin. > Push It Real Good… >

Slide 620

Slide 620 text

git push origin --set-upstream userfuncs Counting objects: 18, done. Delta compression using up to 4 threads. Compressing objects: 100% (11/11), done. Writing objects: 100% (12/12), 1.96 KiB, done. Total 12 (delta 1), reused 0 (delta 0) To ../flipr-remote * [new branch] userfuncs -> userfuncs Branch userfuncs set up to track remote branch userfuncs from origin. > Push It Real Good… >

Slide 621

Slide 621 text

Reset, Mes Amis! antisocial network

Slide 622

Slide 622 text

Reset, Mes Amis! git checkout users antisocial network

Slide 623

Slide 623 text

Reset, Mes Amis! git checkout users git revert -y antisocial network

Slide 624

Slide 624 text

Reset, Mes Amis! git checkout users git revert -y git reset --hard upstream/users antisocial network

Slide 625

Slide 625 text

Reset, Mes Amis! git checkout users git revert -y git reset --hard upstream/users git checkout -b userfuncs antisocial network

Slide 626

Slide 626 text

Reset, Mes Amis! git checkout users git revert -y git reset --hard upstream/users git checkout -b userfuncs git reset --hard upstream/insert_user antisocial network

Slide 627

Slide 627 text

Reset, Mes Amis! git checkout users git revert -y git reset --hard upstream/users git checkout -b userfuncs git reset --hard upstream/insert_user git deploy antisocial network

Slide 628

Slide 628 text

antisocial network None Shall Pass

Slide 629

Slide 629 text

antisocial network None Shall Pass Create change_pass()

Slide 630

Slide 630 text

antisocial network None Shall Pass Create change_pass() Params:

Slide 631

Slide 631 text

antisocial network None Shall Pass Create change_pass() Params: nickname

Slide 632

Slide 632 text

antisocial network None Shall Pass Create change_pass() Params: nickname old_pass

Slide 633

Slide 633 text

antisocial network None Shall Pass Create change_pass() Params: nickname old_pass new_pass

Slide 634

Slide 634 text

antisocial network None Shall Pass Create change_pass() Params: nickname old_pass new_pass Only update if old pass correct

Slide 635

Slide 635 text

antisocial network None Shall Pass Create change_pass() Params: nickname old_pass new_pass Only update if old pass correct Use TDDD

Slide 636

Slide 636 text

antisocial network None Shall Pass Create change_pass() Params: nickname old_pass new_pass Only update if old pass correct Use TDDD https:/ /github.com/ theory/agile-flipr.git

Slide 637

Slide 637 text

Resets >

Slide 638

Slide 638 text

> sqitch revert -y > git reset --hard upstream/change_pass HEAD is now at 048017a Add `change_pass()`. > Resets > My solution

Slide 639

Slide 639 text

> sqitch revert -y > git reset --hard upstream/change_pass HEAD is now at 048017a Add `change_pass()`. > git checkout master > Resets >

Slide 640

Slide 640 text

> sqitch revert -y > git reset --hard upstream/change_pass HEAD is now at 048017a Add `change_pass()`. > git reset --hard upstream/appschema HEAD is now at e46bdf9 Add appschema test. > git checkout master > Resets >

Slide 641

Slide 641 text

> sqitch revert -y > git reset --hard upstream/change_pass HEAD is now at 048017a Add `change_pass()`. > git reset --hard upstream/appschema HEAD is now at e46bdf9 Add appschema test. > git checkout master > Resets > Known good.

Slide 642

Slide 642 text

> sqitch revert -y > git reset --hard upstream/change_pass HEAD is now at 048017a Add `change_pass()`. > git reset --hard upstream/appschema HEAD is now at e46bdf9 Add appschema test. > git checkout master > Resets > Known good. sqitch deploy

Slide 643

Slide 643 text

Mergers and Acquisitions >

Slide 644

Slide 644 text

git merge users Updating d72aeb4..c343b84 Fast-forward deploy/users.sql | 13 +++++++++++++ revert/users.sql | 7 +++++++ sqitch.plan | 1 + test/users.sql | 29 +++++++++++++++++++++++++++++ verify/users.sql | 9 +++++++++ 5 files changed, 59 insertions(+) create mode 100644 deploy/users.sql create mode 100644 revert/users.sql create mode 100644 test/users.sql create mode 100644 verify/users.sql > Mergers and Acquisitions >

Slide 645

Slide 645 text

git merge users Updating d72aeb4..c343b84 Fast-forward deploy/users.sql | 13 +++++++++++++ revert/users.sql | 7 +++++++ sqitch.plan | 1 + test/users.sql | 29 +++++++++++++++++++++++++++++ verify/users.sql | 9 +++++++++ 5 files changed, 59 insertions(+) create mode 100644 deploy/users.sql create mode 100644 revert/users.sql create mode 100644 test/users.sql create mode 100644 verify/users.sql > Mergers and Acquisitions > So far…

Slide 646

Slide 646 text

Mergers and Acquisitions >

Slide 647

Slide 647 text

> git merge flips Updating c343b84..d6f4ee2 Fast-forward deploy/flips.sql | 15 +++++++++++++++ revert/flips.sql | 7 +++++++ sqitch.plan | 1 + test/flips.sql | 39 +++++++++++++++++++++++++++++++++++++ verify/flips.sql | 12 ++++++++++++ 5 files changed, 74 insertions(+) create mode 100644 deploy/flips.sql create mode 100644 revert/flips.sql create mode 100644 test/flips.sql create mode 100644 verify/flips.sql > Mergers and Acquisitions >

Slide 648

Slide 648 text

> git merge flips Updating c343b84..d6f4ee2 Fast-forward deploy/flips.sql | 15 +++++++++++++++ revert/flips.sql | 7 +++++++ sqitch.plan | 1 + test/flips.sql | 39 +++++++++++++++++++++++++++++++++++++ verify/flips.sql | 12 ++++++++++++ 5 files changed, 74 insertions(+) create mode 100644 deploy/flips.sql create mode 100644 revert/flips.sql create mode 100644 test/flips.sql create mode 100644 verify/flips.sql > Mergers and Acquisitions > So good…

Slide 649

Slide 649 text

Mergers and Acquisitions >

Slide 650

Slide 650 text

> git merge userfuncs Auto-merging sqitch.plan CONFLICT (content): Merge conflict in sqitch.plan Automatic merge failed; fix conflicts and then commit the result. > Mergers and Acquisitions >

Slide 651

Slide 651 text

> git merge userfuncs Auto-merging sqitch.plan CONFLICT (content): Merge conflict in sqitch.plan Automatic merge failed; fix conflicts and then commit the result. > Mergers and Acquisitions >

Slide 652

Slide 652 text

> git merge userfuncs Auto-merging sqitch.plan CONFLICT (content): Merge conflict in sqitch.plan Automatic merge failed; fix conflicts and then commit the result. > Mergers and Acquisitions >

Slide 653

Slide 653 text

> git merge userfuncs Auto-merging sqitch.plan CONFLICT (content): Merge conflict in sqitch.plan Automatic merge failed; fix conflicts and then commit the result. > Mergers and Acquisitions > Wha???

Slide 654

Slide 654 text

Back in Time… >

Slide 655

Slide 655 text

Back in Time… git checkout -b userfuncs users Switched to a new branch 'userfuncs' > >

Slide 656

Slide 656 text

Back in Time… git checkout -b userfuncs users Switched to a new branch 'userfuncs' > > Ah-ha!

Slide 657

Slide 657 text

Branching Out antisocial network

Slide 658

Slide 658 text

Branching Out users branched from master antisocial network

Slide 659

Slide 659 text

Branching Out users branched from master flips branched from users antisocial network

Slide 660

Slide 660 text

Branching Out users branched from master flips branched from users userfuncs branched from users antisocial network

Slide 661

Slide 661 text

Branching Out users branched from master flips branched from users userfuncs branched from users users and flips merged to master antisocial network

Slide 662

Slide 662 text

Branching Out users branched from master flips branched from users userfuncs branched from users users and flips merged to master userfuncs unaware of flips antisocial network

Slide 663

Slide 663 text

Backbrancher master A

Slide 664

Slide 664 text

Backbrancher master users A branch

Slide 665

Slide 665 text

Backbrancher master users A B Add users table branch

Slide 666

Slide 666 text

Backbrancher master users A B flips branch branch

Slide 667

Slide 667 text

Backbrancher master users A B flips C Add flips table branch branch

Slide 668

Slide 668 text

Backbrancher master users A B flips C userfuncs branch branch branch

Slide 669

Slide 669 text

Backbrancher master users A B flips C userfuncs Add insert_user function D branch branch branch

Slide 670

Slide 670 text

Backbrancher master users A B flips C userfuncs D branch branch branch E Add change_pass function

Slide 671

Slide 671 text

Backbrancher master users A B flips C userfuncs B merge B D branch branch branch E

Slide 672

Slide 672 text

Backbrancher master users A B flips C userfuncs B merge B C merge C D branch branch branch E

Slide 673

Slide 673 text

Backbrancher master users A B flips C userfuncs B merge B C merge C D F merge D & E branch branch branch E

Slide 674

Slide 674 text

Backbrancher master users A B flips C userfuncs B merge B C merge C D No F merge D & E branch branch branch E

Slide 675

Slide 675 text

Backbrancher master users A B flips C userfuncs B merge B C merge C D conflict! branch branch branch E

Slide 676

Slide 676 text

Backbrancher master users A B flips C userfuncs B merge B C merge C D conflict! Now what? branch branch branch E

Slide 677

Slide 677 text

Rebase userfuncs master users A B flips C userfuncs B merge B C merge C branch branch branch D E

Slide 678

Slide 678 text

Rebase userfuncs master users A B flips C userfuncs B merge B C merge C branch branch branch Last common with master: B

Slide 679

Slide 679 text

Rebase userfuncs master users A B flips C userfuncs B merge B C merge C branch branch branch C

Slide 680

Slide 680 text

Rebase userfuncs master users A B flips C userfuncs B merge B C merge C branch branch branch C D Rebased E

Slide 681

Slide 681 text

Rebase userfuncs master users A B flips C userfuncs B merge B C merge C branch branch branch C D E merge D & E E

Slide 682

Slide 682 text

\o/ Rebase userfuncs master users A B flips C userfuncs B merge B C merge C branch branch branch C D E merge D & E E

Slide 683

Slide 683 text

Reset >

Slide 684

Slide 684 text

sqitch revert -y > git reset --hard HEAD HEAD is now at d6f4ee2 Add flips table. > Reset >

Slide 685

Slide 685 text

sqitch revert -y > git reset --hard HEAD HEAD is now at d6f4ee2 Add flips table. > Reset > Use with care!

Slide 686

Slide 686 text

sqitch revert -y > git reset --hard HEAD HEAD is now at d6f4ee2 Add flips table. > Reset >

Slide 687

Slide 687 text

sqitch revert -y > git reset --hard HEAD HEAD is now at d6f4ee2 Add flips table. > Reset > git checkout userfuncs Switched to branch 'userfuncs' >

Slide 688

Slide 688 text

sqitch revert -y > git reset --hard HEAD HEAD is now at d6f4ee2 Add flips table. > Reset > git checkout userfuncs Switched to branch 'userfuncs' > sqitch deploy >

Slide 689

Slide 689 text

Rebase >

Slide 690

Slide 690 text

> git rebase master First, rewinding head to replay your work on top of it... Applying: Add `insert_user()`. Using index info to reconstruct a base tree... M sqitch.plan Falling back to patching base and 3-way merge... Auto-merging sqitch.plan CONFLICT (content): Merge conflict in sqitch.plan Failed to merge in the changes. Patch failed at 0001 Add `insert_user()`. The copy of the patch that failed is found in: /Users/david/Desktop/flipr-db/.git/rebase-apply/patch When you have resolved this problem, run "git rebase --contin If you prefer to skip this patch, run "git rebase --skip" ins To check out the original branch and stop rebasing, run "git rebase --abort". > Rebase >

Slide 691

Slide 691 text

> git rebase master First, rewinding head to replay your work on top of it... Applying: Add `insert_user()`. Using index info to reconstruct a base tree... M sqitch.plan Falling back to patching base and 3-way merge... Auto-merging sqitch.plan CONFLICT (content): Merge conflict in sqitch.plan Failed to merge in the changes. Patch failed at 0001 Add `insert_user()`. The copy of the patch that failed is found in: /Users/david/Desktop/flipr-db/.git/rebase-apply/patch When you have resolved this problem, run "git rebase --contin If you prefer to skip this patch, run "git rebase --skip" ins To check out the original branch and stop rebasing, run "git rebase --abort". > Rebase > Back to B, apply C.

Slide 692

Slide 692 text

> git rebase master First, rewinding head to replay your work on top of it... Applying: Add `insert_user()`. Using index info to reconstruct a base tree... M sqitch.plan Falling back to patching base and 3-way merge... Auto-merging sqitch.plan CONFLICT (content): Merge conflict in sqitch.plan Failed to merge in the changes. Patch failed at 0001 Add `insert_user()`. The copy of the patch that failed is found in: /Users/david/Desktop/flipr-db/.git/rebase-apply/patch When you have resolved this problem, run "git rebase --contin If you prefer to skip this patch, run "git rebase --skip" ins To check out the original branch and stop rebasing, run "git rebase --abort". > Rebase > That’s D

Slide 693

Slide 693 text

> git rebase master First, rewinding head to replay your work on top of it... Applying: Add `insert_user()`. Using index info to reconstruct a base tree... M sqitch.plan Falling back to patching base and 3-way merge... Auto-merging sqitch.plan CONFLICT (content): Merge conflict in sqitch.plan Failed to merge in the changes. Patch failed at 0001 Add `insert_user()`. The copy of the patch that failed is found in: /Users/david/Desktop/flipr-db/.git/rebase-apply/patch When you have resolved this problem, run "git rebase --contin If you prefer to skip this patch, run "git rebase --skip" ins To check out the original branch and stop rebasing, run "git rebase --abort". > Rebase > Here comes D…

Slide 694

Slide 694 text

> git rebase master First, rewinding head to replay your work on top of it... Applying: Add `insert_user()`. Using index info to reconstruct a base tree... M sqitch.plan Falling back to patching base and 3-way merge... Auto-merging sqitch.plan CONFLICT (content): Merge conflict in sqitch.plan Failed to merge in the changes. Patch failed at 0001 Add `insert_user()`. The copy of the patch that failed is found in: /Users/david/Desktop/flipr-db/.git/rebase-apply/patch When you have resolved this problem, run "git rebase --contin If you prefer to skip this patch, run "git rebase --skip" ins To check out the original branch and stop rebasing, run "git rebase --abort". > Rebase > D’oh!

Slide 695

Slide 695 text

> git rebase master First, rewinding head to replay your work on top of it... Applying: Add `insert_user()`. Using index info to reconstruct a base tree... M sqitch.plan Falling back to patching base and 3-way merge... Auto-merging sqitch.plan CONFLICT (content): Merge conflict in sqitch.plan Failed to merge in the changes. Patch failed at 0001 Add `insert_user()`. The copy of the patch that failed is found in: /Users/david/Desktop/flipr-db/.git/rebase-apply/patch When you have resolved this problem, run "git rebase --contin If you prefer to skip this patch, run "git rebase --skip" ins To check out the original branch and stop rebasing, run "git rebase --abort". > Rebase >

Slide 696

Slide 696 text

Wha Happen? antisocial network

Slide 697

Slide 697 text

Wha Happen? Same conflict antisocial network

Slide 698

Slide 698 text

Wha Happen? Same conflict Both branches modified sqitch.plan antisocial network

Slide 699

Slide 699 text

Wha Happen? Same conflict Both branches modified sqitch.plan The same line! antisocial network

Slide 700

Slide 700 text

Wha Happen? >

Slide 701

Slide 701 text

> git diff diff --cc sqitch.plan index 16c537f,f6949a6..0000000 --- a/sqitch.plan +++ b/sqitch.plan @@@ -4,4 -4,4 +4,8 @@@ appschema 2016-01-26T22:47:50Z David E. Wheeler >>>>>> Add `insert_user()`. > Wha Happen? >

Slide 702

Slide 702 text

> git diff diff --cc sqitch.plan index 16c537f,f6949a6..0000000 --- a/sqitch.plan +++ b/sqitch.plan @@@ -4,4 -4,4 +4,8 @@@ appschema 2016-01-26T22:47:50Z David E. Wheeler >>>>>> Add `insert_user()`. > Wha Happen? >

Slide 703

Slide 703 text

> git diff diff --cc sqitch.plan index 16c537f,f6949a6..0000000 --- a/sqitch.plan +++ b/sqitch.plan @@@ -4,4 -4,4 +4,8 @@@ appschema 2016-01-26T22:47:50Z David E. Wheeler >>>>>> Add `insert_user()`. > Wha Happen? > B

Slide 704

Slide 704 text

> git diff diff --cc sqitch.plan index 16c537f,f6949a6..0000000 --- a/sqitch.plan +++ b/sqitch.plan @@@ -4,4 -4,4 +4,8 @@@ appschema 2016-01-26T22:47:50Z David E. Wheeler >>>>>> Add `insert_user()`. > Wha Happen? > C B

Slide 705

Slide 705 text

> git diff diff --cc sqitch.plan index 16c537f,f6949a6..0000000 --- a/sqitch.plan +++ b/sqitch.plan @@@ -4,4 -4,4 +4,8 @@@ appschema 2016-01-26T22:47:50Z David E. Wheeler >>>>>> Add `insert_user()`. > Wha Happen? > C D B

Slide 706

Slide 706 text

Scratch that Sqitch antisocial network

Slide 707

Slide 707 text

Scratch that Sqitch Screwed either way? antisocial network

Slide 708

Slide 708 text

Scratch that Sqitch Screwed either way? Fortunately, this is Git antisocial network

Slide 709

Slide 709 text

Scratch that Sqitch Screwed either way? Fortunately, this is Git Tell it to treat Sqitch plans differently antisocial network

Slide 710

Slide 710 text

Scratch that Sqitch Screwed either way? Fortunately, this is Git Tell it to treat Sqitch plans differently Changes on single lines antisocial network

Slide 711

Slide 711 text

Scratch that Sqitch Screwed either way? Fortunately, this is Git Tell it to treat Sqitch plans differently Changes on single lines Only appended to plan file antisocial network

Slide 712

Slide 712 text

Scratch that Sqitch Screwed either way? Fortunately, this is Git Tell it to treat Sqitch plans differently Changes on single lines Only appended to plan file Use the “union” merge antisocial network

Slide 713

Slide 713 text

Re: Union Merge

Slide 714

Slide 714 text

Re: Union Merge Run 3-way file level merge for text files, but take lines from both versions, instead of leaving conflict markers. This tends to leave the added lines in the resulting file in random order and the user should verify the result. Do not use this if you do not understand the implications. —Git Manual

Slide 715

Slide 715 text

Hallelunion antisocial network

Slide 716

Slide 716 text

Hallelunion Just appends lines antisocial network

Slide 717

Slide 717 text

Hallelunion Just appends lines Exactly how changes work antisocial network

Slide 718

Slide 718 text

Hallelunion Just appends lines Exactly how changes work Let’s clean up our mess antisocial network

Slide 719

Slide 719 text

Hallelunion Just appends lines Exactly how changes work Let’s clean up our mess And try again antisocial network

Slide 720

Slide 720 text

Reemerge >

Slide 721

Slide 721 text

git rebase --abort > Reemerge >

Slide 722

Slide 722 text

echo sqitch.plan merge=union > .gitattributes > git rebase --abort > Reemerge >

Slide 723

Slide 723 text

echo sqitch.plan merge=union > .gitattributes > git rebase --abort > git rebase master First, rewinding head to replay your work on top of it... Applying: Add `insert_user()`. Using index info to reconstruct a base tree... M sqitch.plan Falling back to patching base and 3-way merge... Auto-merging sqitch.plan Applying: Add `change_pass()`. Using index info to reconstruct a base tree... M sqitch.plan Falling back to patching base and 3-way merge... Auto-merging sqitch.plan > Reemerge >

Slide 724

Slide 724 text

echo sqitch.plan merge=union > .gitattributes > git rebase --abort > git rebase master First, rewinding head to replay your work on top of it... Applying: Add `insert_user()`. Using index info to reconstruct a base tree... M sqitch.plan Falling back to patching base and 3-way merge... Auto-merging sqitch.plan Applying: Add `change_pass()`. Using index info to reconstruct a base tree... M sqitch.plan Falling back to patching base and 3-way merge... Auto-merging sqitch.plan > Reemerge > Back to B, applies C

Slide 725

Slide 725 text

echo sqitch.plan merge=union > .gitattributes > git rebase --abort > git rebase master First, rewinding head to replay your work on top of it... Applying: Add `insert_user()`. Using index info to reconstruct a base tree... M sqitch.plan Falling back to patching base and 3-way merge... Auto-merging sqitch.plan Applying: Add `change_pass()`. Using index info to reconstruct a base tree... M sqitch.plan Falling back to patching base and 3-way merge... Auto-merging sqitch.plan > Reemerge > That’s D

Slide 726

Slide 726 text

echo sqitch.plan merge=union > .gitattributes > git rebase --abort > git rebase master First, rewinding head to replay your work on top of it... Applying: Add `insert_user()`. Using index info to reconstruct a base tree... M sqitch.plan Falling back to patching base and 3-way merge... Auto-merging sqitch.plan Applying: Add `change_pass()`. Using index info to reconstruct a base tree... M sqitch.plan Falling back to patching base and 3-way merge... Auto-merging sqitch.plan > Reemerge > Union merge

Slide 727

Slide 727 text

echo sqitch.plan merge=union > .gitattributes > git rebase --abort > git rebase master First, rewinding head to replay your work on top of it... Applying: Add `insert_user()`. Using index info to reconstruct a base tree... M sqitch.plan Falling back to patching base and 3-way merge... Auto-merging sqitch.plan Applying: Add `change_pass()`. Using index info to reconstruct a base tree... M sqitch.plan Falling back to patching base and 3-way merge... Auto-merging sqitch.plan > Reemerge > That’s E

Slide 728

Slide 728 text

echo sqitch.plan merge=union > .gitattributes > git rebase --abort > git rebase master First, rewinding head to replay your work on top of it... Applying: Add `insert_user()`. Using index info to reconstruct a base tree... M sqitch.plan Falling back to patching base and 3-way merge... Auto-merging sqitch.plan Applying: Add `change_pass()`. Using index info to reconstruct a base tree... M sqitch.plan Falling back to patching base and 3-way merge... Auto-merging sqitch.plan > Reemerge > Union merge

Slide 729

Slide 729 text

echo sqitch.plan merge=union > .gitattributes > git rebase --abort > git rebase master First, rewinding head to replay your work on top of it... Applying: Add `insert_user()`. Using index info to reconstruct a base tree... M sqitch.plan Falling back to patching base and 3-way merge... Auto-merging sqitch.plan Applying: Add `change_pass()`. Using index info to reconstruct a base tree... M sqitch.plan Falling back to patching base and 3-way merge... Auto-merging sqitch.plan > Reemerge > Success!

Slide 730

Slide 730 text

echo sqitch.plan merge=union > .gitattributes > git rebase --abort > git rebase master First, rewinding head to replay your work on top of it... Applying: Add `insert_user()`. Using index info to reconstruct a base tree... M sqitch.plan Falling back to patching base and 3-way merge... Auto-merging sqitch.plan Applying: Add `change_pass()`. Using index info to reconstruct a base tree... M sqitch.plan Falling back to patching base and 3-way merge... Auto-merging sqitch.plan > Reemerge > emacs sqitch.plan > Success!

Slide 731

Slide 731 text

sqitch.plan What’s the Plan, Man? %syntax-version=1.0.0 %project=flipr %uri=file://../flipr-remote appschema 2016-01-26T22:47:50Z David E. Wheeler # Adds flipr app schema. users [appschema] 2016-01-27T00:26:52Z David E. Wheeler # Creates table to track our users. flips [appschema users] 2016-01-27T00:58:48Z David E. Wheeler # Adds table for storing flips. insert_user [users appschema] 2016-01-27T01:02:43Z David E. Wheeler # Creates a function to insert a user. change_pass [users appschema] 2016-01-27T01:34:15Z David E. Wheeler # Creates a function to

Slide 732

Slide 732 text

sqitch.plan What’s the Plan, Man? %syntax-version=1.0.0 %project=flipr %uri=file://../flipr-remote appschema 2016-01-26T22:47:50Z David E. Wheeler # Adds flipr app schema. users [appschema] 2016-01-27T00:26:52Z David E. Wheeler # Creates table to track our users. flips [appschema users] 2016-01-27T00:58:48Z David E. Wheeler # Adds table for storing flips. insert_user [users appschema] 2016-01-27T01:02:43Z David E. Wheeler # Creates a function to insert a user. change_pass [users appschema] 2016-01-27T01:34:15Z David E. Wheeler # Creates a function to

Slide 733

Slide 733 text

sqitch.plan What’s the Plan, Man? %syntax-version=1.0.0 %project=flipr %uri=file://../flipr-remote appschema 2016-01-26T22:47:50Z David E. Wheeler # Adds flipr app schema. users [appschema] 2016-01-27T00:26:52Z David E. Wheeler # Creates table to track our users. flips [appschema users] 2016-01-27T00:58:48Z David E. Wheeler # Adds table for storing flips. insert_user [users appschema] 2016-01-27T01:02:43Z David E. Wheeler # Creates a function to insert a user. change_pass [users appschema] 2016-01-27T01:34:15Z David E. Wheeler # Creates a function to

Slide 734

Slide 734 text

sqitch.plan What’s the Plan, Man? %syntax-version=1.0.0 %project=flipr %uri=file://../flipr-remote appschema 2016-01-26T22:47:50Z David E. Wheeler # Adds flipr app schema. users [appschema] 2016-01-27T00:26:52Z David E. Wheeler # Creates table to track our users. flips [appschema users] 2016-01-27T00:58:48Z David E. Wheeler # Adds table for storing flips. insert_user [users appschema] 2016-01-27T01:02:43Z David E. Wheeler # Creates a function to insert a user. change_pass [users appschema] 2016-01-27T01:34:15Z David E. Wheeler # Creates a function to

Slide 735

Slide 735 text

sqitch.plan What’s the Plan, Man? %syntax-version=1.0.0 %project=flipr %uri=file://../flipr-remote appschema 2016-01-26T22:47:50Z David E. Wheeler # Adds flipr app schema. users [appschema] 2016-01-27T00:26:52Z David E. Wheeler # Creates table to track our users. flips [appschema users] 2016-01-27T00:58:48Z David E. Wheeler # Adds table for storing flips. insert_user [users appschema] 2016-01-27T01:02:43Z David E. Wheeler # Creates a function to insert a user. change_pass [users appschema] 2016-01-27T01:34:15Z David E. Wheeler # Creates a function to

Slide 736

Slide 736 text

sqitch.plan What’s the Plan, Man? %syntax-version=1.0.0 %project=flipr %uri=file://../flipr-remote appschema 2016-01-26T22:47:50Z David E. Wheeler # Adds flipr app schema. users [appschema] 2016-01-27T00:26:52Z David E. Wheeler # Creates table to track our users. flips [appschema users] 2016-01-27T00:58:48Z David E. Wheeler # Adds table for storing flips. insert_user [users appschema] 2016-01-27T01:02:43Z David E. Wheeler # Creates a function to insert a user. change_pass [users appschema] 2016-01-27T01:34:15Z David E. Wheeler # Creates a function to

Slide 737

Slide 737 text

sqitch.plan What’s the Plan, Man? %syntax-version=1.0.0 %project=flipr %uri=file://../flipr-remote appschema 2016-01-26T22:47:50Z David E. Wheeler # Adds flipr app schema. users [appschema] 2016-01-27T00:26:52Z David E. Wheeler # Creates table to track our users. flips [appschema users] 2016-01-27T00:58:48Z David E. Wheeler # Adds table for storing flips. insert_user [users appschema] 2016-01-27T01:02:43Z David E. Wheeler # Creates a function to insert a user. change_pass [users appschema] 2016-01-27T01:34:15Z David E. Wheeler # Creates a function to Perfect

Slide 738

Slide 738 text

Work It >

Slide 739

Slide 739 text

> sqitch rebase -y Reverting all changes from db:pg:flipr_test - change_pass .. ok - insert_user .. ok - users ........ ok - appschema .... ok Deploying changes to db:pg:flipr_test + appschema .... ok + users ........ ok + flips ........ ok + insert_user .. ok + change_pass .. ok > Work It >

Slide 740

Slide 740 text

> sqitch rebase -y Reverting all changes from db:pg:flipr_test - change_pass .. ok - insert_user .. ok - users ........ ok - appschema .... ok Deploying changes to db:pg:flipr_test + appschema .... ok + users ........ ok + flips ........ ok + insert_user .. ok + change_pass .. ok > Work It > {

Slide 741

Slide 741 text

> sqitch rebase -y Reverting all changes from db:pg:flipr_test - change_pass .. ok - insert_user .. ok - users ........ ok - appschema .... ok Deploying changes to db:pg:flipr_test + appschema .... ok + users ........ ok + flips ........ ok + insert_user .. ok + change_pass .. ok > Work It > { {

Slide 742

Slide 742 text

> sqitch rebase -y Reverting all changes from db:pg:flipr_test - change_pass .. ok - insert_user .. ok - users ........ ok - appschema .... ok Deploying changes to db:pg:flipr_test + appschema .... ok + users ........ ok + flips ........ ok + insert_user .. ok + change_pass .. ok > Work It > { { Awesomsauce

Slide 743

Slide 743 text

Prove It >

Slide 744

Slide 744 text

> pg_prove -d flipr_test test/*.sql test/appschema.sql .... ok test/change_pass.sql .. ok test/flips.sql ........ ok test/insert_user.sql .. ok test/users.sql ........ ok All tests successful. Files=5, Tests=59, 0 wallclock secs Result: PASS > Prove It >

Slide 745

Slide 745 text

> pg_prove -d flipr_test test/*.sql test/appschema.sql .... ok test/change_pass.sql .. ok test/flips.sql ........ ok test/insert_user.sql .. ok test/users.sql ........ ok All tests successful. Files=5, Tests=59, 0 wallclock secs Result: PASS > Prove It > Booyah.

Slide 746

Slide 746 text

Make it So >

Slide 747

Slide 747 text

> git add . > Make it So >

Slide 748

Slide 748 text

> git add . > git commit -m 'Use union merge for `sqitch.plan`.' [userfuncs 0e31da9] Use union merge for `sqitch.plan`. 1 file changed, 1 insertion(+) create mode 100644 .gitattributes > Make it So >

Slide 749

Slide 749 text

> git add . > git commit -m 'Use union merge for `sqitch.plan`.' [userfuncs 0e31da9] Use union merge for `sqitch.plan`. 1 file changed, 1 insertion(+) create mode 100644 .gitattributes > git push --force origin userfuncs Counting objects: 31, done. Delta compression using up to 4 threads. Compressing objects: 100% (24/24), done. Writing objects: 100% (25/25), 3.83 KiB, done. Total 25 (delta 7), reused 0 (delta 0) To ../flipr-remote + e7477c...0e31da userfuncs -> userfuncs (forced update > Make it So > Overwrite history

Slide 750

Slide 750 text

> git add . > git commit -m 'Use union merge for `sqitch.plan`.' [userfuncs 0e31da9] Use union merge for `sqitch.plan`. 1 file changed, 1 insertion(+) create mode 100644 .gitattributes > git push --force origin userfuncs Counting objects: 31, done. Delta compression using up to 4 threads. Compressing objects: 100% (24/24), done. Writing objects: 100% (25/25), 3.83 KiB, done. Total 25 (delta 7), reused 0 (delta 0) To ../flipr-remote + e7477c...0e31da userfuncs -> userfuncs (forced update > Make it So >

Slide 751

Slide 751 text

>

Slide 752

Slide 752 text

> git checkout - Switched to branch 'master' > >

Slide 753

Slide 753 text

git merge userfuncs Updating fbf8469..0e31da9 Fast-forward .gitattributes | 1 + deploy/change_pass.sql | 21 ++++++++++++++++++ deploy/insert_user.sql | 14 ++++++++++++ revert/change_pass.sql | 7 ++++++ revert/insert_user.sql | 7 ++++++ sqitch.plan | 2 ++ test/change_pass.sql | 52 ++++++++++++++++++++++++++++++++++ test/insert_user.sql | 69 ++++++++++++++++++++++++++++++++++ verify/change_pass.sql | 7 ++++++ verify/insert_user.sql | 10 +++++++++ 10 files changed, 190 insertions(+) create mode 100644 .gitattributes create mode 100644 deploy/change_pass.sql create mode 100644 deploy/insert_user.sql create mode 100644 revert/change_pass.sql create mode 100644 revert/insert_user.sql create mode 100644 test/change_pass.sql create mode 100644 test/insert_user.sql create mode 100644 verify/change_pass.sql create mode 100644 verify/insert_user.sql > > git checkout - Switched to branch 'master' > >

Slide 754

Slide 754 text

git merge userfuncs Updating fbf8469..0e31da9 Fast-forward .gitattributes | 1 + deploy/change_pass.sql | 21 ++++++++++++++++++ deploy/insert_user.sql | 14 ++++++++++++ revert/change_pass.sql | 7 ++++++ revert/insert_user.sql | 7 ++++++ sqitch.plan | 2 ++ test/change_pass.sql | 52 ++++++++++++++++++++++++++++++++++ test/insert_user.sql | 69 ++++++++++++++++++++++++++++++++++ verify/change_pass.sql | 7 ++++++ verify/insert_user.sql | 10 +++++++++ 10 files changed, 190 insertions(+) create mode 100644 .gitattributes create mode 100644 deploy/change_pass.sql create mode 100644 deploy/insert_user.sql create mode 100644 revert/change_pass.sql create mode 100644 revert/insert_user.sql create mode 100644 test/change_pass.sql create mode 100644 test/insert_user.sql create mode 100644 verify/change_pass.sql create mode 100644 verify/insert_user.sql > > git checkout - Switched to branch 'master' > > \O/

Slide 755

Slide 755 text

Pusher >

Slide 756

Slide 756 text

git push Counting objects: 20, done. Delta compression using up to 4 threads. Compressing objects: 100% (13/13), done. Writing objects: 100% (14/14), 2.31 KiB, done. Total 14 (delta 2), reused 0 (delta 0) To ../flipr-remote fbf8469..0e31da9 master -> master > Pusher >

Slide 757

Slide 757 text

antisocial network

Slide 758

Slide 758 text

Ship it! antisocial network

Slide 759

Slide 759 text

Ship Shape antisocial network

Slide 760

Slide 760 text

Ship Shape Good work so far antisocial network

Slide 761

Slide 761 text

Ship Shape Good work so far People gonna flip out antisocial network

Slide 762

Slide 762 text

Ship Shape Good work so far People gonna flip out Let’s tag a dev release antisocial network

Slide 763

Slide 763 text

Ship Shape Good work so far People gonna flip out Let’s tag a dev release Bundle it up antisocial network

Slide 764

Slide 764 text

Ship Shape Good work so far People gonna flip out Let’s tag a dev release Bundle it up And ship it antisocial network

Slide 765

Slide 765 text

You’re It >

Slide 766

Slide 766 text

sqitch tag v1.0.0-r1 -n 'Tag v1.0.0-r1.' Tagged "change_pass" with @v1.0.0-r1 > You’re It >

Slide 767

Slide 767 text

sqitch tag v1.0.0-r1 -n 'Tag v1.0.0-r1.' Tagged "change_pass" with @v1.0.0-r1 > git commit -am 'Tag the database @v1.0.0-r1.' [master 6661268] Tag the database @v1.0.0-r1. 1 file changed, 1 insertion(+) > You’re It >

Slide 768

Slide 768 text

git tag v1.0.0-r1 -am 'Tag v1.0.0-r1.' > sqitch tag v1.0.0-r1 -n 'Tag v1.0.0-r1.' Tagged "change_pass" with @v1.0.0-r1 > git commit -am 'Tag the database @v1.0.0-r1.' [master 6661268] Tag the database @v1.0.0-r1. 1 file changed, 1 insertion(+) > You’re It > In sync. In sync.

Slide 769

Slide 769 text

git tag v1.0.0-r1 -am 'Tag v1.0.0-r1.' > sqitch tag v1.0.0-r1 -n 'Tag v1.0.0-r1.' Tagged "change_pass" with @v1.0.0-r1 > git commit -am 'Tag the database @v1.0.0-r1.' [master 6661268] Tag the database @v1.0.0-r1. 1 file changed, 1 insertion(+) > git push Counting objects: 5, done. Writing objects: 100% (3/3), 346 bytes, done. Total 3 (delta 2), reused 0 (delta 0) To ../flipr-remote 0e31da9..6661268 master -> master > You’re It >

Slide 770

Slide 770 text

git tag v1.0.0-r1 -am 'Tag v1.0.0-r1.' > sqitch tag v1.0.0-r1 -n 'Tag v1.0.0-r1.' Tagged "change_pass" with @v1.0.0-r1 > git commit -am 'Tag the database @v1.0.0-r1.' [master 6661268] Tag the database @v1.0.0-r1. 1 file changed, 1 insertion(+) > git push Counting objects: 5, done. Writing objects: 100% (3/3), 346 bytes, done. Total 3 (delta 2), reused 0 (delta 0) To ../flipr-remote 0e31da9..6661268 master -> master > git push --tags To ../flipr-remote * [new tag] v1.0.0-r1 -> v1.0.0-r1 > You’re It >

Slide 771

Slide 771 text

Bundle Up >

Slide 772

Slide 772 text

sqitch bundle --dest-dir flipr-1.0.0-r1 Bundling into flipr-1.0.0-r1 Writing config Writing plan Writing scripts + appschema + users + flips + insert_user + change_pass @v1.0.0-r1 > Bundle Up >

Slide 773

Slide 773 text

sqitch bundle --dest-dir flipr-1.0.0-r1 Bundling into flipr-1.0.0-r1 Writing config Writing plan Writing scripts + appschema + users + flips + insert_user + change_pass @v1.0.0-r1 > Bundle Up > {

Slide 774

Slide 774 text

Bundled? >

Slide 775

Slide 775 text

> cd flipr-1.0.0-r1 > Bundled? >

Slide 776

Slide 776 text

createdb flipr_qa > > cd flipr-1.0.0-r1 > Bundled? >

Slide 777

Slide 777 text

createdb flipr_qa > > cd flipr-1.0.0-r1 > Bundled? > sqitch deploy db:pg:flipr_qa Adding registry tables to db:pg:flipr_qa Deploying changes to db:pg:flipr_qa + appschema ............... ok + users ................... ok + flips ................... ok + insert_user ............. ok + change_pass @v1.0.0-r1 .. ok >

Slide 778

Slide 778 text

createdb flipr_qa > > cd flipr-1.0.0-r1 > Bundled? > Ship it! sqitch deploy db:pg:flipr_qa Adding registry tables to db:pg:flipr_qa Deploying changes to db:pg:flipr_qa + appschema ............... ok + users ................... ok + flips ................... ok + insert_user ............. ok + change_pass @v1.0.0-r1 .. ok >

Slide 779

Slide 779 text

createdb flipr_qa > > cd flipr-1.0.0-r1 > Bundled? > sqitch deploy db:pg:flipr_qa Adding registry tables to db:pg:flipr_qa Deploying changes to db:pg:flipr_qa + appschema ............... ok + users ................... ok + flips ................... ok + insert_user ............. ok + change_pass @v1.0.0-r1 .. ok > > cd .. > tar czf flipr-1.0.0-r1.tgz flipr-1.0.0-r1 >

Slide 780

Slide 780 text

antisocial network Merge Madness

Slide 781

Slide 781 text

antisocial network Merge Madness Merge everything

Slide 782

Slide 782 text

antisocial network Merge Madness Merge everything Back to master

Slide 783

Slide 783 text

antisocial network Merge Madness Merge everything Back to master users

Slide 784

Slide 784 text

antisocial network Merge Madness Merge everything Back to master users flips

Slide 785

Slide 785 text

antisocial network Merge Madness Merge everything Back to master users flips userfuncs

Slide 786

Slide 786 text

antisocial network Merge Madness Merge everything Back to master users flips userfuncs Union merge sqitch.plan

Slide 787

Slide 787 text

antisocial network Merge Madness Merge everything Back to master users flips userfuncs Union merge sqitch.plan Bundle and ship

Slide 788

Slide 788 text

antisocial network Merge Madness Merge everything Back to master users flips userfuncs Union merge sqitch.plan Bundle and ship https:/ /github.com/ theory/agile-flipr.git

Slide 789

Slide 789 text

Ruh-Roh >

Slide 790

Slide 790 text

Ruh-Roh sqitch revert -y > git reset --hard upstream/reltag HEAD is now at 6661268 Tag the database @v1.0.0-r1. > sqitch deploy > >

Slide 791

Slide 791 text

psql -d flipr_test -c " SELECT flipr.insert_user('foo', 'secr3t'), flipr.insert_user('bar', 'secr3t'); SELECT nickname, password FROM flipr.users; " nickname | password ----------+---------------------------------- foo | 9695da4dd567a19f9b92065f240c6725 bar | 9695da4dd567a19f9b92065f240c6725 (2 rows) > Ruh-Roh sqitch revert -y > git reset --hard upstream/reltag HEAD is now at 6661268 Tag the database @v1.0.0-r1. > sqitch deploy > > Same password

Slide 792

Slide 792 text

psql -d flipr_test -c " SELECT flipr.insert_user('foo', 'secr3t'), flipr.insert_user('bar', 'secr3t'); SELECT nickname, password FROM flipr.users; " nickname | password ----------+---------------------------------- foo | 9695da4dd567a19f9b92065f240c6725 bar | 9695da4dd567a19f9b92065f240c6725 (2 rows) > Ruh-Roh sqitch revert -y > git reset --hard upstream/reltag HEAD is now at 6661268 Tag the database @v1.0.0-r1. > sqitch deploy > >

Slide 793

Slide 793 text

psql -d flipr_test -c " SELECT flipr.insert_user('foo', 'secr3t'), flipr.insert_user('bar', 'secr3t'); SELECT nickname, password FROM flipr.users; " nickname | password ----------+---------------------------------- foo | 9695da4dd567a19f9b92065f240c6725 bar | 9695da4dd567a19f9b92065f240c6725 (2 rows) > Ruh-Roh sqitch revert -y > git reset --hard upstream/reltag HEAD is now at 6661268 Tag the database @v1.0.0-r1. > sqitch deploy > > Not good.

Slide 794

Slide 794 text

PGCryptonite >

Slide 795

Slide 795 text

sqitch add pgcrypto -n 'Loads pgcrypto extension.' Adding deploy/pgcrypto.sql Adding revert/pgcrypto.sql Adding verify/pgcrypto.sql Added "pgcrypto" to sqitch.plan > PGCryptonite >

Slide 796

Slide 796 text

sqitch add pgcrypto -n 'Loads pgcrypto extension.' Adding deploy/pgcrypto.sql Adding revert/pgcrypto.sql Adding verify/pgcrypto.sql Added "pgcrypto" to sqitch.plan > PGCryptonite > emacs deploy/pgcrypto.sql >

Slide 797

Slide 797 text

deploy/pgcrypto deploy/pgcrypto.sql -- Deploy flipr:pgcrypto to pg BEGIN; COMMIT; -- XXX Add DDLs here.

Slide 798

Slide 798 text

deploy/pgcrypto deploy/pgcrypto.sql -- Deploy flipr:pgcrypto to pg BEGIN; COMMIT; CREATE EXTENSION pgcrypto;

Slide 799

Slide 799 text

sqitch add pgcrypto -n 'Loads pgcrypto extension.' Adding deploy/pgcrypto.sql Adding revert/pgcrypto.sql Adding verify/pgcrypto.sql Added "pgcrypto" to sqitch.plan > emacs deploy/pgcrypto.sql > PGCryptonite >

Slide 800

Slide 800 text

sqitch add pgcrypto -n 'Loads pgcrypto extension.' Adding deploy/pgcrypto.sql Adding revert/pgcrypto.sql Adding verify/pgcrypto.sql Added "pgcrypto" to sqitch.plan > emacs deploy/pgcrypto.sql > PGCryptonite > emacs verify/pgcrypto.sql >

Slide 801

Slide 801 text

-- Verify flipr:pgcrypto on pg BEGIN; verify/pgcrypto verify/pgcrypto.sql -- XXX Add verifications here. COMMIT;

Slide 802

Slide 802 text

-- Verify flipr:pgcrypto on pg BEGIN; verify/pgcrypto verify/pgcrypto.sql COMMIT; SELECT 1/count(*) FROM pg_extension WHERE extname = 'pgcrypto'; SELECT has_function_privilege('crypt(text, text)', 'execute'); SELECT has_function_privilege('gen_salt(text)', 'execute');

Slide 803

Slide 803 text

-- Verify flipr:pgcrypto on pg BEGIN; verify/pgcrypto verify/pgcrypto.sql COMMIT; SELECT 1/count(*) FROM pg_extension WHERE extname = 'pgcrypto'; SELECT has_function_privilege('crypt(text, text)', 'execute'); SELECT has_function_privilege('gen_salt(text)', 'execute');

Slide 804

Slide 804 text

-- Verify flipr:pgcrypto on pg BEGIN; verify/pgcrypto verify/pgcrypto.sql COMMIT; SELECT 1/count(*) FROM pg_extension WHERE extname = 'pgcrypto'; SELECT has_function_privilege('crypt(text, text)', 'execute'); SELECT has_function_privilege('gen_salt(text)', 'execute');

Slide 805

Slide 805 text

You Know the Drill antisocial network

Slide 806

Slide 806 text

You Know the Drill Write revert script antisocial network

Slide 807

Slide 807 text

You Know the Drill Write revert script Add test antisocial network

Slide 808

Slide 808 text

You Know the Drill Write revert script Add test Use has_function() antisocial network

Slide 809

Slide 809 text

You Know the Drill Write revert script Add test Use has_function() Commit antisocial network

Slide 810

Slide 810 text

You Know the Drill Write revert script Add test Use has_function() Commit Push antisocial network

Slide 811

Slide 811 text

You Know the Drill Write revert script Add test Use has_function() Commit Push Modify the insert_user test antisocial network

Slide 812

Slide 812 text

>

Slide 813

Slide 813 text

> git diff test/insert_user.sql @@ -5,7 +5,7 @@ SET search_path TO flipr,public; -- Plan the tests. BEGIN; -SELECT plan(11); +SELECT plan(12); SELECT has_function( 'insert_user' ); SELECT has_function( @@ -29,25 +29,25 @@ SELECT lives_ok( 'Insert a user' ); -SELECT row_eq( - 'SELECT * FROM users', - ROW('theory', md5('foo'), NOW())::users, - 'The user should have been inserted' -); +SELECT ok( EXISTS( + SELECT 1 FROM flipr.users + WHERE nickname = 'theory' + AND password = crypt('foo', password) +), 'The user should have been inserted' );

Slide 814

Slide 814 text

> git diff test/insert_user.sql @@ -5,7 +5,7 @@ SET search_path TO flipr,public; -- Plan the tests. BEGIN; -SELECT plan(11); +SELECT plan(12); SELECT has_function( 'insert_user' ); SELECT has_function( @@ -29,25 +29,25 @@ SELECT lives_ok( 'Insert a user' ); -SELECT row_eq( - 'SELECT * FROM users', - ROW('theory', md5('foo'), NOW())::users, - 'The user should have been inserted' -); +SELECT ok( EXISTS( + SELECT 1 FROM flipr.users + WHERE nickname = 'theory' + AND password = crypt('foo', password) +), 'The user should have been inserted' );

Slide 815

Slide 815 text

> git diff test/insert_user.sql @@ -5,7 +5,7 @@ SET search_path TO flipr,public; -- Plan the tests. BEGIN; -SELECT plan(11); +SELECT plan(12); SELECT has_function( 'insert_user' ); SELECT has_function( @@ -29,25 +29,25 @@ SELECT lives_ok( 'Insert a user' ); -SELECT row_eq( - 'SELECT * FROM users', - ROW('theory', md5('foo'), NOW())::users, - 'The user should have been inserted' -); +SELECT ok( EXISTS( + SELECT 1 FROM flipr.users + WHERE nickname = 'theory' + AND password = crypt('foo', password) +), 'The user should have been inserted' );

Slide 816

Slide 816 text

SELECT lives_ok( $$ SELECT insert_user('strongrrl', 'w00t') $$, 'Insert another user' ); -SELECT bag_eq( - 'SELECT * FROM users', - $$ VALUES - ('theory', md5('foo'), NOW()), - ('strongrrl', md5('w00t'), NOW()) - $$, - 'Both users should be present' -); +SELECT is(COUNT(*)::INT, 2, 'There should be two users') + FROM flipr.users; + +SELECT ok( EXISTS( + SELECT 1 FROM flipr.users + WHERE nickname = 'strongrrl' + AND password = crypt('w00t', password) +), 'The second user should have been inserted' ); SELECT throws_ok( $$ SELECT insert_user('theory', 'ha-ha') $$,

Slide 817

Slide 817 text

SELECT lives_ok( $$ SELECT insert_user('strongrrl', 'w00t') $$, 'Insert another user' ); -SELECT bag_eq( - 'SELECT * FROM users', - $$ VALUES - ('theory', md5('foo'), NOW()), - ('strongrrl', md5('w00t'), NOW()) - $$, - 'Both users should be present' -); +SELECT is(COUNT(*)::INT, 2, 'There should be two users') + FROM flipr.users; + +SELECT ok( EXISTS( + SELECT 1 FROM flipr.users + WHERE nickname = 'strongrrl' + AND password = crypt('w00t', password) +), 'The second user should have been inserted' ); SELECT throws_ok( $$ SELECT insert_user('theory', 'ha-ha') $$,

Slide 818

Slide 818 text

SELECT lives_ok( $$ SELECT insert_user('strongrrl', 'w00t') $$, 'Insert another user' ); -SELECT bag_eq( - 'SELECT * FROM users', - $$ VALUES - ('theory', md5('foo'), NOW()), - ('strongrrl', md5('w00t'), NOW()) - $$, - 'Both users should be present' -); +SELECT is(COUNT(*)::INT, 2, 'There should be two users') + FROM flipr.users; + +SELECT ok( EXISTS( + SELECT 1 FROM flipr.users + WHERE nickname = 'strongrrl' + AND password = crypt('w00t', password) +), 'The second user should have been inserted' ); SELECT throws_ok( $$ SELECT insert_user('theory', 'ha-ha') $$,

Slide 819

Slide 819 text

SELECT lives_ok( $$ SELECT insert_user('strongrrl', 'w00t') $$, 'Insert another user' ); -SELECT bag_eq( - 'SELECT * FROM users', - $$ VALUES - ('theory', md5('foo'), NOW()), - ('strongrrl', md5('w00t'), NOW()) - $$, - 'Both users should be present' -); +SELECT is(COUNT(*)::INT, 2, 'There should be two users') + FROM flipr.users; + +SELECT ok( EXISTS( + SELECT 1 FROM flipr.users + WHERE nickname = 'strongrrl' + AND password = crypt('w00t', password) +), 'The second user should have been inserted' ); SELECT throws_ok( $$ SELECT insert_user('theory', 'ha-ha') $$,

Slide 820

Slide 820 text

@@ -56,14 +56,8 @@ SELECT throws_ok( 'Should get an error for duplicate nickname' ); -SELECT bag_eq( - 'SELECT * FROM users', - $$ VALUES - ('theory', md5('foo'), NOW()), - ('strongrrl', md5('w00t'), NOW()) - $$, - 'Should still have just the two users' -); +SELECT is(COUNT(*)::INT, 2, 'Should still have two users') + FROM flipr.users; SELECT finish(); ROLLBACK; >

Slide 821

Slide 821 text

@@ -56,14 +56,8 @@ SELECT throws_ok( 'Should get an error for duplicate nickname' ); -SELECT bag_eq( - 'SELECT * FROM users', - $$ VALUES - ('theory', md5('foo'), NOW()), - ('strongrrl', md5('w00t'), NOW()) - $$, - 'Should still have just the two users' -); +SELECT is(COUNT(*)::INT, 2, 'Should still have two users') + FROM flipr.users; SELECT finish(); ROLLBACK; >

Slide 822

Slide 822 text

@@ -56,14 +56,8 @@ SELECT throws_ok( 'Should get an error for duplicate nickname' ); -SELECT bag_eq( - 'SELECT * FROM users', - $$ VALUES - ('theory', md5('foo'), NOW()), - ('strongrrl', md5('w00t'), NOW()) - $$, - 'Should still have just the two users' -); +SELECT is(COUNT(*)::INT, 2, 'Should still have two users') + FROM flipr.users; SELECT finish(); ROLLBACK; >

Slide 823

Slide 823 text

FAIL >

Slide 824

Slide 824 text

FAIL > pg_prove -d flipr_test test/insert_user.sql test/insert_user.sql .. 1/12 # Failed test 7: "The user should have been inserted" # Failed test 10: "The second user should have been inserted" # Looks like you failed 2 tests of 12 test/insert_user.sql .. Failed 2/12 subtests Test Summary Report ------------------- test/insert_user.sql (Wstat: 0 Tests: 12 Failed: 2) Failed tests: 7, 10 Files=1, Tests=12, 1 wallclock secs Result: FAIL > >

Slide 825

Slide 825 text

FAIL > pg_prove -d flipr_test test/insert_user.sql test/insert_user.sql .. 1/12 # Failed test 7: "The user should have been inserted" # Failed test 10: "The second user should have been inserted" # Looks like you failed 2 tests of 12 test/insert_user.sql .. Failed 2/12 subtests Test Summary Report ------------------- test/insert_user.sql (Wstat: 0 Tests: 12 Failed: 2) Failed tests: 7, 10 Files=1, Tests=12, 1 wallclock secs Result: FAIL > > As expected.

Slide 826

Slide 826 text

Back when discussing traditional migration systems, I said… antisocial network

Slide 827

Slide 827 text

Managing procedures is a PITA! antisocial network

Slide 828

Slide 828 text

Consider this Change >

Slide 829

Slide 829 text

Consider this Change git diff diff --git a/deploy/insert_user.sql b/deploy/insert_user.sql index eb30fed..5c28d02 100644 --- a/deploy/insert_user.sql +++ b/deploy/insert_user.sql @@ -8,7 +8,7 @@ CREATE OR REPLACE FUNCTION flipr.insert_user( nickname TEXT, password TEXT ) RETURNS VOID LANGUAGE SQL SECURITY DEFINER AS $$ - INSERT INTO flipr.users VALUES($1, md5($2)); + INSERT INTO flipr.users values($1, crypt($2, gen_salt('md5'))); $$; COMMIT; >

Slide 830

Slide 830 text

Consider this Change git diff diff --git a/deploy/insert_user.sql b/deploy/insert_user.sql index eb30fed..5c28d02 100644 --- a/deploy/insert_user.sql +++ b/deploy/insert_user.sql @@ -8,7 +8,7 @@ CREATE OR REPLACE FUNCTION flipr.insert_user( nickname TEXT, password TEXT ) RETURNS VOID LANGUAGE SQL SECURITY DEFINER AS $$ - INSERT INTO flipr.users VALUES($1, md5($2)); + INSERT INTO flipr.users values($1, crypt($2, gen_salt('md5'))); $$; COMMIT; > Simple, right?

Slide 831

Slide 831 text

Not So Much antisocial network

Slide 832

Slide 832 text

Not So Much Copy insert_user.sql to new deploy file antisocial network

Slide 833

Slide 833 text

Not So Much Copy insert_user.sql to new deploy file Change that new file antisocial network

Slide 834

Slide 834 text

Not So Much Copy insert_user.sql to new deploy file Change that new file Copy insert_user.sql to new revert file antisocial network

Slide 835

Slide 835 text

Not So Much Copy insert_user.sql to new deploy file Change that new file Copy insert_user.sql to new revert file Test it antisocial network

Slide 836

Slide 836 text

Not So Much Copy insert_user.sql to new deploy file Change that new file Copy insert_user.sql to new revert file Test it Do the same for change_pass.sql antisocial network

Slide 837

Slide 837 text

Not So Much Copy insert_user.sql to new deploy file Change that new file Copy insert_user.sql to new revert file Test it Do the same for change_pass.sql The problem with that… antisocial network

Slide 838

Slide 838 text

>

Slide 839

Slide 839 text

> git diff HEAD^ diff --git a/deploy/insert_user_crypt.sql b/deploy/insert_user_crypto.sql new file mode 100644 index 0000000..fa8d0c6 --- /dev/null +++ b/deploy/insert_user_crypt.sql @@ -0,0 +1,8 @@ +-- requires: users, appuser, pgcrypto + +CREATE OR REPLACE FUNCTION insert_user( + nickname TEXT, + password TEXT +) RETURNS VOID LANGUAGE SQL AS $$ + INSERT INTO users values($1, crypt($2, gen_salt('md5'))); +$$; diff --git a/revert/insert_user_crypt.sql b/revert/insert_user_crypto.sql new file mode 100644 index 0000000..a7f4e31 --- /dev/null +++ b/revert/insert_user_crypt.sql @@ -0,0 +1,8 @@ +-- requires: users, appuser + +CREATE OR REPLACE FUNCTION insert_user( + nickname TEXT, + password TEXT +) RETURNS VOID LANGUAGE SQL AS $$ + INSERT INTO users values($1, md5($2)); +$$; >

Slide 840

Slide 840 text

> git diff HEAD^ diff --git a/deploy/insert_user_crypt.sql b/deploy/insert_user_crypto.sql new file mode 100644 index 0000000..fa8d0c6 --- /dev/null +++ b/deploy/insert_user_crypt.sql @@ -0,0 +1,8 @@ +-- requires: users, appuser, pgcrypto + +CREATE OR REPLACE FUNCTION insert_user( + nickname TEXT, + password TEXT +) RETURNS VOID LANGUAGE SQL AS $$ + INSERT INTO users values($1, crypt($2, gen_salt('md5'))); +$$; diff --git a/revert/insert_user_crypt.sql b/revert/insert_user_crypto.sql new file mode 100644 index 0000000..a7f4e31 --- /dev/null +++ b/revert/insert_user_crypt.sql @@ -0,0 +1,8 @@ +-- requires: users, appuser + +CREATE OR REPLACE FUNCTION insert_user( + nickname TEXT, + password TEXT +) RETURNS VOID LANGUAGE SQL AS $$ + INSERT INTO users values($1, md5($2)); +$$; > Oy.

Slide 841

Slide 841 text

Let Sqitch do the work. antisocial network

Slide 842

Slide 842 text

Rework It >

Slide 843

Slide 843 text

sqitch rework insert_user -r pgcrypto \ -n 'Changes insert_user to use pgcrypto.' Added "insert_user [[email protected] pgcrypto]" to sqitch.plan. Modify these files as appropriate: * deploy/insert_user.sql * revert/insert_user.sql * verify/insert_user.sql > Rework It >

Slide 844

Slide 844 text

sqitch rework insert_user -r pgcrypto \ -n 'Changes insert_user to use pgcrypto.' Added "insert_user [[email protected] pgcrypto]" to sqitch.plan. Modify these files as appropriate: * deploy/insert_user.sql * revert/insert_user.sql * verify/insert_user.sql > Rework It >

Slide 845

Slide 845 text

sqitch rework insert_user -r pgcrypto \ -n 'Changes insert_user to use pgcrypto.' Added "insert_user [[email protected] pgcrypto]" to sqitch.plan. Modify these files as appropriate: * deploy/insert_user.sql * revert/insert_user.sql * verify/insert_user.sql > Rework It >

Slide 846

Slide 846 text

sqitch rework insert_user -r pgcrypto \ -n 'Changes insert_user to use pgcrypto.' Added "insert_user [[email protected] pgcrypto]" to sqitch.plan. Modify these files as appropriate: * deploy/insert_user.sql * revert/insert_user.sql * verify/insert_user.sql > Rework It > Same files?

Slide 847

Slide 847 text

Same Files? >

Slide 848

Slide 848 text

git status On branch master Changes not staged for commit: (use "git add ..." to update what will be committed) (use "git checkout -- ..." to discard changes in wor modified: revert/insert_user.sql modified: sqitch.plan modified: test/insert_user.sql Untracked files: (use "git add ..." to include in what will be commit deploy/[email protected] revert/[email protected] verify/[email protected] > Same Files? >

Slide 849

Slide 849 text

git status On branch master Changes not staged for commit: (use "git add ..." to update what will be committed) (use "git checkout -- ..." to discard changes in wor modified: revert/insert_user.sql modified: sqitch.plan modified: test/insert_user.sql Untracked files: (use "git add ..." to include in what will be commit deploy/[email protected] revert/[email protected] verify/[email protected] > Same Files? >

Slide 850

Slide 850 text

git status On branch master Changes not staged for commit: (use "git add ..." to update what will be committed) (use "git checkout -- ..." to discard changes in wor modified: revert/insert_user.sql modified: sqitch.plan modified: test/insert_user.sql Untracked files: (use "git add ..." to include in what will be commit deploy/[email protected] revert/[email protected] verify/[email protected] > Same Files? > As of @v1.0.0-r1

Slide 851

Slide 851 text

git status On branch master Changes not staged for commit: (use "git add ..." to update what will be committed) (use "git checkout -- ..." to discard changes in wor modified: revert/insert_user.sql modified: sqitch.plan modified: test/insert_user.sql Untracked files: (use "git add ..." to include in what will be commit deploy/[email protected] revert/[email protected] verify/[email protected] > Same Files? >

Slide 852

Slide 852 text

git status On branch master Changes not staged for commit: (use "git add ..." to update what will be committed) (use "git checkout -- ..." to discard changes in wor modified: revert/insert_user.sql modified: sqitch.plan modified: test/insert_user.sql Untracked files: (use "git add ..." to include in what will be commit deploy/[email protected] revert/[email protected] verify/[email protected] > Same Files? > Previous deploy becomes revert

Slide 853

Slide 853 text

What’s the Diff? >

Slide 854

Slide 854 text

What’s the Diff? diff -u deploy/insert_user.sql diff --git a/deploy/insert_user.sql b/deploy/insert_user.sql @@ -1,6 +1,7 @@ -- Deploy insert_user -- requires: users -- requires: appschema +-- requires: pgcrypto BEGIN; @@ -8,7 +9,7 @@ CREATE OR REPLACE FUNCTION flipr.insert_user( nickname TEXT, password TEXT ) RETURNS VOID LANGUAGE SQL SECURITY DEFINER AS $$ - INSERT INTO flipr.users VALUES($1, md5($2)); + INSERT INTO flipr.users values($1, crypt($2, gen_salt('md5'))); $$; COMMIT; > >

Slide 855

Slide 855 text

Send it Up! >

Slide 856

Slide 856 text

Send it Up! > sqitch deploy Deploying changes to db:pg:flipr_test + insert_user .. ok > >

Slide 857

Slide 857 text

> psql -d flipr_test -c " DELETE FROM flipr.users; SELECT flipr.insert_user('foo', 'secr3t'), flipr.insert_user('bar', 'secr3t'); SELECT nickname, password FROM flipr.users; " nickname | password ----------+------------------------------------ foo | $1$nKO47p03$YRXYTt4NoNncTThLyxzEq1 bar | $1$LbVUs/p.$LVbvPlkD8rJlixW2nS3WP0 (2 rows) > Send it Up! > sqitch deploy Deploying changes to db:pg:flipr_test + insert_user .. ok > >

Slide 858

Slide 858 text

> psql -d flipr_test -c " DELETE FROM flipr.users; SELECT flipr.insert_user('foo', 'secr3t'), flipr.insert_user('bar', 'secr3t'); SELECT nickname, password FROM flipr.users; " nickname | password ----------+------------------------------------ foo | $1$nKO47p03$YRXYTt4NoNncTThLyxzEq1 bar | $1$LbVUs/p.$LVbvPlkD8rJlixW2nS3WP0 (2 rows) > Send it Up! > sqitch deploy Deploying changes to db:pg:flipr_test + insert_user .. ok > > \o/

Slide 859

Slide 859 text

Can We Go Back? >

Slide 860

Slide 860 text

Can We Go Back? > sqitch revert --to @HEAD^ -y Reverting changes to pgcrypto from db:pg:flipr_test - insert_user .. ok > >

Slide 861

Slide 861 text

psql -d flipr_test -c " DELETE FROM flipr.users; SELECT flipr.insert_user('foo', 'secr3t'), flipr.insert_user('bar', 'secr3t'); SELECT nickname, password FROM flipr.users; " nickname | password ----------+---------------------------------- foo | 9695da4dd567a19f9b92065f240c6725 bar | 9695da4dd567a19f9b92065f240c6725 (2 rows) Can We Go Back? > sqitch revert --to @HEAD^ -y Reverting changes to pgcrypto from db:pg:flipr_test - insert_user .. ok > >

Slide 862

Slide 862 text

Verify How? >

Slide 863

Slide 863 text

Verify How? > emacs verify/insert_user.sql > >

Slide 864

Slide 864 text

-- Verify flipr:insert_user on pg BEGIN; SELECT has_function_privilege( 'flipr.insert_user(text, text)', 'execute' ); verify/insert_u verify/insert_user.sql COMMIT;

Slide 865

Slide 865 text

SELECT 1/COUNT(*) FROM pg_catalog.pg_proc WHERE proname = 'insert_user' AND pg_get_functiondef(oid) LIKE $$%crypt($2, gen_salt('md5'))%$$; -- Verify flipr:insert_user on pg BEGIN; SELECT has_function_privilege( 'flipr.insert_user(text, text)', 'execute' ); verify/insert_u verify/insert_user.sql COMMIT;

Slide 866

Slide 866 text

SELECT 1/COUNT(*) FROM pg_catalog.pg_proc WHERE proname = 'insert_user' AND pg_get_functiondef(oid) LIKE $$%crypt($2, gen_salt('md5'))%$$; -- Verify flipr:insert_user on pg BEGIN; SELECT has_function_privilege( 'flipr.insert_user(text, text)', 'execute' ); verify/insert_u verify/insert_user.sql COMMIT; Yeah, compare source.

Slide 867

Slide 867 text

> emacs verify/insert_user.sql > Let’s Go!

Slide 868

Slide 868 text

> emacs verify/insert_user.sql > Let’s Go! > sqitch deploy Deploying changes to db:pg:flipr_test + insert_user .. ok >

Slide 869

Slide 869 text

> emacs verify/insert_user.sql > Let’s Go! > sqitch deploy Deploying changes to db:pg:flipr_test + insert_user .. ok > > psql -d flipr_test -c 'DELETE FROM flipr.users' DELETE 2 >

Slide 870

Slide 870 text

> emacs verify/insert_user.sql > Let’s Go! > sqitch deploy Deploying changes to db:pg:flipr_test + insert_user .. ok > > psql -d flipr_test -c 'DELETE FROM flipr.users' DELETE 2 > pg_prove -d flipr_test test/insert_user.sql test/insert_user.sql .. ok All tests successful. Files=1, Tests=12, 0 wallclock secs Result: PASS > Shazam!

Slide 871

Slide 871 text

Add, Commit, Push, Go >

Slide 872

Slide 872 text

git add . > git commit -m 'Update insert_user to use pgcrypto.' [master 59f5823] Update insert_user to use pgcrypto. 8 files changed, 66 insertions(+), 25 deletions(-) create mode 100644 deploy/[email protected] create mode 100644 revert/[email protected] create mode 100644 verify/[email protected] > Add, Commit, Push, Go >

Slide 873

Slide 873 text

git add . > git commit -m 'Update insert_user to use pgcrypto.' [master 59f5823] Update insert_user to use pgcrypto. 8 files changed, 66 insertions(+), 25 deletions(-) create mode 100644 deploy/[email protected] create mode 100644 revert/[email protected] create mode 100644 verify/[email protected] > Add, Commit, Push, Go > git push Counting objects: 17, done. Delta compression using up to 4 threads. Compressing objects: 100% (10/10), done. Writing objects: 100% (10/10), 1.75 KiB, done. Total 10 (delta 6), reused 0 (delta 0) To ../flipr-remote 5f4c29a..59f5823 master -> master > >

Slide 874

Slide 874 text

antisocial network Change It Up

Slide 875

Slide 875 text

antisocial network Change It Up git reset --hard insert_user2

Slide 876

Slide 876 text

antisocial network Change It Up git reset --hard insert_user2 Rework change_pass

Slide 877

Slide 877 text

antisocial network Change It Up git reset --hard insert_user2 Rework change_pass Use pgcrypo

Slide 878

Slide 878 text

antisocial network Change It Up git reset --hard insert_user2 Rework change_pass Use pgcrypo Test first!

Slide 879

Slide 879 text

antisocial network Change It Up git reset --hard insert_user2 Rework change_pass Use pgcrypo Test first! Bundle, tag, release

Slide 880

Slide 880 text

antisocial network Change It Up git reset --hard insert_user2 Rework change_pass Use pgcrypo Test first! Bundle, tag, release https:/ /github.com/ theory/agile-flipr.git

Slide 881

Slide 881 text

I’m afraid I have some bad news… antisocial network

Slide 882

Slide 882 text

No content

Slide 883

Slide 883 text

Antisocial Networking Startup Flipr Heads To The Deadpool by Michael Arrington on November 2, 2010 antisocial network I loved this site. Flipr, an online “antisocial networking” site that encouraged users to alienate each other in order to increase their antisocial cred, is shutting down. The startup’s homepage now consists of a letter to Flipr users instructing them to download their “flips” by November 30, at which point nearly all of the service’s features will be taken offline and data deleted. In the letter, Flipr CEO David Wheeler writes that despite ample venture funding and a dedicated team of database developers, the site underestimated people’s willingness to be assholes. This is not something I can relate to, although from what I’ve been told by more polite society, it is indeed the case. Such a shame.

Slide 884

Slide 884 text

I’m afraid it’s true. antisocial network RIP

Slide 885

Slide 885 text

I’m sorry I have no money left to pay you. antisocial network RIP

Slide 886

Slide 886 text

I hope you enjoyed working here. antisocial network RIP

Slide 887

Slide 887 text

And that you’re able to use the skills you’ve gained in your next job. antisocial network RIP

Slide 888

Slide 888 text

Git Skillz antisocial network RIP

Slide 889

Slide 889 text

Git Skillz Branching antisocial network RIP

Slide 890

Slide 890 text

Git Skillz Branching Diffing antisocial network RIP

Slide 891

Slide 891 text

Git Skillz Branching Diffing Rebasing antisocial network RIP

Slide 892

Slide 892 text

Git Skillz Branching Diffing Rebasing Merging antisocial network RIP

Slide 893

Slide 893 text

Git Skillz Branching Diffing Rebasing Merging Committing antisocial network RIP

Slide 894

Slide 894 text

Git Skillz Branching Diffing Rebasing Merging Committing Pushing antisocial network RIP

Slide 895

Slide 895 text

MOAR Git antisocial network RIP

Slide 896

Slide 896 text

MOAR Git Bisecting antisocial network RIP

Slide 897

Slide 897 text

MOAR Git Bisecting Blaming antisocial network RIP

Slide 898

Slide 898 text

MOAR Git Bisecting Blaming Pull requests antisocial network RIP

Slide 899

Slide 899 text

MOAR Git Bisecting Blaming Pull requests Submitting patches antisocial network RIP

Slide 900

Slide 900 text

MOAR Git Bisecting Blaming Pull requests Submitting patches Rewriting history antisocial network RIP

Slide 901

Slide 901 text

MOAR Git Bisecting Blaming Pull requests Submitting patches Rewriting history Log formatting antisocial network RIP

Slide 902

Slide 902 text

MOAR Git Bisecting Blaming Pull requests Submitting patches Rewriting history Log formatting git help --all antisocial network RIP

Slide 903

Slide 903 text

pgTAP Skillz antisocial network RIP

Slide 904

Slide 904 text

pgTAP Skillz TDDD antisocial network RIP

Slide 905

Slide 905 text

pgTAP Skillz TDDD Schema testing antisocial network RIP

Slide 906

Slide 906 text

pgTAP Skillz TDDD Schema testing Scalar testing antisocial network RIP

Slide 907

Slide 907 text

pgTAP Skillz TDDD Schema testing Scalar testing Functional testing antisocial network RIP

Slide 908

Slide 908 text

pgTAP Skillz TDDD Schema testing Scalar testing Functional testing Relational testing antisocial network RIP

Slide 909

Slide 909 text

MOAR pgTAP antisocial network RIP

Slide 910

Slide 910 text

MOAR pgTAP Testing privileges antisocial network RIP

Slide 911

Slide 911 text

MOAR pgTAP Testing privileges Mocking interfaces antisocial network RIP

Slide 912

Slide 912 text

MOAR pgTAP Testing privileges Mocking interfaces Custom test functions antisocial network RIP

Slide 913

Slide 913 text

MOAR pgTAP Testing privileges Mocking interfaces Custom test functions xUnit-style testing antisocial network RIP

Slide 914

Slide 914 text

MOAR pgTAP Testing privileges Mocking interfaces Custom test functions xUnit-style testing Tests maintained in functions antisocial network RIP

Slide 915

Slide 915 text

MOAR pgTAP Testing privileges Mocking interfaces Custom test functions xUnit-style testing Tests maintained in functions http:/ /pgtap.org/documentation.html antisocial network RIP

Slide 916

Slide 916 text

Sqitch Skillz antisocial network RIP

Slide 917

Slide 917 text

Sqitch Skillz Adding changes antisocial network RIP

Slide 918

Slide 918 text

Sqitch Skillz Adding changes Dependency management antisocial network RIP

Slide 919

Slide 919 text

Sqitch Skillz Adding changes Dependency management Deploying changes antisocial network RIP

Slide 920

Slide 920 text

Sqitch Skillz Adding changes Dependency management Deploying changes Verifying changes antisocial network RIP

Slide 921

Slide 921 text

Sqitch Skillz Adding changes Dependency management Deploying changes Verifying changes Reverting changes antisocial network RIP

Slide 922

Slide 922 text

Sqitch Skillz Adding changes Dependency management Deploying changes Verifying changes Reverting changes Rebasing changes antisocial network RIP

Slide 923

Slide 923 text

Sqitch Skillz Adding changes Dependency management Deploying changes Verifying changes Reverting changes Rebasing changes Reworking changes antisocial network RIP

Slide 924

Slide 924 text

MOAR Sqitch antisocial network RIP

Slide 925

Slide 925 text

MOAR Sqitch Cross-project dependencies antisocial network RIP

Slide 926

Slide 926 text

MOAR Sqitch Cross-project dependencies Multiple projects, one database antisocial network RIP

Slide 927

Slide 927 text

MOAR Sqitch Cross-project dependencies Multiple projects, one database Script templating antisocial network RIP

Slide 928

Slide 928 text

MOAR Sqitch Cross-project dependencies Multiple projects, one database Script templating Changing Branches antisocial network RIP

Slide 929

Slide 929 text

MOAR Sqitch Cross-project dependencies Multiple projects, one database Script templating Changing Branches Checkout command antisocial network RIP

Slide 930

Slide 930 text

MOAR Sqitch Cross-project dependencies Multiple projects, one database Script templating Changing Branches Checkout command Reverts to last common change antisocial network RIP

Slide 931

Slide 931 text

MOAR Sqitch Cross-project dependencies Multiple projects, one database Script templating Changing Branches Checkout command Reverts to last common change Changes Git branch & Deploys antisocial network RIP

Slide 932

Slide 932 text

MOAR Sqitch Cross-project dependencies Multiple projects, one database Script templating Changing Branches Checkout command Reverts to last common change Changes Git branch & Deploys sqitch help, sqitch help --guide antisocial network RIP

Slide 933

Slide 933 text

Good luck out there. antisocial network RIP

Slide 934

Slide 934 text

Agile Database Development Text: Attribution-Noncommercial-Share Alike 3.0 United States: http:/ /creativecommons.org/licenses/by-nc-sa/3.0/us/ Images licensed independently and © Their respective owners. David E. Wheeler sqitch.org iovation January 28, 2016