Ir al contenido

Compilar en CI con GitHub Actions

Como cada sistema compila su propia app, la forma más fácil de publicarlas todas es dejar que GitHub las compile en sus propias máquinas Windows, macOS y Linux (“runners”), en x64 y ARM, cada vez que publicas una versión.

Ventana de terminal
uv run pyzed build --workflow

Escribe .github/workflows/build.yml, con un trabajo por cada destino de targets en [tool.pyzed.build] (por defecto Windows x64, macOS en Apple silicon y Linux x64). En Pyzed Design, marca las plataformas en Archivo → Exportar aplicación… → Plataformas y pulsa Escribir workflow de CI (Exportar tu app).

.github/workflows/build.yml
name: Build
# Builds the app for each target with `pyzed build` and keeps the result as an
# artifact (Actions -> this run -> Artifacts). The backends cannot cross-compile, so
# every platform and architecture builds on its own runner.
on:
push:
tags: ["v*"]
workflow_dispatch:
jobs:
build:
name: Build ${{ matrix.target }}
runs-on: ${{ matrix.runner }}
strategy:
fail-fast: false
matrix:
include:
- { target: windows-x64, runner: windows-latest }
- { target: macos-arm64, runner: macos-latest }
- { target: linux-x64, runner: ubuntu-22.04 }
steps:
- uses: actions/checkout@v4
- uses: astral-sh/setup-uv@v6
- run: uv sync --locked
- run: uv run pyzed build --target ${{ matrix.target }}
- uses: actions/upload-artifact@v4
with:
name: shop-${{ matrix.target }}
path: dist/

--target hace que cada trabajo compruebe que su máquina compila lo que dice la matriz. El empaquetador, el icono, la pantalla de inicio y el resto de ajustes salen de pyproject.toml, igual que en tu equipo.

  1. Haz commit del flujo y de tu uv.lock (la compilación usa uv sync --locked, así que el archivo de bloqueo tiene que estar al día).

  2. Sube una etiqueta de versión:

    Ventana de terminal
    git tag v1.0.0
    git push origin v1.0.0

    O lánzalo a mano: Actions → Build → Run workflow.

  3. Cuando termine, descarga las compilaciones desde la página de la ejecución, en Artifacts.

Destino Runner Compila para
windows-x64 windows-latest Windows 10 y 11 en Intel y AMD
windows-arm64 windows-11-arm Windows 11 en ARM
macos-arm64 macos-latest Macs con Apple silicon
macos-x64 macos-15-intel Macs con Intel
linux-x64 ubuntu-22.04 Linux en Intel y AMD
linux-arm64 ubuntu-22.04-arm Linux en ARM

Los runners de Linux son a propósito el Ubuntu más antiguo que ofrece GitHub: la app funciona con la glibc del runner o una más nueva (Linux). Con backend = "nuitka" todos los runners ya tienen el compilador de C que necesita Nuitka.

Los artifacts caducan pasado un tiempo y piden iniciar sesión en GitHub para descargarlos. Para dar a la gente una página de descarga permanente, fija archive antes de escribir el flujo:

pyproject.toml
[tool.pyzed.build]
archive = "zip"

Cada compilación empaqueta entonces la app como <app>-<sistema>-<arq>.zip (shop-windows-x86_64.zip, shop-macos-arm64.zip, shop-linux-x86_64.zip), los nombres que busca la autoactualización, y el flujo gana un último paso que lo adjunta a la Release de la etiqueta (y el permiso para crearla):

.github/workflows/build.yml (lo que añade archive)
jobs:
build:
permissions:
contents: write
steps:
# ... la compilación, y luego:
- name: Attach to the GitHub Release
if: startsWith(github.ref, 'refs/tags/v')
shell: bash
env:
GH_TOKEN: ${{ github.token }}
run: |
# the first build to get here creates the release; the others only upload
gh release create "$GITHUB_REF_NAME" --title "$GITHUB_REF_NAME" --verify-tag || true
gh release upload "$GITHUB_REF_NAME" dist/*.zip --clobber

En macOS el zip se crea con ditto, que conserva los enlaces simbólicos y la firma del paquete. Si firmas la app, fírmala antes de comprimirla: fija archive solo después de añadir el paso de firma, o comprime tú tras firmar.

Guarda los certificados en secretos de GitHub (Settings → Secrets and variables → Actions), nunca en el repositorio. Luego decodifícalos en un paso antes de firmar. Es lo que hace el flujo de versiones de Pyzed para Pyzed Design:

Guarda el archivo .pfx en base64 en WINDOWS_CERTIFICATE y su contraseña en WINDOWS_CERTIFICATE_PASSWORD:

- name: Sign
if: runner.os == 'Windows'
shell: bash
env:
CERT: ${{ secrets.WINDOWS_CERTIFICATE }}
PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }}
run: |
echo "$CERT" | base64 --decode > "$RUNNER_TEMP/cert.pfx"
signtool=$(ls "/c/Program Files (x86)/Windows Kits/10/bin/"*/x64/signtool.exe | tail -1)
"$signtool" sign /f "$RUNNER_TEMP/cert.pfx" /p "$PASSWORD" /fd sha256 \
/tr http://timestamp.digicert.com /td sha256 dist/Shop/Shop.exe

Pon el paso de firma después de uv run pyzed build y antes de comprimir. Mira Windows y macOS para saber qué hace cada comando.