Zenn
🦍

changesets-gitlabを使って、changesets を自動化してみた

2025/03/29に公開

はじめに

この記事では、changesetsでできること・changesets-gitlabを使ってどう自動化したかについてまとめました。

changesetsの概要

まず最初に簡単にですがchangesetsの概要について触れていきます。

https://github.com/changesets/changesets
Changesetsは、パッケージごとの変更内容(機能追加、バグ修正、破壊的変更など)を個別のファイルで記録する仕組みです。任意のタイミングで変更のログを記録して、設定を行うことでChangelogの作成と自動的にパッケージのバージョンアップを行なってくれます。

changesetsの使い方

変更記録の作成

各機能追加や修正を行った後に以下のコマンドを使用する。

$ npx changeset

変更内容を記録するためのmdファイルを作成していきます。

🦋  What kind of change is this for <プロジェクト名>? (current version is 0.2.4) · patch
🦋  Please enter a summary for this change (this will be in the changelogs).
🦋    (submit empty line to open external editor)
🦋  Summary · changelogに記載したい内容
🦋  
🦋  === Summary of changesets ===
🦋  patch:  <プロジェクト名>
🦋  
🦋  Is this your desired changeset? (Y/n) · true

ターミナルに出力される質問に従って回答していきます。

質問内容

  • 変更の種類の確認(🦋 What kind of change is this for <プロジェクト名>? )
    • どのレベルのバージョンを上げるかを選択する(patch、minor、major)
  • 変更内容の要約入力(🦋 Please enter a summary for this change (this will be in the changelogs).)
    • changelogに記載したい内容を書く
  • 変更内容の確認(🦋 Is this your desired changeset?)
    • 変更内容に問題なければ、Yesと回答する

mdファイルが自動生成

質問への回答が完了すると、.changesetフォルダ配下に変更が記録されたmdファイルが作成されます。ファイル名はランダムです。

CHANGELOG.mdの作成

リリースのタイミングで変更記録を元にCHANGELOG.mdを作成します。

$ npx changeset version

上記のコマンドを実行すると、

  • .changesetフォルダ配下に変更が記録されたmdファイルを元にCHANGELOG.mdの生成
  • .changesetフォルダ配下に変更が記録されたmdファイルは削除
  • package.jsonのversionをインクリメント
    • レベルが異なるバージョンの変更があった場合は、上位のレベルで変更されます。例えば、minorとmajorが存在していたら、majorバージョンでインクリメントされます。

概要、使い方としては以上になります。

実装の準備

cliツールをインストール

最初に、changesetsのcliツールをインストールします。

$ npm install --save-dev @changesets/cli

初期化

$ npx changeset init
🦋  Thanks for choosing changesets to help manage your versioning and publishing
🦋  
🦋  You should be set up to start using changesets now!
🦋  
🦋  info We have added a `.changeset` folder, and a couple of files to help you out:
🦋  info - .changeset/README.md contains information about using changesets
🦋  info - .changeset/config.json is our default config

changesetを初期化すると、ルートに.changesetフォルダが作成されます。
中には、config.jsonとREADME.mdが存在しています。

