Stencil & CircleCI

Terence McDevitt

August 10, 2016

Stencil is a newly introduced framework that’s greatly improving the development process for BigCommerce stores. Developers are finding that Stencil is giving them powerful tools to quickly and easily make site improvements all without the need to spin up a dedicated BigCommerce development store or to push untested code into production.

While the speed and efficiencies gained by using Stencil certainly help individual developers, it can make things a little more challenging when it comes to ensuring that a team of developers is collaborating at the same level. Introducing a continuous integration service like CircleCI into your Stencil project can help you better understand the state of your code and identify any bottlenecks in your build and deploy process.

A Case for Continuous Integration

At Blue Fish, we’ve been using continuous integration (CI) as a core part of our enterprise development projects for nearly a decade. When we’re working on large projects with team members distributed around the globe, it’s important for all of us to quickly know when something blocks our development process. Automated CI tools help to provide this proactive visibility into the code health of our projects.

In the past, development teams would typically associate a concept like CI with back-end development. Front-end developers would crank out markup, CSS and JavaScript all backed by server-side code built and managed with processes like CI. Front-end development “tools” were few and far between and teams wouldn’t necessarily have insight into the quality of the code being developed.

In the last few years, however, we’ve started to see many of the traditional back-end development tools and processes make their way into front-end aspects of a project. This is a welcome change, for sure, as the promise of incorporating such tools into your development lifecycle is to ensure consistency and quality of code.

BigCommerce understands this shift and this is incredibly evident with their latest development and theming framework – Stencil. The BigCommerce Stencil framework is a collection of widely-used development libraries that are intended to make store development quicker and easier. For more detailed information about Stencil, head on over to the Stencil Overview.

One of the core features of Stencil is the ability to package up a theme and distribute it out to stores on the BigCommerce platform. To do this, BigCommerce takes advantage of Node.js and a handful of other tools. In order to ensure that a Stencil theme is valid, a number of quality checks are performed on the theme assets during the packaging process. This gives developers a bit of a heads up on potential issues before letting them actually deploy out to a live store.

After developing a number of Stencil-based projects, we realized that we wanted to have the Stencil packaging process automated such that our developers would immediately know if their commits were going to cause problems. Enter CircleCI.

What’s CircleCI?

CircleCI is a cloud-based continuous integration service that supports a variety of development languages, testing frameworks and deployment targets. Simply create an account, tell CircleCI where your code is and it will, for the most part, figure out the rest.

Once you’ve stepped through initial configuration, CircleCI will start to build your code in what it calls “containers”. The containers are essentially small servers that are spun up at build time. To start, everyone gets a single container tied to their account. This means that only one build can happen per project at a time for your organization. If you need to scale up and support building multiple projects in a concurrent manner, you can increase the number of containers (this is where CircleCI starts to make their money as the first container is free of charge).

Since CircleCI supports Node.js, it implicitly supports building and packaging a BigCommerce Stencil project. With some minimal, upfront configuration you can easily get your Stencil project up and running with CircleCI.

Getting Started

Getting your Stencil project “enabled” for CircleCI is easy:

Set up a CircleCI account

Of course, before you can build anything, you’ll want to establish an account with CircleCI. Your CircleCI account is directly tied to your GitHub or Bitbucket account. When you sign up for CircleCI, it will prompt you for your repository service credentials and automatically connect your CircleCI account with those credentials. There’s no need to create a separate username/password with CircleCI.

Once you’ve indicated your repository service of choice and provided credentials, CircleCI will be “connected” to all of your repositories. In Bitbucket, you can see this integration in the “OAuth Integrated Applications” section under settings.

Bitbucket or GitHub?

As of now, CircleCI only supports git repositories hosted with GitHub or Bitbucket. Technically, the Bitbucket integration is in beta but we’ve found that all of the features we need are already included with this integration and work quite well. If you use Bitbucket, simply sign up to be part of CircleCI’s beta program. Once approved, you’ll authenticate with your Bitbucket credentials and will be good to go.

