Juniper projects work seamlessly with continuous integration and deployment pipelines. This guide covers setting up GitHub Actions for automated testing, linting, and deployment.
Create a workflow file at .github/workflows/ci.yml:
name: CI
on:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
format-and-lint:
name: Check formatting and lint
runs-on: ubuntu-latest
steps:
- name: Clone repository
uses: actions/checkout@v4
- name: Setup Deno
uses: denoland/setup-deno@v2
with:
deno-version: v2.x
cache: true
- name: Check formatting
run: deno fmt --check
- name: Lint source files
run: deno lint
test:
name: Run tests
needs: [format-and-lint]
runs-on: ubuntu-latest
steps:
- name: Clone repository
uses: actions/checkout@v4
- name: Setup Deno
uses: denoland/setup-deno@v2
with:
deno-version: v2.x
cache: true
- name: Install dependencies
run: deno install
- name: Run tests
run: deno task test
build:
name: Build application
needs: [test]
runs-on: ubuntu-latest
steps:
- name: Clone repository
uses: actions/checkout@v4
- name: Setup Deno
uses: denoland/setup-deno@v2
with:
deno-version: v2.x
cache: true
- name: Install dependencies
run: deno install
- name: Build for production
run: deno task build:prodConfigure the test job to run on multiple platforms:
test:
name: Test on ${{ matrix.os }}
needs: [format-and-lint]
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
steps:
- name: Clone repository
uses: actions/checkout@v4
- name: Setup Deno
uses: denoland/setup-deno@v2
with:
deno-version: v2.x
cache: true
- name: Install dependencies
run: deno install
- name: Run tests with coverage (Ubuntu)
if: matrix.os == 'ubuntu-latest'
run: deno task test --coverage
- name: Run tests (macOS/Windows)
if: matrix.os != 'ubuntu-latest'
run: deno task test --parallelThe deno install step ensures all npm dependencies are fully resolved before
tests start. On Windows, you may also need to disable Deno's cache in GitHub
Actions to avoid stale npm package data causing resolution failures.
Add test coverage reporting with Codecov:
- name: Upload coverage
if: matrix.os == 'ubuntu-latest'
uses: codecov/codecov-action@v5
with:
fail_ci_if_error: true
files: coverage/lcov.info
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}Add a type checking step:
type-check:
name: Type check
runs-on: ubuntu-latest
steps:
- name: Clone repository
uses: actions/checkout@v4
- name: Setup Deno
uses: denoland/setup-deno@v2
with:
deno-version: v2.x
cache: true
- name: Install dependencies
run: deno install
- name: Check types
run: deno checkCreate a combined check task in deno.json:
{
"tasks": {
"check": {
"description": "Check formatting, lint, and types",
"command": "deno check && deno lint && deno fmt --check"
}
}
}Then use it in your workflow:
- name: Run all checks
run: deno task checkAdd a build job for production:
build:
name: Build for production
needs: [test]
runs-on: ubuntu-latest
steps:
- name: Clone repository
uses: actions/checkout@v4
- name: Setup Deno
uses: denoland/setup-deno@v2
with:
deno-version: v2.x
cache: true
- name: Install dependencies
run: deno install
- name: Build application
run: deno task build:prod
- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: build
path: public/build/Deno Deploy is the recommended platform for deploying Juniper applications. It handles building and deployment automatically through its dashboard.
See Deployment for complete setup instructions.
For Deno Deploy Classic, add automatic deployment via GitHub Actions:
deploy:
name: Deploy to Deno Deploy Classic
needs: [build]
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
steps:
- name: Clone repository
uses: actions/checkout@v4
- name: Setup Deno
uses: denoland/setup-deno@v2
with:
deno-version: v2.x
cache: true
- name: Build for production
run: deno task build:prod
- name: Deploy to Deno Deploy Classic
uses: denoland/deployctl@v1
with:
project: my-juniper-app
entrypoint: main.tsBuild and push a Docker image. See Deployment for Dockerfile examples.
deploy-docker:
name: Build and push Docker image
needs: [test]
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
steps:
- name: Clone repository
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ghcr.io/${{ github.repository }}:latestHere's a complete CI/CD workflow. If you're using Deno Deploy (recommended), you
can omit the build and deploy jobs since Deno Deploy handles building and
deployment automatically when you push to your configured branch.
This example includes the build and deploy jobs for Deno Deploy Classic:
name: CI/CD
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
check:
name: Format and lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: denoland/setup-deno@v2
with:
deno-version: v2.x
cache: true
- run: deno fmt --check
- run: deno lint
test:
name: Test
needs: [check]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: denoland/setup-deno@v2
with:
deno-version: v2.x
cache: true
- run: deno install
- run: deno task test --coverage
- uses: codecov/codecov-action@v5
with:
files: coverage/lcov.info
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
# Omit build and deploy jobs if using Deno Deploy (not Classic)
build:
name: Build
needs: [test]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: denoland/setup-deno@v2
with:
deno-version: v2.x
cache: true
- run: deno install
- run: deno task build:prod
- uses: actions/upload-artifact@v4
with:
name: build
path: public/build/
deploy:
name: Deploy to Deno Deploy Classic
needs: [build]
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
steps:
- uses: actions/checkout@v4
- uses: denoland/setup-deno@v2
with:
deno-version: v2.x
cache: true
- run: deno install
- run: deno task build:prod
- uses: denoland/deployctl@v1
with:
project: my-juniper-app
entrypoint: main.tsNext: Deployment - Deploy to Deno Deploy, Docker, and more
Related topics:
- Testing - Testing utilities and patterns
- Configuration - Project and build configuration