💭

Turborepo x GitHub Actions x changesets でパッケージを限定公開

2023/09/26に公開

1. はじめに

自分専用、あるいは社内のみで利用するパッケージを GitHub Actions を介して、GitHub Packages に限定公開する方法を説明します。プロジェクトは Turoborepo で管理されていることを想定します。特に、以下の記事を参考に記述しました。

https://tech-broccoli.life/articles/engineer/use-github-packages/

https://efcl.info/2023/07/17/regular-updates-by-changesets/

作業リポジトリは以下です。

https://github.com/hayato94087/turborepo-changesets-template

2. 全体像

本記事では以下を実装します。

  • モノレポのプロジェクトを Turborepo で作成
  • arithmetic パッケージと geometry パッケージの2つのワークスペースを作成
  • arithmetic パッケージと geometry パッケージを GitHub Packages に限定公開
  • arithmetic パッケージと geometry パッケージに機能を追加しバージョンアップを実施
  • arithmetic パッケージと geometry パッケージを web アプリケーションで利用

3.モノレポを作成

限定公開するパッケージを含むモノレポを作成します。

create-turbo で、新規に Turborepo でモノレポを作成します。

モノレポ作成の詳細

$ pnpm dlx create-turbo@latest

>>> TURBOREPO

>>> Welcome to Turborepo! Let's get you set up with a new codebase.

? Where would you like to create your turborepo? turborepo-changesets-template
? Which package manager do you want to use? pnpm workspaces

Downloading files. This might take a moment.

>>> Created a new Turborepo with the following:

apps
 - apps/docs
 - apps/web
packages
 - packages/eslint-config-custom
 - packages/tsconfig
 - packages/ui

Installing packages. This might take a couple of minutes.

>>> Success! Created a new Turborepo at "turborepo-changesets-template".
Inside that directory, you can run several commands:

  pnpm run build
     Build all apps and packages

  pnpm run dev
     Develop all apps and packages

  pnpm run lint
     Lint all apps and packages

Turborepo will cache locally by default. For an additional
speed boost, enable Remote Caching with Vercel by
entering the following command:

  pnpm dlx turbo login

We suggest that you begin by typing:

  cd turborepo-changesets-template
  pnpm dlx turbo login

プロジェクトディレクトリーに移動します。

$ cd turborepo-changesets-template

web アプリケーションの page.tsx を以下で上書きし、サンプルのページを作成します。

apps/web/app/page.tsx
export default function Page(): JSX.Element {
 return (
   <h1 className="text-xl">Web</h1>
 );
}

.npmrc の中身を削除しておきます。

.npmrc
-auto-install-peers = true

さらに、.npmrc はリポジトリの管理対象外とします。

.gitignore
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
node_modules
.pnp
.pnp.js

# testing
coverage

# next.js
.next/
out/
build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# local env files
.env
.env.local
.env.development.local
.env.test.local
.env.production.local

# turbo
.turbo

# vercel
.vercel

+# npmrc
+.npmrc

ローカルで実行します。

$ pnpm dev --filter=web

Alt text

コミットします。

$ pnpm build
$ git add .
$ git commit -m "Turborepoの初期環境を構築"

4. geometry パッケージを作成

限定公開するパッケージを作成します。パッケージには rectangleArea を含みます。

packages/geometry/index.ts
export const rectangleArea = (a: number, b: number) => {
  return a * b;
};

パッケージ作成詳細

4.1. パッケージのプロジェクトフォルダを作成

プロジェクトフォルダを作成します。

$ mkdir -p packages/geometry

4.2. package.jsonを作成

package.json を作成します。

$ touch packages/geometry/package.json
packages/geometry/package.json
{
  "name": "@hayato94087/geometry",
}

コミットします。

$ git add .
$ git commit -m "add package.json"

4.3. TypeScriptを追加

TypeScript を devDependencies に追加します。

$ pnpm add -D typescript --filter=@hayato94087/geometry

.gitignore を作成し、node_modules をリポジトリの管理対象外とします。

$ touch packages/geometry/.gitignore
packages/geometry/.gitignore
# Ignore bundler config
node_modules

コミットします。

$ git add .
$ git commit -m "add typescript, .gitignore"

4.4. tsconfig.jsonを作成

tsconfig.json を作成します。

$ touch packages/geometry/tsconfig.json

作成された tsconfig.jsonnoUncheckedIndexedAccessnoEmit を追加します。noEmit をついかしているのは、tsc を linter として利用するためです。

packages/geometry/tsconfig.json
{
  "compilerOptions": {
    "target": "es2016",                                  /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
    "module": "commonjs",                                /* Specify what module code is generated. */
    "esModuleInterop": true,                             /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
    "forceConsistentCasingInFileNames": true,            /* Ensure that casing is correct in imports. */
    "strict": true,                                      /* Enable all strict type-checking options. */
    "skipLibCheck": true,                                 /* Skip type checking all .d.ts files. */
    "noUncheckedIndexedAccess": true,                     /* Include 'undefined' in index signature results */
    "noEmit": true                                        /* Do not emit outputs. */
  }
}

