CI/CDのセットアップ① (GitHub & Azure)

今回は、CI/CD (継続的インテグレーション/継続的デリバリー)が行える環境を構築します。簡単にご説明すると、CI/CDとはソフトウェアのビルドやテスト、さらにはデプロイ(デリバリー)を自動化する仕組みになっています。CI/CDと言えば「GitHub Actions」などが有名ですが、今シリーズではこれに加えて同様なサービスである「Azure Pipelines」の環境も構築します。これらのサービスは基本的には条件付きで無料ですが、条件によっては規定された時間を越えた分は課金対象になりますので、これらの仕組みをローカル環境(ご自身のPC等)でも実行できる仕組みも構築します。この記事は GitHub の CIについて書かれた記事になっています。
今回の記事を作成するにあたり、以下の講座で勉強させていただきました。非常に分かりやすく大変勉強になりました。タイトルの通り内容的には、GitHub Actionsを使用してCI (ビルド、テスト、カバレッジ測定)を行い、AWS に CD (デプロイ 、デリバリー)を行う内容になっています。(少し環境が古めなので実際にやってみる場合は少し工夫が必要かもしれません。)
Udemy
GitHub Actionsで学ぶCI/CD入門―ビルド・デプロイの基本からAPI自動テスト・AWSへの自動デプロイまで
目次
サンプルアプリケーションを作成します
このセクションではVSCodeで、「myapp」というサンプルアプリケーションを作成します。今回はアプリがメインではないので、画面に「Hello! CI/CD」と表示する React アプリを作成して、CI/CD環境を作成していきます。今シリーズでは最終的に AWS の S3 と呼ばれる静的コンテンツを配信するサービスにデプロイするところまで目指します。
今回の記事で使用している環境は以下の様になっています。
- VSCode・・・Windows版 1.103.2
- Node.js・・・バージョン 24.7.0
- npm・・・バージョン 11.5.1
・Node.jsをインストールします
Reactをインストールするには、npmというパッケージマネージャー(Node.jsに含まれています)が必要なため、こちらのサイト様からNode.jsのインストーラーをダウンロードします。ダウンロードが完了したらすべてデフォルトの設定でNode.jsをインストールして下さい。(少し早いですが、v24シリーズはLTS(長期サポート版)になる様なので最新バージョンをインストールしました。)

