Skip to content

Quickstart

kamsar edited this page Nov 20, 2012 · 6 revisions

Beaver is pretty easy to use, but it does have some conventions you should be aware of that you might want to tweak if integrating it into an existing build process.

How Beaver Deployments Run

Deployments are started (usually) by running the Build/deploy.cmd file and choosing an environment to deploy for.

The process begins by gathering properties. Properties are well-known variables that are available to all buildlets run during the deployment. As with all things in Beaver, you can define environmental properties (Build/Environments/$(EnvironmentName)/props.ps1), archetype properties (Build/Archetypes/$(ArchetypeName)/props.ps1), and global properties (Build/System/Properties/*.ps1). Environmental properties override archetypal properties, which in turn override global properties. You can define new properties at any level in the structure.

Next the pipeline cascade is executed and passed the merged set of properties. The pipeline cascade allows for pipeline extension similar to properties but in reverse. First, a global pipeline is executed - say Build/Global/0 Build.pipeline. Next any pipelines with the same name in archetypes are executed, for example Build/Archetypes/Foo/Pipelines/0 Build.pipeline. Finally any pipelines with the same name in the environment are executed, for example Build/Environments/Bar/Pipelines/0 Build.pipeline. The pipelines are executed sequentially, i.e. 70 foo.ps1 in a global pipeline will always execute before 00 bar.ps1 in an archetypal pipeline. If any pipelines are present with names that do not match global pipeline names in archetypes or environments, they will be executed after all other pipelines have completed.

Default Conventions in Beaver

Beaver has an opinion on how to run deployments by default. It is built on the idea that the output of a deployment should be:

  • Dependent only on files in source control, so that the next point is true.
  • Completely repeatable given the same SCM revision, so that if a deploy ever goes badly you can simply revert the deployment codebase to the last release, redeploy, and thus rollback the environment
  • Result in a clean, SCM-less folder that is ready to zip/robocopy/etc to the target server

Any of these conventions can be changed: they are all themselves implemented in buildlets, and you can change how those work to match your desired conventions.

The standard build is split up into four pipelines:

  • Build (0 Build.pipeline). This is responsible for compiling the project and updating the working directory where the deployment output is staged and transformed before being ready to deploy.
  • Configure (1 Configure.pipeline). This pipeline executes config transformations, adds or removes files, etc to configure the build output to match the target environment.
  • Validate (2 Validate.pipeline). Executes unit tests, code analysis, and other validation actions against the working directory's code.
  • Deploy (3 Deploy.pipeline). Executes deployment actions on the completed and validated working directory. Deploying using robocopy to 1..n servers over local or UNC paths is supported, but building fancier schemes such as Web Deploy packages, WIX installers, etc are totally possible.

Anatomy of a Pipeline

Pipelines are all over the place in Beaver. Fortunately, every pipeline works the same way, receives the same properties and supports all of the same types of buildlets.

Default Buildet Types

There is a very heavily commented pipeline with all possible options for all buildlet types here.

  • PowerShell (*.ps1). This is the native tongue of Beaver. Properties are simply variables in scope. These buildlets should be used for bulk file operations, invoking PowerShell APIs, etc.
  • XDT Transforms (*.xdt). Implements XDT (Web.config Transformations) in a generalized way. XDT buildlets use an extra XML namespace to define what file(s) in the working directory it should be applied to, if an error should occur if the target file isn't found, or a PowerShell conditional expression to determine if the transform should run at all. Properties are passed as XDT variables (e.g. <foo bar="{VariableName}" />).
  • MSBuild (*.build) execute using the MSBuild engine. The default target(s) defined in the <Project> element will be executed. Properties are passed as...properties.
  • Disabled buildlets (*.disabled) will be ignored. This allows you to turn off specific buildlets, if you want to keep them around for future use or debug the build process.
  • Subpipelines (directories that end in *.pipeline) will execute their child files (or subpipelines) as any other pipeline. These can be used to organize and group tasks that require multiple buildlets to accomplish (for example a PowerShell buildlet and an XDT buildlet).

Setting up a Beaver Deploy

  1. Clone the repository
  2. Place your solution file in / (it can have any name .sln)
  3. Place your source project(s) in /Source and fix any links to the .sln (it should build in VS)
  4. Your main web project should end in ".Web", e.g. "Foo.Web"
  5. Run Build/deploy.cmd and select an environment.
  6. Assuming the deploy completes successfully, its resulting working directory will be present at /Deploy/$(environmentName). Note that the actual web site files are placed in the Website sub-directory of the working directory. This allows you to add out-of-webroot items such as lucene indexes to the deployment easily.

Once the deploy is working, you can go about configuring environments, archetypes, and specific buildlets for your environment.

Running Beaver using a Continuous Integration server

That's easy. In any CI server that can execute PowerShell scripts, simply have it execute Build/System/deploy.ps1 and pass the environment name to build as the first argument.