Simply Wall St
Published in

Simply Wall St

Building a CI/CD Template to Publish TypeScript Libraries to the GitLab Package Registry

As an engineering team that develops a lot of front-end and back-end JavaScript applications grows, it quickly becomes clear that breaking down shared functionality into smaller, well-tested and properly documented packages will be necessary for:

  1. Scaling the team. Breaking down functionality into smaller parts makes it easier for new hires to contribute without being dropped into a monolithic repository.

As for how to actually go about doing this, I will cover an implementation that uses GitLab CI/CD to build, test and publish a TypeScript library to the GitLab Package Registry. As a bonus, we’ll create a repository to host a CI/CD template so that we can re-use it across many libraries.

Creating a TypeScript Library

First, we’ll create an example TypeScript library. In my case, I typically go with a project structure that you can check out and clone here. The notable parts are:

  • The name field in your package.json must be scoped to match either your username or the name of the topmost group that your repository belongs to. You can read more about package scopes and naming requirements in the GitLab documentation.

This template is a good starting point for fleshing out a vanilla JavaScript library with unit tests. Next, we’ll cover some registry pre-requisites.

Getting Setup to Work with the Package Registry

Before we can publish anything to the package registry, we’ll need to cover some preliminary steps. The first thing we need to do is authenticate locally with the registry, otherwise, we won’t actually be able to use our newly published packages in locally running code.

  1. You must create a personal access token, which will be used to authenticate with the registry.

For steps 2 & 3, you can either follow the GitLab documentation or simply append the following to your ~/.npmrc replacing SCOPE and TOKEN as needed.

@SCOPE:registry=https://gitlab.com/api/v4/packages/npm/
//gitlab.com/api/v4/packages/npm/:_authToken=TOKEN
//gitlab.com/api/v4/projects/:_authToken=TOKEN

You’ll see steps very similar to these being repeated as we flesh out our CI/CD since authentication is obviously required there as well.

Building the CI/CD Template

For the GitLab pipeline, we’ll want to have something that can:

  • Build the package. This will verify that no compilation errors, dependency issues or other build-related problems have surfaced between pushes.

For the above, we arrive at something like this (replacing MY-SCOPE with your scope name):

While running within the CI/CD environment, we are able to utilise the CI_JOB_TOKEN as our authentication credential, rather than having to inject your personal access token created in the earlier stages of this walkthrough.

Saving this .gitlab-ci.yml into your project root and pushing to master will run successful build and test stages, with the latter including a coverage report column:

Passing stages with coverage report

When you create new tags to mark a release, you will see an additional publish stage, which will take your compiled dist folder from the artifacts directive in the build stage and publish it to the registry.

Additional publish stage

At this point, your package will be available through the Packages & Registries tab on GitLab, with a version matching the version you entered when you created the tag.

The package listed within the GitLab registry

Installing Your Dependencies in External Pipelines

Projects that depend on your package and have their own CI/CD with a dependency installation step will need to know where your packages are and authenticate with the registry. To do this, you can include the following lines before your script runs:

Creating and Deploying a Shared CI/CD Template

To avoid needing to manually copy and paste this CI/CD YAML around all of your projects, you can leverage GitLab Pages to deploy a template that can be included by all of your projects. This means that any future improvements to the template will be automatically inherited by all of your pipelines across packages that use it, which becomes extremely valuable as you start managing dozens of libraries in your team.

Before you begin, it’s important to understand that templates must be public for your CI/CD pipelines to access them. For this reason, it is extremely important that you do not include private information in templates. Instead, leverage variables to allow the project level CI/CD to inject secret values.

First, create a new repository in GitLab that will store your template YAML. After it is created, go to Settings → General, expand the Visibility section and make sure that Pages is enabled and accessible by everyone. Note that the repository itself does not need to be public, just the template YAML itself will be published in a publicly accessible way.

Ensure “everyone” is selected

Once that’s done, you can define a simple CI/CD that will copy any templates you commit to the repository to a public directory, which is where GitLab pages will publicly host files from. In our case, we’ll make a dedicated templates directory in the repository root that will contain all of our YAML templates, then create the following .gitlab-ci.yml

Once you push and the pages stage passes, you’ll be able to see your templates on a URL similar to:

https://my-username.gitlab.io/my-repo/my-template.yml

From this point, all you need to do is use the include directive in your project level CI/CD to inherit it. You can override stages as needed and declare your own variables which can be passed down to the template.

Between the example TypeScript project and the ability to define your own shared CI/CD templates, it should be trivial to start breaking down code into smaller, sharable JavaScript packages for your team or even just for personal use.

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store