PowerShell + GitHub Actions + Codecov でカバレッジを可視化する

# はじめに

以前 Pester でテストコードを書く方法と PSScriptAnalyzer で静的解析する方法の紹介記事を投稿していました。
ただ、ここまで記事を書いて CI の方法を紹介しないのは尻切れトンボ感が強いと思い、
GitHub Actions で `git push` したときに自動でテストコードと静的解析を実行し、
Codecov でカバレッジをいい感じに可視化するまでを試してみたので、その手順も残しておきます。

関連する過去の記事はこちら。

https://qiita.com/nimzo6689/items/65948bbfcda1f775a91f

https://qiita.com/nimzo6689/items/c19ad02f7f510e87ea49

https://qiita.com/nimzo6689/items/1c55c6782027a78a51e5

本稿で紹介する一式のソースコードはこちらに置いてます。

https://github.com/nimzo6689/pwsh-ci-demo

## CI で使用するツールについて

### GitHub Actions

https://docs.github.com/ja/actions

PowerShell 界隈では AppVeyor がよく利用される CI サービスになってますが、今回は GitHub Actions を採用しています。
かつては Windows 環境を無料で提供する CI サービスといえば AppVeyor が主流でしたが、
2019 年頃から GitHub や他の CI サービスでも無料で Windows 環境を利用できるようになりました。

この記事では、GitHub にサンプルを公開しているので、 GitHub Actions をそのまま CI サービスとして使うことにしました。
GitHub の公開リポジトリであれば無料で使えるので。
※ 本稿では基本的なところの説明は省きます。

### Codecov

https://docs.codecov.com/docs

カバレッジツールは Codecov を使いましたが、他にも有名どころとしては Coveralls があります。
ただ、 Codecov の方が使用感の評価が高い印象を持っていたことと、
PowerShell のカバレッジを Coveralls に連携できる確かな情報がなかったので、Codecov を採用しました。

ちなみに、こちらも公開リポジトリであれば無料で使えます。

# Pester でカバレッジレポートを出力する

Codecov に連携するカバレッジレポートは `Invoke-Pester` に CodeCoverage 関連の設定を有効にすることで出力できます。

https://pester.dev/docs/usage/code-coverage

設定情報は `Invoke-Pester` で該当するパラメータを指定するやり方（`-CodeCoverage`, `-CodeCoverageOutputFile` など）と
`PesterConfiguration` オブジェクトを作ってそれを `-Configuration` に渡す
やり方があります。
指定可能なオプションの詳細は [New-PesterConfiguration | Pester](https://pester.dev/docs/commands/New-PesterConfiguration) をご参照ください。

今回は yml ファイルで管理しやすいように後者を使っています。
書き方はざっくり以下のようになります。

```powershell
$PesterPreference = New-PesterConfiguration
$PesterPreference.Run.Path = ".\PwshCIDemo.Tests"
$PesterPreference.CodeCoverage.Enabled = $true
$PesterPreference.CodeCoverage.Path = ".\PwshCIDemo\*.ps*1"
Invoke-Pester -Configuration $PesterPreference
```

上記以外にも設定項目はありますが、基本デフォルト設定で問題ないです。
デフォルトの場合、 `coverage.xml` というファイルで JaCoCo 形式にカバレッジレポートが出力されます。

ちなみにテストが失敗すると以下のように GitHub Actions から確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114728/a5bbed1e-87fe-adab-0688-32e887a40cf5.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114728/74ce1c7f-9417-b1db-c2f2-c684253a9b08.png)

# PSScriptAnalyzer での解析結果を出力する

静的解析の範囲としてテストコードは対象外にしたいので、 `PwshCIDemo` 配下の PowerShell ファイルのみを対象にしています。
※ ファイルパターンを特に指定していなければ、`.ps1`、`.psm1` および `.psd1` が評価されます。 

CI で実行する際は `-OutVariable` を使って解析結果を PowerShell オブジェクトで取得し、メッセージの出し分けを行うようにしました。

