DEV Community

Cover image for Publish/Update NPM packages with GitHub Actions
Carl-W
Carl-W

Posted on

Publish/Update NPM packages with GitHub Actions

Ever had an NPM package that never get's updated even though you make changes from time to time. I do! which I talked about in a previous post: cross-platform-react-native-scroll-picker-component. It's time to make my life just slightly easier and automate the publish step with Github Actions.

Since the release of GitHub Actions everyone I know have been raving about them, so In an attempt to learn a little bit, and solve a problem I have, I thought I could try it out :)

oh and here's the official GitHub Actions docs: GH Actions Docs

Goal

It's important to know what you want to do, before starting configuring (or.. doing anything, really!). For me it's going to be something quite simple, but very useful.

This is my starting point and what I want to achieve:

  1. I have an open source package which is published to NPM
  2. When I make a new "official" release on Github I want to update / re-publish this package, so my updates go live.

To do this manually we need to login in and publish/re-publish through the NPM CLI, something like this:



# Authenticating with npm
$ npm login

# Publish the package
$ npm publish


Enter fullscreen mode Exit fullscreen mode

I know, I know, it's not a massive amount of work to do those two steps each time I want to push out an update to the package, but we are learning something here.

Prior to GitHub Actions in order to automate this task, I would have needed to involve a third party CI/CD solution, and on top, it's free.

So let's get started with the config.

Preparing our repo to use GitHub Actions

The execution chains or jobs which we want to run inside of our GitHub Actions are called workflows.

So GitHub will look inside .github/workflows for workflows / execution chains so let's make a .github folder inside of our root, this folder is common if there are special configurations to the repository, like code owners. Further we need to make a folder inside our .github folder called workflows.

When all is done you'll have a a root/.github/workflows folder.

Like most CI/CD solutions GitHub Actions workflows are configured using a .yml file, and we need to put that that file into the workflow folder we created above. I named my yml-file npm-publish.yml and here's a badly made folder-tree to make it more clear.



---> root
|   ---> .github
|      ----> workflows
|          ----> npm-publish.yml // contains our workflows.
| ----> rest of app


Enter fullscreen mode Exit fullscreen mode

Configuring our workflow

So inside of our npm-publish.yml we are good to go configuring our workflow. I'll post the finished thing first and then I'll go through it step by step what it does.



name: Npm Publish

on:
  release:
    types: [published]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: actions/setup-node@v1
        with:
          node-version: 12
          registry-url: https://registry.npmjs.org/
      - run: yarn install
      - run: npm publish --access public
        env:
          NODE_AUTH_TOKEN: ${{secrets.NPM_AUTH_TOKEN}}


Enter fullscreen mode Exit fullscreen mode

Let's break it down



name: Npm Publish


Enter fullscreen mode Exit fullscreen mode

Giving the workflow a name, at the very top we give the encompassing workflow a name that makes sense to us, you are free to name it anything you'd like :)



on:
  release:
    types: [published]


Enter fullscreen mode Exit fullscreen mode

The on-keyword tells GitHub when the workflow is going to run, in this case I specify that I want it to run when there is a new release, and more specifically I want it when the release type is published. This is important and required because releases could also be updated or deleted. This makes sure that we run on release publish only.



jobs:
  build:
    runs-on: ubuntu-latest


Enter fullscreen mode Exit fullscreen mode

The jobs keyword tells our CI the different steps we want to execute.

In this case I want to build the project, on the latest version of Ubuntu, so that is specified as ubuntu-latest.

Further we need to define the steps within our job:



   steps:
      - uses: actions/checkout@v2
      - uses: actions/setup-node@v1
        with:
          node-version: 12
          registry-url: https://registry.npmjs.org/
      - run: yarn install
      - run: npm publish --access public


Enter fullscreen mode Exit fullscreen mode

Inside of our job we are now defining the steps, We already defined the operating system of our virtual machine / box, so we are at the same stage as when we run the project locally on our computer.

Well, in plain English, what do we do locally when we run a project like this?

Normally it would look something like this in our terminal:

1. Clone our project



$ git clone git:repo-address


Enter fullscreen mode Exit fullscreen mode

2. Install all packages / dependencies



$ yarn install


