Skip to content

Instantly share code, notes, and snippets.

@ammuench
Created August 19, 2025 23:19
Show Gist options
  • Select an option

  • Save ammuench/9363b87715fee9b28062dba8d6a92e88 to your computer and use it in GitHub Desktop.

Select an option

Save ammuench/9363b87715fee9b28062dba8d6a92e88 to your computer and use it in GitHub Desktop.
Annotated workflow for publishing deno packages to NPM with Github CI and Deno-to-node
##
## Quick annotated example file to build a Github CI workflow to publish your Deno package to
## npm using Deno-To-Node (https://github.com/denoland/dnt) whenever you create and publish a
## new versioned system tag!
##
## Could also be easily used to build and deploy standard node packages to NPM with just a little bit of tweaking
##
name: Publish to NPM
on:
push:
# Runs on creation of tags created of type v.X.Y.Z (eg `tag -a v2.3.21`)
tags: ["v*"]
workflow_dispatch:
# Allows for user to manually trigger a tag publish event
inputs:
tag:
description: "Tag to publish (e.g., v1.0.0)"
required: true
type: string
jobs:
validate:
name: Pre-publish Validation
runs-on: ubuntu-latest
outputs:
version: ${{ steps.version.outputs.version }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Deno
uses: denoland/setup-deno@v1
with:
deno-version: v2.x
# Gets version from workflow dispatch or tag name
- name: Extract version from tag
id: version
run: |
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
VERSION="${{ github.event.inputs.tag }}"
else
VERSION="${GITHUB_REF#refs/tags/}"
fi
echo "version=${VERSION}" >> $GITHUB_OUTPUT
echo "Publishing version: ${VERSION}"
# Ensure that tag passed matches what you have in the deno.json manifest
# (this will pass to the package.json file as part of the DNT build step)
#
# You could remove this if you want have more control to deploy manually
# and potentially add in something that adds the tag to your deno.json in this flow
- name: Verify version in deno.json matches tag
run: |
DENO_VERSION=$(jq -r '.version' deno.json)
TAG_VERSION="${{ steps.version.outputs.version }}"
TAG_VERSION_CLEAN="${TAG_VERSION#v}"
if [ "$DENO_VERSION" != "$TAG_VERSION_CLEAN" ]; then
echo "Error: Version mismatch!"
echo "deno.json version: $DENO_VERSION"
echo "Tag version: $TAG_VERSION_CLEAN"
exit 1
fi
# Re-run basic quality checks before we start publishing. Add any other required commands here
- name: Run quality checks
run: |
deno fmt --check
deno lint
deno test
build-and-publish:
name: Build and Publish to NPM
runs-on: ubuntu-latest
needs: validate
environment: publishing
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Deno
uses: denoland/setup-deno@v1
with:
deno-version: v2.x
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: "22"
registry-url: "https://registry.npmjs.org"
# Run DNT build script, add any other prerequesite steps here if needed
- name: Build NPM package with dnt
run: deno run -A scripts/build_npm.ts
# Ensure the built package.json inhereted the right version from the deno.json file
- name: Verify NPM package version matches tag
run: |
NPM_VERSION=$(jq -r '.version' npm/package.json)
TAG_VERSION="${{ needs.validate.outputs.version }}"
TAG_VERSION_CLEAN="${TAG_VERSION#v}"
if [ "$NPM_VERSION" != "$TAG_VERSION_CLEAN" ]; then
echo "Error: NPM package version mismatch!"
echo "npm/package.json version: $NPM_VERSION"
echo "Tag version: $TAG_VERSION_CLEAN"
exit 1
fi
# Ensure all your files are properly created from the DNT build script
# Add/remove things here as needed
- name: Verify package structure
run: |
test -f npm/package.json
test -d npm/esm
test -d npm/script
test -f npm/LICENSE
test -f npm/README.md
- name: Test NPM package imports
working-directory: npm
run: |
# Test CommonJS import, you can remove this if you don't plan to export CJS
node -e "const contrastrast = require('./script/mod.js'); console.log('CommonJS import successful:', typeof contrastrast);"
# Test ESM import
node -e "import('./esm/mod.js').then(m => console.log('ESM import successful:', typeof m.default || typeof m));"
- name: Publish to NPM
working-directory: npm
env:
# Tokens can be generated from https://www.npmjs.com/settings/YOUR_USERNAME/tokens
# Make sure to add it as a secret to your GH Action in your repo settings
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
run: |
if [[ "${{ needs.validate.outputs.version }}" == *"-"* ]]; then
echo "Publishing non-stable release with beta tag"
npm publish --tag beta
else
echo "Publishing stable release"
npm publish
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment