Showing posts with label SourceSafe. Show all posts
Showing posts with label SourceSafe. Show all posts

Monday, June 4, 2007

Pseudo-changesets In SourceSafe

Let's say you make a code change that spans multiple files across several projects. When the change is complete, you need to check in all of the files at the same time. Otherwise, you end up with a broken build. Most source-control systems include the concept of a changeset. As you check out files, they are grouped in a specified set. After the modifications have been made and tested, you check in the changeset as opposed to the individual files. The bad news: SourceSafe doesn't include changesets. The good news: you can work around the limitation.

I previously added the MSBuild.Community.Tasks code to SourceSafe. Let's say I modified code within the XmlQuery task. This also required changing the unit tests. To see all of the relevant checkouts, select the folder common to both projects ('Source' in this case.)


From the menu, choose View > Search > Status Search. In the "Search for Status" dialog, select the options to display files checked out to you, in current project and all subprojects. Click OK.


The search results will look similar to this


Select the necessary files, right-click and choose Check In from the menu. Assuming you selected the correct files, the code should be updated without breaking the build.

Thursday, May 3, 2007

Source Code Control 101

At work, we're moving toward a more standardized development process. Part of that standardization is on the usage of SourceSafe for source code control, and CruiseControl.Net for continuous integration (CI.) The developers on the team come from a variety of backgrounds, and have different levels of experience with CI. As the resident Build Guy, I've spent the most time with the tools and decided to lay out my thoughts on the process.

*Note that these are not the only tools available, and with SourceSafe in particular there are certainly better options. These are simply the tools we are working with.

*Note also that I intended to cover both SS and CC.Net in a single post. It ended up a bit longer than expected, so I'm splitting it into two entries. This post is limited to source code control. The next will dig into continuous integration.

SourceSafe as version control

SourceSafe is not merely a way to back up code in case of hard drive failure. It is a way to revision your code. It allows you to define checkpoints in completed work. It provides an easy way to compare changes and roll back work if you find yourself going down the wrong path.

For example, let's say you're updating a desktop application. The current app generates a text file as output. The goals for the next release are to enhance the logging and to generate xml instead of plain text. To start, you decide to replace the existing log with xml. Looking at the code, you realize the log messages are scattered throughout the entire app. Unless each message is to be a self-contained element, this makes it difficult to generate well-formed xml.

So you begin by creating a custom logger class. This lets you track where in the xml tree you are, and ensures the output is well-formed. After you've finished testing the logger, it's time to replace all of the old logging code with calls to the new class. Right?

Not just yet. Now that you have working code it needs to be checked into SourceSafe. "It doesn't do anything yet," you say? True. However, even though the class isn't used, it's still a functioning piece of code. If you have to switch projects now, you know you can come back later and pick up with a working app.

"What if you need to make a bug fix and release to production?" The code isn't being used, remember? So there shouldn't be an issue.

With the logger checked into SourceSafe, it's time to replace the existing logging code. At the start, everything seems fine. But several hours into the process, you realize something. It appears there's a bit of rarely-used code that logs info in a non-trivial, non-standard way. No problem - you can update the xml logger to deal with the new info. A few changes, which you of course check into SS, and you're back to replacing code. But shortly thereafter, for whatever reason, you realize the logger changes shouldn't have been made. Now what?

Fortunately, the previous revision exists in SourceSafe. It's easy to roll back the code and continue with your work. But say you hadn't checked in the changes? Instead, you would have had to manually modify the code until you were back to the point you were before. If you've ever tried this, you know it's not often a trivial matter. It certainly takes longer than the minute or two required for a SourceSafe rollback.

SourceSafe allows collaboration

Most software projects involve several team members contributing code. This requires some means of getting updated code to the other developers. It may also require a new developer to come in and pick up where another left off.

Going back to the xml logger, say you have the logger code checked in and are pulled off to work on another project. A new developer comes in and is tasked with replacing the old log code. All the new guy has to do is get latest from SS and he can continue right where you left off. Or maybe he comes in at the point where you've added to the logger (just before you realized those changes weren't necessary.) Once the new guy figures out what's going on, it's as easy for him to roll back the code as it would have been for you. There's a clear snapshot of where the code was before the change.

Checkin frequency

So you now see a few benefits of source code control. The next question you may have is "How often do I check in my code?" It depends on what you are doing, but the general answer is "Often." A few times a week is typical, and multiple times a day is entirely possible. The key is to find stopping points throughout the project.

Say you start coding a new multi-tiered application. You begin by writing a few classes in the data layer, making sure you can connect to the database. As soon as you have these compiling and running correctly, check the code in. As you add new classes, check them in. There's no reason to wait until the entire layer is code complete.

Say instead you are working on a desktop application. You begin by placing a few controls on a blank form. Maybe you hook those controls to business logic. Or maybe you prefer to setup the layout before making the code do anything useful. Either way, each piece of logic and each set of controls define a discrete unit of work. Hook up a couple buttons and check the code in. Add logic to traverse the local hard drive, then check the code in. With a bit of practice, you should recognize several good checkin opportunities on any given day. That's not to say you need to check code in this often, but once a day is certainly possible.

