At the 2018 OU Conference in Anaheim California, I mentioned that I am using GIT to push XSL changes to both a testing and development XSL locations. Some folks expressed interest in this setup and wanted to know more about it. This post will hopefully answer some questions and help you determine what setup will work best for you.

XSL Location

Site Drop Down List

All of our production XSL sits on its own site called “XSL”, our development XSL sits in two sites called “XSL-dev” and “XSL-Jesse”. Start with one development instance if you are going to use this setup, for the write-up below I will talk about “XSL-dev”.

The PCFs that are in the sites “arts”, “extended”, “mcb”, and “www” reference the “XSL” site for their XSL. The reason these are broken up into their own sites is that they are subdomains. The fewer sites in OU Campus the better as it makes managing the system a whole lot easier. But that’s a different post.

Connecting a PCF to the XSL

The second line of every PCF file references the path the to XSL location including an optional attribute for the site:

<?pcf-stylesheet site="XSL" path="/xsl/interior-rows.xsl" title="Interior Page" extension="aspx" ?>

If you don’t include the site attribute, the XSL parser assumes the site the PCF exists on. Many installations don’t include this attribute so many folks don’t know about it. By single sourcing your XSL, it doesn’t need to be duplicated across multiple sites and is managed in one place.

The “XSL-dev” site contains the same files as the “XSL” site with development modifications. With my personal XSL development workflow, I may modify multiple XSL templates at a time and don’t want to copy files to make changes (e.g. common-1.xsl). I also make changes via trial and error so I expect to throw errors and can’t make these changes on production XSL. That’s where the “XSL-dev” site comes in. Let’s say I’m making a new snippet and I want to build and test it out. I will create a PCF page and change the site to “XSL-dev”:

<?pcf-stylesheet site="XSL-dev" path="/xsl/interior-rows.xsl" title="Interior Page" extension="aspx" ?>

The path stays the same since the files are identical other than the modifications I am about to make, or am in the process of making. I can now modify all the XSL files in “XSL-dev” without risk of breaking something in production.

Writing XSL outside of OU Campus using WebDAV

XSL is written outside of OU Campus using Dreamweaver (put the pitchfork down and keep reading) and published to OU Campus. You can use whatever application or IDE (Integrated Development Environment) you would like as long as it allows for a WebDAV connection. Ideally, it also has a keyboard shortcut for publishing.

In the site settings for your XSL site, navigate down to “Optional Features” and make sure “WebDAV” is checked.

Optional Features - WebDAV

Next, go to “Setup”/”Users” and find your username. Scroll down to “Restrictions” and make sure the “Allow WebDAV Access” button is checked. A textbox below will appear with the “WebDAV URL”, copy that.

User Restrictions

In your IDE set up a site/folder where your XSL will be saved locally. Use the WebDAV URL as the remote/publish location. You will also need your OU Campus username, password, and the site name. Below is an example of this setup using Dreamweaver.

Site setup in Dreamweaver

Append the site to the end of the URL and fill out your username and password. Start with the production version of your XSL. Now you should be able to download all of your XSL to your local machine using your IDE. Initialize a new GIT repository and push it to your favorite GIT server where you also have created a GIT Repository.

Version Control using GIT

Each site has its own GIT repo associated with it. We are using Bitbucket to host them but you can use GitLab, GitHub or any other GIT server. We have added the prefix of OMNI to the start of our repositories so we can identify them.

Bitbucket Repo List

“OMNI XSL-Dev” and “OMNI XSL-Jesse” repositories are forks of the “OMNI XSL” repository which means that “OMNI XSL” needs to be created and then forked for the number of development instances that you want to have. After the “OMNI XSL repository is set up, create a fork of it which will become your development repo, in this example, it is the “OMNI XSL-Dev” repository. Clone that repository onto your local machine. You now have two repositories on your local machine, one for development and one for production. The screenshot below is from GitKraken, but again, use whatever GIT interface (or terminal) you are comfortable with:

Git Kraken Repos

In your IDE setup a second site/folder for your Development repository with WebDAV that points to your OU Campus development site, in this example, “XSL-dev”.

Now you have both production and development XSL on your local machine, source controlled with GIT and connected to OU Campus via WebDAV. One of the reasons I separate out development changes into its own repository is that I currently work on many branches at one time some that will never see production. By having my own set of XSL templates I can keep them as messy or clean as I want. Below is every unmerged branch that exists in “OMNI JESSE XSL”:

Git Branch Branches

That might drive my coworkers crazy, it might drive you crazy! Compare that to the “OMNI XSL” unmerged branches:

Master Unmerged Changes

It is also harder to accidentally do a pull request with a different repository than accidentally merge a feature branch into the master.

Full workflow

Here is an example of a full workflow from development to production:

  1. Create a new PCF file and change the site to “XSL-dev”.
  2. Check out a new branch in “OMNI XSL-Dev”.
  3. In your IDE open “XSL-dev” and develop something really cool.
    • You will probably throw all sorts of XSL errors, which is why we are in development.
    • Make a change, publish to OU Campus, preview page, repeat. This is where the keyboard shortcut comes in handy. Publishing to see changes is usually really quick, even though it may sound clunky.
  4. Commit your finished changes to your “XSL-dev” repository. Push the branch you created in step 2 to Bitbucket.
  5. In Bitbucket do a pull request into the “OMNI XSL” repository from your feature branch.
    • If you have a team, do a code review!
    • Reject changes if needed and go back to step 3 and continue developing.
    • If everything looks good, continue to step 6.
  6. Accept Pull Request in production repository.
  7. Pull changes from pull request in OMNI XSL repository onto your local machine.
  8. Publish the production XSL changes to the production XSL OU Campus site.
  9. Go back to Bitbucket and sync your development copy back with master.
  10. Switch to your master branch in “XSL-dev” and pull the local copy. Delete your feature branch that has been merged.
  11. Change the site back to “XSL” from the PCF from step 1. Or delete the file if you no longer need it. Or forget about it as I often do!

I usually forget to do steps 9 & 10 which isn’t a problem as long as it happens every once and a while.

You know what would be super cool? Use a GIT hook to publish the changes from OMNI XSL to OmniUpdate!

90% of the commits to our XSL happen this way, but every once in a while an emergency hotfix does get committed straight to the master bypassing the workflow. However, this change is always committed and distributed down to the forked repositories. So it’s not as strict as it looks!

Hotfix Change

Final thoughts

That is the workflow that we use at the University of Northern Colorado uses and it might not be appropriate for all users. The workflow makes it look more intense than what it really is. Feel free to pick and choose parts of it that will work with your organization’s business processes. It might be a good idea to use your sandbox instance from OUTC to test this out before going into production.

The versioning for dev and production doesn’t have to be in their own sites. Within your “XSL” site (or even default site) you could have a folder for production and testing and change the path attribute rather than the site attribute. This is just the way I set it up in the beginning and it works for me.

As always, use caution and test everything.