4 :Author: Edward Z. Yang <ezyang@mit.edu>
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.
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.
24 First you prepare the pristine copy::
27 wizard prepare-pristine $APP-$VERSION
28 git commit -asm "$APPLICATION $VERSION"
31 Next, you merge those changes to the scriptsified ``master`` copy::
34 git merge pristine --no-commit
36 git commit -asm "$APPLICATION $VERSION-scripts"
40 If you are creating a fix for a previous scripts version, you should
41 bump the version to ``$VERSION-scripts2``.
43 Then, on a scripts server with Wizard pointed at the latest version, run::
46 env WIZARD_NO_COMMIT=1 ./test-install-$APP.sh
47 cd testdir_install_$APP_head
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::
56 git tag $APP-$VERSION-scripts
58 git push --force --tags
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::
63 git fetch --tags $REMOTE
64 git reset --hard $REMOTE/master
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.
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
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,
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
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:
104 .. code-block:: python
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)
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.
121 When a merge fails, it's often good to refresh your memory about what
122 particular patch was made to that file. You can find out with::
124 git diff :1:$FILE :2:$FILE
126 If you are performing a repository conversion, a failed merge likely
127 means that there is an updated patch lying around in
128 :file:`/mit/scripts/deploy/$APP-$VERSION`. You can then revert
129 the files to the pristine version::
131 git checkout --theirs $FILE
133 And then apply the patch. If the patch is complicated, you may get
134 warnings about hunks already being applied; you can ignore those warnings
135 (don't assume ``-R``!)
140 Under certain circumstances, you may need to splice in older versions
141 of the application into your history. Do not rebase: you should never
142 rebase published history. Instead, use the following procedure:
144 Identify the version that, with regards to version numbering,
145 directly precedes the version you'd like to add. For example, if
146 you have the following commit tree:
148 .. digraph:: original_dag
151 subgraph cluster_master {
153 as [label="1.0-scripts"]
154 bs [label="2.0-scripts"]
158 subgraph cluster_pristine {
168 And you are adding the 1.1 version, 1.0 and 1.0-scripts are the
169 tags immediately preceding this version. Create temporary
170 branches (we'll name them ``tmaster`` and ``tpristine``) pointing
173 git checkout -b tmaster
174 git reset --hard 1.0-scripts
175 git checkout -b tpristine
178 Find the committer date associated with the ``tmaster`` commit using ``git show tmaster``
179 and note it somewhere::
181 DATE=`git show tmaster --pretty="format:%cd" | head -n1`
183 Next, begin performing ordinary procedure for preparing the
184 pristine copy. There are two caveats: you will need to use ``--force``
185 to make ``wizard prepare-pristine`` not complain about not being on
186 the ``pristine`` branch, and you will need to falsify the author
187 and committer time on the commits to be the times we noted down
190 # on the tpristine branch
191 wizard prepare-pristine $APP-$VERSION --force
192 env GIT_AUTHOR_DATE="$DATE" GIT_COMMITTER_DATE="$DATE" git commit -asm "$APPLICATION $VERSION"
193 git tag $APP-$VERSION
197 The date falsification is necessary to make Git prefer the
198 later version tag when a commit has this (newer) commit and
199 the most up-to-date version as merge parents. By default
200 Git prefers the temporally closest commit.
202 Next, merge the changes to the scriptsified ``tmaster`` (not ``master``!) copy,
203 and falsify the dates as well::
206 git merge tpristine --no-commit
208 env GIT_AUTHOR_DATE="$DATE" GIT_COMMITTER_DATE="$DATE" git commit -asm "$APPLICATION $VERSION-scripts"
209 git tag $APP-$VERSION-scripts
211 Note that we are creating a tag, because otherwise there is not an easy way
212 to refer to this non-HEAD tag. On a scripts server with Wizard pointed at the
213 latest version, run::
216 env WIZARD_NO_COMMIT=1 ./$APP-install-test.sh $VERSION
217 cd testdir_install_$APP_$VERSION
218 wizard prepare-config
220 Note that ``$VERSION`` is specified explicitly. If there are changes,
221 manually restore any custom changes we may have made, then amend your commit and
224 # you probably lost your environment variable
225 DATE=`git show HEAD --pretty="format:%ad" | head -n1`
226 env GIT_AUTHOR_DATE="$DATE" GIT_COMMITTER_DATE="$DATE" git commit --amend -a
227 git tag -d $APP-$VERSION-scripts
228 git tag $APP-$VERSION-scripts
229 git push --force --tags
231 And on your now invalid version, grab the new version::
233 git fetch --tags --force $REMOTE
235 Note that there is no need to reset the master branch, which hasn't changed.