Renewing Our Open Source Commitment
Tags: opensource, node, tutorial
Published: 2019-10-15 15:39:49

## Motivation

Cascade Energy is an engineering services company, focused on helping industrial customers increase their energy efficiency. The software team, of which I am a part, is a small group within that company, responsible for the development, operations, and security of energy management software. Our team resources are limited, and so we make extensive use of open source libraries to increase the value we can deliver.

Over the years, the team, through its various incarnations, has also published a number of open source projects (see our past [public projects](https://github.com/CascadeEnergy?type=public)), but the efforts had decreased over time. (As it turns out, many of our earlier contributions are less relevant now as the ecosystem itself has evolved.) Recently, however, we were revisiting the Cascade Energy core values (_Do the Right Thing_, _Put Others First_, _Seek Shared Success_, _Learn Constantly_, and _Be Industrious_). We considered how much value we get from the technology community of which we are a part, and we were inspired to redouble our efforts to give back. To crystallize our thinking into action, we initiated an ongoing series of team meetings oriented around "outreach" of all kinds, including meetups and conferences, blog posts, open source, and even hosting interns.

As a result of our deliberate attention, we have tangibly increased our own engagement level in these areas, all of which are worthy of their own write-ups. This article, in particular, is about our concrete efforts toward rekindling our open source efforts.

## First Things First

Given how much time had passed since our previous efforts, we did some preliminary groundwork to make sure company leadership understood and supported our renewed drive to publish open source. As we had hoped, they were completely supportive of our efforts, but it was important for us to verify that.

To minimize the chances of accidentally publishing something that shouldn't be, and to emphasize the difference between public and private, we decided to create separate "orgs" in `github.com` and `npmjs.com`, distinct from the existing orgs that hold our proprietary work. (This may also make it more straightforward to include outside maintainers, if that were desired in the future.) We picked a name to publish under, "Cascade Energy Labs", and cleared that with Marketing and Legal.


## The Set Up

### GitHub

Everyone on the team already has a GitHub account tied to their work email. So, once signed in, I found the tiny `+` drop-down in the top bar, and clicked "New Organization".
* For "Organization name" I entered `Cascade Energy Labs` (which generated an org URL of `https://github.com/cascade-energy-labs`).
* For "Choose a subscription" I selected `Team For Open Source:  $0 per month` (being thankful how supportive of open source these collaboration platforms are).
* For "Billing email" I entered the team-lead's email address
* For "This organization belongs to" I selected `A business or institution` and entered `Cascade Energy, Inc.`

Once created, I invited the rest of the team to the new org (via their email addresses). And after they accepted the invitations, I set each of them to have a role of "Owner" via the "Change role" option, under the gear menu for each person in the "People" tab of the org.

> Note: this is also the place to verify that all the members have 2FA enabled for their sign-in. If, as we do, you want to *enforce* that for everyone in the org, go to the "Settings" page for the org, go to the "Security" section, and select "Require two-factor authentication for everyone".)

With this new org, we saw a great opportunity to explore some of the new features offered by GitHub, namely "GitHub Actions" and "GitHub Package Registry", and so I applied for the public beta of both of those programs. (We received confirmation of acceptance into both of them about a week later.) Finally, I made sure a couple of GitHub Apps were installed for the org, namely "Dependabot" and "Pull Panda".

### NPM

Team members also all have an NPM account tied to their work email. I clicked to `+` next to Organizations in the left bar:
* For "Name" I entered `cascade-energy-labs`
* For the "Unlimited public packages / Free" option I clicked the `Create` button (again being thankful of open source support).

I then invited the rest of the team via their email addresses. After they accepted the invitations, I set each of them as an "owner" of the org.

To enable automated package publishing, I:
* (through our IT department) created a special email list alias (that includes the team members as recipients)
* used it to create a "bot" account for our org (saving the password in a secure location accessible by the team)
* created a "publish" token for the account (also saving the token in a secure location)

## The First Project

Given the likelihood of false starts and missteps when establishing new patterns, I decided to start off our new org with a toy project that would let us focus on the infrastructure first. After much consideration, I finally came up with (wait for it...) "Hello World". And, since automation in software deployment has become the norm in our industry, the rest of this section describes exactly how I configured that.

Creating a new project in GitHub is incredibly easy. Under the Repositories page for the org, I just clicked the "New" button, made sure the "Owner" was shown as `cascade-energy-labs`, and typed in the name `hello-world` (as well as a helpful "Description"). I made sure the "Public" box was checked (enforced for you when your org is Open Source), and also selected "Initialize this repository with a README". Finally, I opted to "Add .gitignore" for `Node`, and also opted to "Add a license" of `MIT`. Then I clicked the big green "Create repository" button, and [there it was](https://github.com/cascade-energy-labs/hello-world)!

> Note: The selection of an open source license has many ramifications, far too many to address here. A web search on "open source licenses overview" will turn up countless resources to guide you.

Since Dependabot is enabled, I went to the "Security" tab for the repo, and enabled "Automated security fixes". (This will automatically generate pull requests for package updates related to known security vulnerabilities.) Also, since I know I want to publish to NPM, I went to the "Settings" tab for the repo, clicked the "Secrets" menu, and added a secret named `npm_token` (the exact name is important) with the value of the NPM "publish" token that I had saved off up above.

### GitHub Actions 

A new feature of GitHub (still in beta testing) is [GitHub Actions](https://github.com/features/actions). This is a mechanism that allows creating continuous integration (CI) and other workflows from scripts that will automatically execute on your behalf, based on various events.  Although you can write your own workflows from scratch, there is a growing library of [canned workflows](https://github.com/actions) that cover many common use cases.

In my case, I started with [Node CI](https://github.com/actions/starter-workflows/blob/master/ci/node.js.yml) (which will build and test your project on every push, in every branch).  Once our org was accepted into the beta program, adding the first action to a repo was incredibly simple.  In the repo page, I went to the "Actions" tab, and under the "Popular continuous integration workflows" found the "Node.js" card. I clicked "Set up this workflow", and instantly had a pre-filled YML file in front of me, ready to commit. (The commit process via the web interface is straightforward - I was presented with the choice to either commit directly to master, or to create a new branch to commit to while automatically starting a PR.)

Including additional workflows is just as simple, by clicking the "New workflow" button in the Actions screen. Using this, I added the [Node.js Package](https://github.com/actions/starter-workflows/blob/master/ci/npm-publish.yml) workflow to the repo.  To get it to work correctly, I *did* have to make a couple of modifications to the default file:
* for the `publish-npm` job, I needed the `--access public` option on the `npm publish` command (otherwise NPM tries to create it as a "private" package, which is unsupported under the "Free" option).
* also for the `publish-npm` job, I verified `NODE_AUTH_TOKEN: ${{secrets.npm_token}}` - the name should match the secret added when you created the repo above.
* for the `publish-gpr` job, I needed `scope: '@cascade-energy-labs'` instead of the canned `scope: '@your-github-username'`.

The "Node.js Package" workflow, by default, is triggered on a release action, and publishes to both GPR (see below) and NPM. So, from the [releases](https://github.com/cascade-energy-labs/hello-world/releases) page of my repo I clicked the "Draft a new release" button, and [watched the actions run](https://github.com/cascade-energy-labs/hello-world/actions). Several minutes later, my package [appeared in NPM](https://www.npmjs.com/package/@cascade-energy-labs/hello-world) and [also in GPR](https://github.com/cascade-energy-labs/hello-world/packages).

> Note: Repo workflows are stored as files in your code repository; any `.yml` file in `.github/workflows` will be treated as one. And, while various versions of these files may exist in other branches, only the version in the "default" branch (typically `master`) will actually be applied to the repo as a whole (including all branches). You can add and edit files here directly as well (as an alternative to using the "New workflow" UI), which allows you to create custom workflows, and also make modifications to canned workflows. Given that the feature is still in beta, editing [might be needed](https://github.com/actions/starter-workflows/pull/129) from time to time.


### GitHub Package Registry (GPR)

Another new feature of GitHub (also in beta testing) is [GitHub Package Registry](https://github.com/features/package-registry) (also known as "GPR").  This functions as a storage-and-delivery service for code packages (similar to, e.g., NPM and Maven Central).

To publish a Node project to GPR, I used the same `npm publish` command as when publishing to the central NPM repository, but configured with a different registry URL and explicitly specified scope. (Those differences can be seen in the "Node.js Package" workflow referenced above.) Although I used GitHub Actions to do the publishing, executing it from a command line would be very similar (with the changes being made in the `.npmrc` file directly).

I published to *both* GPR and NPM, since `npm` tools make it easier to pull from the default NPM registry than from other places. But if I had *only* published on GPR, or if GPR was preferred as a source, a consumer of my Node package would simply need to set an entry in their `.npmrc` file tied to my package's scope, e.g., `@cascade-energy-labs:registry=https://npm.pkg.github.com/`; then, `npm install` would download from there instead.

## Going Forward

We wanted to make sure we were set up properly for our renewed efforts. (Sometimes the first steps are the hardest.) And now that the groundwork is laid, we, as a team, have identified several real projects that we'd like to share with the community in the coming months. There is some effort needed to make them "publishable" (like removing hard-coded idiosyncrasies that are tied to our specific environment). And that effort has to be squeezed in between our regular work tasks. But it's something we're excited about doing!

So, what about you?  What has inspired you to enter (or re-enter) the world of open source? I'd like to hear your story.  Did our story make you think of other things? Please let me know in the comments!