Skip to content

Build Dev Release

Build Dev Release #249

Workflow file for this run

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