コミットします。

$ git add .
$ git commit -m "add tsconfig.json"

4.7. index.tsを作成

index.ts で足し算の関数を作成します。

$ touch packages/geometry/index.ts
packages/geometry/index.ts
export const rectangleArea = (a: number, b: number) => {
  return a * b;
};

コミットします。

$ git add .
$ git commit -m "add rectangle area"

4.8. tsup を設定

tsupは、TypeScript のバンドラです。

tsup を devDependencies に追加します。

$ pnpm add -D tsup --filter=@hayato94087/geometry

build スクリプトを package.json に追加します。

packages/geometry/package.json
{
 "name": "@hayato94087/geometry",
+ "scripts": {
+   "build": "tsup index.ts --format cjs,esm --dts --minify"
+ },
  "devDependencies": {
    "tsup": "^7.2.0",
    "typescript": "^5.2.2"
  }
}

.gitignoredist を追加します。

packages/geometry/.gitignore
# Ignore bundler config
node_modules

+# Ignore the build directory
+dist

build スクリプトを実行します。

$ pnpm run build --filter=@hayato94087/geometry

> turborepo-changesets-template@ build /Users/hayato94087/Private/turborepo-changesets-template
> turbo run build "--filter=@hayato94087/geometry"

• Packages in scope: @hayato94087/geometry
• Running build in 1 packages
• Remote caching disabled
@hayato94087/geometry:build: cache miss, executing 154c5affa76095e9
@hayato94087/geometry:build: 
@hayato94087/geometry:build: > @hayato94087/geometry@ build /Users/hayato94087/Private/turborepo-changesets-template/packages/geometry
@hayato94087/geometry:build: > tsup index.ts --format cjs,esm --dts --minify
@hayato94087/geometry:build: 
@hayato94087/geometry:build: CLI Building entry: index.ts
@hayato94087/geometry:build: CLI Using tsconfig: tsconfig.json
@hayato94087/geometry:build: CLI tsup v7.2.0
@hayato94087/geometry:build: CLI Target: es2016
@hayato94087/geometry:build: CJS Build start
@hayato94087/geometry:build: ESM Build start
@hayato94087/geometry:build: ESM dist/index.mjs 45.00 B
@hayato94087/geometry:build: ESM ⚡️ Build success in 218ms
@hayato94087/geometry:build: CJS dist/index.js 535.00 B
@hayato94087/geometry:build: CJS ⚡️ Build success in 218ms
@hayato94087/geometry:build: DTS Build start
@hayato94087/geometry:build: DTS ⚡️ Build success in 1154ms
@hayato94087/geometry:build: DTS dist/index.d.ts  90.00 B
@hayato94087/geometry:build: DTS dist/index.d.mts 90.00 B

 Tasks:    1 successful, 1 total
Cached:    0 cached, 1 total
  Time:    3.669s 

dist フォルダが作成され、index.jsindex.mjsindex.d.tsindex.d.mts が作成されていることが確認できます。

$ tree packages/geometry/dist

dist
├── index.d.mts
├── index.d.ts
├── index.js
└── index.mjs

コミットします。

$ git add .
$ git commit -m "add tsup and update .gitignore"

4.9 package.jsonを修正

package.json を修正します。lint スクリプトを追加します。

packages/geometry/package.json
{
  "scripts": {
    "build": "tsup index.ts --format cjs,esm --dts --minify",
+   "lint": "tsc"
  },
  "devDependencies": {
    "tsup": "^7.2.0",
    "typescript": "^5.2.2"
  }
}

tsc で文法チェックします。

$ pnpm run lint --filter=@hayato94087/geometry

> turborepo-changesets-template@ lint /Users/hayato94087/Private/turborepo-changesets-template
> turbo run lint "--filter=@hayato94087/geometry"

• Packages in scope: @hayato94087/geometry
• Running lint in 1 packages
• Remote caching disabled
@hayato94087/geometry:lint: cache miss, executing 08715360dc9af4f1
@hayato94087/geometry:lint: 
@hayato94087/geometry:lint: > @hayato94087/geometry@ lint /Users/hayato94087/Private/turborepo-changesets-template/packages/geometry
@hayato94087/geometry:lint: > tsc
@hayato94087/geometry:lint: 

 Tasks:    1 successful, 1 total
Cached:    0 cached, 1 total
  Time:    2.56s 

コミットします。

$ git add .
$ git commit -m "add lint to package.json"

4.10. README.mdの追加

README.md を追加します。

$ touch packages/geometry/README.md
packages/geometry/README.md
# features

- rectangleArea

コミットします。

$ git add .
$ git commit -m "add README.md"

4.11. package.jsonを修正

GitHub Packages をパッケージを公開するために package.json を設定します。

