name: Publish CLI & Engine
on:
  push:
    branches: ["main"]
    tags: ["v**"]

  # Run tests in a PR when an SDK has a default CLI version bump
  pull_request:
    types:
      - opened
      - synchronize
      - reopened
      - ready_for_review
    paths:
      - sdk/go/internal/engineconn/version.gen.go
      - sdk/python/src/dagger/_engine/_version.py
      - sdk/typescript/provisioning/default.ts
      - sdk/rust/src/crates/dagger-sdk/src/core/mod.rs

jobs:
  publish:
    if: ${{ github.repository == 'dagger/dagger' && github.event_name == 'push' }}
    # Use our own Dagger runner when running in the dagger/dagger repo (including PRs)
    runs-on: dagger-runner-16c-64g
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-go@v4
        with:
          go-version: "1.21"
          cache-dependency-path: "internal/mage/go.sum"
      - name: "Publish Engine & CLI"
        run: |
          ./hack/make dagger:publish ${{ github.ref_name }}
        env:
          GH_ORG_NAME: ${{ vars.GH_ORG_NAME }}
          GITHUB_TOKEN: ${{ secrets.RELEASE_DAGGER_CI_TOKEN }}
          DAGGER_ENGINE_IMAGE: ${{ secrets.RELEASE_DAGGER_ENGINE_IMAGE }}
          AWS_ACCESS_KEY_ID: ${{ secrets.RELEASE_AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.RELEASE_AWS_SECRET_ACCESS_KEY }}
          AWS_REGION: ${{ secrets.RELEASE_AWS_REGION }}
          AWS_BUCKET: ${{ secrets.RELEASE_AWS_BUCKET }}
          ARTEFACTS_FQDN: ${{ secrets.RELEASE_FQDN }}
          GORELEASER_KEY: ${{ secrets.GORELEASER_PRO_LICENSE_KEY }}
          DAGGER_ENGINE_IMAGE_REGISTRY: ghcr.io
          DAGGER_ENGINE_IMAGE_USERNAME: ${{ github.actor }}
          DAGGER_ENGINE_IMAGE_PASSWORD: ${{ secrets.RELEASE_DAGGER_CI_TOKEN }}
          _EXPERIMENTAL_DAGGER_RUNNER_HOST: "unix:///var/run/buildkit/buildkitd.sock"
      - name: "Bump SDK Engine Dependencies"
        uses: peter-evans/create-pull-request@v3
        if: github.ref_name != 'main'
        with:
          add-paths: ./sdk/
          committer: Dagger CI <hello@dagger.io>
          author: Dagger CI <hello@dagger.io>
          commit-message: "sdk: Bump engine dependency to ${{ github.ref_name }}"
          signoff: true
          base: main
          title: "sdk: Bump engine dependency to ${{ github.ref_name }}"
          body: |
            This PR was auto-generated.
          delete-branch: true
          branch: bump-engine
          draft: true

  scan-engine:
    runs-on: ubuntu-latest
    name: "Scan Engine Image for Vulnerabilities"
    needs: [publish]
    # only run this on push events, not in PRs (since we only publish images during pushes)
    if: github.event_name == 'push' && github.repository == 'dagger/dagger'
    steps:
      - uses: aquasecurity/trivy-action@0.11.2
        with:
          image-ref: ${{ secrets.RELEASE_DAGGER_ENGINE_IMAGE }}:main
          format: "json"
          exit-code: "1"
          severity: "CRITICAL,HIGH"

  test-provision-macos:
    name: "Test SDK Provision / macos"
    # We want to test the SDKs in a CLI dependency bump PR, in which case publish
    # has to be skipped, AND after every push to main/tags, in which case publish
    # must run first. This is unfortunately quite annoying to express in yaml...
    # https://github.com/actions/runner/issues/491#issuecomment-850884422
    needs: [publish]
    if: |
      always() &&
      github.repository == 'dagger/dagger' &&
      (needs.publish.result == 'success' || needs.publish.result == 'skipped')
    runs-on: macos-latest
    steps:
      - name: "Set CLI Test URL"
        run: |
          if [ ${{ github.event_name }} == 'push' ]; then
            BASE_URL="https://${{ secrets.RELEASE_FQDN }}/dagger"
            if [ $GITHUB_REF_NAME == 'main' ]; then
              # this is a push to the main branch
              ARCHIVE_URL="${BASE_URL}/main/${GITHUB_SHA}/dagger_${GITHUB_SHA}_darwin_amd64.tar.gz"
              CHECKSUMS_URL="${BASE_URL}/main/${GITHUB_SHA}/checksums.txt"
              RUNNER_HOST="docker-image://${{ secrets.RELEASE_DAGGER_ENGINE_IMAGE }}:main"
            else
              # this is a tag push
              ARCHIVE_URL="${BASE_URL}/releases/${GITHUB_REF_NAME:1}/dagger_${GITHUB_REF_NAME}_darwin_amd64.tar.gz"
              CHECKSUMS_URL="${BASE_URL}/releases/${GITHUB_REF_NAME:1}/checksums.txt"
              RUNNER_HOST="docker-image://${{ secrets.RELEASE_DAGGER_ENGINE_IMAGE }}:${GITHUB_REF_NAME}"
            fi
            echo "_INTERNAL_DAGGER_TEST_CLI_URL=${ARCHIVE_URL}" >> $GITHUB_ENV
            echo "_INTERNAL_DAGGER_TEST_CLI_CHECKSUMS_URL=${CHECKSUMS_URL}" >> $GITHUB_ENV
            echo "_EXPERIMENTAL_DAGGER_RUNNER_HOST=${RUNNER_HOST}" >> $GITHUB_ENV
          fi
        shell: bash
      - name: "Install Docker"
        run: |
          echo "Install docker CLI..."
          brew install docker
          echo "Start Docker daemon via Colima..."
          echo "⚠️ Use mount-type 9p so that launched containers can chown: https://github.com/abiosoft/colima/issues/54#issuecomment-1250217077"
          colima start --mount-type 9p

      - uses: actions/checkout@v3

      - uses: actions/setup-go@v3
        with:
          go-version: "1.21"

      - name: "Test Go SDK"
        run: |
          cd sdk/go
          go test -v -run TestProvision ./...

      - uses: actions/setup-python@v4
        with:
          python-version: "3.11"
          cache: "pip"
          cache-dependency-path: "sdk/python/requirements.txt"
      - name: "Test Python SDK"
        run: |
          cd sdk/python
          pip install -r requirements.txt .
          pytest -xm provision

      - uses: actions/setup-node@v2
        with:
          node-version: 16

      - name: "Test TypeScript SDK"
        run: |
          cd sdk/typescript
          yarn install
          yarn test -g 'Automatic Provisioned CLI Binary'

      - name: "Setup Rust"
        uses: dtolnay/rust-toolchain@stable

      - name: "ALWAYS print engine logs - especially useful on failure"
        if: always()
        run: docker logs $(docker ps -q --filter name=dagger-engine)

      - name: "ALWAYS print kernel logs - especially useful on failure"
        if: always()
        run: sudo dmesg

  test-provision-go-linux:
    name: "Test SDK Provision / go / linux"
    needs: [publish]
    if: |
      always() &&
      github.repository == 'dagger/dagger' &&
      (needs.publish.result == 'success' || needs.publish.result == 'skipped')
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: "Set CLI Test URL"
        run: |
          if [ ${{ github.event_name }} == 'push' ]; then
            BASE_URL="https://${{ secrets.RELEASE_FQDN }}/dagger"
            if [ $GITHUB_REF_NAME == 'main' ]; then
              # this is a push to the main branch
              ARCHIVE_URL="${BASE_URL}/main/${GITHUB_SHA}/dagger_${GITHUB_SHA}_linux_amd64.tar.gz"
              CHECKSUMS_URL="${BASE_URL}/main/${GITHUB_SHA}/checksums.txt"
              RUNNER_HOST="docker-image://${{ secrets.RELEASE_DAGGER_ENGINE_IMAGE }}:main"
            else
              # this is a tag push
              ARCHIVE_URL="${BASE_URL}/releases/${GITHUB_REF_NAME:1}/dagger_${GITHUB_REF_NAME}_linux_amd64.tar.gz"
              CHECKSUMS_URL="${BASE_URL}/releases/${GITHUB_REF_NAME:1}/checksums.txt"
              RUNNER_HOST="docker-image://${{ secrets.RELEASE_DAGGER_ENGINE_IMAGE }}:${GITHUB_REF_NAME}"
            fi
            echo "_INTERNAL_DAGGER_TEST_CLI_URL=${ARCHIVE_URL}" >> $GITHUB_ENV
            echo "_INTERNAL_DAGGER_TEST_CLI_CHECKSUMS_URL=${CHECKSUMS_URL}" >> $GITHUB_ENV
            echo "_EXPERIMENTAL_DAGGER_RUNNER_HOST=${RUNNER_HOST}" >> $GITHUB_ENV
          fi
        shell: bash
      - uses: actions/setup-go@v3
        with:
          go-version: "1.21"
      - name: "Test Go SDK"
        run: |
          cd sdk/go
          go test -v -run TestProvision ./...
      - name: "ALWAYS print engine logs - especially useful on failure"
        if: always()
        run: docker logs $(docker ps -q --filter name=dagger-engine)
      - name: "ALWAYS print kernel logs - especially useful on failure"
        if: always()
        run: sudo dmesg

  test-provision-python-linux:
    name: "Test SDK Provision / python / linux"
    needs: [publish]
    if: |
      always() &&
      github.repository == 'dagger/dagger' &&
      (needs.publish.result == 'success' || needs.publish.result == 'skipped')
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: "Set CLI Test URL"
        run: |
          if [ ${{ github.event_name }} == 'push' ]; then
            BASE_URL="https://${{ secrets.RELEASE_FQDN }}/dagger"
            if [ $GITHUB_REF_NAME == 'main' ]; then
              # this is a push to the main branch
              ARCHIVE_URL="${BASE_URL}/main/${GITHUB_SHA}/dagger_${GITHUB_SHA}_linux_amd64.tar.gz"
              CHECKSUMS_URL="${BASE_URL}/main/${GITHUB_SHA}/checksums.txt"
              RUNNER_HOST="docker-image://${{ secrets.RELEASE_DAGGER_ENGINE_IMAGE }}:main"
            else
              # this is a tag push
              ARCHIVE_URL="${BASE_URL}/releases/${GITHUB_REF_NAME:1}/dagger_${GITHUB_REF_NAME}_linux_amd64.tar.gz"
              CHECKSUMS_URL="${BASE_URL}/releases/${GITHUB_REF_NAME:1}/checksums.txt"
              RUNNER_HOST="docker-image://${{ secrets.RELEASE_DAGGER_ENGINE_IMAGE }}:${GITHUB_REF_NAME}"
            fi
            echo "_INTERNAL_DAGGER_TEST_CLI_URL=${ARCHIVE_URL}" >> $GITHUB_ENV
            echo "_INTERNAL_DAGGER_TEST_CLI_CHECKSUMS_URL=${CHECKSUMS_URL}" >> $GITHUB_ENV
            echo "_EXPERIMENTAL_DAGGER_RUNNER_HOST=${RUNNER_HOST}" >> $GITHUB_ENV
          fi
        shell: bash
      - uses: actions/setup-python@v4
        with:
          python-version: "3.11"
          cache: "pip"
          cache-dependency-path: "sdk/python/requirements.txt"
      - name: "Test Python SDK"
        run: |
          cd sdk/python
          pip install -r requirements.txt .
          pytest -xm provision
      - name: "ALWAYS print engine logs - especially useful on failure"
        if: always()
        run: docker logs $(docker ps -q --filter name=dagger-engine)
      - name: "ALWAYS print kernel logs - especially useful on failure"
        if: always()
        run: sudo dmesg

  test-provision-typescript-linux:
    name: "Test SDK Provision / TypeScript / linux"
    needs: [publish]
    if: |
      always() &&
      github.repository == 'dagger/dagger' &&
      (needs.publish.result == 'success' || needs.publish.result == 'skipped')
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: "Set CLI Test URL"
        run: |
          if [ ${{ github.event_name }} == 'push' ]; then
            BASE_URL="https://${{ secrets.RELEASE_FQDN }}/dagger"
            if [ $GITHUB_REF_NAME == 'main' ]; then
              # this is a push to the main branch
              ARCHIVE_URL="${BASE_URL}/main/${GITHUB_SHA}/dagger_${GITHUB_SHA}_linux_amd64.tar.gz"
              CHECKSUMS_URL="${BASE_URL}/main/${GITHUB_SHA}/checksums.txt"
              RUNNER_HOST="docker-image://${{ secrets.RELEASE_DAGGER_ENGINE_IMAGE }}:main"
            else
              # this is a tag push
              ARCHIVE_URL="${BASE_URL}/releases/${GITHUB_REF_NAME:1}/dagger_${GITHUB_REF_NAME}_linux_amd64.tar.gz"
              CHECKSUMS_URL="${BASE_URL}/releases/${GITHUB_REF_NAME:1}/checksums.txt"
              RUNNER_HOST="docker-image://${{ secrets.RELEASE_DAGGER_ENGINE_IMAGE }}:${GITHUB_REF_NAME}"
            fi
            echo "_INTERNAL_DAGGER_TEST_CLI_URL=${ARCHIVE_URL}" >> $GITHUB_ENV
            echo "_INTERNAL_DAGGER_TEST_CLI_CHECKSUMS_URL=${CHECKSUMS_URL}" >> $GITHUB_ENV
            echo "_EXPERIMENTAL_DAGGER_RUNNER_HOST=${RUNNER_HOST}" >> $GITHUB_ENV
          fi
        shell: bash
      - uses: actions/setup-node@v2
        with:
          node-version: 16
      - name: "Test TypeScript SDK"
        run: |
          cd sdk/typescript
          yarn install
          yarn test -g 'Automatic Provisioned CLI Binary'
      - name: "ALWAYS print engine logs - especially useful on failure"
        if: always()
        run: docker logs $(docker ps -q --filter name=dagger-engine)
      - name: "ALWAYS print kernel logs - especially useful on failure"
        if: always()
        run: sudo dmesg
