リポジトリの一部分だけcheckoutできるsparse-checkoutがactions/checkout@v4に来てた

正確には[**3.5.3**](https://github.com/actions/checkout/releases/tag/v3.5.3)で追加されたらしい。

## 目次
- [sparse-checkoutとは？](https://qiita.com/nicco_mirai/items/5a306549e57ee69403c9#sparse-checkout%E3%81%A8%E3%81%AF)
- [actions/checkout@v4での使い方](https://qiita.com/nicco_mirai/items/5a306549e57ee69403c9#actionscheckoutv4%E3%81%A7%E3%81%AE%E4%BD%BF%E3%81%84%E6%96%B9)
- [モノレポではないプロジェクトにおける利点](https://qiita.com/nicco_mirai/items/5a306549e57ee69403c9#%E3%83%A2%E3%83%8E%E3%83%AC%E3%83%9D%E3%81%A7%E3%81%AF%E3%81%AA%E3%81%84%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%81%AB%E3%81%8A%E3%81%91%E3%82%8B%E5%88%A9%E7%82%B9)

## sparse-checkoutとは？
そもそもはgitの機能で、

```
./
  ├ .git/
  ├ hoge/
  ├ fuga/
  ├ piyo/
  └ README.md
```
このようなモノレポがある場合に

```bash
# CI環境の場合は`--filter=blob:none`より`--depth=1`の方がおすすめ
git clone --filter=blob:none --no-checkout https://github.com/you/your-repo
cd your-repo
git sparse-checkout set hoge
git checkout
```

とすると

```
./
  └ your-repo/
    ├ .git/
    ├ hoge/
    └ README.md
```

こんな感じで一部分だけcheckoutできますよというもの。
本筋ではないので詳しくは[公式ドキュメント](https://git-scm.com/docs/git-sparse-checkout)に譲ります。

## actions/checkout@v4での使い方
参考: [公式README](https://github.com/actions/checkout#checkout-v4)

上と同じモノレポで考えてみます。

### 1つのディレクトリだけ欲しい
```yml
- uses: actions/checkout@v4
  with:
    sparse-checkout: hoge
```

↓

```
./
  └ your-repo/
    ├ .git/
    ├ hoge/
    └ README.md
```


### 複数ディレクトリ欲しい
```yml
- uses: actions/checkout@v4
  with:
    sparse-checkout: |
      hoge
      fuga
```

↓

```
./
  └ your-repo/
    ├ .git/
    ├ hoge/
    ├ fuga/
    └ README.md
```

### ディレクトリはいらない(トップレベルにあるファイルだけ欲しい)
```yml
- uses: actions/checkout@v4
  with:
    sparse-checkout: .
```

↓

```
./
  └ your-repo/
    ├ .git/
    └ README.md
```

### 指定したファイルだけ欲しい(非コーンモード)

```yml
- uses: actions/checkout@v4
  with:
    sparse-checkout: |
      README.md
    sparse-checkout-cone-mode: false # デフォルトはtrue
```

↓

```
./
  └ your-repo/
    ├ .git/
    └ README.md
```

今回の例では上と変わりません。コーンモードの挙動について詳しくは[**こちら**](https://git-scm.com/docs/git-sparse-checkout#_internalscone_mode_handling)。

## モノレポではないプロジェクトにおける利点
このようにsparse-checkoutとは元来モノレポで開発を行っているプロジェクトに向けた機能ではあるものの、実は我々GitHub Actions芸人にとっても嬉しいことがあります。
それは**ワークフロー内で実行するスクリプトを別ファイルに切り出せる**ことです。

- スクリプトが長くなってしまってymlの見通しが悪い
- 他のワークフローと共有したい
- 1stepだけ丁寧にデバッグしたい
- スクリプトを**他の言語で書きたい**

のようなニーズからスクリプトファイルを作成したり(場合によっては[reusing-workflows](https://docs.github.com/ja/actions/using-workflows/reusing-workflows)を作ったり)しますが、従来はこのファイルを読み込むためにリポジトリの全てをfetchする必要がありました。

```yml
- uses: actions/checkout@v4 # ←これがないと動かないのにこれが一番遅い
- uses: actions/setup-python@v4
  with:
    python-version: "3.11"
- run: python .github/scripts/awesome_script.py
```

それが今ではこう。

```yml
- uses: actions/checkout@v4
  with:
    sparse-checkout: .github # 速い！
- uses: actions/setup-python@v4
  with:
    python-version: "3.11"
- run: python .github/scripts/awesome_script.py
```

他にも[`gh`コマンド](https://cli.github.com/manual/)やGitHub APIを叩くために.gitだけ欲しい場合もあります。

```yml
name: PR Number
on:
  workflow_dispatch:
    inputs:
      branch_name:
        required: true
        type: string
env:
  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
jobs:
  search:
    name: Search PR
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4 # ←これがないと動かない
        with:
          sparse-checkout: . # .gitディレクトリ(とトップレベルのファイル)だけ取得
      - run: gh pr view ${{ inputs.branch_name }} --json number | jq -r .number
```

便利ですね。

## おわりに
というわけで3.5.3から追加されたsparse-checkoutについてご紹介しました。特にgithub-hosted runnerを使っている場合は秒単位での課金になりますので、こういった細かいテクニックを使ってガンガン節約していきましょう。

それでは。