]> scripts.mit.edu Git - wizard.git/blobdiff - doc/repository-conversion.rst
More documentation improvements.
[wizard.git] / doc / repository-conversion.rst
index 14a8547c6e35361719338dd4e0ce9d616cc0be2f..171f592db46ddcc70bf76a64d543d761cd2207ee 100644 (file)
@@ -1,6 +1,8 @@
 Repository conversion
 =====================
 
+.. highlight:: sh
+
 One of Wizard's goals is to replace the previous autoinstaller infrastructure.
 Pre-wizard autoinstalls live in :file:`/mit/scripts/deploy` and consist of a
 tarball from upstream, possibly a scripts patch, and possibly some post-install
@@ -19,8 +21,6 @@ an example.
 Setup
 -----
 
-.. highlight:: sh
-
 Probably the easiest way to do development is entirely on :term:`AFS`:  all
 of your source code should live in publically readable (i.e.
 ``system:anyuser`` as read permissions) directories, so that if you
@@ -70,8 +70,6 @@ named ``$WIZARD``; note that application repositories live in ``$WIZARD/srv``.
 Pristine
 --------
 
-.. highlight:: sh
-
 This is a tutorial centered around migrating `Wordpress <http://wordpress.org/>`_
 into our Git repository.  For the sake of demonstration,
 we shall assume that this repository hasn't been created yet.
@@ -82,17 +80,21 @@ The repository then doesn't exist, we should create it::
     cd wordpress
     git init
 
-.. highlight:: python
-
 We also have to create a module for the application, so we
-create ``$WIZARD/wizard/app/wordpress.py`` and fill it in with a bare bones template::
+create ``$WIZARD/wizard/app/wordpress.py`` and fill it in with a bare bones template:
+
+.. code-block:: python
+
+    import os
+    import re
+    import logging
+
+    from wizard import app, install, resolve, sql, util
+    from wizard.app import php
 
-    from wizard import app
     class Application(app.Application):
         pass
 
-.. highlight:: sh
-
 Now we are ready to put some code in our repository: the first thing we will
 add is the :term:`pristine` branch, which contains verbatim the code from upstream.
 If we were starting a new autoinstaller, we'd pop off and use the latest version,
@@ -108,17 +110,15 @@ Try running the following command in :file:`$WIZARD/srv/wordpress`::
 
     wizard prepare-pristine wordpress-2.0.2
 
-.. highlight:: python
-
 You should get an error complaining about :meth:`wizard.app.Application.download`
-not being implemented yet. Let's fix that::
+not being implemented yet. Let's fix that:
+
+.. code-block:: python
 
     class Application(app.Application):
         def download(self, version):
             return "http://wordpress.org/wordpress-%s.tar.gz" % version
 
-.. highlight:: sh
-
 We determined this by finding `Wordpress's Release Archive <http://wordpress.org/download/release-archive/>`_
 and inferring the naming scheme by inspecting various links.  You should now
 be able to run the prepare-pristine command successfully: when it is
@@ -202,8 +202,6 @@ are done, here is the graph from before, but augmented with the scripts versions
     c -> cs
     a []
 
-.. highlight:: sh
-
 First things first: verify that we are on the master branch::
 
     git checkout master
@@ -254,8 +252,14 @@ configuration file, so creating the install script involves:
 There's an in-depth explanation of named input values in
 :mod:`wizard.install`.  The short version is that your application
 contains a class-wide :data:`~wizard.app.Application.install_schema`
-attribute that encodes this information.  The constructor takes
-an arbitrary number of arguments (to be continued)
+attribute that encodes this information.  Instantiate it with
+:class:`wizard.install.ArgSchema` (passing in arguments to get
+some pre-canned input values), and then add application specific
+arguments by passing instances of :class:`wizard.install.Arg`
+to the method :meth:`~wizard.install.ArgSchema.add`.  Usually you should
+be able to get away with pre-canned attributes.  You can access
+these arguments inside :meth:`~wizard.app.Application.install` via
+the ``options`` value.
 
 Some tips and tricks for writing :meth:`wizard.app.Application.install`:
 
@@ -279,6 +283,11 @@ Some tips and tricks for writing :meth:`wizard.app.Application.install`:
       consequently be queried.  For convenience, we've bound metadata
       to the connection, you can perform implicit execution.
 
