Skip to Content

GitHub Notesアクション

GitHub Notesアクションは、実行のノートをGitHubに投稿します。投稿先は、プルリクエストのコメント、GitHub Actionsのジョブのサマリー、Issueのいずれかです。

アクションは、ステップが通ったかどうかとは別に、人に向けたノートを残せます。後続のステップはそれをnotesとして読み、各ノートにはジョブとステップが付き、シークレットは隠されています。Probeはノートをどこにも投稿しません。投稿するのはこのアクションで、どのタイミングでどのノートを投稿するかはワークフローに書きます。このアクションはノートを投稿するためだけのもので、GitHub全般を操作するアクションではありません。

外部アクションとしてmozership/probe-github-notes で公開しています。ワークフローが初めて使うときにProbeがダウンロードし、固定したコミットのaction.ymlが示すSHA-256と一致する実行ファイルだけを実行します。notesコンテキストを持つ最初のバージョンであるProbe v1.32.0以降が必要です。

基本的な構文

ステップでは40文字のコミットSHAでアクションを固定します。各リリース のノートの先頭に、コピーして使うusesの行があります。このステップは最後のジョブに置き、そのジョブはalways付きでほかのジョブをneedsにします。こうすると、ほかのジョブがどう終わっても、すべて終わったあとに実行され、すべてのノートを読めます。

name: Shop actions: github-notes: github.com/mozership/probe-github-notes@76735813d682751a3b743a0dbce0ad49a8d372ad # v0.1.0 secrets: - GITHUB_TOKEN vars: github_token: "{{GITHUB_TOKEN}}" jobs: # helloは受け取ったwithをそのままresとして返すので、 # ノートを残すアクションの代わりに使える - name: Checkout id: checkout steps: - name: A first-time shopper uses: hello with: notes: - level: critical title: The checkout button is under the cookie banner body: On a 390px wide screen the banner covers the button until it is closed. - level: info body: The search took 4s to show results. - name: Notes needs: [checkout] always: true steps: - name: Put the notes on the pull request uses: github-notes with: to: comment token: "{{vars.github_token}}" notes: "{{ notes }}" test: status == 0

ノートの投稿先

toで書き込む先を選びます。

to書き込む先次の実行ではノートがないとき
commentプルリクエストのコメント同じコメントを編集するコメントがあれば、ノートがないことを書いて編集する。新しくは作らない
summaryGitHub Actionsのジョブのサマリージョブの実行ごとに別のサマリーになる何も書かない
issuelabelsが付いたopenなIssueopenの間は同じIssueを編集するopenなIssueがあれば、ノートがないことを書いて編集し、クローズする。次にノートが出た実行で新しく作る

コメントは、変更に対して実行するワークフローで、レビューする人に読んでもらうためのものです。サマリーはトークンが要らず、コメントするプルリクエストがない実行や、レビューする人に向けないノートに使います。Issueは、ステージング環境に対して毎晩実行するような定期実行のワークフローで、ノートを作業として追跡するためのものです。実行がノートを残す間はopenのままで、ノートを残さなかった最初の実行でクローズされます。

アクションはkeyごとにコメントかopenなIssueを1つ持ち、本文の先頭に<!-- probe-github-notes:<key> -->というマーカーを書きます。プルリクエストのコメント、またはlabelsが付いたopenなIssueから、マーカーで始まる最初のものを探して編集し、なければ新しく作ります。ノートの一部を別のコメントに投稿するには、別のkeyを使います。

- name: The critical notes, in a comment of their own uses: github-notes with: to: comment key: critical token: "{{vars.github_token}}" notes: "{{ filter(notes, .level == 'critical') }}"

同じ場所に投稿する2つの実行が同時に走ると、どちらもコメントを見つけられずにそれぞれ作ることがあり、以降の実行は最初の1つだけを編集します。別々の実行の間をアクションが調整することはできないので、GitHub Actionsのconcurrencyなどで、ワークフローの実行が重ならないようにしてください。

パラメータ

パラメータ型必須デフォルト説明
toStringはい-comment、summary、issueのいずれか
notesArrayはい-"{{ notes }}"のような、notesコンテキストのエントリ。空のリストは、ノートを残さなかった実行として扱う
bodyStringいいえ-ノートの上に書くMarkdown
timeoutDurationいいえ30sステップの制限時間。10sのような形式か秒数で指定する
tokenStringcomment、issue-リポジトリにコメントやIssueを書けるトークン
repositoryStringいいえGITHUB_REPOSITORYowner/name形式のリポジトリ
keyStringいいえprobeアクションが編集するコメントやIssueの名前。英数字、.、_、-を使える
api_urlStringいいえGITHUB_API_URL、なければhttps://api.github.comREST API。GitHub Enterprise Serverで使う
numberIntegerいいえイベントのプルリクエストcommentで、コメントするプルリクエストまたはIssue
titleStringいいえProbe notesissueのタイトル
labelsArrayいいえ[probe]issueに付けるラベル。アクションはこのラベルでIssueを探す