packages/geometry/package.json
{
  "name": "@hayato94087/geometry",
+ "version": "0.0.1",
+ "license": "UNLICENSED",
+ "main": "dist/index.js",
+ "module": "dist/index.mjs",
+ "types": "dist/index.d.ts",
+ "repository": {
+   "type": "git",
+   "url": "https://github.com/hayato94087/turborepo-changesets-template.git",
+   "directory": "packages/geometry"
+ },
+ "files": [
+   "dist"
+ ],
+ "private": false,
  "scripts": {
    "build": "tsup index.ts --format cjs,esm --dts --minify",
    "lint": "tsc"
  },
  "devDependencies": {
    "tsup": "^7.2.0",
    "typescript": "^5.2.2"
  }
}
項目 説明
name GitHub Packages に公開するパッケージ名です。@{GitHubのユーザー名 or 組織名}/{リポジトリ名} のフォーマットで記述します。ここでは、@hayato94087/geometry と記述します。
version GitHub Packages で公開するパッケージのバージョンを指定します。ここでは初期のバージョンとして 0.0.1 と指定します。
license パッケージのライセンスです。ここでは UNLICENSED を指定します。
main 呼び出す側が参照するファイルを指定します。tsup で作成されるファイルを指定します。
module ES モジュールを指定します。tsup で作成されるファイルを指定します。
types 型定義ファイルを指定します。tsup で作成されるファイルを指定します。型定義を export しない場合は指定不要です。
repository.type repositoryのtypeを指定します。ここでは git を指定します。
repository.url repositoryのurlを指定します。
repository.directory repositoryのdirectoryを指定します。
files パッケージに含めるファイルを指定します。dist フォルダを指定します。
private パッケージを公開するかどうかを指定します。true を指定します。

コミットします。

$ git add .
$ git commit -m "add items to package.json"

5. arithmetic パッケージを作成

限定公開するパッケージを作成します。パッケージには add を含みます。

packages/arithmetic/index.ts
export const add = (a: number, b: number) => {
  return a + b;
};

パッケージ作成詳細

5.1. パッケージのプロジェクトフォルダを作成

プロジェクトフォルダを作成します。

$ mkdir -p packages/arithmetic

5.2. package.jsonを作成

package.json を作成します。

$ touch packages/arithmetic/package.json
packages/arithmetic/package.json
{
  "name": "@hayato94087/arithmetic",
}

コミットします。

$ git add .
$ git commit -m "add package.json"

5.3. TypeScriptを追加

TypeScript を devDependencies に追加します。

$ pnpm add -D typescript --filter=@hayato94087/arithmetic

.gitignore を作成し、node_modules をリポジトリの管理対象外とします。

$ touch packages/arithmetic/.gitignore
packages/arithmetic/.gitignore
# Ignore bundler config
node_modules

コミットします。

$ git add .
$ git commit -m "add typescript, .gitignore"

5.4. tsconfig.jsonを作成

tsconfig.json を作成します。

$ touch packages/arithmetic/tsconfig.json

作成された tsconfig.jsonnoUncheckedIndexedAccessnoEmit を追加します。noEmit をついかしているのは、tsc を linter として利用するためです。

packages/arithmetic/tsconfig.json
{
  "compilerOptions": {
    "target": "es2016",                                  /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
    "module": "commonjs",                                /* Specify what module code is generated. */
    "esModuleInterop": true,                             /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
    "forceConsistentCasingInFileNames": true,            /* Ensure that casing is correct in imports. */
    "strict": true,                                      /* Enable all strict type-checking options. */
    "skipLibCheck": true,                                 /* Skip type checking all .d.ts files. */
    "noUncheckedIndexedAccess": true,                     /* Include 'undefined' in index signature results */
    "noEmit": true                                        /* Do not emit outputs. */
  }
}

コミットします。

$ git add .
$ git commit -m "add tsconfig.json"

5.7. index.tsを作成

index.ts で足し算の関数を作成します。

$ touch packages/arithmetic/index.ts
packages/arithmetic/index.ts
export const rectangleArea = (a: number, b: number) => {
  return a * b;
};

コミットします。

$ git add .
$ git commit -m "add add"

5.8. tsup を設定

tsupは、TypeScript のバンドラです。

tsup を devDependencies に追加します。

$ pnpm add -D tsup --filter=@hayato94087/arithmetic

build スクリプトを package.json に追加します。

packages/arithmetic/package.json
{
 "name": "@hayato94087/arithmetic",
+ "scripts": {
+   "build": "tsup index.ts --format cjs,esm --dts --minify"
+ },
  "devDependencies": {
    "tsup": "^7.2.0",
    "typescript": "^5.2.2"
  }
}

.gitignoredist を追加します。

packages/arithmetic/.gitignore
# Ignore bundler config
node_modules

+# Ignore the build directory
+dist

build スクリプトを実行します。

$ pnpm run build --filter=@hayato94087/arithmetic

> turborepo-changesets-template@ build /Users/hayato94087/Private/turborepo-changesets-template
> turbo run build "--filter=@hayato94087/arithmetic"

