LoginSignup
518
368

More than 1 year has passed since last update.

Github Actionsの使い方メモ

Last updated at Posted at 2019-10-13

Github Actions をワークフロー内で使う方法についてすぐに見返すための備忘録
Github Action を作るためのメモはこちら => Github Action の作り方メモ

ドキュメント

ワークフローの定義

リポジトリに次のディレクトリを作成し、その中にYAML形式で定義する。

.github/workflows/

YAMLファイルは名前は自由。複数OK。

ワークフローの構造

ワークフローを定義するYAMLファイルは次のような階層構造を持っている。

ワークフロー(YAMLファイル)
  └ jobs:
    └ ジョブ(名前は任意)
       └ steps:
         └ アクション

ワークフロー

  • .github/workflows/ ディレクトリ以下に配置されるYAMLファイルが個別のワークフローとなる。
  • 複数のワークフローを設置してもOK。
  • ワークフローは並列で実行される。

ジョブ

  • 各ジョブは仮想環境の新しいインスタンスで実行される。
  • したがって、ジョブ間で環境変数やファイル、セットアップ処理の結果などは共有されない。
  • ジョブ間の依存を定義して待ち合わせることができる。
    • データの受け渡しが必要ならアーティファクト経由で。

Step

  • Jobが実行する処理の集合。
  • 同じJobのStepは同じ仮想環境で実行されるのでファイルやセットアップ処理は共有できる。
  • しかし各ステップは別プロセスなのでステップ内で定義した環境変数は共有できない。
    • jobs.<job_id>.envで定義した環境変数は全Step で利用できる

アクション

  • ワークフローの最小構成要素。
  • 単にrunでコマンドを実行することもできるし、Githubやサードパーティの公開アクションを利用(use)することもできる。
  • コンテキストを利用して秘密情報を受け取ったりできる

仮想環境

Jobが実行される仮想環境のスペックは次の通り。
そんなにスペックは高くない。

  • 2コアCPU
  • 7 GBのRAMメモリー
  • 14 GBのSSDディスク容量

Publicリポジトリなら無料。
Privateだと Linux仮想環境で $0.008/min かかる。

$0.008/min = $0.48/hour = 約52円/hour($1=108.4円)

10分かかるビルドを実行すると約9円かかる。
Freeアカウントで2,000分/月 無料。

Permission

リポジトリごとにどの Github Action を利用できるのか? あるいは、Workflow中でリポジトリの読み書きを許可するかを設定できる。
設定はリポジトリの Settings/Actions にある。

Actions permissions

リポジトリで Github Action を実行できるかどうかを設定する。
次の選択肢から選ぶ。

  • Allow all actions: すべての Action の実行を許可
  • Disable Actions: すべての Action の実行禁止
  • Allow local actions only: リポジトリ内で定義した Action のみ実行を許可
  • Allow select actions: 実行できる Action を選択する
    • Allow actions created by GitHub: Github製 Action のみ実行を許可
    • Allow Marketplace actions by verified creators: 認証された作者の Action のみ実行を許可
    • Allow specified actions: 設定した任意の Action のみ実行を許可

Fork pull request workflows

プライベートリポジトリのみで設定できる項目。フォークされたプルリクエストからのワークフローの権限を設定でできる。
Run workflows from fork pull requests を有効にすると次の2項目を設定できる。

  • Send write tokens to workflows from fork pull requests: 書き込めるGITHUB_TOKENを利用を許可する
  • Send secrets to workflows from fork pull requests: すべてのシークレットを利用可能にする

Workflow permissions

Workflow 内で実行される Action がリポジトリを操作することを許可するかどうかを設定する。
次の2つの選択肢から選び、その選択が GITHUB_TOKEN に与えられるデフォルトの権限となる。

  • Read and write permissions: 読み書きを許可する。
    • ただし、フォークされたリポジトリからのPRでは読み込みのみに制限される
  • Read repository contents permission: 読み込みのみ許可する

ワークフローの permissions 設定

Read repository contents permission を設定した場合、リポジトリのコンテンツ(コミットやIssue, PR)に対して書き込むような Action は実行時に権限エラーが発生する。

