くらげになりたい。

くらげのようにふわふわ生きたい日曜プログラマなブログ。趣味の備忘録です。

un/jsのchangelogenを詳しく理解して、いい感じに自動リリースする

CHANGELOGの自動生成とversion bumpを
unjs/changelogenで自動化したいなと思い、
いろいろ調べてみたときの備忘録(*´ω`*)

changelogenでできること

changelogenは、シンプルでいい感じのCHANELOGを生成してくれる

主な機能は、以下の通り

使い方

それぞれこんな感じ

# 標準出力にCHANGELOGの内容を表示
$ npx changelogen@latest

# CHNAGELOGファイルを更新
$ npx changelogen@latest --output

# コミットの内容からversion変更 + CHNAGELOGファイルを更新
$ npx changelogen@latest --bump

# コミットの内容からversion変更 + CHNAGELOGファイルを更新
# + tagの作成 + commitの追加
# + CHNAGELOGファイルの内容からGitHub Releaseの作成
$ npx changelogen@latest --release

# さらにgit pushもする
$ npx changelogen@latest --release --push

bumpの仕組み

--bumpオプションとあわせて、--patchなども指定できる

# package.jsonのbump + CHANGELOGの更新
$ pnpm changelogen --bump # or --prerelease
$ pnpm changelogen --bump --patch # or --prepatch
$ pnpm changelogen --bump --minor # or --preminor
$ pnpm changelogen --bump --major # or --premajor

デフォルトの--bumpだと、
.changelogen.jsonで指定されたものになる

// デフォルトのconfig
types: {
  feat: { title: "🚀 Enhancements", semver: "minor" },
  perf: { title: "🔥 Performance", semver: "patch" },
  fix: { title: "🩹 Fixes", semver: "patch" },
  refactor: { title: "💅 Refactors", semver: "patch" },
  docs: { title: "📖 Documentation", semver: "patch" },
  build: { title: "📦 Build", semver: "patch" },
  types: { title: "🌊 Types", semver: "patch" },
  chore: { title: "🏡 Chore" },
  examples: { title: "🏀 Examples" },
  test: { title: "✅ Tests" },
  style: { title: "🎨 Styles" },
  ci: { title: "🤖 CI" },
},

Conventional Commitsに従っていて、
semverが未指定のものだけの場合は、patchになる

また、!BREAKING CHANGEで、majorになることはない。

さらに、0.0.1など、majorが0の場合は、ちょっと特殊な動きをしていて、
一段ズレた形でバージョンが変更される

// 0.0.1 + --major => 0.1.0
// 0.0.1 + --minor => 0.1.1
// 0.0.1 + --patch => 0.1.1
if (currentVersion.startsWith("0.")) {
  if (type === "major") {
    type = "minor";
  } else if (type === "minor") {
    type = "patch";
  }
}

CHANGELOG生成の仕組み

基本的には、対象範囲のコミットを拾って、
featなどのグループにまとめて更新してくれる感じ

# Changelog

## v0.1.0

### 🚀 Enhancements

- Init ([96f3a9d](https://github.com/memory-lovers/changelogen-sample/commit/96f3a9d))

### 🏡 Chore

- Minor change ([cb92149](https://github.com/memory-lovers/changelogen-sample/commit/cb92149))

### ❤️ Contributors

- Memory-lovers ([@memory-lovers](https://github.com/memory-lovers))

bumpと同じで、このtypesに定義されているものが対象になる

// デフォルトのconfig
types: {
  feat: { title: "🚀 Enhancements", semver: "minor" },
  // ...
}

ので、git commit -m "minor change"のように、
なにもprefixがついてないものは、CHANGELOGに表示されないので注意が必要

逆に、--releaseフラグのとのコミットを載せたくないなどの場合は、
configでprefixなしのメッセージになるようtempletesを変更すればOK

  // .changelogen.json
  {
    "templates": {
-     "commitMessage": "v{{newVersion}}"
+     "commitMessage": "chore(release): v{{newVersion}}",
    }
  }

また、Contributorsセクションをなくしたい場合は、
--noAuthorsをつけれると、抽出されなくなる

npx changelogen@latest --output --noAuthors

releaseの仕組み

GitHub Releaseの作成まで自動でやってくれるオプション

流れとしては、

  • package.jsonのversion変更
  • CHANGELOGの更新
  • 変更したpackage.jsonCHANGELOGをcommit
  • 変更したversionでtagを作成
  • (--pushがあれば、) commitとtagをpush
  • GitHub Releaseの作成(--no-githubでskipできる)

内部では、gitコマンドと、GitHubREST APIを使っている感じ

また、GitHub Releaseだけ作成/更新することもできる

# CHANGELOGの`v1.0.0`の内容で、GitHub Releaseの作成 or 更新/同期
$ npx changelogen gh release "v1.0.0"

GitHub Actionsで自動化する

自動化するとこんな感じ
いきなりpushはせず、なにかリリースし終わったら、
push&GitHub Releaseを作成するようにしている

また、pnpm版&package.jsonchangelogenをインストール済み

name: relase

on:
  # 手動実行のみ
  workflow_dispatch:
    # `--minor`などの指定。未指定の場合は、`--bump`のみ
    inputs:
      release_type:
        description: "Release type"
        type: choice
        options:
          - patch
          - minor
          - major

# ジョブに必要な権限を設定
permissions:
  contents: write
  pull-requests: write

env:
  STORE_PATH:

jobs:
  publish:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          fetch-depth: 0 # 全履歴が必要

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version-file: ".node-version"

      - name: Install pnpm
        uses: pnpm/action-setup@v2
        with:
          version: "latest" # package.jsonのpnpmバージョンフィールドを参照
          run_install: false

      - name: Get pnpm store directory
        shell: bash
        run: |
          echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV

      - name: Setup pnpm cache
        uses: actions/cache@v3
        with:
          path: ${{ env.STORE_PATH }}
          key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
          restore-keys: |
            ${{ runner.os }}-pnpm-store-

      - name: Install dependencies
        run: pnpm install --frozen-lockfile

      - name: Setup GitHub Config
        run: |
          git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com"
          git config --local user.name "github-actions[bot]"

      - name: Version Bump and Generate CHANGELOG
        run: |
          if [ -z "${{ github.event.inputs.release_type }}" ]; then
            pnpm changelogen --release --noAuthors --no-github
          else
            pnpm changelogen --release --${{ github.event.inputs.release_type }} --noAuthors --no-github
          fi
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

      # なにかデプロイする

      - name: upload file into release
        run: |
          # push commit and tag
          git push --all

          # get version
          VERSION=`jq -r ".version" ./package.json`

          # create github release
          pnpm changelogen gh release "v${VERSION}"

          # attach artifact: GitHub Releaseに添付したいファイルを指定
          gh release upload "v${VERSION}" *.md
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

以上!! これでボタンをポチッとするだけで、
Release&CHANGELOG更新などができるように(*´ω`*)

参考にしたサイトさま