はじめに
TechCommit Advent Calendar 2021 16日目を担当させていただきます、うらさくと申します!よろしくお願いします。
今回会社でGitHubのOrganizationユーザ管理をGitHub上でやっていこうぜということで、いろいろGitHubのAPIに触れていたのですが、TypeScript(Javascript)で使用されている記事が少なく、少し苦労したところがあるので、octkitの種類から基本的なoctkitの使い方まで簡単にまとめてみました
これらを使うと、UIを使わずにユーザの登録や削除ができますし、ソースコードと一緒にユーザ一覧表を管理することで半自動でユーザの管理をすることができます
GitHubAPI興味あったけど使ったことない方や、GitHubのユーザ管理に悩まれている方のご参考になれば幸いです
octkitとは
GitHub公式のGitHub APIのラッパーです
今回説明するNode.js版の他に、Ruby、.Net等で使用することができます
APIの種類
レポジトリを見ていただくとわかるように、単にoctkitといっても結構種類があります
jsだけで見ても
- octkit.js
- rest.js
- request.js
- endpoint.js
- webhook.js
- adtions.js
などなど
全部説明するのはきりがない(正直私もほとんど知らない^^;)ので、今回は私が使用した、rest.jsについて説明したいと思います
@octkit/rest
@octkit/requestとの違い
javaScript(TypeScript)からGitHubのAPIを叩く場合は、rest.jsとrequest.jsのどちらかになると思います
違いを軽く説明しますと、request.jsは実施にAPIを叩くところを担当しているライブラリで、rest.jsはrequest.jsに認証やフック、ページネーションなどの便利機能を付与した最終的なAPIクライアントです
request.jsをそのまま使ってAPIを叩くことも可能ではありますが、rest.jsの便利機能を捨ててまで使うメリットはあまりないと思いますので、ここからいくつかrest.jsの使い方を説明していきます
用途と使い方
導入とインポート
まずはいつものようにnpm installを実行します
npm install @octokit/rest @octokit/request-error --save
@octokit/request-errorについて
後ろの@octokit/request-errorってなに?と思われた方がいらっしゃると思いますが、これは@octokit/requestのエラーハンドリングで使用しているGitHub独自のエラークラスです。
API実行時に発生したExceptionは、RequestError型としてthrowされます
ですので、クライアント側でcatchするためには、このクラスも同時に使用する必要があります
こちらに関しても使用例のところで軽く触れていきます
用途と使い方
今回はOrganization周りで使うことが多かったので、いくつか紹介させていただきます
Organizationにユーザを招待する
async function sendInvitation(userId: number, teamIds?: number[]): Promise<number | RequestError> {
const params = {
org: OWNER,
invitee_id: userId,
team_ids: teamIds,
}
try {
const response = await octokit.request('POST /orgs/{org}/invitations', params)
return response.status
} catch (e) {
console.warn(`[WARN] ${e}`)
const error = e as RequestError
return error
}
}
パラメータのうち、org(Organization名)とinvitee_id(招待するユーザID)は必須項目です。
team_idsは招待時にチームを指定するときのみ記載します。(Array形式)
上記の通り、エラーはRequestErrorという独自の型で帰ってくるので、catchしたエラーはキャストしてからreturnします
インターネットアクセスしますので、async/awaitを使用しています
async function main(): Promise<void> {
for (const member of members) {
const inviteResponseStatus = await github.sendInvitation(userId, teamIds)
if (inviteResponseStatus instanceof RequestError) {
console.error(`[ERROR] Invitation ${member.username} is failed.`)
} else {
console.log(`[INFO] Success. Invitation ${member.username} is succeed.`)
}
}
}
呼び出し先で返り値で分岐させることで、複数人招待する際に一人が入力ミスなどでエラーになっても、ログを出して止めずに次の処理へ進ませることができます
ユーザ名からユーザIDを取得
async function getUserIdFromUserName(username: string): Promise<number | RequestError> {
try {
const response = await octokit.request('GET /users/{username}', { username: username })
return response.data.id as number
} catch (e) {
console.warn(`[WARN] ${e}`)
const error = e as RequestError
return error
}
}
ユーザIDはUI上から確認することができないので、APIから取得する必要があります
チーム名からチームIDを取得
export async function getTeamIds(teams: string[]): Promise<number[]> {
const teamIdsList: number[] = []
for (const team of teams!) {
const params = {
org: OWNER,
team_slug: team,
}
try {
const response = await octokit.request('GET /orgs/{org}/teams/{team_slug}', params)
teamIdsList.push(response.data.id)
} catch (e) {
console.error(`[Error] ${e}`)
throw new Error(`[Error] Teams ${team} doesn't exist. Please check this team name.`)
}
}
return teamIdsList
}
チームIDも同様です。こちらは配列としてreturnしています
現在Organizationに登録されているユーザを取得する
async function getOrgMembers() {
const response = await octokit.paginate('GET /orgs/{org}/members', { org: OWNER })
const memberList = response.map((element) => {
return { username: element.login }
})
return memberList
}
すでに登録されているユーザは上記のように取得できます
ユーザ名一覧のMapをreturnしています
ユーザ名はusernameではなく、loginで取得できる点に注意です
Pagenationについて
リスト系のAPIでは、per_pageオプションで一度に取得する情報数を指定できますが、上限があり一度に最大100件までの情報しか取得できません。これは、GitHub REST APIの制約なので、このようなケースでは本来ならば複数回に分けてリクエストする必要がありますが、rest.jsではPagenationという便利な仕組みを使うことができます。
まとめ
個人での使用に限ればあまり使う機会はないかもしれませんが、Organizationで使用されている方はこれらを使うことでユーザ管理をGitHub上で完結することができます
例えば、、
ユーザ一覧CSV+スクリプトのActionsファイルのGitHubレポジトリ作成
↓
ユーザ一覧CSVに登録したいユーザを追加してPull Request作成
↓
管理者がPRを確認して問題なければマージ
↓
マージ時にActionsからOrganizationへのInviteAPIを叩いてユーザを招待
などでしょうか?
こうすることでわざわざ「登録お願いします」や「登録しました」などのやり取りが不要になるだけでなく、APIを駆使してユーザの上限をチェックしたり、複数のOrganizationを管理する際にも役に立つと思います
他にもいろいろなAPIがあり、使い方は無限大なので、皆さんも色々試してみて、良いGitHubライフをお過ごしください!
ご覧頂きありがとうございました
参考