mandag den 4. juni 2012

Mercurial operations and IIS 7.5

This example is based on Mercurial used up against development of websites on IIS 7.5
In the example, the repositories will copy and add new files between a repositories according web-folder and it's location on IIS, which also is the safest option.

When you work with Mercurial and in addition got the need to update your IIS 7.5 development files, here is how you can do it with ease.
The scripts will stop a sites AppPool and the website itself, run the Mercurial commands and start the AppPool and website up again.
Which means that the developer always sees the updated site when checking it with a web-browser.
There is some logging added as well.
 
Locate the websites repositories .hg folder and create/edit the file named hgrc (Remember to adjust the account name and paths)

hgrc
[ui]
; editor used to enter commit logs, etc.  Most text editors will work.
editor = notepad
username = administrator@contoso.com

[paths]
default = D:\Repositories\Contoso\

[hooks]
commit = D:\Repositories\Contoso\.hg\HgPost_COMMIT.cmd
push = D:\Repositories\Contoso\.hg\HgPost_PUSH.cmd
changegroup = D:\Repositories\Contoso\.hg\HgPost_CHANGE.cmd

Now add following bat files (Remember to adjust the account name and paths)


HgPost_COMMIT.cmd
CALL "%~dp0HgPost.cmd" commit %* >> C:\inetpub\logs\hg\post.log 2>&1
HgPost_PUSH.cmd
CALL "%~dp0HgPost.cmd" push %* >> C:\inetpub\logs\hg\post.log 2>&1
HgPost_CHANGE.cmd
 CALL "%~dp0HgPost.cmd" change %* >> C:\inetpub\logs\hg\post.log 2>&1
HgPull.cmd
 @C:\Python26\Scripts\hg pull
HgUpdate.cmd
 @C:\Python26\Scripts\hg update -C
HgPost.cmd
@ECHO off

:: Projects need to have their webfiles in a folder labeled WEBFILES
:: Example: \Repositories\Contoso.com\WEBFILES\index.cfm

:: !!! USER SETTINGS !!!
::Correct IIS_Root and RepoRoot pointers needed!!!
@SET IIS_Root=C:\inetpub\wwwroot\
@SET RepoRoot=D:\Repositories\
@SET UserName=Contoso\Administrator

@ECHO.
@ECHO _________________________________________________________________________________

:: Checks if the pointers are correct
@IF NOT EXIST %IIS_Root% (
    ECHO Error: %IIS_Root% not available
    GOTO :eof )
@IF NOT EXIST %RepoRoot% (
    ECHO Error: %RepoRoot% not available
    GOTO :eof )

:: Finds the Repository name
@SET ThisDir=%~p0
@SET ThisDir=%ThisDir:.hg\=%
@SET ThisDir=%ThisDir:~1,-1%
@SET ThisDir=%ThisDir:\=,%
@FOR %%a IN (%ThisDir%) DO SET "RepoMap=%%a"

@SET IIS_Dir=%IIS_Root%%RepoMap%
@SET RepoDir=%RepoRoot%%RepoMap%
@SET WebDir=%RepoRoot%%RepoMap%\WEBFILES

:: ROBOCOPY
:: /E : Copy Subfolders, including Empty Subfolders.
:: /B :: copy files in Backup mode.
@SET _what=/E /B
:: /R:n :: number of Retries
:: /W:n :: Wait time between retries
@SET _options=/R:0 /W:0
::/NFL : No File List - don't log file names
::/NDL : No Directory List - don't log directory names
@SET _log=/NFL /NDL
:: And all added to one string
@SET _roboString=%WebDir% %IIS_Dir% %_what% %_options% %_log%

@IF NOT EXIST %RepoDir% (
    @ECHO Error: %RepoDir% is not available
    GOTO :eof )

@IF [%1] EQU [commit] SET HgCommand=COMMIT
@IF [%1] EQU [change] SET HgCommand=CHANGE
@IF [%1] EQU [push] SET HgCommand=PUSH

