Make Release

Table of Contents

1 Project Details

     Download: via SVN only
     Website: makerelease
     SF Project: makerelease

2 Introduction and History

2.1 Release Pain

One of the issues with releasing software is that you need to do mind-numbing tasks over and over and it is a barrier to "release early, release often". Not only that, releasing a particular package becomes an art-form to do all the right steps in the right order without forgetting anything.

The result of this problem is usually one of:

  1. 1-2 knowledgeable people and if they perished someone else would be bound to repeat the undocumented mistakes they made.
  2. A hand-crafted shell script of some kind that automates at least some of the tasks. (somewhere in the middle there is invariably a human step that needs to be done that requires "do this and press enter".)
  3. Documentation describing the release-steps that need to be performed.

For projects I've worked on in the past, there is often been all three. The scripts get you "so far" but there is still a lot of operator knowledge. Sometimes that knowledge is encoded into a documentation file, but I've found that typically the documentation lags behind the script, the expert operator or both.

2.2 The solution: makerelease

It is, of course, impossible to take all the fun out of the process and make everything totally automated. The goal of makerelease is a few fold:

  • Ensure the documentation and the automated systems are combined and thus always in sync
  • Automattable instructions (commands to be run) can be included directly and run automatically.
  • The user can be prompted for values that need to be entered by a human (like a version number for the release).
  • It can be run interactively, prompting the administrator at each step if each step should be done or not.
  • Steps can be grouped together (e.g. "preparing", "packaging", "uploading", …)

3 Usage

3.1 Step by Step

makerelease divides up your release steps into pieces. Each step contains documentation and instructions (automatically done or not) that need to be done. There are a number of different types of steps.

3.2 Structured in XML

