Find your dream job at PaperCut

Choose your language

Choose your login

Contact us

Blog

Upgrade Automation: Putting it all together


This is part three of a three part series exploring how to automate the experience of alerting your sysadmin that PaperCut MF has a new version available:

PART 1 – Automate your PaperCut MF upgrade review process – Alec shows you how to discover which version of PaperCut MF is currently running on your server

PART 2 - What’s the latest and greatest release of PaperCut MF? - Alec explains how to identify the most current PaperCut MF release version available


In the previous two posts in this three part series, we discovered:

  1. Which version of PaperCut MF was running on the server (INSTALLED_VERSION), and
  2. What’s the latest release from PaperCut Software (CURRENT_RELEASE).

Now we need to tie it all together so that a review ticket gets assigned to the correct application administrator for action if a new release appears.

Unfortunately, it’s not as simple as just comparing the two numbers we get every week to see if a release is available. (Once a week seems like a good interval to check for new releases, but you may prefer something different)

It’s more than likely that, in the normal course of events, we might wait more than a week for a suitable upgrade window (unless there was a critical security or bug fix). It would be tedious to keep getting the same reminder repeatedly over the ensuing weeks.

So each time we check, we need to record that version (LAST_VERSION_CHECKED) and compare that to the published latest release, and not the version we have installed. If the LAST_VERSION_CHECKED is the same as the latest release, then let’s not annoy the system admins with another potential review ticket.

For example, using the Dash shell:

echo Latest PaperCut release is $CURRENT_RELEASE. Installed Release is $INSTALLED_RELEASE

#Default
LAST_VERSION_CHECKED=$INSTALLED_RELEASE

if [ -e ~/LAST_VERSION_CHECKED ] ;then
  LAST_VERSION_CHECKED=$(cat ~/LAST_VERSION_CHECKED) # Override default
fi

if [ "$LAST_VERSION_CHECKED" = "$CURRENT_RELEASE" ] ; then
  echo PaperCut $PRODUCT_UPCASE $CURRENT_RELEASE  already checked. Nothing to do here
  exit 0
fi

And in PowerShell:

Write-Host "Latest PaperCut release is $CURRENT_RELEASE. Installed Release is $INSTALLED_RELEASE"

try {
  $LAST_VERSION_CHECKED = Import-Clixml -path ~/LAST_VERSION_CHECKED
}
catch {
  $LAST_VERSION_CHECKED = $INSTALLED_RELEASE
}

if ( "$LAST_VERSION_CHECKED" -eq "$CURRENT_RELEASE" ) {
  Write-Host No new release
  exit 0
}

If the LAST_VERSION_CHECKED is not equal to the CURRENT_RELEASE, then we can check the CURRENT_RELEASE against the INSTALLED_VERSION to see if an upgrade is possible. It’s possible to argue this check will generally be redundant, but I think it’s better to be sure:

if [ "$INSTALLED_RELEASE" = "$CURRENT_RELEASE" ] ; then
  echo Installed release $INSTALLED_RELEASE is already up to date. No new update available
  exit 0
fi
if ( "$CURRENT_RELEASE"  -eq  "$INSTALLED_RELEASE") {
  Write-Host Installed release $INSTALLED_RELEASE is already up to date. No new update available
  Exit-PSHostProcess 0
}

All that’s left now is to create a job ticket that ensures the new release gets reviewed and hopefully scheduled.

As a further service to our colleagues, we can add a link to the release notes in the ticket as well. For that, we need to extract the MAJOR, MINOR, and FIX numbers from the CURRENT_RELEASE:

echo PaperCut $PRODUCT_UPCASE $INSTALLED_RELEASE can be upgraded to $CURRENT_RELEASE

MAJOR="$(echo $CURRENT_RELEASE  | cut -d . -f 1)"
MINOR="$(echo $CURRENT_RELEASE  | cut -d . -f 2)"
FIX="$(echo $CURRENT_RELEASE  | cut -d . -f 3)"

RELEASE_NOTES="https://www.papercut.com/products/$PRODUCT/release-history/${MAJOR}-${MINOR}/#v${MAJOR}-${MINOR}-${FIX}"

The PowerShell version looks a bit different. See below for further details.

