fix(galgame): 语音对话下不空耗 token —— 后端 takeover 守卫 + 不变量测试 (#1647) #356
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
| name: Docker Build | |
| on: | |
| push: | |
| branches: | |
| - main # 主分支有新 commit 时触发(合并 PR 后的 squash commit 在这里验) | |
| tags: | |
| - 'v*' # 匹配 v 开头的标签,例如 v1.0.0 | |
| paths-ignore: | |
| - '**.md' | |
| - 'docs/**' | |
| - '.gitignore' | |
| # PR 触发刻意不开:单个 PR 的多次 commit 会触发多次 multi-arch build, | |
| # 200 PR/月 × N commit 占满 runner 队列;让 squash 进 main 的那次 push 来验证即可。 | |
| # 单 PR 想手动验,用 workflow_dispatch + ci 模式即可。 | |
| workflow_dispatch: | |
| inputs: | |
| build_mode: | |
| description: '构建模式' | |
| type: choice | |
| options: | |
| - ci | |
| - custom | |
| default: 'ci' | |
| required: true | |
| version: | |
| description: '自定义版本号 (仅在 custom 模式下生效)' | |
| required: false | |
| default: '' | |
| skip_dockerhub: | |
| description: '跳过 Docker Hub 推送 (仅推送到 GHCR)' | |
| type: boolean | |
| required: false | |
| default: false | |
| # Concurrency configuration: queue Docker builds to avoid parallel runs | |
| # - Same group for all triggers to ensure serialization | |
| # - cancel-in-progress: false to wait for current build to complete | |
| # - PR builds use separate group to not block main branch builds | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref == 'refs/heads/main' && 'main' || github.head_ref || github.ref }} | |
| cancel-in-progress: ${{ github.event_name == 'pull_request' }} | |
| env: | |
| REGISTRY_GHCR: ghcr.io | |
| IMAGE_NAME: project-n-e-k-o/n.e.k.o | |
| jobs: | |
| # ============================================================================ | |
| # Job 1: Calculate version (shared by all build jobs) | |
| # ============================================================================ | |
| calculate-version: | |
| runs-on: ubuntu-latest | |
| outputs: | |
| image_version: ${{ steps.version_calc.outputs.VERSION }} | |
| skip_dockerhub: ${{ steps.calc_skip.outputs.SKIP_DOCKERHUB }} | |
| is_main_commit: ${{ steps.calc_is_main.outputs.IS_MAIN_COMMIT }} | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Calculate is_main_commit flag | |
| id: calc_is_main | |
| run: | | |
| # True for: main branch push OR manual dispatch from main branch in CI mode | |
| # 必须同时锁定 ref==main,否则在 feature branch 上手动 dispatch ci 模式 | |
| # 会让 ci-standard/ci-full 等共享别名被未合并代码覆盖 | |
| if [[ "$GITHUB_REF" == refs/heads/main ]] && [[ "$GITHUB_EVENT_NAME" == "push" ]]; then | |
| echo "IS_MAIN_COMMIT=true" >> $GITHUB_OUTPUT | |
| elif [[ "$GITHUB_EVENT_NAME" == "workflow_dispatch" ]] && [[ "${{ github.event.inputs.build_mode }}" == "ci" ]] && [[ "$GITHUB_REF" == refs/heads/main ]]; then | |
| echo "IS_MAIN_COMMIT=true" >> $GITHUB_OUTPUT | |
| else | |
| echo "IS_MAIN_COMMIT=false" >> $GITHUB_OUTPUT | |
| fi | |
| - name: Calculate skip_dockerhub flag | |
| id: calc_skip | |
| run: | | |
| # 策略:Docker Hub 只发 release(tag push)和手动 dispatch(按 input)。 | |
| # 主线 commit / PR(如果重新启用)只推 GHCR,避免主线滚动版污染对外 channel。 | |
| if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then | |
| echo "SKIP_DOCKERHUB=${{ github.event.inputs.skip_dockerhub || 'false' }}" >> $GITHUB_OUTPUT | |
| elif [[ "$GITHUB_REF" == refs/tags/* ]]; then | |
| # Release tag: 推 Docker Hub 作为对外公开发布 channel | |
| echo "SKIP_DOCKERHUB=false" >> $GITHUB_OUTPUT | |
| else | |
| # 其他(main push / PR 等): 只推 GHCR | |
| echo "SKIP_DOCKERHUB=true" >> $GITHUB_OUTPUT | |
| fi | |
| - name: Calculate Docker image version | |
| id: version_calc | |
| run: | | |
| # 策略1: 如果是由 git tag 触发,则使用 tag 作为版本号 (去掉 'v' 前缀) | |
| if [[ "$GITHUB_REF" == refs/tags/* ]]; then | |
| VERSION=${GITHUB_REF#refs/tags/v} | |
| echo "版本号来源于Git标签: $VERSION" | |
| # 策略2: 如果手动触发且选择 CI 模式,使用 ci-{commit hash} 格式 | |
| elif [[ "$GITHUB_EVENT_NAME" == "workflow_dispatch" ]] && [[ "${{ github.event.inputs.build_mode }}" == "ci" ]]; then | |
| COMMIT_SHORT=$(git rev-parse --short HEAD) | |
| VERSION="ci-${COMMIT_SHORT}" | |
| echo "版本号来源于CI模式(手动触发): $VERSION" | |
| # 策略3: 如果手动触发且选择 custom 模式,使用自定义版本号 | |
| elif [[ "$GITHUB_EVENT_NAME" == "workflow_dispatch" ]] && [[ "${{ github.event.inputs.build_mode }}" == "custom" ]]; then | |
| VERSION="${{ github.event.inputs.version }}" | |
| if [ -z "$VERSION" ] || [ "$VERSION" = "" ]; then | |
| COMMIT_SHORT=$(git rev-parse --short HEAD) | |
| DATE=$(date +%Y%m%d) | |
| VERSION="${DATE}-${COMMIT_SHORT}" | |
| echo "版本号为自动生成(未提供自定义版本): $VERSION" | |
| else | |
| echo "版本号来源于手动输入: $VERSION" | |
| fi | |
| # 策略4: 如果是 PR 触发,使用 pr-{number}-ci 标签 | |
| elif [[ "$GITHUB_EVENT_NAME" == "pull_request" ]]; then | |
| PR_NUMBER=${{ github.event.pull_request.number }} | |
| VERSION="pr-${PR_NUMBER}-ci" | |
| echo "版本号来源于PR编号: $VERSION" | |
| # 策略5: 如果是 main 分支 commit,使用 ci-{commit hash} 格式 | |
| elif [[ "$GITHUB_REF" == refs/heads/main ]]; then | |
| COMMIT_SHORT=$(git rev-parse --short HEAD) | |
| VERSION="ci-${COMMIT_SHORT}" | |
| echo "版本号来源于main分支commit: $VERSION" | |
| # 策略6: 其他情况,生成基于日期和提交哈希的版本号 | |
| else | |
| COMMIT_SHORT=$(git rev-parse --short HEAD) | |
| DATE=$(date +%Y%m%d) | |
| VERSION="${DATE}-${COMMIT_SHORT}" | |
| echo "版本号为自动生成: $VERSION" | |
| fi | |
| echo "VERSION=$VERSION" >> $GITHUB_OUTPUT | |
| # ============================================================================ | |
| # Job 2: Build and push STANDARD version (parallel with full version) | |
| # ============================================================================ | |
| build-standard: | |
| needs: calculate-version | |
| # 仅在上游仓库运行:fork 上的 push / workflow_dispatch 用其 GITHUB_TOKEN 无法写入上游 GHCR namespace,会必然失败 | |
| if: github.repository == 'Project-N-E-K-O/N.E.K.O' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| packages: write | |
| outputs: | |
| skipped: ${{ steps.check-dockerfile.outputs.skipped }} | |
| strategy: | |
| matrix: | |
| platform: [linux/amd64, linux/arm64] | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Check if Dockerfile exists | |
| id: check-dockerfile | |
| run: | | |
| if [ -f "./docker/Dockerfile" ]; then | |
| echo "skipped=false" >> $GITHUB_OUTPUT | |
| echo "✅ docker/Dockerfile found, proceeding with standard build" | |
| else | |
| echo "skipped=true" >> $GITHUB_OUTPUT | |
| echo "⚠️ docker/Dockerfile not found, skipping standard build" | |
| fi | |
| - name: Set up QEMU | |
| if: steps.check-dockerfile.outputs.skipped != 'true' | |
| uses: docker/setup-qemu-action@v3 | |
| - name: Set up Docker Buildx | |
| if: steps.check-dockerfile.outputs.skipped != 'true' | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Log in to GHCR | |
| if: steps.check-dockerfile.outputs.skipped != 'true' | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Check Docker Hub credentials | |
| id: check_dockerhub | |
| if: steps.check-dockerfile.outputs.skipped != 'true' && needs.calculate-version.outputs.skip_dockerhub != 'true' | |
| run: | | |
| if [ -n "${{ secrets.DOCKERHUB_USERNAME }}" ] && [ -n "${{ secrets.DOCKERHUB_TOKEN }}" ]; then | |
| echo "has_credentials=true" >> $GITHUB_OUTPUT | |
| echo "✅ Docker Hub credentials found" | |
| else | |
| echo "has_credentials=false" >> $GITHUB_OUTPUT | |
| echo "⚠️ Docker Hub credentials not configured, skipping Docker Hub push" | |
| echo " To enable Docker Hub push, set DOCKERHUB_USERNAME and DOCKERHUB_TOKEN in repository secrets" | |
| fi | |
| - name: Log in to Docker Hub | |
| if: steps.check-dockerfile.outputs.skipped != 'true' && needs.calculate-version.outputs.skip_dockerhub != 'true' && steps.check_dockerhub.outputs.has_credentials == 'true' | |
| uses: docker/login-action@v3 | |
| with: | |
| username: ${{ secrets.DOCKERHUB_USERNAME }} | |
| password: ${{ secrets.DOCKERHUB_TOKEN }} | |
| - name: Extract metadata for Docker (GHCR only) | |
| if: steps.check-dockerfile.outputs.skipped != 'true' && (needs.calculate-version.outputs.skip_dockerhub == 'true' || (needs.calculate-version.outputs.skip_dockerhub != 'true' && steps.check_dockerhub.outputs.has_credentials != 'true')) | |
| id: meta_ghcr | |
| uses: docker/metadata-action@v5 | |
| with: | |
| images: ${{ env.REGISTRY_GHCR }}/${{ env.IMAGE_NAME }} | |
| flavor: | | |
| suffix=-${{ matrix.platform }} | |
| tags: | | |
| # PR builds: pr-{number}-ci-standard-linux-amd64/arm64 AND pr-ci-standard-linux-amd64/arm64 | |
| type=raw,value=${{ needs.calculate-version.outputs.image_version }}-standard,enable=${{ startsWith(needs.calculate-version.outputs.image_version, 'pr-') }} | |
| type=raw,value=pr-ci-standard,enable=${{ startsWith(needs.calculate-version.outputs.image_version, 'pr-') }} | |
| # CI builds: ci-{hash}-standard-linux-amd64/arm64 AND ci-standard-linux-amd64/arm64 | |
| type=raw,value=${{ needs.calculate-version.outputs.image_version }}-standard,enable=${{ startsWith(needs.calculate-version.outputs.image_version, 'ci-') }} | |
| type=raw,value=ci-standard,enable=${{ startsWith(needs.calculate-version.outputs.image_version, 'ci-') }} | |
| # Other builds (manual/tag): use version as-is | |
| type=raw,value=${{ needs.calculate-version.outputs.image_version }}-standard,enable=${{ !startsWith(needs.calculate-version.outputs.image_version, 'pr-') && !startsWith(needs.calculate-version.outputs.image_version, 'ci-') }} | |
| - name: Extract metadata for Docker (both registries) | |
| if: steps.check-dockerfile.outputs.skipped != 'true' && needs.calculate-version.outputs.skip_dockerhub != 'true' && steps.check_dockerhub.outputs.has_credentials == 'true' | |
| id: meta_both | |
| uses: docker/metadata-action@v5 | |
| with: | |
| images: | | |
| ${{ env.REGISTRY_GHCR }}/${{ env.IMAGE_NAME }} | |
| ${{ secrets.DOCKERHUB_USERNAME }}/n.e.k.o | |
| flavor: | | |
| suffix=-${{ matrix.platform }} | |
| tags: | | |
| # PR builds: pr-{number}-ci-standard-linux-amd64/arm64 AND pr-ci-standard-linux-amd64/arm64 | |
| type=raw,value=${{ needs.calculate-version.outputs.image_version }}-standard,enable=${{ startsWith(needs.calculate-version.outputs.image_version, 'pr-') }} | |
| type=raw,value=pr-ci-standard,enable=${{ startsWith(needs.calculate-version.outputs.image_version, 'pr-') }} | |
| # CI builds: ci-{hash}-standard-linux-amd64/arm64 AND ci-standard-linux-amd64/arm64 | |
| type=raw,value=${{ needs.calculate-version.outputs.image_version }}-standard,enable=${{ startsWith(needs.calculate-version.outputs.image_version, 'ci-') }} | |
| type=raw,value=ci-standard,enable=${{ startsWith(needs.calculate-version.outputs.image_version, 'ci-') }} | |
| # Other builds (manual/tag): use version as-is | |
| type=raw,value=${{ needs.calculate-version.outputs.image_version }}-standard,enable=${{ !startsWith(needs.calculate-version.outputs.image_version, 'pr-') && !startsWith(needs.calculate-version.outputs.image_version, 'ci-') }} | |
| - name: Build and push standard image | |
| if: steps.check-dockerfile.outputs.skipped != 'true' | |
| uses: docker/build-push-action@v5 | |
| with: | |
| context: . | |
| file: ./docker/Dockerfile | |
| platforms: ${{ matrix.platform }} | |
| push: true | |
| tags: ${{ steps.meta_ghcr.outputs.tags || steps.meta_both.outputs.tags }} | |
| labels: ${{ steps.meta_ghcr.outputs.labels || steps.meta_both.outputs.labels }} | |
| cache-from: type=gha | |
| cache-to: type=gha,mode=max | |
| # ============================================================================ | |
| # Job 3: Build and push FULL version (parallel with standard version) | |
| # ============================================================================ | |
| build-full: | |
| needs: calculate-version | |
| # 仅在上游仓库运行:fork 上的 push / workflow_dispatch 用其 GITHUB_TOKEN 无法写入上游 GHCR namespace,会必然失败 | |
| if: github.repository == 'Project-N-E-K-O/N.E.K.O' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| packages: write | |
| strategy: | |
| matrix: | |
| platform: [linux/amd64, linux/arm64] | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Set up QEMU | |
| uses: docker/setup-qemu-action@v3 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Log in to GHCR | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Check Docker Hub credentials | |
| id: check_dockerhub | |
| if: needs.calculate-version.outputs.skip_dockerhub != 'true' | |
| run: | | |
| if [ -n "${{ secrets.DOCKERHUB_USERNAME }}" ] && [ -n "${{ secrets.DOCKERHUB_TOKEN }}" ]; then | |
| echo "has_credentials=true" >> $GITHUB_OUTPUT | |
| echo "✅ Docker Hub credentials found" | |
| else | |
| echo "has_credentials=false" >> $GITHUB_OUTPUT | |
| echo "⚠️ Docker Hub credentials not configured, skipping Docker Hub push" | |
| echo " To enable Docker Hub push, set DOCKERHUB_USERNAME and DOCKERHUB_TOKEN in repository secrets" | |
| fi | |
| - name: Log in to Docker Hub | |
| if: needs.calculate-version.outputs.skip_dockerhub != 'true' && steps.check_dockerhub.outputs.has_credentials == 'true' | |
| uses: docker/login-action@v3 | |
| with: | |
| username: ${{ secrets.DOCKERHUB_USERNAME }} | |
| password: ${{ secrets.DOCKERHUB_TOKEN }} | |
| - name: Extract metadata for Docker (GHCR only) | |
| if: needs.calculate-version.outputs.skip_dockerhub == 'true' || (needs.calculate-version.outputs.skip_dockerhub != 'true' && steps.check_dockerhub.outputs.has_credentials != 'true') | |
| id: meta_ghcr | |
| uses: docker/metadata-action@v5 | |
| with: | |
| images: ${{ env.REGISTRY_GHCR }}/${{ env.IMAGE_NAME }} | |
| flavor: | | |
| suffix=-${{ matrix.platform }} | |
| tags: | | |
| # PR builds: pr-{number}-ci-full-linux-amd64/arm64 AND pr-ci-full-linux-amd64/arm64 | |
| type=raw,value=${{ needs.calculate-version.outputs.image_version }}-full,enable=${{ startsWith(needs.calculate-version.outputs.image_version, 'pr-') }} | |
| type=raw,value=pr-ci-full,enable=${{ startsWith(needs.calculate-version.outputs.image_version, 'pr-') }} | |
| # CI builds: ci-{hash}-full-linux-amd64/arm64 AND ci-full-linux-amd64/arm64 | |
| type=raw,value=${{ needs.calculate-version.outputs.image_version }}-full,enable=${{ startsWith(needs.calculate-version.outputs.image_version, 'ci-') }} | |
| type=raw,value=ci-full,enable=${{ startsWith(needs.calculate-version.outputs.image_version, 'ci-') }} | |
| # Other builds (manual/tag): use version as-is | |
| type=raw,value=${{ needs.calculate-version.outputs.image_version }}-full,enable=${{ !startsWith(needs.calculate-version.outputs.image_version, 'pr-') && !startsWith(needs.calculate-version.outputs.image_version, 'ci-') }} | |
| - name: Extract metadata for Docker (both registries) | |
| if: needs.calculate-version.outputs.skip_dockerhub != 'true' && steps.check_dockerhub.outputs.has_credentials == 'true' | |
| id: meta_both | |
| uses: docker/metadata-action@v5 | |
| with: | |
| images: | | |
| ${{ env.REGISTRY_GHCR }}/${{ env.IMAGE_NAME }} | |
| ${{ secrets.DOCKERHUB_USERNAME }}/n.e.k.o | |
| flavor: | | |
| suffix=-${{ matrix.platform }} | |
| tags: | | |
| # PR builds: pr-{number}-ci-full-linux-amd64/arm64 AND pr-ci-full-linux-amd64/arm64 | |
| type=raw,value=${{ needs.calculate-version.outputs.image_version }}-full,enable=${{ startsWith(needs.calculate-version.outputs.image_version, 'pr-') }} | |
| type=raw,value=pr-ci-full,enable=${{ startsWith(needs.calculate-version.outputs.image_version, 'pr-') }} | |
| # CI builds: ci-{hash}-full-linux-amd64/arm64 AND ci-full-linux-amd64/arm64 | |
| type=raw,value=${{ needs.calculate-version.outputs.image_version }}-full,enable=${{ startsWith(needs.calculate-version.outputs.image_version, 'ci-') }} | |
| type=raw,value=ci-full,enable=${{ startsWith(needs.calculate-version.outputs.image_version, 'ci-') }} | |
| # Other builds (manual/tag): use version as-is | |
| type=raw,value=${{ needs.calculate-version.outputs.image_version }}-full,enable=${{ !startsWith(needs.calculate-version.outputs.image_version, 'pr-') && !startsWith(needs.calculate-version.outputs.image_version, 'ci-') }} | |
| - name: Build and push full image | |
| uses: docker/build-push-action@v5 | |
| with: | |
| context: . | |
| file: ./docker/Dockerfile.full | |
| platforms: ${{ matrix.platform }} | |
| push: true | |
| tags: ${{ steps.meta_ghcr.outputs.tags || steps.meta_both.outputs.tags }} | |
| labels: ${{ steps.meta_ghcr.outputs.labels || steps.meta_both.outputs.labels }} | |
| cache-from: type=gha | |
| cache-to: type=gha,mode=max | |
| # ============================================================================ | |
| # Job 4: Create multi-arch manifests (runs after both versions are built) | |
| # ============================================================================ | |
| create-manifests: | |
| needs: [calculate-version, build-standard, build-full] | |
| if: github.repository == 'Project-N-E-K-O/N.E.K.O' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) && always() && needs.build-full.result == 'success' | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| packages: write | |
| steps: | |
| - name: Log in to GHCR | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Check Docker Hub credentials | |
| id: check_dockerhub | |
| if: needs.calculate-version.outputs.skip_dockerhub != 'true' | |
| run: | | |
| if [ -n "${{ secrets.DOCKERHUB_USERNAME }}" ] && [ -n "${{ secrets.DOCKERHUB_TOKEN }}" ]; then | |
| echo "has_credentials=true" >> $GITHUB_OUTPUT | |
| echo "✅ Docker Hub credentials found" | |
| else | |
| echo "has_credentials=false" >> $GITHUB_OUTPUT | |
| echo "⚠️ Docker Hub credentials not configured, skipping Docker Hub manifest push" | |
| fi | |
| - name: Log in to Docker Hub | |
| if: needs.calculate-version.outputs.skip_dockerhub != 'true' && steps.check_dockerhub.outputs.has_credentials == 'true' | |
| uses: docker/login-action@v3 | |
| with: | |
| username: ${{ secrets.DOCKERHUB_USERNAME }} | |
| password: ${{ secrets.DOCKERHUB_TOKEN }} | |
| - name: Create and push multi-arch manifest for standard version (GHCR) | |
| if: needs.build-standard.outputs.skipped != 'true' | |
| run: | | |
| VERSION=${{ needs.calculate-version.outputs.image_version }} | |
| docker buildx imagetools create \ | |
| -t ghcr.io/${{ env.IMAGE_NAME }}:${VERSION}-standard \ | |
| ghcr.io/${{ env.IMAGE_NAME }}:${VERSION}-standard-linux-amd64 \ | |
| ghcr.io/${{ env.IMAGE_NAME }}:${VERSION}-standard-linux-arm64 | |
| - name: Create and push multi-arch manifest for standard version (DockerHub) | |
| if: needs.build-standard.outputs.skipped != 'true' && needs.calculate-version.outputs.skip_dockerhub != 'true' && steps.check_dockerhub.outputs.has_credentials == 'true' | |
| run: | | |
| VERSION=${{ needs.calculate-version.outputs.image_version }} | |
| docker buildx imagetools create \ | |
| -t ${{ secrets.DOCKERHUB_USERNAME }}/n.e.k.o:${VERSION}-standard \ | |
| ${{ secrets.DOCKERHUB_USERNAME }}/n.e.k.o:${VERSION}-standard-linux-amd64 \ | |
| ${{ secrets.DOCKERHUB_USERNAME }}/n.e.k.o:${VERSION}-standard-linux-arm64 | |
| - name: Create and push multi-arch manifest for full version (GHCR) | |
| run: | | |
| VERSION=${{ needs.calculate-version.outputs.image_version }} | |
| docker buildx imagetools create \ | |
| -t ghcr.io/${{ env.IMAGE_NAME }}:${VERSION}-full \ | |
| ghcr.io/${{ env.IMAGE_NAME }}:${VERSION}-full-linux-amd64 \ | |
| ghcr.io/${{ env.IMAGE_NAME }}:${VERSION}-full-linux-arm64 | |
| - name: Create and push multi-arch manifest for full version (DockerHub) | |
| if: needs.calculate-version.outputs.skip_dockerhub != 'true' && steps.check_dockerhub.outputs.has_credentials == 'true' | |
| run: | | |
| VERSION=${{ needs.calculate-version.outputs.image_version }} | |
| docker buildx imagetools create \ | |
| -t ${{ secrets.DOCKERHUB_USERNAME }}/n.e.k.o:${VERSION}-full \ | |
| ${{ secrets.DOCKERHUB_USERNAME }}/n.e.k.o:${VERSION}-full-linux-amd64 \ | |
| ${{ secrets.DOCKERHUB_USERNAME }}/n.e.k.o:${VERSION}-full-linux-arm64 | |
| - name: Create and push CI short tags - standard (GHCR) | |
| if: needs.calculate-version.outputs.is_main_commit == 'true' && needs.build-standard.outputs.skipped != 'true' | |
| run: | | |
| VERSION=${{ needs.calculate-version.outputs.image_version }} | |
| # GHCR - ci-standard (without hash) | |
| docker buildx imagetools create \ | |
| -t ghcr.io/${{ env.IMAGE_NAME }}:ci-standard \ | |
| ghcr.io/${{ env.IMAGE_NAME }}:${VERSION}-standard-linux-amd64 \ | |
| ghcr.io/${{ env.IMAGE_NAME }}:${VERSION}-standard-linux-arm64 | |
| - name: Create and push CI short tags - full (GHCR) | |
| if: needs.calculate-version.outputs.is_main_commit == 'true' | |
| run: | | |
| VERSION=${{ needs.calculate-version.outputs.image_version }} | |
| # GHCR - ci-full (without hash) | |
| docker buildx imagetools create \ | |
| -t ghcr.io/${{ env.IMAGE_NAME }}:ci-full \ | |
| ghcr.io/${{ env.IMAGE_NAME }}:${VERSION}-full-linux-amd64 \ | |
| ghcr.io/${{ env.IMAGE_NAME }}:${VERSION}-full-linux-arm64 | |
| - name: Create and push CI short tags - standard (DockerHub) | |
| if: needs.calculate-version.outputs.is_main_commit == 'true' && needs.build-standard.outputs.skipped != 'true' && needs.calculate-version.outputs.skip_dockerhub != 'true' && steps.check_dockerhub.outputs.has_credentials == 'true' | |
| run: | | |
| VERSION=${{ needs.calculate-version.outputs.image_version }} | |
| # DockerHub - ci-standard (without hash) | |
| docker buildx imagetools create \ | |
| -t ${{ secrets.DOCKERHUB_USERNAME }}/n.e.k.o:ci-standard \ | |
| ${{ secrets.DOCKERHUB_USERNAME }}/n.e.k.o:${VERSION}-standard-linux-amd64 \ | |
| ${{ secrets.DOCKERHUB_USERNAME }}/n.e.k.o:${VERSION}-standard-linux-arm64 | |
| - name: Create and push CI short tags - full (DockerHub) | |
| if: needs.calculate-version.outputs.is_main_commit == 'true' && needs.calculate-version.outputs.skip_dockerhub != 'true' && steps.check_dockerhub.outputs.has_credentials == 'true' | |
| run: | | |
| VERSION=${{ needs.calculate-version.outputs.image_version }} | |
| # DockerHub - ci-full (without hash) | |
| docker buildx imagetools create \ | |
| -t ${{ secrets.DOCKERHUB_USERNAME }}/n.e.k.o:ci-full \ | |
| ${{ secrets.DOCKERHUB_USERNAME }}/n.e.k.o:${VERSION}-full-linux-amd64 \ | |
| ${{ secrets.DOCKERHUB_USERNAME }}/n.e.k.o:${VERSION}-full-linux-arm64 | |
| - name: Create and push PR short tags - standard (GHCR) | |
| if: github.event_name == 'pull_request' && needs.build-standard.outputs.skipped != 'true' | |
| run: | | |
| VERSION=${{ needs.calculate-version.outputs.image_version }} | |
| # GHCR - pr-ci-standard (without PR number) | |
| docker buildx imagetools create \ | |
| -t ghcr.io/${{ env.IMAGE_NAME }}:pr-ci-standard \ | |
| ghcr.io/${{ env.IMAGE_NAME }}:${VERSION}-standard-linux-amd64 \ | |
| ghcr.io/${{ env.IMAGE_NAME }}:${VERSION}-standard-linux-arm64 | |
| - name: Create and push PR short tags - full (GHCR) | |
| if: github.event_name == 'pull_request' | |
| run: | | |
| VERSION=${{ needs.calculate-version.outputs.image_version }} | |
| # GHCR - pr-ci-full (without PR number) | |
| docker buildx imagetools create \ | |
| -t ghcr.io/${{ env.IMAGE_NAME }}:pr-ci-full \ | |
| ghcr.io/${{ env.IMAGE_NAME }}:${VERSION}-full-linux-amd64 \ | |
| ghcr.io/${{ env.IMAGE_NAME }}:${VERSION}-full-linux-arm64 | |
| - name: Create and push latest manifests - standard (GHCR) | |
| if: github.event_name != 'pull_request' && needs.calculate-version.outputs.is_main_commit != 'true' && needs.build-standard.outputs.skipped != 'true' | |
| run: | | |
| VERSION=${{ needs.calculate-version.outputs.image_version }} | |
| # GHCR - latest (traditional alias pointing to standard) | |
| docker buildx imagetools create \ | |
| -t ghcr.io/${{ env.IMAGE_NAME }}:latest \ | |
| ghcr.io/${{ env.IMAGE_NAME }}:${VERSION}-standard-linux-amd64 \ | |
| ghcr.io/${{ env.IMAGE_NAME }}:${VERSION}-standard-linux-arm64 | |
| # GHCR - latest-standard | |
| docker buildx imagetools create \ | |
| -t ghcr.io/${{ env.IMAGE_NAME }}:latest-standard \ | |
| ghcr.io/${{ env.IMAGE_NAME }}:${VERSION}-standard-linux-amd64 \ | |
| ghcr.io/${{ env.IMAGE_NAME }}:${VERSION}-standard-linux-arm64 | |
| - name: Create and push latest manifests - full (GHCR) | |
| if: github.event_name != 'pull_request' && needs.calculate-version.outputs.is_main_commit != 'true' | |
| run: | | |
| VERSION=${{ needs.calculate-version.outputs.image_version }} | |
| # GHCR - latest-full | |
| docker buildx imagetools create \ | |
| -t ghcr.io/${{ env.IMAGE_NAME }}:latest-full \ | |
| ghcr.io/${{ env.IMAGE_NAME }}:${VERSION}-full-linux-amd64 \ | |
| ghcr.io/${{ env.IMAGE_NAME }}:${VERSION}-full-linux-arm64 | |
| - name: Create and push latest manifests - standard (DockerHub) | |
| if: github.event_name != 'pull_request' && needs.calculate-version.outputs.is_main_commit != 'true' && needs.build-standard.outputs.skipped != 'true' && needs.calculate-version.outputs.skip_dockerhub != 'true' && steps.check_dockerhub.outputs.has_credentials == 'true' | |
| run: | | |
| VERSION=${{ needs.calculate-version.outputs.image_version }} | |
| # DockerHub - latest (traditional alias pointing to standard) | |
| docker buildx imagetools create \ | |
| -t ${{ secrets.DOCKERHUB_USERNAME }}/n.e.k.o:latest \ | |
| ${{ secrets.DOCKERHUB_USERNAME }}/n.e.k.o:${VERSION}-standard-linux-amd64 \ | |
| ${{ secrets.DOCKERHUB_USERNAME }}/n.e.k.o:${VERSION}-standard-linux-arm64 | |
| # DockerHub - latest-standard | |
| docker buildx imagetools create \ | |
| -t ${{ secrets.DOCKERHUB_USERNAME }}/n.e.k.o:latest-standard \ | |
| ${{ secrets.DOCKERHUB_USERNAME }}/n.e.k.o:${VERSION}-standard-linux-amd64 \ | |
| ${{ secrets.DOCKERHUB_USERNAME }}/n.e.k.o:${VERSION}-standard-linux-arm64 | |
| - name: Create and push latest manifests - full (DockerHub) | |
| if: github.event_name != 'pull_request' && needs.calculate-version.outputs.is_main_commit != 'true' && needs.calculate-version.outputs.skip_dockerhub != 'true' && steps.check_dockerhub.outputs.has_credentials == 'true' | |
| run: | | |
| VERSION=${{ needs.calculate-version.outputs.image_version }} | |
| # DockerHub - latest-full | |
| docker buildx imagetools create \ | |
| -t ${{ secrets.DOCKERHUB_USERNAME }}/n.e.k.o:latest-full \ | |
| ${{ secrets.DOCKERHUB_USERNAME }}/n.e.k.o:${VERSION}-full-linux-amd64 \ | |
| ${{ secrets.DOCKERHUB_USERNAME }}/n.e.k.o:${VERSION}-full-linux-arm64 |