Skip to content

v1.1.0

v1.1.0 #17

Workflow file for this run

name: Release
on:
workflow_dispatch:
inputs:
platform:
description: 'Platform to build'
required: false
default: 'all'
type: choice
options:
- all
- macos
- linux
- windows
release:
types: [published]
permissions:
contents: write
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
jobs:
build-macos:
name: Build macOS (ARM64)
if: >
github.event_name == 'release' ||
inputs.platform == 'all' || inputs.platform == 'macos' || inputs.platform == ''
runs-on: [macOS, ARM64, studio]
timeout-minutes: 30
steps:
- uses: actions/checkout@v4
- name: Setup Tauri build environment
uses: ./.github/actions/setup-tauri-build
- name: Import Apple certificate
env:
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
run: |
KEYCHAIN_PATH="$HOME/Library/Keychains/ci_signing.keychain-db"
echo $APPLE_CERTIFICATE | base64 --decode > certificate.p12
security create-keychain -p "$KEYCHAIN_PASSWORD" ci_signing.keychain
security default-keychain -s ci_signing.keychain
security unlock-keychain -p "$KEYCHAIN_PASSWORD" ci_signing.keychain
security set-keychain-settings -t 3600 -u ci_signing.keychain
security list-keychains -d user -s ci_signing.keychain login.keychain
security import certificate.p12 -k ci_signing.keychain \
-P "$APPLE_CERTIFICATE_PASSWORD" -T /usr/bin/codesign
security set-key-partition-list -S apple-tool:,apple:,codesign: \
-s -k "$KEYCHAIN_PASSWORD" ci_signing.keychain
security find-identity -v -p codesigning ci_signing.keychain
rm certificate.p12
- name: Decode App Store Connect API key
env:
APPLE_API_KEY_B64: ${{ secrets.APPLE_API_KEY_B64 }}
run: |
echo "$APPLE_API_KEY_B64" | base64 --decode > /tmp/auth_key.p8
- name: Build binary
env:
GITHUB_TOKEN: ${{ github.token }}
LASTFM_API_KEY: ${{ secrets.LASTFM_API_KEY }}
LASTFM_API_SECRET: ${{ secrets.LASTFM_API_SECRET }}
run: task ci:build TARGET=aarch64-apple-darwin
- name: Bundle and sign
env:
APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }}
run: task ci:bundle TARGET=aarch64-apple-darwin
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: macos-arm64
path: |
target/aarch64-apple-darwin/release/bundle/dmg/*.dmg
target/aarch64-apple-darwin/release/bundle/macos/*.app
retention-days: 7
- name: Notarize
env:
APPLE_API_KEY: ${{ secrets.APPLE_API_KEY }}
APPLE_API_ISSUER: ${{ secrets.APPLE_API_ISSUER }}
run: task ci:notarize TARGET=aarch64-apple-darwin
- name: Upload release assets
if: github.event_name == 'release'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh release upload "${{ github.event.release.tag_name }}" \
target/aarch64-apple-darwin/release/bundle/dmg/*.dmg
- name: Cleanup CI keychain
if: always()
run: |
security delete-keychain ci_signing.keychain || true
rm -f /tmp/auth_key.p8
build-linux-amd64:
name: Build Linux (amd64)
if: >
github.event_name == 'release' ||
inputs.platform == 'all' || inputs.platform == 'linux' || inputs.platform == ''
runs-on: blacksmith-4vcpu-ubuntu-2404
timeout-minutes: 30
steps:
- uses: actions/checkout@v4
- name: Setup Tauri build environment
uses: ./.github/actions/setup-tauri-build
- name: Build binary
env:
GITHUB_TOKEN: ${{ github.token }}
LASTFM_API_KEY: ${{ secrets.LASTFM_API_KEY }}
LASTFM_API_SECRET: ${{ secrets.LASTFM_API_SECRET }}
run: task ci:build TARGET=x86_64-unknown-linux-gnu
- name: Bundle
run: task ci:bundle TARGET=x86_64-unknown-linux-gnu BUNDLES=deb
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: linux-amd64
path: target/x86_64-unknown-linux-gnu/release/bundle/deb/*.deb
retention-days: 7
- name: Upload release assets
if: github.event_name == 'release'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh release upload "${{ github.event.release.tag_name }}" \
target/x86_64-unknown-linux-gnu/release/bundle/deb/*.deb
build-linux-arm64:
name: Build Linux (ARM64)
if: >
github.event_name == 'release' ||
inputs.platform == 'all' || inputs.platform == 'linux' || inputs.platform == ''
runs-on: blacksmith-4vcpu-ubuntu-2404
timeout-minutes: 60
steps:
- uses: actions/checkout@v4
- name: Install Task
uses: go-task/setup-task@v1
- name: Restore Taskfile fingerprint cache
uses: actions/cache@v4
with:
path: .task
key: task-${{ runner.os }}-${{ hashFiles('taskfiles/ci.yml') }}
restore-keys: |
task-${{ runner.os }}-
- name: Setup Blacksmith Builder
uses: useblacksmith/setup-docker-builder@v1
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
with:
platforms: arm64
- name: Build ARM64 .deb
run: |
docker buildx build \
--platform linux/arm64 \
--file docker/Dockerfile.linux-arm64 \
--build-arg LASTFM_API_KEY=${{ secrets.LASTFM_API_KEY }} \
--build-arg LASTFM_API_SECRET=${{ secrets.LASTFM_API_SECRET }} \
--target artifacts \
--output type=local,dest=dist/linux-arm64 \
.
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: linux-arm64
path: dist/linux-arm64/*.deb
retention-days: 7
- name: Upload release assets
if: github.event_name == 'release'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh release upload "${{ github.event.release.tag_name }}" \
dist/linux-arm64/*.deb
build-windows:
name: Build Windows (x64)
if: >
github.event_name == 'release' ||
inputs.platform == 'all' || inputs.platform == 'windows' || inputs.platform == ''
runs-on: [self-hosted, Windows, X64]
timeout-minutes: 45
steps:
- name: Bootstrap Windows prerequisites
shell: powershell
run: |
$ProgressPreference = 'SilentlyContinue'
$toInstall = @()
if (-not (Get-Command git -ErrorAction SilentlyContinue)) { $toInstall += 'git' }
if (-not (Get-Command pwsh -ErrorAction SilentlyContinue)) { $toInstall += 'pwsh' }
if ($toInstall.Count -gt 0) {
choco install @toInstall -y
}
$gitPath = (Get-ItemProperty 'HKLM:\SOFTWARE\GitForWindows' -ErrorAction SilentlyContinue).InstallPath
if ($gitPath) {
echo "$gitPath\cmd" >> $env:GITHUB_PATH
}
- uses: actions/checkout@v4
- name: Setup Tauri build environment
uses: ./.github/actions/setup-tauri-build
- name: Install Windows SDK (signtool)
shell: pwsh
run: |
choco install windows-sdk-10.1 -y
$signtool = Get-ChildItem -Path "${env:ProgramFiles(x86)}\Windows Kits\10\bin" `
-Recurse -Filter signtool.exe | Where-Object { $_.FullName -match '\\x64\\' } `
| Sort-Object { [version]($_.FullName -replace '.*\\(\d+\.\d+\.\d+\.\d+)\\.*','$1') } `
| Select-Object -Last 1 -ExpandProperty FullName
echo "SIGNTOOL_PATH=$signtool" >> $env:GITHUB_ENV
- name: Generate self-signed code signing certificate
shell: pwsh
env:
WINDOWS_CERT_PASSWORD: ${{ secrets.WINDOWS_CERT_PASSWORD }}
run: |
$password = ConvertTo-SecureString -String $env:WINDOWS_CERT_PASSWORD -Force -AsPlainText
$cert = New-SelfSignedCertificate -Type CodeSigningCert -Subject 'CN=MT' `
-CertStoreLocation Cert:\CurrentUser\My -NotAfter (Get-Date).AddYears(5)
Export-PfxCertificate -Cert $cert -FilePath "${{ runner.temp }}\mt-cert.pfx" -Password $password
echo "CERT_PATH=${{ runner.temp }}\mt-cert.pfx" >> $env:GITHUB_ENV
- name: Write signing config override
shell: pwsh
env:
WINDOWS_CERT_PASSWORD: ${{ secrets.WINDOWS_CERT_PASSWORD }}
run: |
$signScript = Join-Path "${{ runner.temp }}" 'sign.cmd'
@"
@echo off
"$env:SIGNTOOL_PATH" sign /f "$env:CERT_PATH" /p "$env:WINDOWS_CERT_PASSWORD" /t http://timestamp.digicert.com /fd SHA256 %1
"@ | Out-File -FilePath $signScript -Encoding ascii
$config = @{
build = @{ beforeBuildCommand = "" }
bundle = @{ windows = @{ signCommand = @{ cmd = "cmd"; args = @("/C", $signScript, "%1") } } }
} | ConvertTo-Json -Depth 5
$configPath = "${{ runner.temp }}\sign-override.json"
$config | Out-File -FilePath $configPath -Encoding utf8
echo "SIGN_CONFIG_PATH=$configPath" >> $env:GITHUB_ENV
- name: Build binary
shell: pwsh
env:
LASTFM_API_KEY: ${{ secrets.LASTFM_API_KEY }}
LASTFM_API_SECRET: ${{ secrets.LASTFM_API_SECRET }}
run: task ci:build TARGET=x86_64-pc-windows-msvc CONFIG=${{ env.SIGN_CONFIG_PATH }}
- name: Bundle NSIS installer
shell: pwsh
run: task ci:bundle TARGET=x86_64-pc-windows-msvc BUNDLES=nsis CONFIG=${{ env.SIGN_CONFIG_PATH }}
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: windows-x64
path: target/x86_64-pc-windows-msvc/release/bundle/nsis/*.exe
retention-days: 7
- name: Upload release assets
if: github.event_name == 'release'
shell: pwsh
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh release upload "${{ github.event.release.tag_name }}" (Get-Item target/x86_64-pc-windows-msvc/release/bundle/nsis/*.exe)
- name: Cleanup certificate
if: always()
shell: pwsh
run: |
Remove-Item -Force "${{ runner.temp }}\mt-cert.pfx" -ErrorAction SilentlyContinue
Remove-Item -Force "${{ runner.temp }}\sign-override.json" -ErrorAction SilentlyContinue
Get-ChildItem Cert:\CurrentUser\My -CodeSigningCert | Where-Object { $_.Subject -eq 'CN=MT' } | Remove-Item
update-readme:
name: Update README download links
needs: [build-macos, build-linux-amd64, build-linux-arm64, build-windows]
if: github.event_name == 'release'
runs-on: blacksmith-4vcpu-ubuntu-2404
steps:
- uses: actions/checkout@v4
with:
ref: main
token: ${{ secrets.GITHUB_TOKEN }}
- name: Update download table
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAG: ${{ github.event.release.tag_name }}
run: |
python3 << 'EOF'
import json, os, re, subprocess
tag = os.environ['TAG']
result = subprocess.run(
['gh', 'api', f'repos/pythoninthegrass/mt/releases/tags/{tag}'],
capture_output=True, text=True, check=True
)
assets = json.loads(result.stdout)['assets']
PLATFORM_MAP = [
('.dmg', 'macOS', 'Apple Silicon (ARM64)'),
('amd64', 'Linux', 'x86_64 (amd64)'),
('arm64', 'Linux', 'ARM64'),
('.exe', 'Windows', 'x64'),
]
rows = []
for asset in sorted(assets, key=lambda a: a['name']):
name = asset['name']
url = asset['browser_download_url']
for key, platform, arch in PLATFORM_MAP:
if key in name:
rows.append(f'| {platform} | {arch} | [{name}]({url}) |')
break
table = '\n'.join([
'| Platform | Architecture | Download |',
'|----------|--------------|----------|',
*rows,
])
section = f'<!-- DOWNLOADS:START -->\n{table}\n<!-- DOWNLOADS:END -->'
readme = open('README.md').read()
updated = re.sub(
r'<!-- DOWNLOADS:START -->.*?<!-- DOWNLOADS:END -->',
section, readme, flags=re.DOTALL
)
open('README.md', 'w').write(updated)
print(f"Updated README with {len(rows)} download link(s)")
EOF
- name: Commit and push
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add README.md
git diff --staged --quiet || git commit -m "chore: update download links for ${{ github.event.release.tag_name }} [skip ci]"
git push origin main