One final thought - before checking in the code, make sure it compiles and runs on your box. Checking in code that doesn't compile only hinders development. I'll cover this next time when I introduce continuous integration using CruiseControl.Net.

Wednesday, April 25, 2007

CruiseControl.Net 101 - Projects

Last time, we installed CC.Net and created a blank project. This time, we'll have that project actually *do* something.

The first thing we need is something in source control to point to. I happen to have a SourceSafe database at c:\vss, so I'll use that. In SourceSafe (SS), I've created a new project, MSBuild.Chainsaw.Tasks. There aren't any files in there currently, but we'll get to that shortly. For now, let's add the following to ccnet.config, between the <project></project> tags:


<sourcecontrol type="vss" autoGetSource="true">
<ssdir>c:\vss</ssdir>
<executable>C:\Program Files\Microsoft Visual SourceSafe\ss.exe</executable>
<project>$/MSBuild.Chainsaw.Tasks</project>
<workingDirectory>MSBuild.Chainsaw.Tasks</workingDirectory>
</sourcecontrol>

This tells CC.Net to monitor the project $/MSBuild.Chainsaw.Tasks and any sub-projects. If files are added or checked into the project, CC.Net will kick off a build. At this point, we should test the updated project.

Start Visual Studio 2005 (VS2005) and create a new C# Windows Class Library. Give it a name of MSBuild.Chainsaw.Tasks. Do not check the boxes to "Create directory for solution" or "Add to Source Control." The former is unnecessary, the later would ruin my cleverly devised plan. Once the project is generated, save the files and close VS2005. Nope, we're not actually writing code. We'll have to save that for another time.

Back in SS, drag the solution file into $/MSBuild.Chainsaw.Tasks. Open the CCTray app. You should see the Last Build Label increment (CC.Net looks for changes once a minute, so you might have to wait a few seconds.) The build still shows green - we haven't specified any tasks to perform. Open Windows Explorer and browse to your CC.Net install folder. Expand \server\Project 1\WorkingDirectory\MSBuild.Chainsaw.Tasks. You should see the .sln file, meaning it's at least pulling the source correctly.

To compile with MSBuild, there is one more piece we need. By default, msbuild sends text output to the console. CC.Net requires XML output from all of the build tasks. You'll need to download ThoughtWorks.CruiseControl.MSBuild.dll. Out of shear laziness, I place this file in the root of the c: drive.

With that out of the way, let's go back to ccnet.config. Add the following to the file:


<tasks>
<msbuild>
<executable>c:\winnt\Microsoft.Net\Framework\v2.0.50727\msbuild.exe</executable>
<projectFile>MSBuild.Chainsaw.Tasks\MSBuild.Chainsaw.Tasks.sln</projectFile>
<buildArgs>/noconsolelogger </buildArgs>
<logger>c:\ThoughtWorks.CruiseControl.MsBuild.dll</logger>
</msbuild>
</tasks>

Note: The <executable> tag is necessary if you're running on Windows2000. If you're on WinXP, it isn't required.

Save the config and go back to CCTray. Hmm... Nothing happened. That's of course by design - nothing's changed in SS. To test the config change we need to force a build. This can be done with the Force button in the Dashboard, or by right-clicking the project in CCTray and choosing Force Build.

After the build runs, the CCTray icon will be red. In the Dashboard, the Last Build Status shows "Failure." To look at the details, open Project 1 in the Dashboard. Select the most recent build. The Build Report for this build doesn't tell us much (we'll fix this shortly.) Click "View Build Log" from the menu on the left. This is the raw XML output from the build. If you look in the <msbuild> section, you should see a line that includes 'The project file "MSBuild.Chainsaw.Tasks.csproj" was not found.' Not surprising since we didn't add it to SS yet.

Before we fix this error, let's modify the report to show MSBuild output. In Windows Explorer, browse to \webdashboard in the install folder. Open dashboard.config. Locate the following:


<buildPlugins>
<buildReportBuildPlugin>
<xslFileNames>
<xslFile>xsl\header.xsl</xslFile>
<xslFile>xsl\modifications.xsl</xslFile>
<xslFile>xsl\compile.xsl</xslFile>

Beneath this, add the line:


<xslFile>xsl\compile-msbuild.xsl</xslFile>

This will format msbuild output within the build report. Note that the ordering of the .xsl files determines the ordering in the report. Also, if there are items you aren't interested in, those lines can be removed from the config.

After you save the config, force another build and verify that you now have two additional sections in the Build Report - Errors and Warnings.

Now to fix the build error. Add the remaining files from the MSBuild.Chainsaw.Tasks project to SS. Having done that, we wait patiently while CC.Net kicks off another build. Assuming all the files were added, the build should complete successfully.

Sorry for the lengthy post. I could have stopped somewhere in the middle, but the one thing I can't stand is a broken build. My co-workers can attest to this.