Posts

SVN log parsing using PowerShell

This script can be useful when gathering SVN release changes that occurred since the last release. It connects to SVN server, gets logs from within date range (last build and date now). Logs are then filtered, cleaned (removed if no comments were added). Next, email message is sent based on the retrieved data. To be able to run the script, you need to configure it by setting-up your own svn server url, credentials, also please make sure you have enabled running ps scripts on your server.

Enjoy!

svn_log_parser

 param (
[string]$Version = "2.12.0.2",
[string]$SendEmailsTo = "test@test.com",
[string]$SVNUser = "user",
[string]$SVNPass = "pass",
[string]$SVNbranchRoot = "https://svn.test.com/www/Branches/MyApp/2.12.0"
)

#get svn logs for the current release
 Function GetSVNLogs($lastBuildDate_)
 {
    [string]$fromDate = $lastBuildDate_.ToString("yyyy-MM-dd");
    [string]$toDate = (get-date).ToString("yyyy-MM-dd");
    [string]$RevisionDates = "{$fromDate}:{$toDate}"; 

    #add -v param for verbose
    1$log = 1(&$svn log $SVNbranchRoot -r $RevisionDates --limit 500 --xml --username $SVNUser --password $SVNPass);

    $logObjects = $log.log.logentry | Foreach-Object {
            $logEntry = $_

            $logEntry | Select-Object `
                @{ Name = "Revision"; Expression = { [int]$logEntry.revision } },
                @{ Name = "Author"; Expression = { $logEntry.author } },
                @{ Name = "Date"; 
                   Expression = {
                       if ( $NoFormat )
                       {
                           [datetime]$logEntry.date
                       }
                       else
                       {
                           "{0:dd/MM/yyyy hh:mm:ss}" -f [datetime]$logEntry.date
                       }
                   } },
                @{ Name = "Message"; Expression = { $logEntry.msg } } | 

            Foreach-Object {        
                $_ | where-object { ![string]::IsNullOrEmpty($logEntry.msg) }  | Select-Object  Author, Date, Message              
            }
      }

    return $logObjects
 }

#send email function
 Function SendEmail($SendEmailsTo_, $EmailSubject_, $changes_)
 {
   $emailFrom = "automation@test.com" 
   $smtpserver="smtp.test.com" 
   $smtp=new-object Net.Mail.SmtpClient($smtpServer) 

   foreach ($email in $SendEmailsTo_.split(';'))
   {   
      $smtp.Send($emailFrom, $email, $EmailSubject_, $changes_)
   }
 }

#get svn logs since the last release
$SVNChanges = GetSVNLogs $lastBuildDate

$changes += "`r`n`r`n";
$changes += "SVN changes sice last release`r`n";
$changes += $SVNChanges | Format-Table -AutoSize | Out-String;
$changes += "`r`n-------------------------------------------------------------------`r`n";
$changes += "This is automated email, please do reply directly!";

#send email 
$EmailSubject = "Release $Version changes";

SendEmail $SendEmailsTo $EmailSubject $changes;

1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
Loading...Loading...

Using automation for gathering release changes

If you need to gather release changes when creating installers, the script below can help you. Script simply gets all or current database release changes stored in file. I use it to automatically gather the latest changes after TeamCity builds release installer. The changes could be sent to PR for documentation. You can of course use more complicated patterns when extracting script text when required. To execute it, just pass in update script location, version number and email addresses.

release_changes

 

 param (
 [string]$ScriptFolder = "C:\Database\Updates",
 [string]$Version = "2.11.0.0",
 [string]$SendEmailsTo = "test@test.com",
 [boolean]$GetAllChanges = 0
)

#sends notification emails
 Function SendEmail($SendEmailsTo_, $EmailSubject_, $changes_)
 {
   $emailFrom = "teamcity@test.com" 
   $smtpserver="smtp.test.com" 
   $smtp=new-object Net.Mail.SmtpClient($smtpServer) 

   foreach ($email in $SendEmailsTo_.split(';'))
   {   
      $smtp.Send($emailFrom, $email, $EmailSubject_, $changes_)
   }
 }

 #get file by version number
 Function GetReleaseFileName($Version_)
 {
    $VersionFilename_ ="v";
     $Version_.split('.') | ForEach-Object{
        $VersionFilename_ +=  [System.Convert]::ToDouble($_).ToString("00"); 
    }
    $VersionFilename_ += ".sql";

     #format e.g. v12.12.00.10.sql
    return $VersionFilename_;
 }

#return if no emails added
if($SendEmailsTo.trim() -eq "") { "no emails defined!"; return;}

$VersionFilename =  GetReleaseFileName $Version;

$EmailSubject = "Release $Version database changes";
$changes = "Changes in release file $VersionFilename `r`n `r`n";
$hasChanges = 0;

if(!$GetAllChanges) {  
    (dir $ScriptFolder) | sort CreationTime -Descending |
     ForEach-Object {  
        $fileContent = get-content ($_.Directory.FullName + "\" + $VersionFilename) -Raw;

        $patterns = 'alter','drop','insert','delete','update','create'; #paterns/strings to find
        $hasChanges = 0;
        foreach ($pattern in $patterns)
        {
           $fileContent.split("`r`n") | ?  { $_ -match $pattern } | % { $changes += $_.trim() + "`r`n"; $hasChanges = 1; } 
        } 

        if($hasChanges -eq 0) { $changes += "`r`nNo database changes for release $Version !"}

        write-output $changes

        SendEmail $SendEmailsTo $EmailSubject $changes;

        break;        
    }
}
else
{
  #parse all files for all previous releases
  $EmailSubject = "All database changes";
  $changes = "All database changes: `r`n `r`n";

  (dir $ScriptFolder) | sort CreationTime -Descending |
    ForEach-Object {  
        $fileContent = get-content ($_.Directory.FullName + "\" + $_.name) -Raw;

        $patterns = 'alter','drop','insert','delete','update','create';
        $changes += "`r`nChanges in release file $_`r`n";
        $hasChanges = 0;

        foreach ($pattern in $patterns)
        {          
           if($fileContent)
           {
              $fileContent.split("`r`n") | ?  { $_ -match $pattern } | % { $changes += $_.trim() + "`r`n"; $hasChanges = 1; }  
           } 
        } 

        if($hasChanges -eq 0) { $changes += "`r`nNo database changes for release " + $_.name.Replace(".sql","").Replace("v0","");}

        $changes += "`r`n-------------------------------`r`n";      
    }

    write-output $changes 

    SendEmail $SendEmailsTo $EmailSubject $changes;
}

I have included full script sample below
release_changes_notifier

1 Star2 Stars3 Stars4 Stars5 Stars (1 votes, average: 4.00 out of 5)
Loading...Loading...

Auto creating SVN tags and custom release installers

Automation within the software development company allows to save tremendous amount of time in the long run. The time spend for initial configuration of the automated tasks is almost nothing compared to running all processes manually. In this article I will show you how to configure auto SVN tagging and creating custom installation files each time after the TeamCity build is performed.

In our scenario we want to copy our current branch files to the https://svn.mycompany.com/Releases/Tags/ReleaseVersion location and from that location we want to create installation file that we want to deploy on the client server.

The first step is to create new TeamCity build configuration and as a first build step define following configuration:

svn_tags

Let’s create our svn-create-TAGS.bat file. The implementation is quite simple. There are 3 parameters that we will pass in from the TeamCity step: ReleaseVersion (%1), SVNRevision (%2), BranchSVNRoot (%3). Based on that we will trigger script below.

Because subversion copy function doesn’t have replace functionality that we can use, we then decide to delete current tag if exists. If the tag doesn’t exist then we will get svn error that could be passed to TeamCity Log. In our case we will use -q param to not display any error messages as this script will be run multiple times so each time the tags will have to replaced if the same release version is used.

After running this script we will have following tag created eg. https://svn.mycompany.com/Releases/Tags/Release.2.8.0.3″

 echo version %1
 echo revision %2
 echo branch path %3

  echo delete first if exists as there is no overwrite function for svn copy
  "C:\Program Files\TortoiseSVN\bin\svn.exe" delete "https://svn.mycompany.com/Releases/Tags/Release.%1" -q 
    -m "TeamCity generated: Deleting TAG branch for the release: %1" 

 echo copy to tag
 "C:\Program Files\TortoiseSVN\bin\svn.exe" copy -r%2 "%3/MyMainProjectFolder" "https://svn.mycompany.com/Releases/Tags/Release.%1" 
   -m "TeamCity generated: Creating TAG branch for the release: %1"

We also need to configure TeamCity parameters as follows:
svntags_params

When we have release tag created, we can now make release installer that can be deployed to the client. To do that we will define new build step (configuration is similar as the step above – script name and params will only be different).

Let’s create Installer_build.bat script then. We will pass in 2 parameters ReleaseVersion (%1), SVNRevision (%2). The script will create folder structure in Windows Temp location that we will use to import and compress our release files to. After we done with it we will clear that location and move executable file to our final release file location.

The script is basically importing files from the tag we created earlier, then the files are being compressed using 7za.exe command line utility. We can re-build the project in between but in our case project was built already by the other TeamCity process before it was moved to the release tag. After creating zip package we can build custom installer based on that file. This depends on your custom solution. In our example we will simply output the final zip file to be deployed to the client. Please see in-line comments for detailed information:

 echo params
 echo version %1
 echo revision %2

 echo top level folder stucture
 set root=%TEMP%\MyProjectBuild
 set export="%root%\Export"
 set build=%root%\Build
 set installer=%root%\Installer

 echo make sure nothing already exists
 rmdir /s /q "%root%"

 mkdir "%root%"
 mkdir "%build%"

 echo Create the installer
 echo %installer%
 mkdir %installer%

 svn export -r%2 "https://svn.mycompany.com/Releases/Tags/Release.%1/" "%export%"

 echo you may build you project here or proceed
 set MSBUILD_PATH=C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe

 echo Copy files ready to be compressed
 set InstallerFiles=%build%

 echo copy from export filder to the final build folder
 xcopy "%export%\*.*" "%InstallerFiles%\" /E /Y

 echo set tools location that contains your compressor file, set path the same as the executing batch file
 set Tools="%~dp0"
 set BuildZip=%installer%\MyProject.%1.zip

 echo current path %Tools%

 echo build your custom installer or export just zip file
 set FinalExecutable=%BuildZip%
 %Tools%\7za.exe a -tzip -r "%BuildZip%" "%build%\*.*

 echo copy it to the releases location and clear up
 set Releases=C:\Installers

 copy "%installer%\%FinalExecutable%" "%Releases%\%FinalExecutable%"

 if exist "%Releases%\%FinalExecutable%" (
	rmdir /s /q "%root%"
	echo The build is complete.
 ) else (
	echo Unable to copy to final destination. The installer is here: %installer%\%FinalExecutable%
 )

After creating above TeamCity build steps we can configure the release installer build to be triggered on successful main project build.

svntag_build_trigger

In order to get above scripts to work you need to adjust it to your requirements as I took it from the running solution I have created and for obvious reasons had to change the paths and names.
I hope this will help you to be more productive in your daily programming 🙂

1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
Loading...Loading...