```powershell
Invoke-ScriptAnalyzer -Path ".\PwshCIDemo" -Recurse -OutVariable issues
$errors   = $issues | ? {$_.Severity -eq 'Error'}
$warnings = $issues | ? {$_.Severity -eq 'Warning'}
if ($errors) {
    Write-Error "There were $($errors.Count) errors and $($warnings.Count) warnings total." -ErrorAction Stop
} else {
    Write-Output "There were $($errors.Count) errors and $($warnings.Count) warnings total."
}
```

もし、 `$errors` が１件以上であれば、GitHub Actions で以下のような表示になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114728/a4b12abf-877d-046c-4c43-06f5a4d13585.png)

# GitHub Actions を設定する

これまで説明した Pester と PSScriptAnalyzer のコマンドを GitHub Actions の設定ファイルに記載したのが以下のファイルです。

https://github.com/nimzo6689/pwsh-ci-demo/blob/main/.github/workflows/ci.yml

実行するプラットフォームとして、 Ubuntu, macOS, Windows の各最新バージョンを指定しています。

```yaml
    strategy:
      matrix:
        platform: [ubuntu-latest, macos-latest, windows-latest]
    runs-on: ${{ matrix.platform }}
```

これらのプラットフォームには、必要最小限のものしか入っていないので、
`Install from PSGallery` にて Pester と PSScriptAnalyzer を PSGallery からインストールします。

ちなみに、 shell に `pwsh` を指定していますが、 Windows 環境であれば `powershell` も指定可能です。
ただ、 `pwsh` が 7 系なのに対して、 `powershell` は 5 系が使われるようになるため注意が必要です。

今回はマルチプラットフォームに対応する PowerShell モジュールを想定しているので、 `pwsh` のみにしています。

## テストが Pass しているかのバッジを README.md につける

直前のテストが成功しているかどうかを示すために、README.md にバッジを追加します。

表示するバッジは以下の URL から取得できます。

`https://github.com/<OWNER>/<REPOSITORY>/actions/workflows/<WORKFLOW_FILE>/badge.svg`

今回ですとこちらです。

https://github.com/nimzo6689/pwsh-ci-demo/actions/workflows/ci.yml/badge.svg

参考：

https://docs.github.com/ja/actions/monitoring-and-troubleshooting-workflows/adding-a-workflow-status-badge

# Codecov を設定する

Pester で生成した `coverage.xml` を Codecov へアップロードする設定をしていきます。
Codecov へ連携するためには、ユーザ登録と Codecov の GitHub App のインストールが必要です。

まだの方は、以下のリンクから実施できます。

https://github.com/apps/codecov

GitHub Actions の設定内容はこちらです。
`secrets.CODECOV_TOKEN` を設定していますが、公開リポジトリの場合はなくても大丈夫です。

```yaml
- name: Upload test coverage to Codecov
  uses: codecov/codecov-action@v1.0.13
  with:
    name: Output coverage with Codeocv
    token: ${{ secrets.CODECOV_TOKEN }}
    file: coverage.xml
```

出力結果はこちらのリンクから確認できます。

https://app.codecov.io/gh/nimzo6689/pwsh-ci-demo

こんな感じで１ファイルごとにカバレッジが把握できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114728/bf2950e8-3764-0c0c-4c73-c78415bc10c4.png)

各ファイルを開けば、どの行でテストが実施・未実施なのかが一目でわかります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114728/77b92962-83d3-2731-81c8-5c17837d3bab.png)

## カバレッジの数値を示すバッジを README.md につける

Codecov で表示しているカバレッジの数値もバッジで表示できます。
バッジは以下の URL から取得しました。

https://app.codecov.io/gh/nimzo6689/pwsh-ci-demo/settings/badge

# 参考

https://dev.to/roberthstrand/code-coverage-for-powershell-module-development-1kh4

https://docs.github.com/ja/actions/automating-builds-and-tests/building-and-testing-powershell