On drupal.org, we use project release in conjunction with Git to manage releases of Drupal core and all the contributions (modules, themes, etc). There is a packaging script included with the Project release module, called package-release-nodes.php, which is the script used on drupal.org itself. It is included as an example, and is heavily commented. Running this script on your own site will definitely involve some modifications to the script, so please read it carefully before you just install it and setup a cron job to invoke it periodically.

The following page will explain in high-level terms what the script is doing for the drupal.org case, to give you an overview to understand the process we use as you seek to customize it for your own needs.

The script has two modes: "branch" mode for the dev snapshots, and "tag" mode for the official releases. Cron calls the script every 12 hours in branch mode, and every 5 minutes in tag mode.

Branch mode

  • Queries the DB for every release node that's marked as a dev snapshot (the "rebuild" bit is set in {project_release_nodes}). Actually, the query is a little more complicated, since it also makes sure that either the release node is published, or it doesn't have a file (the case for a brand new dev snapshot release) so that if you unpublish an existing -dev, the script will ignore it.
  • For each one, checks out the appropriate directory/branch from the release node into a temp dir.
  • Recursively finds the newest modification date of any file in the directory tree.
  • Compares to the timestamp on the existing tarball for this release.
  • If the tarball is newer, cleanup and move on.
  • If a file is newer, tar up the directory, overwrite the tarball, and update the row for this release node in the DB with the new md5 hash and date.

Tag mode

  • Queries the DB for every release node that's from a tag ("rebuild" bit set to 0) which doesn't have a file associated with it.
  • For each one, checks out the appropriate directory/branch from the release node into a temp dir.
  • Tar it up.
  • Update the DB for the release node to give it a file path, md5 hash, date, etc.

Common tasks

In both cases, if it's going to tar up the directory, it also updates the .info files with the special stuff that's automatically appended, such as the human-readable version string and the project name. Also, in both cases, it will publish the release node once the tarball exists and the metadata is in the DB (assuming it's not tagged as a "security update", in which case the script leaves it unpublished).

So, it's about as efficient as can be. The tag case is obviously vastly less expensive, which is why it happens much more frequently. The full branch mode run takes about 30 minutes or so on the drupal.org infrastructure with a few thousand contributed projects, the last time I checked (there are watchdog entries where you can view all this stuff). There's some other details in the script about error propagation and the like, but those aren't essential to understand the basic functioning. There's also a mode to run it interactively where you restrict it to a specific project id (which is handy when debugging or repairing something, etc).