・アプリのひな型を作成します
どこか任意のフォルダ内に「myapp」というフォルダを作成してVSCodeで開きます。Ctrl + @と入力して表示されたターミナル画面に以下のコマンドを入力して、Reactアプリのひな型を作成します。アプリの構成は React (TypeScript版) + Vitest になっています。
npm create vite@latest . -- --template react-ts
「npm i」と入力して、必要なパッケージをインストールします。環境によっては以下の様なエラーが出るかもしれません。
PS C:\MAMP\htdocs\ci_cd_projects\myapp> npm i
npm error code ERR_INVALID_ARG_TYPE
npm error The "file" argument must be of type string. Received undefined
npm error A complete log of this run can be found in: C:\Users\admin\AppData\Local\npm-cache\_logs\2025-09-07T08_10_17_935Z-debug-0.log
PS C:\MAMP\htdocs\ci_cd_projects\myapp>
上記のエラーが出る場合は、コンソール画面に以下のコマンドを入力するとエラーが解消すると思われます。このエラーは「COMSPEC」という環境変数にWindowsのコマンドプロンプトのパスが設定されていないのが原因で発生する様です。
$env:ComSpec = "$env:windir\System32\cmd.exe"
npm i
# OKであれば管理者権限で PowerShell を起動して以下のコマンドで永続化します。
setx COMSPEC "%SystemRoot%\System32\cmd.exe" /M
# 保険のためnpmの設定ファイルにも設定を追加します。
npm config set script-shell "C:\\Windows\\System32\\cmd.exe"
特に問題なければ、テストに必要な以下のパッケージを追加でインストールします。
npm i -D vitest
npm i -D @vitejs/plugin-react
npm i -D @testing-library/react
npm i -D @testing-library/jest-dom
npm i -D @types/jest
npm i -D @vitest/coverage-v8
npm i -D jsdom
プロジェクトフォルダ内の「package.json」ファイルを開いて「scripts」設定を以下の様に修正します。
"scripts": {
"dev": "vite",
"build": "tsc -b && vite build",
"lint": "eslint .",
"preview": "vite preview",
"test": "vitest",
"test:run": "vitest run",
"coverage": "vitest run --coverage"
},
・テストに必要な設定ファイルとテストファイルを作成します
プロジェクトフォルダ内に「vitest.config.ts」という設定ファイルを作成して以下の内容を書き込みます。
import { defineConfig } from 'vitest/config'
import react from '@vitejs/plugin-react'
export default defineConfig({
plugins: [react()],
test: {
environment: 'jsdom',
globals: true,
setupFiles: './src/setupTests.ts',
coverage: {
provider: 'v8',
reporter: ['text', 'html'],
reportsDirectory: './coverage',
},
},
})
「src\setupTests.ts」というファイルを作成して以下の内容を書き込みます。
import '@testing-library/jest-dom';
「src/App.test.tsx」というテストファイルを作成して以下のテストを書き込みます。
import { render, screen } from '@testing-library/react';
import App from './App';
test('renders hello message', () => {
render(<App />);
expect(screen.getByText(/hello/i)).toBeInTheDocument();
});
・テストを実行します
ここまで実装できたら、コンソール画面に「npm run test:run」と入力してテストを実行します。
PS C:\MAMP\htdocs\ci_cd_projects\myapp> npm run test:run
> myapp@0.0.0 test:run
> vitest run
RUN v3.2.4 C:/MAMP/htdocs/ci_cd_projects/myapp
❯ src/App.test.tsx (1 test | 1 failed) 38ms
× renders hello message 36ms
→ Unable to find an element with the text: /hello/i. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible.
<中略...>
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯ Failed Tests 1 ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
<中略...>
FAIL src/App.test.tsx > renders hello message
TestingLibraryElementError: Unable to find an element with the text: /hello/i. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible.
❯ Object.getElementError node_modules/@testing-library/dom/dist/config.js:37:19
❯ node_modules/@testing-library/dom/dist/query-helpers.js:76:38
❯ node_modules/@testing-library/dom/dist/query-helpers.js:52:17
❯ node_modules/@testing-library/dom/dist/query-helpers.js:95:19
❯ src/App.test.tsx:6:17
4| test('renders hello message', () => {
5| render(<App />);
6| expect(screen.getByText(/hello/i)).toBeInTheDocument();
| ^
7| });
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯
Test Files 1 failed (1)
Tests 1 failed (1)
Start at 18:56:56
Duration 1.22s (transform 53ms, setup 111ms, collect 132ms, tests 38ms, environment 537ms, prepare 123ms)
PS C:\MAMP\htdocs\ci_cd_projects\myapp>
テストが失敗するのを確認できましたので、今度はテストが成功する様にアプリを修正します。「src\App.tsx」というファイルを開いて以下の様に修正します。
import './App.css'
function App() {
return (<p>Hello! CI/CD</p>)
}
export default App
再度、コンソール画面に「npm run test:run」と入力してテストを実行します。今度はテストが成功しました。
PS C:\MAMP\htdocs\ci_cd_projects\myapp> npm run test:run
> myapp@0.0.0 test:run
> vitest run
RUN v3.2.4 C:/MAMP/htdocs/ci_cd_projects/myapp
✓ src/App.test.tsx (1 test) 25ms
✓ renders hello message 24ms
Test Files 1 passed (1)
Tests 1 passed (1)
Start at 19:10:14
Duration 1.18s (transform 46ms, setup 113ms, collect 119ms, tests 25ms, environment 536ms, prepare 118ms)
PS C:\MAMP\htdocs\ci_cd_projects\myapp>
・カバレッジを実行します
カバレッジとは、テストによってどの位のコード範囲がテストされたかを示す指標になっています。極めて重要なシステムでは90%以上のカバレッジを求められる場合もある様ですが、一般的には70~80%を越えていれば十分高いとされている様です。ただし、カバレッジが高いからと言ってバグが少ないとは言い切れません。テストコードの品質も重要です。
前置きが長くなりましたが、カバレッジを実行するにはターミナル画面に「npm run coverage」と入力します。
PS C:\MAMP\htdocs\ci_cd_projects\myapp> npm run coverage
> myapp@0.0.0 coverage
> vitest run --coverage
RUN v3.2.4 C:/MAMP/htdocs/ci_cd_projects/myapp
Coverage enabled with v8
✓ src/App.test.tsx (1 test) 25ms
✓ renders hello message 24ms
Test Files 1 passed (1)
Tests 1 passed (1)
Start at 08:35:39
Duration 1.94s (transform 92ms, setup 177ms, collect 184ms, tests 25ms, environment 941ms, prepare 169ms)
% Coverage report from v8
----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
----------|---------|----------|---------|---------|-------------------
All files | 35.71 | 50 | 50 | 35.71 |
App.tsx | 100 | 100 | 100 | 100 |
main.tsx | 0 | 0 | 0 | 0 | 1-10
----------|---------|----------|---------|---------|-------------------
PS C:\MAMP\htdocs\ci_cd_projects\myapp>
カバレッジを実行するとプロジェクトフォルダ内に「coverage」というフォルダが作成されます。このフォルダ内の「index.html」を開くと実行結果をブラウザで確認できます。