After successfully connecting CircleCI, you’ll be able to specify which projects should be built automatically. CircleCI will display a list of all repositories associated with your account. After selecting a repo, CircleCI will create a project for that repository.

After creating a project, CircleCI will automatically look for commits on all branches of that repository. If a commit is found, a build will be automatically kicked off and displayed in the CircleCI dashboard.

Prepping your BigCommerce project

CircleCI will do everything it can do determine your project’s technology and corresponding dependencies. For the most part, this actually works great. However, we found that we needed to give CircleCI a bit of additional information about Stencil projects. The good news is that all of this is dead simple and involves simply creating a file called “circle.yml” at the root of your project’s source repository.

Here’s a breakdown of what we added to the “circle.yml” file and why:

“machine/node/version:” – Stencil requires a specific version of node in order to be able to package your theme properly. By default, CircleCI will attempt to use the latest stable version of node unless you tell it otherwise. In our case, we’re explicitly using 4.1.2

“machine/node/timezone:” – This will set the timezone for the CircleCI container that’s spun up at the start of a build. If you’re timestamping anything in your code as part of your Stencil bundle process, you’ll want this timezone to be correct

“dependencies/pre:” – Allows us to execute commands in the container prior to running the build. For Stencil projects, you’ll want to make sure the Stencil Command Line Interface (CLI) is installed prior to packaging

“dependencies/post:” – Any actions to be performed once the build process has been completed. The OOTB Stencil Node configuration was including a module that was causing issues. For details, see the section on “Hapi“

“general/build_dir:” – A critical setting for a Stencil project! This instructs CircleCI to use your theme’s directory as the starting point for the build. In our case, this is usually a sub-folder under the project’s root folder. So, we’ll just name that folder here

“test/override:” – This setting is the magic in this entire process. It’s here where we’ll run the “stencil bundle” task which indirectly calls ESLint and other sub-tasks as part of the packaging process. You’ll probably notice that this is considered a test and is not actually a build step. There are two reasons for this – 1) There is no true “build” step for Stencil projects. Nothing gets compiled or built outside of the bundle step. 2) Making this a test will ensure that if there’s a failure, CircleCI will treat it as a test failure and will ultimately fail the overall build

Here’s our resulting “circle.yml” file (ensure that you substitute in your project name and Stencil theme folder name accordingly):

If you commit the above “circle.yml” to your source repository and you’ve configured CircleCI to use that project’s repository, you should see a build kick off in the CircleCI Dashboard. If your build fails, check out “Potential Gotchas”

Gaining Better Visibility

At Blue Fish, we like to know immediately when a build fails – so, we use CircleCI’s integration with HipChat to send build result notifications to designated HipChat rooms. This way, our developers don’t need to log into the CircleCI dashboard in order to know if all is good. Of course, if something fails, they can drill into CircleCI to get details of what commit broke the build.

Configuring HipChat notifications with CircleCI is easy. Simply navigate to your project’s settings in CircleCI and select “Chat Notifications”. Enter the HipChat room into which you’d like notifications to be sent, as well as your HipChat notifications API token. Hit “Save” and you’re all set up.

Any time a build fails, your team will know about it (assuming they’re actually hanging out in the build notifications HipChat room). CircleCI will give details on the commit hash as well as the description provided with that commit.

Unfortunately, CircleCI doesn’t really give much else in terms of context when it notifies a room in HipChat. So, for details, your team will need to click on the links within the HipChat notification. This will take them to the actual build results in CircleCI, which should give them what they need to diagnose what went wrong.

Potential Gotchas

If only we lived in a world where things “just worked” the first time… While configuring CircleCI itself isn’t challenging, you may find yourself struggling to get your code prepped for a Stencil bundle. Here are some things that tripped us up and what we did to solve them.

ESLint