ほかのtoのためのパラメータは読まないので、ジョブのdefaultsで、どのtoのステップにもtokenを渡せます。どれにも当てはまらないキーは、ステップを失敗させます。action.ymlがこれらをparamsとして宣言しているので、probe checkはそのようなキーを行番号付きで報告します。

notesは、notesコンテキストと同じ形のエントリを受け取ります。levelがinfo、warning、criticalのいずれでもないエントリや、bodyのないエントリがあると、ステップは失敗します。手で書いたリストではなく、コンテキストそのもの、またはfilter(notes, .level != 'info')のようにその一部を渡してください。

to: commentでnumberがないときは、GitHub Actionsの実行を起動したイベントのプルリクエストにコメントします。イベントはGITHUB_EVENT_PATHから読み、pull_requestとpull_request_targetが対象です。ブランチへのpushなどそれ以外のイベントでは、何も投稿せずにステップを通し、res.postedはfalseになります。

GitHub Actionsの実行のトークンGITHUB_TOKENには、書き込みの権限が必要です。プルリクエストへのコメントにはpull-requests: write、IssueやIssueへのコメントにはissues: writeを付けます。Probeが出力の中で隠すように、トークンはsecretsに入れてください。

書き込む内容

先頭の1行でレベルごとのノートの件数を数え、そのあとにジョブとステップの名前の下にノートを並べます。ステップにはその状態と、repeatのジョブであれば何回目の実行かを添えます。ノートはレベルに応じたGitHubのアラートで書き、criticalはCAUTION、warningはWARNING、infoはNOTEです。タイトルと本文はそのまま書きます。

The run left 2 notes: 1 critical, 1 info. ### Checkout **A first-time shopper** · passed > [!CAUTION] > **The checkout button is under the cookie banner** > > On a 390px wide screen the banner covers the button until it is closed. > [!NOTE] > The search took 4s to show results. <sub>From [run 123456](https://github.com/owner/name/actions/runs/123456) of _Shop_.</sub>

最後の行はGitHub Actionsの実行へのリンクで、GitHub Actionsの外では書きません。Probeが隠した値は、ノートの中では<secret:NAME>や<redacted>になっています。GitHubはこれをHTMLタグとみなして表示しないので、アクションはコードの外ではこれを文字として書きます。コードの中では、そのまま表示されます。

GitHubが受け付けるのは、コメントとIssueでは65536文字まで、ステップのサマリーでは1 MiBまでで、サマリーはそれまでに書かれた分も含みます。これより長いページでは末尾のノートを省き、省いた件数を1行で書きます。ノートをすべて省いても収まらないほどbodyが長いときは、ステップは失敗します。

レスポンスオブジェクト

プロパティ型説明
res.postedBooleanアクションが何かを書いたかどうか
res.actionStringcreated、updated、closed(Issue)、written(サマリー)、noneのいずれか
res.numberInteger投稿したプルリクエストかIssue、または投稿するものがなかったプルリクエスト。対象がないときとサマリーでは0
res.urlStringGitHub上のコメントかIssue。サマリーでは空
res.idIntegerコメントかIssueのID
res.codeIntegerGitHubへの最後のリクエストのステータスコード。サマリーでは0
reqObjectto、notesの件数、投稿先。トークンは含まない
rtDurationステップにかかった時間
statusInteger0

書き込めないトークンでの403や、存在しないプルリクエストへの404など、GitHubがエラーを返すと、ステップはGitHubのステータスとメッセージで失敗します。書き込みをGitHubが301や302でリダイレクトした場合も失敗します。そのまま従うと、書き込みが読み取りとして送り直されるためです。

アクションは、GitHubに投稿したノートをres.notesとして返しません。返すと、後続のステップに同じノートがもう一度残るためです。

ガードの下での動作

このアクションは実行のガードに従い、action.ymlでguard: [read-only, allow-host]を宣言しています。そのため、どちらのガードの下でも--allow-actionなしで実行します。拒否したステップは、リクエストを送る前に種類refusedで失敗します。

  • --read-onlyの下では、to: commentとto: issueはGitHubに書き込むので拒否します。to: summaryはジョブのページにだけ書くので実行します。
  • --allow-hostの下では、api_urlのホストと、各リダイレクト先のホストが、実行が許可するものでなければなりません。GitHubであればapi.github.comです。ポートのないURLは、スキームの既定のポートとして扱います。

ガードを参照してください。

関連項目

  • ノート - アクションがノートを残し、後続のステップがそれを読む仕組み
  • 外部アクション - Probeが外部アクションを解決し、照合する仕組み
更新日時