GithubActionsであるRepositoryから別のRepositoryにissueを丸ごとコピーする

**[YUMEMI Advent Calendar Advent Calendar 2021](https://qiita.com/advent-calendar/2021/yumemi)**
23日目の記事です。


Github Actionsを利用して、あるRepositoryから別のRepositoryにissueを丸ごとコピーする
っということにチャレンジしました。

この記事ではその時に得られたTipsなどをご紹介します。

## なぜissueをコピーしようと思ったか？

### 背景
ゆめみのiOS/Androidエンジニアの採用ではコードディングテストを実施しております。
以下、Githubに課題のリポジトリを公開しております。

- [iOS](https://github.com/yumemi-inc/ios-engineer-codecheck)
- [Android](https://github.com/yumemi-inc/android-engineer-codecheck)

課題の実施方法は、候補者さんのGithubアカウントに上記リポジトリを[複製](https://docs.github.com/en/repositories/creating-and-managing-repositories/duplicating-a-repository)する
上記リポジトリのissueを消化する
っというものです。

このリポジトリの[複製](https://docs.github.com/en/repositories/creating-and-managing-repositories/duplicating-a-repository)、issueは複製されないのです。

### issueの丸ごとコピーで期待できるとと

もし、issueが自動的に複製されれば

- 2つのリポジトリを行き来しなくて良い
- PRと紐付け
- issueに取り組んだときのメモとして活用

などなど、候補者さんの体験向上や評価に関わる情報量が増えることが期待できる
っと考えました。

## 実際にやってみた

そこで、複製元リポジトリから複製先リポジトリへissueを丸ごとごっそりコピーするGithubActionsのworkflowを作ろう と考えました。

出来上がったWorkflowが[こちら](https://github.com/yumemi-inc/ios-engineer-codecheck/blob/main/.github/workflows/copy-issues.yml)です。
全てのケースを完全に網羅出来ていませんが、現状の課題issueのコピーはほとんどのケースで問題なく動作します。

当初、簡単にできるだろうと高を括るっていましたが、想像以上に大変でした...

### Githubの情報取得、操作について

今回はいくつかのGithub APIを利用しています。

- issue情報取得・作成
- label取得・作成
- マイルストーン取得・作成

これらは[octokitのGitHub API Request](https://github.com/marketplace/actions/github-api-request)を利用しました。
GithubのAPIリファレンスを参考に、エンドポイントとパラメータを指定すればGithub APIが簡単に利用できます。

### Github Actionsで利用できる式

Github Actionsで利用できる独自の式があります。
文字列を式として評価させるには `${{ }}` で式を囲います。

それほど多機能ではありませんが、Jsonエンコード・デコードや配列操作などがあります。
https://docs.github.com/ja/actions/learn-github-actions/expressions

残念なのが式は表現できても文は使えないので、配列のループが出来ません。

今回ですと、

`複製元リポジトリのissueを取得し、そのissueリストのループを回して、複製先リポジトリにissueを作成する`
といったことを簡単に記述できません。そのため、次に記載するMatrixを利用しました。

### JobからJobへデータの受け渡し

Jobの結果を出力し、後続のJobで使うことができます。
[on.workflow_call.outputs](https://docs.github.com/ja/actions/learn-github-actions/workflow-syntax-for-github-actions#onworkflow_calloutputs)

Jobを役割ごとに分割すると可読性の向上に繋がります。
また、下のMatrixを使って
`あるJobの出力した配列要素を一つづつ処理するJob` を記述できます。

Jobの結果には、改行のある文字列を格納することができませんでしたので
私は改行文字を除去したりエスケープすることで対応しました。
この辺り、良い方法をご存知の方がいらっしゃいましたら是非ご教示頂きたいです。
https://github.com/yumemi-inc/ios-engineer-codecheck/blob/7e658bd9b29d28f883995d1b7bb5594f86f6d92c/.github/workflows/copy-issues.yml#L21

### Github ActionsのMatrix

MatrixはJobを実行するためのバリエーションを定義する仕組みです。
公式サンプルにあるように、実行OSや環境のバージョンを複数指定して、それぞれ実行するようなことができるようです。
[example-running-with-multiple-operating-systems](https://docs.github.com/ja/actions/learn-github-actions/workflow-syntax-for-github-actions#example-running-with-multiple-operating-systems)

今回は主に、複製元issue一つひとつをバリエーションとし、複製先リポジトリにissueを作成するJobを書きました。
https://github.com/yumemi-inc/ios-engineer-codecheck/blob/7e658bd9b29d28f883995d1b7bb5594f86f6d92c/.github/workflows/copy-issues.yml#L140

このようにJobからJobへの値受け渡しとMatrixを連携することで配列要素を処理することが出来ました。

### その他大変だったこと

issue同士のリンク (Githubでの `#7` ← のような記述)を保つことが大変でした...
結局、作成するissueの数や、すでにあるissueの数からshell芸で計算しています。

他に、
[octokitのGitHub API Request](https://github.com/marketplace/actions/github-api-request)の入力値として改行を処理させることが出来ませんでした。具体的にはissueを作成するときのissue本文です。
っというのも、このissue本文は前段のJobから受け渡された値...つまり改行のエスケープを余儀なくされた値です。
そのため、今回はissueの作成のみ[octokitのGitHub API Request](https://github.com/marketplace/actions/github-api-request)を使わずにcurlコマンドで実行しました...
https://github.com/yumemi-inc/ios-engineer-codecheck/blob/7e658bd9b29d28f883995d1b7bb5594f86f6d92c/.github/workflows/copy-issues.yml#L151-L177


## 最後に

ゆめみのiOS/Android採用にご応募いただく際は、ぜひissue丸ごとコピーのworkflowをご活用ください。