はなちるのマイノート

Unityをメインとした技術ブログ。自分らしくまったりやっていきたいと思いますー!

【Actions】GitHub REST APIを用いてブランチを作成する方法

はじめに

今回はGitHub ActionsからGitHub REST APIを利用してブランチを作成する方法を紹介したいと思います。

概要

GitHub REST APIを利用することで、Repositoryの情報取得・Issue管理・PullRequestの管理・CommitやBranch管理などなど、GitHubの様々な操作を自動化できます。
docs.github.com

詳細は公式ドキュメントを参照してみてください。

やり方

name: test
on:
  workflow_dispatch:
    inputs:
      new_branch:
        description: "New branch name"
        required: true
jobs:
  create-branch:
    runs-on: ubuntu-latest
    permissions:
      contents: write # GITHUB_TOKENに書き込み権限を付与
    steps:
      - env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          REPOSITORY: ${{ github.repository }}
          BASE_BRANCH: main
          NEW_BRANCH: ${{ inputs.new_branch }}
        run: |
          # 指定したレポジトリ・ブランチの最新のコミットハッシュ取得
          LATEST_COMMIT=$(gh api "repos/${REPOSITORY}/commits/${BASE_BRANCH}" | jq -r '.sha')

          # ブランチを作成する
          gh api --method POST "repos/${REPOSITORY}/git/refs" -f "ref=refs/heads/${NEW_BRANCH}" -f "sha=${LATEST_COMMIT}"

gh auth login コマンドを使用するのでなく、アクセス トークンをGH_TOKENという環境変数として渡します。 これでその後の処理ができるようになります。
GitHub REST API のクイックスタート - GitHub Docs

最新コミットSHAの取得

LATEST_COMMIT=$(gh api "repos/${REPOSITORY}/commits/${BASE_BRANCH}" | jq -r '.sha')

指定されたリポジトリとブランチの最新コミットSHAを取得します。
docs.github.com

公式ドキュメントの例
# Request
$ gh api \
  -H "Accept: application/vnd.github+json" \
  -H "X-GitHub-Api-Version: 2022-11-28" \
  /repos/OWNER/REPO/commits

