Powering a Website Publishing workflow with Forestry CMS and Aerobatic
At Aerobatic we are big proponents of treating content (markdown, images, etc.) with the same special care and feeding that we demand for our source code. Namely that it lives in Git where it benefits from all the great stuff we developers have come to rely upon — branching, pull requests, history, auditability, forks, and so on, not to mention peace of mind. For someone that spends their days with a code editor and terminal window open the process of editing markdown files and committing to git is a totally natural workflow.
But for the majority of marketers, technical writers, editors, and other content contributors, giving up a WordPress style admin interface for a plain text editor is often a non-starter. The lack of a smooth editing experience for non-developers has been the biggest impediment for wider spread adoption of static site generators as a replacement to traditional CMSes such as WordPress.
Fortunately a new breed of CMS tools are emerging that bridge the gap — providing a friendly interface for content editors but utilizing Git as the underlying storage repository rather than a proprietary database. As we'll see, this enables a universal deployment pipeline where changes from developers and changes from content contributors follow the same flow to production.
In this blog post we'll walk through how to accomplish this flow using Forestry.io as the CMS, Hugo as the static site generator, GitHub, AppVeyor for CI, and of course Aerobatic for hosting. You can easily substitute Bitbucket for GitHub and most any CI provider for AppVeyor.
Forestry is a CMS specifically designed for managing content for Jekyll and Hugo sites. It reads and writes directly from/to your GitHub or Bitbucket repository. It has built-in preview functionality that runs the specified static generator and provides a URL to the actual built site with the latest local changes. This is a great way to visualize how changes will look in the actual site before publishing to the underlying git repo. While Forestry can deploy directly to a hosting provider, we'd like all changes (both from developers and editors) to flow through the same CI build process, so we'll configure it to only publish to the repo.
For this walkthrough we'll use a demonstration repo hosted on GitHub.
- Fork the demo repo from https://github.com/aerobatic/forestry-cms-demo
- Clone the repo locally
- From the root of the repo, run
aero create. The CLI will report back the URL for your website which you will need in the next section.
- Now login to Forestry.io (you can use your GitHub credentials if you like)
- Click the Setup Site button and select Import Existing Site
- In the Generator drop down, select "Hugo" and leave the Version as-is
- Now select GitHub as the repository provider and Public Repos
- In the Choose Repository screen select your-github-user/forestry-cms-demo and leave branch as master
- On the Site Settings screen set the name to something like aerobatic-forestry-demo and the Url to the value provided from the
aero createcommand run in step 3 from the previous section. It should look something like
- On the Hosting Info screen select Commit to source repo only
- Finally click Save Changes
Forestry is now linked to the GitHub repo. You can add and update pages, menus, and other content using their visual editing controls. If you click on the "Sample blog post" you'll notice a big green Publish button that will push a commit with the latest changes to the repository. In the next step we will configure the CI provider to build the changes and deploy to Aerobatic.
The Preview button below the Publish button will launch the rendered site in a new browser window so you can see exactly how the changes will look once live. There is also the ability to upload images. Finally the View Site button in the header will launch the live site URL that we configured in step 6 above.
See the Forestry documentation to learn more about how it works and what it is capable of.
The final piece of the puzzle is setting up a CI provider to automatically build and deploy the site whenever commits are pushed to GitHub. As mentioned earlier, for this demo we are using AppVeyor(which is free for open-source projects), but you can use your favorite CI service just as easily.
The process for setting up any CI provider is roughly:
- Log into their dashboard
- Create a new CI project
- Bind it to the desired Git repo
- Add a build manifest to your repo, i.e.
- Create an environment variable named
AEROBATIC_API_KEYwhose value you can retrieve by running the
aero apikeyCLI command locally.
The demo repo already has an appveyor.yml file that does the following:
- Download and install Hugo
npm installto install the the aerobatic-cli
- Configure the
node_modulesdirectory to be cached to speed up subsequent builds
npm run deployto deploy the built site from the
publicdirectory (where Hugo write the output) to Aerobatic. The
package.jsonsimply runs the
aero deploycommand, but we put it in an npm script in order to resolve to the
aerocommand in the
deploycommand relies upon the
AEROBATIC_API_KEYenvironment variable set in step 5 above.
Now our end to end publishing toolchain is all in place. Go ahead and try updating the title or body of a blog post back in Forestry and click the Publish button. Visit the AppVeyor dashboard and within seconds you should see a new build triggered. The build page for the demo site is at https://ci.appveyor.com/project/dvonlehman/forestry-cms-demo. If the build completes with a green status, that means it's been successfully deployed to Aerobatic.
Now whenever a change is pushed to the repo, whether a stylesheet update by a developer, or a blog post update from a marketer, the same build pipeline is run to integrate the changes and deploy them live.
This setup works great for small teams where everyone is allowed to deploy straight to production. But many teams want some controls in place where changes are first deployed to a test environment before being promoted to production. This is where Aerobatic deploy stages come into play.
Back in the Forestry setup, we selected the "master" branch. However a different branch such as "preview" could have been selected. Then in the CI build instructions, the "preview" branch would be configured to deploy to the preview stage rather than production. This is done by passing the
--stage option to the CLI, i.e.
aero deploy -d public --stage preview. The preview URL is a private instance where reviewers and other stakeholders can see and approve changes prior to going live to production. You can even utilize the password-protect plugin to require a password for the preview stage ensuring only authorized people can access it.
The process for promoting to production then becomes:
- Submit a pull request from preview branch to master
- Approver reviews and either requests changes or approves
- Pull request is merged to master
- A CI build is triggered that build and deploys the master branch to production
While pull requests are likely a new concept for most non-developers, the basic idea of an approval workflow is well understood. Admittedly this notion of marketers and content editors utilizing Git is not widely practiced yet, but hopefully as services like Forestry continue to evolve, they will provide friendly abstractions around things like pull requests that makes taking advantage of these powerful tools increasingly accessible to developers and non-developers alike.
So that's our end to end publishing workflow. While there are a few moving parts involved, once setup the entire system works quite reliably. Both the code and content happily reside together in the same repo and all changes, both those initiated by developers and content editors, flows through a common deployment (and approval) pipeline. If you're a developer and have been wanting to switch from a CMS to a static site generator, but have been holding off because the marketing folks demand a GUI interface, check out Forestry.io and see if you can say goodbye to WordPress once and for all.