views:

739

answers:

3

We are gearing up for some pretty serious Sharepoint(MOSS 2007) development including custom web parts, lists, master pages and layouts etc etc and etc.

We are evaluating version control and it seems that the discussion has not got much deeper than that. I am keen that we can easily deploy from the source control to our test and production servers with as little human contact as possible, and preferably entirely automatically after every check in.

I have not worked using CI before and so am feeling a bit ignorant as to what is possible with Sharepoint, and what is too complex to be sensible.

I fear if we head off down a too 'easy' path then we will come to regret it pretty swiftly when we have to spend half a day setting up each environment after we release some new functionality.

I have not even started to address in my head what happens when there is actual content in the lists added by users and how that will affect what we do on the development side.

Links to blogs/documentation are welcomed. Personal experiences VERY welcome.

+5  A: 

The closest I have experience is on a project that used STSDEV to build solutions for release. Custom build actions allowed us to remove the sharepoint solution from the target server, install the new solutions and reset the required application pools.

Took a while to build, but it worked well. We did not release to test using this process, but it may be possible.

Here is an example of a targets file. Unfortunately, it is a bit complex.

<?xml version="1.0" encoding="utf-8" ?>
<Project DefaultTargets="DebugBuild" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"&gt;

  <PropertyGroup>
    <PackageName>MyFeatures.wsp</PackageName>
    <PackageFile>MyFeatures.wsp</PackageFile>
    <TargetUrl>http://intranet&lt;/TargetUrl&gt;
    <ProjectDeploymentFilesFolder>DeploymentFiles</ProjectDeploymentFilesFolder>
    <ProjectRootFilesFolder>$(ProjectDir)\RootFiles</ProjectRootFilesFolder>
    <WssRootFilesFolder>$(ProgramFiles)\Common Files\Microsoft Shared\web server extensions\12</WssRootFilesFolder>
    <ReleaseFolder>$(SolutionDir)Deployment</ReleaseFolder>
    <MAKECAB>"C:\Windows\System32\makecab.exe"</MAKECAB>
    <STSADM>"$(ProgramFiles)\Common Files\Microsoft Shared\web server extensions\12\bin\stsadm.exe"</STSADM>
    <STSDEV>"$(SolutionDir)..\Tools\STSDev\stsdev.exe"</STSDEV>
    <GACUTIL>"C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin\gacutil.exe"</GACUTIL>
    <IISAPP>cscript c:\windows\system32\iisapp.vbs</IISAPP>    
    <WARMUPSITE>"$(SolutionDir)..\Tools\WarmUpServer\AsyncWarmup.bat" "$(SolutionDir)..\Tools\WarmUpServer\"</WARMUPSITE>
    <TIMERJOBSRESTART>net stop SPTimerV3 &amp; net start SPTimerV3</TIMERJOBSRESTART>
  </PropertyGroup>

  <ItemGroup>
    <WSSSourceFiles Include="$(ProjectDir)\RootFiles\**\*.*" />
  </ItemGroup>  

<Target Name="DebugBuild">
  <Message Text="Refreshing Deployment Files..." Importance="high" />
  <Exec Command="$(STSDEV) /refresh $(TargetName) $(ProjectDir)" ContinueOnError="true" />
  <Message Text="Deleting Solution Package File..." Importance="high" />
  <Delete Files="$(ProjectDeploymentFilesFolder)\$(PackageFile)" ContinueOnError="true" />
  <Message Text="Building Solution Package (Debug Version)" Importance="high" />
  <Exec Command="$(MAKECAB) /F $(ProjectDir)\$(ProjectDeploymentFilesFolder)\SolutionPackage.ddf /D CabinetNameTemplate=$(PackageFile)" ContinueOnError="false" />
  <Message Text="" Importance="high" />
  <Message Text="Copying WSP file to CAB" Importance="high" />
  <Delete Files="$(ProjectDeploymentFilesFolder)\$(PackageFile).cab" ContinueOnError="true" />
  <Copy SourceFiles="$(ProjectDeploymentFilesFolder)\$(PackageFile)" DestinationFiles="$(ProjectDeploymentFilesFolder)\$(PackageFile).cab" SkipUnchangedFiles="false" />
  <Message Text="Copying WSP file to release folder: $(ReleaseFolder) from $(ProjectDeploymentFilesFolder)\$(PackageFile)" Importance="high" />
  <Exec Command="attrib -r &quot;$(ReleaseFolder)\$(PackageFile)&quot;" ContinueOnError="true"></Exec>
  <Delete Files="$(ReleaseFolder)\$(PackageFile)" ContinueOnError="true" />
  <Copy SourceFiles="$(ProjectDeploymentFilesFolder)\$(PackageFile)" DestinationFolder="$(ReleaseFolder)" SkipUnchangedFiles="false" />
  <Message Text="" Importance="high" />