• Packages in scope: @hayato94087/arithmetic
• Running build in 1 packages
• Remote caching disabled
@hayato94087/arithmetic:build: cache miss, executing 3e58e9d8f7f6fd3c
@hayato94087/arithmetic:build: 
@hayato94087/arithmetic:build: > @hayato94087/arithmetic@ build /Users/hayato94087/Private/turborepo-changesets-template/packages/arithmetic
@hayato94087/arithmetic:build: > tsup index.ts --format cjs,esm --dts --minify
@hayato94087/arithmetic:build: 
@hayato94087/arithmetic:build: CLI Building entry: index.ts
@hayato94087/arithmetic:build: CLI Using tsconfig: tsconfig.json
@hayato94087/arithmetic:build: CLI tsup v7.2.0
@hayato94087/arithmetic:build: CLI Target: es2016
@hayato94087/arithmetic:build: CJS Build start
@hayato94087/arithmetic:build: ESM Build start
@hayato94087/arithmetic:build: ESM dist/index.mjs 35.00 B
@hayato94087/arithmetic:build: ESM ⚡️ Build success in 26ms
@hayato94087/arithmetic:build: CJS dist/index.js 515.00 B
@hayato94087/arithmetic:build: CJS ⚡️ Build success in 27ms
@hayato94087/arithmetic:build: DTS Build start
@hayato94087/arithmetic:build: DTS ⚡️ Build success in 1074ms
@hayato94087/arithmetic:build: DTS dist/index.d.ts  70.00 B
@hayato94087/arithmetic:build: DTS dist/index.d.mts 70.00 B

 Tasks:    1 successful, 1 total
Cached:    0 cached, 1 total
  Time:    3.887s 

dist フォルダが作成され、index.jsindex.mjsindex.d.tsindex.d.mts が作成されていることが確認できます。

$ tree packages/arithmetic/dist

dist
├── index.d.mts
├── index.d.ts
├── index.js
└── index.mjs

コミットします。

$ git add .
$ git commit -m "add tsup and update .gitignore"

5.9 package.jsonを修正

package.json を修正します。lint スクリプトを追加します。

packages/arithmetic/package.json
{
  "scripts": {
    "build": "tsup index.ts --format cjs,esm --dts --minify",
+   "lint": "tsc"
  },
  "devDependencies": {
    "tsup": "^7.2.0",
    "typescript": "^5.2.2"
  }
}

tsc で文法チェックします。

$ pnpm run lint --filter=@hayato94087/arithmetic

> turborepo-changesets-template@ lint /Users/hayato94087/Private/turborepo-changesets-template
> turbo run lint "--filter=@hayato94087/arithmetic"

• Packages in scope: @hayato94087/arithmetic
• Running lint in 1 packages
• Remote caching disabled
@hayato94087/arithmetic:lint: cache miss, executing 37a12c373b5be886
@hayato94087/arithmetic:lint: 
@hayato94087/arithmetic:lint: > @hayato94087/arithmetic@ lint /Users/hayato94087/Private/turborepo-changesets-template/packages/arithmetic
@hayato94087/arithmetic:lint: > tsc
@hayato94087/arithmetic:lint: 

 Tasks:    1 successful, 1 total
Cached:    0 cached, 1 total
  Time:    2.56s 

コミットします。

$ git add .
$ git commit -m "add lint to package.json"

5.10. README.mdの追加

README.md を追加します。

$ touch packages/arithmetic/README.md
packages/arithmetic/README.md
# features

- add

コミットします。

$ git add .
$ git commit -m "add README.md"

5.11. package.jsonを修正

GitHub Packages をパッケージを公開するために package.json を設定します。

packages/arithmetic/package.json
{
  "name": "@hayato94087/arithmetic",
+ "version": "0.0.1",
+ "license": "UNLICENSED",
+ "main": "dist/index.js",
+ "module": "dist/index.mjs",
+ "types": "dist/index.d.ts",
+ "repository": {
+   "type": "git",
+   "url": "https://github.com/hayato94087/turborepo-changesets-template.git",
+   "directory": "packages/arithmetic"
+ },
+ "files": [
+   "dist"
+ ],
+ "private": false,
  "scripts": {
    "build": "tsup index.ts --format cjs,esm --dts --minify",
    "lint": "tsc"
  },
  "devDependencies": {
    "tsup": "^7.2.0",
    "typescript": "^5.2.2"
  }
}
項目 説明
name GitHub Packages に公開するパッケージ名です。@{GitHubのユーザー名 or 組織名}/{リポジトリ名} のフォーマットで記述します。ここでは、@hayato94087/arithmetic と記述します。
version GitHub Packages で公開するパッケージのバージョンを指定します。ここでは初期のバージョンとして 0.0.1 と指定します。
license パッケージのライセンスです。ここでは UNLICENSED を指定します。
main 呼び出す側が参照するファイルを指定します。tsup で作成されるファイルを指定します。
module ES モジュールを指定します。tsup で作成されるファイルを指定します。
types 型定義ファイルを指定します。tsup で作成されるファイルを指定します。型定義を export しない場合は指定不要です。
repository.type repositoryのtypeを指定します。ここでは git を指定します。
repository.url repositoryのurlを指定します。
repository.directory repositoryのdirectoryを指定します。
files パッケージに含めるファイルを指定します。dist フォルダを指定します。
private パッケージを公開するかどうかを指定します。false を指定します。true を設定すると公開・限定公開対象になりません。

コミットします。

$ git add .
$ git commit -m "add items to package.json"

6. changeset-botを設定

changeset-bot とは、GitHub のプルリクエストに対して、changeset を自動で作成してくれる GitHub App です。GitHub にログインし、changeset-bot のプラグインを以下のサイトからインストールします。

https://github.com/apps/changeset-bot

changeset-botのインストール方法

「Install」をクリックします。

Alt text

「All repositories」を選択し、「Install」をクリックします。(特定のリポジトリを選択しても良いです)

Alt text

これで changeset-bot の設定完了です。

7. changesets を設定

Changesets CLIをパッケージを管理するためのツールです。こちらをモノレポに設定します。

changesetsの設定方法

7.1 changesets をインストール

changesetsdevDependency にインストールします。

$ pnpm add -Dw @changesets/cli

コミットします。

$ git add .
$ git commit -m "add changesets"

7.2 changesets を初期化

changeset init で設定を初期化します。

$ pnpm 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

設定を初期化後に、1 フォルダ、2 ファイルが作成されます。

$ tree .changeset

.changeset
├── README.md
└── config.json

1 directory, 2 files

以下が作成されたファイルの中身です。

.changeset/config.json
{
  "$schema": "https://unpkg.com/@changesets/config@2.3.1/schema.json",
  "changelog": "@changesets/cli/changelog",
  "commit": false,
  "fixed": [],
  "linked": [],
  "access": "restricted",
  "baseBranch": "main",
  "updateInternalDependencies": "patch",
  "ignore": []
}
README.md
# 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)

コミットします。

$ git add .
$ git commit -m "initialize changesets"

7.3. コマンドを追加

package.json にパッケージをリリースするためのコマンドを追加します。release コマンドは、次に記載する GitHub Actions で実行されます。

package.json
{
  "private": true,
  "scripts": {
    "build": "turbo run build",
    "dev": "turbo run dev",
    "lint": "turbo run lint",
    "format": "prettier --write \"**/*.{ts,tsx,md}\"",
+   "changeset": "changeset",
+   "version-packages": "changeset version",
+   "release": "turbo run build && changeset publish"
  },
  "devDependencies": {
    "@changesets/cli": "^2.26.2",
    "eslint": "^8.48.0",
    "prettier": "^3.0.3",
    "tsconfig": "workspace:*",
    "turbo": "latest"
  },
  "packageManager": "pnpm@8.6.10",
  "name": "turborepo-geometry"
}

コミットします。

$ git add .
$ git commit -m "add script"

7.4. changelog のフォーマットを変更

changelog に自動的にプルリクとプルリク作成者のリンクを追加できるようにします。

参考までに以下のように changesets が生成する CHANGELOG.md にて、プルリクのリンクと作成者が表示される表になります。

Alt text

@changesets/changelog-github をインストールします。

$ pnpm add -Dw @changesets/changelog-github
.changeset/config.json
{
  "$schema": "https://unpkg.com/@changesets/config@2.3.1/schema.json",
- "changelog": "@changesets/cli/changelog",
+ "changelog": [
+   "@changesets/changelog-github",
+   { "repo": "hayato94087/turborepo-changesets-template" }
+ ],
  "commit": false,
  "fixed": [],
  "linked": [],
  "access": "restricted",
  "baseBranch": "main",
  "updateInternalDependencies": "patch",
  "ignore": []
}

コミットします。

$ git add .
$ git commit -m "add changelog-github"

8. GitHub Actions を設定

GitHub Actions を設定します。GitHub Actions は、GitHub が提供する CI/CD サービスです。GitHub Actions を利用することで、GitHub 上で CI/CD を実行できます。

ここでは3つの GitHub Actions のワークフローを作成します。

ワークフロー 説明
Continuous Integration いずれかのブランチにプッシュされるとlintとbuildが実行されます。
Release mainブランチにプッシュすると、changesetを作成し、パッケージをリリースします。

GitHub Actionsの設定方法

8.1. GitHub Actions の処理を定義したymlファイルを作成

GitHub Actions の yml ファイルを2つ作成します。

$ mkdir -p .github/workflows
$ touch .github/workflows/continuous-integration.yml
$ touch .github/workflows/release.yml
.github/workflows/continuous-integration.yml
name: Continuous Integration
on:
  push:
    branches:
      - "**"

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: pnpm/action-setup@v2
        with:
          version: 8
      - uses: actions/setup-node@v3
        with:
          node-version: 18
          registry-url: https://npm.pkg.github.com/
          scope: "@hayato94087"
          cache: "pnpm"

      - run: pnpm install --frozen-lockfile
      - run: pnpm run lint && pnpm run format && pnpm run build
.github/workflows/release.yml
name: Release

on:
  workflow_run:
    workflows: ["Continuous Integration"]
    types:
      - completed
  push:
    branches:
      - "main"


concurrency: ${{ github.workflow }}-${{ github.ref }}

permissions:
  contents: write
  issues: write
  pull-requests: write
  packages: write

jobs:
  build:
    if: ${{ github.event.workflow_run.conclusion == 'success' }}
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: pnpm/action-setup@v2
        with:
          version: 8
      - uses: actions/setup-node@v3
        with:
          node-version: 18
          registry-url: https://npm.pkg.github.com/
          scope: "@hayato94087"
          cache: "pnpm"

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

      - name: Creating .npmrc
        run: |
          echo "@username:registry=https://npm.pkg.github.com" >> .npmrc
          echo "//npm.pkg.github.com/:_authToken=${{ secrets.GITHUB_TOKEN }}" >> .npmrc

      - name: Create Release Pull Request or Publish to npm
        id: changesets
        uses: changesets/action@v1
        with:
          publish: pnpm run release
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

コミットします。

$ git add .
$ git commit -m "add yml files for GitHub Actions"

9. リリース作業

GitHub リポジトリを作成し、リポジトリにモノレポをアップし、arithmeticgeometry パッケージをリリースします。

リリース作業

9.1. GitHub のリポジトリを作成

GitHub のリポジトリを作成しコードをアップします。まず、リポジトリを作成します。

Alt text

以下を実行しリポジトリにアップします。

$ git remote add origin https://github.com/hayato94087/turborepo-changesets-template.git
$ git branch -M main
$ git push -u origin main

コードがアップされました。

Alt text

以下のように、GitHub Actions が実行されます。ただし、「Snapshot Release@next」は初回失敗します。おそらく GitHub Packages にパッケージがまだリリースされていないからです。

Alt text

無事パッケージ 0.0.1 がリリースされました。

Alt text
Alt text
Alt text

9.2. GitHub Actions にプルリクエストを実行する権限を付与


デフォルトでは、GitHub Actions はプルリクエストを実行する権限がありません。こちらの権限を付与します。リポジトリの「Settings」->「Actions」→「General」->「Workflow permissions」->「Allow Github Actions to create and approve pull requests」をチェックし、「Save」をクリックします。

Alt text

10. 機能を追加

arithmetic パッケージに subtract を追加します。

packages/arithmetic/index.ts
export const add = (a: number, b: number) => {
  return a + b;
};

export const subtract = (a: number, b: number) => {
  return a - b;
};

geometry パッケージに triangleArea を追加します。

export const rectangleArea = (a: number, b: number) => {
  return a * b;
};

export const triangleArea = (a: number, b: number) => {
  return (a * b) / 2;
};

subtractを追加

10.1. subtractを追加

ブランチを作成します。

$ git checkout -b feature/add-subtract

subtract を追加します。

packages/arithmetic/index.ts
export const add = (a: number, b: number) => {
  return a + b;
};

+export const subtract = (a: number, b: number) => {
+  return a - b;
+};

lint を build を実施します。

$ pnpm run lint --filter=@hayato94087/artichmetic
$ pnpm run build --filter=@hayato94087/artichmetic

README.md を修正します。

packages/arithmetic/README.md
# features

- add
- subtract

コミットします。

$ git add .
$ git commit -m "add subtract"

triangleAreaを追加

10.2. triangleAreaブランチ作成

ブランチを作成します。

$ git checkout -b feature/add-triangleArea

subtract を追加します。

packages/geometry/index.ts
export const rectangleArea = (a: number, b: number) => {
  return a * b;
};

+export const triangleArea = (a: number, b: number) => {
+  return (a * b) / 2;
+};

lint を build を実施します。

$ pnpm run lint --filter=@hayato94087/geometry
$ pnpm run build --filter=@hayato94087/geometry

README.md を修正します。

packages/geometry/README.md
# features

- rectangleArea
- triangleArea

コミットします。

$ git add .
$ git commit -m "add triangleArea"

11. パッケージを更新

作成した subtracttriangleArea をリリースします。

11.1. lintとformatを実行

ブランチを作成します。

$ git checkout -b feature/add-changeset

lint と format を実行します。

$ pnpm run lint && pnpm run format

11.2. arithmetic パッケージ用のchangesetを作成

changesetchangeset を作成します。

$ pnpm run changeset

🦋  Which packages would you like to include? · @hayato94087/arithmetic
🦋  Which packages should have a major bump? · No items were selected
🦋  Which packages should have a minor bump? · No items were selected
🦋  The following packages will be patch bumped:
🦋  @hayato94087/arithmetic@0.0.1
🦋  Please enter a summary for this change (this will be in the changelogs).
🦋    (submit empty line to open external editor)
🦋  Summary · add subtract
🦋  
🦋  === Summary of changesets ===
🦋  patch:  @hayato94087/arithmetic
🦋  
🦋  Note: All dependents of these packages that will be incompatible with
🦋  the new version will be patch bumped when this changeset is applied.
🦋  
🦋  Is this your desired changeset? (Y/n) · true
🦋  Changeset added! - you can now commit it
🦋  
🦋  If you want to modify or expand on the changeset summary, you can find it here
🦋  info /Users/hayato94087/Private/turborepo-changesets-template/.changeset/shiny-papayas-check.md

下記のファイルが作成されました。

.changeset/shiny-papayas-check.md
---
"@hayato94087/arithmetic": patch
---

add subtract

11.3. geometry パッケージ用のchangesetを作成

changesetchangeset を作成します。

$ pnpm run changeset

  Which packages would you like to include? · @hayato94087/geometry
🦋  Which packages should have a major bump? · No items were selected
🦋  Which packages should have a minor bump? · No items were selected
🦋  The following packages will be patch bumped:
🦋  @hayato94087/geometry@0.0.1
🦋  Please enter a summary for this change (this will be in the changelogs).
🦋    (submit empty line to open external editor)
🦋  Summary · add triangleArea
🦋  
🦋  === Summary of changesets ===
🦋  patch:  @hayato94087/geometry
🦋  
🦋  Note: All dependents of these packages that will be incompatible with
🦋  the new version will be patch bumped when this changeset is applied.
🦋  
🦋  Is this your desired changeset? (Y/n) · true
🦋  Changeset added! - you can now commit it
🦋  
🦋  If you want to modify or expand on the changeset summary, you can find it here
🦋  info /Users/hayato94087/Private/turborepo-changesets-template/.changeset/slow-spoons-float.md

下記のファイルが作成されました。

.changeset/slow-spoons-float.md
---
"@hayato94087/geometry": patch
---

add triangleArea

11.4. リポジトリを更新

リポジトリにプッシュします。

$ git add .
$ git commit -m "perform lint and format and create changesets"
$ git push origin feature/add-changeset

GitHub Actions & プルリクでパッケージを更新します。

パッケージの更新手順

以下のように、GitHub Actions が実行されます。今回は、「Snapshot Release@next」が実行されました。

Alt text

「Compare & pull request」をクリックします。

Alt text

「Create pull request」をクリックし、main ブランチにプルリクエストを作成します。

Alt text

プルリクエストが作成されました。先程作成した arithmeticgeometry パッケージの更新のための changeset に対して changeset-bot が反応しています。「Merge pull request」をクリックします。

Alt text

「Confirm merge」をクリックします。

Alt text

ワークフローが実行されます。

Alt text

プルリクを確認すると、「Verson Packages」が作成されています。

Alt text

「Merge pull request」をクリックすることで、バージョンが 0.0.2 にあがります。

Alt text

「Confirm merge」をクリックします。

Alt text

ワークフローが実行されます。

Alt text

バージョンが 0.0.2 になりました。

Alt text
Alt text

12. パッケージを利用

限定公開したパッケージを利用します。

以下が手順です。

  • GitHub から Personal access token を取得する必要があります。
    - .npmrc を作成し、Personal access token を記載します。
  • パッケージをインストールします。
  • パッケージをインポートして利用します。

12.1. Personal access tokenを取得

GitHub から Personal access token を取得します。

PAT取得手順詳細

GitHub アカウントを開き、Settings をクリックします。

Alt text

Developer settings をクリックします。

Alt text

Tokens(classic) をクリックします。

Alt text

Alt text

名前を入力し、トークンの有効期限を短めに設定し、read:packages にチェックを入れます。

Alt text

Generate token をクリックします。

Alt text

コピーしておきます。

Alt text

12.2. .npmrcを編集

.npmrc を編集しトークンを設定します。

.npmrcの設定

以下のようなルールで記述します。

.npmrc
...
@{GitHubのユーザー名 or 組織名}:registry=https://npm.pkg.github.com/
//npm.pkg.github.com/:_authToken=<取得した Personal Access Token の値>
...

私の場合は、以下のようになります。

.npmrc
...
@hayato94087:registry=https://npm.pkg.github.com/
//npm.pkg.github.com/:_authToken=xxxxxxxxxxxxxxxxxx
...

あるいは、環境変数として保存して利用する方法もあります。今回はこちらを利用します。

.npmrc
...
@{GitHubのユーザー名 or 組織名}:registry=https://npm.pkg.github.com/
//npm.pkg.github.com/:_authToken=${NPM_TOKEN}
...

私の場合は、以下のようになります。

.npmrc
...
@hayato94087:registry=https://npm.pkg.github.com/
//npm.pkg.github.com/:_authToken=${NPM_TOKEN}
...

.zshrc に以下を追記します。

.zshrc
export NPM_TOKEN=<取得した Personal Access Token の値>

更に .npmrc の参考ファイルを作成します。

$ touch .npmrc.example
.npmrc.example
@hayato94087:registry=https://npm.pkg.github.com/
//npm.pkg.github.com/:_authToken=${NPM_TOKEN}

設定を反映します。

$ source ~/.zshrc

12.3. パッケージをインストール

パッケージをインストールします。するとエラーが出ます。

$ pnpm add @hayato94087/arithmetic --filter=web

 ERR_PNPM_REGISTRIES_MISMATCH  This modules directory was created using the following registries configuration: {"@NAMESPACE":"https://npm.pkg.github.com/","default":"https://registry.npmjs.org/"}. The current configuration is {"default":"https://registry.npmjs.org/","@NAMESPACE":"https://npm.pkg.github.com/","@hayato94087":"https://npm.pkg.github.com/"}. To recreate the modules directory using the new settings, run "pnpm install".

エラーメッセージの内容にしたがい、pnpm install を実行します。

$ pnpm install

Scope: all 8 workspace projects
✔ The modules directories will be removed and reinstalled from scratch. Proceed? (Y/n) · true
Recreating /Users/hayato94087/Private/turborepo-changesets-template/node_modules

Lockfile is up to date, resolution step is skipped
Packages: +718
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Packages are hard linked from the content-addressable store to the virtual store.
  Content-addressable store is at: /Users/hayato94087/Library/pnpm/store/v3
  Virtual store is at:             node_modules/.pnpm
Progress: resolved 718, reused 718, downloaded 0, added 718, done
node_modules/.pnpm/core-js-pure@3.32.1/node_modules/core-js-pure: Running postinstall script, done in 122ms

devDependencies:
+ @changesets/changelog-github 0.4.8
+ @changesets/cli 2.26.2
+ eslint 8.48.0
+ prettier 3.0.3
+ tsconfig 0.0.0 <- packages/tsconfig
+ turbo 1.10.14

The integrity of 3283 files was checked. This might have caused installation to take longer.
Done in 31s

以下のようにパッケージをインストールします。

$ pnpm add @hayato94087/arithmetic --filter=web 
$ pnpm add @hayato94087/geometry --filter=web 

すると、package.json では、workspace を参照するようになります。

apps/web/package.json
{
  ...
  "dependencies": {
    "@hayato94087/arithmetic": "workspace:^",
    "@hayato94087/geometry": "workspace:^",
    ...
  },
  ...
}

geometry0.0.1 を利用し、arithmeticworkspace を利用してみます。geometry0.0.1 なので、triangleArea は利用できません。

apps/web/package.json
{
  ...
  "dependencies": {
    "@hayato94087/arithmetic": "workspace:^",
    "@hayato94087/geometry": "0.0.1",
    ...
  },
  ...
}

パッケージをインストールします。

$ pnpm i

12.4. パッケージをインポートし利用

page.tsx で利用します。

apps/web/page.tsx
import { rectangleArea } from "@hayato94087/geometry";
import { add, subtract } from "@hayato94087/arithmetic";

export default function Page(): JSX.Element {
  return (
    <>
      <h1 className="text-xl">Web</h1>
      <p>2 * 3 = {rectangleArea(2, 3)}</p>
      <p>2 + 3 = {add(2, 3)}</p>
      <p>2 - 3 = {subtract(2, 3)}</p>
    </>
  );
}

ローカルで実行します。

$ pnpm dev --filter=web 

Alt text

コミットします。

$ git add .
$ git commit -m "used package from GitHub Packages"

13. まとめ

自分専用、あるいは社内のみで利用するパッケージを GitHub Actions を介して、GitHub Packages に限定公開する方法を説明しました。プロジェクトは Turoborepo で管理されていることを想定しました。

作業リポジトリは以下です。

https://github.com/hayato94087/turborepo-changesets-template

14. 参考

https://uit-inside.linecorp.com/episode/132

https://github.com/vercel/turbo/tree/main/examples/design-system

https://github.com/anthonyhastings/turborepo-design-system

https://github.com/alexrusin/react-express-turbo

https://github.com/hayato94087/turborepo-nextjs-external-package-sample

https://zenn.dev/uttk/articles/create-pnpm-monorepo

https://turbo.build/repo/docs/handbook/publishing-packages/versioning-and-publishing

https://uit-inside.linecorp.com/episode/132

https://qiita.com/macropygia/items/7d9a06cf33ec4997dcfa

https://qiita.com/macropygia/items/c74d3c1f27addb70b280

https://vercel.com/templates/react/turborepo-design-system

https://zenn.dev/mouse_484/articles/easy-changesets

https://github.com/apps/changeset-bot

https://zenn.dev/mouse_484/articles/easy-changesets

https://github.com/anthonyhastings/turborepo-design-system

https://efcl.info/2023/07/17/regular-updates-by-changesets/

Discussion