[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

Re: Suggestions and pitfalls for a development/deployment setup.

From: Ryan Schmidt <subversion-2006c_at_ryandesign.com>
Date: 2006-09-10 15:14:13 CEST

On Sep 8, 2006, at 23:49, Walter Hop wrote:

> I am currently designing a SVN setup to use for our website and
> backend.
> This is the first time I am going to use SVN for a serious project, so
> I'd like to get it right the first time! I hope somebody with
> experience
> can give me some comments on the viability and possible pitfalls of a
> setup like this. I'll try to be as brief as possible!

> - Are there any pitfalls in doing this kind of setup, or is there an
> easier way to go abou this than the scenario?

Hi Walter. I'll give you some answers based on what we did in the web
development shop where I worked. I can't say whether it's the best
strategy, but it's at least not completely horrible.

> My goals:
> - Develop on a test server, and do controlled deployments to the
> production server.
> - Do periodic releases where all changes from the test server are
> merged
> into a production release.
> - Support for doing "hotfixes" on the production server and
> backporting
> them to the development machine; this should be as easy and
> painless as
> possible.
>
> I was thinking of the following:
> - Set up a SVN repository with a trunk and a release branch.
> - Check out a local copy of the trunk on the test server.
> - Check out a local copy of the release branch on the production
> server.

You can point your web server directly at a working copy, yes, but be
aware that "svn up" is neither instant nor atomic. This means that if
you update the working copy, between the time the update starts and
the time it finishes, your web site is in an inconsistent state, and
may blow up, depending on your programming. And if there is a network
problem such that the update does not complete, then your working
copy may be half updated and half not. To avoid these problems, we
used a lengthier process which is described here:

http://svn.haxx.se/users/archive-2005-05/1117.shtml

In most of our projects we did indeed have a trunk and a release
branch (say "1.0"). Smaller changes that should go into 1.0 right
away could be made in either the trunk or the branch and then merged
to the other place. Bigger changes that would wait for version 1.1
would happen only in trunk. When the team mutually agrees that 1.1 is
ready, trunk is copied to a new branch "1.1", it is pushed to the
production server, and the 1.0 branch is moved to an "old_branches"
directory so everyone knows not to use it anymore [1].

But the reality of doing customer-driven projects, which is what we
did, is that most changes the customer asks for are "really
important" changes that must go online immediately, so the vast
majority of changes ended up having to be done in both places (trunk
and branch) and a release cut immediately. The merging got tedious.
I'm now of the opinion that one should only have a trunk, and cut
releases directly from that. This eliminates the need to merge in the
vast majority of cases (of our cases anyway). In the rare
circumstance that a larger feature is being developed that will take
some time and can't go online right away (perhaps because the
customer hasn't paid for it yet), you can either then mutually agree
with the team to cut a release branch before the development of this
new feature starts on trunk, or else you can develop it in a feature
branch and then merge it back to trunk when it's ready to go online.

To be honest, the frequency of our releases also made our release
deployment process tedious. (Create a new tag of the release branch.
ssh to the development server. cd to the project directory. Run the
upgrade script. Remove the old symlink and add the new one.) Had I
stayed at the company I likely would have investigated ways of
automating this. Maybe do just have a single release branch like you
propose. Or even define that the trunk is the release branch. Make it
clear to developers that anything committed to this sacred release
branch will appear on the production site immediately. Write a post-
commit hook script which makes this possible (which ssh's to the
production server and updates the production working copy, or else
does the export and symlink switcheroo). The only problem with this
idea is database updates, which we never attempted to automate. If
there were database updates that needed to happen for a particular
feature, we either did this on the live server immediately, if they
posed no danger to the rest of the system (for example, adding a new
table, or adding a new column or index in an existing table), or we
wrote down the necessary SQL statements in our ticket system and ran
these at the time that we deployed a new version of the site. You'd
need to think about how you want to handle this situation.

> - Development use cases:
> 1. the developer works on local copy on the test server, and commits
> this to the trunk.
> 2. when an urgent bug is noticed that cannot wait for a release,
> work
> on local copy on the production server, and commit this (changes go
> into the release branch), then merge these changes back into the
> trunk.

The developers should not work in the central working copies on the
test server or the production server. They should each work in their
own working copies in their home directories. Your web site should be
programmed so that it works regardless of where it is located on
disk. To avoid having to configure a web server and database server
on each developer's machine, we stored all our working copies in the
home directories on the central development server and accessed the
files via Samba. This put a bit of strain on the development server,
but if your working copies are small or you have few developers or
your server has a lot of RAM then it should be ok. Some things were
still shared between developers: the MySQL database, for example, and
the directories where photos and things were uploaded. The photo
directory was located in a central place on the server, and its
location defined in the web site code as an absolute path in a
constant so that it could be found regardless of where the working
copy is.

The point is that during development you break stuff, often
deliberately. If Bob is fixing problems in the sitewide config file
and to do this he needs to break it for about an hour, you do not
want this breakage to occur in the central working copy on the
development server because nobody else could work on the project
during that time. You want this to occur in a private environment set
up just for Bob; that would be Bob's own working copy. When Bob is
done fixing whatever problem it was and has repaired the intermediate
breakage, then he can commit his changes, which can trigger a post-
commit script which updates the central development working copy.

If every developer has their own working copy, you don't even
particularly need a central development working copy, because nobody
will be developing there, and anybody who wants to see what the
system looks like can just look in their own working copy after
updating it. The reason we still kept a central development working
copy was for the nontechnical people who wanted to look at the
current development state of the site -- the managers. Managers (at
least ours) don't want to learn about "svn checkout" and "svn update"
and they certainly don't want to wait seconds or minutes for those
commands to complete. They want a simple well-defined URL where they
can go to always see the current state of the project, so that's what
we gave them.

> - Release use case: merge all changes from trunk into the release
> branch, then do an 'svn update' on the production server.

You can do this if you want to always only have a single release
branch, or you can do as we did and make a new release branch each
time a major release is cut. This also helps if you say things like
"feature foo is introduced in version 1.1" and you later want to see
what the system looked like without feature foo. It's easy -- just
look at the 1.0 branch. (Not that we wanted to do this often, but if
we did, it would be easier to look in the 1.0 directory than to look
through the log of trunk to try to figure out when that feature was
created -- particularly with some of the nonspectacular commit
messages some of our developers have written. :))

