name: Build Stable Image

on:
  push:
    branches:
      - "release/**"
    tags:
      - "v*.*.*"

jobs:
  prepare:
    runs-on: ubuntu-latest
    outputs:
      version: ${{ steps.version.outputs.version }}
    steps:
      - name: Extract version
        id: version
        run: |
          if [[ "$GITHUB_REF_TYPE" == "tag" ]]; then
            echo "version=${GITHUB_REF_NAME#v}" >> $GITHUB_OUTPUT
          else
            echo "version=${GITHUB_REF_NAME#release/}" >> $GITHUB_OUTPUT
          fi

  build-frontend:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6

      - uses: pnpm/action-setup@v4.2.0
        with:
          version: 10
      - uses: actions/setup-node@v6
        with:
          node-version: "22"
          cache: pnpm
          cache-dependency-path: "web/pnpm-lock.yaml"
      - name: Get pnpm store directory
        id: pnpm-cache
        shell: bash
        run: echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT
      - name: Setup pnpm cache
        uses: actions/cache@v5
        with:
          path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
          key: ${{ runner.os }}-pnpm-store-${{ hashFiles('web/pnpm-lock.yaml') }}
          restore-keys: ${{ runner.os }}-pnpm-store-
      - run: pnpm install --frozen-lockfile
        working-directory: web
      - name: Run frontend build
        run: pnpm release
        working-directory: web

      - name: Upload frontend artifacts
        uses: actions/upload-artifact@v6
        with:
          name: frontend-dist
          path: server/router/frontend/dist
          retention-days: 1

  build-push:
    needs: [prepare, build-frontend]
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write
    strategy:
      fail-fast: false
      matrix:
        platform:
          - linux/amd64
          - linux/arm/v7
          - linux/arm64
    steps:
      - uses: actions/checkout@v6

      - name: Download frontend artifacts
        uses: actions/download-artifact@v7
        with:
          name: frontend-dist
          path: server/router/frontend/dist

      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Login to Docker Hub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKER_HUB_USERNAME }}
          password: ${{ secrets.DOCKER_HUB_TOKEN }}

      - name: Login to GitHub Container Registry
        uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ github.token }}

      - name: Build and push by digest
        id: build
        uses: docker/build-push-action@v6
        with:
          context: .
          file: ./scripts/Dockerfile
          platforms: ${{ matrix.platform }}
          cache-from: type=gha,scope=build-${{ matrix.platform }}
          cache-to: type=gha,mode=max,scope=build-${{ matrix.platform }}
          outputs: type=image,name=neosmemo/memos,push-by-digest=true,name-canonical=true,push=true

      - 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@v6
        with:
          name: digests-${{ strategy.job-index }}
          path: /tmp/digests/*
          if-no-files-found: error
          retention-days: 1

  merge:
    needs: [prepare, build-push]
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write
    steps:
      - name: Download digests
        uses: actions/download-artifact@v7
        with:
          pattern: digests-*
          merge-multiple: true
          path: /tmp/digests

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Docker meta
        id: meta
        uses: docker/metadata-action@v5
        with:
          images: |
            neosmemo/memos
            ghcr.io/usememos/memos
          tags: |
            type=semver,pattern={{version}},value=${{ needs.prepare.outputs.version }}
            type=semver,pattern={{major}}.{{minor}},value=${{ needs.prepare.outputs.version }}
            type=raw,value=stable
          flavor: |
            latest=false
          labels: |
            org.opencontainers.image.version=${{ needs.prepare.outputs.version }}

      - name: Login to Docker Hub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKER_HUB_USERNAME }}
          password: ${{ secrets.DOCKER_HUB_TOKEN }}

      - name: Login to GitHub Container Registry
        uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ github.token }}

      - 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 'neosmemo/memos@sha256:%s ' *)
        env:
          DOCKER_METADATA_OUTPUT_JSON: ${{ steps.meta.outputs.json }}

      - name: Inspect images
        run: |
          docker buildx imagetools inspect neosmemo/memos:stable
          docker buildx imagetools inspect ghcr.io/usememos/memos:stable