For this example, I am going to create tickets in a GitHub repository, using the gh CLI tool. Of course, you should integrate with your own work management system. But in case you’re curious, here are the details (again the PowerShell version is a bit different – see below).

The gh command needs an API token that can be stored in a file and passed via an environment variable:

# Use appropriate API for your ticket system
GH_TOKEN=$(cat ~/.GITHUB_ACCESS_TOKEN) gh issue -R $GH_REPO create -a $MINION \
   -t "Review PaperCut $PRODUCT_UPCASE $INSTALLED_RELEASE upgrade to version $CURRENT_RELEASE" \
   -b "Review release notes at $RELEASE_NOTES"

Passing environment values to commands in PowerShell is not quite so elegant, but upcasing strings with ToUpper() is easy:

$env:GH_TOKEN = (Get-Content -raw ~/.GITHUB_ACCESS_TOKEN).trim()

gh issue -R "$GH_REPO" create -a "$MINION" `
  -t "Review PaperCut $($PRODUCT.ToUpper()) $($INSTALLED_RELEASE.ToString()) upgrade to version $($CURRENT_RELEASE.ToString())" `
  -b "Review release notes at $RELEASE_NOTES"

(I also had to convert from System.Version to System.String using ToString(). More on that below).

Now we have a shiny new ticket to review:

[caption id=“attachment7239” align=“aligncenter” width=“1024”] _New ticket created[/caption]

And finally, don’t forget to update the LAST_VERSION_CHECKED!

echo -n $CURRENT_RELEASE > ~/LAST_VERSION_CHECKED

See below for the PowerShell version.

Next steps

You can find the examples at https://github.com/PaperCutSoftware/PaperCutExamples/tree/main/mf-automation

I’ve tried to make the examples as simple as possible, whilst being fully functional. As a result, there are some things that should be done, and things that could be done, when using this approach.

  1. The example scripts generally take an optimistic view of success and it may be hard to track down problems when they occur. More rigorous checking of all return values and appropriate diagnostic messages would help.
  2. There are a number of values and API credentials stored in the home (~) directory of the user running the scripts. This content could be stored elsewhere, for example in the Windows credentials store, or a data directory specific to the script.
  3. The script currently stores the LAST_VERSION_CHECKED in a local file. There may be value in looking at the previous review tickets instead to see if a new ticket needs to be created.

Additional Notes for PowerShell

There were a few details I skipped over in the example snippets above:

  1. .NET has built-in support for semver objects. Just make sure you coerce semver format strings, like this:

    $ver = [System.Version]"12.4.5"
    $ver
    ($ver | get-member).TypeName[0]
    Write-Host "MAJOR is $($ver.MAJOR), MINOR is $($ver.MINOR) FIX is $($ver.BUILD)"
    ($ver.ToString() | get-member).TypeName[0]
    Write-Host $ver
    

    Notice that the field I have previously refereed to as “fix”, is called “BUILD” in .NET (a.k.a “Patch” in the semvar 2.0 documentation).

    This means extracting the values of MAJOR, MINOR, and BUILD needed to download the RELEASE_NOTES does not need us to cut slices from a string (like we did for the dash shell), because the MAJOR, MINOR, and BUILD fields can be referenced directly. For example:

    $RELEASE_NOTES="https://www.papercut.com/products/$PRODUCT/release-history/$($CURRENT_RELEASE.MAJOR)-$($CURRENT_RELEASE.MINOR)/#v$($CURRENT_RELEASE.MAJOR)-$($CURRENT_RELEASE.MINOR)-$($CURRENT_RELEASE.BUILD)"
    
  2. You can store and retrieve PowerShell objects using the Export-Clixml and Import-Clixml. Again, some script fragments can help understand how they work:

    [System.Version]"12.4.5" | Export-Clixml -path "c:\tmp\myVersionRecord.xml"
    Get-Content -raw -path "c:\tmp\myVersionRecord.xml"
    Import-Clixml -path "c:\tmp\myVersionRecord.xml"
    Import-Clixml -path "c:\tmp\myVersionRecord.xml" | Get-Member
    

Revisit the first two posts in this series:

  1. Automate your PaperCut MF upgrade review process - Alec shows you how to discover which version of PaperCut MF is currently running on your server
  2. What’s the latest and greatest release of PaperCut MF? - Alec explains how to identify the most current PaperCut MF release version available