@ECHO HG %HgCommand% for %RepoMap% executed %DATE% %TIME%
@ECHO.
@SETLOCAL
@ECHO Localizing Repository %RepoDir%
@PUSHD %RepoDir%
@ECHO _____________________________________________
@ECHO Updating %RepoDir%
@ECHO.
@CALL %RepoDir%\.hg\HgPull.cmd
@ECHO.
@ECHO.
@CALL %RepoDir%\.hg\HgUpdate.cmd
@ECHO.
@ECHO _____________________________________________
@IF EXIST %IIS_DIR% (
    IF EXIST %WebDir% (
        @ECHO Stopping %RepoMap% on IIS
        @ECHO.
        @RUNAS /user %UserName% C:\Windows\system32\inetsrv\AppCmd Stop Site %RepoMap%
        @RUNAS /user %UserName% C:\Windows\system32\inetsrv\AppCmd Stop Apppool %RepoMap%
        @ECHO.
        @ECHO Updating %IIS_Dir%
        @ROBOCOPY %_roboString%
        @ECHO.
        @ECHO Starting %RepoMap% on IIS
        @ECHO.
        @RUNAS /user %UserName% C:\Windows\system32\inetsrv\AppCmd Start Apppool %RepoMap%
        @RUNAS /user %UserName% C:\Windows\system32\inetsrv\AppCmd Start Site %RepoMap%
    ) ELSE (
    @ECHO Warning: The repository does not exist as a website. )
    )
@ECHO.
@ENDLOCAL
GOTO :eof

EXIT

In addition to the above, we want some log management added, for that we create another bat file and add it on a task schedule. (Remember to adjust the path)

archive_hg_logs-cmd
ECHO

:DATE
IF NOT EXIST C:\inetpub\logs\hg\post.log GOTO :CLEANUP
MOVE C:\inetpub\logs\hg\post.log C:\inetpub\logs\hg\post_%date:~0,2%%date:~3,2%%date:~6,4%.log

:CLEANUP
IF NOT EXIST C:\inetpub\logs\hg\*.log GOTO :EXIT

::Delete logs older than 3 weeks
FORFILES /P C:\inetpub\logs\hg\ /S /M *.log /D -21 /C "CMD /c DEL @PATH"


:EXIT
EXIT

My task schedule looks like this in XML

TaskSchedule.XML
<?xml version="1.0" encoding="UTF-16"?>
<Task version="1.3" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
  <RegistrationInfo>
    <Date>2012-06-04T00:00:00.3697552</Date>
    <Author>Contoso\administrator</Author>
  </RegistrationInfo>
  <Triggers>
    <CalendarTrigger>
      <StartBoundary>2012-06-04T00:00:00Z</StartBoundary>
      <ExecutionTimeLimit>PT1H</ExecutionTimeLimit>
      <Enabled>true</Enabled>
      <ScheduleByDay>
        <DaysInterval>1</DaysInterval>
      </ScheduleByDay>
    </CalendarTrigger>
  </Triggers>
  <Principals>
    <Principal id="Author">
      <UserId>Contoso\administrator</UserId>
      <LogonType>Password</LogonType>
      <RunLevel>HighestAvailable</RunLevel>
    </Principal>
  </Principals>
  <Settings>
    <MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
    <DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>
    <StopIfGoingOnBatteries>false</StopIfGoingOnBatteries>
    <AllowHardTerminate>true</AllowHardTerminate>
    <StartWhenAvailable>true</StartWhenAvailable>
    <RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
    <IdleSettings>
      <StopOnIdleEnd>true</StopOnIdleEnd>
      <RestartOnIdle>false</RestartOnIdle>
    </IdleSettings>
    <AllowStartOnDemand>true</AllowStartOnDemand>
    <Enabled>true</Enabled>
    <Hidden>false</Hidden>
    <RunOnlyIfIdle>false</RunOnlyIfIdle>
    <DisallowStartOnRemoteAppSession>false</DisallowStartOnRemoteAppSession>
    <UseUnifiedSchedulingEngine>false</UseUnifiedSchedulingEngine>
    <WakeToRun>true</WakeToRun>
    <ExecutionTimeLimit>PT1H</ExecutionTimeLimit>
    <Priority>7</Priority>
  </Settings>
  <Actions Context="Author">
    <Exec>
      <Command>C:\BatchFiles\archive_hg_logs.cmd</Command>
    </Exec>
  </Actions>
</Task>
That's all there is to it.

1 kommentar:

  1. There's also HgLab ( http://hglabhq.com ) - a source control management system for and Mercurial Server for Windows with push, pull and streaming capabilities, repository browser, Active Directory integration, ACLs and lots of other things.

    SvarSlet