Automating Workflows: Harnessing GitHub Actions, Docker, and GitHub npm Package
Tags: devops, github, docker, npm
Published: 2024-04-24 12:12:22

![Github docker CI/CD](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r53hz2xhm0t2qbn7ypsm.png)

In the ever-evolving landscape of software development, streamlining workflows is paramount to success. In this article, we’ll explore how to leverage the powerful combination of GitHub Actions, Docker, and the GitHub npm Package to automate and optimize your development processes. From automating CI/CD pipelines to seamlessly managing dependencies, join us as we delve into the world of automation and discover how these tools can revolutionize your development workflow.

## Github, NPM registry, Docker

In today’s software development landscape, GitHub stands out as the most popular platform for storing and managing Git repositories. Beyond its fundamental role in version control, GitHub offers additional functionalities, including the capability to host private NPM registry. This feature facilitates the storage and sharing of JavaScript and TypeScript code among projects and teams, enhancing collaboration and code reusability across your organization.

GitHub Actions allows you to automate tasks for your projects, such as checking code styles, running tests, building Docker images, deploying to different environments, and more.

When discussing Docker, it’s common practice to build your application, library, or any code within a specific Docker image. Within this image, you can define the version of the Node machine, as well as any external resources and libraries required during the build process. This approach offers remarkable convenience, as it eliminates the need to rely on a specific PC or virtual machine with all the necessary setup. Instead, you can prepare the environment at the Docker level once and reuse it consistently across different machines and environments, ensuring consistency and reproducibility throughout your development workflow.

However, a challenge arises when you attempt to build your application within Docker and it requires an npm library stored in your GitHub NPM private registry. Moreover, this process should be feasible within GitHub Actions. In this article, I will guide you through the setup process for achieving this seamlessly!

## How to Utilize a Private GitHub Registry?

Firstly, let’s begin with a simple scenario involving routing. Picture a project with a dependency from a private NPM registry.

```
{
  ...
  "dependencies": {
    ...
    "@targsoft/private-lib": "^1.0.0",
    ...
  }
  ...
}
```
First of all, you need to generate a new GitHub Token. You can generate a token in your GitHub account settings at https://github.com/settings/tokens. Make sure to add the ‘read:packages’ scope to your token.

![Github Personal Token](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/36x15nd784de1jv6ute5.png)

Once you’ve obtained your token, you have two options:

Add your token to your global npm configuration. Open your terminal and run the following commands:

```
npm login --registry=https://npm.pkg.github.com --scope=@targsoft
login: your username password=TOKEN
```
where scope is your registry name

Alternatively, you can create an .npmrc file next to your package.json file with the following content:

```
@targsoft:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=TOKEN
always-auth=true
```
This should do the trick, and your global npm will fetch the library from the private registry. Try running ‘npm install’ to see if it works!

## How to use a Private GitHub Registry inside Docker?

Okay, so it’s pretty clear how to use the GitHub registry from your local machine. But what if you have a Dockerfile that builds your application within itself and then runs the application? For example, it could be a small web application with nginx as the web server.

```
FROM node:20-alpine AS build


WORKDIR /opt
COPY ./package.json ./yarn.lock /opt/

RUN --mount=type=secret,id=npmrc,target=/root/.npmrc yarn install --frozen-lockfile

COPY . .

RUN yarn audit --omit=dev
RUN yarn build


FROM nginx:1.25.4-alpine AS runtime
COPY --from=build /opt/dist/targpatrol-main-frontend /usr/share/nginx/html
COPY docker/nginx.conf /etc/nginx/nginx.conf
CMD ["/bin/sh",  "-c",  "envsubst < /usr/share/nginx/html/assets/env.template.js > /usr/share/nginx/html/assets/env.js && exec nginx -g 'daemon off;'"]
```

The trick here is to pass secrets into your Dockerfile so that npm inside Docker can access the GitHub private registry.

```
RUN --mount=type=secret,id=npmrc,target=/root/.npmrc yarn install --frozen-lockfile
```

As you can see, we mount secrets before installing packages. This ensures that npm has the necessary credentials to fetch dependencies from the private registry.

The Docker Compose file will resemble the following:

```
version: '3.9'

secrets:
  npmrc:
    file: ./.npmrc

....

services:
  targpatrol-main-frontend:
    build:
      context: ../../targpatrol-main-frontend
      secrets:
        - npmrc
    container_name: targpatrol-main-frontend
    restart: always
    networks:
      - targpatrol-docker-network
```
.npmrc is the same file we used to fetch library using global npm.

```
@targsoft:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=TOKEN
always-auth=true
```

Now you can run try to build the container:

```
docker compose up --build --force-recreate
```

## How to use Github Action to build Docker image?
Okay, now that we’re able to build the Docker image on our local machines, what if we want to use GitHub Actions to build the image? Here’s how we need to do it.

```
name:  targpatrol-main-frontend-pr-opened

...

jobs:
  build-and-test:
    runs-on: ubuntu-latest
    defaults:
      run:
        shell: bash
        working-directory: ${{ env.SERVICE }}

    steps:
      - name: Checkout
        uses: actions/checkout@v3

      - name: Setup node
        uses: actions/setup-node@v3
        with:
          node-version: '20.x'
          registry-url: 'https://npm.pkg.github.com'
          scope: '@targsoft'

      - name: Install npm packages
        run: yarn install --frozen-lockfile
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

      - name: Lint
        run: yarn lint

      - name: Audit
        run: yarn audit --omit=dev

      - name: Build
        run: yarn build

      - name: Docker Build and push to AWS ECR
        uses: docker/build-push-action@v5
        with:
          context: ${{ env.SERVICE }}
          file: ${{ env.SERVICE }}/Dockerfile
          secrets: |
            "npmrc=${{ secrets.NPMRC_SECRET_FILE }}"
          push: false
```
This is an example of how to set up Node.js inside a GitHub action. The NPM_TOKEN should be set up at the repository or organization level. NPMRC_SECRET_FILE is the GitHub Action secret that contains the same content as the .npmrc file.

## Don’t forget about Dependabot
If you are using Dependabot to watch your packages versions you have to create separate secrets for it because it won’t take secrets from your Github Actions.

![Dependabot token](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/aw00iuae2q6wi9r2e95y.png)

## Conclusion
In conclusion, the integration of GitHub Actions, Docker, and the GitHub npm Package presents a powerful solution for automating workflows in software development. By harnessing these tools, developers can streamline their processes, increase productivity, and ensure consistency across projects and teams. From automating builds and deployments to managing dependencies seamlessly, the possibilities are endless. As technology continues to evolve, mastering these tools will become increasingly essential for staying competitive in the ever-changing landscape of software development. So, dive in, experiment, and discover the endless possibilities of automating your workflows with GitHub Actions, Docker, and the GitHub npm Package.