name: Windows MSVC builds

on: [push, pull_request]

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

env:
  VCPKG_ROOT: C:\vcpkg
  VCPKG_BINARY_SOURCES: 'clear;nuget,GitHub,readwrite'

jobs:
  build_windows_vs:
    name: ${{ matrix.conf.name }}
    runs-on: windows-2022
    if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository
    strategy:
      matrix:
        conf:
          - name: MSVC 32-bit
            arch: x86
            max_warnings: 17
          - name: MSVC 64-bit
            arch: x64
            max_warnings: 687

    steps:
      - name: Checkout repository
        uses: actions/checkout@v4
        with:
          submodules: false

      - name:  Setup vcpkg and NuGet
        shell: bash
        run: |
          set -euo pipefail
          cd "${{ env.VCPKG_ROOT }}"
          git checkout master -f
          git pull
          ./bootstrap-vcpkg.sh -disableMetrics
          nuget=$(./vcpkg.exe fetch nuget | tail -n 1)
          owner="${GITHUB_REPOSITORY%/*}"
          source_url="https://nuget.pkg.github.com/$owner/index.json"
          "$nuget" sources add \
            -source "$source_url" \
            -storepasswordincleartext \
            -name "GitHub" \
            -username "$owner" \
            -password "${{ secrets.GITHUB_TOKEN }}"
          "$nuget" setapikey "${{ secrets.GITHUB_TOKEN }}" \
            -source "$source_url"

      - name: Add MSBuild to PATH
        uses: microsoft/setup-msbuild@v2
        with:
            vs-prerelease: true
            msbuild-architecture: ${{ matrix.conf.arch }}

      - name:  Integrate packages
        shell: pwsh
        run: |
          ${{ env.VCPKG_ROOT }}\vcpkg.exe integrate install
          if (-not $?) { throw "vcpkg failed to integrate packages" }

      - name:  Log environment
        shell: pwsh
        run:   .\scripts\log-env.ps1

      - name:  Run tests
        shell: pwsh
        run: |
          cd vs
          MSBuild -m dosbox.sln -t:tests:Rebuild -p:Configuration=Debug -p:Platform=${{ matrix.conf.arch }}

      - name:  Build
        shell: pwsh
        run: |
          cd vs
          MSBuild -m dosbox.sln -t:dosbox:Rebuild -p:Configuration=Debug -p:Platform=${{ matrix.conf.arch }} | Tee-Object build.log

      - name:  Summarize warnings
        shell: pwsh
        env:
          MAX_WARNINGS: ${{ matrix.conf.max_warnings }}
        run: python scripts\count-warnings.py -f --msvc vs\build.log

  build_windows_vs_release:
    name: ${{ matrix.conf.name }}
    if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository
    runs-on: windows-2022
    strategy:
      matrix:
        conf:
          - name: Release build (32-bit)
            arch: x86
            vs-release-dirname: Win32
            debugger: false
          - name: Release build (64-bit)
            arch: x64
            vs-release-dirname: x64
            debugger: false
          - name: Release build w/ debugger (32-bit)
            arch: x86
            vs-release-dirname: Win32
            debugger: true
          - name: Release build w/ debugger (64-bit)
            arch: x64
            vs-release-dirname: x64
            debugger: true

    steps:
      - name: Checkout repository
        uses: actions/checkout@v4
        with:
          submodules: false

      - name:  Setup vcpkg and NuGet
        shell: bash
        run: |
          set -euo pipefail
          cd "${{ env.VCPKG_ROOT }}"
          git checkout master -f
          git pull
          ./bootstrap-vcpkg.sh -disableMetrics
          nuget=$(./vcpkg.exe fetch nuget | tail -n 1)
          owner="${GITHUB_REPOSITORY%/*}"
          source_url="https://nuget.pkg.github.com/$owner/index.json"
          "$nuget" sources add \
            -source "$source_url" \
            -storepasswordincleartext \
            -name "GitHub" \
            -username "$owner" \
            -password "${{ secrets.GITHUB_TOKEN }}"
          "$nuget" setapikey "${{ secrets.GITHUB_TOKEN }}" \
            -source "$source_url"

      - name: Add MSBuild to PATH
        uses: microsoft/setup-msbuild@v1.3
        with:
            vs-prerelease: true
            msbuild-architecture: ${{ matrix.conf.arch }}

      - name:  Integrate packages
        shell: pwsh
        run: |
          ${{ env.VCPKG_ROOT }}\vcpkg.exe integrate install
          if (-not $?) { throw "vcpkg failed to integrate packages" }

      - name:  Log environment
        shell: pwsh
        run:   .\scripts\log-env.ps1

      - name:  Set version
        id:    set_dosbox_vers
        shell: bash
        run: |
          set -x
          git fetch --prune --unshallow
          git fetch --all --tags --force
          export VERSION=$(git describe --abbrev=0)
          # inject version based on vcs
          sed -i "s|DOSBOX_DETAILED_VERSION \"git\"|DOSBOX_DETAILED_VERSION \"$VERSION\"|" src/platform/visualc/config.h
          echo "VERSION=$VERSION" >> $GITHUB_ENV
          echo "dosbox_vers=${VERSION}" >> $GITHUB_OUTPUT

      - name:  Enable the debugger in config.h
        if: ${{ matrix.conf.debugger }}
        shell: bash
        run: |
          set -x
          sed -i "s|C_DEBUG.*|C_DEBUG 1|"             src/platform/visualc/config.h
          sed -i "s|C_HEAVY_DEBUG.*|C_HEAVY_DEBUG 1|" src/platform/visualc/config.h

      - name:  Build release
        shell: pwsh
        run: |
          cd vs
          MSBuild -m dosbox.sln -t:dosbox:Rebuild -p:Configuration=Release -p:Platform=${{ matrix.conf.arch }}

      - name:  Set packaging names
        id:    set_pkg_dir
        shell: bash
        run: |
          echo "pkg_dir=dosbox-staging-windows-${{ matrix.conf.arch }}-${{ env.VERSION }}" >> $GITHUB_OUTPUT

      - name: Package standard build
        if: ${{ !matrix.conf.debugger }}
        shell: bash
        run: |
          # Construct VC_REDIST_DIR
          readonly VC_REDIST_BASE="C:/Program Files/Microsoft Visual Studio/2022/Enterprise/VC/Redist/MSVC"
          readonly VC_REDIST_VERSION="14.36.32532"
          readonly VC_REDIST_CRT_VERSION="Microsoft.VC143.CRT"
          export VC_REDIST_DIR="$VC_REDIST_BASE/$VC_REDIST_VERSION/${{ matrix.conf.arch }}/$VC_REDIST_CRT_VERSION"
          find "$VC_REDIST_BASE" -maxdepth 3 -type d

          # Package
          ./scripts/create-package.sh \
            -p msvc \
            vs/${{ matrix.conf.vs-release-dirname }}/Release \
            "${{ steps.set_pkg_dir.outputs.pkg_dir }}"

      - name:  Package the debugger
        if:    ${{ matrix.conf.debugger }}
        shell: bash
        run: |
          set -x
          mkdir -p ${{ steps.set_pkg_dir.outputs.pkg_dir }}
          # Move the debugger build into the release area
          readonly RELEASE_DIR=${{ matrix.conf.vs-release-dirname }}/Release
          ls "vs/$RELEASE_DIR"
          cp vs/$RELEASE_DIR/dosbox.exe   ${{ steps.set_pkg_dir.outputs.pkg_dir }}/dosbox_with_debugger.exe

      - name: Upload package
        if:   ${{ !matrix.conf.debugger }}
        uses: actions/upload-artifact@v4.3.1
        with:
          name: ${{ steps.set_pkg_dir.outputs.pkg_dir }}
          path: ${{ steps.set_pkg_dir.outputs.pkg_dir }}
          overwrite: true

      - name: Upload debugger artifact
        if:   ${{ matrix.conf.debugger }}
        uses: actions/upload-artifact@v4.3.1
        with:
          name: ${{ steps.set_pkg_dir.outputs.pkg_dir }}
          path: ${{ steps.set_pkg_dir.outputs.pkg_dir }}/dosbox_with_debugger.exe
          overwrite: true

  # This job exists only to publish an artifact with version info when building
  # from main branch, so snapshot build version will be visible on:
  # https://dosbox-staging.github.io/downloads/devel/
  #
  publish_additional_artifacts:
    name: Publish additional Windows artifacts
    needs: build_windows_vs_release
    runs-on: windows-2022
    if: github.event_name == 'push' && github.ref == 'refs/heads/main'
    steps:
      - uses: actions/checkout@v4
        with:
          submodules: false

      - name: Generate changelog
        shell: bash
        run: |
          set +x
          git fetch --unshallow
          git fetch --all --tags --force
          VERSION=$(git describe --abbrev=0)
          echo "VERSION=$VERSION" >> $GITHUB_ENV
          NEWEST_TAG=$(git describe --abbrev=0)
          git log "$NEWEST_TAG..HEAD" > changelog-$VERSION.txt

      - uses: actions/upload-artifact@v4.3.1
        with:
          # Keep exactly this artifact name; it's being used to propagate
          # version info via GitHub REST API
          name: changelog-${{ env.VERSION }}.txt
          path: changelog-${{ env.VERSION }}.txt
          overwrite: true