上記の結果で「main.tsx」ファイルはアプリのエントリーポイントですが、ほぼ修正することはないと思われますので、「vitest.config.ts」ファイルを以下の様に修正してテストから除外しておきます。その他のテストが不要と思われる設定ファイル等も除外しておきます。
import { defineConfig } from 'vitest/config'
import react from '@vitejs/plugin-react'
export default defineConfig({
plugins: [react()],
test: {
environment: 'jsdom',
globals: true,
setupFiles: './src/setupTests.ts',
coverage: {
provider: 'v8',
reporter: ['text', 'html'],
exclude: [ // 以下のファイルをテストから除外します
'src/main.tsx', // エントリーポイント
'**/*.config.{ts,js}', // 設定ファイル全般
'**/*.d.ts', // 型定義全般 (必要に応じて)
'**/*.stories.tsx', // モックやストーリーファイル
'dist/**', // ビルド生成物 (アーティファクト)
],
},
},
})
以上でサンプルアプリの作成は終了です。以降からは GitHub Actions の設定を行っていきます。
GitHub Actionsを設定/実行します (クラウド版)
まずこちらのサイト様等を参考にして、GitHubにアカウントを作成しておきます。(多少の制限はありますが、作成も維持費も無料です。)
プロジェクトファイル内に「.github/workflows/ci.yml」というファイルを作成して以下の内容を書き込みます。設定内容を詳しく知りたい方は、お手数ですがこちらの公式ドキュメントをご参照ください。また、こちらのサイト様では実際の使い方を詳しくご説明されています。
name: CI
on:
push:
branches:
- main
jobs:
test-and-build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 24
cache: 'npm'
- run: npm ci
- run: npm run lint
- run: npm run test:run
- run: npm run coverage
- run: npm run build
# HTML レポートを成果物として保存(Artifacts)
- uses: actions/upload-artifact@v4
if: always()
with:
name: coverage-html
path: coverage
追加や修正したファイルをコミットしたら、ソース管理画面の「Brachch の発行」ボタンを押します。

保存するリポジトリのタイプを聞かれますので、公開する予定がない場合はプライベートリポジトリを選択します。初めてリポジトリをプッシュした場合はログイン処理を求められますので、こちらの記事を参考にしてログイン処理を行ってください。

GitHubにログインして、「myapp」というリポジトリ画面内にある「Acitons」というタブを選択します。

表示されたワークフローをクリックします。

スクリプト設定名をクリックします。

スクリプトの実行結果が表示されます。特に問題がない場合は緑色のチェックマークが表示されます。

