]> scripts.mit.edu Git - wizard.git/blob - doc/upgrade.rst
Handle Wordpress random keys correctly on install and upgrade.
[wizard.git] / doc / upgrade.rst
1 Preparing an upgrade
2 ====================
3
4 :Author: Edward Z. Yang <ezyang@mit.edu>
5
6 .. highlight:: sh
7
8 Wizard is designed to make pushing upgrades as painless as possible.
9 In the best case scenario, adding a new version to a Wizard repository
10 is as simple as running a few commands.  Even when upstream makes
11 backwards incompatible changes, or some of your patches conflict with
12 other changes, Wizard aims to make resolving these changes tractable.
13
14 Summary
15 -------
16
17 ``$VERSION`` is a version number i.e. ``1.2.4``,
18 ``$APPLICATION`` is the official application name i.e. ``MediaWiki``, and
19 ``$APP`` is our internal name i.e. ``mediawiki``.  The key thing to note
20 is that we use ``wizard prepare-pristine`` in order to simulate the
21 upstream upgrade, and then we piggy back off of Git's merge machinery
22 to do everything else.
23
24 First you prepare the pristine copy::
25
26     git checkout pristine
27     wizard prepare-pristine $APP-$VERSION
28     git commit -asm "$APPLICATION $VERSION"
29     git tag $APP-$VERSION
30
31 Next, you merge those changes to the scriptsified ``master`` copy::
32
33     git checkout master
34     git merge pristine --no-commit
35     # resolve conflicts
36     git commit -asm "$APPLICATION $VERSION-scripts"
37
38 .. note::
39
40     If you are creating a fix for a previous scripts version, you should
41     bump the version to ``$VERSION-scripts2``.
42
43 Then, on a scripts server with Wizard pointed at the latest version, run::
44
45     cd tests
46     env WIZARD_NO_COMMIT=1 ./test-install-$APP.sh
47     cd testdir_install_$APP_head
48     wizard prepare-config
49
50 With any luck, there will be no differences; if there are
51 manually restore any custom changes we may have made to the configuration
52 file, make sure that no upstream changes broke our regular expressions
53 for matching.  Then amend your commit and push back::
54
55     git commit --amend -a
56     git tag $APP-$VERSION-scripts
57     git push --force
58     git push --force --tags
59
60 On any other copies that have the older commit, run the following commands
61 while on the ``master`` branch to grab the new version::
62
63     git fetch --tags $REMOTE
64     git reset --hard $REMOTE/master
65
66 Be sure to verify that your commit is the correct one; you can check with
67 ``git show``, which should show the changes you made when amending the
68 commit.  Be especially careful to make sure you don't nuke any in
69 configuration scripts changes.
70
71 Implementation
72 --------------
73
74 If it is the first time you have pushed an upgrade for an application, you
75 will have to write a few more methods in your :class:`wizard.app.Application`
76 class:  :meth:`~wizard.app.Application.upgrade`, :meth:`~wizard.app.Application.checkWeb`,
77 :meth:`~wizard.app.Application.backup` and :meth:`~wizard.app.Application.restore`.
78 The latter three may not seem so useful for just pushing an upgrade, but are helpful
79 for integrity checking installations post-upgrade, and rolling back if something
80 went wrong.
81
82 :meth:`~wizard.app.Application.checkWeb` is a method that should check whether
83 or not an application is running properly.  We use this to prevent us from trying
84 to upgrade an install that is not publically accessible, or was broken from
85 the very start, and we use it to automatically determine if our upgrade was
86 successful or not.  A common and easy way to perform this check is to
87 use the :meth:`~wizard.app.Application.checkWebPage` method, which, along
88 with the parameters :meth:`~wizard.app.Application.checkWeb` accepts, accepts
89 two more: ``page`` and ``output``, which correspond to the page to grab from
90 the web and the output string to match for in this page,
91
92 .. warning::
93
94     We still haven't quite figured out a good combination of in-depth error checking
95     and robustness against skin changes.  This section should be further developed
96     with tips about this.
97
98 :meth:`~wizard.app.Application.backup` and :meth:`~wizard.app.Application.restore`
99 perform backup and restoration of non-filesystem contents; the most common application
100 is for the database.  :func:`wizard.app.backup_database` and :func:`wizard.app.restore_database`
101 implement this common functionality, and for
102 most application implementing these methods is as simple as:
103
104 .. code-block:: python
105
106     def backup(self, deployment, backup_dir, options):
107         app.backup_database(backup_dir, deployment)
108     def restore(self, deployment, backup_dir, options):
109         app.restore_database(backup_dir, deployment)
110
111 Finally, :meth:`~wizard.app.Application.upgrade` actually performs an upgrade,
112 and will most frequently call a shell script or fetches a web page that will
113 perform a schema upgrade.
114
115 .. note::
116
117     When migrating an old-style autoinstall, it is neither expected nor
118     required for upgrade scripts for the intervening versions to be
119     created.
120
121 Troubleshooting
122 ---------------
123
124 Merge failed
125 ''''''''''''
126
127 When a merge fails, it's often good to refresh your memory about what
128 particular patch was made to that file.  You can find out with::
129
130     git diff :1:$FILE :2:$FILE
131
132 If you are performing a repository conversion, a failed merge likely
133 means that there is an updated patch lying around in
134 :file:`/mit/scripts/deploy/$APP-$VERSION`.  You can then revert
135 the files to the pristine version::
136
137     git checkout --theirs $FILE
138
139 And then apply the patch.  If the patch is complicated, you may get
140 warnings about hunks already being applied; you can ignore those warnings
141 (don't assume ``-R``!)
142
143 Going retro
144 -----------
145
146 Under certain circumstances, you may need to splice in older versions
147 of the application into your history.  Do not rebase: you should never
148 rebase published history.  Instead, use the following procedure:
149
150 Identify the version that, with regards to version numbering,
151 directly precedes the version you'd like to add.  For example, if
152 you have the following commit tree:
153
154 .. digraph:: original_dag
155
156     node [shape=square]
157     subgraph cluster_master {
158         bs -> as
159         as [label="1.0-scripts"]
160         bs [label="2.0-scripts"]
161         label = "master"
162         color = white
163     }
164     subgraph cluster_pristine {
165         b -> a
166         a [label="1.0"]
167         b [label="2.0"]
168         label = "pristine"
169         color = white
170     }
171     bs -> b
172     as -> a
173
174 And you are adding the 1.1 version, 1.0 and 1.0-scripts are the
175 tags immediately preceding this version.  Create temporary
176 branches (we'll name them ``tmaster`` and ``tpristine``) pointing
177 to these tags::
178
179     git checkout -b tmaster
180     git reset --hard 1.0-scripts
181     git checkout -b tpristine
182     git reset --hard 1.0
183
184 Find the committer date associated with the ``tmaster`` commit using ``git show tmaster``
185 and note it somewhere::
186
187     DATE=`git show tmaster --pretty="format:%cd" | head -n1`
188
189 Next, begin performing ordinary procedure for preparing the
190 pristine copy.  There are two caveats:  you will need to use ``--force``
191 to make ``wizard prepare-pristine`` not complain about not being on
192 the ``pristine`` branch, and you will need to falsify the author
193 and committer time on the commits to be the times we noted down
194 previously::
195
196     # on the tpristine branch
197     wizard prepare-pristine $APP-$VERSION --force
198     env GIT_AUTHOR_DATE="$DATE" GIT_COMMITTER_DATE="$DATE" git commit -asm "$APPLICATION $VERSION"
199     git tag $APP-$VERSION
200
201 .. note::
202
203     The date falsification is necessary to make Git prefer the
204     later version tag when a commit has this (newer) commit and
205     the most up-to-date version as merge parents.  By default
206     Git prefers the temporally closest commit.
207
208 Next, merge the changes to the scriptsified ``tmaster`` (not ``master``!) copy,
209 and falsify the dates as well::
210
211     git checkout tmaster
212     git merge tpristine --no-commit
213     # resolve conflicts
214     env GIT_AUTHOR_DATE="$DATE" GIT_COMMITTER_DATE="$DATE" git commit -asm "$APPLICATION $VERSION-scripts"
215     git tag $APP-$VERSION-scripts
216
217 Note that we are creating a tag, because otherwise there is not an easy way
218 to refer to this non-HEAD tag.  On a scripts server with Wizard pointed at the
219 latest version, run::
220
221     cd tests
222     env WIZARD_NO_COMMIT=1 ./$APP-install-test.sh $VERSION
223     cd testdir_install_$APP_$VERSION
224     wizard prepare-config
225
226 Note that ``$VERSION`` is specified explicitly.  If there are changes,
227 manually restore any custom changes we may have made, then amend your commit and
228 push back::
229
230     # you probably lost your environment variable
231     DATE=`git show HEAD --pretty="format:%ad" | head -n1`
232     env GIT_AUTHOR_DATE="$DATE" GIT_COMMITTER_DATE="$DATE" git commit --amend -a
233     git tag -d $APP-$VERSION-scripts
234     git tag $APP-$VERSION-scripts
235     git push --force --tags
236
237 And on your now invalid version, grab the new version::
238
239     git fetch --tags --force $REMOTE
240
241 Note that there is no need to reset the master branch, which hasn't changed.