Enter fullscreen mode Exit fullscreen mode

3. do the publishing steps



$ npm login
$ npm Publish


Enter fullscreen mode Exit fullscreen mode

Locally we already have our development environment setup, we already have node, yarn, etc. But because we are essentially creating a new computer on Githubs servers running Ubuntu we need to be more specific, and that's what we are doing in the configuration file:

1. Clone the repo.



- uses: actions/checkout@v2


Enter fullscreen mode Exit fullscreen mode

2. Install node on a known working version, Specify what package registry we want to use.



    - uses: actions/setup-node@v1
        with:
          node-version: 12
          registry-url: https://registry.npmjs.org/


Enter fullscreen mode Exit fullscreen mode

3. Install dependencies



- run: yarn install


Enter fullscreen mode Exit fullscreen mode

4. Publish to NPM



- run: npm publish --access public


Enter fullscreen mode Exit fullscreen mode

5. Further since there is no human sitting and looking at the script to authenticate us by passing in username and password, we need to pass a pre-authenticated token to our node environment



        env:
          NODE_AUTH_TOKEN: ${{secrets.NPM_AUTH_TOKEN}}


Enter fullscreen mode Exit fullscreen mode

And that's our new Github Action workflow configuration all done 🎉

Hold on! you might say, what about that NPM Auth token thingy?

Let's get that configured next.

Configuring Auth tokens

As I described earlier we need a pre-authenticated token to pass into our node environment. This is the way we authenticate towards NPM, and it's not very complicated to setup.

Never put your token into the configuration file, it should be kept private

Note: I presume you have an account on npmjs.org if you are interested in following along.

Head on over to your account in npm and in the quick account menu press Auth Tokens

npm menu picture

Inside the Auth Token page you'll want to create a new Token.

create new token

You will then be prompted if you want to grant the token read and publish or just read, for the purpose in this case we need to have publishing rights, so read and publish it is.

npm permissions

After the token has been created copy it, and make sure you can keep it with you for a little while until we add it into our repository secrets.

Adding NPM token to our repository

Head over to your GitHub repository where your package exists and go to the settings page.

github settings menu

Inside of settings head on over to the secrets sub-page.

secret sub menu

Click Create a new Secret

new secret button

And in here you'll want to match the name of the token with what we wrote in our action configuration file.

Alt Text

In our case we named our secret variable reference NPM_AUTH_TOKEN and then you'll want to paste the token you got from NPM in the value field.

When everything is well and done we will have it added.

Alt Text

That's all we need for configuration, commit it, merge into master and let's try it out to see if it works.

Testing it out

So, to test our newly created workflow we need to make a new release (published), since that what we configured it to trigger on.

Alt Text

It does not really matter what you tag you choose for the release, but make sure the that the pre-release checkbox is not checked. And you bumped the version in package.json, NPM requires us to update the version when we publish changes.

When the release is done let's head on over to our repository's action tab and see if we have something running!

Alt Text

there we go, microphone drop.

End

If you like to visit the repo I've been working in it's available right here:

ugglr/react-native-value-picker

The package is available through NPM:

NPM: react-native-value-picker

And the creation of that package was part of a previous post right here:

DEV.to Cross platform react native scroll picker

Thanks for reading!

Top comments (5)

Collapse
 
unfor19 profile image
Meir Gabay • Edited

Great post, thank you for that.

Positive feedback - I think you meant "Configuring our Workflow" instead of "Action", I got a little bit confused when I started reading this, I thought you're talking about creating a GitHub Action. This mix up is repeated in this blog post, so you might want to change "Action" to "Workflow". Other than that, it's a great post

Collapse
 
ugglr profile image
Carl-W

Hey Meir! Thank you for the positive response! I think you are right I did not pick up on that the correct word for the execution chain (lack of a better word?) is called workflow XD I'll change it 🚀

Collapse
 
unfor19 profile image
Meir Gabay

Sure thing

Collapse
 
daviddalbusco profile image
David Dal Busco

I was literally thinking about it today, can't be a better timing!

Thank you for the share Carl-W 🙏

Collapse
 
ugglr profile image
Carl-W • Edited

Haha that's awesome, glad I could help! Thanks for reading and the positive feedback David 😁