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