スクリプト選択画面に戻ると、HTML形式のカバレッジ実行結果がダウンロードできます。このセクションの設定では保存しませんでしたが、ビルド成果物 (アーティファクト) も作成して保存する様にしておけば CD (デプロイ、デリバリー) のコピー元ファイルとして使用できます。

以上で、クラウド版のGitHub Actions の CI 設定は終了です。次はこの仕組みをローカル環境で実行できる様に設定します。
GitHub Actionsを設定/実行します (ローカル版:nektos/act)
このセクションでは「nektos/act」と呼ばれる CLI ツールを使用してローカル環境で GitHub Actions を実行できる様に設定します。通常 GitHub Actions のワークフロー(CI/CD ジョブ)は GitHub のクラウド上で動作しますが、nektos/act を使うと同じワークフローを自分の PC 上の Docker コンテナ内で再現できます。
このツールは以下のような特徴があります。
- ローカルで GitHub Actions を実行
.github/workflows/ にある YAML ファイルを読み込み、GitHub Actions と同じようにジョブを動かせます。 - 高速なデバッグ
GitHub に push して待つ必要がなく、すぐにワークフローの挙動を確認できます。 - Docker コンテナを利用
各ジョブは Docker イメージを用いて実行されるため、環境の再現性が高いです。
--container-architecture オプションなどで環境を調整可能です。 - イベントのシミュレーション
push, pull_request など、特定のイベントをトリガーにした実行をローカルで試せます。
まずは、PowerShell または VSCode のターミナル画面に以下の様に入力してスクリプトの実行ポリシーを変更します。確認メッセージが表示されたら「y」を入力します。
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
次に「scoop」というコマンドインストールするために、以下のコマンドを実行します。
iwr -useb get.scoop.sh | iex
最後に以下のコマンドを実行して「act」と呼ばれる CLI ツールをインストールします。
scoop install act
実際に動作させるためには Docker が必要なため、こちらのサイト様から「Docker Desktop」をダウンロードします。

ダウンロードが完了したら、すべてデフォルト状態でインストールして起動します。インストール時と初回の起動時にメンバー登録を求められますが、スキップしても正常に起動する様です。

後はプロジェクトルートでターミナル画面を開いて、「act」と入力すると GitHub Actions のワークフローがローカルの Docker コンテナ上で実行されます。

act がエラーで起動できない場合は、エクスプローラーを起動して上部のパス表示欄に「%USERPROFILE%\.docker」と入力して、表示された画面内にある「config.json」ファイルを開いて以下の様に修正すると起動すると思われます。
# この様になっていた場合は
{
"auths": {},
"credsStore": "desktop",
"currentContext": "desktop-linux"
}
↓
# 以下の様に修正します
{
"auths": {}
}
制限事項として、act で作成したビルド成果物(アーティファクト)を GitHub Actions に登録することはできない様です。(ローカルの Docker コンテナでサーバーを立てて、ローカル環境に保存することは可能な様です。) GitHub Actions にアーティファクトを登録したい場合は、この後でご説明する「Self-hosted Runner」という仕組みを使用すれば可能な様です。
GitHub Actionsを設定/実行します (ローカル版:Self-hosted Runner)
このセクションでは「Self-hosted Runner」と呼ばれる仕組みを利用して、 GitHub Actions のワークフローをローカル(自分のPC)または外部のサーバーで実行できる様に設定します。自前の装置を使用するので、 プライベートリポジトリでも時間的な利用制限はありません。(アーティファクト保存などのストレージの利用制限はあります。)
このツールは以下のような利点があります。
- GitHub のテストランナーで用意されていないソフトウェアを利用できる
- 高性能 GPU など特別なハードウェアを利用できる
- 秘密情報やセキュリティ要件に対応
社内ネットワークに閉じた環境でビルド/デプロイができる。 - リソース制限なし
GitHub テストランナーでは時間・同時実行数に制約があるが、自前のサーバーなら制御可能。
Self-hosted Runner は Windows のネイティブ環境でも WSL2 でも利用可能です。まずは直接 Windows 上で実行する様に設定します。
・Windows 上で Self-hosted Runner を起動する方法
最初に GitHub にログインして、リポジトリを選択します。その後「Settings 」→「Actions 」→「Runners 」→「New self-hosted runner」を選択します。