{
  "$schema": "https://unpkg.com/@changesets/config@3.1.1/schema.json",
  "changelog": "@changesets/cli/changelog",
  "commit": false,
  "fixed": [],
  "linked": [],
  "access": "restricted",
  "baseBranch": "main",
  "updateInternalDependencies": "patch",
  "ignore": []
}
# Changesets

Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works
with multi-package repos, or single-package repos to help you version and publish your code. You can
find the full documentation for it [in our repository](https://github.com/changesets/changesets)

We have a quick list of common questions to get you started engaging with this project in
[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)

こちらですでに変更の記録ができるようになっています(npx changesetが使用できる)

自動化の対応

https://www.npmjs.com/package/changesets-gitlab
changesets-gitlabを使用して、CHANGELOG.mdの作成とマージリクエストの自動生成を実現します。

changesets-gitlabをインストール

$ npm install changesets-gitlab --save-dev

package.jsonのスクリプト設定

package.jsonにスクリプトを追加して、CI上でchangesets-gitlabを実行できるようにします。

  "scripts": {
     ...
     "changesets": "changesets-gitlab"
  }

CIの設定

定義したジョブは以下のようにしました。

update:changesets:
  stage: update_packages
  rules:
    - if: '$CI_COMMIT_REF_NAME == "main"'
      when: on_success
  script:
    - npm ci
    - npm run changesets
  variables:
    GITLAB_TOKEN: ${PROJECT_ACCESS_TOKEN} # required
    INPUT_COMMIT: update changelog and package. # optional
    INPUT_TITLE: Update Changelog and Package. # optional

mainブランチへのマージ完了時に、changesets-gitlabが実行されるようにしています。

環境変数 入力 備考
GITLAB_TOKEN アクセストークン プロジェクトアクセストークンでも可
INPUT_COMMIT コミットメッセージ 指定なしならVersion Packagesとなる
INPUT_TITLE マージリクエストのタイトル 指定なしならVersion Packagesとなる

環境変数は、上記3つを指定しました。
備考にもありますが、GITLAB_TOKENは、プロジェクトトークンを新しく作成して、変数として定義して使用しました。INPUT_COMMITINPUT_TITLEの指定は任意です。

https://www.npmjs.com/package/changesets-gitlab#usage

また、環境変数には、INPUT_VERSIONというものが存在しています。任意の値で指定しなければ内部でchangeset versionを実行してくれます。

ここまでの対応で、変更記録を含むブランチがmainブランチにマージされると、自動でマージリクエストが生成されるようになります。

Changelogのフォーマットをカスタマイズ

changesetsには、生成されたChangelogのフォーマットをカスタマイズすることが可能です。
デフォルトの設定だと、changesetsの変更点がplain textとして出力されるだけなのでカスタマイズしました。
https://github.com/changesets/changesets/blob/main/docs/modifying-changelog-format.md#writing-changelog-formatting-functions

変更には、getReleaseLine・getDependencyReleaseLineの2つの関数を使用します。getReleaseLineは、スクショの赤枠部分で、getDependencyReleaseLineはスクショの青枠部分です。後はバージョン番号の横に日付を入れたかったのですが、現状では見出しのカスタマイズはできないようでした...

https://github.com/changesets/changesets/pull/1127
話は上がっているようなので今後に期待です🙏

では、changelog-function.jsのような名前のファイルを作成して、以下のような実装例でカスタマイズしていきます

const changelogFunctions = {
  getDependencyReleaseLine: () => Promise.resolve(''), // 今回は特にカスタマイズなし
  getReleaseLine: (changeset, _, options) => {
    if (!changeset || !options.repo) {
      return
    }

    let mrNumber
    const replacedChangelogSummary = changeset.summary
      .replace(/#(\d+)/, (_, pr) => {
        let num = Number(pr)
        if (!isNaN(num)) mrNumber = num
        return ''
      })
      .trim()

    const mrLink = `${options.repo}/-/merge_requests/${mrNumber}`

    return mrNumber
      ? `- ${replacedChangelogSummary}([#${mrNumber}](${mrLink}))`
      : `- ${replacedChangelogSummary}`
  }
}

export default changelogFunctions

getReleaseLineの関数を使用してリリースノート一行のみカスタマイズを行いました。
実装の中身としては、変更内容の要約にgitlabのマージリクエスト番号(#付きで)が入力されていたら、リンクになるようにしてみました。また、関数の返り値はをマークダウンで書くことで、リストやテキストリンクを表現することができます。

後は、上記の関数が実行されるようにconfig.jsonに追記します。
repoに、gitlabのリポジトリURLを入れてあげるとgetReleaseLineの引数であるoptions.repoで値を受け取ることができます。

{
  ...
  "changelog": [
    "./changelog-function.js", { "repo": "gitlabのリポジトリURL" }
  ],
  ...
}

これでマージリクエストが自動生成された時に、CHANGELOG.mdのフォーマットを変更することができました。と同時に自動化とフォーマットのカスタマイズ対応も以上となります。

その他

changesetsの実装をする中で困ったことを2点共有します。
もしどなたかの参考に少しでもなればと思い記載させていただきます🙇‍♂️

1. lockファイルが更新されない問題

changeset versionの実行時に、package.jsonのバージョンは更新されますが、package.lock.jsonのバージョンは更新されません。
https://github.com/changesets/changesets/issues/1139
issuesにも上がっていますが、対応はまだのようです。そのため、現状ではlockファイルも更新したい場合は、自動生成されたマージリクエストが作成された時に、CI上でnpm installlをする or package.lock.jsonのバージョンを直接書き換える関数を用意して実行する、等の別途でアプローチが必要そうです...(私は暫定的ですが直接書き換える関数を用意する方を選択しました)

2. フォーマットのカスタマイズはTypescriptで書くことができない?

Typescriptのサポートをしていない?ようです...
https://github.com/changesets/changesets/issues/1323

型定義ファイルも存在しているので、Typescriptで書きたかったのですが現状ではJavascriptで書きました。

おわりに

changesetsを導入することで変更履歴やバージョンの管理が楽になりました。また、gitlabの場合はchangesets-gitlabを使うことで、自動でマージリクエストを作成してくれたりと便利になりました🙌

資料

Discussion

ログインするとコメントできます