自動で立てたIssueがslug改名で自動クローズされずに残る穴を塞いだ

  • #画像生成
  • #Issue
  • #slug
  • #自動化

今回やったこと

画像生成を後段へ回す自動化では、記事が画像待ちになった時点で依頼Issueを作り、生成物がそろったら公開処理の後段でIssueを閉じる。ここで記事の slug を、依頼と記事を結び付ける識別子として使っていた。公開前後に slug が改名されると、記事自体は存在するのに、Issueを閉じるための鍵だけが失われる。

結果として、画像生成が完了しても未処理のIssueが残り続ける。人間から見ると同じ記事でも、自動処理から見ると「古いslugの依頼」と「新しいslugの記事」が別物になるためだ。今回の修正では、画像依頼・生成から公開昇格に至るまでの識別子の受け渡し経路を見直した。

slugは表示名であって安定したIDではない

slugはURLやファイル名に使いやすく、記事を探すには便利である。一方で、編集判断によって変わり得る。タイトルを短くしたり、表記を揃えたり、公開前に検索向けの名前へ変更したりする運用では、slugが永続識別子だとは限らない。

用途slugの適性理由
URL・記事の見た目高い読者が辿る名前として分かりやすい
ファイル名高い作業対象を一覧しやすい
非同期Issueの永続的な対応付け低い改名で過去の鍵が変わる
状態遷移の内部ID低い表示名と識別子の責務が混ざる

問題は、slugを使ったこと自体ではない。変更される可能性のある表示名を、閉じる処理の唯一の鍵にしたことにある。画像生成はその場で完結する処理ではなく、依頼作成、生成、rawへの保存、レビュー、公開という複数の段階をまたぐ。その間に名前が変わるなら、状態を追跡する別の軸が必要になる。

依頼と公開を別の状態として扱う

まず、画像依頼Issueの状態と、記事の公開状態を同じものとして扱わない。Issueは画像を生成・添付する作業の状態を持ち、記事は ready、deploy、journalなど別の昇格状態を持つ。記事が公開されたからといって、Issue側の対応関係をslugの再計算だけで探す設計にすると、改名で切れる。

今回の対象では、画像生成スクリプト、起稿手順、公開昇格スクリプトをまとめて確認した。依頼時に残す情報、生成物が置かれる場所、公開後に閉じる対象をそれぞれ確認し、slugの変更後も元の依頼へ戻れる情報を使うように経路を修正した。重要なのは、Issueのタイトルを人間向けに読みやすくすることと、機械が対応関係を解決することを分離することだ。

コードだけを直して終わりにしないため、生成・昇格・テストを同じ前提で揃える。生成側が新しい識別方法で記録しても、昇格側が古いslug検索を続ければ、見かけ上は直ったように見えて実運用で残る。反対に、閉じる処理だけを変更しても、過去の依頼に必要な情報が保存されていなければ対応できない。

自動化で名前を使うときの確認項目

記事や画像の処理に名前を使う場合、少なくとも次の境界を確認する。

  1. その名前は人間の編集で変わるか。
  2. 非同期処理が終わるまで、同じ値を保証できるか。
  3. 名前を変えた後も、過去の依頼を検索できるか。
  4. 依頼作成・生成・昇格・クローズの全段階が同じ識別規則か。
  5. 対応付けに失敗したとき、未処理として見えるか。

最後の点も重要である。閉じる対象が見つからないときに成功扱いにすると、Issueだけが積み残される。自動化の出口では、対象が見つかったこと、状態が変わったこと、変えられなかったことを分けて記録する必要がある。

やってみてわかったこと

人間には同じ記事に見える名前の変更が、無人処理では状態遷移を壊す。特に画像生成のような非同期処理は、依頼した時点と公開する時点が離れるため、表示名を内部IDに流用すると問題が後から現れる。

対策は、slugの変更を禁止することではない。slugはURLやファイル名として変更可能なままにし、Issueと記事の対応には変更されない情報を持たせることだ。そして、生成・昇格・テストのすべてがその情報を使うようにする。名前は読者と人間のため、識別子は状態機械のため、と責務を分けると、改名が自動化全体の破綻条件にならない。

実装ステータスと更新履歴

実装済み・稼働中。参照した実装は、画像生成・自動起稿・公開昇格を担うスクリプト群である。

  • 更新履歴: 2026-09-12 初稿。
  • 訂正履歴: なし。