Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 47 additions & 3 deletions .github/workflows/build-binaries.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@ name: Build binaries

# Freezes a standalone `becwright` binary per platform with PyInstaller.
# These artifacts are what the npm packages ship, so users without Python can
# install becwright via npm/pnpm. Release publishing is wired in publish.yml.
# install becwright via npm/pnpm. Release publishing is wired in release.yml.
#
# macOS is built once as a universal2 binary (Intel + Apple Silicon) on the
# Apple Silicon runner, then served for both the darwin-arm64 and darwin-x64 npm
# packages — GitHub's Intel macOS runners are unreliable, so we don't depend on
# them.
on:
workflow_dispatch:
workflow_call: # invoked by release.yml on a published release
Expand All @@ -17,17 +22,46 @@ jobs:
include:
- { os: ubuntu-latest, target: linux-x64, ext: "" }
- { os: ubuntu-24.04-arm, target: linux-arm64, ext: "" }
- { os: macos-14, target: darwin-arm64, ext: "" }
- { os: macos-14, target: darwin-universal2, ext: "" }
- { os: windows-latest, target: win32-x64, ext: ".exe" }
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5

# --- Standard build (Linux / Windows): host-arch binary ---
- name: Set up Python
if: matrix.target != 'darwin-universal2'
uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install
if: matrix.target != 'darwin-universal2'
run: pip install ".[build]"
- name: Build
if: matrix.target != 'darwin-universal2'
run: pyinstaller --clean --noconfirm packaging/becwright.spec

# --- macOS universal2 build (Intel + Apple Silicon in one binary) ---
# setup-python is arch-specific, so use the python.org universal2 framework
# build. pyyaml ships an arch-specific C extension; drop it so the bundle is
# pure-Python and the result is cleanly universal2 (becwright only needs
# yaml.safe_load/dump, which the pure-Python loader provides).
- name: Build universal2 (macOS)
if: matrix.target == 'darwin-universal2'
env:
BECWRIGHT_TARGET_ARCH: universal2
PYVER: "3.12.8"
run: |
set -euo pipefail
curl -sSLo /tmp/python.pkg "https://www.python.org/ftp/python/${PYVER}/python-${PYVER}-macos11.pkg"
sudo installer -pkg /tmp/python.pkg -target /
PY=/Library/Frameworks/Python.framework/Versions/3.12/bin/python3
"$PY" -m pip install --upgrade pip
"$PY" -m pip install ".[build]"
SITE="$("$PY" -c 'import sysconfig; print(sysconfig.get_paths()["purelib"])')"
find "$SITE" -name "_yaml*.so" -delete || true
"$PY" -m PyInstaller --clean --noconfirm packaging/becwright.spec
echo "--- lipo ---"; lipo -info dist/becwright

- name: Smoke test
shell: bash
run: |
Expand All @@ -39,6 +73,16 @@ jobs:
echo "forbid should have exited non-zero on a match"; exit 1
fi
echo "frozen 'run' dispatch works"

- name: Smoke test Intel slice via Rosetta (macOS universal2)
if: matrix.target == 'darwin-universal2'
run: |
set -euo pipefail
softwareupdate --install-rosetta --agree-to-license || true
arch -x86_64 dist/becwright --version
arch -x86_64 dist/becwright list >/dev/null
echo "Intel slice runs under Rosetta"

- uses: actions/upload-artifact@v4
with:
name: becwright-${{ matrix.target }}
Expand Down
4 changes: 3 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ jobs:
run: |
node npm/stage.mjs linux-x64 artifacts/becwright-linux-x64/becwright
node npm/stage.mjs linux-arm64 artifacts/becwright-linux-arm64/becwright
node npm/stage.mjs darwin-arm64 artifacts/becwright-darwin-arm64/becwright
# One universal2 macOS binary serves both Apple Silicon and Intel.
node npm/stage.mjs darwin-arm64 artifacts/becwright-darwin-universal2/becwright
node npm/stage.mjs darwin-x64 artifacts/becwright-darwin-universal2/becwright
node npm/stage.mjs win32-x64 artifacts/becwright-win32-x64/becwright.exe
- name: Set version from tag
run: node npm/set-version.mjs "${GITHUB_REF_NAME#v}"
Expand Down
2 changes: 1 addition & 1 deletion README.es.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ becwright init # detecta tu lenguaje, escribe .bec/rules.ya

