diff --git a/.github/workflows/release-evm.yaml b/.github/workflows/release-evm.yaml index 902c7acb3..fbd5bb988 100644 --- a/.github/workflows/release-evm.yaml +++ b/.github/workflows/release-evm.yaml @@ -1,63 +1,15 @@ -name: Release +name: Release EVM -## workflow will trigger on below condition, -## except image release that have jobs condition to trigger only on tagging on: workflow_dispatch: push: tags: - - 'evm/v*.*.*' - -defaults: - run: - shell: bash - -env: - REGISTRY: ghcr.io - IMAGE_NAME_PREFIX: ${{ github.repository }} + - 'v*.*.*' jobs: - build-evm: - name: Docker Image (EVM) - if: startsWith(github.ref, 'refs/tags/evm/v') - runs-on: namespace-profile-linux-8vcpu-16gb-cached - # Add "id-token" with the intended permissions. - permissions: - contents: read - id-token: write - packages: write - steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Install and configure Namespace CLI - uses: namespacelabs/nscloud-setup@v0 - - name: Configure Namespace powered Buildx - uses: namespacelabs/nscloud-setup-buildx-action@v0 - - name: Docker - Auth to Github Container Registry - uses: docker/login-action@v3 - with: - registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - name: Extract semver from tag - id: semver - run: | - echo "tag=$(echo ${GITHUB_REF#refs/tags/evm/})" >> $GITHUB_OUTPUT - - name: Extract Docker metadata - id: meta - uses: docker/metadata-action@v5 - with: - images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_PREFIX }}-evm - tags: | - type=semver,pattern={{version}},value=${{ steps.semver.outputs.tag }} - type=semver,pattern={{major}}.{{minor}},value=${{ steps.semver.outputs.tag }} - type=sha - - name: Build and push - uses: docker/build-push-action@v5 - with: - context: . - file: ./evm/Dockerfile - platforms: linux/amd64,linux/arm64 - push: true - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} + build: + if: ${{ !contains(github.event.head_commit.message, '[skip ci]') }} + uses: ./.github/workflows/templates/docker-build.yaml + with: + component: evm + dockerfile: ./evm/Dockerfile diff --git a/.github/workflows/release-nakama.yaml b/.github/workflows/release-nakama.yaml index 1e682cc3b..9d11922c7 100644 --- a/.github/workflows/release-nakama.yaml +++ b/.github/workflows/release-nakama.yaml @@ -1,82 +1,15 @@ -name: Release +name: Release Nakama -## workflow will trigger on below condition, -## except image release that have jobs condition to trigger only on tagging on: workflow_dispatch: push: tags: - - 'relay/nakama/v*.*.*' - -defaults: - run: - shell: bash - -env: - REGISTRY: ghcr.io - IMAGE_NAME_PREFIX: ${{ github.repository }} + - 'v*.*.*' jobs: - build-nakama: - name: Docker Image (Nakama) - if: startsWith(github.ref, 'refs/tags/relay/nakama/v') - runs-on: namespace-profile-linux-8vcpu-16gb-cached - # Add "id-token" with the intended permissions. - permissions: - contents: read - id-token: write - packages: write - steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Install and configure Namespace CLI - uses: namespacelabs/nscloud-setup@v0 - - name: Configure Namespace powered Buildx - uses: namespacelabs/nscloud-setup-buildx-action@v0 - - name: Docker - Auth to Github Container Registry - uses: docker/login-action@v3 - with: - registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - name: Extract semver from tag - id: semver - run: | - echo "tag=$(echo ${GITHUB_REF#refs/tags/relay/nakama/})" >> $GITHUB_OUTPUT - - name: Extract Docker metadata - id: meta - uses: docker/metadata-action@v5 - with: - images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_PREFIX }}-nakama - tags: | - type=semver,pattern={{version}},value=${{ steps.semver.outputs.tag }} - type=semver,pattern={{major}}.{{minor}},value=${{ steps.semver.outputs.tag }} - type=sha - - name: Prepare arm64 tags - id: arm64_tags - run: | - TAGS="${{ steps.meta.outputs.tags }}" - TAGS_ARM64="$(echo "$TAGS" | grep -v 'sha-' | sed 's/$/-arm64/g')" - echo "tags<> $GITHUB_OUTPUT - echo "$TAGS_ARM64" >> $GITHUB_OUTPUT - echo "EOF" >> $GITHUB_OUTPUT - - name: Build and push - uses: docker/build-push-action@v5 - with: - context: . - file: ./relay/nakama/Dockerfile - target: nakama - platforms: linux/amd64 - push: true - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} - - name: Build and push (linux/arm64) - uses: docker/build-push-action@v5 - with: - context: . - file: ./relay/nakama/Dockerfile - target: nakama-arm - platforms: linux/arm64 - push: true - tags: ${{ steps.arm64_tags.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }}-arm64 + build: + if: ${{ !contains(github.event.head_commit.message, '[skip ci]') }} + uses: ./.github/workflows/templates/docker-build.yaml + with: + component: nakama + dockerfile: ./relay/nakama/Dockerfile diff --git a/.github/workflows/templates/docker-build.yaml b/.github/workflows/templates/docker-build.yaml new file mode 100644 index 000000000..a6d6537ae --- /dev/null +++ b/.github/workflows/templates/docker-build.yaml @@ -0,0 +1,55 @@ +name: Docker Build Template + +on: + workflow_call: + inputs: + component: + required: true + type: string + dockerfile: + required: true + type: string + platforms: + required: false + type: string + default: 'linux/amd64,linux/arm64' + +env: + REGISTRY: ghcr.io + IMAGE_NAME_PREFIX: ${{ github.repository }} + +jobs: + build: + runs-on: namespace-profile-linux-8vcpu-16gb-cached + permissions: + contents: read + id-token: write + packages: write + steps: + - uses: actions/checkout@v4 + - uses: namespacelabs/nscloud-setup@v0 + - uses: namespacelabs/nscloud-setup-buildx-action@v0 + - uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - id: semver + run: | + echo "tag=$(echo ${GITHUB_REF#refs/tags/v})" >> $GITHUB_OUTPUT + - uses: docker/metadata-action@v5 + id: meta + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_PREFIX }}-${{ inputs.component }} + tags: | + type=semver,pattern={{version}},value=${{ steps.semver.outputs.tag }} + type=semver,pattern={{major}}.{{minor}},value=${{ steps.semver.outputs.tag }} + type=sha + - uses: docker/build-push-action@v5 + with: + context: . + file: ${{ inputs.dockerfile }} + platforms: ${{ inputs.platforms }} + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} diff --git a/docs/ci-cd-standards.md b/docs/ci-cd-standards.md new file mode 100644 index 000000000..5c02c848f --- /dev/null +++ b/docs/ci-cd-standards.md @@ -0,0 +1,58 @@ +# CI/CD Standards + +## Versioning +- All services use semantic versioning +- Tags follow pattern: v{major}.{minor}.{patch} +- Component names included in image tags + +## Multi-architecture Support +- All services support linux/amd64,linux/arm64 +- Uses Docker Buildx for efficient multi-arch builds +- Platform-specific optimizations in Dockerfiles + +## Container Image Tagging +- Format: ghcr.io/{org}/{repo}-{component}:{version} +- Tags include: full version, major.minor, and commit SHA + +## Implementation Details + +### Tag Management +- Use `make tag-component COMPONENT=` for new releases +- Legacy format tags are maintained for backward compatibility +- Components: nakama, evm, cardinal, sign + +### Docker Build Process +- Shared workflow template in `.github/workflows/templates/docker-build.yaml` +- Automated builds triggered by version tags +- Multi-architecture images built using Docker Buildx +- Images pushed to GitHub Container Registry (ghcr.io) + +### Release Process +1. Create a new version tag: + ```bash + make tag-component COMPONENT= + ``` +2. CI/CD pipeline automatically: + - Builds multi-arch images + - Tags images appropriately + - Pushes to container registry + +### Examples + +Tag Format: +``` +v1.2.3 # Full version tag +ghcr.io/org/repo-nakama:1.2.3 # Full version image +ghcr.io/org/repo-nakama:1.2 # Minor version image +ghcr.io/org/repo-nakama:sha-abc123 # Commit SHA image +``` + +Multi-arch Support: +```dockerfile +FROM --platform=$TARGETPLATFORM base-image:tag +``` + +### Migration Notes +- Legacy tag format (`component/v*.*.*`) remains supported +- New standardized format (`v*.*.*`) preferred for all new releases +- Component information moved from tag prefix to image name suffix diff --git a/evm/Dockerfile b/evm/Dockerfile index 585a754d1..288a00693 100644 --- a/evm/Dockerfile +++ b/evm/Dockerfile @@ -1,7 +1,10 @@ ################################ # Build Image ################################ -FROM golang:1.22.1-bullseye AS build +FROM --platform=$TARGETPLATFORM golang:1.22.1-bullseye AS build + +ARG TARGETPLATFORM +ARG BUILDPLATFORM WORKDIR /go/src/app/ @@ -21,7 +24,7 @@ RUN CGO_ENABLED=1 make install # Binary will be in /go/bin/world-evm ################################ # Runtime Image ################################ -FROM ubuntu:18.04 AS runtime +FROM --platform=$TARGETPLATFORM ubuntu:18.04 AS runtime # Expose ports needed by the World EVM EXPOSE 26656 26657 1317 9090 8546 8545 9601 diff --git a/makefiles/tag.mk b/makefiles/tag.mk index eaa7fef13..25894f222 100644 --- a/makefiles/tag.mk +++ b/makefiles/tag.mk @@ -1,7 +1,7 @@ # Use PWD instead of CURDIR for better cross-platform compatibility ROOT_DIR := $(shell pwd) -.PHONY: tag tag-cardinal tag-sign tag-nakama +.PHONY: tag tag-cardinal tag-sign tag-nakama tag-component # scripts/tag identifies the most current version based on git tags, makes # a best-guess about the next logical version number, applies the tag to @@ -9,11 +9,20 @@ ROOT_DIR := $(shell pwd) tag: @bash "$(ROOT_DIR)/scripts/tag.sh" +# Generic component tagging target +tag-component: + @test -n "$(COMPONENT)" || (echo "Error: COMPONENT variable is required" && exit 1) + @$(MAKE) tag TAG_PREFIX=v COMPONENT=$(COMPONENT) + +# Legacy format targets that create both old and new format tags tag-cardinal: @$(MAKE) tag TAG_PREFIX=cardinal/v + @$(MAKE) tag-component COMPONENT=cardinal tag-sign: @$(MAKE) tag TAG_PREFIX=sign/v + @$(MAKE) tag-component COMPONENT=sign tag-nakama: @$(MAKE) tag TAG_PREFIX=relay/nakama/v + @$(MAKE) tag-component COMPONENT=nakama diff --git a/relay/nakama/Dockerfile b/relay/nakama/Dockerfile index cb1a072fd..3abc18f88 100644 --- a/relay/nakama/Dockerfile +++ b/relay/nakama/Dockerfile @@ -1,4 +1,4 @@ -FROM heroiclabs/nakama-pluginbuilder:3.25.0 AS builder +FROM --platform=$TARGETPLATFORM heroiclabs/nakama-pluginbuilder:3.25.0 AS builder ENV GO111MODULE on ENV CGO_ENABLED 1 @@ -12,21 +12,7 @@ RUN go mod download RUN go build --trimpath --buildmode=plugin -o ./plugin.so -FROM heroiclabs/nakama-pluginbuilder:3.25.0-arm AS builder-arm - -ENV GO111MODULE on -ENV CGO_ENABLED 1 - -WORKDIR /nakama/plugin - -COPY relay/nakama . -COPY sign /sign - -RUN go mod download - -RUN go build --trimpath --buildmode=plugin -o ./plugin.so - -FROM heroiclabs/nakama:3.25.0 AS nakama +FROM --platform=$TARGETPLATFORM heroiclabs/nakama:3.25.0 RUN apt-get -y update && \ apt-get -y install --no-install-recommends curl && \ @@ -34,8 +20,3 @@ RUN apt-get -y update && \ COPY --from=builder /nakama/plugin/plugin.so /nakama/data/modules/ COPY relay/nakama/local.yml /nakama/data/ - -FROM heroiclabs/nakama:3.25.0-arm AS nakama-arm - -COPY --from=builder-arm /nakama/plugin/plugin.so /nakama/data/modules/ -COPY relay/nakama/local.yml /nakama/data/