Build Dev Release #249
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Build Dev Release | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| cx_freeze_version: | |
| description: 'cx_Freeze version to use' | |
| required: true | |
| default: 'dev' | |
| type: choice | |
| options: | |
| - stable | |
| - dev | |
| permissions: | |
| contents: read | |
| env: | |
| PYTHON_VERSION: '3.14' | |
| jobs: | |
| build: | |
| permissions: | |
| contents: write | |
| strategy: | |
| matrix: | |
| include: | |
| - arch: x64 | |
| runner: windows-latest | |
| python_arch: x64 | |
| artifact_suffix: x64 | |
| unsigned_exe_name: unsigned-exes-x64 | |
| unsigned_msi_name: unsigned-msi-x64 | |
| - arch: arm64 # Temporarily skipped due to build issues | |
| runner: windows-11-arm | |
| python_arch: arm64 | |
| artifact_suffix: aarch64 | |
| unsigned_exe_name: unsigned-exes-arm64 | |
| unsigned_msi_name: unsigned-msi-arm64 | |
| runs-on: ${{ matrix.runner }} | |
| name: Build (${{ matrix.arch }}) | |
| steps: | |
| - name: Checkout Repository | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: ${{ env.PYTHON_VERSION }} | |
| architecture: ${{ matrix.python_arch }} | |
| - name: Create virtual environment | |
| run: | | |
| python -m venv venv | |
| shell: pwsh | |
| - name: Get App Info | |
| id: get_info | |
| run: | | |
| .\venv\Scripts\Activate | |
| $currentDateTime = Get-Date -Format "yyyy-MM-dd HH:mm:ss UTC" | |
| echo "BUILD_DATETIME=$currentDateTime" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append | |
| $commitHash = git rev-parse --short HEAD | |
| echo "COMMIT_HASH=$commitHash" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append | |
| # Also expose as step outputs for use in later expression fields | |
| echo "BUILD_DATETIME=$currentDateTime" | Out-File -FilePath $env:GITHUB_OUTPUT -Encoding utf8 -Append | |
| echo "COMMIT_HASH=$commitHash" | Out-File -FilePath $env:GITHUB_OUTPUT -Encoding utf8 -Append | |
| shell: pwsh | |
| - name: Update Release Channel | |
| run: | | |
| .\venv\Scripts\Activate | |
| $settingsPath = "src/settings.py" | |
| $content = Get-Content $settingsPath -Raw | |
| $replacement = 'RELEASE_CHANNEL = "dev-' + $env:COMMIT_HASH + '"' | |
| $content = $content -replace 'RELEASE_CHANNEL = "stable"', $replacement | |
| Set-Content -Path $settingsPath -Value $content -NoNewline | |
| Write-Host "Updated RELEASE_CHANNEL to dev-$env:COMMIT_HASH" | |
| shell: pwsh | |
| - name: Install dependencies | |
| run: | | |
| .\venv\Scripts\Activate | |
| python -m pip install --upgrade pip | |
| pip install --force --no-cache .[packaging] | |
| $cxFreezeVersion = "${{ github.event.inputs.cx_freeze_version }}" | |
| if ($cxFreezeVersion -eq "dev") { | |
| Write-Host "Installing cx_Freeze dev version from GitHub" | |
| pip install git+https://github.com/amnweb/cx_Freeze.git@fix/msi-product-name | |
| pip install git+https://github.com/amnweb/python-msilib --force --no-cache | |
| } | |
| shell: pwsh | |
| - name: Build EXE | |
| run: | | |
| .\venv\Scripts\Activate | |
| cd src | |
| python build.py build | |
| shell: pwsh | |
| - name: Upload unsigned EXE artifacts | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: ${{ matrix.unsigned_exe_name }} | |
| path: | | |
| src/dist/yasb.exe | |
| src/dist/yasbc.exe | |
| src/dist/yasb_themes.exe | |
| - name: Get unsigned-exes artifact id | |
| id: get_exes_artifact | |
| uses: actions/github-script@v7 | |
| env: | |
| ARTIFACT_NAME: ${{ matrix.unsigned_exe_name }} | |
| with: | |
| github-token: ${{ secrets.PAT }} | |
| script: | | |
| const { owner, repo } = context.repo; | |
| const run_id = context.runId; | |
| const expectedName = process.env.ARTIFACT_NAME; | |
| const res = await github.rest.actions.listWorkflowRunArtifacts({ owner, repo, run_id }); | |
| const artifact = res.data.artifacts.find(a => a.name === expectedName); | |
| if (!artifact) throw new Error(`${expectedName} artifact not found`); | |
| return artifact.id; | |
| - name: Submit EXE signing request | |
| id: sign_exes | |
| uses: signpath/github-action-submit-signing-request@v1 | |
| with: | |
| api-token: '${{ secrets.SIGN_TOKEN }}' | |
| organization-id: '9efb6764-d1fc-46c5-b050-5ef07bb67a8c' | |
| project-slug: 'yasb' | |
| signing-policy-slug: '${{ secrets.SIGN_POLICY_SLUG }}' | |
| artifact-configuration-slug: 'signing_executable' | |
| github-artifact-id: '${{ steps.get_exes_artifact.outputs.result }}' | |
| wait-for-completion: 'true' | |
| output-artifact-directory: 'src/signed' | |
| - name: Replace unsigned EXE with signed | |
| if: steps.sign_exes.outcome == 'success' | |
| run: | | |
| .\venv\Scripts\Activate | |
| $signedDir = 'src/signed' | |
| if (-not (Test-Path $signedDir)) { | |
| Write-Host "Signed artifacts directory $signedDir not found. Ensure SignPath places signed files there."; | |
| exit 1 | |
| } | |
| # Copy signed EXEs into the distribution folder; fail if none found | |
| $signedExes = Get-ChildItem -Path $signedDir -File -Filter '*.exe' -Recurse -ErrorAction SilentlyContinue | |
| if ($null -eq $signedExes -or $signedExes.Count -eq 0) { | |
| Write-Error "No signed .exe files found in $signedDir after extraction. Failing the job." | |
| exit 1 | |
| } | |
| Write-Host "Copying signed EXEs from $signedDir to src/dist" | |
| foreach ($f in $signedExes) { | |
| Copy-Item -Path $f.FullName -Destination (Join-Path 'src/dist' $f.Name) -Force | |
| } | |
| # Clean up signed directory after successful copy | |
| try { | |
| Get-ChildItem -Path $signedDir -Recurse -Force | Remove-Item -Force -Recurse | |
| Write-Host "Cleaned up $signedDir" | |
| } catch { | |
| Write-Warning "Failed to clean up ${signedDir}: $($_.Exception.Message)" | |
| } | |
| shell: pwsh | |
| - name: Build MSI | |
| run: | | |
| .\venv\Scripts\Activate | |
| cd src | |
| python build.py bdist_msi | |
| shell: pwsh | |
| - name: Upload unsigned MSI | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: ${{ matrix.unsigned_msi_name }} | |
| path: src/dist/out/*.msi | |
| - name: Get unsigned-msi artifact id | |
| id: get_msi_artifact | |
| uses: actions/github-script@v7 | |
| env: | |
| ARTIFACT_NAME: ${{ matrix.unsigned_msi_name }} | |
| with: | |
| github-token: ${{ secrets.PAT }} | |
| script: | | |
| const { owner, repo } = context.repo; | |
| const run_id = context.runId; | |
| const expectedName = process.env.ARTIFACT_NAME; | |
| const res = await github.rest.actions.listWorkflowRunArtifacts({ owner, repo, run_id }); | |
| const artifact = res.data.artifacts.find(a => a.name === expectedName); | |
| if (!artifact) throw new Error(`${expectedName} artifact not found`); | |
| return artifact.id; | |
| - name: Submit MSI signing request | |
| id: sign_msi | |
| uses: signpath/github-action-submit-signing-request@v1 | |
| with: | |
| api-token: '${{ secrets.SIGN_TOKEN }}' | |
| organization-id: '9efb6764-d1fc-46c5-b050-5ef07bb67a8c' | |
| project-slug: 'yasb' | |
| signing-policy-slug: '${{ secrets.SIGN_POLICY_SLUG }}' | |
| artifact-configuration-slug: 'signing_installer' | |
| github-artifact-id: '${{ steps.get_msi_artifact.outputs.result }}' | |
| wait-for-completion: 'true' | |
| output-artifact-directory: 'src/signed' | |
| - name: Replace unsigned MSI with signed | |
| if: steps.sign_msi.outcome == 'success' | |
| run: | | |
| .\venv\Scripts\Activate | |
| $signedDir = 'src/signed' | |
| if (-not (Test-Path $signedDir)) { | |
| Write-Host "Signed artifacts directory $signedDir not found. Ensure SignPath places signed files there."; | |
| exit 1 | |
| } | |
| # Copy signed MSIs into the output folder; fail if none found | |
| $signedMsis = Get-ChildItem -Path $signedDir -File -Filter '*.msi' -Recurse -ErrorAction SilentlyContinue | |
| if ($null -eq $signedMsis -or $signedMsis.Count -eq 0) { | |
| Write-Error "No signed .msi files found in $signedDir after extraction. Failing the job." | |
| exit 1 | |
| } | |
| Write-Host "Copying signed MSIs from $signedDir to src/dist/out" | |
| foreach ($f in $signedMsis) { | |
| Copy-Item -Path $f.FullName -Destination (Join-Path 'src/dist/out' $f.Name) -Force | |
| } | |
| # Clean up signed directory after successful copy | |
| try { | |
| Get-ChildItem -Path $signedDir -Recurse -Force | Remove-Item -Force -Recurse | |
| Write-Host "Cleaned up $signedDir" | |
| } catch { | |
| Write-Warning "Failed to clean up ${signedDir}: $($_.Exception.Message)" | |
| } | |
| shell: pwsh | |
| - name: Upload Artifacts | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: yasb-dev-${{ steps.get_info.outputs.COMMIT_HASH }}-${{ matrix.artifact_suffix }} | |
| path: | | |
| src/dist/out/*.msi | |
| retention-days: 10 | |
| - name: Delete Artifacts | |
| uses: geekyeggo/delete-artifact@v5 | |
| with: | |
| name: | | |
| unsigned-* | |
| signed-* | |
| publish_dev_release: | |
| needs: build | |
| permissions: | |
| contents: write | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout Repository | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| ref: ${{ github.ref }} | |
| - name: Set release metadata | |
| id: release_info | |
| run: | | |
| currentDateTime=$(date -u +"%Y-%m-%d %H:%M:%S UTC") | |
| echo "BUILD_DATETIME=$currentDateTime" >> "$GITHUB_ENV" | |
| commitHash=$(git rev-parse --short HEAD) | |
| echo "COMMIT_HASH=$commitHash" >> "$GITHUB_ENV" | |
| echo "COMMIT_HASH=$commitHash" >> "$GITHUB_OUTPUT" | |
| - name: Generate Changelog | |
| run: | | |
| latestVersionTag=$(git tag --sort=-version:refname | grep -E "^v[0-9]+\.[0-9]+\.[0-9]+" | head -n 1 || true) | |
| if [ -n "$latestVersionTag" ]; then | |
| commits=$(git log "$latestVersionTag..HEAD" --pretty=format:"* %s %h" --no-merges) | |
| else | |
| commits=$(git log -n 20 --pretty=format:"* %s %h" --no-merges) | |
| fi | |
| if [ -z "$commits" ]; then | |
| if [ -n "$latestVersionTag" ]; then | |
| commits="* No significant changes detected since $latestVersionTag" | |
| else | |
| commits="* No significant changes detected" | |
| fi | |
| fi | |
| printf '%s\n' "$commits" > CHANGELOG.md | |
| - name: Download MSI artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| pattern: yasb-dev-* | |
| path: artifacts | |
| merge-multiple: true | |
| - name: Generate Checksums | |
| run: | | |
| cd artifacts | |
| sha256sum *.msi > checksums.txt | |
| - name: Delete existing dev release | |
| run: | | |
| gh release delete dev --yes || true | |
| git tag -d dev || true | |
| git push origin :refs/tags/dev || true | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| - name: Create GitHub Release | |
| uses: softprops/action-gh-release@v1 | |
| with: | |
| name: YASB Pre-release (${{ steps.release_info.outputs.COMMIT_HASH }}) | |
| tag_name: dev | |
| prerelease: true | |
| files: | | |
| artifacts/*.msi | |
| artifacts/checksums.txt | |
| body_path: CHANGELOG.md | |