複数のプログラミング言語向けSDKを1つのリポジトリで管理する方法
こんにちは🐔
Showcase Gigの林 (howyi) です。
この記事は、Showcase Gig Advent Calendar 2021 4日目の記事です
私たちShowcase Gigが開発・運用しているプラットフォームの管理において、プラットフォーム利用者向けSDKを1つのリポジトリで管理している手法について紹介します。
なぜ複数の言語向けにSDKを用意したいのか、なぜ1つのリポジトリで管理したいのか
現在私たちが構築しているサーバはgRPCで構成されています。
サーバは主に「注文サービスと店舗をつなぐ」ことを目的とした機能を持っています。
例えば「注文」の場合、「注文を受け付けるサービスからデータを受け取り、伝えるべき端末に送信する」といった形です。
「注文を受け付けるサービス」と「伝えるべき端末」の数が少なかったり、同じチームで管理している場合、わざわざ別途SDKを作り保守するよりも、ただprotoを共有したほうが早い、ということもあります。
今回の場合、両方において今後も増え続ける展望があり、チーム外や社外の開発にも利用されるためSDKを作成しました。
また、gRPCのメリットの1つとしてコード生成が公式で充実している事が挙げられます。
単純なgRPCサーバへ接続するためのSDKであれば、コード生成結果をうまく活用すれば各SDKの中身はほとんどが自動生成のコードで済ませられるはずです。
サーバのproto更新があり、SDKに反映したい時、sdkのリポジトリでタグを切れば各言語向けのSDKもバージョンアップできることを目的として、以下のようにサブディレクトリを切りました。
showcase-gig/hoge-sdk
├ proto
│ ├ hoge.proto
│ └ fuga.proto
├ go
│ ├ client.go
│ └ go.mod
├ dart
│ ├ lib/
│ └ pubspec.yaml
├ js
│ ├ src/
│ ├ package.json
│ └ tsconfig.json
└ php
├ src/
└ composer.json
今回はprotoの各言語向けのコードの自動生成については説明せず、サブディレクトリでプライベートパッケージを作ろうとして困ったポイント、解消した方法などを機作します。
以降の説明の内容はgRPCに限らないため、GraphQLやOpenAPIからの自動生成をベースとしたSDKでも参考にできます。
ホスティングしているのはGitHubを前提としています。
Go /go
Go言語は go/v0.1.0 という形でタグを切っておくと、 go get github.com/{リポジトリ}/go@v0.1.0 といった形で go get できます。
プライベートリポジトリの場合は別途GitHubのパーソナルアクセストークンを設定しておきましょう。
GOPRIVATE=github.com/showcase-gig go get github.com/showcase-gig/hoge-sdk/go@v0.1.0
このように、サブディレクトリであってもあまりサブディレクトリを意識せずにプライベートパッケージとして利用できます。
例えば以下のような GitHub Actionsを作り、 v0.1.0 でリリースが作られたときに自動で go/v0.1.0 といったタグも付与すると、専用作業が発生せず楽になります。
name: "On release"
env:
CI: true
on:
release:
types: [published]
jobs:
go-release:
name: go release
runs-on: ubuntu-latest
steps:
- name: Set version variable
id: version
run: |
VERSION=$(echo ${{ github.ref }} | sed -e "s#refs/tags/##g")
echo ::set-output name=version::$VERSION
- name: checkout
uses: actions/checkout@v2
- name: tag to go sdk
run: |
git tag go/${{ steps.version.outputs.version }}
git push origin go/${{ steps.version.outputs.version }}
Dart /dart
Dartは pubspec.yaml でurlとパスを指定できます。こちらもそこまで悩むことはないですね。
cloneになるので、こちらをインストールする際はsshの鍵を設定しておく必要があります。
hoge_sdk:
git:
url: git@github.com:showcase-gig/hoge-sdk.git
path: dart
TypeScript (JavaScript) /js
package.jsonはGitの特定ディレクトリ以下をpackageとして読み込む、といったことは できません
そのため、 GitHub Actions と GitHub Packages を使用し、タグを切ったタイミングでJSディレクトリのパッケージをビルドしアップロードしてみます。
js/package.json の publishConfig と repository は以下のように設定し、Publish先をnpmからGitHub Packagesにしましょう。
{
"name": "@showcase-gig/hoge-sdk",
~~~~~~~~~~
"publishConfig": {
"access": "restricted",
"registry": "https://npm.pkg.github.com/"
},
"repository": {
"type": "git",
"url": "https://github.com/showcase-gig/hoge-sdk",
"directory": "js"
},
~~~~~~~~~~
}
GitHub Actionsのworkflowはこうなります。
今回の場合、GitHubのReleaseのタイミングでタグを切り、そのタグでアップロードしています。
on: の部分を変更すれば特定フォーマットのタグをpushしたタイミングや、特定条件でリリースということも可能です。
name: "On release"
env:
CI: true
on:
release:
types: [published]
jobs:
js-release:
name: js release
runs-on: ubuntu-latest
steps:
- name: Set version variable
id: version
run: |
VERSION=$(echo ${{ github.ref }} | sed -e "s#refs/tags/##g")
echo ::set-output name=version::$VERSION
- name: checkout
uses: actions/checkout@v2
with:
fetch-depth: 0
- name: setup Node
uses: actions/setup-node@v1
with:
node-version: 14.x
registry-url: 'https://npm.pkg.github.com'
- name: install
run: cd js && npm install
- name: package.jsonのversionを更新
run: |
sed -i -e "s/\"version\":.*\"/\"version\": \"${{ steps.version.outputs.version }}\"/" js/package.json
- name: build
run: cd js && npm run build
- name: publish
run: cd js && npm publish
env:
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
アップロードしたパッケージのインストールは GitHub Packagesの公式 をご覧ください
PHP /php
PHPもJSと同様に、Gitのディレクトリを指定した呼び出しはできません。
また、 composer.json がリポジトリ直下にない限りライブラリとして読み込めません。
そのため、ちょっとルール違反ですが今回は「hoge_sdk_php というコピーリポジトリを作り、タグを切るたびコピー先に同期する」という方向とします。
ちなみにこの方法は grpc/grpc-php でも行っている手法です。
GitHub Actionsを使う場合、リポジトリを跨いで作用するためリポジトリにのアクセストークンを発行し、 REPO_ACCESS_TOKEN としてsecretsに登録しておいてください。
hoge_sdkのworkflow (コピー元)
name: release
on:
push:
tags:
- "v[0-9]+.[0-9]+.[0-9]+"
jobs:
copy-to-repository:
strategy:
matrix:
repo: ['showcase-gig/hoge_sdk_php']
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v1
- run: ls
- name: Get the version
run: echo ${GITHUB_REF#refs/tags/}
- name: dispatch target-updated
uses: peter-evans/repository-dispatch@v1
with:
token: ${{ secrets.REPO_ACCESS_TOKEN }}
repository: ${{ matrix.repo }}
event-type: target-released
client-payload: '{"ref": "${{ github.ref }}", "sha": "${{ github.sha }}"}'
タグを切った際、コピー先リポジトリに、 target-released のイベントを送信しています。
payloadとして、リリースしたタグを送信しています。
hoge_sdk_phpのworkflow (コピー先)
name: release
on:
repository_dispatch:
types: [target-released]
jobs:
copy-from-repository:
runs-on: ubuntu-latest
steps:
- name: Set version variable
id: version
run: |
VERSION=$(echo ${{ github.event.client_payload.ref }} | sed -e "s#refs/tags/##g")
echo ::set-output name=version::$VERSION
- name: checkout
uses: actions/checkout@v2
- run: mkdir ../tmp_to
- name: 更新後も残したいファイルを退避
run: |
cp README.md ../tmp_to
cp -r .github ../tmp_to
- name: ファイル内を全削除
run: rm -rf *
- name: コピー元リポジトリをclone
uses: actions/checkout@v2
with:
repository: showcase-gig/hoge_sdk
path: tmp_from
ref: ${{ github.event.client_payload.ref }}
token: ${{ secrets.REPO_ACCESS_TOKEN }}
- name: 対象ディレクトリを移動
run: cp -r tmp_from/copy/* ./
- run: rm -rf tmp_from/
- name: 退避したファイルを戻す
run: cp -r ../tmp_to/* .
- run: git status
- name: 差分があればpush
run: |
git add .
if ! $(git status -s)
then
git config user.name github-actions
git config user.email github-actions@github.com
git add .
git commit -m "Update to version ${{ steps.version.outputs.version }}"
git push
fi
- name: タグを付ける
run: |
git tag ${{ steps.version.outputs.version }}
git push origin ${{ steps.version.outputs.version }}
タグからリポジトリをcloneし、差分があれば反映してpushした後、コピー元同様にタグを切ります。
アップロードしたパッケージのインストールは以下のようにできます。
composer config repositories.showcase-gig/hoge_sdk_php vcs https://github.com/showcase-gig/hoge_sdk_php
composer require showcase-gig/hoge_sdk_php:v0.1.0
実際に動作するサンプルを個人リポジトリに作成しているため、ぜひ参考にしてみてください。
まとめ
サブディレクトリで複数言語のSDKをプライベートで反映する方法を紹介してみました。
同様に困っている方、悩んでいる方の助けとなれば幸いです。
ということで Showcase Gig Advent Calendar 2021 4日目でした!明日もお楽しみに 🍗
Showcase Gigでは多種多様な技術に挑戦する仲間を募集しています!
ぜひチェックしてみてください ✨
この記事が気に入ったらサポートをしてみませんか?