gh cliを触って個人的に良さそうだったコマンドメモ

## はじめに
以前から気になっていた`gh cli`を触ってみただけの記事です。
私と同じく、気になっているけどまだ触ったことない方へ参考になれば幸いです。

公式ドキュメントが読みやすくまとまっているのですが、その中で個人的に使えそうなものをまとめました。

[GitHub CLI | Take GitHub to the command line](https://cli.github.com/)

[gh reference | GitHub CLI](https://cli.github.com/manual/gh_help_reference)

[GitHub Documentation](https://docs.github.com/ja)

### GitHub CLIとは
GitHub公式のOSS (オープンソースソフトウェア)です。
以下、公式ブログから引用します。

> GitHub CLI とは、利用しているターミナルでGitHubを使用できるようにするものです。コンテキストの切り替え回数が減るため、これまで以上に作業そのものに集中でき、スクリプトの記述や独自のワークフローの作成が、さらに簡素化されます。
> 引用：[GitHub CLI 1.0をリリース - GitHubブログ](https://github.blog/jp/2020-09-18-github-cli-1-0-is-now-available/)

利点としては、「画面ポチポチする作業をコマンドで解決する」という一般的なものだと思います。
例えば、
- コンテキストの切り替え回数が減る[^1]ので楽になる
- 作業をコード化できる
  - 似た作業を素早く行える
  - 作業フローを振り返りやすくなる
  - 作業を自動化しやすくなる

とかだと思います。

[^1]:例えば
(ターミナル　→　ブラウザ（GitHub）→　ターミナル　→　他作業)
が
(ターミナル　→　他作業)
になることだと思います。

## 本題

### インストールと認証

[Manual | GitHub CLI](https://cli.github.com/manual/) の通り行いました。

インストールはこちらから
[cli/cli: GitHub's official command line tool](https://github.com/cli/cli#installation)

インストールできたら以下のコマンドを実行します。
```bash
gh auth login
```

詳細は多くの記事で紹介されているので割愛させていただきます。

[GitHub CLI を使ってみた | DevelopersIO](https://dev.classmethod.jp/articles/tried-using-github-cli/)

[GitHub CLI 2.0でIssue周りの操作を試してみた | DevelopersIO](https://dev.classmethod.jp/articles/i-tried-operations-around-issue-with-github-cli-20/#toc-2)



### そのまま使えそうなコマンド

```bash
gh issue list     # イシューを一覧取得する(最新30件)
gh pr list        # プルリクエストを一覧表示する(最新30件)
gh pr diff        # プルリクエストの差分確認
gh pr checkout 1  # プルリクエスト#1の状態をチェックアウトする
gh pr view        # 現在のブランチに対するプルリクエストを表示する
```

#### [プルリクエストをローカルでチェック アウトする](https://docs.github.com/ja/pull-requests/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/checking-out-pull-requests-locally)

```bash
gh pr checkout {<number> | <url> | <branch>}
```
例えば、プルリクエストの番号を確認してコマンドを打つだけで、ローカルへチェックアウトできます。
ブランチを確認して、切り替えるという作業を一発で行えそうな気がします。
参考： [gh pr checkout | GitHub CLI](https://cli.github.com/manual/gh_pr_checkout)


#### リポジトリ間でラベルをクローンする
```bash
gh label clone <repository>
```
現在のリポジトリに対して、指定したリポジトリのラベルをクローンできます。

同名ラベルがあるとスキップされます。
上書きしたい場合は、`-f`オプションを使います。

>Labels from the source repository that already exist in the destination repository will be skipped. You can overwrite existing labels in the destination repository using the --force flag.
[gh label clone | GitHub CLI](https://cli.github.com/manual/gh_label_clone)

### エイリアスを貼って使いたいコマンド

`gh alias`でエイリアスを作成・一覧・削除できるので活用しましょう。
（以下は公式の例を引用してます）

```bash
# 自分に割り当てられたイシューを一覧表示する
gh issue list --assignee @me
# エイリアスを作成する
gh alias set homework 'issue list --assignee @me'
# 使用例
gh homework
# 設定したエイリアスを一覧表示する
gh alias list
# 設定したエイリアス'homework'を削除する              
gh alias delete homework
```

参考: [gh alias | GitHub CLI](https://cli.github.com/manual/gh_alias)

#### イシュー本文中にキーワードを含むものを一覧表示する

```bash
# イシュー本文中に「hoge」を含むものを一覧表示する
gh issue list -S hoge
# エイリアスを作成する
gh alias set --shell isearch 'gh issue list -S "$1"'
# 使用例
gh isearch hoge
```

参考：[gh issue list | GitHub CLI](https://cli.github.com/manual/gh_issue_list)

#### ラベルに紐づいたイシューを確認する

```bash
# bugsラベルのイシューを一覧表示する
gh issue list --label=bugs
# エイリアスを作成する
gh alias set bugs 'issue list --label=bugs'
# 使用例
gh bugs
```

↓ ラベルを引数で渡す形にしました

```bash
# bugsラベルのイシューを一覧表示する
gh issue list --label=bugs
# エイリアスを作成する
gh alias set --shell iwith 'gh issue list --label="$1"'
# 使用例
gh iwith bugs
```

`--shell`: エイリアスに引数を設定する

#### ブラウザで新規プルリクエストを作成する

```bash
# ブラウザでプルリクエストを作成する
gh pr create -w
# エイリアスを作成する
gh alias set propen 'pr create -w'
# 使用例
gh propen
```
`-w`: ブラウザで開く
pushした後に便利だと思います。
コマンドラインだけでもプルリクエストを作成できますが、ここはお好みで・・

参考：[gh pr create | GitHub CLI](https://cli.github.com/manual/gh_pr_create)

#### Githubのリモートブランチを一覧表示する

```bash
# Githubのリモートブランチを一覧表示する
gh api -H "Accept: application/vnd.github.v3+json" repos/{owner}/{repo}/branches --jq ".[].name" --paginate
# エイリアスを作成する
gh alias set branch 'api -H "Accept: application/vnd.github.v3+json" repos/{owner}/{repo}/branches --jq ".[].name" --paginate'
# 使用例
gh branch
```
- `gh api`: GitHub API(v3)を利用する
  - `-H`: リクエストヘッダを指定する
    - `"Accept: application/vnd.github.v3+json"`: AcceptヘッダにGitHub API v3のjsonを指定する (参考: [メディアタイプ - GitHub Docs](https://docs.github.com/ja/rest/overview/media-types))
  - `--jq`: レスポンスをjq形式に整形する
  - `--paginate`: レスポンス結果がなくなるまでリクエストする
  - `{owner}`、`{repo}`: 現在のユーザー、リポジトリが反映される（PowerShellなどは`{}`の解釈で競合するので注意らしいです） 
  >Placeholder values "{owner}", "{repo}", and "{branch}" in the endpoint argument will get replaced with values from the repository of the current directory or the repository specified in the GH_REPO environment variable. Note that in some shells, for example PowerShell, you may need to enclose any value that contains "{...}" in quotes to prevent the shell from applying special meaning to curly braces.
引用：[gh api | GitHub CLI](https://cli.github.com/manual/gh_api)

参考：
[gh api | GitHub CLI](https://cli.github.com/manual/gh_api)
[ブランチ - GitHub Docs](https://docs.github.com/ja/rest/branches/branches#list-branches)

#### プルリクエストの変更ファイルを一覧表示する
```bash
# プルリクエストの変更ファイルを一覧表示する
gh api -H "Accept: application/vnd.github.v3+json" repos/{owner}/{repo}/pulls/{pull_number}/files --paginate --jq '.[].filename'
# エイリアスを作成する
gh alias set --shell prfiles 'gh api -H "Accept: application/vnd.github.v3+json" repos/{owner}/{repo}/pulls/"$1"/files --paginate --jq ".[].filename"'
# 使用例
gh pr list
gh prfiles 1
```
役立つ場面は滅多にないかもしれません。。

参考：[Pulls - GitHub Docs](https://docs.github.com/ja/rest/pulls/pulls#list-pull-requests-files)

#### プルリクエストのリンクを取得する

メモ・報告用です。

```bash
# プルリクエスト(#1)のリンクを取得する
gh pr view 1 --json number,title,url -q "\"[#\" + (.number|tostring) + \" \" + .title + \"](\" + .url + \")\""
# エイリアスを作成する(クリップボードへ保存するコマンドを加えてます)
gh alias set --shell pclip \
'gh pr view "$1" --json number,title,url -q "\"[#\" + (.number|tostring) + \" \" + .title + \"](\" + .url + \")\"" | pbcopy'
# 使用例
gh pr list
gh pclip 1
```
`-q`オプションで`jq -r`と同じようにjsonでなく文字列で出力できます。
> The --jq option accepts a query in jq syntax and will print only the resulting values that match the query. This is equivalent to piping the output to jq -r, but does not require the jq utility to be installed on the system.
>引用： [gh formatting | GitHub CLI](https://cli.github.com/manual/gh_help_formatting)

参考： [jq 1.6 Manual](https://stedolan.github.io/jq/manual/v1.6/)

<details>
<summary>クリップボードへ保存するコマンド</summary>

macOSの場合
```bash
pbcopy
```

Ubuntuの場合
xselをインストールして行う。
```bash
xsel --clipboard --input
```

Windows、WSLの場合
```bash
clip.exe
```

参考：
[コマンドラインからクリップボードへのコピー - Qiita](https://qiita.com/Kzno/items/6f2fa98256bdffb0fd43)
[WSLでpbcopyを使う - Qiita](https://qiita.com/meihei/items/d1c4399b99e4f22eabab)

</details>



#### イシューのリンクを取得する

```bash
# イシュー(#1)のリンクを取得する
gh issue view 1 --json number,title,url --template "[#{{.number}} {{.title}}]({{.url}})"
# エイリアスを作成する(クリップボードへ保存するコマンドを加えてます)
gh alias set --shell iclip \
'gh issue view "$1" --json number,title,url --template "[#{{.number}} {{.title}}]({{.url}})" | pbcopy'
# 使用例
gh issue list
gh iclip 1
```
jqだけでなく、Go言語のテンプレート形式でも出力を整形できます。
> With --template, the provided Go template is rendered using the JSON data as input. 
>引用： [gh formatting | GitHub CLI](https://cli.github.com/manual/gh_help_formatting)

参考： [template package - text/template - pkg.go.dev](https://pkg.go.dev/text/template)


### 実現できなかったこと

#### Github上で最新ブランチから新規リモートブランチを作成する
ローカルで作業ブランチを作成する前のfetch忘れを防ぐためです。

参考：[リポジトリ内でブランチを作成および削除する - GitHub Docs](https://docs.github.com/ja/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-and-deleting-branches-within-your-repository#creating-a-branch)

#### イシュー、プルリクエストの本文をVSCodeで編集する
とても些細なことですが、ブラウザ上だと編集しにくいからです。
(タブでインデントできない、慣れたショートカット使えない、etc...)

以下のようにvimは設定できますが、VSCodeは使えないようでした。
```bash
gh config set editor vim
```
（決してvimが嫌いなわけではないです。好きになっていきたいです。）


## 参考
[GitHub CLIで始める快適GitHub生活 - Qiita](https://qiita.com/ryo2132/items/2a29dd7b1627af064d7b)
[jqでjson以外の文字列を表示する | 瀬戸内の雲のように](https://www.setouchino.cloud/blogs/91)
[bshでのクォーテーションの入れ子 | b.l0g.jp](https://b.l0g.jp/shell/bsh-nested-quotation/)

## おわりに
導入も使用方法も簡単なので、少しでも効率的にしたい方におすすめでした。

個人的には、コマンドで解決できることは理解して使っていけるようになりたいです。
`gh api`を使えば、
[GitHubのREST API - GitHub Docs](https://docs.github.com/ja/rest)
に載っている内容は大体実現できそうなことが分かったのでよかったです。


最後に`gh cli`の拡張機能を置いておきます。
[gh-extension · GitHub Topics](https://github.com/topics/gh-extension)
どんどん便利になっていきそうですね！