Frequent Sitecore upgrades are good!

Frequent Sitecore upgrades have convincing benefits and lower its TCO.

My employer’s current practice is an annual Sitecore upgrade. I recommend this as the maximum interval; we should do more frequent upgrades when important-to-us new features, fixes, or enhancements are released. It may be prudent to even consider twice-a-year upgrades given Sitecore’s rapid release schedule.

Here’s the specific benefits of frequent upgrades:

  • Fast track putting UI enhancements and bug fixes into production.
  • Puts new features front and center. Even if we don’t use these features right away, they are often the basis of near-term enhancements.
  • Fast track putting enhanced modules into production. Many times, newer module versions require upgrades of the base product, too.
  • Avoids bifurcated environments. Aggressive upgrade policies reduce the pressure to try out and do development on newer releases than what we have in production.
  • Avoid cost of delaying implementing new features. We once delayed upgrading from 6.2 to 6.4. This contributed to not-aggressive-enough learning of 6.4’s enhancements, causing our old technology to get more deeply ingrained in our practices. This made our move to 6.4’s paradigm more complex.
  • Reduced upgrade complexity. We and other customers experienced difficult upgrades when we failed to upgrade frequently. Frequent upgrades means each upgrade is more of a snack than a huge meal.
  • Better supportability. While Sitecore has a generous support policy—they appear to support many versions going back—it is inevitable economic reality that dusty versions will have a harder support experience. The best companies are aggressively forward-looking.
  • Cleaner install and better reliability due to reduced use of hotfixes. If we do a frequent upgrade regimen, we can often defer hotfixes to when problems get fixed in future releases. With infrequent upgrades, we will be under pressure to rely more heavily on hotfixes (customizations) that 1. must later be backed out, 2. may not be as well-tested, creating unintended consequences during use, and 3. when backed out, could cause unpredictable changes.

My employer has a legitimate fear of frequent upgrades due to its experience with our ERP. Indeed, upgrades to this ERP are monstrously complicated. A Sitecore upgrade is a fraction of the complexity of an upgrade or even a patch on our ERP.

Due to the way Sitecore is architected—it generally disallows spaghetti code or direct modification of vendor code or logic—and my disinclination to customize the base product, compared to our ERP, it is rare that we will run into code incompatibilities with newer versions. Our custom code will usually “just work”.

To conclude, I recommend frequent upgrades whenever possible. It has convincing benefits, and, really, it is just a sign of an engaged product owner that wants a relevant, competitive web marketing presence.

Beware of Drupal for enterprise WCM

A colleague at large university asked my thoughts on using Drupal for enterprise web content management (WCM).

Drupal has its uses, but I only recommend it for point solutions or, if in large-scale use, for cookie-cutter things where all the Drupal instances are configured almost identically and share little content. I generally do not recommend it for enterprise-wide WCM.

I wrote:

Drupal is a great solution for certain purposes, but I hesitate at recommending it for an enterprise CMS. Even though some tools make it easier to manage [edit: like Aegir], Drupal “enterprise”, especially for a college campus, is still essentially flying many individual instances in parallel, so I don’t consider that a real enterprise setup. No other “enterprise” system that I am aware of is so loosely-coupled on the application layer of the service delivery stack.