例えば、Lint系の Action ならば、検査結果でプルリクエストやコミットの状態を更新したり、プルリクエストににコメントを追加したりするものがあるが、それらができなくなる。

このような処理を許可するために Workflow 定義に permissions を設定することで許可してやることができる。
設定できる権限の種類は次の通り。

permissions:
  actions: read|write|none
  checks: read|write|none
  contents: read|write|none
  deployments: read|write|none
  issues: read|write|none
  packages: read|write|none
  pull-requests: read|write|none
  repository-projects: read|write|none
  security-events: read|write|none
  statuses: read|write|none

上記のLint系 Action では pull-requestsstatuseswrite の許可が必要となるであろう。
Read and write permissionsを選択した場合にはこれらの項目に一律write 権限が与えられるということ。

コンカレンシー

同時に複数のジョブを実行されないように制限することもできる。
例えば、 Push すると自動テストを実行するワークフローを実行中に次の Push を行うと、実行中のワークフローを中断して、後続の Push に対するワークフロー実行を実施することができる(つまり、実行の意味を失った先行 Push のテストをやめてワークフロー実行に対するコストを節約できる)。

コンカレンシーはワークフローレベルまたはジョブレベルで設定できる。

次の例はプルリクエストに Push した際に実行するワークフローで、同じブランチに対してすでにワークフローが実行中であれば、それをキャンセルして、新たなワークフローを実行する例。

name: concurrency sample
on:
    pull_request:
    types: [opened, synchronize]

concurrency: 
    group: ${{ github.workflow }}-${{ github.ref }}
    cancel-in-progress: true

コンテナ内でのジョブ実行

ジョブを指定したコンテナ内で実行することもできる。

次の例は ruby:3.1.2 コンテナでジョブを実行する例。
通常は actions/setup-ruby で Ruby の実行環境を用意するが、ruby:3.1.2 コンテナで実行するのでそれが不要となっている。

name: Container job sample 
on:
  push:

jobs:
  container-test-job:
    runs-on: ubuntu-latest
    container:
      image: ruby:3.1.2
    steps:
      - name: show ruby version
        run: ruby -v

このワークフローのログを確認すると show ruby version の結果は次の様に出力されている。

ruby 3.1.2p20 (2022-04-12 revision 4491bb740a) [x86_64-linux]

ジョブを実効するコンテナに対して volumes をマウントしたり、 env で環境変数を設定したりできる。
また、 credentials を設定できるのでプライベートレジストリからイメージを Pull することもできる。

see コンテナ内でのジョブの実行 - GitHub Docs

サービスコンテナ

ワークフローの処理の中で、Dockerコンテナを起動することができる。
例えば、DB を利用するアプリケーションのテストを実行する場合に MySQL や PostgreSQL をコンテナで建てることができる。

サービスコンテナを立ち上げるには Job 内で service: を利用する。

次の例は PostgreSQL を利用する Rails アプリケーションの Rspec を実行する例。

.github/workflows/rspec.yml
name: Rspec for Rails with PostgreSQL
on: push
jobs:
  # Label of the container job
  rspec:
    # Containers must run in Linux based operating systems
    runs-on: ubuntu-latest
    services: # サービスコンテナの定義
      postgres:
        image: postgres:15.0-alpine3.16
        ports:
            - 5432:5432
        env:
          POSTGRES_PASSWORD: postgres
        options: >- # 起動後のヘルスチェック
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
    steps:
      - name: Check out repository code
        uses: actions/checkout@v3
      - actions/setup-ruby@v1
        with:
            ruby-version: 3.1
      - name: Rspec
        env: 
          # テスト対象の Rails アプリケーションは次の環境変数で DB 接続先を設定できる想定
          - DB_HOST: localhost
          - DB_PORT: 5432
        run: |
            bundle install
            bundle install --jobs 4 --retry 3
            bundle exec rails db:create
            bundle exec rails db:migrate
            bundle exec rspec

上記の例ではコンテナを使わずに Rspec を実行しているが、コンテナでジョブを実行する場合、 DB_HOST: postgres の様にサービスの名前で接続先を指定できる。
また、 volumes をマウントしたり、 credentials を設定することもできる。

see サービスコンテナについて - GitHub Docs

