Showing posts with label Continuous Integration / Build. Show all posts
Showing posts with label Continuous Integration / Build. Show all posts

Friday, November 19, 2010

PowerShell script to get a list of all assemblies required by a .NET executable

param ([string][parameter(mandatory=$true)]$path)

function GetReferencedAssemblies([reflection.assembly][parameter(mandatory=$true)]$top)
{
    $script:found += $top.Location

    $ref = $top.getreferencedassemblies() 
    $ref | % {
        $name = $_.name
        $loaded = $null
        try
        {
            $loaded = [reflection.assembly]::load($_) 
        }
        catch
        {
            $loaded = [reflection.assembly]::loadfrom((resolve-path ($name + '.dll')))
        }

        if($script:found -notcontains $loaded.Location -and -not $loaded.GlobalAssemblyCache)
        {
            GetReferencedAssemblies $loaded
        }
    }
}

$path = resolve-path $path -ErrorAction stop
pushd (split-path $path)
try
{
    $found = @()
    $top = [reflection.assembly]::loadfrom($path)
    GetReferencedAssemblies $top
    $found
}
finally
{
    popd
}

Generate DB script using PowerShell

This is an example script that can be used to dump a SQL Server database schema into a creation script. The advantages of this method over using SQL Server Management Studio include:
  • Scriptable. Can be included in a build or commit script.
  • Repeatable. SQL Server Management Studio generated scripts vary from run to run, so it can be difficult to make comparisons with previous versions of the schema in source control.
  • Repeatable. Using the SQL Server Management Studio GUI to create scripts relies on everyone ticking the same boxes to generate consistent and correct DB scripts.
  • Configurable. This script ignores objects (e.g. tables and triggers) with names starting with 'test'.
<#
.SYNOPSIS
.NOTES
Author: 
#>

$root = resolve-path ((split-path -path $MyInvocation.MyCommand.Definition -Parent) + '\..\..');
$serverURL = 'SQL2005'
$databaseName = "DBToDump";
$scriptFile = "$root\Scripts\Create.sql"

#================== GetObjectsFromDB ===================
function GetObjectsFromDB(
[parameter(mandatory=$true)]$Database, 
[parameter(mandatory=$true)][string]$ObjectType)
{
    $objects = [Microsoft.SqlServer.Management.Smo.SqlSmoObject[]]($database.$ObjectType | Where-object {$_.IsSystemObject -ne $true -and $_.IsFixedRole -ne $true -and $_.Name -notmatch '^test' } );
    if($objects)
    {
        ,$objects
    }
    else
    {
        ,@()
    }
}
#=======================================================

[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SMO") | out-null
$server = new-object Microsoft.SqlServer.Management.Smo.Server ($serverURL);
$server.SetDefaultInitFields([Microsoft.SqlServer.Management.SMO.StoredProcedure], "IsSystemObject")
$db = $server.Databases[$databaseName];

if(Test-Path $scriptFile)
{
    del $scriptFile
}

$scripter = new-object Microsoft.SqlServer.Management.Smo.Scripter ($server);
$options = $scripter.Options
$options.ScriptDrops = $false
$options.IncludeIfNotExists = $false
$options.ScriptData = $false
$options.NoCommandTerminator = $false
$options.FileName = $scriptFile
$options.SchemaQualify = $true
$options.ToFileOnly = $true
$options.AppendToFile = $true
$options.DriAllConstraints = $true
$options.Indexes = $true
$options.ClusteredIndexes = $true
$options.Statistics = $true
$options.IncludeDatabaseRoleMemberships = $true
$options.TargetServerVersion = [Microsoft.SqlServer.Management.Smo.SqlServerVersion]::Version90
$options.NoFileGroup = $true
$options.DriAll = $true

echo "Scripting database..."
$scripter.EnumScript($db)

#don't script collation for DB objects since it has been done for the database as a whole
$options.NoCollation = $true

#switch to newly created DB
"
USE [$databaseName]
GO
" | out-file -append $scriptFile -ErrorAction stop

$objects = GetObjectsFromDB $db "Schemas"
$objects += GetObjectsFromDB $db "Roles"
$objects += GetObjectsFromDB $db "Tables"
$objects += GetObjectsFromDB $db "UserDefinedFunctions"
$objects += GetObjectsFromDB $db "StoredProcedures"
$objects += GetObjectsFromDB $db "Views"

$scripter.EnumScript($objects)

echo "Done."

#set permissions (not sure how to script the ones I want without including test permissions)
"
GRANT EXECUTE ON SCHEMA::[app] TO [application] AS [dbo]
GO
GRANT SELECT ON SCHEMA::[cfg] TO [application] AS [dbo]
GO
GRANT SELECT ON SCHEMA::[cfg] TO [support] AS [dbo]
GO
GRANT SELECT ON SCHEMA::[dbo] TO [support] AS [dbo]
GO
GRANT UPDATE ON SCHEMA::[cfg] TO [support] AS [dbo]
GO
GRANT SELECT ON SCHEMA::[sup] TO [support] AS [dbo]
GO
GRANT VIEW DEFINITION ON SCHEMA::[sup] TO [support] AS [dbo]
GO
GRANT VIEW DEFINITION ON SCHEMA::[cfg] TO [support] AS [dbo]
GO
GRANT VIEW DEFINITION ON SCHEMA::[dbo] TO [support] AS [dbo]
GO
GRANT EXECUTE ON SCHEMA::[sup] TO [support] AS [dbo]
GO" | out-file -append $scriptFile -ErrorAction stop

Tuesday, October 19, 2010

Continuous integration

This is what I like to run for continuous integration builds:
  1. Set version numbers in all assemblies.
  2. The release build.
  3. Code analysis (build breaker).
  4. Unit tests (build breaker).
  5. Integration tests (build stability).
  6. FitNesse tests (build stability).

Outputs I like to collect are:
  • Build outputs, including PDBs, ideally in a symbol server.
  • Code coverage percentage and details.
  • Test results.