+.. todo::
+
+    Our installer needs to also parametrize :file:`php.ini`, which we haven't
+    done yet.
+
 To test if your installation function works, it's probably convenient to
 create a test script in :file:`tests`; :file:`tests/test-install-wordpress.sh`
 in the case of Wordpress.  It will look something like::
@@ -295,6 +304,97 @@ in the case of Wordpress.  It will look something like::
 operation without any version specified (since we haven't tagged any of our
 commits yet, we can't use the specific version functionality; not that we'd want
 to, though).  ``TESTNAME`` is simply the name of the file with the leading
-``test-`` stripped and dashes converted to underscores.
+``test-`` stripped and dashes converted to underscores.  Run the script with
+verbose debugging information by using::
+
+    env WIZARD_DEBUG=1 ./test-install-wordpress.sh
+
+Versioning config
+-----------------
+
+A design decision that was made early on during Wizard's development was that
+the scriptsified versions would contain generic copies of the configuration
+files.  You're going to generate this generic copy now and in doing so,
+overload your previous scripts commit.   Because some installers
+exhibit different behavior depending on server configuration, you should run
+the installation on a Scripts server::
+
+    wizard install wordpress --no-commit
+
+The installer will interactively prompt you for some values, and then conclude
+the install.  ``--no-commit`` prevents the installer from generating a Git
+commit after the install, and will make it easier for us to propagate the
+change back to the parent repository.
+
+Look at the changes the installer made::
+
+    git status
+
+There are probably now a few unversioned files lounging around; these are probably
+the configuration files that the installer generated.
+
+You will now need to implement the following data attributes and methods in your
+:class:`~wizard.app.Application` class: :attr:`~wizard.app.Application.extractors`,
+:attr:`~wizard.app.Application.substitutions`, :attr:`~wizard.app.Application.parametrized_files`,
+:meth:`~wizard.app.Application.checkConfig` and :meth:`~wizard.app.Application.detectVersion`.
+These are all closely related to the configuration files that the installer generated.
+
+:meth:`~wizard.app.Application.checkConfig` is the most straightforward method to
+write: you will usually only need to test for the existence of the configuration file.
+Note that this function will always be called with the current working directory being
+the deployment, so you can simplify your code accordingly:
+
+.. code-block:: python
+
+    def checkConfig(self, deployment):
+        return os.path.isfile("wp-config.php")
+
+:meth:`~wizard.app.Application.detectVersion` should detect the version of the application
+by regexing it out of a source file.  We first have to figure out where the version number
+is stored: a quick grep tells us that it's in :file:`wp-includes/version.php`:
+
+.. code-block:: php
+
+    <?php
+
+    // This just holds the version number, in a separate file so we can bump it without cluttering the SVN
+
+    $wp_version = '2.0.4';
+    $wp_db_version = 3440;
+
+    ?>
+
+We could now grab the :mod:`re` module and start constructing a regex to grab ``2.0.4``, but it
+turns out this isn't necessary: :meth:`wizard.app.php.re_var` does this for us already!
+If such a module doesn't exist, you should create it and place an equivalent ``re_var()``
+function for that language there.
+
+With this function in hand, writing a version detection function is pretty straightforward.
+There is one gotcha: the value that ``re_var`` returns as the second subpattern is quoted (the reasons for this
+will become clear shortly), so you will need to trim off the last and first characters or
+use :mod:`shlex`.  In the case of version numbers, there are probably no escape characters
+in the string, so the former is relatively safe.
+
+.. code-block:: python
+
+    def detectVersion(self, deployment):
+        contents = open("wp-includes/version.php").read()
+        match = php.re_var("wp_version").search(contents)
+        if not match: return None
+        return distutils.version.LooseVersion(match.group(2)[1:-1])
+
+:attr:`~wizard.app.Application.parametrized_files` is a simple list of files that the
+program's installer wrote or touched during the installation process.
+
+.. code-block:: python
+
+    parametrized_files = ['wp-config.php']
+
+This is actually is a lie: we also need to include changes to :file:`php.ini` that
+we made:
+
+.. code-block:: python
+
+    parametrized_files = ['wp-config.php'] + php.parametrized_files
+
 
-(to be continued)