Automatic publish of Sitecore content at end of TDS CI deploy
Asked Answered
P

3

7

I'm using Teamcity to automate (single click) deploys into our QA environment. At the moment content items are being deployed, but the QA guys then have to go and manually trigger a re-publish of the site.

Is there anyway using either TDS, Sitecore Rocks or A.N.Other tool to automate the re-publish at the end of the deploy process.

I know I can configure Sitecore to automatically publish every x minutes, but I would rather leave that deactivated as QA will also be performing load tests and I don't want the scheduler getting in the way.

Pharisaic answered 15/10, 2012 at 13:11 Comment(0)
R
10

We have done this by setting up an ASPX on our daily build and QA websites that triggers a publish. The build then has a Powershell call to trigger this. We've done this with CruiseControl, TeamCity, and Team Build.

TeamCity Configuration

The configuration for TeamCity uses an additional build step after you've deployed files and TDS:

  1. Runner Type: Powershell
  2. Step name: Trigger Publish to Web DB
  3. Powershell run mode: x64
  4. Working Directory: [no value]
  5. Script: Source code
  6. Script Source:

    $r = [System.Net.WebRequest]::Create('http://myqasite/SomePath/Publish.aspx'); $resp = $r.GetResponse();

  7. Script execution mode: Put script into Powershell stdin with "-Command -" arguments

Publish.aspx

The code for our Publish page is something like this:

    string full = Request.QueryString["full"];

    // Set up the publish mode
    PublishMode publishMode = PublishMode.Smart;
    if (!string.IsNullOrWhiteSpace(full) && (full == "1" || full.Equals("true", StringComparison.InvariantCultureIgnoreCase)) ) {
        publishMode = PublishMode.Full;
    }

    using (new Sitecore.SecurityModel.SecurityDisabler()) {
        //We need the target database
        var webDb = Sitecore.Configuration.Factory.GetDatabase("web");

        //source db
        var masterDb = Sitecore.Configuration.Factory.GetDatabase("master");

        try {
            foreach (Language language in masterDb.Languages) {
                //loops on the languages and do a full republish on the whole sitecore content tree
                var options = new PublishOptions(masterDb, webDb, publishMode, language, DateTime.Now)
                              {RootItem = masterDb.Items["/sitecore"], RepublishAll = true, Deep = true};
                        var myPublisher = new Publisher(options);
                        myPublisher.Publish();
            }
        }
        catch (Exception ex) {
            Sitecore.Diagnostics.Log.Error("Could not publish the master database to the web", ex);
        }

    }
Rodney answered 15/10, 2012 at 13:49 Comment(5)
It's probably unnecessary to do a full publish of the entire content tree. TDS edits items and places them into the Publish Queue, so you should be able to trigger an incremental publish which will do the same job but a lot more efficiently. NOTE: either way, you'll need workflows properly set up across all content and media items, in case an editor has made a change that they don't want published yet.Koren
Sean: this is only going to happen in QA and it will be a full db reset :)Pharisaic
Note that the code above defaults to doing a Smart publish and only does a full publish if the user requests it in the URL to the page.Rodney
Ah, missed that. I still believe incremental publish will be quicker, as it won't need to do item comparisons between databases. I may be wrong. Either way, it's a nice script you have there.Koren
Yup, incremental may be fastest but does depend on the application not being restarted. I believe the queue for incremental gets cleared on application reset? We've had issues depending on that publish in the past for automated tasks. It would be pretty easy to extend the script to add a way to specify using incremental mode for a given build by altering the powershell script parameters to the page and adding a new check for parameter values.Rodney
P
7

While waiting for an answer I shared the question on twitter, this resulted being given a guiding hand by Stephen Pope (his response) He suggested using the PowerShell enhancements offered by Sitecore Rocks, it took a while (documentation is thin on the ground) but I have achieved the result I was after :)

As a record of what I found, the following is provided as a potential answer to my own question, though big thanks to Jay S who's solution I would have used if not for this..

Anyway.. Using an additional build step in the Teamcity build, I have the following:

  • Runner type: Powershell
  • Step name: Publish site
  • Powershell run mode: x64
  • script: Source code
  • script execution mode: Put script into powershell stdin with "-Command -" arguments
  • Additional command line parameters: -ExecutionPolicy Unrestricted
  • Script source:

    import-module '.\build-modules\sitecore\sitecore.psd1';
    new-psdrive -name "rocks" -psp SitecoreRocks -root "" -host "%QA.Url%" -usr "%QA.sitecore.user%" -pwd "%QA.sitecore.password%" -databasename "master" -scope "Script";
    set-location rocks:
    Publish-SCDatabase;

The magic happens within the Publish-SCDatabase commandlet which when you run Get-Help shows a bunch of parameters, it turns out that only two of the parameters are usable -Name and -Mode

Finding documentation beyond the vs-plugins link above was impossible, so a bit of .net reflection and a good dose of patiense showes that the parameters have the following options:

  • -Name The name of the database to run the publish against (default is the psdrive database
  • -Mode Sets the publish mode of the comandlet with the following options available:
    • 0: Republish
    • 1: Incremental
    • 2: Smart
    • 3: Rebuild

Of course better documentation, and possibly additional info via the Get-Help commandlet would be nice.. if the rocks project was open source, I may well have forked the project to generate the additional help.

Now that there are two very good solutions to this question, I will let peoples votes decide on which is the best answer, in a few days I will check the votes and mark the most voted as the accepted answer.

Pharisaic answered 16/10, 2012 at 11:14 Comment(2)
This solution works only if you don't have multiple publish targets and only want to publish to one of them. If you want to publish to all targets or only have one, then this is a great solution that keeps solution in the build engine.Dogie
Up-voted for using reflector to work out what Rocks is doing. Good effort.Adis
A
5

Whist these are both good solutions (the custom aspx and the Powershell via Rocks one), they both have some shortcomings.

  1. Custom aspx page. Unless you "go to town" on your C# solution for publishing, in offering a very sophisticated way to change publishing targets, Root nodes and other options (e.g. smart, incremental), and allowing for invocation of these options in as flexible manner as possible, you would risk having to change your code to change deployment strategies periodically. The comment by Richard R below the Rocks answer concedes that. Contrast that with some kind of scripted solution. The fact it wouldn't be compiled code lends itself to being chopped and changed, and even proliferating into lots of different scripts for different purposes.

  2. Powershell via Rocks. Again there are shortcomings in terms of customization. You are limited to what commandlets (and ultimately CRUD operations) are supported by that particular implementation. Not to mention it being closed source and having limited documentation.

I probably need to elaborate a little about the use cases I have in mind that may need to be catered for. What if it is particularly important for us to publish only parts of the content tree on deploys (aspects like /templates, /system, /layouts)? In our deployments we have huge /content and /media library sections so being more granular about what gets published for certain deployments is essential to expedite deploys. Now, whilst it's perfectly feasible to create your own /Publish.aspx page which will specify the Root items and do these (deep) publishes for you, it would be much more elegant to do it via some kind of script. Not only that but consider the myriad other operations you may wish to automate on scripted deployments and environmental set-up such as adding content, applying workflows e.t.c.

Contrast both of these with Adam Najmanowicz's Powershell Console/Extensions. By allowing you to develop powershell scripts within sitecore, you can effectively create whatever you wish to by way of a scripted solution and even invoke it from an external tool in order to make that a step in a CI server or orchestrator: http://blog.najmanowicz.com/2011/12/19/continuous-deployment-in-sitecore-with-powershell/

Adis answered 31/12, 2013 at 11:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.