All the steps are documented and defined using a simple xml syntax. This provides easy editing using any common text editor, but still allows for documentation to be easily embedded and displayable by the makerlease tool. The most basic step structure looks like:

 <makerelease>
   <steps>
     <step type="informational">
       <text>
        Advertise: NEWS upload to sf, publish on -announce, freshmeat,
        and the GNU FSF directory
        (http://directory.fsf.org/)...
         (send mail to bug-directory@gnu.org)
       </text>
     </step>
   </steps>
 </makerelease>

This example step (an informational step) simply prints the text to the screen for the user to read.

3.3 makerelease -n: dry-run and produce documentation

You can test running makerelease on a defined xml file using the -n switch. This produces documentation about the steps to be done. For example, running makerelease -n on the previous example would produce:

3.4 makerelease:

By default, makerelease looks for a makerelease.xml file in the current directory. Use the -c FILE flag to specify a particular file to load. It will then proceed to iterate through each step and act accordingly. See the Writing Steps section below for details.

 # makerelease -c example.xml -n
 STEP: 1:

   Advertise: NEWS upload to sf, publish on -announce, freshmeat, and
   the GNU FSF directory (http://directory.fsf.org/)... (send mail to
   bug-directory@gnu.org)

Note: by default it wraps all text nicely to fit into the screen for you.

4 Writing Steps

There are a large number of step types, each with their own purpose. Some flags for them work globally (on any step type) and some are Step specific.

4.1 Global Attributes and Data

4.1.1 <text>foo</text>

The <text> section is used to describe a particular step for documentational purposes. It is output both to the operator doing an actual release as well as when using the -n flag to simply produce documentation.

4.1.2 title="Title for the Step"

A step with the /title="something"/ attribute to the step will "name" the step when displaying it to the user.

     <step type="informational" title="Call Bob">
       <text>
        Call Bob and have him commit all his outstanding changes.
       </text>
     </step>

Produces:

 # makerelease -c example.xml
 [...]
 STEP: 2:  Call Bob

   Call Bob and have him commit all his outstanding changes.

4.1.3 stepname="name"

The stepname will eventually be used to control auto-skipping of things. It is most useful when used with a structured naming scheme like "build:configure".

4.1.4 pause="true"

Creating a step with <step pause="true" …> will tell makerelease to stop after the text is displayed and wait for the user to acknowledge the screen.

     <step type="informational" pause="true" title="Call Bob">
       <text>
        Call Bob and have him commit all his outstanding changes.
       </text>
     </step>

Produces:

 # makerelease -c example.xml
 [...]
 STEP: 2:  Call Bob

   Call Bob and have him commit all his outstanding changes.

 ---- PRESS ENTER TO CONTINUE (q=quit) ----

4.2 Step Types

4.2.1 Informational

Informational steps simply present information to the administrator and do not perform any specific action. They're there just to document a step. They can be used to tell an administrator to do something that can't be automated by including the prompt flag to ensure the user sees it.

     <step type="informational" pause="true">
       <text>
        Call Bob and have him commit all his outstanding changes.
       </text>
     </step>

Produces:

 # makerelease -c example.xml
 [...]
 STEP: 2:

   Call Bob and have him commit all his outstanding changes.

 ---- PRESS ENTER TO CONTINUE (q=quit) ----

4.2.2 Section

The section type lets you group various sub-steps together. It allows for entire sections to be skipped when using the -i p flag and documentation to be divided up into sections.

    <step type="section" title="Setup Steps" mandatory="1">
     <text>These steps do preliminary work for making a release.</text>
     <steps>
       <step type="system">
         <commands>
           <command>echo "hello world"</command>
         </commands>
       </step>
       <step type="informational">
         <text>Also, Hello Universe</text>
       </step>
     </steps>
    </step>

Produces:

 # makerelease -c example.xml -n
 STEP: 1: Setup Steps                                                          

   These steps do preliminary work for making a release.

   ===== Entering Step: 1 =====

 STEP: 1.1:

   Commands to execute:

     echo "hello world"

 STEP: 1.2:

   Also, Hello Universe

   (Leaving Step: 1)

4.2.3 Include

An include directive is functionally the same as a section directive, but the sections are specified in another makerelease xml file (which must be a fully qualified xml file with the top level <makerelease> tag in place.

    <step type="include" title="Super extra steps">
     <file>/path/to/foo.xml</file>
    </step>

4.2.4 Command

Command steps are designed to run a particular set of commands via system() calls. All the commands must succeed or the user will be prompted for what to do next (continue, retry or quit).

     <step type="command">
       <commands>
         <command>echo "hello world"</command>
         <command>rm /</command>
       </commands>
     </step>

Produces:

  STEP: 3:

    running 'echo "hello world"'

  hello world


    running 'rm /'

  rm: cannot remove `/': Is a directory
  failed: status=256 what now (c,r,q)?

4.2.5 Prompt

     <step type="prompt" prompt="Enter the version number:"
           title="Pick a Version Number for this release"
           parameter="VERSION">
     </step>

Asks the user for a version number and assigns the result to the VERSION parameter. The VERSION parameter can be used in future system commands, text, etc by wrapping the parameter name in {} brackets.

     <step type="system">
       <text>We're going to produce {VERSION}
       <commands>
         <command>echo Hello World version {VERSION}</command>
       </commands>
     </step>

You can also add a values= attribute to specify the legal values that can be chosen based on a regular expression. For example, the following enforces a strict NUM.NUM format:

     <step type="prompt" prompt="Enter the version number:"
           title="Pick a Version Number for this release"
           parameter="VERSION"
           values="^\d+\.\d+$">
     </step>

4.2.6 Modify

The modify step lets you make regexp based modifications to files within the distribution. Files are passed through glob() so can include wildcards (*) characters.

        <step type="modify" title="Update the version number">
          <text>
            We will now modify files through the code to replace the
            version number with the newer one.
          </text>
          <modifications>
            <modify
              find="VERSION = '(.*)'"
              replace="VERSION = \'{VERSION}\'">
              <files>
                <file>lib/MyModule.pm</file>
                <file>lib/SubDir/*.pm</file>
              </files>
            </modify>
          </modifications>
        </step>

Note: You may specify multiple <modify> sections within the <modifications> tag too.

4.2.7 Perl

A wise man once said "when all else fails, resort to perl". Ok, I don't know that anyone said that actually. But I bet someone did because it seems wise to me. Sometimes it's necessary to do extra processing of user-entered data or files or the moon. Embedding perl code directly lets you accomplish these sorts of things.

The $self variable will be to the current Makerelease::Step::Perl module, and within that is a reference to the parameters hash in $self->{'parameters'}.

Here's an example that takes the VERSION parameter and creates a new one called VERSIONDASHES with the dots replaced by dashes.

        <step type="perl" title="Defining a second internal version string"
          mandatory="1">
          <perl>
            <code>
              # version number with dashes instead of dots
              $self->{'parameters'}{'VERSIONDASHES'} =
                  $self->{'parameters'}{'VERSION'};
              $self->{'parameters'}{'VERSIONDASHES'} =~ s/\./-/g;
            </code>
          </perl>
        </step>

5 Examples

5.1 Projects that are making use of makerelease scripts

(scripts are located in the "dist" subdirectory if not otherwise specified):

5.2 Included example scripts

  • dist/makerelease.xml: the release script for this package!


Date: 2008-11-03 08:57:26 PST

HTML generated by org-mode 6.10c in emacs 21