Deno has been getting a lot of attention. There are already more than 700 third-party modules and the number is quickly rising. People are starting to use it for real business applications. We even have a blockchain-based repository, something that blew my mind. But I haven't seen a lot of tutorials covering CI/CD and Docker with Deno, so I wrote one. I hope you find it handy, so be sure to bookmark it š
Node has gained a lot of popularity since it was introduced in 2009. Despite its success, Ryan Dahl, Nodeās original creator, believes thereās room for improvement, and so he has recently released Deno, a new runtime for JavaScript and TypeScript, as its successor.
How is Deno different? Well, Deno, like Node, uses the V8 engine and event-driven architecture. But here is where the similarities end.
TypeScript gets first-class support at last. Deno compiles to JavaScript without additional packages.
Deno has better security by default. Programs run in a sandbox that doesnāt have access to the network, the environment, or the filesystem unless explicitly granted.
The most significant difference, though, is that Deno doesnāt have a package manager (say goodbye to npm). That means Node.js modules are largely unsupported. Instead, Deno uses decentralized ES Modules. To compensate, Deno developers have introduced an audited standard library and support for third-party modules.
In this tutorial, weāll learn how to use Semaphore Continuous Integration (CI) to test Deno applications. As a bonus, weāll explore how to release Deno applications in Docker using Continuous Delivery (CD).
Prerequisites
If you wish to do this tutorial along with me, youāll need the following:
Feel free to fork it. It features an oak-based HTTP API service with a PostgreSQL backend and includes integration tests. The project comes with everything you need to build Docker images.
Otherwise, these instructions should work with any Deno application. You may need to make slight adjustments, though, depending on how your code is organized.
Prepare a Testing Image
Semaphoreās composable containers feature lets us work with cutting-edge tools and languages like Deno. We can tailor Docker images to exact specifications and use them to drive CI/CD jobs seamlessly. Semaphore supports any container as long as it includes some basic packages like SSH, Git, and FTP.
Letās take a few minutes to prepare a Dockerfile for Deno.
We can start from a Debian image:
FROM debian:buster
Then, we tweak some settings and install the required packages:
To add your project to Semaphore follow these steps:
Log in with your account and click on the + (plus sign) next to projects.
Select your repository from the list.
In the next screen, you can add more people to the project. Once done, click on Go to Workflow Builder to continue.
Choose the Single Job starter workflow and click on Customize it first.
You are now at the Workflow Builder, which lets you visually set up the CI/CD pipeline.
The main element in the view is the pipeline. A pipeline consists of a series of blocks which are executed from left to right.
Each block has one or more jobs. Once all jobs in a block complete, the next block starts.
Jobs contain the commands that do the work and run in parallel. If any command fails, the pipeline stops and is marked as failed.
Letās create our first job:
Click the pipeline to view its settings. On the right side, under Environment Type select Docker containers.
Type the name of the image you uploaded in the previous section: YOUR_DOCKER_HUB_USER/deno:v1.1.1.
Click on the first block in the pipeline to begin editing it.
In this block, we only need to download and cache the projectās dependencies. For this, we can combine Semaphoreās cache tool with deno cache:
cache restore takes a list of keys and retrieves the first match. Our project lists all dependencies in src/deps.ts, so we can use it as part of the key:
In this section, weāll create a new block with two test jobs. The tests use a PostgreSQL database. The easiest way to get one is to connect a new container since weāre already using them in the pipeline.
Select the pipeline and click on +Add Container
Call the new container āpostgresā
Type the name of a postgres image on Image: postgres:12
Click on +Add environment variable and add the POSTGRES_HOST_AUTH_METHOD variable with value trust to allow connections without a password.
Create a new block using +Add Block.
Open the Prologue section. The commands we put here will be executed before every job in the block. Weāll use these commands to retrieve the dependencies:
Open the Environment Variables section and create the variable DB_HOST = postgres
Create three test jobs:
The first job does Database tests. Type the following commands:
deno run --allow-net--allow-env src/migrate.js
deno test--allow-net--allow-env src/tests/database.test.js
Click on +Add another job.
The second job does Integration tests. Type the following commands. Note that in this one, we also need to start the application before running the tests.
deno run --allow-net--allow-env src/app.js &
deno run --allow-net--allow-env src/migrate.js
deno test--allow-net--allow-env src/tests/app.test.js
The third job does Static tests. Deno ships with a code linter. To enable it, we need to use the --unstable flag.
Compared with the image we used in the CI pipeline, this production image is leaner, has all the code and dependencies baked in, and runs as the deno user instead of root.
Weāre done configuring the pipeline. Start it one last time.
Once it completes, click on promote to start the build.
Thatās all! From now on, Semaphore will run the pipelines on every push to GitHub.
Whatās Next?
You have prepared a production image with your application, now itās time to think about deploying it š ā donāt leave it sitting on Docker Hub, collecting dust.
Do you want to run your Deno application in Kubernetes but donāt know how to begin? Download our free CI/CD with Docker and Kubernetes ebook, which explains everything you need to know to get started and includes detailed how-to tutorials.
After that, check out my Docker & Kubernetes guides: