TECH BOX

Technology blog from Web Engineer

denoland/dntでビルドしたライブラリをGitLab CI経由で公開する

Denoを利用してコードを書いたものをnpmライブラリとして公開したいと思うことがあります。
npmライブラリに公開するためにはTypeScriptのままではだめなのでJavaScriptにビルドする必要があり、ビルド方法はいくつかあります。
その中でも最も簡単なのがdnt – Deno to Node Transformを利用することです。

dntの何がいいかと言うと、一番大きいのはpackage.jsonを始めとしたnpmライブラリとして公開するためのファイルを簡単に作成できることです。
せっかくdenoで書いているのに別でpackage.jsonなんて書くのは面倒ですからね。

そのdntのGitHubにはGitHub Actionsを使ったnpmレジストリへの公開方法は記載されていますが、GitLab CIを使った方法は記載されていません。
GitLab CIはdocker imageを使ってジョブを構築します。
dntはビルド時に npm install を行うため、dockerのdenoイメージだけだと動作しません。
逆にnodejsイメージでdenoを動かすのも難しいです。

そこで、alpineを使ったの解決方法を見つけました。

alpine:edgeイメージを利用

色々試行錯誤した結果、denoもnpmも利用できる alpine:edge を使用することで解決しました。
なぜ、edgeなのかというと2023年11月のv3.18時点ではdenoがまだ alpine:latest に存在していないためです。

ビルドファイルを用意

ビルドファイルを作成したらそのファイルに対して deno run を行えばよいです。
例えば、下記のビルドファイル(Node CLIビルド)が存在したとします。
dntでビルドした結果は npm ディレクトリに格納されます。

// build.ts
import { build, emptyDir } from 'dnt'

await emptyDir('npm')

await build({
  entryPoints: [{
    kind: 'bin',
    name: '名前',
    path: 'メインファイルのパス',
  }],
  packageManager: 'npm',
  outDir: './npm',
  importMap: './import_map.json',
  shims: {
    deno: true,
  },
  package: {
    name: '名前',
    version: '1.0.0',
    description: '説明',
    main: './esm/main.js',
    bin: {
      'CLIコマンド名': './esm/main.js',
    },
    engines: {
      node: '>=16.0.0',
      npm: '>=8.0.0'
    },
    license: 'MIT',
    repository: {
      type: 'git',
      url: 'Gitリポジトリのパス',
    },
    bugs: {
      url: 'イシューのパス',
    },
  },
  typeCheck: 'both',
  test: false,
  declaration: 'separate',
  scriptModule: false,
})

Deno.copyFileSync('README.md', './npm/README.md')

GitLab CIの設定

ビルドファイル(build.ts)を作ったら .gitlab-ci.yml には下記のように記述します。

image: alpine:edge

stages:
  - publish

default:
  before_script:
    - apk update

deploy:
  stage: publish
  script:
    - apk add npm deno
    - deno run -A build.ts
    - cd npm
    - npm publish
  only:
    refs:
      - main

これでnpmレジストリへの公開ができます。