TDM Release Mechanics
This article describes the process of creating a TDM point release. It will be fleshed out over the next few days/weeks.
The team is using a version control system (SVN) for development, and the objective is to create a set of PK4 file from the repository which can be uploaded to the TDM mirrors. Let's go through this step by step:
Development
Just for the sake of completeness, this step includes the regular development between two TDM releases. This day-to-day development is always happening on the trunk, so all commits are ending up there. Stuff gets broken, stuff gets fixed, stuff gets evaluated, some might be ripped out again.
Branching off
At some point the team decides that it might be time for a new release - a so-called branch date (some sort of semi-freeze) is suggested and agreed upon. To this date, team members are supposed to wrap up their pending changes and commit them to the trunk. About two to three weeks are long enough of a time span for people to get everything into SVN.
Once the deadline arrives, the release branch is created:
- Update your darkmod working copy.
- Update the darkmod_src repository too.
- Right-click the darkmod folder to create the branch
- Select SVN > Branch/Tag...
- A new dialog appears asking for a URL. Enter a URL like this: https://<darkmod_server_here>/svn/darkmod/branches/release1.xx where xx is replaced by whatever version the next release will be.
- You'll probably want to switch to the new branch once it is created, so make sure the check button at the bottom of the dialog is active.
- Hit OK to let the SVN server create the branch (the server will create a copy of the trunk, placing it at the URL you specified. It might be notable that the files are not physically copied, the branch requires a marginal amount of additional server space).
- The same should happen with the darkmod_src repository, the code needs to be frozen as well. Perform the same steps as above, using the URL scheme https://<darkmod_server_here>/svn/darkmod_src/branches/release1.xx
At this point there are two new branches, one for the darkmod repo, one for darkmod_src. Consider them a snapshot of the trunk at the point in time you created the branch.
Important: commits to the trunk won't affect this newly created branch. The team members not involved in the release can just continue working as usual. Also note that if you as branch creator had the check button ("switch working copy") activated, your working copy has been switched to the release branch. Your commits will go to the branch, keep that in mind. To learn how to merge stuff between the trunk and the release branch, see below.
Compile Game Binaries
Before the PK4 files can be assembled into a release package, the code from darkmod_src needs to be re-compiled for the Windows and Linux platforms. This is to make sure that the release is built from the most recent (and hopefully most stable) source. If you're not a coder, you can either ask your fellow coders to switch to the branch and compile the tdm_gameNN.pk4 for you, or you can bite the bullet and follow the TDM Compilation Guide to compile it yourself. As Windows user, I recommend setting up an Ubuntu 10.04 32-Bit instance in VirtualBox. The downside of using virtualisation is that compilation takes 30-40 Minutes depending on your CPU power, but you at least don't need a dual-boot setup, let alone a second PC.
Make sure you compile a release build (debug builds are terribly slow), I also recommend re-compiling everything from scratch everytime you build a binary:
- Windows/VC++: Menu Build > Rebuild Solution
- Linux: scons -c && scons BUILD="release" BUILD_GAMEPAK="1"
Once compiled, make sure that the tdm_game01.pk4 is updated with the newly compiled DLL and the tdm_game02.pk4 is copied over from darkmod_src (where it is created after compilation) to darkmod and commit these two files to the branch.
The Manifest
The "manifest" is a huge text files listing all the files that are nominated to go into the release. Not all files in SVN are supposed to be released (like test files, test maps, other broken or unfinished stuff), so we need a white list. The manifest text file is located in the SVN repository: devel/manifests/darkmod.txt
Building the Manifest
Note: This section is more or less for your understanding, you don't need to manually generate the manifest anymore as this step is part of the automated process running on the TDM server itself.
The manifest file is generated by the tdm_package application. (The tdm_package sources are in the darkmod_src repository, in a subfolder called tdm_update. There is a VC++ 2010 solution and a sconscript for Linux and Mac builds available. You don't need to compile it if you're in Windows, there is a pre-compiled version in the darkmod repo as well, in the devel/packager folder.)
After the generation step the file devel/manifests/darkmod.txt will have been updated. You might want to review the modifications the script made to that file and commit it to the release branch if you're satisfied.
What is included in the Manifest
The package application is using the file devel/manifests/darkmod_maps.txt to decide whether to include or exclude stuff. In a first internal step the script will include all files in specific folders:
# Include all these files (but without parsing them like maps), each # statement will include files (from SVN) in that folder: INCLUDE def/ INCLUDE dds/ ... INCLUDE video/ INCLUDE xdata/
As visible in the above example, the sharp character # is used to denote comments. Put that at the beginning of a line to disable the statement.
As next step the algorithm will exclude certain files matching the regular expressions in EXCLUDE statements like this:
EXCLUDE dds/darkmod/test
In 95% of the cases it's enough to just specify the path of the files you want to exclude (use forward slashes), but you can do more fancy stuff like this:
EXCLUDE models/md5/chars/undead/revenant/.*.md5anim EXCLUDE ^(dds/)?models/md5/chars/undead/revenant
The first line will exclude all MD5ANIM files in the revenant folder. The second line will exclude all files in models/md5/chars/undead/revenant and the ones in dds/models/md5/chars/undead/revenant (the dds/ part is marked to be optional).
In summary, all files that are INCLUDE'd as denoted above and afterwards manage to get through the hundreds of lines of EXCLUDE filters will end up in the manifest file.
Distribute files into PK4s
Each of the roughly 15000 files in the manifest needs to be sorted into the correct PK4. This is done by defining a rules in the file devel/manifests/darkmod_pk4s.txt. Each of the lines there defines a PK4 and which files go into it:
# Miscellaneous stuff (GL Progs, Script, Language Files, Rope Arrow) tdm_base01.pk4: ^glprogs, ^script, ^strings, sound\.wav, _emptyname\.wav, ^models/md5/environments, ^dds/models/md5/environments, ...
Again, lines starting with the sharp # character denote comments.
Leftmost is the PK4 filename, followed by a colon character. To the right of the colon a list comma-separated patterns is defined, whereas each pattern is interpreted as regular expression. As with the darkmod_maps.txt you don't need to know very much about regular expressions to define those rules, it's usually enough to write the folder names and use wildcards like .*.md5anim
Build the Package
The package is built right on the TDM server - there is a full darkmod repository checked out on the server's filesystem, and it will be processed through some scripts that are listening to your commands.
Once triggered, the process goes roughly like this, I'll comment on these steps below:
- The working copy is reverted, such that it is clean.
- The working copy is switched to the release branch of the version you're about to release (it must exist at this point).
- The working copy is implicitly updated by the switch operation.
- The manifest is generated.
- The full set of PK4 files is generated (it takes a while, the server CPU is not very powerful).
- The differential package is generated.
- The files are copied to a public folder reachable through HTTP such that it can be tested by the team. The team will test it by storing a manipulated tdm_mirrors.txt file next to their tdm_update application.
Prepare the packaging process
A few steps need to be done before kicking off the process on the server.
- The release branch must be created, with a specific naming convention: https://<darkmod_server>/svn/darkmod/branches/releaseY.XX where Y is the major version and XX is the two-digit minor version, e.g. "1.08".
- The inclusion statements in the darkmod_maps.txt file need to be up to date, make sure everything is committed to the branch.
- The tdm_version.txt file should be containing the correct version number, it's located in devel/release/tdm_version.txt. Commit that change to the release branch, needless to say.
Kicking off the packaging process
There is a special admin page on the server which can be used to kick off the process. The URL has been posted on the forums before, greebo or grayman know the URL. It's password protected, so you'll be asked to enter credentials. Once there, you can enter the two version numbers, the previous one (the latest released one) and the one you're building. E.g.: 1.07 and 1.08. It's sufficient to enter the currently released one, e.g. 1.07, the website will automatically fill in the next version number - you can override it if really necessary.
Once you start the process you'll be presented a text window with some progress information, and you can watch the messages emitted by the svn client and the tdm_package application running on the server. It takes a while, about half an hour, until the package is built.
Prepare the internal package test
The team needs to have access to the package as created above for internal testing, so you'll have to upload it into a subfolder on one of our FTP servers - as Fidcal and Komag have the highest bandwidth allowance I usually chose their FTP for this internal test. Proceed like this:
- Connect to that FTP
- Change folders such that you'll find the files of the current public release - don't touch them.
- Create a new subfolder below those files, let's say it's called "pre_release_test".
- Upload the full TDM release package there:
- All the PK4 files as created in the darkmod1.03 folder by the tdm_package app.
- The crc_info.txt file.
- The tdm_version_info.txt file
- The differential update, e.g. tdm_update_1.02_to_1.03.zip.
Create the customised tdm_mirrors.txt file
Once the upload is complete you need to create a custom tdm_mirrors.txt file, otherwise the testers can't reach the package. Copy the existing tdm_mirrors.txt file (there is one in your regular TDM installation, or copy the one in SVN darkmod/devel/tdm_mirrors.txt). Open the file in a text editor and throw out all the mirrors you don't need, except the server you uploaded the test package to: adjust the subfolder in that server URL to match your test. You don't need to worry about the weighting, as there's only one server for testing. Here's an example file:
[Mirror fidcal.com] url = http://www.fidcal.com/darkuser/pre_release_test/ weight = 1
Create a test thread
Now open a new thread in the inner forums and attach that customised tdm_mirrors.txt file to it. Important: instruct the testers that they need to use the --keep-mirrors option when trying to update their installation. If the --keep-mirrors option is omitted the updater will connect to the regular TDM 1.02 update mirrors, which is not the point.
The Test & Bugfix cycle
Once the testers post their bug reports, the dev team needs to get moving to fix them. It's recommended that all fixes will be committed to the trunk (both for darkmod and darkmod_src repos), and the release manager should merge the changes into the release branch.
Merge Fixes into the Release Branch
Let's assume there is a fix that got committed to darkmod SVN in order to fix an issue discovered in the test package. Proceed like this to merge it to the release branch.
- Make sure your local working copy is switched to the release branch.
- Now right-click the darkmod folder and choose SVN > Merge
- Select Merge a range of revisions
- As URL to merge from use the address of the trunk: https://<darkmod_server>/svn/darkmod/trunk
- In the field revision range to merge you need to specify which exact change you intend to merge. It's easier if you click the "Show Log" button right next to the entry field to view the SVN Log of the trunk. You can either select a single commit, or you can select a range of commits. Perhaps double-check the changes of that checkin.
- Hit Next, then Merge.
- Important: the changes will be incorporated into your working copy. If you want these changes to actually be stored in the release branch, you need to perform the commit.
Special note for code changes: once these are committed to darkmod_src turnk, you need to merge them just like described above. Then you're going to recompile the game binaries (I recommend from scratch) and commit the tdm_game01.pk4 / tdm_game02.pk4 files to the darkmod release branch too.
Update the Test Package
Re-package the TDM package, as described above. Under the assumption that you don't want to re-upload the entire 2 GB to the FTP again, I recommend the following steps to figure out which files actually got changed since the previous test package:
- Copy a crc_info.txt file from the test directory on the FTP server (pre_release_test/crc_info.txt).
- Compare that old CRC file to the newer one you just created (I can recommend SourceGear DiffMerge to do that, but any text file comparator will do the job).
- Upload the PK4 files that got changed
- Upload the new crc_info.txt file
- Upload the new tdm_version_info.txt file
- Upload the new differential package
Test again
Inform your testers about the update and which things got changed since the last test. Instruct them to update their test installation (don't forget to mention --keep-mirrors) and enter the next round of testing.
Upload & Release
Notes for greebo:
- Create package remotely
- Copy crc_info.txt and tdm_version_info.txt to devel/release/version_info/1.0x and commit
- Create tag for darkmod and darkmod_src repositories (/tags/1.0x)
- Copy package from www/tdm_update to tdm_releases/1.0x/
- Copy /tdm_releases/1.05/index.html to /tdm_releases/1.0x
- Move all differential packages back to www/tdm_update
- Copy the one differential update package updating to the new 1.0x version back to /tdm_releases/1.0x
- Start uploading to all mirrors ./upload_to_all_mirrors.sh 1.0x
- Update tdm_mirrors.txt and tdm_version.xml on thedarkmod.com
Glossary
- Release Fileset: the PK4 files forming the actual release.
- SVN: an acronym for Subversion, a version control system
- Commit: The process of a team member uploading files to the SVN repository - a commit always creates a new SVN revision.
- Mirrors: The servers where the PK4 files are stored for download by the updater.
- updater: The TDM Updater executable, used for downloading and updating TDM.
- binary: Source code is compiled into so-called binaries. This can be an executable (.exe) file or a module (.dll/.so).
- darkmod_src: The code repository holding all the TDM source files, including the tdm_update application.
- branch: A tree in the SVN repository. Several branches can co-exist side-by-side without interfering.
- trunk: The main branch where all the ongoing development is happening.