From ae946375c0c9fb466d324e6373a901b5b60d43b6 Mon Sep 17 00:00:00 2001 From: Philipp Wolfer Date: Fri, 6 Dec 2024 08:08:38 +0100 Subject: [PATCH 1/2] Split CI package tasks into separate files --- .github/workflows/package-macos.yml | 99 ++++++++++++ .github/workflows/package-windows.yml | 136 ++++++++++++++++ .github/workflows/package.yml | 225 +------------------------- 3 files changed, 243 insertions(+), 217 deletions(-) create mode 100644 .github/workflows/package-macos.yml create mode 100644 .github/workflows/package-windows.yml diff --git a/.github/workflows/package-macos.yml b/.github/workflows/package-macos.yml new file mode 100644 index 0000000000..bfea2b830e --- /dev/null +++ b/.github/workflows/package-macos.yml @@ -0,0 +1,99 @@ +name: Package and release + +on: [workflow_call] + +permissions: {} + +jobs: + package-macos: + runs-on: macos-13 + strategy: + matrix: + setup: + - macos-deployment-version: 10.12 + python-version: 3.9.12-macosx10.9 + python-sha256sum: 7888174c6fe441b00448c7ab3e9cbf0e6c3c7dea0750577baf09e1383fc44656 + disable-webp: 1 + - macos-deployment-version: 10.14 + python-version: 3.11.5-macos11 + python-sha256sum: c6cd76659bfb364c2ac63bc57f6b10c1e131a20170359c5d65e2d41fdc674a4f + disable-webp: 0 + env: + DISCID_VERSION: 0.6.4 + DISCID_SHA256SUM: 829133dd38acbdaa2b989de59e256c8d139ac34cb4dd4b8fd3c9d55a97c824f3 + FPCALC_VERSION: 1.5.1 + FPCALC_SHA256SUM: d4d8faff4b5f7c558d9be053da47804f9501eaa6c2f87906a9f040f38d61c860 + PYTHON_VERSION: ${{ matrix.setup.python-version }} + PYTHON_SHA256SUM: ${{ matrix.setup.python-sha256sum }} + MACOSX_DEPLOYMENT_TARGET: ${{ matrix.setup.macos-deployment-version }} + CODESIGN: 0 + steps: + - uses: actions/checkout@v4 + 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: 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 .. + pip3 install . + env: + PYINSTALLER_VERSION: v5.13.2 + CFLAGS: -mmacosx-version-min=${{ matrix.setup.macos-deployment-version }} + CPPFLAGS: -mmacosx-version-min=${{ matrix.setup.macos-deployment-version }} + LDFLAGS: -mmacosx-version-min=${{ matrix.setup.macos-deployment-version }} + LINKFLAGS: -mmacosx-version-min=${{ matrix.setup.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 + timeout-minutes: 30 + run: | + python3 setup.py test + - name: Prepare code signing certificate + run: | + if [ -n "$CODESIGN_MACOS_P12_URL" ] && [ -n "$AWS_ACCESS_KEY_ID" ]; then + pip3 install awscli + aws s3 cp "$CODESIGN_MACOS_P12_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_P12_URL: ${{ secrets.CODESIGN_MACOS_P12_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_TEAM: ${{ secrets.APPLE_ID_TEAM }} + APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }} + CODESIGN_MACOS_P12_PASSWORD: ${{ secrets.CODESIGN_MACOS_P12_PASSWORD }} + DISABLE_WEBP: ${{ matrix.setup.disable-webp }} + - name: Archive production artifacts + uses: actions/upload-artifact@v4 + with: + name: macos-app-${{ matrix.setup.macos-deployment-version }} + path: artifacts/ diff --git a/.github/workflows/package-windows.yml b/.github/workflows/package-windows.yml new file mode 100644 index 0000000000..c5a36d4e40 --- /dev/null +++ b/.github/workflows/package-windows.yml @@ -0,0 +1,136 @@ +name: Package and release + +on: [workflow_call] + +permissions: {} + +jobs: + package-windows: + runs-on: windows-2019 + strategy: + matrix: + type: + - store-app + - signed-app + - installer + - portable + fail-fast: false + env: + CODESIGN: 0 + steps: + - uses: actions/checkout@v4 + 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@v5 + 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 + Add-Content $env:GITHUB_PATH "C:\Program Files (x86)\Windows Kits\10\bin\10.0.18362.0\x64" + $ReleaseTag = $(git describe --match "release-*" --abbrev=0 --always HEAD) + $BuildNumber = $(git rev-list --count "$ReleaseTag..HEAD") + Add-Content $env:GITHUB_ENV "BUILD_NUMBER=$BuildNumber" + New-Item -Name .\artifacts -ItemType Directory + env: + DISCID_VERSION: 0.6.4 + DISCID_SHA256SUM: 330199495d71f71251e91eb0b4e3103b6c663fea09ffc9fd3e5108d48e0452c8 + FPCALC_VERSION: 1.5.1 + FPCALC_SHA256SUM: 36b478e16aa69f757f376645db0d436073a42c0097b6bb2677109e7835b59bbc + - name: Install gettext + run: | + & .\scripts\package\win-setup-gettext.ps1 ` + -GettextVersion $Env:GETTEXT_VERSION -GettextSha256Sum $Env:GETTEXT_SHA256SUM + Add-Content $env:GITHUB_PATH (Join-Path -Path (Resolve-Path .) -ChildPath gettext\bin) + env: + GETTEXT_VERSION: 0.22.4 + GETTEXT_SHA256SUM: 220068ac0b9e7aedda03534a3088e584640ac1e639800b3a0baa9410aa6d012a + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install -r requirements-build.txt + pip install -r requirements-win.txt + - 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: Run tests + timeout-minutes: 30 + run: python setup.py test + - name: Prepare code signing certificate + if: matrix.type != 'store-app' + run: | + If ($Env:CODESIGN_P12_URL -And $Env:AWS_ACCESS_KEY_ID) { + pip install awscli + aws s3 cp "$Env:CODESIGN_P12_URL" .\codesign.pfx + Add-Content $env:GITHUB_ENV "CODESIGN=1" + } 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_P12_URL: ${{ secrets.CODESIGN_P12_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: | + $CertificateFile = ".\codesign.pfx" + $CertificatePassword = ConvertTo-SecureString -String $Env:CODESIGN_P12_PASSWORD -Force -AsPlainText + & .\scripts\package\win-package-appx.ps1 -BuildNumber $Env:BUILD_NUMBER ` + -CertificateFile $CertificateFile -CertificatePassword $CertificatePassword + Move-Item .\dist\*.msix .\artifacts + env: + CODESIGN_P12_PASSWORD: ${{ secrets.CODESIGN_P12_PASSWORD }} + - name: Build Windows installer + if: matrix.type == 'installer' + run: | + # choco install nsis + If ($Env:CODESIGN -eq "1") { + $CertificateFile = ".\codesign.pfx" + $CertificatePassword = ConvertTo-SecureString -String $Env:CODESIGN_P12_PASSWORD -Force -AsPlainText + } Else { + $CertificateFile = $null + $CertificatePassword = $null + } + & .\scripts\package\win-package-installer.ps1 -BuildNumber $Env:BUILD_NUMBER ` + -CertificateFile $CertificateFile -CertificatePassword $CertificatePassword + Move-Item .\installer\*.exe .\artifacts + dist\picard\fpcalc -version + env: + CODESIGN_P12_PASSWORD: ${{ secrets.CODESIGN_P12_PASSWORD }} + - name: Build Windows portable app + if: matrix.type == 'portable' + run: | + If ($Env:CODESIGN -eq "1") { + $CertificateFile = ".\codesign.pfx" + $CertificatePassword = ConvertTo-SecureString -String $Env:CODESIGN_P12_PASSWORD -Force -AsPlainText + } Else { + $CertificateFile = $null + $CertificatePassword = $null + } + & .\scripts\package\win-package-portable.ps1 -BuildNumber $Env:BUILD_NUMBER ` + -CertificateFile $CertificateFile -CertificatePassword $CertificatePassword + Move-Item .\dist\*.exe .\artifacts + env: + CODESIGN_P12_PASSWORD: ${{ secrets.CODESIGN_P12_PASSWORD }} + - name: Cleanup + if: env.CODESIGN == '1' + run: Remove-Item .\codesign.pfx + - name: Archive production artifacts + uses: actions/upload-artifact@v4 + if: matrix.type != 'signed-app' || env.CODESIGN == '1' + with: + name: windows-${{ matrix.type }} + path: artifacts/ diff --git a/.github/workflows/package.yml b/.github/workflows/package.yml index 5ae16a2d11..c2c13ffcef 100644 --- a/.github/workflows/package.yml +++ b/.github/workflows/package.yml @@ -3,7 +3,7 @@ name: Package and release on: push: paths: - - '.github/workflows/package.yml' + - '.github/workflows/package*.yml' - '.github/workflows/pypi-release.yml' - 'installer/**' - 'picard/**' @@ -26,230 +26,21 @@ permissions: {} jobs: package-macos: - runs-on: macos-13 + uses: ./.github/workflows/package-macos.yml strategy: - matrix: - setup: - - macos-deployment-version: 10.12 - python-version: 3.9.12-macosx10.9 - python-sha256sum: 7888174c6fe441b00448c7ab3e9cbf0e6c3c7dea0750577baf09e1383fc44656 - disable-webp: 1 - - macos-deployment-version: 10.14 - python-version: 3.11.5-macos11 - python-sha256sum: c6cd76659bfb364c2ac63bc57f6b10c1e131a20170359c5d65e2d41fdc674a4f - disable-webp: 0 - env: - DISCID_VERSION: 0.6.4 - DISCID_SHA256SUM: 829133dd38acbdaa2b989de59e256c8d139ac34cb4dd4b8fd3c9d55a97c824f3 - FPCALC_VERSION: 1.5.1 - FPCALC_SHA256SUM: d4d8faff4b5f7c558d9be053da47804f9501eaa6c2f87906a9f040f38d61c860 - PYTHON_VERSION: ${{ matrix.setup.python-version }} - PYTHON_SHA256SUM: ${{ matrix.setup.python-sha256sum }} - MACOSX_DEPLOYMENT_TARGET: ${{ matrix.setup.macos-deployment-version }} - CODESIGN: 0 - steps: - - uses: actions/checkout@v4 - 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: 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 .. - pip3 install . - env: - PYINSTALLER_VERSION: v5.13.2 - CFLAGS: -mmacosx-version-min=${{ matrix.setup.macos-deployment-version }} - CPPFLAGS: -mmacosx-version-min=${{ matrix.setup.macos-deployment-version }} - LDFLAGS: -mmacosx-version-min=${{ matrix.setup.macos-deployment-version }} - LINKFLAGS: -mmacosx-version-min=${{ matrix.setup.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 - timeout-minutes: 30 - run: | - python3 setup.py test - - name: Prepare code signing certificate - run: | - if [ -n "$CODESIGN_MACOS_P12_URL" ] && [ -n "$AWS_ACCESS_KEY_ID" ]; then - pip3 install awscli - aws s3 cp "$CODESIGN_MACOS_P12_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_P12_URL: ${{ secrets.CODESIGN_MACOS_P12_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_TEAM: ${{ secrets.APPLE_ID_TEAM }} - APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }} - CODESIGN_MACOS_P12_PASSWORD: ${{ secrets.CODESIGN_MACOS_P12_PASSWORD }} - DISABLE_WEBP: ${{ matrix.setup.disable-webp }} - - name: Archive production artifacts - uses: actions/upload-artifact@v4 - with: - name: macos-app-${{ matrix.setup.macos-deployment-version }} - path: artifacts/ + fail-fast: false + secrets: inherit package-windows: - runs-on: windows-2019 + uses: ./.github/workflows/package-windows.yml strategy: - matrix: - type: - - store-app - - signed-app - - installer - - portable fail-fast: false - env: - CODESIGN: 0 - steps: - - uses: actions/checkout@v4 - 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@v5 - 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 - Add-Content $env:GITHUB_PATH "C:\Program Files (x86)\Windows Kits\10\bin\10.0.18362.0\x64" - $ReleaseTag = $(git describe --match "release-*" --abbrev=0 --always HEAD) - $BuildNumber = $(git rev-list --count "$ReleaseTag..HEAD") - Add-Content $env:GITHUB_ENV "BUILD_NUMBER=$BuildNumber" - New-Item -Name .\artifacts -ItemType Directory - env: - DISCID_VERSION: 0.6.4 - DISCID_SHA256SUM: 330199495d71f71251e91eb0b4e3103b6c663fea09ffc9fd3e5108d48e0452c8 - FPCALC_VERSION: 1.5.1 - FPCALC_SHA256SUM: 36b478e16aa69f757f376645db0d436073a42c0097b6bb2677109e7835b59bbc - - name: Install gettext - run: | - & .\scripts\package\win-setup-gettext.ps1 ` - -GettextVersion $Env:GETTEXT_VERSION -GettextSha256Sum $Env:GETTEXT_SHA256SUM - Add-Content $env:GITHUB_PATH (Join-Path -Path (Resolve-Path .) -ChildPath gettext\bin) - env: - GETTEXT_VERSION: 0.22.4 - GETTEXT_SHA256SUM: 220068ac0b9e7aedda03534a3088e584640ac1e639800b3a0baa9410aa6d012a - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install -r requirements-build.txt - pip install -r requirements-win.txt - - 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: Run tests - timeout-minutes: 30 - run: python setup.py test - - name: Prepare code signing certificate - if: matrix.type != 'store-app' - run: | - If ($Env:CODESIGN_P12_URL -And $Env:AWS_ACCESS_KEY_ID) { - pip install awscli - aws s3 cp "$Env:CODESIGN_P12_URL" .\codesign.pfx - Add-Content $env:GITHUB_ENV "CODESIGN=1" - } 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_P12_URL: ${{ secrets.CODESIGN_P12_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: | - $CertificateFile = ".\codesign.pfx" - $CertificatePassword = ConvertTo-SecureString -String $Env:CODESIGN_P12_PASSWORD -Force -AsPlainText - & .\scripts\package\win-package-appx.ps1 -BuildNumber $Env:BUILD_NUMBER ` - -CertificateFile $CertificateFile -CertificatePassword $CertificatePassword - Move-Item .\dist\*.msix .\artifacts - env: - CODESIGN_P12_PASSWORD: ${{ secrets.CODESIGN_P12_PASSWORD }} - - name: Build Windows installer - if: matrix.type == 'installer' - run: | - # choco install nsis - If ($Env:CODESIGN -eq "1") { - $CertificateFile = ".\codesign.pfx" - $CertificatePassword = ConvertTo-SecureString -String $Env:CODESIGN_P12_PASSWORD -Force -AsPlainText - } Else { - $CertificateFile = $null - $CertificatePassword = $null - } - & .\scripts\package\win-package-installer.ps1 -BuildNumber $Env:BUILD_NUMBER ` - -CertificateFile $CertificateFile -CertificatePassword $CertificatePassword - Move-Item .\installer\*.exe .\artifacts - dist\picard\fpcalc -version - env: - CODESIGN_P12_PASSWORD: ${{ secrets.CODESIGN_P12_PASSWORD }} - - name: Build Windows portable app - if: matrix.type == 'portable' - run: | - If ($Env:CODESIGN -eq "1") { - $CertificateFile = ".\codesign.pfx" - $CertificatePassword = ConvertTo-SecureString -String $Env:CODESIGN_P12_PASSWORD -Force -AsPlainText - } Else { - $CertificateFile = $null - $CertificatePassword = $null - } - & .\scripts\package\win-package-portable.ps1 -BuildNumber $Env:BUILD_NUMBER ` - -CertificateFile $CertificateFile -CertificatePassword $CertificatePassword - Move-Item .\dist\*.exe .\artifacts - env: - CODESIGN_P12_PASSWORD: ${{ secrets.CODESIGN_P12_PASSWORD }} - - name: Cleanup - if: env.CODESIGN == '1' - run: Remove-Item .\codesign.pfx - - name: Archive production artifacts - uses: actions/upload-artifact@v4 - if: matrix.type != 'signed-app' || env.CODESIGN == '1' - with: - name: windows-${{ matrix.type }} - path: artifacts/ + secrets: inherit package-pypi: uses: ./.github/workflows/package-pypi.yml + strategy: + fail-fast: false secrets: inherit permissions: id-token: write From c4be51bde9d87f73c9bbeaf2472810e3792c1a66 Mon Sep 17 00:00:00 2001 From: Philipp Wolfer Date: Fri, 6 Dec 2024 08:13:27 +0100 Subject: [PATCH 2/2] PICARD-3002: Use Azure Trusted Signing for code signing # Conflicts: # .github/workflows/package-windows.yml # scripts/package/win-common.ps1 --- .github/workflows/package-windows.yml | 127 ++++++++++------------ scripts/package/win-build-fixes.ps1 | 18 +++ scripts/package/win-common.ps1 | 47 -------- scripts/package/win-package-appx.ps1 | 60 +--------- scripts/package/win-package-installer.ps1 | 43 -------- scripts/package/win-package-portable.ps1 | 39 ------- 6 files changed, 83 insertions(+), 251 deletions(-) create mode 100644 scripts/package/win-build-fixes.ps1 delete mode 100644 scripts/package/win-package-installer.ps1 delete mode 100644 scripts/package/win-package-portable.ps1 diff --git a/.github/workflows/package-windows.yml b/.github/workflows/package-windows.yml index c5a36d4e40..a2f037a2a3 100644 --- a/.github/workflows/package-windows.yml +++ b/.github/workflows/package-windows.yml @@ -9,14 +9,15 @@ jobs: runs-on: windows-2019 strategy: matrix: - type: - - store-app - - signed-app - - installer - - portable + setup: + - type: installer + - type: portable + build-portable: 1 + - type: store-app + disable-autoupdate: 1 fail-fast: false env: - CODESIGN: 0 + CODESIGN: ${{ !!secrets.AZURE_CERT_PROFILE_NAME }} steps: - uses: actions/checkout@v4 with: @@ -32,9 +33,6 @@ jobs: -DiscidVersion $Env:DISCID_VERSION -DiscidSha256Sum $Env:DISCID_SHA256SUM ` -FpcalcVersion $Env:FPCALC_VERSION -FpcalcSha256Sum $Env:FPCALC_SHA256SUM Add-Content $env:GITHUB_PATH "C:\Program Files (x86)\Windows Kits\10\bin\10.0.18362.0\x64" - $ReleaseTag = $(git describe --match "release-*" --abbrev=0 --always HEAD) - $BuildNumber = $(git rev-list --count "$ReleaseTag..HEAD") - Add-Content $env:GITHUB_ENV "BUILD_NUMBER=$BuildNumber" New-Item -Name .\artifacts -ItemType Directory env: DISCID_VERSION: 0.6.4 @@ -57,80 +55,73 @@ jobs: - name: Patch build version if: startsWith(github.ref, 'refs/tags/') != true run: | + $ReleaseTag = $(git describe --match "release-*" --abbrev=0 --always HEAD) + $BuildNumber = $(git rev-list --count "$ReleaseTag..HEAD") python setup.py patch_version --platform=$Env:BUILD_NUMBER.$(git rev-parse --short HEAD) - name: Run tests timeout-minutes: 30 run: python setup.py test - - name: Prepare code signing certificate - if: matrix.type != 'store-app' + - name: Prepare clean build environment run: | - If ($Env:CODESIGN_P12_URL -And $Env:AWS_ACCESS_KEY_ID) { - pip install awscli - aws s3 cp "$Env:CODESIGN_P12_URL" .\codesign.pfx - Add-Content $env:GITHUB_ENV "CODESIGN=1" - } 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_P12_URL: ${{ secrets.CODESIGN_P12_URL }} - - name: Build Windows 10 store app package - if: matrix.type == 'store-app' + Remove-Item -Path build,dist/picard,locale -Recurse -ErrorAction Ignore + python setup.py clean + - name: Build run: | - & .\scripts\package\win-package-appx.ps1 -BuildNumber $Env:BUILD_NUMBER - Move-Item .\dist\*.msix .\artifacts + python setup.py build --build-number=$BuildNumber + python setup.py build_ext + pyinstaller --noconfirm --clean picard.spec + If ($env:PICARD_BUILD_PORTABLE -ne "1") { + dist\picard\fpcalc -version + } 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: | - $CertificateFile = ".\codesign.pfx" - $CertificatePassword = ConvertTo-SecureString -String $Env:CODESIGN_P12_PASSWORD -Force -AsPlainText - & .\scripts\package\win-package-appx.ps1 -BuildNumber $Env:BUILD_NUMBER ` - -CertificateFile $CertificateFile -CertificatePassword $CertificatePassword - Move-Item .\dist\*.msix .\artifacts - env: - CODESIGN_P12_PASSWORD: ${{ secrets.CODESIGN_P12_PASSWORD }} + PICARD_BUILD_PORTABLE: ${{ matrix.setup.build-portable }} + PICARD_DISABLE_AUTOUPDATE: ${{ matrix.setup.disable-autoupdate }} + - name: Sign picard.exe + uses: azure/trusted-signing-action@v0.5.0 + if: matrix.setup.type != 'portable' && env.CODESIGN == 'true' + with: + azure-tenant-id: ${{ secrets.AZURE_TENANT_ID }} + azure-client-id: ${{ secrets.AZURE_CLIENT_ID }} + azure-client-secret: ${{ secrets.AZURE_CLIENT_SECRET }} + endpoint: ${{ secrets.AZURE_ENDPOINT }} + trusted-signing-account-name: ${{ secrets.AZURE_CODE_SIGNING_NAME }} + certificate-profile-name: ${{ secrets.AZURE_CERT_PROFILE_NAME }} + files-folder: dist\picard + files-folder-filter: exe + files-folder-recurse: true + timestamp-rfc3161: http://timestamp.acs.microsoft.com + timestamp-digest: SHA256 - name: Build Windows installer - if: matrix.type == 'installer' + if: matrix.setup.type == 'installer' run: | - # choco install nsis - If ($Env:CODESIGN -eq "1") { - $CertificateFile = ".\codesign.pfx" - $CertificatePassword = ConvertTo-SecureString -String $Env:CODESIGN_P12_PASSWORD -Force -AsPlainText - } Else { - $CertificateFile = $null - $CertificatePassword = $null - } - & .\scripts\package\win-package-installer.ps1 -BuildNumber $Env:BUILD_NUMBER ` - -CertificateFile $CertificateFile -CertificatePassword $CertificatePassword + makensis.exe /INPUTCHARSET UTF8 installer\picard-setup.nsi Move-Item .\installer\*.exe .\artifacts - dist\picard\fpcalc -version - env: - CODESIGN_P12_PASSWORD: ${{ secrets.CODESIGN_P12_PASSWORD }} - name: Build Windows portable app - if: matrix.type == 'portable' + if: matrix.setup.type == 'portable' run: | - If ($Env:CODESIGN -eq "1") { - $CertificateFile = ".\codesign.pfx" - $CertificatePassword = ConvertTo-SecureString -String $Env:CODESIGN_P12_PASSWORD -Force -AsPlainText - } Else { - $CertificateFile = $null - $CertificatePassword = $null - } - & .\scripts\package\win-package-portable.ps1 -BuildNumber $Env:BUILD_NUMBER ` - -CertificateFile $CertificateFile -CertificatePassword $CertificatePassword Move-Item .\dist\*.exe .\artifacts - env: - CODESIGN_P12_PASSWORD: ${{ secrets.CODESIGN_P12_PASSWORD }} - - name: Cleanup - if: env.CODESIGN == '1' - run: Remove-Item .\codesign.pfx + - name: Build Windows 10 store app package + if: matrix.setup.type == 'store-app' + run: | + & .\scripts\package\win-package-appx.ps1 dist\picard + Move-Item .\dist\*.msix .\artifacts + - name: Sign final executable + uses: azure/trusted-signing-action@v0.5.0 + if: matrix.setup.type != 'store-app' && env.CODESIGN == 'true' + with: + azure-tenant-id: ${{ secrets.AZURE_TENANT_ID }} + azure-client-id: ${{ secrets.AZURE_CLIENT_ID }} + azure-client-secret: ${{ secrets.AZURE_CLIENT_SECRET }} + endpoint: ${{ secrets.AZURE_ENDPOINT }} + trusted-signing-account-name: ${{ secrets.AZURE_CODE_SIGNING_NAME }} + certificate-profile-name: ${{ secrets.AZURE_CERT_PROFILE_NAME }} + files-folder: artifacts + files-folder-filter: exe + timestamp-rfc3161: http://timestamp.acs.microsoft.com + timestamp-digest: SHA256 - name: Archive production artifacts uses: actions/upload-artifact@v4 - if: matrix.type != 'signed-app' || env.CODESIGN == '1' with: - name: windows-${{ matrix.type }} + name: windows-${{ matrix.setup.type }} path: artifacts/ diff --git a/scripts/package/win-build-fixes.ps1 b/scripts/package/win-build-fixes.ps1 new file mode 100644 index 0000000000..494ce6397f --- /dev/null +++ b/scripts/package/win-build-fixes.ps1 @@ -0,0 +1,18 @@ +# Apply fixes to the build result + +Param( + [ValidateScript({Test-Path $_ -PathType Container})] + [String] + $Path +) + +$ErrorActionPreference = 'Stop' + +# Move all Qt5 DLLs into the main folder to avoid conflicts with system wide +# versions of those dependencies. Since some version PyInstaller tries to +# maintain the file hierarchy of imported modules, but this easily breaks +# DLL loading on Windows. +# Workaround for https://tickets.metabrainz.org/browse/PICARD-2736 +$Qt5BinDir = (Join-Path -Path $Path -ChildPath PyQt5\Qt5\bin) +Move-Item -Path (Join-Path -Path $Qt5BinDir -ChildPath *.dll) -Destination $Path -Force +Remove-Item -Path $Qt5BinDir diff --git a/scripts/package/win-common.ps1 b/scripts/package/win-common.ps1 index 5e8c6d6e7d..e903b8c7c0 100644 --- a/scripts/package/win-common.ps1 +++ b/scripts/package/win-common.ps1 @@ -8,53 +8,6 @@ Param( $CertificatePassword ) -# RFC 3161 timestamp server for code signing -$TimeStampServer = 'http://ts.ssl.com' - -Function CodeSignBinary { - Param( - [ValidateScript({Test-Path $_ -PathType Leaf})] - [String] - $BinaryPath - ) - If ($CertificateFile) { - SignTool sign /v /fd SHA256 /tr "$TimeStampServer" /td sha256 ` - /f "$CertificateFile" /p (ConvertFrom-SecureString -AsPlainText $CertificatePassword) ` - $BinaryPath - ThrowOnExeError "SignTool failed" - } Else { - Write-Output "Skip signing $BinaryPath" - } -} - -Function ThrowOnExeError { - Param( [String]$Message ) - If ($LastExitCode -ne 0) { - Throw $Message - } -} - -Function FinalizePackage { - Param( - [ValidateScript({Test-Path $_ -PathType Container})] - [String] - $Path - ) - - CodeSignBinary -BinaryPath (Join-Path -Path $Path -ChildPath picard.exe) -ErrorAction Stop - CodeSignBinary -BinaryPath (Join-Path -Path $Path -ChildPath fpcalc.exe) -ErrorAction Stop - CodeSignBinary -BinaryPath (Join-Path -Path $Path -ChildPath discid.dll) -ErrorAction Stop - - # Move all Qt5 DLLs into the main folder to avoid conflicts with system wide - # versions of those dependencies. Since some version PyInstaller tries to - # maintain the file hierarchy of imported modules, but this easily breaks - # DLL loading on Windows. - # Workaround for https://tickets.metabrainz.org/browse/PICARD-2736 - $Qt5BinDir = (Join-Path -Path $Path -ChildPath PyQt5\Qt5\bin) - Move-Item -Path (Join-Path -Path $Qt5BinDir -ChildPath *.dll) -Destination $Path -Force - Remove-Item -Path $Qt5BinDir -} - Function DownloadFile { Param( [Parameter(Mandatory = $true)] diff --git a/scripts/package/win-package-appx.ps1 b/scripts/package/win-package-appx.ps1 index 50f41f8664..6941afc510 100644 --- a/scripts/package/win-package-appx.ps1 +++ b/scripts/package/win-package-appx.ps1 @@ -1,72 +1,24 @@ # Build a MSIX app package for Windows 10 Param( - [ValidateScript({ (Test-Path $_ -PathType Leaf) -or (-not $_) })] + [ValidateScript({ Test-Path $_ -PathType Container })] [String] - $CertificateFile, - [SecureString] - $CertificatePassword, - [Int] - $BuildNumber + $PackageDir ) -# Errors are handled explicitly. Otherwise any output to stderr when -# calling classic Windows exes causes a script error. -# TODO: For PowerShell >= 7.3 use $PSNativeCommandUseErrorActionPreference = $true -$ErrorActionPreference = 'Continue' +$ErrorActionPreference = 'Stop' +$PSNativeCommandUseErrorActionPreference = $true -If (-Not $BuildNumber) { - $BuildNumber = 0 -} - -If (-Not $Certificate -And $CertificateFile) { - $Certificate = Get-PfxCertificate -FilePath $CertificateFile -Password $CertificatePassword -} - -$ScriptDirectory = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent -. $ScriptDirectory\win-common.ps1 -CertificateFile $CertificateFile -CertificatePassword $CertificatePassword - -Write-Output "Building Windows 10 app package..." - -# Set the publisher based on the certificate subject -if ($Certificate) { - $env:PICARD_APPX_PUBLISHER = $Certificate.Subject - Write-Output "Publisher: $env:PICARD_APPX_PUBLISHER" -} - -# Build -Remove-Item -Path build,dist/picard,locale -Recurse -ErrorAction Ignore -python setup.py clean 2>&1 | %{ "$_" } -ThrowOnExeError "setup.py clean failed" -python setup.py build --build-number=$BuildNumber --disable-autoupdate 2>&1 | %{ "$_" } -ThrowOnExeError "setup.py build failed" -python setup.py build_ext -i 2>&1 | %{ "$_" } -ThrowOnExeError "setup.py build_ext -i failed" - -# Package application -pyinstaller --noconfirm --clean picard.spec 2>&1 | %{ "$_" } -ThrowOnExeError "PyInstaller failed" -$PackageDir = (Resolve-Path dist\picard) -FinalizePackage $PackageDir +$PackageDir = (Resolve-Path $PackageDir) # Generate resource files Copy-Item appxmanifest.xml $PackageDir $PriConfigFile = (Join-Path (Resolve-Path .\build) priconfig.xml) Push-Location $PackageDir MakePri createconfig /ConfigXml $PriConfigFile /Default en-US /Overwrite -ThrowOnExeError "MakePri createconfig failed" MakePri new /ProjectRoot $PackageDir /ConfigXml $PriConfigFile -ThrowOnExeError "MakePri new failed" Pop-Location # Generate msix package -$PicardVersion = (python -c "import picard; print(picard.__version__)") -If ($CertificateFile -or $Certificate) { - $PackageFile = "dist\MusicBrainz-Picard-$PicardVersion.msix" -} Else { - $PackageFile = "dist\MusicBrainz-Picard-$PicardVersion-unsigned.msix" -} +$PackageFile = "dist\MusicBrainz-Picard-${PicardVersion}_unsigned.msix" MakeAppx pack /o /h SHA256 /d $PackageDir /p $PackageFile -ThrowOnExeError "MakeAppx failed" - -CodeSignBinary -BinaryPath $PackageFile -ErrorAction Stop diff --git a/scripts/package/win-package-installer.ps1 b/scripts/package/win-package-installer.ps1 deleted file mode 100644 index 4653973df1..0000000000 --- a/scripts/package/win-package-installer.ps1 +++ /dev/null @@ -1,43 +0,0 @@ -# Build a Windows installer - -Param( - [ValidateScript({ (Test-Path $_ -PathType Leaf) -or (-not $_) })] - [String] - $CertificateFile, - [SecureString] - $CertificatePassword, - [Int] - $BuildNumber -) - -# Errors are handled explicitly. Otherwise any output to stderr when -# calling classic Windows exes causes a script error. -$ErrorActionPreference = 'Continue' - -If (-Not $BuildNumber) { - $BuildNumber = 0 -} - -$ScriptDirectory = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent -. $ScriptDirectory\win-common.ps1 -CertificateFile $CertificateFile -CertificatePassword $CertificatePassword - -Write-Output "Building Windows installer..." - -# Build -Remove-Item -Path build,dist/picard,locale -Recurse -ErrorAction Ignore -python setup.py clean 2>&1 | %{ "$_" } -ThrowOnExeError "setup.py clean failed" -python setup.py build --build-number=$BuildNumber 2>&1 | %{ "$_" } -ThrowOnExeError "setup.py build failed" -python setup.py build_ext -i 2>&1 | %{ "$_" } -ThrowOnExeError "setup.py build_ext -i failed" - -# Package application -pyinstaller --noconfirm --clean picard.spec 2>&1 | %{ "$_" } -ThrowOnExeError "PyInstaller failed" -FinalizePackage dist\picard - -# Build the installer -makensis.exe /INPUTCHARSET UTF8 installer\picard-setup.nsi 2>&1 | %{ "$_" } -ThrowOnExeError "NSIS failed" -CodeSignBinary -BinaryPath installer\picard-setup-*.exe -ErrorAction Stop diff --git a/scripts/package/win-package-portable.ps1 b/scripts/package/win-package-portable.ps1 deleted file mode 100644 index 79b4633efc..0000000000 --- a/scripts/package/win-package-portable.ps1 +++ /dev/null @@ -1,39 +0,0 @@ -# Build a portable app - -Param( - [ValidateScript({ (Test-Path $_ -PathType Leaf) -or (-not $_) })] - [String] - $CertificateFile, - [SecureString] - $CertificatePassword, - [Int] - $BuildNumber -) - -# Errors are handled explicitly. Otherwise any output to stderr when -# calling classic Windows exes causes a script error. -$ErrorActionPreference = 'Continue' - -If (-Not $BuildNumber) { - $BuildNumber = 0 -} - -$ScriptDirectory = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent -. $ScriptDirectory\win-common.ps1 -CertificateFile $CertificateFile -CertificatePassword $CertificatePassword - -Write-Output "Building portable exe..." - -# Build -Remove-Item -Path build,locale -Recurse -ErrorAction Ignore -python setup.py clean 2>&1 | %{ "$_" } -ThrowOnExeError "setup.py clean failed" -python setup.py build --build-number=$BuildNumber 2>&1 | %{ "$_" } -ThrowOnExeError "setup.py build failed" -python setup.py build_ext -i 2>&1 | %{ "$_" } -ThrowOnExeError "setup.py build_ext -i failed" - -# Package application -$env:PICARD_BUILD_PORTABLE = '1' -pyinstaller --noconfirm --clean picard.spec 2>&1 | %{ "$_" } -ThrowOnExeError "PyInstaller failed" -CodeSignBinary -BinaryPath dist\MusicBrainz-Picard-*.exe -ErrorAction Stop