name: Package and release

on:
  push:
    paths:
    - '.github/workflows/package.yml'
    - 'installer/**'
    - 'picard/**'
    - 'po/**.po'
    - 'resources/win10/**'
    - 'scripts/package/*'
    - 'scripts/pyinstaller/*'
    - 'test/**'
    - 'appxmanifest.xml.in'
    - 'picard.icns'
    - 'picard.ico'
    - 'picard.spec'
    - 'requirements*.txt'
    - 'setup.py'
    - 'tagger.py.in'
    - 'win.version-info.txt.in'
  pull_request:

jobs:
  package-macos:
    runs-on: macos-10.15
    strategy:
      matrix:
        macos-deployment-version: [10.12, 10.14]
    env:
      DISCID_VERSION: 0.6.2
      DISCID_SHA256SUM: f9e443ac4c0dd4819c2841fcc82169a46fb9a626352cdb9c7f65dd3624cd31b9
      FPCALC_VERSION: 1.5.1
      FPCALC_SHA256SUM: c6c2797c4f087cf139eedd71554bc59ef8f26a783dc00c7f3ad5ae71d3a616fe
      PYTHON_VERSION: 3.9.12
      PYTHON_SHA256SUM: 7888174c6fe441b00448c7ab3e9cbf0e6c3c7dea0750577baf09e1383fc44656
      MACOSX_DEPLOYMENT_TARGET: ${{ matrix.macos-deployment-version }}
    steps:
    - uses: actions/checkout@v2
      with:
        fetch-depth: 0  # Fetch entire history, needed for setting the build number
    - run: git fetch --depth=1 origin +refs/tags/release-*:refs/tags/release-*
    - name: Cache libdiscid
      uses: actions/cache@v1
      with:
        path: ~/libdiscid
        key: ${{ runner.os }}-libdiscid-${{ env.DISCID_VERSION }}-${{ env.MACOSX_DEPLOYMENT_TARGET }}
    - name: Setup macOS build environment
      run: |
        ./scripts/package/macos-setup.sh
        PYTHON_BASE_VERSION=$(echo $PYTHON_VERSION | sed -e "s/\.[0-9]\{1,\}$//")
        echo "/Library/Frameworks/Python.framework/Versions/$PYTHON_BASE_VERSION/bin" >> $GITHUB_PATH
        echo "/usr/local/opt/gettext/bin" >> $GITHUB_PATH
        RELEASE_TAG=$(git describe --match "release-*" --abbrev=0 --always HEAD)
        BUILD_NUMBER=$(git rev-list --count $RELEASE_TAG..HEAD)
        echo "BUILD_NUMBER=$BUILD_NUMBER" >> $GITHUB_ENV
        mkdir artifacts
        python3 -m pip install --upgrade pip setuptools wheel
    - name: Patch build version
      if: startsWith(github.ref, 'refs/tags/') != true
      run: |
        python3 setup.py patch_version --platform=$BUILD_NUMBER.$(git rev-parse --short HEAD)
    - name: Compile and install PyInstaller
      run: |
        git clone --depth 1 --branch "$PYINSTALLER_VERSION" https://github.com/pyinstaller/pyinstaller.git pyinstaller
        cd pyinstaller/bootloader
        python3 ./waf --verbose all
        cd ..
        rm pyinstaller.py  # workaround for https://github.com/pyinstaller/pyinstaller/pull/6701
        pip3 install .
      env:
        PYINSTALLER_VERSION: v4.10
        CFLAGS: -mmacosx-version-min=${{ matrix.macos-deployment-version }}
        CPPFLAGS: -mmacosx-version-min=${{ matrix.macos-deployment-version }}
        LDFLAGS: -mmacosx-version-min=${{ matrix.macos-deployment-version }}
        LINKFLAGS: -mmacosx-version-min=${{ matrix.macos-deployment-version }}
    - name: Install dependencies
      run: |
        pip3 install -r requirements-build.txt
        pip3 install -r requirements-macos-${MACOSX_DEPLOYMENT_TARGET}.txt
    - name: Run tests
      run: |
        python3 setup.py test
    - name: Prepare code signing certificate
      run: |
        if [ -n "$CODESIGN_MACOS_PFX_URL" ] && [ -n "$AWS_ACCESS_KEY_ID" ]; then
          pip3 install awscli
          aws s3 cp "$CODESIGN_MACOS_PFX_URL" ./scripts/package/appledev.p12
        else
          echo "::warning::No code signing certificate available, skipping code signing."
        fi
      env:
        AWS_DEFAULT_REGION: eu-central-1
        AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
        AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
        CODESIGN_MACOS_PFX_URL: ${{ secrets.CODESIGN_MACOS_PFX_URL }}
    - name: Build macOS app
      run: |
        ./scripts/package/macos-package-app.sh
        rm -f ./scripts/package/appledev.p12
        mv dist/*.dmg artifacts/
      env:
        APPLE_ID_USER: ${{ secrets.APPLE_ID_USER }}
        APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
        CODESIGN_MACOS_P12_PASSWORD: ${{ secrets.CODESIGN_MACOS_P12_PASSWORD }}
    - name: Archive production artifacts
      uses: actions/upload-artifact@v1
      with:
        name: macos-app-${{ matrix.macos-deployment-version }}
        path: artifacts/

  package-windows:
    runs-on: windows-2019
    strategy:
      matrix:
        type:
        - store-app
        - signed-app
        - installer
        - portable
      fail-fast: false
    steps:
    - uses: actions/checkout@v2
      with:
        fetch-depth: 0  # Fetch entire history, needed for setting the build number
    - run: git fetch --depth=1 origin +refs/tags/release-*:refs/tags/release-*
    - name: Set up Python 3.8
      uses: actions/setup-python@v1
      with:
        python-version: 3.8
    - name: Setup Windows build environment
      run: |
        & .\scripts\package\win-setup.ps1 `
          -DiscidVersion $Env:DISCID_VERSION -DiscidSha256Sum $Env:DISCID_SHA256SUM `
          -FpcalcVersion $Env:FPCALC_VERSION -FpcalcSha256Sum $Env:FPCALC_SHA256SUM
        Write-Output "C:\Program Files (x86)\Windows Kits\10\bin\10.0.18362.0\x64" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8
        $ReleaseTag = $(git describe --match "release-*" --abbrev=0 --always HEAD)
        $BuildNumber = $(git rev-list --count "$ReleaseTag..HEAD")
        Write-Output "BUILD_NUMBER=$BuildNumber" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8
        New-Item -Name .\artifacts -ItemType Directory
      env:
        DISCID_VERSION: 0.6.2
        DISCID_SHA256SUM: 9fd815f6bd0c624f0f41dd81209aeaa3f2129dcd1d617f88b844b4503d12598e
        FPCALC_VERSION: 1.5.1
        FPCALC_SHA256SUM: 36b478e16aa69f757f376645db0d436073a42c0097b6bb2677109e7835b59bbc
    - name: Patch build version
      if: startsWith(github.ref, 'refs/tags/') != true
      run: |
        python setup.py patch_version --platform=$Env:BUILD_NUMBER.$(git rev-parse --short HEAD)
    - name: Install dependencies
      run: |
        python -m pip install --upgrade pip
        pip install -r requirements-build.txt
        pip install -r requirements-win.txt
    - name: Run tests
      run: python setup.py test
    - name: Prepare code signing certificate
      if: matrix.type != 'store-app'
      run: |
        If ($Env:CODESIGN_PFX_URL -And $Env:AWS_ACCESS_KEY_ID) {
          pip install awscli
          aws s3 cp "$Env:CODESIGN_PFX_URL" .\codesign.pfx
          Write-Output "CODESIGN=1" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8
        } Else {
          Write-Output "::warning::No code signing certificate available, skipping code signing."
        }
      env:
        AWS_DEFAULT_REGION: eu-central-1
        AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
        AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
        CODESIGN_PFX_URL: ${{ secrets.CODESIGN_PFX_URL }}
    - name: Build Windows 10 store app package
      if: matrix.type == 'store-app'
      run: |
        & .\scripts\package\win-package-appx.ps1 -BuildNumber $Env:BUILD_NUMBER
        Move-Item .\dist\*.msix .\artifacts
      env:
        PICARD_APPX_PUBLISHER: CN=0A9169B7-05A3-4ED9-8876-830F17846709
    - name: Build Windows 10 signed app package
      if: matrix.type == 'signed-app' && env.CODESIGN == '1'
      run: |
        $CertPassword = ConvertTo-SecureString -String $Env:CODESIGN_PFX_PASSWORD -Force -AsPlainText
        & .\scripts\package\win-package-appx.ps1 -BuildNumber $Env:BUILD_NUMBER -CertificateFile .\codesign.pfx -CertificatePassword $CertPassword
        Move-Item .\dist\*.msix .\artifacts
      env:
        CODESIGN_PFX_PASSWORD: ${{ secrets.CODESIGN_PFX_PASSWORD }}
    - name: Build Windows installer
      if: matrix.type == 'installer'
      run: |
        # choco install nsis
        If ($Env:CODESIGN) {
          $CertPassword = ConvertTo-SecureString -String $Env:CODESIGN_PFX_PASSWORD -Force -AsPlainText
          $Certificate = Get-PfxCertificate -FilePath .\codesign.pfx -Password $CertPassword
        } Else {
          $Certificate = $null
        }
        & .\scripts\package\win-package-installer.ps1 -BuildNumber $Env:BUILD_NUMBER -Certificate $Certificate
        Move-Item .\installer\*.exe .\artifacts
        dist\picard\fpcalc -version
      env:
        CODESIGN_PFX_PASSWORD: ${{ secrets.CODESIGN_PFX_PASSWORD }}
    - name: Build Windows portable app
      if: matrix.type == 'portable'
      run: |
        If ($Env:CODESIGN) {
          $CertPassword = ConvertTo-SecureString -String $Env:CODESIGN_PFX_PASSWORD -Force -AsPlainText
          $Certificate = Get-PfxCertificate -FilePath .\codesign.pfx -Password $CertPassword
        } Else {
          $Certificate = $null
        }
        & .\scripts\package\win-package-portable.ps1 -BuildNumber $Env:BUILD_NUMBER -Certificate $Certificate
        Move-Item .\dist\*.exe .\artifacts
      env:
        CODESIGN_PFX_PASSWORD: ${{ secrets.CODESIGN_PFX_PASSWORD }}
    - name: Cleanup
      if: env.CODESIGN == '1'
      run: Remove-Item .\codesign.pfx
    - name: Archive production artifacts
      uses: actions/upload-artifact@v1
      if: matrix.type != 'signed-app' || env.CODESIGN == '1'
      with:
        name: windows-${{ matrix.type }}
        path: artifacts/

  github-release:
    runs-on: ubuntu-latest
    if: startsWith(github.ref, 'refs/tags/')
    needs:
      - package-macos
      - package-windows
    steps:
    - uses: actions/checkout@v2
    - uses: actions/setup-python@v1
      with:
        python-version: 3.9
    - uses: actions/download-artifact@v1
      with:
        name: macos-app-10.12
        path: artifacts/
    - uses: actions/download-artifact@v1
      with:
        name: macos-app-10.14
        path: artifacts/
    - uses: actions/download-artifact@v1
      with:
        name: windows-signed-app
        path: artifacts/
    - uses: actions/download-artifact@v1
      with:
        name: windows-store-app
        path: artifacts/
    - uses: actions/download-artifact@v1
      with:
        name: windows-installer
        path: artifacts/
    - uses: actions/download-artifact@v1
      with:
        name: windows-portable
        path: artifacts/
    - name: Generate checksums
      run: |
        cd artifacts
        sha256sum * > SHA256SUMS
    - name: Prepare changelog
      id: changelog
      continue-on-error: true
      run: |
        PICARD_VERSION=$(python -c "import picard; print(picard.__version__)")
        echo "::set-output name=version::"$PICARD_VERSION
        ./scripts/tools/changelog-for-version.py $PICARD_VERSION > changes-$PICARD_VERSION.txt
    - name: Create release
      uses: softprops/action-gh-release@v1
      with:
        name: MusicBrainz Picard ${{ steps.changelog.outputs.version }}
        body_path: changes-${{ steps.changelog.outputs.version }}.txt
        files: artifacts/*
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