BigCommerce uses ESLint as part of the bundling/packaging process. A linting tool like ESLint can help to make sure that your code is structured in a manner that’s consistent and follows specified best practices. The beauty of ESLint is that it’s both pluggable and configurable. If you want to enforce coding standards that are unique to your organization, you can build a module and configure ESLint to apply that module when analyzing JavaScript. Additionally, ESLint is highly configurable, allowing teams to fine tune the rules ESLint uses when it attempts to analyze code.

While BigCommerce’s intent of using ESLint for Stencil themes is almost certainly to ensure that theme developers are adhering to their standards, we found that some of the OOTB ESLint rules with Stencil are too strict. As a result, we ended up implementing our own ESLint configuration that loosened some of these constraints.

We specifically changed the following:

“extends:” – Out of the Box, Stencil’s ESLint configuration extends “airbnb/base”. The configuration was incredibly hard on our custom JavaScript functions. So, we ended up changing this to “eslint:recommended”

“rules/indent:” – While we didn’t want to use the “airbnb/base” rules for most ESLint configuration, we did want to use it when it came to indentation of our code. So, we overrode the recommended ESLint indentation rules

To make similar changes for your Stencil project, you’ll need to update the “.eslintrc” file at the root folder of your Stencil theme. Here’s a copy of our final “.eslintrc” file:

Hapi

Despite it’s name, the Hapi Node module actually made us quite sad… Somewhere in the BigCommerce Stencil dependency tree, a module known as “Hapi.js” is referenced. The module itself is perfectly fine, as far as we can tell. However, when it’s included in a project that’s going to be built and tested on CircleCI, any Node tests will fail. It turns out that this module has its own set of unit tests that are executed whenever the Stencil task is executed. One of those unit tests is to test the deletion of a folder that the test believes to be a file. On MacOS, this test executes without problems. However, in Ubuntu (used by CircleCI) this very test fails with the following: “Error: EISDIR, read”.

After several hours of debugging, we ended up deciding that simply getting rid of the folder being deleted was easier than trying to actually fix the problem. To do this, we simply added a “post” script in our project’s “circle.yml” file that deletes this file prior to the Stencil bundle task (ensure that you substitute in your project name and Stencil theme folder name accordingly):

So, What’s Next?

We feel like we’ve only started to scratch the surface of what’s possible with Stencil and tools like CircleCI. While we’ve got a pretty good process in place for Stencil projects, there are a few things we’d love to see. Some of these are likely possible and we’ve just not had a chance to get there yet, while others may rely on some additional functionality provided in the Stencil framework:

“Builds Now, Deployments Later” – The process described above is great for understanding if someone’s going to break your Stencil bundle before you actually try to push it out to a store. However, this process does not actually deploy anything. Ideally, if a build is successful, we’d take advantage of CircleCI’s deployment capabilities and automatically push the resulting Stencil bundle out to a target development BigCommerce store. As of now, the only way to actually deploy and apply a Stencil bundled theme is via the store’s admin console. We’ve talked a bit with BigCommerce about a remote deployment feature and it is on their longer-term roadmap.

“Additional Unit Tests” – There’s nothing really stopping us from leveraging Node unit test services like Mocha to test out our site’s JavaScript functions. While we didn’t describe the mechanics in this post it is something we’re actively working to integrate into this overall process.

“No Management of Finished Bundle” – As stated above, this CI process is really about ensuring quality. It’s not (yet) about taking an artifact and actually deploying it or storing it somewhere. Ideally, upon a successful build, we’d like to take the built bundle and drop it somewhere so it’s a snapshot that we can easily grab at a later time, if needed. CircleCI will remove a build container after 30 minutes, so if you don’t manage to get the resulting Stencil bundle, you’ll need to either build again through CircleCI or build locally. Technically, CircleCI will allow us to push the bundle to a remote location, we just haven’t spent time on the “right” way to do this relative to our internal processes. It is something that’s in our near-term plans to figure out.

That’s it for now. Of course, if you need any help implementing your BigCommerce site (Stencil or not) or if you’ve got any questions for us, feel free to drop us a line: