🦭

GitHub Actions で GitHub Packages にパッケージを限定公開

2023/09/21に公開

1. はじめに

自分専用、あるいは社内のみで利用するパッケージを GitHub Actions を介して、GitHub Packages に限定公開する方法を説明します。特に、以下の記事を参考に記述しました。

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

限定公開に利用したパッケージは、以下のリポジトリです。

https://github.com/hayato94087/math-helpers-arithmetics-github-actions-publish

限定公開したパッケージをインポートし利用したプロジェクトは、以下のリポジトリです。

https://github.com/hayato94087/math-helpers-arithmetics-github-actions-publish-read

2. 限定公開するパッケージを作成

限定公開するパッケージを作成します。

2.1. プロジェクトフォルダを作成

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

$ mkdir math-helpers-arithmetics-github-actions-publish
$ cd math-helpers-arithmetics-github-actions-publish

2.2. ローカルリポジトリを作成

ローカルリポジトリを作成します。

$ git init

2.3. package.jsonを作成

package.json を作成します。

  • name は、GitHub Packages に公開するパッケージ名です。@{GitHubのユーザー名 or 組織名}/{リポジトリ名} のフォーマットで記述します。
  • license は、パッケージのライセンスです。
$ touch package.json
package.json
{
}

コミットします。

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

2.4. TypeScriptを追加

TypeScript を devDependencies に追加します。

$ pnpm add -D typescript

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

$ touch .gitignore
.gitignore
# Ignore bundler config
node_modules

コミットします。

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

2.5. tsconfig.jsonを作成

tsconfig.json を作成します。

$ pnpm tsc --init

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

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"

2.6. index.tsを作成

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

$ touch index.ts
index.ts
export const add = (a: number, b: number) => {
  return a + b
}

コミットします。

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

2.7. tsup を設定

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

tsup を devDependencies に追加します。

$ pnpm add -D tsup

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

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

.gitignoredist を追加します。

.gitignore
# Ignore bundler config
node_modules

+# Ignore the build directory
+dist

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

$ pnpm run build

CLI Building entry: index.ts
CLI Using tsconfig: tsconfig.json
CLI tsup v7.2.0
CLI Target: es2016
CJS Build start
ESM Build start
ESM dist/index.mjs 35.00 B
ESM ⚡️ Build success in 209ms
CJS dist/index.js 515.00 B
CJS ⚡️ Build success in 210ms
DTS Build start
DTS ⚡️ Build success in 974ms
DTS dist/index.d.ts  70.00 B
DTS dist/index.d.mts 70.00 B

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

$ tree dist

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

以下が作成されたファイルです。--minify を指定しているので、index.jsindex.mjs は、minify されています。

dist/index.d.mts
declare const add: (a: number, b: number) => number;

export { add };
dist/index.d.ts
declare const add: (a: number, b: number) => number;

export { add };
dist/index.js
"use strict";var u=Object.defineProperty;var d=Object.getOwnPropertyDescriptor;var m=Object.getOwnPropertyNames;var o=Object.prototype.hasOwnProperty;var a=(e,r)=>{for(var t in r)u(e,t,{get:r[t],enumerable:!0})},c=(e,r,t,b)=>{if(r&&typeof r=="object"||typeof r=="function")for(let n of m(r))!o.call(e,n)&&n!==t&&u(e,n,{get:()=>r[n],enumerable:!(b=d(r,n))||b.enumerable});return e};var p=e=>c(u({},"__esModule",{value:!0}),e);var x={};a(x,{add:()=>s});module.exports=p(x);var s=(e,r)=>e+r;0&&(module.exports={add});
dist/index.mjs
var n=(r,e)=>r+e;export{n as add};

--minify を指定していない場合は、index.jsindex.mjs は、minify されません。

dist/index.js
"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);

// index.ts
var package_release_sample_exports = {};
__export(package_release_sample_exports, {
  add: () => add
});
module.exports = __toCommonJS(package_release_sample_exports);
var add = (a, b) => {
  return a + b;
};
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  add
});
dist/index.mjs
// index.ts
var add = (a, b) => {
  return a + b;
};
export {
  add
};

コミットします。

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

2.8 package.jsonを修正

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

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

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

$ pnpm run lint

> @hayato94087/math-helpers-arithmetics-github-actions-publish@ lint /Users/hayato94087/Private/math-helpers-arithmetics-github-actions-publish
> tsc

コミットします。

$ git add .
$ git commit -m "add main, module, types, add lint to package.json"

2.9. lintの補足説明

lint の補足です。

2.9.1. noEmit

もし、noEmitfalse の場合、tsc を実行すると index.js というファイルを作成します。

package.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. */
+   "noEmit": false                                        /* Do not emit outputs. */
  }
}

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

$ pnpm run lint

> @hayato94087/math-helpers-arithmetics-github-actions-publish@ lint /Users/hayato94087/Private/math-helpers-arithmetics-github-actions-publish
> tsc

すると、index.js が作成されます。

Alt text

index.js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.add = void 0;
const add = (a, b) => {
    return a + b;
};
exports.add = add;

tsc を linter として利用する場合は、noEmittrue に設定しておきます。

package.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. */
-   "noEmit": false                                        /* Do not emit outputs. */
  }
}

以下のように作成された index.js は削除しておき、lint スクリプトを実行し、元の状態に戻しておきます。

$ rm -f index.js
$ pnpm run lint

2.9.2. Lintエラーの場合

tsc で Lint し、エラーがあった場合は、lint スクリプトを実行するとエラーが出ます。

以下のように、index.ts を修正し、バグを入れます。

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

lint スクリプトを実行します。以下のようにエラーが出ます。

$ pnpm run lint

index.ts:2:10 - error TS2365: Operator '+' cannot be applied to types 'boolean' and 'number'.

2   return a + b;
           ~~~~~

Found 1 error in index.ts:2

バグを修正しておきます。

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

2.10. README.mdの追加

README.md を追加します。

$ touch README.md
README.md
# features

- add

コミットします。

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

3. GitHub Packagesで公開

ローカルから GitHub Packages で公開するため設定します。

3.1. 公開に向けてpackage.jsonを修正

GitHub Packages を使い公開出来るよう package.json を設定します。

package.json
{
+ "name": "@hayato94087/math-helpers-arithmetics-github-actions-publish",
+ "version": "0.0.1",
+ "license": "UNLICENSED",
+ "main": "dist/index.js",
+ "module": "dist/index.mjs",
+ "types": "dist/index.d.ts",
+ "publishConfig": {
+   "access": "restricted",
+   "registry": "https://npm.pkg.github.com/"
+ },
+ "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のユーザー名 or 組織名}/{リポジトリ名} にします。インストールする際は、pnpm add @{GitHubのユーザー名 or 組織名}/{リポジトリ名} となります。
  • version は、GitHub Packages で公開するパッケージのバージョンを指定します。
  • license は、パッケージのライセンスを指定します。"UNLICENSED"を指定します。
  • main は呼び出す側が参照するファイルを指定します。tsup で作成されたファイルを指定します。
  • module は ES モジュールを指定します。tsup で作成されたファイルを指定します。
  • types は型定義ファイルを指定します。tsup で作成されたファイルを指定します。型定義を export しない場合は指定不要です。
  • publishConfig はパッケージを公開するための設定を記載します。こちら参照
    • access はパッケージの公開範囲を指定します。public は公開、restricted は制限付き公開です。
    • registry はパッケージを公開するレジストリを指定します。https://npm.pkg.github.com/ を指定します。
  • files はパッケージに含めるファイルを指定します。dist フォルダを指定します。
  • private はパッケージを公開するかどうかを指定します。false を指定します。デフォルトは false のため指定する必要はありません。

コミットします。

$ git add .
$ git commit -m "fix packages.json"

3.2. GitHub Actions のymlファイルを作成

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

$ mkdir -p .github/workflows
$ touch .github/workflows/auto-publish.yml
.github/workflows/auto-publish.yml
name: Publish package to GitHub Packages

on:
  push:
    branches:
      - main

jobs:
  build:
    runs-on: ubuntu-latest
    permissions:
      packages: write
      contents: read

    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/
          cache: "pnpm"

      - name: install
        run: pnpm i

      - name: build
        run: pnpm build

      - name: publish
        run: npm publish
        env:
          NODE_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}}

コミットします。

$ git add .
$ git commit -m "add yml for GitHub Actions"
$ git push origin main

main ブランチに push するとパッケージを publish できます。

以下のように、GitHub Actions が実行されます。

Alt text

パッケージが公開されました。

Alt text

npm publish の場合は、自動的にリポジトリと GitHub Packages が紐付きませんが、GitHub Actions で実行した場合は自動的に紐付きます。

Alt text

4. パッケージを利用する手順

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

以下が手順です。

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

4.1. Personal access tokenを取得

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

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

Alt text

Developer settings をクリックします。

Alt text

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

Alt text

Alt text

名前を入力し、read:packages にチェックを入れます。

Alt text

Generate token をクリックします。

Alt text

Alt text

コピーしておきます。

Alt text

4.2. プロジェクト作成

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

$ mkdir math-helpers-arithmetics-github-actions-publish-read
$ cd math-helpers-arithmetics-github-actions-publish-read

ローカルリポジトリを作成します。

$ git init

package.json を作成します。

$ touch package.json
package.json
{
}

TypeScript を devDependencies に追加します。

$ pnpm add -D typescript

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

$ touch .gitignore
.gitignore
# Ignore bundler config
node_modules

tsconfig.json を作成します。

$ pnpm tsc --init
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. */
  }
}

4.3. .npmrcを作成

.npmrc を作成します。

$ touch .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 の値>

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

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

$ pnpm add @hayato94087/math-helpers-arithmetics-github-actions-publish

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

✔ The modules directory at "/Users/hayato94087/Private/math-helpers-arithmetics-github-actions-publish-read/node_modules" will be removed and reinstalled from scratch. Proceed? (Y/n) · true

Recreating /Users/hayato94087/Private/math-helpers-arithmetics-github-actions-publish-read/node_modules
Lockfile is up to date, resolution step is skipped
Packages: +1
+
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

devDependencies:
+ typescript 5.2.2

Progress: resolved 1, reused 1, downloaded 0, added 1, done
Done in 4.3s

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

$ pnpm add @hayato94087/math-helpers-arithmetics-github-actions-publish

Packages: +1
+

dependencies:
+ @hayato94087/math-helpers-arithmetics-github-actions-publish 0.0.1

Progress: resolved 2, reused 2, downloaded 0, added 1, done
Done in 883ms

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

index.ts を作成します。

$ touch index.ts

パッケージをインポートし利用します。

index.ts
import { add } from "@hayato94087/math-helpers-arithmetics-github-actions-publish";

console.log(add(1, 2));

実行すると、ちゃんと動いています。

$ ts-node index.ts

3

コミットします。

$ git add .
$ git commit -m "create project for reading package on github packages"

5. パッケージを更新する手順

パッケージを更新する手順を紹介します。

5.1. 機能を追加実装

subtract を追加します。

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

version を上げます。

package.json
{
  "name": "@hayato94087/math-helpers-arithmetics-github-actions-publish",
- "version": "0.0.1",
+ "version": "0.0.2",
  "license": "UNLICENSED",
  "main": "dist/index.js",
  "module": "dist/index.mjs",
  "types": "dist/index.d.ts",
  "publishConfig": {
    "access": "restricted",
    "registry": "https://npm.pkg.github.com/"
  },
  "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"
  }
}

5.2. パッケージを更新

README.md を修正します。

README.md
# features

- add
- subtract

公開するために、main にプッシュします。

$ git add .
$ git commit -m "add subtract"
$ git push origin main

公開されました。バージョンがアップされてます。

Alt text

6. まとめ

自分専用、あるいは社内のみで利用するパッケージを GitHub Actions を介して、GitHub Packages に限定公開する方法を説明しました。

限定公開に利用したパッケージは、以下のリポジトリです。

https://github.com/hayato94087/math-helpers-arithmetics-github-actions-publish

限定公開したパッケージを利用したプロジェクトは、以下のリポジトリです。

https://github.com/hayato94087/math-helpers-arithmetics-github-actions-publish-read

7. 参考

https://engineer-first.net/create-github-packages

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

https://github.com/changesets/changesets/issues/287

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

https://docs.github.com/ja/actions/publishing-packages/publishing-nodejs-packages#github-packagesへのパッケージの公開

https://note.com/shift_tech/n/ne2a7ebaa7343

Discussion