地図の経路詳細にも天気のリンクを出す #100
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # mainへのpushで本番用Dockerイメージをビルドし、GHCRへ公開する。 | |
| # 本番環境の更新はこれらをpullするだけでよい(README「本番運用」参照)。 | |
| # ghcr.io/rtcode337/travel-log … アプリ本体(Dockerfileのprodステージ、appサービス) | |
| # ghcr.io/rtcode337/travel-log-db-init … スキーマ・マイグレーション適用 | |
| # (db/Dockerfile、initサービス。イメージ名は旧構成の名残) | |
| # | |
| # アプリ本体は amd64/arm64 を「それぞれのアーキのネイティブランナー」で並列ビルドし、 | |
| # ダイジェストで push したものを最後の merge ジョブでマニフェストにまとめる。 | |
| # 以前は amd64 ランナー上で arm64 を QEMU エミュレーションしていたが、arm64 の | |
| # `npm ci`(や next build)が極端に遅く、まれにハングしてビルドが 40 分以上 | |
| # 進まないことがあったため、ネイティブランナー方式に変えた(publicリポジトリは | |
| # ubuntu-24.04-arm ランナーを無料で使える)。 | |
| name: docker-publish | |
| on: | |
| push: | |
| branches: [main] | |
| workflow_dispatch: | |
| permissions: | |
| contents: read | |
| packages: write | |
| env: | |
| IMAGE: ghcr.io/${{ github.repository }} | |
| jobs: | |
| # 管理画面に表示するビルド番号(JSTの日時 + 短縮コミットハッシュ)を1回だけ決めて、 | |
| # 両アーキのビルドで同じ値を焼き込む(アーキごとに別値にならないように) | |
| prepare: | |
| runs-on: ubuntu-latest | |
| outputs: | |
| build_number: ${{ steps.build_number.outputs.value }} | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - id: build_number | |
| run: | | |
| echo "value=$(TZ=Asia/Tokyo date +'%Y%m%d-%H%M')-$(git rev-parse --short HEAD)" >> "$GITHUB_OUTPUT" | |
| # アーキごとにネイティブランナーでビルドし、タグを付けずダイジェストで push する | |
| build: | |
| needs: prepare | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - platform: linux/amd64 | |
| runner: ubuntu-latest | |
| - platform: linux/arm64 | |
| runner: ubuntu-24.04-arm | |
| runs-on: ${{ matrix.runner }} | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - uses: docker/setup-buildx-action@v4 | |
| - uses: docker/login-action@v4 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - id: meta | |
| uses: docker/metadata-action@v6 | |
| with: | |
| images: ${{ env.IMAGE }} | |
| - id: build | |
| uses: docker/build-push-action@v7 | |
| with: | |
| context: . | |
| target: prod | |
| platforms: ${{ matrix.platform }} | |
| build-args: | | |
| BUILD_NUMBER=${{ needs.prepare.outputs.build_number }} | |
| labels: ${{ steps.meta.outputs.labels }} | |
| # タグではなくダイジェストで push する(マニフェストは merge ジョブで作る) | |
| outputs: type=image,name=${{ env.IMAGE }},push-by-digest=true,name-canonical=true,push=true | |
| cache-from: type=gha,scope=app-${{ matrix.platform }} | |
| cache-to: type=gha,mode=max,scope=app-${{ matrix.platform }} | |
| - 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-app-${{ strategy.job-index }} | |
| path: /tmp/digests/* | |
| if-no-files-found: error | |
| retention-days: 1 | |
| # 各アーキのダイジェストを1つのマニフェスト(latest / sha-xxxxxxx タグ)にまとめて push する | |
| merge: | |
| needs: [build] | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Download digests | |
| uses: actions/download-artifact@v8 | |
| with: | |
| path: /tmp/digests | |
| pattern: digests-app-* | |
| merge-multiple: true | |
| - uses: docker/setup-buildx-action@v4 | |
| - uses: docker/login-action@v4 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - id: meta | |
| uses: docker/metadata-action@v6 | |
| with: | |
| images: ${{ env.IMAGE }} | |
| # latest(既定ブランチのみ)+ コミットSHA(sha-xxxxxxx)の2タグ。 | |
| # 障害時はSHAタグを指定してpullすれば任意の時点に戻せる | |
| tags: | | |
| type=raw,value=latest,enable={{is_default_branch}} | |
| type=sha | |
| - name: Create manifest list and push | |
| working-directory: /tmp/digests | |
| run: | | |
| docker buildx imagetools create \ | |
| $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ | |
| $(printf '${{ env.IMAGE }}@sha256:%s ' *) | |
| - name: Inspect | |
| run: docker buildx imagetools inspect ${{ env.IMAGE }}:${{ steps.meta.outputs.version }} | |
| # DBの準備・マイグレーション適用用イメージ(db/Dockerfile)。マイグレーションSQLを | |
| # 焼き込むため、db/migrations/ を足したときもこのイメージのpullだけで本番に反映される。 | |
| # 小さいイメージ(Alpine + SQLコピー)でハングの実績も無いため、こちらは従来どおり | |
| # QEMUマルチアーキビルドのまま(アプリ本体とは独立して並列に走る) | |
| build-and-push-db-init: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - uses: docker/setup-qemu-action@v4 | |
| - uses: docker/setup-buildx-action@v4 | |
| - uses: docker/login-action@v4 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - id: meta | |
| uses: docker/metadata-action@v6 | |
| with: | |
| images: ghcr.io/${{ github.repository }}-db-init | |
| tags: | | |
| type=raw,value=latest,enable={{is_default_branch}} | |
| type=sha | |
| - uses: docker/build-push-action@v7 | |
| with: | |
| # マイグレーションSQLとentrypoint.shだけを含む小さなコンテキスト | |
| context: ./db | |
| push: true | |
| platforms: linux/amd64,linux/arm64 | |
| tags: ${{ steps.meta.outputs.tags }} | |
| labels: ${{ steps.meta.outputs.labels }} | |
| cache-from: type=gha,scope=db-init | |
| cache-to: type=gha,mode=max,scope=db-init | |
| # 古い版を消して直近 10 世代だけ残す。 | |
| # | |
| # 公開パッケージなので GHCR の容量・転送は無料枠を消費しないが、版は放っておくと | |
| # 際限なく積み上がる(`latest` を付け替えても前の版は SHA タグ付きで残る)。 | |
| # 一覧が読めなくなるのと、どれが生きているか分からなくなるのを防ぐための掃除。 | |
| # | |
| # **専用のジョブにして、両方の push が終わってから走らせる。** db-init のジョブは | |
| # 本体のビルドと並行に走るので、そちらに相乗りさせると「新しい版が出来る前に掃除する」 | |
| # 順序になりうる。 | |
| # | |
| # **actions/delete-package-versions は使わない。** このリポジトリはマルチアーキで、 | |
| # 1 つのタグが manifest list + アーキごとの子イメージで構成される。あちらは | |
| # 子イメージを「タグ無しの版」として消してしまい、残したはずのタグが壊れる。 | |
| # この action は manifest list を理解して親子まとめて扱う。 | |
| cleanup: | |
| needs: [merge, build-and-push-db-init] | |
| runs-on: ubuntu-latest | |
| permissions: | |
| packages: write | |
| steps: | |
| - name: 古いイメージを削除して直近 10 世代だけ残す | |
| uses: dataaxiom/ghcr-cleanup-action@v1 | |
| with: | |
| packages: travel-log,travel-log-db-init | |
| keep-n-tagged: 10 | |
| delete-untagged: true | |
| token: ${{ secrets.GITHUB_TOKEN }} |