name: start-cli

on:
  workflow_call:
  workflow_dispatch:
    inputs:
      environment:
        type: choice
        description: Environment
        options:
          - NONE
          - dev
          - unstable
          - dev-unstable
      runner:
        type: choice
        description: Runner
        options:
          - standard
          - fast
      arch:
        type: choice
        description: Architecture
        options:
          - ALL
          - x86_64
          - x86_64-apple
          - aarch64
          - aarch64-apple
          - riscv64
  # `paths:` below mirror projects/start-cli/build.mk's build inputs — keep both
  # in sync (see root AGENTS.md "Coupled changes").
  push:
    branches:
      - master
      - integration/*
    paths:
      - 'projects/start-cli/**'
      - 'shared-libs/crates/**'
      - 'Cargo.toml'
      - 'Cargo.lock'
      - 'build/**'
      - 'debian/**'
      - '.github/workflows/start-cli.yaml'
      - '.github/actions/setup-build/**'
      # Doc-only edits shouldn't trigger a build. (start-cli has no docs/ subtree
      # today, but this guards a README or future docs added under the allowlist.)
      - '!**/*.md'
      # A release tags alpha's commit, which must contain its notes.
      - 'projects/start-cli/release-notes/**'
  pull_request:
    # The jobs below skip drafts, and `ready_for_review` is not a default
    # activity type, so without it a draft marked ready is never checked.
    types: [opened, synchronize, reopened, ready_for_review]
    branches:
      - master
      - integration/*
    paths:
      - 'projects/start-cli/**'
      - 'shared-libs/crates/**'
      - 'Cargo.toml'
      - 'Cargo.lock'
      - 'build/**'
      - 'debian/**'
      - '.github/workflows/start-cli.yaml'
      - '.github/actions/setup-build/**'
      # Doc-only edits shouldn't trigger a build. (start-cli has no docs/ subtree
      # today, but this guards a README or future docs added under the allowlist.)
      - '!**/*.md'

# The group is scoped by event so a master push can't cancel an in-flight
# dispatched release build. Only pull requests cancel: a push to master
# publishes to alpha, so master pushes queue behind each other rather than
# aborting a publish half-done.
concurrency:
  group: start-cli-${{ github.event_name }}-${{ github.head_ref || github.ref }}
  cancel-in-progress: ${{ github.event_name == 'pull_request' }}

env:
  NODEJS_VERSION: '24.11.0'
  # Empty (release-equivalent) on master, `dev` everywhere else a build happens
  # without an explicit input — PRs and integration/* branches. Continuous
  # deployment must not ship dev-flavoured artifacts.
  ENVIRONMENT: >-
    ${{
      fromJson(format('["{0}", ""]', github.event.inputs.environment || 'dev'))[
        github.event.inputs.environment == 'NONE'
        || (github.event_name == 'push' && github.ref == 'refs/heads/master')
      ]
    }}

jobs:
  compile:
    name: Build Binary
    if: github.event.pull_request.draft != true
    strategy:
      fail-fast: true
      matrix:
        triple: >-
          ${{
            fromJson('{
              "x86_64": ["x86_64-unknown-linux-musl"],
              "x86_64-apple": ["x86_64-apple-darwin"],
              "aarch64": ["aarch64-unknown-linux-musl"],
              "aarch64-apple": ["aarch64-apple-darwin"],
              "riscv64": ["riscv64gc-unknown-linux-musl"],
              "ALL": ["x86_64-unknown-linux-musl", "x86_64-apple-darwin", "aarch64-unknown-linux-musl", "aarch64-apple-darwin", "riscv64gc-unknown-linux-musl"]
            }')[github.event.inputs.arch || 'ALL']
          }}
    runs-on: ${{ fromJson('["ubuntu-latest", "ubuntu-24.04-32-cores"]')[github.event.inputs.runner == 'fast'] }}
    steps:
      - name: Mount tmpfs
        if: ${{ github.event.inputs.runner == 'fast' }}
        run: sudo mount -t tmpfs tmpfs .
      - uses: actions/checkout@v6
      - uses: ./.github/actions/setup-build
        with:
          nodejs-version: ${{ env.NODEJS_VERSION }}

      - name: Make
        run: TARGET=${{ matrix.triple }} make start-cli
        env:
          PLATFORM: ${{ matrix.arch }}
          SCCACHE_GHA_ENABLED: on
          SCCACHE_GHA_VERSION: 0

      - uses: actions/upload-artifact@v7
        with:
          name: start-cli_${{ matrix.triple }}
          path: target/${{ matrix.triple }}/release/start-cli
          retention-days: 14

  deb:
    name: Build Debian Package
    needs: [compile]
    # Skip apple-only arch selections — macOS targets have no .deb. The matrix
    # selector below still resolves to a valid (unused) value so evaluation never
    # errors; this `if` is what actually prevents the job from running.
    if: ${{ github.event.pull_request.draft != true && !contains(github.event.inputs.arch, 'apple') }}
    strategy:
      fail-fast: true
      matrix:
        arch: >-
          ${{
            fromJson('{
              "x86_64": ["x86_64"],
              "aarch64": ["aarch64"],
              "riscv64": ["riscv64"],
              "ALL": ["x86_64", "aarch64", "riscv64"]
            }')[contains(github.event.inputs.arch, 'apple') && 'ALL' || github.event.inputs.arch || 'ALL']
          }}
    runs-on: ${{ fromJson('["ubuntu-latest", "ubuntu-24.04-32-cores"]')[github.event.inputs.runner == 'fast'] }}
    steps:
      - name: Mount tmpfs
        if: ${{ github.event.inputs.runner == 'fast' }}
        run: sudo mount -t tmpfs tmpfs .
      - uses: actions/checkout@v6
      - uses: ./.github/actions/setup-build
        with:
          nodejs-version: ${{ env.NODEJS_VERSION }}

      - name: Resolve musl target triple
        id: triple
        run: |
          case "${{ matrix.arch }}" in
            x86_64)  triple=x86_64-unknown-linux-musl ;;
            aarch64) triple=aarch64-unknown-linux-musl ;;
            riscv64) triple=riscv64gc-unknown-linux-musl ;;
            *) echo "::error::unsupported arch ${{ matrix.arch }}"; exit 1 ;;
          esac
          echo "triple=$triple" >> "$GITHUB_OUTPUT"

      - name: Download Build Binary
        uses: actions/download-artifact@v8
        with:
          name: start-cli_${{ steps.triple.outputs.triple }}
          path: target/${{ steps.triple.outputs.triple }}/release

      - name: Stamp prebuilt binary as up-to-date
        # Drop the compiled binary where `make start-cli-deb` expects it and mark it
        # newer than its Make prerequisites (the generated env/git-hash stamp
        # files + checked-out sources) so packaging skips a redundant recompile.
        run: |
          bin="target/${{ steps.triple.outputs.triple }}/release/start-cli"
          chmod +x "$bin"
          ./build/env/check-environment.sh >/dev/null
          ./build/env/check-git-hash.sh >/dev/null
          PLATFORM="${{ matrix.arch }}" ./build/env/check-platform.sh >/dev/null
          touch "$bin"

      - name: Make
        run: make start-cli-deb
        env:
          PLATFORM: ${{ matrix.arch }}
          SCCACHE_GHA_ENABLED: on
          SCCACHE_GHA_VERSION: 0

      - uses: actions/upload-artifact@v7
        with:
          name: start-cli_${{ matrix.arch }}.deb
          path: results/start-cli-*_${{ matrix.arch }}.deb
          retention-days: 14