Mastering GitHub packages like a pro
THE other day I got an email from GitHub informing me that I was granted access to GitHub Packages feature. It was the news I had been waiting for a while as I saw they started beta testing months ago. I really love the way GitHub aggregates code-related services inside the platform. Just imagine that you don’t need to think about where to store your libraries, Docker images, and other stuff! It can save tons of time, especially for small teams and pet projects. You just spend a few hours to set it up and then enjoy smooth cicd process. As you can see, I was super excited to have an access and decided to dive into this feature asap.
At Setronica we follow so-called Ecommerce-Driven-Development, which means that we trying to push e-commerce to the next level. Digital document exchange, marketplaces, complicated workflows — all these things lay on serious requirements on whole platform. We develop zero downtime, fault-tolerant, stable infrastructure in form of Kubernetes cluster. Backend components written in Java and NodeJS, frontend applications — React and Angular-based bundles run and create big platform which connects companies all around the world. We run hundreds of microservices in AWS cloud, so as you can see — GitHub packages might be the feature we can switch to, instead of supporting our internal registries.
In fact, GitHub Packages support different kinds of projects, for instance npm NodeJS packages (sick!), Ruby gem, Maven projects, NuGet packages for .NET and Docker registry. I believe this list will be expanded in the near future but now it already covers most interesting project types. In this article I want to cover npm and docker registries since I am doing frontend awesomeness and these two are the things I use every day.
Oh, one more thing. I found it really awesome: private packages for private repositories. Woah! You can play around with your small private pet project and nobody would know you became a master in making GitHub infrastructure work on 100%.
Hooray, let’s do this!
GitHub Tokens and Scopes
First things first. Let’s talk a bit about security.
We are going to publish our private packages. So you want to know how to access it outside, right? Instead of using your account password everywhere (don’t do it, I tell you), GitHub permission management relies on access tokens. You can generate as many tokens as you want. Each token describes a scope of the permissions you are allowed to do while using it. You can create and manage access tokens in your GitHub account by clicking on your logo in the right corner and then going to the settings > developer settings > personal access tokens. Or simply by navigating this url: https://github.com/settings/tokens
So what we need to do is to create two kinds of tokens. First one would have read:packages permissions so any kind of external system would be able to read packages from GitHub registry. And we need to supply the other one with write:packages permissions so we would be able to publish packages either by ourselves or by some cicd platform. In addition, we need to select whole repo scope to have access to our private repositories. Click on generate new token and select scope we discussed above.
Okay, we have done 80% of our work! Well, not exactly… Jokes aside, let’s go deeper.
Setting up Docker Registry
I tried different registries — TreeScale, Canister, Docker Hub, and all of them work the same. So if you are familiar with some Docker registry and how Docker works, there wouldn’t be any problem with GitHub. If not, I would suggest to try official documentation. Let’s assume we already have a DockerFile and now we want to publish it into GitHub registry.
This is quite typical Docker commands. I would like to draw your attention to a few things.
First of all, we don’t use our GitHub password! We use the token with write permissions instead and it allows us to be more flexible and more secured. We can generate tokens for various purposes — for manual usage, for cicd platforms and more.
Second thing I want to note here — look at the application path at the end of the docker image url. This name will be shown in the GitHub Packages registry and you can vary it if you need to create different image branches like release images, test images, whateveryouwant images. I just simply use application key as I want to show you a single docker image for single project. After doing these three simple steps, you would be able to see your image published in GitHub:
And if we click on it, we will fall into detailed view:
Aha! We have the image, so how to pull it? Easy!
Usually, some external system pulls our Docker images and we want to ensure our GitHub account is safe. So for login we use token with weak access rights. Now we can automate it with some cicd (personally, I use CircleCI for my pet projects) and focus only on writing the code.
Publishing into GitHub NPM Registry
One more thing. What if you want to try to write your own npm package? Or maybe your company has private projects and you want to split some code and reuse it across the repositories? No need to publish it into global npm registry! No need to set up local npm registry and maintain it by yourself! GitHub offers you own npm registry (private for private repositories).
Let’s say we have some package and want to publish it into GitHub registry. First of all, we need to tune our package.json a bit. There is a property called publishConfig does exactly what we want to achieve. It overrides registry we want to publish our package into. So let’s set it up:
That’s it? Well, as you can see, I use semantic-release library together with circleci, that’s why the version is 0.0.0-semantically-released. If I run release process, I would get some error:
We definitely forgot to authorize semantic-release to access our private repository… No worry, .npmrc to the rescue! .npmrc file in the package root folder is the way to configure npm for particular project. It may contain any overrides for global npm config. Our plan is to tell npm to store our package into GitHub registry and authorize circleci executor with appropriate token. This can be achieved by creating <app_root>/.npmrc file with such content:
Now we can merge changes into repository and see how semantic-release worker publishes our package:
And now our GitHub repository contains a new record in packages section:
And in details it looks like this:
Installing NPM Package from the GitHub Registry
As a final step, we want to use our brand new package in some projects. GitHub offers us to run typical npm install @n0th1ng-else/my-test-package@1.2.2. We can try it but, obviously, we will face an access error. Let’s recall we have a token which includes reading packages, so what we want to do is to use the trick we had done before for publishing. In the project where it will be used, we are going to create .npmrc file and use our token there:
Now npm knows the credentials and will kindly install your library! Simple as that. Finally, we all set up.
It’s time to give it a try!
It was the last thing I wanted to cover in this article, so let’s conclude what we have learned for today:
- We learned that GitHub relies on a token-based authorization system. And now we know when and how to use tokens with different scopes. Important thing here is that when you switch your package from private state into public, remember to revoke both tokens and replace them with those without repo scope permissions! Repo scope allows to access your private repositories, so be careful here.
- We realized that GitHub allows to store docker images and it works almost the same as other docker registries except, maybe, the image name (remember that /application suffix at the end of the docker path?)
- We managed to publish our super cool npm package into GitHub with some standard tricks npm offers us.
So what do we want to do next? Practice is the key! Try GitHub packages in your projects, automate as much as you can and focus on the code when it’s all set. Leave feedback and questions in the comments and don’t forget to subscribe to my account so you would not miss new stories.
Thanks for reading!