Drone CI’s got a neat trick up its sleeve: it lets you build and test your Node.js projects without you ever having to think about setting up a build server. It’s a CI/CD platform that integrates directly with your Git repository (like GitHub, GitLab, Bitbucket) and spins up a fresh environment for every commit to run your tests and build your code.
Here’s a Node.js project running a simple test in Drone:
kind: pipeline
type: docker
name: default
steps:
- name: test
image: node:18
commands:
- npm install
- npm test
When a commit hits your repository, Drone reads this drone.yml file. It pulls down the node:18 Docker image, which is basically a clean Linux environment with Node.js v18 pre-installed. Then, it executes the commands listed under commands: first npm install to get your project dependencies, and then npm test to run your test suite. If npm test exits with a non-zero status code (meaning a test failed), Drone marks the build as failed. Otherwise, it’s a success.
This simple setup solves the problem of inconsistent development environments and the manual overhead of running tests before merging code. It ensures that every change is validated automatically, preventing broken code from reaching production.
Internally, Drone orchestrates this process using a Docker engine. When a build is triggered, Drone requests a new container from its Docker daemon based on the image specified in your pipeline. This container is isolated, meaning it has no knowledge of your local machine or any other build. The commands are then executed sequentially within this ephemeral container. This isolation is key: it guarantees that your build environment is always clean and reproducible, free from any lingering artifacts or configurations from previous builds.
The kind: pipeline and type: docker at the top are fundamental. kind: pipeline tells Drone you’re defining a sequence of steps to run. type: docker specifies that these steps will be executed within Docker containers. You can also use type: kubernetes for more complex orchestration.
The steps section is where the magic happens. Each name provides a label for a distinct phase of your build. The image specifies the Docker image to use for that step, which is crucial for ensuring you have the right tools (like Node.js itself) available. The commands array lists the shell commands that Drone will execute in order.
You can also add caching to speed up your builds. For Node.js, this typically means caching your node_modules directory:
kind: pipeline
type: docker
name: default
steps:
- name: test
image: node:18
commands:
- npm install
- npm test
cache:
paths:
- node_modules
Here, the cache block with paths: - node_modules tells Drone to preserve the node_modules directory between builds. On subsequent runs, if the node_modules directory already exists and matches the cache, Drone will restore it, skipping the npm install step if no dependencies have changed. This can dramatically reduce build times.
Beyond basic testing, you can extend this to build your application, publish packages, or deploy to services. For instance, to build a Node.js application for production:
kind: pipeline
type: docker
name: default
steps:
- name: build
image: node:18
commands:
- npm install
- npm run build
when:
branch: main
- name: test
image: node:18
commands:
- npm install
- npm test
cache:
paths:
- node_modules
- name: publish
image: plugins/npm
settings:
token:
from_secret: npm_token
when:
branch: main
event: push
In this example, the build step runs npm run build only when commits are pushed to the main branch. The test step, with caching, runs for all commits. The publish step uses the plugins/npm image, a specialized Docker image designed for publishing to npm. It requires an npm_token secret, which you’d configure in Drone’s settings, to authenticate and push your package to the npm registry, but only when a push event occurs on the main branch.
The when clause is a powerful feature that allows you to conditionally execute steps. Here, branch: main ensures a step only runs on that specific branch, and event: push further refines it to only trigger on push events. This is how you control your CI/CD workflow, automating deployment or publishing only for specific triggers.
What most people overlook is how Drone’s pipeline is fundamentally a directed acyclic graph (DAG) of Docker containers. While the default example shows a linear sequence, you can define parallel steps or steps that depend on the successful completion of others, creating complex workflows that can be optimized for speed and resource utilization. The dependencies keyword allows you to explicitly define these relationships, enabling parallel execution where possible.
The next logical step after setting up builds and tests is often managing environment variables for different stages or integrating with cloud providers for deployments.