
name: deploy

on:
  workflow_dispatch:
  pull_request:
  push:
    branches:
      - main
      - stage/*
  release:
    types:
      - published

env:
  FORCE_COLOR: 3

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

jobs:
  build_sdist:
    name: Build SDist
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v6
        with:
          fetch-depth: 100
          fetch-tags: true


      - name: Install uv
        uses: astral-sh/setup-uv@v7
        with:
          python-version: "3.14"
          enable-cache: true
          cache-dependency-glob: "uv.lock"

      - name: Build SDist
        run: uv build --sdist

      - name: Check metadata
        run: uv tool run twine check dist/*

      - uses: actions/upload-artifact@v4
        with:
          name: cibw-sdist
          path: dist/*.tar.gz


  # Split wheel builds into separate jobs so Docker can depend only on Linux
  build_wheels_linux:
    name: Wheels on Linux
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v6
        with:
          fetch-depth: 100
          fetch-tags: true


      - uses: pypa/cibuildwheel@v3.3
        env:
          CIBW_ARCHS_LINUX: x86_64
          CIBW_MANYLINUX_X86_64_IMAGE: manylinux_2_28
          CIBW_MANYLINUX_AARCH64_IMAGE: manylinux_2_28
          CIBW_MANYLINUX_PYPY_X86_64_IMAGE: manylinux_2_28
          CIBW_MANYLINUX_PYPY_AARCH64_IMAGE: manylinux_2_28

      - name: Verify clean directory
        run: git diff --exit-code
        shell: bash

      - uses: actions/upload-artifact@v4
        with:
          name: cibw-wheels-ubuntu-latest
          path: wheelhouse/*.whl


  build_wheels_macos:
    name: Wheels on macOS
    runs-on: macos-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v6
        with:
          fetch-depth: 100
          fetch-tags: true

      - uses: pypa/cibuildwheel@v3.3
        env:
          CIBW_ARCHS_MACOS: x86_64 arm64

      - name: Verify clean directory
        run: git diff --exit-code
        shell: bash

      - uses: actions/upload-artifact@v4
        with:
          name: cibw-wheels-macos-latest
          path: wheelhouse/*.whl


  build_wheels_windows:
    name: Wheels on Windows
    runs-on: windows-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v6
        with:
          fetch-depth: 100
          fetch-tags: true

      - uses: pypa/cibuildwheel@v3.3
        env:
          CIBW_ARCHS_WINDOWS: AMD64
          CIBW_SKIP: "cp314t-*"  # Skip free-threaded Python (uses python314t.lib, not yet supported)

      - name: Verify clean directory
        run: git diff --exit-code
        shell: bash

      - uses: actions/upload-artifact@v4
        with:
          name: cibw-wheels-windows-latest
          path: wheelhouse/*.whl


  publish_wheels:
    name: Publish Wheels
    needs: [build_wheels_linux, build_wheels_macos, build_wheels_windows, build_sdist]
    runs-on: ubuntu-latest
    # Run even if some wheel builds failed (will publish whatever succeeded)
    if: |
      !cancelled() &&
      github.repository == 'atopile/atopile' &&
      (github.event_name == 'release' && github.event.action == 'published' || github.event_name == 'push' && github.ref == 'refs/heads/main')
    environment: pypi
    permissions:
      id-token: write
      attestations: write

    steps:
    - uses: actions/download-artifact@v4
      with:
        pattern: cibw-*
        merge-multiple: true
        path: dist

    - name: Generate artifact attestation for sdist and wheels
      uses: actions/attest-build-provenance@v2
      with:
        subject-path: "dist/*"

    - name: Publish to TestPyPI
      if: github.event_name != 'release'
      uses: pypa/gh-action-pypi-publish@release/v1
      with:
        repository-url: https://test.pypi.org/legacy/
        skip-existing: true
        verbose: true
        attestations: false

    - name: Publish to PyPI
      if: github.event_name == 'release' && github.event.action == 'published'
      uses: pypa/gh-action-pypi-publish@release/v1
      with:
        attestations: true


  docker:
    name: Docker Build and Publish
    runs-on: blacksmith-4vcpu-ubuntu-2404
    # Only depends on Linux wheels (that's all the Docker container needs)
    needs: build_wheels_linux
    # Run even if other wheel builds failed, as long as Linux succeeded and not cancelled
    if: |
      !cancelled() &&
      needs.build_wheels_linux.result == 'success' &&
      github.repository == 'atopile/atopile' &&
      (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'atopile/atopile')

    strategy:
      matrix:
        include:
          # @kicad10
          - dockerfile: "Dockerfile.kicad"
            image: "atopile-kicad"
            kicad_version: "9.0"
            tag_suffix: "-kicad9"

          # default
          - dockerfile: "Dockerfile.kicad"
            image: "atopile-kicad"
            kicad_version: "9.0"
            tag_suffix: ""

    # Sets the permissions granted to the `GITHUB_TOKEN`
    # for the actions in this job.
    permissions:
      contents: read
      packages: write

    steps:
      - uses: actions/checkout@v6

      - name: Download wheel artifacts
        uses: actions/download-artifact@v4
        with:
          pattern: cibw-*
          merge-multiple: true
          path: dist

      - name: Docker meta
        id: meta
        uses: docker/metadata-action@v5
        with:
          images: |
            ghcr.io/atopile/${{ matrix.image }}
          flavor: |
            latest=${{github.event_name == 'release' && github.event.action == 'published' && !github.event.release.prerelease && !github.event.release.draft && matrix.tag_suffix == ''}}
          tags: |
            type=ref,event=branch,suffix=${{ matrix.tag_suffix }}
            type=ref,event=pr,suffix=${{ matrix.tag_suffix }}
            type=semver,pattern={{version}},suffix=${{ matrix.tag_suffix }}
            type=semver,pattern={{major}}.{{minor}},suffix=${{ matrix.tag_suffix }}
            type=sha,suffix=${{ matrix.tag_suffix }}

      - name: Log in to the Container registry
        uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Set up Docker Buildx
        uses: useblacksmith/setup-docker-builder@v1

      - name: Build and push
        uses: useblacksmith/build-push-action@v2
        with:
          context: .
          file: dockerfiles/${{ matrix.dockerfile }}
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}
          build-args: |
            KICAD_VERSION=${{ matrix.kicad_version }}