ファイルシステム

  • Dockerコンテナで実行されるアクションには、 /githubパスの下に静的なディレクトリがある。
  • Dockerコンテナで実行されないアクションでは3つのディレクトリが作成される。これらのディレクトリパスは動的に生成されるので一定ではない。各ディレクトリの位置は対応する環境変数で取得する。
  • homeHOME): ユーザ認証情報などのユーザ関連データが書き込まれる
  • workspaceGITHUB_WORKSPACE):アクションが実行されるワークディレクトリ
  • workflowworkflow/event.jsonGITHUB_EVENT_PATH)が書き込まれるディレクトリ

公開アクション

Github自身が作成しているActionがリポジトリで公開されている。
サードパーティが作ったものはマーケットプレイスで探せる。

環境変数

環境変数を定義して、ワークフロー内で参照できる。
設定できる環境変数は次のスコープを取ることができる。

  • Workflow (トップレベルの env: で定義)
  • Job (jobs.<job_id>.envで定義)
  • Step (jobs.<job_id>.steps[*].envで定義)

下へ行くほどスコープは狭くなるが、上位のスコープで設定された値を上書きできる。


env:
  SOME_VAR: 'workflow-scope' # Workflowスコープの環境変数

jobs:
  one_job:
    env:
      SOME_VAR: 'job-scope' # Job スコープの環境変数。このJob内ではworkflowスコープの値を上書きする
    runs-on: ubuntu-latest
    steps:
      env:
        SOME_VAR: 'job-scope' # Stepスコープの環境変数。他のスコープで設定された値を上書きする
      - run: echo ${{ env.SOME_VAR }} # 環境変数の参照

環境変数を動的に追加する

例えば、アーティファクトのファイル名にモジュールのバージョン番号などを入れたい場合などに動的に環境変数を設定したい場合がある。

$GITHUB_ENV に追記することで環境変数を設定できる。
環境変数 GITHUB_ENV はステップ内で実行するシェルスクリプトなどの中でも有効。