> Possible problems:
>
> - The various scripts and libraries under version control live in
> various locations on the production/test server. For instance, some
> files live in /usr/local/, some go into /www, some in /home et cetera.
> It seems I should make subdirectories in the repository, checkout the
> relevant parts of the repository at all the root points, and make a
> script to walk through all these directories on the production/test
> server and do a 'svn update' there. But can I also do the same for a
> commit, keeping all the created changes in one singular commit
> (instead
> of executing a 'svn ci' for every dir, creating several commits)?

If you create separate working copies for the separate parts of this
system, then you will need to commit changes to them separately as
separate revisions. This doesn't sound optimal.

You should design your system so that it can be checked out as a
single cohesive working copy in a single location. If for some reason
you absolutely cannot change the fact that different parts of it must
appear in different places, then perhaps you can at least still check
out everything in one location, and then install symlinks at the
various necessary paths that point to where the working copy really is.

> - I would like to have developers use their own login/password when
> committing. But at the same time, they may be working from the
> test/production servers which always have an existing local copy (not
> checked out by the developer account itself). Someone gave me the
> suggestion to have the test/production servers checked out
> anonymously,
> so users would then be asked for their login while committing. Will
> this
> work? Is it also possible with a non-anonymously created local copy
> (for
> instance with a 'testserver' account)?

If each developer has their own working copy as they should, then
each working copy will be owned by the respective developer. The
developer will either ssh to the development server with their own
login or access the files via Samba from their own desktop, and in
the Subversion directory in their home directory, their username will
be cached so that when they commit changes, their username will be used.

> - Merging changes to a different branch (releasing or backporting a
> hotfix) seems to require knowing the revision number of the first
> change
> after the previous merge. I think it's probably easiest to create a
> merge-script which merges in the specified direction and then
> stores the
> resulting revision number in a text file, so that the next merge in
> this
> direction will be from this point. So I'd have to keep track of two
> revision numbers for the latest trunk->release merge and the latest
> release->trunk merge. Is my thinking on this correct?

The script is called svnmerge.py; you can Google for that to learn more.

[1] We could also "svn rm" the 1.0 branch but then it's more
difficult to find it in the repository later should we need to do
that. Since "svn rm" doesn't reclaim any disk space its only purpose
would be to make the directory listing of the branches directory more
manageable, so moving it to an old_branches directory solves this
problem just as well and still lets us find it easily later.

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@subversion.tigris.org
For additional commands, e-mail: users-help@subversion.tigris.org
Received on Sun Sep 10 15:15:49 2006

This is an archived mail posted to the Subversion Users mailing list.