diff --git a/.github/actions/setup-playwright/action.yaml b/.github/actions/setup-playwright/action.yaml index ab150ba..02a69fd 100644 --- a/.github/actions/setup-playwright/action.yaml +++ b/.github/actions/setup-playwright/action.yaml @@ -1,15 +1,25 @@ -# Chapter 5 メンテナンス性を考慮したワークフロー (Custom actions). +# Chapter 5 ワークフローをDRYにする (Custom actions). --- -name: "Setup Playwright" -description: "Setup Playwright with deps and cache" +name: 'Setup Playwright' +description: 'Setup Playwright with deps and cache' inputs: working-directory: - description: "Working directory" + description: 'Working directory' required: false default: ${{ github.workspace }} +# Custom action は再利用可能なステップです。 +# Custom action の種類の一つとして 同じ yaml で記載する Composite action があります。 +# Composite action は複数のステップをまとめて再利用可能にすることができます。 +# たとえば次のケースが考えられます。 +# - 公開されている setup-* がないツールのインストール +# - 認証 +# - キャッシュの設定 +# - 成果物やテストデータのアップロード +# - 完了通知 + runs: - using: "composite" + using: 'composite' steps: - name: Get Playwright version shell: bash diff --git a/.github/workflows/articles-changed-detection.yaml b/.github/workflows/articles-changed-detection.yaml index a430f84..0eb5392 100644 --- a/.github/workflows/articles-changed-detection.yaml +++ b/.github/workflows/articles-changed-detection.yaml @@ -1,4 +1,4 @@ -# articles-changed-detection.yaml - 変更を自動検知しプロジェクトごとに並列実行するテスト +# 変更を自動検知しプロジェクトごとに並列実行するテスト --- name: Articles - Changed detection sample diff --git a/.github/workflows/articles-docker-multi-platform.yaml b/.github/workflows/articles-docker-multi-platform.yaml new file mode 100644 index 0000000..be6b3ff --- /dev/null +++ b/.github/workflows/articles-docker-multi-platform.yaml @@ -0,0 +1,144 @@ +# マルチプラットフォームのDockerイメージをビルドしてGitHub Container Registryにプッシュするワークフロー +--- +name: Articles - Build and push multi-platform image + +on: + pull_request: + paths: + - 'chapters/go/hello-api/**' + - '.github/workflows/articles-docker-multi-platform.yaml' + workflow_dispatch: + +permissions: {} +defaults: + run: + shell: bash + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +env: + IMAGE_NAME: ghcr.io/${{ github.repository }} + +jobs: + build: + name: Build ${{ matrix.platform }} + strategy: + fail-fast: false + matrix: + include: + - platform: linux/amd64 + runner: ubuntu-latest + - platform: linux/arm64 + runner: ubuntu-24.04-arm # arm64 runner + runs-on: ${{ matrix.runner }} + timeout-minutes: 5 + permissions: + contents: read + packages: write + + steps: + - uses: actions/checkout@v7 + + - name: Prepare + run: | + platform=${{ matrix.platform }} + echo "PLATFORM_PAIR=${platform//\//-}" >> "$GITHUB_ENV" + + # https://github.com/marketplace/actions/build-and-push-docker-images + - name: Login to Docker Hub + uses: docker/login-action@v4 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Docker meta + id: meta + uses: docker/metadata-action@v6 + with: + images: ${{ env.IMAGE_NAME }} + + # QEMUは遅いので昨今は、arm64のRunnerを使うのが主流になってきている。 + # - name: Set up QEMU + # uses: docker/setup-qemu-action@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v4 + + # GitHub Packages (GHCR) に latest タグで複数回プッシュすると + # 後から走ったジョブが前のイメージのメタデータを破壊・上書きするのを防ぐ + - name: Build and push by digest + id: build + uses: docker/build-push-action@v7 + with: + context: './chapters/go/hello-api/' + platforms: ${{ matrix.platform }} + labels: ${{ steps.meta.outputs.labels }} + outputs: type=image,name=${{ env.IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=true + provenance: false # 証明書マニフェストを作らない + sbom: false # 証明書マニフェストを作らない + + - name: Export digest + run: | + mkdir -p /tmp/digests + digest="${{ steps.build.outputs.digest }}" + touch "/tmp/digests/${digest#sha256:}" + + - name: Upload digest + uses: actions/upload-artifact@v7 + with: + name: digests-${{ env.PLATFORM_PAIR }} + path: '/tmp/digests/*' + if-no-files-found: error + retention-days: 1 + + merge: + name: Merge and push manifest list + runs-on: ubuntu-latest + needs: build + timeout-minutes: 5 + permissions: + contents: read + packages: write + steps: + - name: Download digests + uses: actions/download-artifact@v7 + with: + path: '/tmp/digests' + pattern: digests-* + merge-multiple: true + + - name: Login to GHCR + uses: docker/login-action@v4 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Docker meta + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.IMAGE_NAME }} + + - name: Create manifest list and push + working-directory: /tmp/digests + run: | + # 1. 最初に空の配列を定義 + IMAGES=() + + # 2. ループを回して配列に1つずつ安全に格納 + for file in *; do + IMAGES+=("ghcr.io/suzu-devworks/examples-github-action@sha256:$file") + done + + docker buildx imagetools create --tag "${{ env.IMAGE_NAME }}:latest" "${IMAGES[@]}" + + - name: Inspect image + run: | + docker buildx imagetools inspect ${{ env.IMAGE_NAME }}:latest diff --git a/.github/workflows/chapter-2-2-cd.yaml b/.github/workflows/chapter-2-2-cd.yaml index fea5009..2ea7a35 100644 --- a/.github/workflows/chapter-2-2-cd.yaml +++ b/.github/workflows/chapter-2-2-cd.yaml @@ -25,6 +25,7 @@ jobs: cd: name: cd runs-on: ubuntu-latest + timeout-minutes: 5 # GitHub Container Registry にイメージを push するための権限を付与する permissions: contents: read diff --git a/.github/workflows/chapter-2-3-cd-action.yaml b/.github/workflows/chapter-2-3-cd-action.yaml deleted file mode 100644 index 7f030cf..0000000 --- a/.github/workflows/chapter-2-3-cd-action.yaml +++ /dev/null @@ -1,56 +0,0 @@ -# Chapter 2 マージ駆動でCDを実現する(Docker公式のactionを使用する方法). ---- -name: Chapter 2 (3) - CD with Docker action - -on: - push: - branches: - - main - paths: - - 'chapters/go/hello-api/**' - - '.github/workflows/chapter-2-3-cd-action.yaml' - workflow_dispatch: - -permissions: {} -defaults: - run: - shell: bash - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - cd: - name: cd - runs-on: ubuntu-latest - permissions: - contents: read - packages: write - defaults: - run: - working-directory: './chapters/go/hello-api/' - - steps: - - uses: actions/checkout@v7 - - # https://github.com/marketplace/actions/build-and-push-docker-images - - name: Login to Docker Hub - uses: docker/login-action@v4 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Set up QEMU - uses: docker/setup-qemu-action@v4 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v4 - - - name: Build and push - uses: docker/build-push-action@v7 - with: - platforms: linux/amd64,linux/arm64 - push: true - tags: ghcr.io/${{ github.repository }}:latest diff --git a/.github/workflows/chapter-3-1-context.yaml b/.github/workflows/chapter-3-1-contexts.yaml similarity index 79% rename from .github/workflows/chapter-3-1-context.yaml rename to .github/workflows/chapter-3-1-contexts.yaml index fecfa78..a5e367d 100644 --- a/.github/workflows/chapter-3-1-context.yaml +++ b/.github/workflows/chapter-3-1-contexts.yaml @@ -1,11 +1,11 @@ # Chapter 3 ワークフロー内で利用可能な値(コンテキスト). --- -name: Chapter 3 (1) - Context +name: Chapter 3 (1) - Contexts on: pull_request: paths: - - '.github/workflows/chapter-3-1-context.yaml' + - '.github/workflows/chapter-3-1-contexts.yaml' workflow_dispatch: permissions: {} @@ -52,7 +52,8 @@ jobs: # runner コンテキストには主に、GitHub Actions の実行環境に関する情報が格納されています env: RUNNER_CONTEXT: ${{ toJson(runner) }} - run: echo "$RUNNER_CONTEXT" + run: | + echo "runner: $RUNNER_CONTEXT" - uses: actions/checkout@v7 # steps コンテキストを利用するには、id を指定する必要があります @@ -62,19 +63,25 @@ jobs: # steps コンテキストには、同じジョブ内で実行されたステップの情報が格納されています run: | # actions/checkout のステータスを表示 - echo "${{ steps.checkout.conclusion }}" + echo "steps.checkout.conclusion: ${{ steps.checkout.conclusion }}" - name: job コンテキストの表示 # job コンテキストには、同じジョブ内で実行されたステップの情報が格納されています + env: + JOB_CONTEXT: ${{ toJson(job) }} run: | - echo "${{ job.status }}" - echo "${{ toJson(job) }}" + echo "job.status: ${{ job.status }}" + echo "job: $JOB_CONTEXT" - name: その他のコンテキストの表示 # - see: https://docs.github.com/ja/actions/writing-workflows/choosing-what-your-workflow-does/accessing-contextual-information-about-workflow-runs + env: + MATRIX_CONTEXT: ${{ toJson(matrix) }} + NEEDS_CONTEXT: ${{ toJson(needs) }} + ENV_CONTEXT: ${{ toJson(env) }} + INPUTS_CONTEXT: ${{ toJson(inputs) }} run: | - echo "${{ toJson(matrix) }}" - echo "${{ toJson(needs) }}" - echo "${{ toJson(runner.os) }}" - echo "${{ toJson(env) }}" - echo "${{ toJson(inputs) }}" + echo "matrix: $MATRIX_CONTEXT" + echo "needs: $NEEDS_CONTEXT" + echo "env: $ENV_CONTEXT" + echo "inputs: $INPUTS_CONTEXT" diff --git a/.github/workflows/chapter-3-2-artifacts.yaml b/.github/workflows/chapter-3-2-artifacts.yaml index 05693c8..49d2211 100644 --- a/.github/workflows/chapter-3-2-artifacts.yaml +++ b/.github/workflows/chapter-3-2-artifacts.yaml @@ -1,6 +1,6 @@ # Chapter 3 ジョブの成果物の保存、次のジョブへの受け渡し. --- -name: Chapter 3 (2) - Artiafacts +name: Chapter 3 (2) - Saving and restoring artifacts on: pull_request: diff --git a/.github/workflows/chapter-3-4-cache.yaml b/.github/workflows/chapter-3-4-caching.yaml similarity index 89% rename from .github/workflows/chapter-3-4-cache.yaml rename to .github/workflows/chapter-3-4-caching.yaml index fc807c9..8903ca1 100644 --- a/.github/workflows/chapter-3-4-cache.yaml +++ b/.github/workflows/chapter-3-4-caching.yaml @@ -1,11 +1,11 @@ # Chapter 3 キャッシュ活用によるCIの高速化. --- -name: Chapter 3 (4) - Cache +name: Chapter 3 (4) - Accelerating CI using caching on: pull_request: paths: - - '.github/workflows/chapter-3-4-cache.yaml' + - '.github/workflows/chapter-3-4-caching.yaml' workflow_dispatch: permissions: {} @@ -43,7 +43,7 @@ jobs: - uses: actions/checkout@v7 # https://github.com/actions/setup-go#caching-dependency-files-and-build-outputs # const primaryKey = `setup-go-${platform}-${arch}-${linuxVersion}go-${versionSpec}-${fileHash}`; - # fileHash のデフォルトは `go.mod` のハッシュ値だそうで + # fileHash のデフォルトは `go.mod` のハッシュ値だそうで # `cache-dependency-path`を指定すると `go.sum` のハッシュ値を利用することができます。 - uses: actions/setup-go@v7 with: @@ -76,11 +76,11 @@ jobs: ~/go/pkg/mod # キーを指定することで、キャッシュ範囲を制御できます。 key: | - ${{ runner.os }}-go-cache-${{ hashFiles('**/go.sum') }}-${{ github.run_id }} + ${{ runner.os }}-${{ runner.arch }}-go-cache-${{ hashFiles('**/go.sum') }}-${{ github.run_id }} # キーに `github.run_id` 含めたため実行単位が変わるとキャッシュがヒットしなくなるため # restore-keys を指定して、キャッシュのヒット率を上げます。 restore-keys: | - ${{ runner.os }}-go-cache-${{ hashFiles('**/go.sum') }}- + ${{ runner.os }}-${{ runner.arch }}-go-cache-${{ hashFiles('**/go.sum') }}- # 依存関係のキャッシュがヒットした場合、go mod download はスキップされます。 - run: go mod download # キャッシュのセーブは、actions/cache のキャッシュキーが変化した場合にのみ行われます。 @@ -185,16 +185,17 @@ jobs: run: working-directory: './chapters/dotnet/HelloWorld/' env: - NUGET_PACKAGES: ${{ github.workspace }}/.nuget/packages + NUGET_PACKAGES: '${{ github.workspace }}/.nuget/packages' steps: - uses: actions/checkout@v7 - uses: actions/cache@v6 with: - path: ~/.nuget/packages + path: ${{ env.NUGET_PACKAGES }} + # キーを指定することで、キャッシュ範囲を制御できます。 key: | - ${{ runner.os }}-nuget-cache-${{ hashFiles('**/packages.lock.json') }}-${{ github.run_id }} + ${{ runner.os }}-${{ runner.arch }}-nuget-cache-${{ hashFiles('**/packages.lock.json') }}-${{ github.run_id }} restore-keys: | - ${{ runner.os }}-nuget-cache- + ${{ runner.os }}-${{ runner.arch }}-nuget-cache- - uses: actions/setup-dotnet@v6 with: dotnet-version: '10.x' @@ -203,7 +204,8 @@ jobs: build-join: runs-on: ubuntu-latest - needs: [build-go-cache, build-node-yarn, build-node-pnpm, build-dotnet-cache] + needs: + [build-go-cache, build-node-yarn, build-node-pnpm, build-dotnet-cache] permissions: contents: read steps: diff --git a/.github/workflows/chapter-3-7-secrets.yaml b/.github/workflows/chapter-3-7-secrets.yaml index f55a7d2..0db6301 100644 --- a/.github/workflows/chapter-3-7-secrets.yaml +++ b/.github/workflows/chapter-3-7-secrets.yaml @@ -20,23 +20,21 @@ concurrency: # GitHub Actions では、リポジトリのシークレットやワークフロー内で定義された変数を扱うことができます。 jobs: - use_github_token: + display: runs-on: ubuntu-latest permissions: contents: read steps: - uses: actions/checkout@v7 + + # vars と secrets の違いはワークフローのログで '*' でマスクされるかどうかです。 - name: Show variables. env: + # インジェクション対策として、変数の値を直接 echo するのではなく、 + # 環境変数に格納してから echo するようにしています。 VARIABLES_VALUE: ${{ vars.USER_VALUE }} SECRETS_VALUE: ${{ secrets.USER_VALUE }} run: | echo "$VARIABLES_VALUE" echo "$SECRETS_VALUE" - - - name: vars, secrets コンテキストの表示 - # vars コンテキストには、ワークフロー内で定義された変数の情報が格納されています - # secrets コンテキストには、リポジトリで設定したシークレットの情報が格納されていますが、 - run: | - echo "${{ toJson(vars) }}" diff --git a/.github/workflows/chapter-4-1-containers.yaml b/.github/workflows/chapter-4-1-containers.yaml index 2a47cd6..bc49ea8 100644 --- a/.github/workflows/chapter-4-1-containers.yaml +++ b/.github/workflows/chapter-4-1-containers.yaml @@ -1,22 +1,33 @@ # Chapter 4 ジョブによるコンテナの利用. --- -name: Chapter 4 (1) - Containers +name: Chapter 4 (1) - Use Containers on: pull_request: paths: - - ".github/workflows/containers.yaml" + - '.github/workflows/chapter-4-1-containers.yaml' workflow_dispatch: permissions: {} +defaults: + run: + shell: bash + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +# アプリケーションをコンテナで開発していたり、ミドルウェアをコンテナで立ち上げたりしている場合 +# ジョブにおいてもコンテナを利用することができます。 jobs: container-test-job: runs-on: ubuntu-latest permissions: contents: read - container: - image: golang:1.23.2 + # ジョブコンテナを指定することで、ジョブ全体をコンテナ内で実行することができる. + container: + image: golang:1.26 steps: - run: go version @@ -24,6 +35,8 @@ jobs: runs-on: ubuntu-latest permissions: contents: read + # サービスコンテナを指定することで、ジョブ内でサービスコンテナを利用することができる. + # サービスコンテナはジョブの開始時に起動され、ジョブの終了時に停止されます。 services: postgres: image: postgres diff --git a/.github/workflows/chapter-4-2-matrix.yaml b/.github/workflows/chapter-4-2-matrix.yaml index 9c104d3..b9250bb 100644 --- a/.github/workflows/chapter-4-2-matrix.yaml +++ b/.github/workflows/chapter-4-2-matrix.yaml @@ -5,10 +5,20 @@ name: Chapter 4 (2) - Matrix strategy on: pull_request: paths: - - '.github/workflows/matrix.yaml' + - '.github/workflows/chapter-4-2-matrix.yaml' workflow_dispatch: permissions: {} +defaults: + run: + shell: bash + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +# Matrix strategy を利用することで、複数のジョブを並列に実行することができます。 +# アプリケーションのビルドを複数の OS や Go のバージョンで実行する場合などに有効です。 jobs: build: @@ -18,6 +28,7 @@ jobs: contents: read timeout-minutes: 5 strategy: + # 次の場合、go-version と os の組み合わせで 6 つのジョブが並列に実行されます。 matrix: go-version: ['1.25', '1.26'] os: [ubuntu-latest, windows-latest, macos-latest] @@ -25,8 +36,7 @@ jobs: run: working-directory: './chapters/go/hello-api/' steps: - - name: Checkout - uses: actions/checkout@v7 + - uses: actions/checkout@v7 - name: Ser up Go ${{ matrix.go-version }} uses: actions/setup-go@v7 with: diff --git a/.github/workflows/chapter-4-2-matrix1-dividing.yaml b/.github/workflows/chapter-4-2-matrix1-dividing.yaml deleted file mode 100644 index a646983..0000000 --- a/.github/workflows/chapter-4-2-matrix1-dividing.yaml +++ /dev/null @@ -1,24 +0,0 @@ -# Chapter 4 ユースケース 1. テストの分割. ---- -name: Chapter 4 - Matrix strategy use case 1 - -on: - pull_request: - paths: - - ".github/workflows/matrix-use-case1.yaml" - workflow_dispatch: - -permissions: {} - -jobs: - test: - name: Example of splitting tests and running them in parallel - runs-on: ubuntu-latest - permissions: - contents: read - strategy: - matrix: - shared: [1/3, 2/3, 3/3] - steps: - - name: Run test - run: echo "npx jest --shred ${{ matrix.shared }}" diff --git a/.github/workflows/chapter-4-2-matrix1-splitting.yaml b/.github/workflows/chapter-4-2-matrix1-splitting.yaml new file mode 100644 index 0000000..4a97c07 --- /dev/null +++ b/.github/workflows/chapter-4-2-matrix1-splitting.yaml @@ -0,0 +1,35 @@ +# Chapter 4 ユースケース 1. テストの分割. +--- +name: Chapter 4 (2) - Use Case 1. Test Splitting + +on: + pull_request: + paths: + - '.github/workflows/chapter-4-2-matrix1-splitting.yaml' + workflow_dispatch: + +permissions: {} +defaults: + run: + shell: bash + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +# テストフレームワークによっては、テストを複数のジョブに分割して並行に実行することで、テストの実行時間を短縮することができます。 + +jobs: + test: + name: Example of splitting tests and running them in parallel + runs-on: ubuntu-latest + permissions: + contents: read + strategy: + matrix: + shared: [1/3, 2/3, 3/3] + steps: + - uses: actions/checkout@v7 + # jest では、--shard オプションを利用することで、テストを分割して実行することができます。 + - name: Run test + run: echo "npx jest --shred ${{ matrix.shared }}" diff --git a/.github/workflows/chapter-4-2-matrix2-dynamic.yaml b/.github/workflows/chapter-4-2-matrix2-dynamic.yaml index 53fc047..fd353d0 100644 --- a/.github/workflows/chapter-4-2-matrix2-dynamic.yaml +++ b/.github/workflows/chapter-4-2-matrix2-dynamic.yaml @@ -1,14 +1,24 @@ # Chapter 4 ユースケース 2. 動的にジョブを構築する. --- -name: Chapter 4 - Matrix strategy use case 2 +name: Chapter 4 (2) - Use Case 2. Dynamically construct jobs on: pull_request: paths: - - ".github/workflows/matrix-use-case2.yaml" + - '.github/workflows/chapter-4-2-matrix2-dynamic.yaml' workflow_dispatch: permissions: {} +defaults: + run: + shell: bash + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +# Matrix strategy はJSONを入力として受け取ることができます。 +# たとえば、ジョブ1でJSONを生成し、ジョブ2でそのJSONを利用してMatrix strategyを構築することができます。 jobs: job1: diff --git a/.github/workflows/chapter-4-3-cache-handling.yaml b/.github/workflows/chapter-4-3-cache-handling.yaml new file mode 100644 index 0000000..9662e0f --- /dev/null +++ b/.github/workflows/chapter-4-3-cache-handling.yaml @@ -0,0 +1,59 @@ +# Chapter 4 キャッシュの取り扱い、save, restore を用いてキャッシュのタイミングを制御する. +--- +name: Chapter 4 (3) - Cache Handling (save and restore) + +on: + pull_request: + paths: + - '.github/workflows/chapter-4-3-cache-handling.yaml' + workflow_dispatch: + +permissions: {} +defaults: + run: + shell: bash + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +# 1つのリポジトリでキャッシュの最大容量は 10GB です。この制限を超えると、GitHubは新しいキャッシュを保存しますが、 +# 合計保存容量がリポジトリの制限を下回るまでキャッシュの削除をします。このときどのキャッシュが削除されるかは、 +# GitHubの内部アルゴリズムに依存するため、ユーザー側で制御することはできません。 + +# actions/cache/save と actions/cache/restore を利用することで、キャッシュの保存と復元のタイミングを細かく制御することができます。 + +jobs: + build-start: + runs-on: ubuntu-latest + permissions: + contents: read + timeout-minutes: 5 + steps: + - uses: actions/checkout@v7 + - uses: actions/cache/restore@v6 + with: + path: | + ./path-to-cahce + key: ${{ runner.os }}-${{ runner.arch }}-${{ github.sha }} + restore-keys: | + ${{ runner.os }}-${{ runner.arch }}- + + - run: echo "Do something" + + - name: dummy + run: | + echo "current is: $(date)" + echo "cache value is: $(cat ./path-to-cahce/file 2>/dev/null)" + echo "ref: $REF" + mkdir -p ./path-to-cahce + date > ./path-to-cahce/file + env: + REF: ${{ github.ref }} + + - uses: actions/cache/save@v6 + if: github.ref == 'refs/heads/main' + with: + path: | + ./path-to-cahce + key: ${{ runner.os }}-${{ runner.arch }}-${{ github.sha }} diff --git a/.github/workflows/chapter-4-3-cache-restore.yaml b/.github/workflows/chapter-4-3-cache-restore.yaml deleted file mode 100644 index c237445..0000000 --- a/.github/workflows/chapter-4-3-cache-restore.yaml +++ /dev/null @@ -1,46 +0,0 @@ -# Chapter 4 キャッシュの取り扱い、save, restoreを用いてキャッシュのタイミングを制御する. ---- -name: Chapter 4 - Cache save,restore - -on: - pull_request: - paths: - - ".github/workflows/cache-restore.yaml" - workflow_dispatch: - -permissions: {} - -jobs: - build-start: - runs-on: ubuntu-latest - permissions: - contents: read - timeout-minutes: 5 - steps: - - uses: actions/checkout@v7 - - uses: actions/cache/restore@v6 - with: - path: | - ./path-to-cahce - key: ${{ runner.os }}-${{ runner.arch }}-${{ github.sha }} - restore-keys: | - ${{ runner.os }}-${{ runner.arch }}- - - - run: echo "Do something" - - - name: dummy - run: | - echo "current is: $(date)" - echo "cache value is: $(cat ./path-to-cahce/file 2>/dev/null)" - echo "ref: $REF" - mkdir -p ./path-to-cahce - date > ./path-to-cahce/file - env: - REF: ${{ github.ref }} - - - uses: actions/cache/save@v6 - if: github.ref == 'refs/heads/main' - with: - path: | - ./path-to-cahce - key: ${{ runner.os }}-${{ runner.arch }}-${{ github.sha }} diff --git a/.github/workflows/chapter-5-1-e2e-test.yaml b/.github/workflows/chapter-5-1-e2e-test.yaml index 702c7e9..782c3b3 100644 --- a/.github/workflows/chapter-5-1-e2e-test.yaml +++ b/.github/workflows/chapter-5-1-e2e-test.yaml @@ -1,22 +1,29 @@ -# Chapter 5 再利用可能なメンテナンス性を考慮したワークフロー. +# Chapter 5 メンテナンス性を考慮したワークフロー. --- -name: Chapter 5 - E2E test (Call) +name: Chapter 5 (1) - Make the workflow DRY (E2E Tests). on: pull_request: paths: - - '.github/workflows/e2e-test.yaml' - - '.github/workflows/reusable-e2e-test.yaml' + - '.github/workflows/chapter-5-1-e2e-test.yaml' + - '.github/workflows/reusables/reusable-e2e-test.yaml' - '.github/actions/setup-playwright/action.yaml' - - 'packages/e2e/**' + - 'chapters/e2e/**' workflow_dispatch: permissions: {} +defaults: + run: + shell: bash + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true jobs: e2e: permissions: contents: read - uses: ./.github/workflows/chapter-5-1-reusable-e2e-test.yaml + uses: ./.github/workflows/reusable-e2e-test.yaml with: - working-directory: 'packages/e2e' + working-directory: './chapters/e2e' diff --git a/.github/workflows/chapter-5-1-reusable-e2e-test.yaml b/.github/workflows/chapter-5-1-reusable-e2e-test.yaml deleted file mode 100644 index 35f158d..0000000 --- a/.github/workflows/chapter-5-1-reusable-e2e-test.yaml +++ /dev/null @@ -1,38 +0,0 @@ -# Chapter 5 再利用可能なワークフローの定義. ---- -name: Chapter 5 - E2E test (Reusable workflow) - -on: - workflow_call: - inputs: - working-directory: - type: string - required: false - default: ${{ github.workspace }} - -permissions: {} -defaults: - run: - shell: bash - -jobs: - e2e-test: - runs-on: ubuntu-latest - permissions: - contents: read - timeout-minutes: 5 - steps: - - uses: actions/checkout@v7 - - uses: pnpm/action-setup@v6 - with: - package_json_file: ${{ inputs.working-directory }}/package.json - - uses: actions/setup-node@v7 - with: - node-version: "26" - - run: pnpm install - working-directory: ${{ inputs.working-directory }} - - uses: ./.github/actions/setup-playwright - with: - working-directory: ${{ inputs.working-directory }} - - run: pnpm exec playwright test --project chromium - working-directory: ${{ inputs.working-directory }} diff --git a/.github/workflows/chapter-5-2-timings1-test-environment-create.yaml b/.github/workflows/chapter-5-2-timings1-test-environment-create.yaml index 84629e6..ae81813 100644 --- a/.github/workflows/chapter-5-2-timings1-test-environment-create.yaml +++ b/.github/workflows/chapter-5-2-timings1-test-environment-create.yaml @@ -1,11 +1,11 @@ # Chapter 5 プルリクエストがオープンされたときに動作確認環境を新規作成&アプリケーションをデプロイ. --- -name: Chapter 5 - Create test environment & Deploy application. -run-name: "Create test environment & Deploy application: ${{ github.event.pull_request.number }}" +name: Chapter 5 (2) - 1. Create test environment & Deploy application. +run-name: 'Create test environment & Deploy application: ${{ github.event.pull_request.number }}' on: pull_request: - types: [ opened, reopened] + types: [opened, reopened] workflow_dispatch: permissions: {} @@ -13,6 +13,10 @@ defaults: run: shell: bash +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: create: name: Create test environment diff --git a/.github/workflows/chapter-5-2-timings2-test-environment-update.yaml b/.github/workflows/chapter-5-2-timings2-test-environment-update.yaml index 80d3d71..320d314 100644 --- a/.github/workflows/chapter-5-2-timings2-test-environment-update.yaml +++ b/.github/workflows/chapter-5-2-timings2-test-environment-update.yaml @@ -1,11 +1,11 @@ # Chapter 5 プルリクエストが更新されたときに動作確認環境へアプリケーションを再デプロイ. --- -name: Chapter 5 - Update application for test environment -run-name: "Update application for test environment: ${{ github.event.pull_request.number }}" +name: Chapter 5 (2) - 2. Update application for test environment +run-name: 'Update application for test environment: ${{ github.event.pull_request.number }}' on: pull_request: - types: [ synchronize ] + types: [synchronize] workflow_dispatch: permissions: {} @@ -13,6 +13,10 @@ defaults: run: shell: bash +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: update: name: Update application diff --git a/.github/workflows/chapter-5-2-timings3-test-environment-destroy.yaml b/.github/workflows/chapter-5-2-timings3-test-environment-destroy.yaml index e0bb34b..2a95674 100644 --- a/.github/workflows/chapter-5-2-timings3-test-environment-destroy.yaml +++ b/.github/workflows/chapter-5-2-timings3-test-environment-destroy.yaml @@ -1,7 +1,7 @@ # Chapter 5 プルリクエストがクローズされたときに動作確認環境を破壊. --- -name: Chapter 5 - Destroy test environment -run-name: "Destroy test environment: ${{ github.event.pull_request.number }}" +name: Chapter 5 (2) - 3. Destroy test environment +run-name: 'Destroy test environment: ${{ github.event.pull_request.number }}' on: pull_request: @@ -13,6 +13,10 @@ defaults: run: shell: bash +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: update: name: Destroy test environment diff --git a/.github/workflows/chapter-5-3-skips-if-no-changes-detected.yaml b/.github/workflows/chapter-5-3-skips-if-no-changes-detected.yaml index 87ced7f..bf8b276 100644 --- a/.github/workflows/chapter-5-3-skips-if-no-changes-detected.yaml +++ b/.github/workflows/chapter-5-3-skips-if-no-changes-detected.yaml @@ -1,11 +1,11 @@ # Chapter 5 ファイルの変更を確認し、変更の有無でジョブをスキップするワークフロー --- -name: Chapter 5 - A workflow that checks for file changes and skips the job if no changes are detected. +name: Chapter 5 (3) - A workflow that checks for file changes and skips the job if no changes are detected. on: pull_request: paths: - - ".github/workflows/enterprise-ci.yaml" - - "project/**" + - '.github/workflows/enterprise-ci.yaml' + - 'chapters/project/**' permissions: {} defaults: @@ -30,13 +30,14 @@ jobs: fetch-depth: 2 # ファイルの変更を取得するために必要 - id: changed_directory env: - CHANGED: ${{ runner.temp }}/changed_files.txt + CHANGED: '${{ runner.temp }}/changed_files.txt' run: | git diff --name-only HEAD^ > "$CHANGED" grep --quiet '^project/frontend/' "$CHANGED" && echo "frontend=true" >> "$GITHUB_OUTPUT" grep --quiet '^project/backend/' "$CHANGED" && echo "backend=true" >> "$GITHUB_OUTPUT" grep --quiet '^project/renovate.json$' "$CHANGED" && echo "renovate=true" >> "$GITHUB_OUTPUT" cat "$CHANGED" #ファイルが変更されていない場合にエラーになるのを防ぎ、かつ、デバッグ時の助けにするために git diff の内容をログに出力する + frontend: runs-on: ubuntu-latest needs: changed_directory @@ -47,6 +48,7 @@ jobs: steps: - uses: actions/checkout@v7 - run: echo "Frontend passes lint, tests, and build are listed here." + backend: runs-on: ubuntu-latest needs: changed_directory @@ -57,6 +59,7 @@ jobs: steps: - uses: actions/checkout@v7 - run: echo "Backend passes lint, tests, and build are listed here." + renovate: runs-on: ubuntu-latest needs: changed_directory diff --git a/.github/workflows/chapter-5-4-rerun-only-failed-tests.yaml b/.github/workflows/chapter-5-4-rerun-only-failed-tests.yaml index d86cc06..c600b8f 100644 --- a/.github/workflows/chapter-5-4-rerun-only-failed-tests.yaml +++ b/.github/workflows/chapter-5-4-rerun-only-failed-tests.yaml @@ -1,11 +1,11 @@ # Chapter 5 失敗したテストのみを re-run する. --- -name: Chapter 5 - Rerun only failed tests. +name: Chapter 5 (4) - Rerun only failed tests. on: pull_request: paths: - - ".github/workflows/rerun-only-failed-tests.yaml" + - '.github/workflows/rerun-only-failed-tests.yaml' workflow_dispatch: permissions: {} @@ -37,8 +37,8 @@ jobs: echo "github.run_attempt is $ATTEMPT" echo "github.ref_name is $REF_NAME" env: - ATTEMPT: "${{ github.run_attempt }}" - REF_NAME: "${{ github.ref_name }}" + ATTEMPT: '${{ github.run_attempt }}' + REF_NAME: '${{ github.ref_name }}' - name: Restore failed tests # デフォルトブランチではない、かつ2度目の実行の場合のみ行う @@ -64,5 +64,5 @@ jobs: if: ${{ failure() && github.ref_name != 'main' }} uses: actions/cache/save@v6 with: - path: "${{ env.FAILED_TEST_FILES }}" + path: '${{ env.FAILED_TEST_FILES }}' key: failed-tests-${{ github.run_id }}-${{ github.run_attempt }} diff --git a/.github/workflows/reusable-e2e-test.yaml b/.github/workflows/reusable-e2e-test.yaml new file mode 100644 index 0000000..2b2416b --- /dev/null +++ b/.github/workflows/reusable-e2e-test.yaml @@ -0,0 +1,55 @@ +# Chapter 5 ワークフローをDRYにする (Reusable workflow). +--- +name: E2E playwright test + +on: + workflow_call: + inputs: + working-directory: + type: string + required: false + default: ${{ github.workspace }} + node-version: + type: string + required: false + default: '26' + pnpm-version: + type: string + required: false + default: '11' + +permissions: {} +defaults: + run: + shell: bash + +# Resusable workflow はその名の通り再利用可能なワークフローです。 +# Custom actionと違い、単体でも実行可能なワークフローです。 +# Reusable workflow は workflow_call イベントをトリガーとして実行されます。 +# ワークフローと同じ記述が可能であるため、matrix strategy や concurrency なども利用可能です。 +# 例えば次のケースが考えられます。 +# - テストのワークフローをさまざまなタイミングで実行したい場合 +# - 環境ごとデプロイしたい + +jobs: + e2e-test: + runs-on: ubuntu-latest + permissions: + contents: read + timeout-minutes: 5 + steps: + - uses: actions/checkout@v7 + - uses: pnpm/action-setup@v6 + with: + version: ${{ inputs.pnpm-version }} + - uses: actions/setup-node@v7 + with: + node-version: ${{ inputs.node-version }} + - run: pnpm install + working-directory: ${{ inputs.working-directory }} + # Use a custom. + - uses: ./.github/actions/setup-playwright + with: + working-directory: ${{ inputs.working-directory }} + - run: pnpm exec playwright test --project chromium + working-directory: ${{ inputs.working-directory }} diff --git a/chapters/e2e/package.json b/chapters/e2e/package.json index af2045a..70b842d 100644 --- a/chapters/e2e/package.json +++ b/chapters/e2e/package.json @@ -2,14 +2,13 @@ "name": "e2e", "version": "1.0.0", "description": "", - "main": "index.js", "scripts": {}, "keywords": [], "author": "", - "license": "ISC", - "packageManager": "pnpm@9.12.3+sha512.cce0f9de9c5a7c95bef944169cc5dfe8741abfb145078c0d508b868056848a87c81e626246cb60967cbd7fd29a6c062ef73ff840d96b3c86c40ac92cf4a813ee", + "license": "MIT", + "type": "module", "devDependencies": { - "@playwright/test": "^1.56.1", - "@types/node": "^22.10.0" + "@playwright/test": "^1.62.1", + "@types/node": "^26.1.2" } -} +} \ No newline at end of file diff --git a/chapters/e2e/pnpm-lock.yaml b/chapters/e2e/pnpm-lock.yaml index 107023c..9b95797 100644 --- a/chapters/e2e/pnpm-lock.yaml +++ b/chapters/e2e/pnpm-lock.yaml @@ -9,59 +9,59 @@ importers: .: devDependencies: '@playwright/test': - specifier: ^1.56.1 - version: 1.56.1 + specifier: ^1.62.1 + version: 1.62.1 '@types/node': - specifier: ^22.10.0 - version: 22.19.0 + specifier: ^26.1.2 + version: 26.1.2 packages: - '@playwright/test@1.56.1': - resolution: {integrity: sha512-vSMYtL/zOcFpvJCW71Q/OEGQb7KYBPAdKh35WNSkaZA75JlAO8ED8UN6GUNTm3drWomcbcqRPFqQbLae8yBTdg==} - engines: {node: '>=18'} + '@playwright/test@1.62.1': + resolution: {integrity: sha512-DTcUc8qii+cpHvtOwggMtBRMjKZHXYWdw8syRYu2vtzuq4Wxphqq4NfCs5Zt44L6mA8rfDfj+PHnxFc/FeK6mQ==} + engines: {node: '>=20'} hasBin: true - '@types/node@22.19.0': - resolution: {integrity: sha512-xpr/lmLPQEj+TUnHmR+Ab91/glhJvsqcjB+yY0Ix9GO70H6Lb4FHH5GeqdOE5btAx7eIMwuHkp4H2MSkLcqWbA==} + '@types/node@26.1.2': + resolution: {integrity: sha512-Vu4a5UFA9rIIFJ7rB/Vaafh9lrCQszopTCx6KjFboXTGQbPNasehVR5TEiithSDGyd1DEiUByggTZsg8jukeIg==} fsevents@2.3.2: resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] - playwright-core@1.56.1: - resolution: {integrity: sha512-hutraynyn31F+Bifme+Ps9Vq59hKuUCz7H1kDOcBs+2oGguKkWTU50bBWrtz34OUWmIwpBTWDxaRPXrIXkgvmQ==} - engines: {node: '>=18'} + playwright-core@1.62.1: + resolution: {integrity: sha512-wPYSwEBJY9GHraISXqyqtx0na0LpO3XEX7jNDhntbex7tzUS7kLnZsOlFruFJB4Hi/rhDMjXGqHewDZ68nYZVw==} + engines: {node: '>=20'} hasBin: true - playwright@1.56.1: - resolution: {integrity: sha512-aFi5B0WovBHTEvpM3DzXTUaeN6eN0qWnTkKx4NQaH4Wvcmc153PdaY2UBdSYKaGYw+UyWXSVyxDUg5DoPEttjw==} - engines: {node: '>=18'} + playwright@1.62.1: + resolution: {integrity: sha512-0M+L3LAD8/nm554LOla9Ayx0j0tmFZ0FBcoQ7F1VuVHpM/XpiC8RcDzBQB8W5+hA8L22THxELzeF+2WcUzvcLg==} + engines: {node: '>=20'} hasBin: true - undici-types@6.21.0: - resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} + undici-types@8.3.0: + resolution: {integrity: sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==} snapshots: - '@playwright/test@1.56.1': + '@playwright/test@1.62.1': dependencies: - playwright: 1.56.1 + playwright: 1.62.1 - '@types/node@22.19.0': + '@types/node@26.1.2': dependencies: - undici-types: 6.21.0 + undici-types: 8.3.0 fsevents@2.3.2: optional: true - playwright-core@1.56.1: {} + playwright-core@1.62.1: {} - playwright@1.56.1: + playwright@1.62.1: dependencies: - playwright-core: 1.56.1 + playwright-core: 1.62.1 optionalDependencies: fsevents: 2.3.2 - undici-types@6.21.0: {} + undici-types@8.3.0: {}