</Target>

<Target Name="DebugInstall" DependsOnTargets="DebugBuild">
  <Message Text="Installing Solution..." Importance="high" />
  <Exec Command="$(STSADM) -o addsolution -filename $(ProjectDeploymentFilesFolder)\$(PackageFile)" ContinueOnError="true" />
  <Exec Command="$(STSADM) -o execadmsvcjobs" />
  <Message Text="" Importance="high" />
</Target>

<Target Name="DebugDeploy" DependsOnTargets="DebugInstall">
  <Message Text="Deploying Solution..." Importance="high" />
  <Exec Command="$(STSADM) -o deploysolution -name $(PackageName) -immediate -allowgacdeployment -url http://intranet" />
  <Exec Command="$(STSADM) -o execadmsvcjobs" />
  <Copy SourceFiles="$(TargetDir)$(TargetName).pdb" DestinationFolder="C:\WINDOWS\assembly\GAC_MSIL\MyFeatures\1.0.0.0__ce271be627d58c77" SkipUnchangedFiles="" />
  <Message Text="$(TargetDir)$(TargetName).pdb copied to GAC for debugging." Importance="high" />
  <Message Text="" Importance="high" />
</Target>

<Target Name="DebugDeployForce" DependsOnTargets="DebugInstall">
  <Message Text="Deploying Solution..." Importance="high" />
  <Exec Command="$(STSADM) -o deploysolution -name $(PackageName) -immediate -allowgacdeployment -url http://intranet -force" />
  <Exec Command="$(STSADM) -o execadmsvcjobs" />
  <Copy SourceFiles="$(TargetDir)$(TargetName).pdb" DestinationFolder="C:\WINDOWS\assembly\GAC_MSIL\MyFeatures\1.0.0.0__ce271be627d58c77" SkipUnchangedFiles="" />
  <Message Text="$(TargetDir)$(TargetName).pdb copied to GAC for debugging." Importance="high" />
  <Message Text="" Importance="high" />
</Target>

<Target Name="DebugRedeploy" >
  <Message Text="" Importance="high" />
  <Message Text="Starting sequence of Retract/Delete/Build/Install/Deploy" Importance="high" />
  <CallTarget Targets="DebugRetract" />
  <CallTarget Targets="DebugDelete" />
  <CallTarget Targets="DebugBuild" />
  <CallTarget Targets="DebugInstall" />
  <CallTarget Targets="DebugDeployForce" />
  <Message Text="" Importance="high" />
</Target>      

  <Target Name="DebugRetract" >
  <Message Text="Retracting Solution" />
  <Exec Command="$(STSADM) -o retractsolution -name $(PackageName) -immediate -url http://intranet" ContinueOnError="true" />
  <Exec Command="$(STSADM) -o execadmsvcjobs" />
  <Message Text="" Importance="high" />
</Target>

<Target Name="DebugDelete" DependsOnTargets="DebugRetract">
  <Message Text="Deleting Solution Package from Farm Solution Package Store" />
  <Exec Command="$(STSADM) -o deletesolution -name $(PackageName)" ContinueOnError="true" />
  <Exec Command="$(STSADM) -o execadmsvcjobs" />
  <Message Text="" Importance="high" />
</Target>

   </Project>
Nat
+3  A: 

Look at Powershell ... unfortunately this is one of the major gripes with SharePoint is a lack of a good development and deployment process. Everything should be packaged into solutions and deployed via powershell, powershell can also manage any clean up of information. To version simply deploy the solutions as an upgrade and use Powershell to update in your apps as appropriate (if you update your version number). It is a lot of extra work but works well enough. In a recent upgrade I had to version two web parts and then used powershell to loop through all ~1,500 my sites removing the old web parts and adding back in the new ones.

As you go you should start to develop a strong Powershell library to perform powerful updating tasks.

webwires
+1  A: 

The only was to work with SharePoint with some kind of continous integration is when you are working with features and solution packages (wsp).

You just have to somehow get to package your wsp with all the necessary files/DLLs and configuration and then deploy it. Once it's deployed, you can create a batch script to automatically reactivate all features.

Please be aware that all file that has been customized (unghosted) will NOT be updated. You must make sure to make a reset to site definition (by code it's "SPFile.RevertContentStream").

Good luck!

Maxim