The first step for our sample is create a blank solution. In VS2015 terminology, a solution is a collection of projects, whereas projects may be web applications, class libraries, or a variety of other things. Start VS2015 and choose "File > New Project…" (Ctrl + Shift + N). In the New Project dialog, on the left, find the "Visual Studio Solutions" node under "Other Project Types", and choose the (only) option to create a "Blank Solution", as shown below.
Supply both a name for our solution, "DevOpsSample", and a location to create it, "C:\Src". However, this is not where we want the solution file to live. VS2015 insists on creating a directory for a solution file, as the grayed-out checkbox to the right suggests. We're going to fix this for reasons that will shortly be made clear. Click the "OK" button.
VS2015 creates the solution file in a new folder with the same name as the solution file under the folder we specified. In other words, the full name of the solution file it actually creates is "C:\Src\DevOpsSample\DevOpsSample.sln". This is fine, except for the fact that developers often need multiple solutions to create/support a given product. Keeping the root of the overall product folder clean can be quite helpful.
Let's move that new solution file to a folder named "Solutions". We can do this right from within VS2015. Select the newly created solution in the "Solution Explorer" pane on the right, then choose "File > Save DevOpsSample.sln As…". We can create a new "Solutions" folder from within the save dialog, and VS2015 will subsequently save our new solution file to the new, desired location. You'll be thankful later when your product has branched out to include dozens of different solution files for various purposes.
With our solution file in our preferred location, it's time to create an actual sample project. Invoke the New Project dialog again, either by using the menu, keyboard shortcuts, or right clicking the solution file and choosing "Add > New Project…" from the context menu. This time choose an "ASP.NET Web Application" from the list of projects. Give it the name "DevOpsWeb" and note that we've specified an "Applications" sub-folder (that doesn't yet exist) in the location field as seen below:
Again, this additional organization isn't required, but it helps keep all our new web application separate from our solution. And these different conceptual entities will subsequently be kept apart from other important things like libraries, test suites, etc. Good product folder organization can pay significant dividends later, which is why we're sharing the scheme most helpful when working with .NET applications.
After clicking the "OK" button, another dialog window opens with a variety of options for an ASP.NET Web Application. For our purposes choose the "MVC" template, check the box for "Web API" support—this will be helpful when we later develop RESTful endpoints—and on the right, un-check the "Host it in the cloud" box.
Clicking the "OK" button generates the project. The process takes a short while; then the following screen appears:
It gives information about what you've just created. Browse through the content created in the Solution explorer on the right. Be advised not to build the application just yet. Building the application right now brings some unwelcome content that we don't want to store in our version control system (VCS). The lack of that content will also highlight a common problem later. So let's wait on building until after we've committed our work to Helix.
Before we make our first commit to Helix, there's one more file to add: an ignore file. For those unfamiliar with this concept, the short version of the story is that an ignore file simplifies interactions with your VCS by preventing you from accidentally versioning things that shouldn't be versioned. Compilers and other tools are notorious for creating all sorts of files during their processing, many of which we don't want to version. Or at least not yet, though later articles in our series will discuss the value of storing certain build artifacts in our VCS.
Those already fluent with the Helix ignore syntax will understand the following screen shot. The file we create will ignore a variety of common Microsoft build artifacts, log files, and other stuff we don't want to version.
Save this file in the root of our product tree (C:\Src\DevOpsSample) so that Helix and all its tools will use it when working under this folder. The Helix ignore handling is flexible enough to work with different specifications in a variety of ways, but this should suffice for our sample [For more information see the blog article entitled P4IGNORE: Ignorance is Bliss]. This should leave the root of our product tree quite clean, as seen in the following screen screenshot:
Next, we want to store and version our sample project in Helix; the first step is to create a new depot. Again, this is not a required step; Helix is the one system that can keep all your content in a single depot if you like. But to illustrate how to create new depots, and particularly how to use the powerful streams features in Helix down the road, let's walk through the process. Start the Helix Administration Utility (P4Admin), which was installed with the Helix Visual Client [directions in this article: DevOps Digest 202: Setting up for Success]. You'll see something like the following screenshot after you navigate to the "Depots" tab.
Helix offers a default depot named "depot". You may create any number of depots with varying settings to accomplish different tasks. Let's create a streams depot named "DevOps". To do this, choose "File > New… > Depot" from the menu and supply a name in the popup.
After clicking the "OK" button, another dialog appears for you to choose the type of depot you wish to create. Select the "stream" option as this will be important later. Clicking the "OK" button creates the new depot and takes you back to the main screen. The new depot appears in the "Depots" tab along with the default "depot".
Now that we have a streams depot, let's create a mainline stream for our project. Streams are a helpful tool for mainline or trunk-based development, which we'll demonstrate later. For now, we need a stream where we can store our sample application. With Helix Visual Client (P4V) launced, choose the "View > Streams" menu option (Ctrl + 7). This opens a new tab on the right titled "Streams", which will show you that there are no streams available because we don't yet have any.
Right-click in the pane that says "No streams selected" and choose the "New Stream…" option from the context menu (Ctrl + N). As you can see in the screenshot below, we've named it "Main" and kept it in our newly-created "DevOps" streams depot. Be sure that the stream type is set to "mainline" (which it will be by default) and uncheck the options to create a workspace or populate the mainline immediately. These options can be convenient, but we'll introduce you to some other key concepts.
Notice how after clicking the "OK" button, the Streams tab updates as seen below. The newly created "Main" stream appears. It is part of a diagram that becomes more populated as we create additional streams.
The "Main" stream is empty, so the next thing we need to do is create a workspace to submit our first batch of content. Again, this isn't strictly necessary as we could use DVCS features to commit and push our content right from the existing folder structure, but a Helix workspace can be a powerful ally. It's worth learning a bit about them and how to create one.
Choose "View > Workspaces" from the menu (Ctrl + 5) and a new "Workspaces" tab appears on the right. To create a new workspace, right-click in the empty pane and choose the "New Workspace…" from the context menu (Ctrl + N). A dialog like the one seen below (in which we've already entered details) appears.
We're using the name of our workspace to indicate both the project in question (our DevOpsSample) and the stream in which we're working (Main). This is not a good convention for everyone, as Helix makes it possible to switch streams back and forth within a single workspace as needed. For the purposes of a build server, however, it's often a good idea simply to enforce a one-workspace-one-build-stream sort of mapping. Whatever convention you prefer, we'll use this new workspace to add our existing files easily. Do not click the "OK" button just yet, click the "Advanced" tab instead, as there is at least one more option worth setting.
As you can see in the screenshot below, there are several advanced options available. For our purposes, it's enough to check the "Allwrite" box. This does not force files to be read-only until checked out for editing. This option can also be crucial when doing component-based development with Microsoft tools for reasons we'll get into later. So be sure to check that option before clicking the "OK" button.
Don't worry if you do not understand all the options just yet, as you can always go back and edit the workspace specification again. That's a key feature about Helix workspaces: you can change the options, re-sync your workspace, and it will update your local content to reflect the new workspace configuration. To edit a workspace, select it in the Workspaces tab, right-click and choose "Edit Workspace…" from the context menu.
After you click the "OK" button, the following prompt below appears. This is because the location specified already has files in it. We're doing this on purpose, so feel free to click the "No" button to continue.
One last popup appears as seen below. This is a notification that our "Main" stream is empty, but we're about to fix that. Hit the "Cancel" button to continue. It's worth skipping the automated steps to illustrate other features.
After clicking the "Cancel" button, you have a new workspace to which the Helix Visual Client will switch immediately (option checked by default). If you un-checked the box to "Switch to the new workspace immediately", expand the workspace-selector dropdown on the left and select the new workspace manually. Be sure that the "Workspace" tab on the left is active and looks like the following:
This shows the current folder we're viewing and that we're looking at the current contents of the workspace named "DevOpsSample-Main" in the file system. None of that content is actually stored in Helix yet.
We chose this particular path to our first submit because we wanted to highlight a really useful feature of Helix: reconciling offline work. The notion of a workspace is likely to be rather foreign to developers experienced only with Subversion, Git, Mercurial (Hg), or other such lightweight VCS—DVCS in the case of Git/Hg. Briefly explained, a workspace is a crucial conceptual component when you're managing millions of files, need to remap content, synchronize as fast as possible, etc.
Workspaces give users a choice of workflow. Those who prefer more "traditional", centralized operation can leave the aforementioned "Allwrite" option unchecked to keep their files marked as read-only until checked out for edit. Regardless of the "Allwrite" setting, files in a workspace may be checked out and locked exclusively as well, so others cannot submit any changes until the lock is released. This can be incredibly useful for artists and other contributors working on content that cannot easily be merged (e.g., animation inverse kinematics, audio, video, etc.).
But what if you prefer the "Allwrite" option, letting the VCS track what has changed? That's where the feature to reconcile offline work shines. To use it, right click the root folder in your workspace and choose the "Reconcile Offline Work…" option from the context menu. This provides the following dialog:
Users of Git and Hg are accustomed to the necessity of "staging" work in progress via the Git/Hg "add" commands. Subversion users do the same thing in a slightly different way. The reconcile-offline-work dialog in the Helix Visual Client offers the same thing only in a unified visual interface. The three panes show modified files, added files, and deleted files from top to bottom respectively. And as you can see, all the content we created previously for our sample application shows up in the middle pane as files to be added.
The ignore file created earlier affects what appears in this dialog, which can greatly improve the "signal to noise ratio" for this (and other similar) operations. If you prefer to work with the command line, there is a "reconcile" command that offers similar functionality to this dialog.
It also bears mention that clicking the "Advanced Reconcile…" button at the bottom opens a very useful differencing tool we'll look at later, which makes it easy to see visually precisely what has changed. From there you can perform operations to help you determine exactly which files you want to include in the reconciliation.
For our purposes, we want to pick up all our new work, however, so simply click the "Reconcile" button down at the bottom. This will take a moment because it's recording all of those file operations to the default changelist. A changelist is another powerful Helix feature that we're not going to explain deeply right now.
You can have multiple changelists within a single workspace and use them to organize changes to different sets of files. You can also shelve those changelists, storing their content on the central server to avoid the possible loss of work in case of a local hard drive crash. We could have specified a non-default changelist in the reconcile process, by using the dropdown at the bottom of the dialog, but the default serves our purposes fine.
Once the reconcile operation completes, you find yourself back at the main screen. Open the pending changelists tab by choosing "View > Pending Changelists" (Ctrl + 1). That tab shows the default changelist with all those file operations we just reconciled.
All that remains is to submit our default changelist to the Helix server, so our work is safely stored and versioned. Select the default changelist and then right-click and choose "Submit…" from the context menu (Ctrl + S). This brings up the "Submit Changelist" dialog, in which to provide a suitable description, as seen below:
Clicking the "Submit" button at the bottom completes the operation. The Helix Visual Client sends our work to the server and clears the default changelist for further use. To confirm that the files were submitted successfully, choose the "View > Submitted Changelists" option from the menu (Ctrl + 2) to bring up the "Submitted" tab on the right. You'll see something like the following:
The "Submitted" tab provides a way to browse the history of submitted changelists. The list displayed may be filtered by various criteria, sorted by the different columns, and so forth. In our case, we can see that our first changelist was submitted at a particular time and date by the Perforce user with the description provided earlier.