表示された画面で「Windows」を選択します。後は表示されている手順に従って設定して行きます。

PowerShell を開いて、Cドライブ直下辺りに「actions-runner」というフォルダを作成して移動します。その後ホームページの指示に従い以下のコマンドを実行してアプリをダウンロードして展開します。(以下のコマンドはサンプルです。ページに表示されているコマンドをコピーして実行してください。)
# ダウンロード
Invoke-WebRequest -Uri https://github.com/actions/runner/releases/download/v2.328.0/actions-runner-win-x64-2.328.0.zip -OutFile actions-runner-win-x64-2.328.0.zip
if((Get-FileHash -Path actions-runner-win-x64-2.328.0.zip -Algorithm SHA256).Hash.ToUpper() -ne '<ハッシュ値>'.ToUpper()){ throw 'Computed checksum did not match' }
Add-Type -AssemblyName System.IO.Compression.FileSystem ; [System.IO.Compression.ZipFile]::ExtractToDirectory("$PWD/actions-runner-win-x64-2.328.0.zip", "$PWD")
「Configure」セクションのコマンドをコピーして実行します。
./config.cmd --url https://github.com/mimura-soft/myapp --token <トークン>
「config.cmd」を実行すると色々聞かれますが、デフォルトのままリターンキーを押します。
PS C:\MAMP\htdocs\ci_cd_projects\myapp\actions-runner> ./config.cmd --url https://github.com/mimura-soft/myapp --token <トークン>
--------------------------------------------------------------------------------
| ____ _ _ _ _ _ _ _ _ |
| / ___(_) |_| | | |_ _| |__ / \ ___| |_(_) ___ _ __ ___ |
| | | _| | __| |_| | | | | '_ \ / _ \ / __| __| |/ _ \| '_ \/ __| |
| | |_| | | |_| _ | |_| | |_) | / ___ \ (__| |_| | (_) | | | \__ \ |
| \____|_|\__|_| |_|\__,_|_.__/ /_/ \_\___|\__|_|\___/|_| |_|___/ |
| |
| Self-hosted runner registration |
| |
--------------------------------------------------------------------------------
# Authentication
√ Connected to GitHub
# Runner Registration
Enter the name of the runner group to add this runner to: [press Enter for Default]
Enter the name of runner: [press Enter for DESKTOP-CQEA49P]
# Runner settings
Enter name of work folder: [press Enter for _work]
√ Settings Saved.
Would you like to run the runner as service? (Y/N) [press Enter for N]
「./run.cmd」と入力すると Self-hosted Runner が起動します。
PS C:\actions-runner> ./run.cmd
1 個のファイルをコピーしました。
√ Connected to GitHub
Current runner version: '2.328.0'
2025-09-10 07:03:34Z: Listening for Jobs
「.github\workflows\ci.yml」ファイルを Self-hosted Runner で実行されるように修正します。(11行目) Windows ネイティブで実行するとキャッシュの作成が遅い様なので、17行目をコメントアウトしておきます。
name: CI
on:
push:
branches:
- main
jobs:
test-and-build:
# runs-on: ubuntu-latest
runs-on: [self-hosted, Windows, X64]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 24
# cache: 'npm'
- run: npm ci
- run: npm run lint
- run: npm run test:run
- run: npm run coverage
- run: npm run build
# HTML レポートを成果物として保存(Artifacts)
- uses: actions/upload-artifact@v4
if: always()
with:
name: coverage-html
path: coverage
以上で設定は終了です。後は通常通りに GitHub にプッシュするとワークフローがローカル環境で実行されます。「Actions」→「Runners」→「Self-hosted runners」と選択すると現在有効なテストランナーが確認できます。

・WSL2 上で Self-hosted Runner を起動する方法
「New runner」を選択します。

表示されたページで先ほどと同じように「New self-hosted runner」を選択します。

表示された画面で「Linux」を選択します。後は表示されている手順に従って設定して行きます。

WSL2のコンソール画面でホームディレクトに移動して「actions-runner」というフォルダを作成して移動します。その後ホームページの指示に従い以下のコマンドを実行してアプリをダウンロードして展開します。(以下のコマンドはサンプルです。ページに表示されているコマンドをコピーして実行してください。)
curl -o actions-runner-linux-x64-2.328.0.tar.gz -L https://github.com/actions/runner/releases/download/v2.328.0/actions-runner-linux-x64-2.328.0.tar.gz
echo "<ハッシュ値> actions-runner-linux-x64-2.328.0.tar.gz" | shasum -a 256 -c
tar xzf ./actions-runner-linux-x64-2.328.0.tar.gz
「Configure」セクションのコマンドをコピーして実行します。
./config.sh --url https://github.com/mimura-soft/myapp --token <トークン>
「config.sh」を実行すると色々聞かれますが、ほぼデフォルトでリターンキーを押します。30行目のランナー名は変えておいた方がいいかもしれません。
user01@DESKTOP-CQEA49P:~/actions-runner$ ./config.sh --url https://github.com/mimura-soft/myapp --token <トークン>
--------------------------------------------------------------------------------
| ____ _ _ _ _ _ _ _ _ |
| / ___(_) |_| | | |_ _| |__ / \ ___| |_(_) ___ _ __ ___ |
| | | _| | __| |_| | | | | '_ \ / _ \ / __| __| |/ _ \| '_ \/ __| |
| | |_| | | |_| _ | |_| | |_) | / ___ \ (__| |_| | (_) | | | \__ \ |
| \____|_|\__|_| |_|\__,_|_.__/ /_/ \_\___|\__|_|\___/|_| |_|___/ |
| |
| Self-hosted runner registration |
| |
--------------------------------------------------------------------------------
# Authentication
√ Connected to GitHub
# Runner Registration
Enter the name of the runner group to add this runner to: [press Enter for Default]
Enter the name of runner: [press Enter for DESKTOP-CQEA49P]
This runner will have the following labels: 'self-hosted', 'Linux', 'X64'
Enter any additional labels (ex. label-1,label-2): [press Enter to skip]
A runner exists with the same name
Would you like to replace the existing runner? (Y/N) [press Enter for N]
Enter the name of runner: [press Enter for DESKTOP-CQEA49P] wsl2-runner-01
This runner will have the following labels: 'self-hosted', 'Linux', 'X64'
Enter any additional labels (ex. label-1,label-2): [press Enter to skip]
√ Runner successfully added
√ Runner connection is good
# Runner settings
Enter name of work folder: [press Enter for _work]
√ Settings Saved.
user01@DESKTOP-CQEA49P:~/actions-runner$
「./run.sh」と入力すると Self-hosted Runner が起動します。
user01@DESKTOP-CQEA49P:~/actions-runner$ ./run.sh
√ Connected to GitHub
Current runner version: '2.328.0'
2025-09-10 07:59:22Z: Listening for Jobs
「.github\workflows\ci.yml」ファイルを WSL2 の Self-hosted Runner で実行されるように修正します。(12行目)
name: CI
on:
push:
branches:
- main
jobs:
test-and-build:
# runs-on: ubuntu-latest
# runs-on: [self-hosted, Windows, X64]
runs-on: [self-hosted, Linux, X64]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 24
# cache: 'npm'
- run: npm ci
- run: npm run lint
- run: npm run test:run
- run: npm run coverage
- run: npm run build
# HTML レポートを成果物として保存(Artifacts)
- uses: actions/upload-artifact@v4
if: always()
with:
name: coverage-html
path: coverage
以上で設定は終了です。後は通常通りに GitHub にプッシュするとワークフローがローカル環境で実行されます。「Actions」→「Runners」→「Self-hosted runners」と選択して画面を確認すると、WSL2 のテストランナーも正常に追加されたようです。

記事が長くなりましたので、今回はここまでとします。次回は Azure Pipelinesで CI を実装していきます。
以上です。よろしかったお試しください。