jobs:
  one_job:
    runs-on: ubuntu-latest
    steps:
      - run: echo "DYN_VAR='value'" >> $GITHUB_ENV # 環境変数 DYN_VAR を追加している
      - run: echo ${{ env.DYN_VAR }} # 環境変数の参照
      - uses: actions/upload-artifact@v3
        with:
          name: artifact-${{ env.DYN_VAR }}  # 環境変数の参照し、アーティファクトのファイル名の一部として利用
          path: artifacts/*

Tips

複数のコマンドを run: したい

通常のYAMLの文法に従ってマルチラインのテキストとして例えば次の様に書けば良い

    steps:
      - name: run multi command
        run: |  # <- ここがミソ
          git config --global user.email "someone@sample.com"
          git config --global user.name "github workflow"
          git add .
          git commit -m 'modify manifests'
          git status

プルリクエストの内容で実行するかしないかを決める

コンテキストgithubにワークフローに関する情報が色々入っている。

例えば、プルリクエストイベントでトリガーするワークフローだとgithub.event.pull_requestにGithub REST APIのpull_request 相当のプルリクの情報が格納されている。

例えば次のようにするとWIPラベルの付いているときだけ実行するjobとなる。

  jobs:
    <job_name>:
      runs-on: ubuntu-latest
      if: "contains(join(github.event.pull_request.labels.*.name), 'WIP')"
      steps:
    	- run: <COMMAND
    	…以下略

条件式の書き方など詳しくはこちら -> GitHub Actions のコンテキストおよび式の構文

チェックアウトするブランチを指定する

Githubが公開するアクション actions/checkoutを利用すれば、ソースコードをチェックアウトできる。

では、チェックアウトしたソースのgit的な状態はどうなっているか?

    steps:
      - uses: actions/checkout@v3
      - run: git status
      - run: git branch

上記のようなコマンドをワークフロー内で実行した結果は次の通り。

    Run git status
    nothing to commit, working tree clean
    Run git status
    HEAD detached at pull/21/merge
    nothing to commit, working tree clean
    Run git branch
    * (HEAD detached at pull/21/merge)

見ての通り、プルリクエストのheadブランチとは異なるブランチとしてチェックアウトされている。

プルリクエストのheadブランチをチェックアウトしたいなら次ように指定する

    steps:
      - uses: actions/checkout@v3
        with:
          ref: ${{github.head_ref}}

${{github.head_ref}} はワークフローを実行するブランチを示す。

${{github.head_ref}} はプルリクエストイベント(pull_request または pull_request_target)でトリガーするワークフローでないと 使えないので注意。

ワークフロー内でファイルを変更 commitpush する

actions/checkout を使って取得したファイルを書き換えてGitコミットすることができる。
コミットをするということは、ワークフローが実行されるブランチに変更を加えたいということであり、そのためには Push する必要もある。

前述したように actions/checkout でデフォルトでチェックアウトされるブランチはプルリクエストのブランチとは異なる。そのため、上のようにチェックアウトするブランチを指定する必要がある。

プルリクエストをマージする

次のGithub製の公開Actionで、Github APIを叩けば、プルリクエストをマージすることもできる。

actions/github-script は Node.js版のoctokitを使うためのアクション。
このアクションは scriptというパラメータを取り、その中にJSのコードを記述すれば実行される。
script内ではgithubという変数に認証済みのoctakitインスタンスが格納されており、ワークフローの情報はcontextオブジェクトに格納されている。

次のワークフロー設定はREADME.mdをちょっと変更して、それをコミットしてpushし、マージする例

name: Test
  on:
    pull_request:
      types:
        - opened
        - synchronize
  jobs:
    merge:
      runs-on: ubuntu-latest
      steps:
        - uses: actions/checkout@v3
          with:
            ref: ${{github.head_ref}}
        - run: |
            date >> README.md
            git add .
        - name: check diff
          shell: bash
          id: changes
          run: |
            echo "::set-output name=count::$(git diff --staged --name-only . |wc -l)"
        - name: git commit and push
          shell: bash
          if: steps.changes.outputs.count > 0
          run: |
            git config --global user.name ${GITHUB_ACTOR}
            git config --global user.email "${GITHUB_ACTOR}@users.noreply.github.com"
            git commit -m "[WF] ${{inputs.operation}} article(s)"
            git push
        - name: merge pull request
          if: steps.changes.outputs.count > 0
          uses: actions/github-script@0.4.0
          with:
            github-token: ${{secrets.GITHUB_TOKEN}}
            script: |
              github.pulls.merge({
                owner: context.repo.owner,
                repo: context.repo.repo,
                pull_number: context.payload.pull_request.number
              })

コミット対象のファイルに変更差分が発生しない場合、commitが失敗する。それを避けるためにステップ name: check diffgit diff を使って変更されているファイルの数をワークフローコマンド set-output を利用して steps.changes.outputs.count に保存している。後続のステップはこの値が 1 以上であれば実行するようにしている。
ステップ name: merge pull request 以下が actions/github-script を使ってプルリクエストをマージしているところ。

ちなみにプルリクエストイベントでトリガーされるワークフローでのcontextはこんな感じ。

`context`の中身を開く

{
  "context": {
    "payload": {
      "action": "synchronize",
      "after": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
      "before": "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz",
      "number": 65,
      "pull_request": {
        "_links": {
          "comments": {
            "href": "https://api.github.com/repos///issues/65/comments"
          },
          "commits": {
            "href": "https://api.github.com/repos///pulls/65/commits"
          },
          "html": {
            "href": "https://github.com///pull/65"
          },
          "issue": {
            "href": "https://api.github.com/repos///issues/65"
          },
          "review_comment": {
            "href": "https://api.github.com/repos///pulls/comments{/number}"
          },
          "review_comments": {
            "href": "https://api.github.com/repos///pulls/65/comments"
          },
          "self": {
            "href": "https://api.github.com/repos///pulls/65"
          },
          "statuses": {
            "href": "https://api.github.com/repos///statuses/79dae33c3eb3dee6990846ed9136649454935bfb"
          }
        },
        "additions": 45,
        "assignee": null,
        "assignees": [],
        "author_association": "OWNER",
        "base": {
          "label": ":master",
          "ref": "master",
          "repo": {
            "archive_url": "https://api.github.com/repos///{archive_format}{/ref}",
            "archived": false,
            "assignees_url": "https://api.github.com/repos///assignees{/user}",
            "blobs_url": "https://api.github.com/repos///git/blobs{/sha}",
            "branches_url": "https://api.github.com/repos///branches{/branch}",
            "clone_url": "https://github.com//.git",
            "collaborators_url": "https://api.github.com/repos///collaborators{/collaborator}",
            "comments_url": "https://api.github.com/repos///comments{/number}",
            "commits_url": "https://api.github.com/repos///commits{/sha}",
            "compare_url": "https://api.github.com/repos///compare/{base}...{head}",
            "contents_url": "https://api.github.com/repos///contents/{+path}",
            "contributors_url": "https://api.github.com/repos///contributors",
            "created_at": "2019-12-04T09:14:10Z",
            "default_branch": "master",
            "deployments_url": "https://api.github.com/repos///deployments",
            "description": null,
            "disabled": false,
            "downloads_url": "https://api.github.com/repos///downloads",
            "events_url": "https://api.github.com/repos///events",
            "fork": false,
            "forks": 0,
            "forks_count": 0,
            "forks_url": "https://api.github.com/repos///forks",
            "full_name": "/",
            "git_commits_url": "https://api.github.com/repos///git/commits{/sha}",
            "git_refs_url": "https://api.github.com/repos///git/refs{/sha}",
            "git_tags_url": "https://api.github.com/repos///git/tags{/sha}",
            "git_url": "git://github.com//.git",
            "has_downloads": true,
            "has_issues": true,
            "has_pages": false,
            "has_projects": true,
            "has_wiki": true,
            "homepage": null,
            "hooks_url": "https://api.github.com/repos///hooks",
            "html_url": "https://github.com//",
            "id": 225825747,
            "issue_comment_url": "https://api.github.com/repos///issues/comments{/number}",
            "issue_events_url": "https://api.github.com/repos///issues/events{/number}",
            "issues_url": "https://api.github.com/repos///issues{/number}",
            "keys_url": "https://api.github.com/repos///keys{/key_id}",
            "labels_url": "https://api.github.com/repos///labels{/name}",
            "language": "HTML",
            "languages_url": "https://api.github.com/repos///languages",
            "license": null,
            "merges_url": "https://api.github.com/repos///merges",
            "milestones_url": "https://api.github.com/repos///milestones{/number}",
            "mirror_url": null,
            "name": "",
            "node_id": "MDEwOlJlcG9zaXRvcnkyMjU4MjU3NDc=",
            "notifications_url": "https://api.github.com/repos///notifications{?since,all,participating}",
            "open_issues": 60,
            "open_issues_count": 60,
            "owner": {
              "avatar_url": "https://avatars0.githubusercontent.com/u/26864070?v=4",
              "events_url": "https://api.github.com/users//events{/privacy}",
              "followers_url": "https://api.github.com/users//followers",
              "following_url": "https://api.github.com/users//following{/other_user}",
              "gists_url": "https://api.github.com/users//gists{/gist_id}",
              "gravatar_id": "",
              "html_url": "https://github.com/",
              "id": 26864070,
              "login": "",
              "node_id": "MDQ6VXNlcjI2ODY0MDcw",
              "organizations_url": "https://api.github.com/users//orgs",
              "received_events_url": "https://api.github.com/users//received_events",
              "repos_url": "https://api.github.com/users//repos",
              "site_admin": false,
              "starred_url": "https://api.github.com/users//starred{/owner}{/repo}",
              "subscriptions_url": "https://api.github.com/users//subscriptions",
              "type": "User",
              "url": "https://api.github.com/users/"
            },
            "private": true,
            "pulls_url": "https://api.github.com/repos///pulls{/number}",
            "pushed_at": "2020-01-24T04:41:03Z",
            "releases_url": "https://api.github.com/repos///releases{/id}",
            "size": 16,
            "ssh_url": "git@github.com:/.git",
            "stargazers_count": 0,
            "stargazers_url": "https://api.github.com/repos///stargazers",
            "statuses_url": "https://api.github.com/repos///statuses/{sha}",
            "subscribers_url": "https://api.github.com/repos///subscribers",
            "subscription_url": "https://api.github.com/repos///subscription",
            "svn_url": "https://github.com//",
            "tags_url": "https://api.github.com/repos///tags",
            "teams_url": "https://api.github.com/repos///teams",
            "trees_url": "https://api.github.com/repos///git/trees{/sha}",
            "updated_at": "2020-01-22T03:25:23Z",
            "url": "https://api.github.com/repos//",
            "watchers": 0,
            "watchers_count": 0
          },
          "sha": "26a7c543d54cd86669592979a5ae35210f05bf35",
          "user": {
            "avatar_url": "https://avatars0.githubusercontent.com/u/26864070?v=4",
            "events_url": "https://api.github.com/users//events{/privacy}",
            "followers_url": "https://api.github.com/users//followers",
            "following_url": "https://api.github.com/users//following{/other_user}",
            "gists_url": "https://api.github.com/users//gists{/gist_id}",
            "gravatar_id": "",
            "html_url": "https://github.com/",
            "id": 26864070,
            "login": "",
            "node_id": "MDQ6VXNlcjI2ODY0MDcw",
            "organizations_url": "https://api.github.com/users//orgs",
            "received_events_url": "https://api.github.com/users//received_events",
            "repos_url": "https://api.github.com/users//repos",
            "site_admin": false,
            "starred_url": "https://api.github.com/users//starred{/owner}{/repo}",
            "subscriptions_url": "https://api.github.com/users//subscriptions",
            "type": "User",
            "url": "https://api.github.com/users/"
          }
        },
        "body": "\nSource PR: [Can merge]()\n",
        "changed_files": 3,
        "closed_at": null,
        "comments": 0,
        "comments_url": "https://api.github.com/repos///issues/65/comments",
        "commits": 6,
        "commits_url": "https://api.github.com/repos///pulls/65/commits",
        "created_at": "2020-01-23T07:07:24Z",
        "deletions": 2,
        "diff_url": "https://github.com///pull/65.diff",
        "draft": false,
        "head": {
          "label": ":can_merge",
          "ref": "can_merge",
          "repo": {
            "archive_url": "https://api.github.com/repos///{archive_format}{/ref}",
            "archived": false,
            "assignees_url": "https://api.github.com/repos///assignees{/user}",
            "blobs_url": "https://api.github.com/repos///git/blobs{/sha}",
            "branches_url": "https://api.github.com/repos///branches{/branch}",
            "clone_url": "https://github.com//.git",
            "collaborators_url": "https://api.github.com/repos///collaborators{/collaborator}",
            "comments_url": "https://api.github.com/repos///comments{/number}",
            "commits_url": "https://api.github.com/repos///commits{/sha}",
            "compare_url": "https://api.github.com/repos///compare/{base}...{head}",
            "contents_url": "https://api.github.com/repos///contents/{+path}",
            "contributors_url": "https://api.github.com/repos///contributors",
            "created_at": "2019-12-04T09:14:10Z",
            "default_branch": "master",
            "deployments_url": "https://api.github.com/repos///deployments",
            "description": null,
            "disabled": false,
            "downloads_url": "https://api.github.com/repos///downloads",
            "events_url": "https://api.github.com/repos///events",
            "fork": false,
            "forks": 0,
            "forks_count": 0,
            "forks_url": "https://api.github.com/repos///forks",
            "full_name": "/",
            "git_commits_url": "https://api.github.com/repos///git/commits{/sha}",
            "git_refs_url": "https://api.github.com/repos///git/refs{/sha}",
            "git_tags_url": "https://api.github.com/repos///git/tags{/sha}",
            "git_url": "git://github.com//.git",
            "has_downloads": true,
            "has_issues": true,
            "has_pages": false,
            "has_projects": true,
            "has_wiki": true,
            "homepage": null,
            "hooks_url": "https://api.github.com/repos///hooks",
            "html_url": "https://github.com//",
            "id": 225825747,
            "issue_comment_url": "https://api.github.com/repos///issues/comments{/number}",
            "issue_events_url": "https://api.github.com/repos///issues/events{/number}",
            "issues_url": "https://api.github.com/repos///issues{/number}",
            "keys_url": "https://api.github.com/repos///keys{/key_id}",
            "labels_url": "https://api.github.com/repos///labels{/name}",
            "language": "HTML",
            "languages_url": "https://api.github.com/repos///languages",
            "license": null,
            "merges_url": "https://api.github.com/repos///merges",
            "milestones_url": "https://api.github.com/repos///milestones{/number}",
            "mirror_url": null,
            "name": "",
            "node_id": "MDEwOlJlcG9zaXRvcnkyMjU4MjU3NDc=",
            "notifications_url": "https://api.github.com/repos///notifications{?since,all,participating}",
            "open_issues": 60,
            "open_issues_count": 60,
            "owner": {
              "avatar_url": "https://avatars0.githubusercontent.com/u/26864070?v=4",
              "events_url": "https://api.github.com/users//events{/privacy}",
              "followers_url": "https://api.github.com/users//followers",
              "following_url": "https://api.github.com/users//following{/other_user}",
              "gists_url": "https://api.github.com/users//gists{/gist_id}",
              "gravatar_id": "",
              "html_url": "https://github.com/",
              "id": 26864070,
              "login": "",
              "node_id": "MDQ6VXNlcjI2ODY0MDcw",
              "organizations_url": "https://api.github.com/users//orgs",
              "received_events_url": "https://api.github.com/users//received_events",
              "repos_url": "https://api.github.com/users//repos",
              "site_admin": false,
              "starred_url": "https://api.github.com/users//starred{/owner}{/repo}",
              "subscriptions_url": "https://api.github.com/users//subscriptions",
              "type": "User",
              "url": "https://api.github.com/users/"
            },
            "private": true,
            "pulls_url": "https://api.github.com/repos///pulls{/number}",
            "pushed_at": "2020-01-24T04:41:03Z",
            "releases_url": "https://api.github.com/repos///releases{/id}",
            "size": 16,
            "ssh_url": "git@github.com:/.git",
            "stargazers_count": 0,
            "stargazers_url": "https://api.github.com/repos///stargazers",
            "statuses_url": "https://api.github.com/repos///statuses/{sha}",
            "subscribers_url": "https://api.github.com/repos///subscribers",
            "subscription_url": "https://api.github.com/repos///subscription",
            "svn_url": "https://github.com//",
            "tags_url": "https://api.github.com/repos///tags",
            "teams_url": "https://api.github.com/repos///teams",
            "trees_url": "https://api.github.com/repos///git/trees{/sha}",
            "updated_at": "2020-01-22T03:25:23Z",
            "url": "https://api.github.com/repos//",
            "watchers": 0,
            "watchers_count": 0
          },
          "sha": "79dae33c3eb3dee6990846ed9136649454935bfb",
          "user": {
            "avatar_url": "https://avatars0.githubusercontent.com/u/26864070?v=4",
            "events_url": "https://api.github.com/users//events{/privacy}",
            "followers_url": "https://api.github.com/users//followers",
            "following_url": "https://api.github.com/users//following{/other_user}",
            "gists_url": "https://api.github.com/users//gists{/gist_id}",
            "gravatar_id": "",
            "html_url": "https://github.com/",
            "id": 26864070,
            "login": "",
            "node_id": "MDQ6VXNlcjI2ODY0MDcw",
            "organizations_url": "https://api.github.com/users//orgs",
            "received_events_url": "https://api.github.com/users//received_events",
            "repos_url": "https://api.github.com/users//repos",
            "site_admin": false,
            "starred_url": "https://api.github.com/users//starred{/owner}{/repo}",
            "subscriptions_url": "https://api.github.com/users//subscriptions",
            "type": "User",
            "url": "https://api.github.com/users/"
          }
        },
        "html_url": "https://github.com///pull/65",
        "id": 366212162,
        "issue_url": "https://api.github.com/repos///issues/65",
        "labels": [],
        "locked": false,
        "maintainer_can_modify": false,
        "merge_commit_sha": "9999999999999999999999999999999999999999",
        "mergeable": null,
        "mergeable_state": "unknown",
        "merged": false,
        "merged_at": null,
        "merged_by": null,
        "milestone": null,
        "node_id": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
        "number": 65,
        "patch_url": "https://github.com///pull/65.patch",
        "rebaseable": null,
        "requested_reviewers": [],
        "requested_teams": [],
        "review_comment_url": "https://api.github.com/repos/
518
368
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
518
368