# Response
[
  {
    "url": "https://api.github.com/repos/octocat/Hello-World/commits/6dcb09b5b57875f334f61aebed695e2e4193db5e",
    "sha": "6dcb09b5b57875f334f61aebed695e2e4193db5e",
    "node_id": "MDY6Q29tbWl0NmRjYjA5YjViNTc4NzVmMzM0ZjYxYWViZWQ2OTVlMmU0MTkzZGI1ZQ==",
    "html_url": "https://github.com/octocat/Hello-World/commit/6dcb09b5b57875f334f61aebed695e2e4193db5e",
    "comments_url": "https://api.github.com/repos/octocat/Hello-World/commits/6dcb09b5b57875f334f61aebed695e2e4193db5e/comments",
    "commit": {
      "url": "https://api.github.com/repos/octocat/Hello-World/git/commits/6dcb09b5b57875f334f61aebed695e2e4193db5e",
      "author": {
        "name": "Monalisa Octocat",
        "email": "support@github.com",
        "date": "2011-04-14T16:00:49Z"
      },
      "committer": {
        "name": "Monalisa Octocat",
        "email": "support@github.com",
        "date": "2011-04-14T16:00:49Z"
      },
      "message": "Fix all the bugs",
      "tree": {
        "url": "https://api.github.com/repos/octocat/Hello-World/tree/6dcb09b5b57875f334f61aebed695e2e4193db5e",
        "sha": "6dcb09b5b57875f334f61aebed695e2e4193db5e"
      },
      "comment_count": 0,
      "verification": {
        "verified": false,
        "reason": "unsigned",
        "signature": null,
        "payload": null
      }
    },
    "author": {
      "login": "octocat",
      "id": 1,
      "node_id": "MDQ6VXNlcjE=",
      "avatar_url": "https://github.com/images/error/octocat_happy.gif",
      "gravatar_id": "",
      "url": "https://api.github.com/users/octocat",
      "html_url": "https://github.com/octocat",
      "followers_url": "https://api.github.com/users/octocat/followers",
      "following_url": "https://api.github.com/users/octocat/following{/other_user}",
      "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
      "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
      "subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
      "organizations_url": "https://api.github.com/users/octocat/orgs",
      "repos_url": "https://api.github.com/users/octocat/repos",
      "events_url": "https://api.github.com/users/octocat/events{/privacy}",
      "received_events_url": "https://api.github.com/users/octocat/received_events",
      "type": "User",
      "site_admin": false
    },
    "committer": {
      "login": "octocat",
      "id": 1,
      "node_id": "MDQ6VXNlcjE=",
      "avatar_url": "https://github.com/images/error/octocat_happy.gif",
      "gravatar_id": "",
      "url": "https://api.github.com/users/octocat",
      "html_url": "https://github.com/octocat",
      "followers_url": "https://api.github.com/users/octocat/followers",
      "following_url": "https://api.github.com/users/octocat/following{/other_user}",
      "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
      "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
      "subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
      "organizations_url": "https://api.github.com/users/octocat/orgs",
      "repos_url": "https://api.github.com/users/octocat/repos",
      "events_url": "https://api.github.com/users/octocat/events{/privacy}",
      "received_events_url": "https://api.github.com/users/octocat/received_events",
      "type": "User",
      "site_admin": false
    },
    "parents": [
      {
        "url": "https://api.github.com/repos/octocat/Hello-World/commits/6dcb09b5b57875f334f61aebed695e2e4193db5e",
        "sha": "6dcb09b5b57875f334f61aebed695e2e4193db5e"
      }
    ]
  }
]

新しいブランチの作成

gh api --method POST "repos/${REPOSITORY}/git/refs" -f "ref=refs/heads/${NEW_BRANCH}" -f "sha=${LATEST_COMMIT}"

新しいブランチを作成します。
docs.github.com

公式ドキュメント例
# Request
$ gh api \
  --method POST \
  -H "Accept: application/vnd.github+json" \
  -H "X-GitHub-Api-Version: 2022-11-28" \
  /repos/OWNER/REPO/git/refs \
   -f "ref=refs/heads/featureA" -f "sha=aa218f56b14c9653891f9e74264a383fa43fefbd"

# Response
{
  "ref": "refs/heads/featureA",
  "node_id": "MDM6UmVmcmVmcy9oZWFkcy9mZWF0dXJlQQ==",
  "url": "https://api.github.com/repos/octocat/Hello-World/git/refs/heads/featureA",
  "object": {
    "type": "commit",
    "sha": "aa218f56b14c9653891f9e74264a383fa43fefbd",
    "url": "https://api.github.com/repos/octocat/Hello-World/git/commits/aa218f56b14c9653891f9e74264a383fa43fefbd"
  }
}

ちなみに

最近はPowerShell布教活動を行っているので、pwshでのやり方も紹介します。

name: test
on:
  workflow_dispatch:
    inputs:
      new_branch:
        description: "New branch name"
        required: true
jobs:
  create-branch:
    runs-on: ubuntu-latest
    permissions:
      contents: write
    steps:
      - env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          REPOSITORY: ${{ github.repository }}
          BASE_BRANCH: main
          NEW_BRANCH: ${{ inputs.new_branch }}
        shell: pwsh
        run: |
          $last_commit = gh api "repos/${env:REPOSITORY}/commits/${env:BASE_BRANCH}" | ConvertFrom-Json | Select-Object -ExpandProperty sha
          gh api --method POST "repos/${env:REPOSITORY}/git/refs" -f "ref=refs/heads/${env:NEW_BRANCH}" -f "sha=${last_commit}"