Instalado como devDependency, el hook de pre-commit resuelve el binario local
desde `node_modules/.bin`, así funciona sin instalación global. Los paquetes npm
cubren `linux-x64`, `linux-arm64`, `darwin-arm64` y `win32-x64`; en
cubren `linux-x64`, `linux-arm64`, `darwin-x64`, `darwin-arm64` y `win32-x64`; en
cualquier otra plataforma usá `pipx install becwright`.

Comandos disponibles:
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ becwright init # detects your language, writes .bec/rules.y

Installed as a devDependency, the pre-commit hook resolves the local binary from
`node_modules/.bin`, so it works without a global install. The npm packages cover
`linux-x64`, `linux-arm64`, `darwin-arm64` and `win32-x64`; on any
`linux-x64`, `linux-arm64`, `darwin-x64`, `darwin-arm64` and `win32-x64`; on any
other platform use `pipx install becwright`.

Available commands:
Expand Down
4 changes: 2 additions & 2 deletions documentation/releasing.es.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
becwright se distribuye por tres canales desde un único release de GitHub:

- **PyPI** — el paquete de Python (`pip` / `pipx`).
- **npm** — un paquete lanzador (`becwright`) más cuatro paquetes por plataforma
- **npm** — un paquete lanzador (`becwright`) más cinco paquetes por plataforma
con `os`/`cpu` (`@becwright/<target>`), cada uno con un binario precompilado,
para que quien no usa Python pueda instalarlo.

Expand All @@ -24,7 +24,7 @@ becwright se distribuye por tres canales desde un único release de GitHub:
2. Commit y crear un **release de GitHub** con tag `vX.Y.Z` (debe coincidir con
`pyproject.toml`).
3. Publicar el release dispara `release.yml`, que:
- construye y prueba el binario en las cuatro plataformas,
- construye y prueba el binario en todas las plataformas (macOS como binario universal2),
- stagea cada binario en su paquete `@becwright/<target>` (`npm/stage.mjs`),
- fija la versión de cada paquete npm desde el tag (`npm/set-version.mjs`),
- publica primero los paquetes de plataforma y luego el lanzador,
Expand Down
4 changes: 2 additions & 2 deletions documentation/releasing.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
becwright ships through three channels from a single GitHub release:

- **PyPI** — the Python package (`pip` / `pipx`).
- **npm** — a launcher package (`becwright`) plus four `os`/`cpu`-gated platform
- **npm** — a launcher package (`becwright`) plus five `os`/`cpu`-gated platform
packages (`@becwright/<target>`) that each carry a prebuilt binary, so users
without Python can install it.

Expand All @@ -23,7 +23,7 @@ becwright ships through three channels from a single GitHub release:
2. Commit, then create a **GitHub release** whose tag is `vX.Y.Z` (must match
`pyproject.toml`).
3. Publishing the release triggers `release.yml`, which:
- builds and smoke-tests the binary on all four platforms,
- builds and smoke-tests the binary on all platforms (macOS as a universal2 binary),
- stages each binary into its `@becwright/<target>` package
(`npm/stage.mjs`),
- sets every npm package version from the tag (`npm/set-version.mjs`),
Expand Down
2 changes: 1 addition & 1 deletion npm/becwright/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ local binary from `node_modules/.bin`, so it works without a global install.

## Supported platforms

`linux-x64`, `linux-arm64`, `darwin-arm64`, `win32-x64`. Intel macOS: use `pipx install becwright`.
`linux-x64`, `linux-arm64`, `darwin-x64`, `darwin-arm64`, `win32-x64` (macOS is a universal2 binary).

