# CI/CD Pipeline for hmac-file-server
name: CI/CD

on:
  push:
    branches: [main, master, develop]
    tags: ['v*']
  pull_request:
    branches: [main, master]

env:
  GITEA_URL: https://git.uuxo.net

jobs:
  test:
    name: Test
    runs-on: ubuntu-latest
    container:
      image: golang:1.24-bookworm
    steps:
      - name: Install git
        run: apt-get update && apt-get install -y git ca-certificates

      - name: Checkout code
        run: |
          git config --global --add safe.directory "$GITHUB_WORKSPACE"
          git clone --depth 1 --branch ${GITHUB_REF_NAME} ${{ env.GITEA_URL }}/${GITHUB_REPOSITORY}.git .

      - name: Download dependencies
        run: go mod download

      - name: Run tests with race detection
        env:
          GOMAXPROCS: 8
        run: go test -race -coverprofile=coverage.out -covermode=atomic ./...

      - name: Generate coverage report
        run: |
          go tool cover -func=coverage.out
          go tool cover -html=coverage.out -o coverage.html

  lint:
    name: Lint
    runs-on: ubuntu-latest
    container:
      image: golang:1.24-bookworm
    steps:
      - name: Install git
        run: apt-get update && apt-get install -y git ca-certificates

      - name: Checkout code
        run: |
          git config --global --add safe.directory "$GITHUB_WORKSPACE"
          git clone --depth 1 --branch ${GITHUB_REF_NAME} ${{ env.GITEA_URL }}/${GITHUB_REPOSITORY}.git .

      - name: Install golangci-lint
        run: go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.62.2

      - name: Run golangci-lint
        env:
          GOMAXPROCS: 8
        run: golangci-lint run --timeout=5m ./...

  build:
    name: Build (${{ matrix.goos }}-${{ matrix.goarch }})
    runs-on: ubuntu-latest
    needs: [test, lint]
    container:
      image: golang:1.24-bookworm
    strategy:
      max-parallel: 8
      matrix:
        goos: [linux, darwin]
        goarch: [amd64, arm64]
    steps:
      - name: Install git
        run: apt-get update && apt-get install -y git ca-certificates

      - name: Checkout code
        run: |
          git config --global --add safe.directory "$GITHUB_WORKSPACE"
          git clone --depth 1 --branch ${GITHUB_REF_NAME} ${{ env.GITEA_URL }}/${GITHUB_REPOSITORY}.git .

      - name: Build server binary
        env:
          GOOS: ${{ matrix.goos }}
          GOARCH: ${{ matrix.goarch }}
          CGO_ENABLED: 0
          GOMAXPROCS: 8
        run: |
          go build -ldflags="-s -w" -o dist/hmac-file-server-${{ matrix.goos }}-${{ matrix.goarch }} ./cmd/server/

      - name: Build monitor binary
        env:
          GOOS: ${{ matrix.goos }}
          GOARCH: ${{ matrix.goarch }}
          CGO_ENABLED: 0
          GOMAXPROCS: 8
        run: |
          go build -ldflags="-s -w" -o dist/hmac-monitor-${{ matrix.goos }}-${{ matrix.goarch }} ./cmd/monitor/

  sbom:
    name: Generate SBOM
    runs-on: ubuntu-latest
    needs: [test]
    container:
      image: golang:1.24-bookworm
    steps:
      - name: Install git
        run: apt-get update && apt-get install -y git ca-certificates

      - name: Checkout code
        run: |
          git config --global --add safe.directory "$GITHUB_WORKSPACE"
          git clone --depth 1 --branch ${GITHUB_REF_NAME} ${{ env.GITEA_URL }}/${GITHUB_REPOSITORY}.git .

      - name: Install Syft
        run: curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin

      - name: Generate SBOM
        run: |
          syft . -o spdx-json=sbom-spdx.json
          syft . -o cyclonedx-json=sbom-cyclonedx.json

  docker:
    name: Build & Push Docker Image
    runs-on: ubuntu-latest
    needs: [test, lint]
    if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/'))
    container:
      image: docker:24-cli
      options: --privileged
    services:
      docker:
        image: docker:24-dind
        options: --privileged
    steps:
      - name: Install dependencies
        run: apk add --no-cache git curl

      - name: Checkout code
        run: |
          git config --global --add safe.directory "$GITHUB_WORKSPACE"
          git clone --depth 1 --branch ${GITHUB_REF_NAME} ${{ env.GITEA_URL }}/${GITHUB_REPOSITORY}.git .

      - name: Set up Docker Buildx
        run: |
          docker buildx create --use --name builder --driver docker-container
          docker buildx inspect --bootstrap

      - name: Login to Gitea Registry
        run: |
          echo "${{ secrets.REGISTRY_TOKEN }}" | docker login git.uuxo.net -u "${{ secrets.REGISTRY_USER }}" --password-stdin

      - name: Build and push
        run: |
          # Determine tags
          if [[ "${GITHUB_REF}" == refs/tags/* ]]; then
            VERSION=${GITHUB_REF#refs/tags/}
            TAGS="-t git.uuxo.net/uuxo/hmac-file-server:${VERSION} -t git.uuxo.net/uuxo/hmac-file-server:latest"
          else
            TAGS="-t git.uuxo.net/uuxo/hmac-file-server:${GITHUB_SHA::8} -t git.uuxo.net/uuxo/hmac-file-server:main"
          fi
          
          docker buildx build \
            --platform linux/amd64,linux/arm64 \
            --file Dockerfile.multiarch \
            --push \
            ${TAGS} \
            .

  release:
    name: Release
    runs-on: ubuntu-latest
    needs: [test, lint, build]
    if: startsWith(github.ref, 'refs/tags/v')
    container:
      image: golang:1.24-bookworm
    steps:
      - name: Install tools
        run: |
          apt-get update && apt-get install -y git ca-certificates
          curl -sSfL https://github.com/goreleaser/goreleaser/releases/download/v2.4.8/goreleaser_Linux_x86_64.tar.gz | tar xz -C /usr/local/bin goreleaser
          curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin

      - name: Checkout code
        run: |
          git config --global --add safe.directory "$GITHUB_WORKSPACE"
          git clone --branch ${GITHUB_REF_NAME} ${{ env.GITEA_URL }}/${GITHUB_REPOSITORY}.git .
          git fetch --tags

      - name: Run goreleaser
        env:
          GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
        run: goreleaser release --clean
