🤖

Benchmark結果をPull Requestしよう!【GitHub、Github Actions、gh-printer】

に公開

はじめに

今回紹介する実行結果をpull requestするためのactionであるgh-printerは私が作りました。
使い方だけ見たい方は使い方のみご覧ください。
お時間のある方や作成過程も知りたい方は作成過程も見ていただけると幸いです。

https://github.com/ROBOTofficial/print

使い方

gh-printerを使う上で必須になる引数は以下の通りです。

  • github-token
  • output-file
  • contents 又は input-file

この中で重要になってくるのがcontentsとinput-fileです。

  • contents 何か特定の文字列を入れたい場合に使用
  • input-file upload-artifactなどでジョブ間共有しているファイルをpull requestする場合に必要

npm run benchmarkをbenchmark.txtとしてpull requestする場合の例

benchmark.yml
name: Benchmark

on:
  push:
    branches:
      - main

jobs:
  benchmark:
    name: Benchmark
    runs-on: ubuntu-latest

    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version-file: .node-version
          cache: npm

      - name: Install Dependencies
        run: npm ci

      - name: Benchmark
        run: echo "$(npm run benchmark)" > tmp.txt

      - name: Upload Artifact
        uses: actions/upload-artifact@v4
        with:
          name: benchmark
          path: tmp.txt

  printer:
    name: Printer

    permissions:
      pull-requests: write
      contents: write

    runs-on: ubuntu-latest

    steps:
      - name: Checkout
        id: checkout
        uses: actions/checkout@v4

      - name: Download Artifact
        uses: actions/download-artifact@v4
        with:
          name: benchmark

      - name: Print
        uses: ROBOTofficial/print@1
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}
          output-file: ./benchmark.txt
          input-file: ./tmp.txt

上記のようなymlによって自動でpull requestが作成されるようになります。
なぜupload-artifactを使っているかというとoutputsやenvでの受け渡しは結果が複数行になる性質上エラーが出てしまうためです。

tmp.txtはコミットされないので安心してください。
※tmp.txtもコミットしたい場合はignore-input-file引数をfalseにしてください

成功した際には以下のようにPull Requestが作成されます。

作成過程

全て解説していると日が暮れてしまうので今回は二点重要な点を解説していきます。

OctokitでPull Requestを実装

1から作る事も考えたのですがメンテナンスなどの面も考えて今回はOctokitを使う事にしました。

import * as github from "@actions/github";

const ghToken = core.getInput("github-token");

const octokit = github.getOctokit(ghToken);

await octokit.rest.pulls.create({
    owner: github.context.repo.owner,
    repo: github.context.repo.repo,
    base: "main",
    head: `${github.context.repo.owner}:main`,
    title: "",
    body: ""
});

上記のようなコードでPull Requestの実装が可能です。

※gh-printerでは既にPull Requestを作成しているかなどのチェックがありますがここでは省略しています。

execを使ってGit操作

import { exec } from "@actions/exec";

await exec("git", ["config", "user.name", `"github-actions[bot]"`]);
await exec("git", [
    "config",
    "user.email",
    `"github-actions[bot]@users.noreply.github.com"`
]);

await exec("git", ["checkout", "-b", "fix"]);

git関連の操作はexec経由で行います。
上記のコードはgithub-actions[bot]でfix branchにチェックアウトするコードです。

github actions上でも基本的には通常のgitと同じです。

作成過程まとめ

Git関係は@actions/exec、Github関係はOctokitを使って実装しました。
詳しいファイル操作などはfs-extraやその他Node.jsのライブラリを使い作成しました。

GitHub Actionsは敷居こそ高いように見えるかもしれませんが案外普通のコードで実装可能です。
皆さんも時間があれば一度お試しください!

最後に

今回作ったgh-printerは作ったばかりで修正の余地があると思います。
何か不満に思った機能等あればgithubリポジトリのissueで言っていただけると幸いです。

またこの記事に誤字脱字等ありましたらお手柔らかに教えていただけると幸いです。

TwitterGitHubのフォローもよろしければお願いします。

Discussion