Deno and GitHub Actions workflows
4 min read
927 words
Today I want to talk about Deno and GitHub Actions. For the last year or so, I have only built new projects with Deno. I really like the runtime, it's typescript out of the box config, formatting, linting etc. It is just a lot of fun to work with.
Since I still wanted to make sure that everything works when pushed to our Github repositories, I had to build some GitHub actions. Today I want to share a repository where I collect useful actions. At the time of writing, the repository contains 3 different workflows. You can find the repository at niklasmtj/deno-actions on GitHub.
CI
The CI workflow runs on every PR creation or commit. It checks the format, runs tests, and lints the whole project. Since these steps are usually really fast, I did not limit it to just the changed files.
name: "CI"
on:
- pull_request
jobs:
ci:
runs-on: ubuntu-latest
steps:
- name: "Checkout"
uses: actions/checkout@v4
- name: "Setup Deno"
uses: denoland/setup-deno@v1
with:
deno-version: "1.x"
- name: "Run Tests"
run: deno task test
- name: "Run Lint"
run: deno task lint
- name: "Run Format"
run: deno task format
To run this workflow you need to set up 3 tasks in the deno.json
file. First
set up test
with the required permissions. Then lint
and format
. This is
done in deno.json
under the tasks
key as you can see in the following block
of code:
{
"tasks": {
"lint": "deno lint",
"format": "deno fmt --check",
"test": "deno test --allow-read --allow-write --allow-net"
}
}
This example uses the `--allow-read --allow-write --allow-net' flags to run the tests. When setting up your workflow tasks, you can easily check the commands locally. Deno will help you figure out the permission flags you need.
Build Docker Container Images
The second action will build a container image using Docker. The workflow runs when new pushes are made to the `main' branch. This happens most often after merging a pull request.
Make sure that you have a Dockerfile
describing your desired container image
in the root directory of the repository. This is used by the build-and-push
action as it's image recipe.
It is set up using buildx
, which allows you to build multi-architecture
images. For example, if you are building your containers locally on an M1 Mac,
these are arm64
images. If your hosting provider does not support arm64
images, but rather uses Intel or AMD processors on their servers, you will need
to build amd64
images. Using buildx
and qemu
we can make sure we're able
to build both in the same build. This is why you see linux/amd64,linux/arm64
in the platforms fields in the following workflow file:
name: "Build Container Image"
on:
push:
branches:
- main
jobs:
ci:
runs-on: ubuntu-latest
steps:
- name: "Checkout"
uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
with:
platforms: linux/amd64,linux/arm64
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
platforms: linux/amd64,linux/arm64
# Login to Docker Hub or any other registry here
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: niklasmtj/deno-image:latest
cache-from: type=gha
cache-to: type=gha,mode=max
The built image here will then be pushed to Docker Hub after login. Make sure
your organization or repository already has the DOCKERHUB_USERNAME
and
DOCKERHUB_TOKEN
secrets set. These are set in a repository under `Settings ->
Secrets and Variables -> Actions -> Repository secrets'. How to obtain a Docker
Hub token can be found in the
Docker documentation.
Caching is also set up when the container image is built to ensure that the subsequent execution is as fast as possible.
Create a Test Coverage Website and Publish to GitHub Pages
Testing should be an integral part of application development. To make sure that every part of the application is covered with tests, Deno supports creating a coverage report right out of the box (🤝). The third action supports building just that. Create the coverage and push it to GitHub pages. To be able to publish, you need to make sure that GitHub Pages is enabled for the repository you want to build coverage for.
name: Code Coverage
on:
push:
branches: [main]
workflow_dispatch:
# Make sure that you set these permissions
permissions:
contents: read
pages: write
id-token: write
jobs:
ci:
runs-on: ubuntu-latest
steps:
- name: Setup repo
uses: actions/checkout@v4
- name: Setup Deno
uses: denoland/setup-deno@v1
- name: Create lcov file
run: deno task coverage
- name: Setup Pages
uses: actions/configure-pages@v4
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: './coverage/html'
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
One thing you need to make sure is that GitHub Actions has permissions to
publish the created website. Make sure you set it under the permissions
key in
the yaml file.
Conclusion
This repository is not set in stone. I will try to keep the dependencies up to date (shout out to Dependabot) and will add or change actions in the future. So make sure you keep an eye on the repo (click the watch button in the top right corner).
Thanks for reading and have a great day!