On other platforms, install via [pipx](https://pipx.pypa.io): `pipx install becwright`.

Expand Down
4 changes: 2 additions & 2 deletions npm/becwright/bin/becwright.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ function resolveBinary() {
const binary = resolveBinary();
if (!binary) {
console.error(`becwright: no prebuilt binary for ${TARGET}.`);
console.error("Supported: linux-x64, linux-arm64, darwin-arm64, win32-x64.");
console.error("On other platforms (e.g. Intel macOS) install via pipx: pipx install becwright");
console.error("Supported: linux-x64, linux-arm64, darwin-x64, darwin-arm64, win32-x64.");
console.error("On other platforms install via pipx: pipx install becwright");
process.exit(1);
}

Expand Down
11 changes: 6 additions & 5 deletions npm/becwright/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "becwright",
"version": "0.1.0",
"version": "0.2.1",
"description": "Deterministically enforces constraints (BECs) on your code, blocking commits that violate them. No Python required.",
"bin": {
"becwright": "bin/becwright.js"
Expand All @@ -25,9 +25,10 @@
"node": ">=16"
},
"optionalDependencies": {
"@becwright/linux-x64": "0.1.0",
"@becwright/linux-arm64": "0.1.0",
"@becwright/darwin-arm64": "0.1.0",
"@becwright/win32-x64": "0.1.0"
"@becwright/linux-x64": "0.2.1",
"@becwright/linux-arm64": "0.2.1",
"@becwright/darwin-x64": "0.2.1",
"@becwright/darwin-arm64": "0.2.1",
"@becwright/win32-x64": "0.2.1"
}
}
2 changes: 1 addition & 1 deletion npm/platforms/darwin-arm64/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@becwright/darwin-arm64",
"version": "0.1.0",
"version": "0.2.1",
"description": "macOS arm64 (Apple Silicon) binary for becwright.",
"os": [
"darwin"
Expand Down
16 changes: 16 additions & 0 deletions npm/platforms/darwin-x64/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"name": "@becwright/darwin-x64",
"version": "0.2.1",
"description": "macOS x64 (Intel) binary for becwright.",
"os": [
"darwin"
],
"cpu": [
"x64"
],
"files": [
"becwright"
],
"license": "MIT",
"homepage": "https://github.com/DataDave-Dev/becwright"
}
2 changes: 1 addition & 1 deletion npm/platforms/linux-arm64/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@becwright/linux-arm64",
"version": "0.1.0",
"version": "0.2.1",
"description": "Linux arm64 binary for becwright.",
"os": [
"linux"
Expand Down
2 changes: 1 addition & 1 deletion npm/platforms/linux-x64/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@becwright/linux-x64",
"version": "0.1.0",
"version": "0.2.1",
"description": "Linux x64 binary for becwright.",
"os": [
"linux"
Expand Down
2 changes: 1 addition & 1 deletion npm/platforms/win32-x64/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@becwright/win32-x64",
"version": "0.1.0",
"version": "0.2.1",
"description": "Windows x64 binary for becwright.",
"os": [
"win32"
Expand Down
6 changes: 5 additions & 1 deletion packaging/becwright.spec
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ entry = os.path.join(SPECPATH, "becwright_entry.py") # noqa: F821
# PyInstaller's static analysis cannot find them. Collect them all explicitly.
hiddenimports = collect_submodules("becwright.checks")

# On macOS we build a single universal2 binary (Intel + Apple Silicon) by setting
# BECWRIGHT_TARGET_ARCH=universal2 in CI; elsewhere it stays the host arch.
target_arch = os.environ.get("BECWRIGHT_TARGET_ARCH") or None

a = Analysis(
[entry],
pathex=[os.path.join(root, "src")],
Expand Down Expand Up @@ -41,7 +45,7 @@ exe = EXE(
console=True,
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
target_arch=target_arch,
codesign_identity=None,
entitlements_file=None,
)
Loading