on:
  push:
    branches:
      - "develop"
      - "feature/update**"
      - "feature/server_esm**"
    paths-ignore:
      - "docs/**"
      - "bin/**"
    tags:
      - "v*"
  workflow_dispatch:

env:
  GHCR_REGISTRY: ghcr.io
  DOCKERHUB_REGISTRY: docker.io
  IMAGE_NAME: ${{ github.repository_owner }}/notes
  TEST_TAG: ${{ github.repository_owner }}/notes:test

permissions:
  contents: read
  packages: write

jobs:
  test_docker:
    name: Check Docker build
    runs-on: ubuntu-latest
    strategy:
      matrix:
        include:
          - dockerfile: Dockerfile.alpine
          - dockerfile: Dockerfile
    steps:
      - name: Checkout the repository
        uses: actions/checkout@v4
        
      - name: Set IMAGE_NAME to lowercase
        run: echo "IMAGE_NAME=${IMAGE_NAME,,}" >> $GITHUB_ENV
      - name: Set TEST_TAG to lowercase
        run: echo "TEST_TAG=${TEST_TAG,,}" >> $GITHUB_ENV

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

      - name: Set up node & dependencies
        uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: "npm"
      
      - run: npm ci
      
      - name: Run the TypeScript build
        run: npx tsc
      
      - name: Create server-package.json
        run: cat package.json | grep -v electron > server-package.json

      - name: Build and export to Docker
        uses: docker/build-push-action@v6
        with:
          context: .
          file: ${{ matrix.dockerfile }}
          load: true
          tags: ${{ env.TEST_TAG }}
          cache-from: type=gha
          cache-to: type=gha,mode=max
      
      - name: Validate container run output
        run: |
          CONTAINER_ID=$(docker run -d --log-driver=journald --rm --name trilium_local ${{ env.TEST_TAG }})
          echo "Container ID: $CONTAINER_ID"
      
      - name: Wait for the healthchecks to pass
        uses: stringbean/docker-healthcheck-action@v1
        with:
          container: trilium_local
          wait-time: 50
          require-status: running
          require-healthy: true

      # Print the entire log of the container thus far, regardless if the healthcheck failed or succeeded
      - name: Print entire log
        if: always()
        run: |
          journalctl -u docker CONTAINER_NAME=trilium_local --no-pager

  build:
    name: Build Docker images
    runs-on: ubuntu-latest
    needs:
      - test_docker
    permissions:
      contents: read
      packages: write
      attestations: write
      id-token: write
    strategy:
      fail-fast: false
      matrix:
        include:
          - dockerfile: Dockerfile.alpine
            platform: linux/amd64
          - dockerfile: Dockerfile
            platform: linux/arm64
          - dockerfile: Dockerfile
            platform: linux/arm/v7
    steps:
      - name: Prepare
        run: |
          platform=${{ matrix.platform }}
          echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
      - name: Set IMAGE_NAME to lowercase
        run: echo "IMAGE_NAME=${IMAGE_NAME,,}" >> $GITHUB_ENV
      - name: Set TEST_TAG to lowercase
        run: echo "TEST_TAG=${TEST_TAG,,}" >> $GITHUB_ENV


      - name: Checkout repository
        uses: actions/checkout@v4
      - name: Docker meta
        id: meta
        uses: docker/metadata-action@v4
        with:
          images: |
            ${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }}
            ${{ env.DOCKERHUB_REGISTRY }}/${{ env.IMAGE_NAME }}
          tags: |
            type=ref,event=branch
            type=ref,event=tag
            type=sha
      
      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3
      
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3
      

      - name: Set up node & dependencies
        uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: "npm"
      - run: npm ci
      - name: Run the TypeScript build
        run: npx tsc
      - name: Create server-package.json
        run: cat package.json | grep -v electron > server-package.json

      - name: Login to GHCR
        uses: docker/login-action@v2
        with:
          registry: ${{ env.GHCR_REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      
      - name: Login to DockerHub
        uses: docker/login-action@v2
        with:
          registry: ${{ env.DOCKERHUB_REGISTRY }}
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}
      
      - name: Build and push by digest
        id: build
        uses: docker/build-push-action@v6
        with:
          context: .
          file: ${{ matrix.dockerfile }}
          platforms: ${{ matrix.platform }}
          labels: ${{ steps.meta.outputs.labels }}
          outputs: type=image,name=${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }},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@v4
        with:
          name: digests-${{ env.PLATFORM_PAIR }}
          path: /tmp/digests/*
          if-no-files-found: error
          retention-days: 1

  merge:
    name: Merge manifest lists
    runs-on: ubuntu-latest
    needs:
      - build
    steps:
      - name: Download digests
        uses: actions/download-artifact@v4
        with:
          path: /tmp/digests
          pattern: digests-*
          merge-multiple: true
      - name: Set IMAGE_NAME to lowercase
        run: echo "IMAGE_NAME=${IMAGE_NAME,,}" >> $GITHUB_ENV
      - name: Set TEST_TAG to lowercase
        run: echo "TEST_TAG=${TEST_TAG,,}" >> $GITHUB_ENV

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3
      
      - name: Docker meta
        id: meta
        uses: docker/metadata-action@v4
        with:
          images: |
            ${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }}
            ${{ env.DOCKERHUB_REGISTRY }}/${{ env.IMAGE_NAME }}
      
      - name: Login to GHCR
        uses: docker/login-action@v2
        with:
          registry: ${{ env.GHCR_REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      
      - name: Login to DockerHub
        uses: docker/login-action@v2
        with:
          registry: ${{ env.DOCKERHUB_REGISTRY }}
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}
      
      - name: Create manifest list and push
        working-directory: /tmp/digests
        run: |
          # Extract the branch or tag name from the ref
          REF_NAME=$(echo "${GITHUB_REF}" | sed 's/refs\/heads\///' | sed 's/refs\/tags\///')

          # Create and push the manifest list with both the branch/tag name and the commit SHA
          docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
            -t ${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }}:${REF_NAME} \
            $(printf '${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }}@sha256:%s ' *)
          
          docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
            -t ${{ env.DOCKERHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${REF_NAME} \
            $(printf '${{ env.DOCKERHUB_REGISTRY }}/${{ env.IMAGE_NAME }}@sha256:%s ' *)
      
      - name: Inspect image
        run: |
          docker buildx imagetools inspect ${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.meta.outputs.version }}
          docker buildx imagetools inspect ${{ env.DOCKERHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.meta.outputs.version }}
