[RSS]

Best Practices for Working with Team Repositories

What Team Repositories are For

Team repositories

  1. Protect you from obvious mistakes made by people in other teams you don't even know.
  2. Relieve you of the burden of running tons of tests locally before making any change.
  3. Reduce the chance that a daily production build fails.

How Team Repositories Work

The team has a team repository, which is a branch of main. Team members push their work in progress here.

There is also a team builder, probably a Hudson continuous build server. It is configured with the team repository for source control. The builder builds the IDE and runs various tests. A job is likely triggered by changes to the team repository, and/or on a fixed schedule.

When your team builder's job is clean (build finished, all tests pass), it fetches from and pushes to main. This propagates your team's work to the world. If the build breaks or tests are failing, the team gets mail and tries to fix the issue.

A separate trivial job is based on main-golden and just fetches from and pushes to the team repo, so the team repo picks up changes from other teams once they have gone through a successful daily build.

(Interested in the details or how to set it up? HgParallelTeamIntegration)

How to Push Your Work

For the most part, you just have a local clone of the team repo which you work in. fetch from and push to the server as usual. If problems are reported from the team builder, fix them as soon as you find out, or if you are not available other team members knowledgeable about the code may do it for you.

In case there is a build breakage in main which is your responsibility, it is helpful to keep a clone of main around so you can fix the breakage more quickly. This could happen if the test were unreliable and happened to pass once on the team builder; or if the team builder did not run that test for whatever reason. But you have to be much more careful pushing to main than to your team repo: run sanity checks locally, and stay at work until you see the trunk build pass.

Manual Synchronization

If the merge with main (in either direction) fails due to a line-level conflict, the Hudson job fails and the team gets a mail notification. Generally this is uncommon, since it is unlikely someone from another team is going to be editing the same line of text as you, but it can happen in some cases. (API changes are especially prone to merge conflicts: the spec version of the module must be incremented in manifest.mf.) If there is a conflict, resolving it is usually straightforward: someone from the team (preferably the person responsible for the team's side of the conflict) with a clone of the team repository fetches from main, resolves the conflict, and pushes normally to the team repo. Obviously that person should notify the rest of the team that they are fixing the problem, e.g. Reply All to the failure message.

While you can just use hg fetch main, if trunk happens to be broken you could propagate the breakage into your team repository. hg fetch main-golden should be safe, but you might want to resolve a conflict with a change in main that did not yet make it into main-golden. In this case, just pick a particular revision for which the deadlock trunk job passes (check the Changes page in Hudson). Example:

cd team
hg fetch
hg fetch -r a77fe9237c00 main
# resolve any conflict...
hg commit -m 'merged with main'
# optional sanity check (summarizes team's pending changes):
hg tip -p | diffstat -p1
hg push

It is also possible to manually synchronize in either direction if you have a special reason. (Mercurial knows how to keep track of which changesets are already in a repository.) For example, you might want to pull from main if there is a new API made by another team which you want to begin making use of immediately, without waiting for a production build. Just make sure main at least passes the continuous build at the revision you pull. Pushing manually to main from a team repo clone threatens the stability of main and should be discouraged unless you really know what you are doing.

Tests

Clearly the team builder should focus on tests related to that team's work, as well as running general commit validation to catch unexpected integration bugs.

Functional tests occasionally fail for no good reason, which is irritating (pushes to main are delayed) but not a huge problem in practice. If certain unit tests fail sporadically, they can be skipped by the team builder using the new @RandomlyFails annotation (on a method or a whole class).

Developers are still advised to run all tests in a module to look for regressions before committing changes. Unlike when pushing to main, you need not do a full clean build and run commit validation.

Issue Tracking

When you fix an issue in your local repository, be sure to include the issue number in the commit log message:

#123456: fixing icon size for the frobble badger.
(I may have a more detailed description of the fix on the second and subsequent lines.)

Resolve the issue as FIXED in Issuezilla. It is polite to enter the Mercurial changeset ID in the issue comment for future reference:

Fixing in frobble-main: #a77fe9237c00

Push to the team repository when you get a chance.

When your fix has been validated by the team builder, makes it into main, and is included in a daily production build, a comment from the pseudo-user qa will be added to the issue. It will again mention the Hg ID and specify which build has the fix.

Checking Status

Not sure if your repository clone contains someone else's change? Check by ID:

hg log -r a77fe9237c00

or by issue number or other identifying keyword:

hg log -k 123456

Want to know what changes are still being validated?

hg fetch
hg out -M main