name: Release (Windows)

# Builds + signs + uploads the Windows installer to the GitHub Release matching
# the app version in electron/package.json. Mac builds stay on the local
# publish.sh flow — this workflow is Windows-only on purpose.
#
# Triggers:
#   - Push a tag `v*` (e.g. v1.0.25) → full signed release build, uploaded to
#     the release of that tag (creates it in draft if absent).
#   - Manual dispatch (workflow_dispatch) with `publish: false` → signed build
#     as an artifact, no release upload. Useful for smoke-tests.
#
# Required repository secrets (Settings → Secrets and variables → Actions):
#   AZURE_TENANT_ID
#   AZURE_CLIENT_ID
#   AZURE_CLIENT_SECRET
#   AZURE_SIGNING_ENDPOINT          e.g. https://wus2.codesigning.azure.net/
#   AZURE_SIGNING_ACCOUNT           mist-code-signing
#   AZURE_SIGNING_CERT_PROFILE      Mist-Windows-Signing
#   GOOGLE_OAUTH_CLIENT_ID          shipped in production .env (Google OAuth)
#   GOOGLE_OAUTH_CLIENT_SECRET      shipped in production .env (Google OAuth)
#                                   v1.0.29 cloud-proxied the OAuth flow itself,
#                                   but the bundled google_workspace_mcp still
#                                   requires CLIENT_SECRET at startup. v1.0.30
#                                   plans to remove this dependency.

on:
  push:
    tags:
      - 'v*'
  workflow_dispatch:
    inputs:
      publish:
        description: 'Publish to GitHub Releases (otherwise artifact only)'
        required: true
        default: 'false'
        type: choice
        options:
          - 'false'
          - 'true'

permissions:
  contents: write

jobs:
  build-windows:
    runs-on: windows-latest
    timeout-minutes: 60

    env:
      AZURE_TENANT_ID:            ${{ secrets.AZURE_TENANT_ID }}
      AZURE_CLIENT_ID:            ${{ secrets.AZURE_CLIENT_ID }}
      AZURE_CLIENT_SECRET:        ${{ secrets.AZURE_CLIENT_SECRET }}
      AZURE_SIGNING_ENDPOINT:     ${{ secrets.AZURE_SIGNING_ENDPOINT }}
      AZURE_SIGNING_ACCOUNT:      ${{ secrets.AZURE_SIGNING_ACCOUNT }}
      AZURE_SIGNING_CERT_PROFILE: ${{ secrets.AZURE_SIGNING_CERT_PROFILE }}
      PUBLISH_INPUT:              ${{ github.event.inputs.publish }}

    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'

      - name: Setup Python (for building bundled python-env)
        uses: actions/setup-python@v5
        with:
          python-version: '3.13'

      # The signing hook calls `signtool.exe` directly. signtool ships in the
      # Windows 10 SDK, preinstalled on windows-latest runners — we just need
      # the dlib for Azure Trusted Signing, pulled via NuGet.
      - name: Install Microsoft.Trusted.Signing.Client (dlib for signtool)
        shell: pwsh
        run: |
          $ErrorActionPreference = 'Stop'
          $dlibDir = Join-Path $env:GITHUB_WORKSPACE 'trusted-signing-client'
          New-Item -ItemType Directory -Force -Path $dlibDir | Out-Null
          nuget install Microsoft.Trusted.Signing.Client -Version 1.0.60 -OutputDirectory $dlibDir -ExcludeVersion
          $dlib = Join-Path $dlibDir 'Microsoft.Trusted.Signing.Client\bin\x64\Azure.CodeSigning.Dlib.dll'
          if (-not (Test-Path $dlib)) {
            Get-ChildItem -Path $dlibDir -Recurse -Filter 'Azure.CodeSigning.Dlib.dll' | ForEach-Object { Write-Host "Found: $($_.FullName)" }
            throw "Azure.CodeSigning.Dlib.dll not found after NuGet install"
          }
          "AZURE_SIGNING_DLIB=$dlib" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8
          Write-Host "AZURE_SIGNING_DLIB=$dlib"

      - name: Locate signtool.exe on the runner
        shell: pwsh
        run: |
          $ErrorActionPreference = 'Stop'
          $candidates = Get-ChildItem -Path 'C:\Program Files (x86)\Windows Kits\10\bin' -Recurse -Filter 'signtool.exe' -ErrorAction SilentlyContinue `
            | Where-Object { $_.FullName -match '\\x64\\signtool\.exe$' } `
            | Sort-Object FullName -Descending
          if (-not $candidates) { throw "signtool.exe not found on runner" }
          $signtool = $candidates[0].FullName
          "SIGNTOOL_PATH=$signtool" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8
          Write-Host "SIGNTOOL_PATH=$signtool"

      - name: Build app
        shell: pwsh
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          GOOGLE_OAUTH_CLIENT_ID:     ${{ secrets.GOOGLE_OAUTH_CLIENT_ID }}
          GOOGLE_OAUTH_CLIENT_SECRET: ${{ secrets.GOOGLE_OAUTH_CLIENT_SECRET }}
        run: |
          $ErrorActionPreference = 'Stop'
          $shouldPublish = ($env:GITHUB_EVENT_NAME -eq 'push') -or `
                           ($env:GITHUB_EVENT_NAME -eq 'workflow_dispatch' -and $env:PUBLISH_INPUT -eq 'true')
          # electron-builder auto-detects prerelease from semver suffix in electron/package.json,
          # but EP_PRE_RELEASE forces the GitHub Releases publisher to mark it Pre-release even
          # when the runner's environment differs from local. Set it whenever the version has a "-" suffix.
          $version = (Get-Content electron/package.json | ConvertFrom-Json).version
          if ($version -match '-') {
            $env:EP_PRE_RELEASE = 'true'
            Write-Host "Version $version is EXPERIMENTAL; setting EP_PRE_RELEASE=true"
          } else {
            Write-Host "Version $version is STABLE"
          }
          if ($shouldPublish) {
            Write-Host "Build mode: PUBLISH"
            pwsh -NoProfile -File scripts\build-app-win.ps1 -Publish
          } else {
            Write-Host "Build mode: SIGN (artifact only)"
            pwsh -NoProfile -File scripts\build-app-win.ps1 -Sign
          }
          if ($LASTEXITCODE -ne 0) { throw "build-app-win.ps1 failed ($LASTEXITCODE)" }

      - name: Upload artifact (non-publish runs)
        if: github.event_name == 'workflow_dispatch' && github.event.inputs.publish != 'true'
        uses: actions/upload-artifact@v4
        with:
          name: openswarm-windows-x64
          path: |
            electron/dist/*.exe
            electron/dist/latest.yml
          if-no-files-found: error
          retention-days: 14
