以前、GitHubとはてなブログを連動させている話を書きました。はてなブログ提供のボイラーテンプレートを今も使っていますが、はてなワークフローは運用していく中で直接使わないケースも出てきたのでメモです。
はてなブログのワークフロー想定と使い勝手
はてなブログのボイラーテンプレートは、はてなが提供しているReusable Workflow hatena/hatenablog-workflowsを使っています。はてな管理のワークフローが実処理を担っているため、利用者はボイラーテンプレートを使うだけで済むという方針ですね。
実際割とよく機能するのですが、私はいくつかのワークフローはコピー&ペーストしてきて自前管理で運用しています。
はてなワークフローを使い続ける課題
はてなワークフローを使ってみると、いくつかの課題が見えてきました。以下に挙げるものは、私が実際に運用していて感じたことです。
ワークフローがタグ指定
hatena/Hatena-Blog-Workflows-Boilerplateとhatena/hatenablog-workflowsは、共にReusable Workflowやアクションをタグ指定しています。昨今のSHA指定が推奨される流れを考えると、タグ指定はセキュリティやメンテナンスの観点で課題があります。ボイラーテンプレートのREADMEを見るとworkflowの変更は原則 Reusable workflows を変更するため基本的には更新は不要です
と書いてあり、v1タグを指定している意図が分かります。
タグ指定は、例えば次の利用シーンで課題があります。
- Reusable Workflowが使っているアクションで脆弱性があった時にユーザーは気づけず回避が難しい
- はてなブログワークフロー自身がSHA固定するプラクティスから外れている
先日のtj-actions/changed-filesの脆弱性CVE-2025-30066が発表されたとき、はてなブログのボイラーテンプレートはこれをタグで指定したため影響を受ける状況でした。脆弱性発生が土曜、SHAに切り替える修正は月曜に入ったのですが、はてなが管理しているため土日は修正されないままでした。Issueで脆弱性共有はあげたものの、PRをあげても週末にマージされないのは分かっていたためこのタイミングで私は自前ワークフローへの変更に切り替えました。
サードパーティアクションはSHA指定されたものの、はてなブログのボイラーテンプレートからワークフロー参照はv1タグを使っておりSHA指定されていません。このため、はてなブログのワークフロー自身が同様のCVE書き換えされた場合、ボイラーテンプレートを使っているユーザーは影響を受けることになります。
ワークフローやアクションの修正
hatena/hatenablog-workflowsの処理に手を入れたいとき、はてな側の方針とやりたいことが一致なければ変更が受け入れられないでしょう。例えば私はtj-actions
を使わないポリシーに変えましたが、はてなブログのボイラーテンプレートはtj-action/changed-files
をそのまま使う方針です。こういった方針の違いは当然ありますし、その場合はフォークするか自前でワークフローを持つしかないでしょう。それはそういうものです。
ボイラーテンプレートでの利用以上の利用想定がなさそう
これはAPI設計の話ですが、はてなブログのワークフローはボイラーテンプレートの利用しか想定されてなさそうです。
これは、ボイラーテンプレートにないワークフローの再利用は試されていなさそうな空気を修正PRから感じています。
この修正PRは、create-draftワークフローがcreate-draft-pull-requestアクションを呼び出す際の修正に関するものです。create-draft-pull-requestアクションはinput
でtitle
を受け取りますが、ボイラーテンプレートではgithub.event.inputs.title
を指定していました。このため、アクションのtitle
は使われず、呼び出し元のcreate-draftワークフロー呼び出し時のtitle
が使用される仕様になっていました。これは、設計上の意図と異なる挙動である可能性が高いと考えられます。他のワークフローも呼び出しやinputsが柔軟ではないことから、ボイラーテンプレートの利用しか想定されていないと推測されます。
uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7 env: OWNER_NAME: ${{ steps.set-owner.outputs.OWNER_NAME }} ENTRY_ID: ${{ steps.set-entry-variables.outputs.ENTRY_ID }} PREVIEW_URL: ${{ steps.set-entry-variables.outputs.PREVIEW_URL }} with: title: ${{ github.event.inputs.title }} branch: draft-entry-${{ env.ENTRY_ID }} body: | ## ${{ github.event.inputs.title }} 省略
アクションに渡したtitle
を使うには次のようにinputs.title
を指定する必要があります。
- name: create draft pull request uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7 env: OWNER_NAME: ${{ steps.set-owner.outputs.OWNER_NAME }} ENTRY_ID: ${{ steps.set-entry-variables.outputs.ENTRY_ID }} PREVIEW_URL: ${{ steps.set-entry-variables.outputs.PREVIEW_URL }} with: title: ${{ inputs.title }} branch: draft-entry-${{ env.ENTRY_ID }} body: | ## ${{ inputs.title }} 省略
暫定対応
私の運用では、ボイラーテンプレートをフォークして運用するのではなく、コピー&ペーストしてファイル名の先頭に_
をつけて運用しています。自分のポリシーと合わないものだけをコピーして修正、あとはボイラーテンプレートのものを使うという運用です。ポリシーは次の通りです。
- 自分が使いたくないアクションを差し替える
- できないことをできるようにする
- hatenablog-workflowsもSHA指定しつつ自動更新する
自分が使いたくないアクションを差し替える例
例えば、hatenablog-workflowsから.github/workflows/push-published-entries.yamlワークフローをもってきて.github/workflows/_push-published-entries.yamlとして保持しています。中で他のワークフローを参照していたらそれももって来る感じです。もともと参照していたワークフローはコメントアウトして、いつでも戻せるようにしておきます。
# BEFORE: hatena/hatenablog-workflows | .github/workflows/push-published-entries.yaml name: "[Reusable workflows] push published entries" on: workflow_call: secrets: OWNER_API_KEY: required: true jobs: upload-images: if: github.event.pull_request.merged == false uses: hatena/hatenablog-workflows/.github/workflows/upload-images.yaml@4cb2032c9665ad3b0eba9835182e2d23a1d49a81 # v1 secrets: OWNER_API_KEY: ${{ secrets.OWNER_API_KEY }} # AFTER: guitarrapc/blog | _push-published-entries.yaml name: "[Reusable workflows] push published entries" on: workflow_call: secrets: OWNER_API_KEY: required: true jobs: upload-images: if: github.event.pull_request.merged == false # uses: hatena/hatenablog-workflows/.github/workflows/upload-images.yaml@v1 uses: ./.github/workflows/_upload-images.yaml secrets: OWNER_API_KEY: ${{ secrets.OWNER_API_KEY }}
これはupload-images.yamlがtj-actions/changed-filesを使っているため、私のポリシーに合わないからです。変更した際は、外部アクションをすべてSHAに変更しつつ、tj-actions/changed-files
からdorny/paths-filter
にしていました。以下は、現在(左)とhatenablog-workflows(右)の差分です。
できないことをできるようにする
例えば、.github/actions/create-draft-pull-request/action.yamlはPRボディが固定文字になっています。PULL_REQUEST_TEMPLATE.mdを指定して持ってくるか、文章を変更するかで悩みましたが、後者にしました。本家の1.3.8でPULL_REQUEST_TEMPLATE.mdがあれば指定できるようになるPRが取り込まれているので、1.3.8が出たら戻す予定です。
hatenablog-workflowsもSHA指定しつつ自動更新する
ユーザーがhatenablog-workflowsワークフローを固定するときも、v1タグで運用する想定なのはちょっと微妙です。初めからSHA指定にしておいてDependabotで自動更新するようにテンプレート展開すれば、ユーザーは自分で更新する手間を最小にしつつワークフローを更新するか選択できます。
私は次のようにして、npmとGitHub Actionsの両方をDependabotで更新するようにしています。これにより、SHA指定しつつも自動更新が可能になります。ボイラーテンプレートでもGitHub Actionsの更新をする.github/dependabot.yaml
が追加されればタグ指定からSHA指定に変更できそうですが、現状はSHA指定のままです。
# ref: https://docs.github.com/en/code-security/dependabot/working-with-dependabot/keeping-your-actions-up-to-date-with-dependabot version: 2 updates: - package-ecosystem: "npm" directory: "/" schedule: interval: "weekly" # Check for updates to GitHub Actions every week ignore: # I just want update action when major/minor version is updated. patch updates are too noisy. - dependency-name: "*" update-types: - version-update:semver-patch - package-ecosystem: "github-actions" directory: "/" schedule: interval: "weekly" # Check for updates to GitHub Actions every week ignore: # I just want update action when major/minor version is updated. patch updates are too noisy. - dependency-name: "*" update-types: - version-update:semver-patch
まとめ
hatena/hatenablog-workflowsは多くの人が使っていて、ワークフローとして想定があるのでなかなか修正を出しにくいものもあります。API的に問題ない場合はこれからも提示していきますが、合わない割り切って手元管理でいい気持ちもあります。徐々に良くなってきているので、今後も貢献できるものはしたいです。