🐾

イシューのコピーをスクリプトでやってみてた

2025/01/31に公開

はじめに

手動でイシューを何度も複製するのが面倒だったので試しにスクリプトを作ってみました。
以下のツールを使用しているので任意の方法でインストールして使えるようにしておきます。

ローカルリポジトリに移動

$ cd /リポジトリのパス

スクリプト用のファイルを設置

任意の場所にスクリプト用のファイルを設置します。

$ mkdir sh
$ cd sh
$ touch cp-issue

リポジトリ内に以下のように作成されます。

sh
 ┗ cp-issue

スクリプトを書く

作成したcp-issueファイルに以下の内容を記述します。

cp-issue
#!/bin/zsh

# コピーしたいイシューのID
issueId=$1

# イシューIDの指定がない場合はエラーで終了させる
if [ -z "$issueId" ]; then
  echo "引数でイシューIDを指定してください"
  exit 1;
fi

# githubからイシューのデータを取得
# @see https://cli.github.com/manual/gh_issue
issueData=$(gh issue view "$issueId" --json body,title,labels --jq '{body: .body, title: .title, labelNameList: [.labels[].name]}')

# JSONから、タイトル、本文、ラベルを抽出
title=$(echo -E "$issueData" | jq -r '.title')
body=$(echo -E "$issueData" | jq -r '.body')
labelNameList=$(echo -E "$issueData" | jq -r '[.labelNameList[]] | join(",")')

# 新しいイシューを作成
gh issue create --title "$title コピー" --body "$body" --label "$labelNameList" --web

gh issueコマンドに複製用のコマンドは用意されていなかったので、コピー元のイシューデータを取得し、それを流用してgh issue createで新規作成するという形になっています。

上記のスクリプトでは、タイトル、本文、ラベルのみコピーしていますが、
参照できるフィールド一覧は以下のようになっています。
gh_issue_list > JSON Fields

assignees, author, body, closed, closedAt, comments, createdAt, id, isPinned, labels, milestone, number, projectCards, projectItems, reactionGroups, state, stateReason, title, updatedAt, url

-w, --webオプションを付けると作成画面がブラウザで表示されます。付けずに実行した場合は自動で作成されてイシュー一覧に登録されます。

jqで改行を含むjsonを扱う

jsonデータ内に以下のように改行コードが含まれているとします。

{
  "body": "## 概要\n\n〇〇の修正\n\n## 備考\n\n ああああ",
  "labels": [
    "fix"
  ],
  "title": "タイトル"
}

これをjqで解析しようとすると以下のようなエラーになってしまいます。

parse error: Invalid string: control characters from U+0000 through U+001F must be escaped at

こちらは下記のイシューのコメントのやり方で解消できました。

https://github.com/jqlang/jq/issues/1049#issuecomment-598247299

## The fix

Make sure the print utility you are using does not interpret newlines:

> printf "%s" '{ "name": ["hi\n", "there"] }' | jq .

or

> echo -E '{ "name": ["hi\n", "there"] }' | jq .

ファイルの権限を変更

コマンドを実行できるようにファイルの権限を変更しておきます。

$ chmod 755 sh/cp-issue

スクリプトを実行する

テスト用のイシューを作成しておきます。

ファイル名 コピー元のイシュー番号で実行します。

$ sh/cp-issue 17
Opening github.com/t-shiratori/github-actions-playground/issues/new in your browser.

#17のイシューの内容をコピーして新規イシュー作成画面が表示されます。

プレビュー表示

複数一気に作成してみる

ghコマンド部分をループで実行させれば複数まとめて作成できます。
--webオプションは削除します。

# 新しいイシューを作成
for i in {1..3}
do
  gh issue create --title "$title コピー" --body "$body" --label "$labelNameList"
done

順に新規作成処理が実行されて、3件のイシューが登録されます。

$ sh/cp-issue 17

Creating issue in t-shiratori/github-actions-playground

https://github.com/t-shiratori/github-actions-playground/issues/18

Creating issue in t-shiratori/github-actions-playground

https://github.com/t-shiratori/github-actions-playground/issues/19

Creating issue in t-shiratori/github-actions-playground

https://github.com/t-shiratori/github-actions-playground/issues/20

Discussion