You’ll find other institutions with a different perspective. I think Stanford is one. Stanford, I believe, is widely using Drupal. [edit: yes, it is: https://techcommons.stanford.edu/drupal]

The problem with their setups is to run a massive Drupal installation, your IT department’s staff commitment to web content management (WCM) will be more heavily expressed in sysadmin skillsets and FTEs than developer skillsets and FTEs. The problem there is cultural: as practitioners of stability, minimizing cost, avoiding change, etc., sysadmins are culturally much further away from web marketing than developers.

And that’s what I like about Sitecore: as a true enterprise WCM, it frees me from much of the sysadmin burden that I would bear by running gobs of parallel instances. It allows me to instead invest in developer skillets and FTEs, which in the long term helps our marketing mission.

Now, there’s also an economy of scale. At some point, you may have sufficient staff resources that it may in fact be cost-effective to go with virtually any free CMS as a base product and develop whatever you want on it.

Three general pointers:

  • Customized code that is not expressed as a formal Drupal module or theme will cause update headaches. Drupal core and the modules have frequent releases, and I recommend staying on top of them because they often contain important bug and security fixes. If you customize Drupal core or customize a module, you’ll have to re-customize it every time there’s a new release. However, if you can implement your custom code as a formal module, it is much more likely to be able to exist unchanged while other modules or Drupal core change. It’s likely, though, that you’ll need to revisit your modules on major new Drupal releases, like v7 to v8.
  • Software costs are a small part of TCO of a system. Just because the software is free does not mean you’re going to get a gigantic savings over a commercial product. That notwithstanding, there are FOSS [edit: free and open source software] tools that make a lot of sense, like, say, Firefox, Chrome, WordPress, and even Drupal for certain situations. But sometimes, FOSS tools may require more FTEs or, like I said above, FTE types that may not be the best cultural fit for marketing.
  • Generally, academic-targeted CMSes are not that good. They seem to have their rabid supporters, but my general experience is that these supporters are suffering from confirmation bias, and that these academic focused CMSes cannot compete with the big players.

Show all Sitecore Active Directory users

I manage a Sitecore installation that’s integrated with an enterprise Active Directory.

We have over 11,000 accounts in our Active Directory. I needed a list of the Sitecore users, who are only a small percentage of the 11,000.

We have nothing in Active Directory that sets them apart, like group membership.

We architected our solution so that users are never assigned directly to items; users are members of Sitecore roles, and we assign Sitecore roles to items. All I have to do is rifle through all my Sitecore roles.

So how do I find my users? It took a little C#. Here’s the core code:

var roles = Sitecore.Security.Domains.Domain.GetDomain("sitecore").GetRoles();
foreach (var role in roles)
{
    foreach(var roleMember in Sitecore.Security.Accounts.RolesInRolesManager.GetRoleMembers(role, false))
    {
        if (roleMember.AccountType == AccountType.User)
        {
            var userObject = Sitecore.Security.Accounts.User.FromName(roleMember.Name, false);
 
            // only adding SMU domain users
            if (userObject.Domain.Name == "myActiveDirectoryDomain")
                AddUserToList(userObject);
        }
    }
}

This gets all Sitecore domain groups and extracts all users who are a member of my corporate domain. Of course, you’ll replace myActiveDirectoryDomain with your own domain name.

I created a separate AddUserToList method to handle adding these items to a Dictionary:

private void AddUserToList(User user)
{
    if (!_users.ContainsKey(user.Name))
    {
        _users.Add(user.Name,user);
    }
}

After the core code runs, you’ll need to code your own stuff to spit out what’s in the dictionary.

Here’s what I used:

foreach(var user in _users)
{
    var row = new TableRow();
    OutputTable.Rows.Add(row);
 
    row.Cells.Add(new TableCell { Text = user.Value.Profile.UserName });
    row.Cells.Add(new TableCell { Text = user.Value.Profile.FullName });
    row.Cells.Add(new TableCell { Text = user.Value.Profile.Email });
 
    if (user.Value.Profile.FullName.Length == 0)
    {
        row.CssClass = "alert";
    }
 
    var rolesCell = new TableCell();
 
    foreach (var role in RolesInRolesManager.GetRolesForUser(user.Value, false))
    {
        if (role.Domain.Name == "sitecore")
        {
            rolesCell.Text += "
 " + role.Name;
        }
    }
 
    rolesCell.Text = rolesCell.Text.Substring(7);
    row.Cells.Add(rolesCell);
}

Note that I already had a Table named OutputTable on my ASPX page.

Tadaa! The result is a list of all my domain members who are Sitecore users.

Upgrading hardened Sitecore content delivery environments

How do you upgrade hardened content delivery (CD) environments? Ours are so hardened that you can’t even get to /sitecore/admin/UpdateInstallationWizard.aspx.

Here’s how. It can be tedious, but these make it easier:

  1. CDs are mostly stripped-down instances of full Sitecore environments.
  2. Any needed database changes are handled when upgrading the content mastering (authoring) environment.

You only need to do 3 things on CDs.

But first, two notes:

  1. If you upgrade the CDs before you’ve upgraded the content mastering (CM) environment, you may have unstable CDs until the CM upgrade is done.
  2. Sitecore’s .update files are really Zip files. Just open it with your favorite Zip program, like 7-Zip, and it works like any other Zip file.

For each update file, do the following three steps. You must perform them in the release order of the update files, starting with the oldest release.

1. Add new or changed files

Extract everything in the addedfiles and changedfiles directories of the update file. You’ll extract them over the web root. Tell your Zip program to overwrite existing files.

2. Delete files no longer needed

This is the hardest part. Inspect the update package’s deletedfiles and deletedfolders directories of the update file. Every file (not folder) under each corresponds to a file or folder under your web root that needs to be trashed.

Note the wording: “every file“. For example, in Sitecore 6.5.0 rev.110602_fromv640rev101012_2.update, there is a file named AuthoringFeedback under deletedfolders\sitecore\shell\Applications\Analytics. That means you would delete the directory at sitecore/shell/Applications/Analytics/AuthoringFeedback under the web root.

You may have to dig deeply and thoroughly to find all files and directories.

3. Edit .config files.

Do all .config file changes that correspond to the update package you just handled. A list of .config file changes are at http://sdn.sitecore.net/Products/Sitecore%20V5/Sitecore%20CMS%206/ReleaseNotes/webConfig.aspx.

Wrapping up

If you’re going through multiple upgrades, it’s tempting to do all them at once–do all the file additions at once, then all the file deletions, and then do all the .config changes. This might work as long as you work through the update files in their release order, starting with the oldest release, and if Sitecore didn’t delete something and add it back or vice versa.

For example, suppose you were doing four updates at once. In update #2, a file named x.png was deleted, but then it was added back in update #4. If you do all your file additions first, then do all deletions 2nd, your final state will have no x.png.

As long as you’ve been careful and did the CM environment upgrade first, the CDs should “just work” when done.

PowerShell’s 248 or 260 character limit path bug

Thanks to bad, old code, Microsoft’s PowerShell breaks on file or directory paths longer than 248 characters. PowerShell reuses other code that maintains compatibility with very old software that can’t understand paths with more than 260 characters. I don’t know how 260 drops to 248 in PowerShell, but it does.

Amazingly, in the first comment in a bug report, Microsoft dodges the question and passes the buck.

I hit this bug when working with a Sitecore web site. For example, I have a path like this:

C:\XXXXXXXXXXXXXXX\raw\WebSite\App_Data\MediaFiles\{11111111-1111-1111-1111-111111111111}\{3D6658D8-A0BF-4E75-B3E2-D050FABCF4E1}\{15451229-7534-44EF-815D-D93D6170BFCB}\{700C2C14-6082-4378-AA43-821E8422E9BE}\{6507E0E5-6CF2-4342-A11F-68F787B32EA3}Boulevard.jpg

That is 259 characters. I can’t delete it with PowerShell’s Remove-Item command.

Fortunately, there is a workaround: use legacy command prompt tools. In my case, I am trying to remove everything below C:\XXXXXXXXXXXXXXX\raw\, so I can use this command in PowerShell:

cmd /c rmdir C:\XXXXXXXXXXXXXXX\raw\ /s/q

But I shouldn’t have to do this. There is no reason that PowerShell can’t delete files with more than 248 character paths.