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
8 changes: 4 additions & 4 deletions .bec/rules.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ rules:
paths:
- "src/**/*.py"
- "tests/**/*.py"
check: "python3 -m becwright.checks.redundant_comments"
check: "becwright run redundant_comments"
severity: warning

- id: no-debug-remnants
Expand All @@ -26,7 +26,7 @@ rules:
# definition (a check that searches for a string can't run over its own source).
paths:
- "src/becwright/*.py"
check: "python3 -m becwright.checks.debug_remnants"
check: "becwright run debug_remnants"
severity: blocking

- id: no-wildcard-imports
Expand All @@ -37,7 +37,7 @@ rules:
paths:
- "src/becwright/**/*.py"
- "tests/**/*.py"
check: "python3 -m becwright.checks.wildcard_imports"
check: "becwright run wildcard_imports"
severity: blocking

- id: no-dangerous-eval
Expand All @@ -50,5 +50,5 @@ rules:
# matches its own pattern definition).
paths:
- "src/becwright/*.py"
check: "python3 -m becwright.checks.dangerous_eval"
check: "becwright run dangerous_eval"
severity: blocking
47 changes: 47 additions & 0 deletions .github/workflows/build-binaries.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
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.
on:
workflow_dispatch:
workflow_call: # invoked by release.yml on a published release

jobs:
build:
name: ${{ matrix.target }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- { os: ubuntu-latest, target: linux-x64, ext: "" }
- { os: ubuntu-24.04-arm, target: linux-arm64, ext: "" }
- { os: macos-13, target: darwin-x64, ext: "" }
- { os: macos-14, target: darwin-arm64, ext: "" }
- { os: windows-latest, target: win32-x64, ext: ".exe" }
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install
run: pip install ".[build]"
- name: Build
run: pyinstaller --clean --noconfirm packaging/becwright.spec
- name: Smoke test
shell: bash
run: |
BIN="dist/becwright${{ matrix.ext }}"
"$BIN" --version
"$BIN" list
echo 'console.log(1)' > x.js
if echo x.js | "$BIN" run forbid --pattern 'console\.log'; then
echo "forbid should have exited non-zero on a match"; exit 1
fi
echo "frozen 'run' dispatch works"
- uses: actions/upload-artifact@v4
with:
name: becwright-${{ matrix.target }}
path: dist/becwright${{ matrix.ext }}
if-no-files-found: error
22 changes: 0 additions & 22 deletions .github/workflows/publish.yml

This file was deleted.

62 changes: 62 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
name: Release

# On a published GitHub release: build the per-platform binaries, publish the
# npm packages (launcher + 5 platform packages) and publish to PyPI. The tag
# name (e.g. v0.1.0) drives the version.
on:
release:
types: [published]

jobs:
binaries:
uses: ./.github/workflows/build-binaries.yml

npm:
needs: binaries
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "20"
registry-url: "https://registry.npmjs.org"
- name: Download built binaries
uses: actions/download-artifact@v4
with:
path: artifacts
- name: Stage binaries into platform packages
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-x64 artifacts/becwright-darwin-x64/becwright
node npm/stage.mjs darwin-arm64 artifacts/becwright-darwin-arm64/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}"
- name: Publish platform packages
run: |
for dir in npm/platforms/*/; do
npm publish "$dir" --access public
done
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Publish launcher package
run: npm publish npm/becwright --access public
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

pypi:
runs-on: ubuntu-latest
permissions:
id-token: write # PyPI Trusted Publishing (OIDC)
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Build
run: |
pip install build
python -m build
- name: Publish
uses: pypa/gh-action-pypi-publish@release/v1
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ dist/
.env
.DS_Store

# npm: staged binaries (built in CI) and installed deps
node_modules/
npm/platforms/*/becwright
npm/platforms/*/becwright.exe

# Prototype and documentation
prototype/
docs/
16 changes: 12 additions & 4 deletions README.es.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,10 @@ becwright se instala una vez como herramienta; cada repo solo aporta su propio
`.bec/rules.yaml`.

```bash
# 1. Instalar el motor (una vez, global)
# 1. Instalar el motor. Elegí tu ecosistema — sin Python vía npm/pnpm, que
# traen un binario autónomo:
npm install --save-dev becwright # o global: npm install -g becwright
pnpm add -D becwright
pipx install becwright # o: pip install becwright

# 2. En tu repo, generar reglas + instalar el hook
Expand All @@ -60,6 +63,11 @@ becwright init # detecta tu lenguaje, escribe .bec/rules.ya
# 3. Listo: cada commit corre los chequeos; si una regla blocking falla, frena.
```

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-x64`, `darwin-arm64` y `win32-x64`; en
cualquier otra plataforma usá `pipx install becwright`.

Comandos disponibles:

| Comando | Qué hace |
Expand All @@ -83,7 +91,7 @@ rules:
Si un token aparece en los logs, cualquiera con acceso a ellos puede
robar la sesión de un usuario.
paths: ["src/**/*.py"]
check: "python3 -m becwright.checks.no_token_in_logs"
check: "becwright run no_token_in_logs"
severity: blocking # blocking = frena el commit | warning = solo avisa
```

Expand Down Expand Up @@ -120,7 +128,7 @@ rules:
why_it_matters: >
Un 'debugger' olvidado detiene la ejecución y no debería llegar a producción.
paths: ["**/*.js", "**/*.ts"]
check: "python3 -m becwright.checks.forbid --pattern '\\bdebugger\\b'"
check: "becwright run forbid --pattern '\\bdebugger\\b'"
severity: blocking
```

Expand Down Expand Up @@ -151,7 +159,7 @@ commit. Usá `--yes` para saltar la confirmación en entornos automatizados.
Hay un **catálogo de BECs listas para usar** en [`becs/`](becs/) que podés
importar directo desde su URL cruda.

Los checks built-in (`python3 -m becwright.checks.*`) viajan con el paquete, así
Los checks built-in (`becwright run *`) viajan con el paquete, así
que el bundle solo guarda su nombre. Un check **custom** (`.bec/checks/foo.py`)
viaja con su código embebido y aterriza en `.bec/checks/` del repo destino.

Expand Down
24 changes: 16 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,10 @@ becwright is installed once as a tool; each repo only contributes its own
`.bec/rules.yaml`.

```bash
# 1. Install the engine (once, global)
# 1. Install the engine. Pick your ecosystem — no Python needed via npm/pnpm,
# which ship a self-contained binary:
npm install --save-dev becwright # or global: npm install -g becwright
pnpm add -D becwright
pipx install becwright # or: pip install becwright

# 2. In your repo, scaffold rules + install the hook
Expand All @@ -59,6 +62,11 @@ becwright init # detects your language, writes .bec/rules.y
# 3. Done: each commit runs the checks; if a blocking rule fails, it stops.
```

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-x64`, `darwin-arm64` and `win32-x64`; on any
other platform use `pipx install becwright`.

Available commands:

| Command | What it does |
Expand All @@ -82,7 +90,7 @@ rules:
If a token shows up in the logs, anyone with access to them can steal a
user's session.
paths: ["src/**/*.py"]
check: "python3 -m becwright.checks.no_token_in_logs"
check: "becwright run no_token_in_logs"
severity: blocking # blocking = stops the commit | warning = only warns
```

Expand Down Expand Up @@ -113,7 +121,7 @@ rules:
A secret in the repo stays in git history forever and is visible to
anyone with access to the code.
paths: ["src/**/*.py"]
check: "python3 -m becwright.checks.hardcoded_secrets"
check: "becwright run hardcoded_secrets"
severity: blocking

- id: no-debug-remnants
Expand All @@ -122,7 +130,7 @@ rules:
why_it_matters: >
A forgotten breakpoint hangs the process in production or CI.
paths: ["src/**/*.py"]
check: "python3 -m becwright.checks.debug_remnants"
check: "becwright run debug_remnants"
severity: blocking

- id: no-dangerous-eval
Expand All @@ -131,7 +139,7 @@ rules:
why_it_matters: >
eval/exec on untrusted input is remote code execution.
paths: ["src/**/*.py"]
check: "python3 -m becwright.checks.dangerous_eval"
check: "becwright run dangerous_eval"
severity: blocking

- id: no-wildcard-imports
Expand All @@ -141,7 +149,7 @@ rules:
Wildcard imports hide where each name comes from and break static
analysis.
paths: ["src/**/*.py"]
check: "python3 -m becwright.checks.wildcard_imports"
check: "becwright run wildcard_imports"
severity: warning
```

Expand All @@ -162,7 +170,7 @@ rules:
why_it_matters: >
A forgotten 'debugger' halts execution and should not reach production.
paths: ["**/*.js", "**/*.ts"]
check: "python3 -m becwright.checks.forbid --pattern '\\bdebugger\\b'"
check: "becwright run forbid --pattern '\\bdebugger\\b'"
severity: blocking
```

Expand Down Expand Up @@ -193,7 +201,7 @@ Use `--yes` to skip the confirmation in automated environments.
There is a **catalog of ready-to-use BECs** in [`becs/`](becs/) that you can
import directly from their raw URL.

Built-in checks (`python3 -m becwright.checks.*`) travel with the package, so
Built-in checks (`becwright run *`) travel with the package, so
the bundle only stores their name. A **custom** check (`.bec/checks/foo.py`)
travels with its code embedded and lands in `.bec/checks/` of the target repo.

Expand Down
5 changes: 4 additions & 1 deletion documentation/portability.es.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,13 @@ Al exportar una regla, su comando `check` se clasifica:

| Tipo | Cuándo | Qué viaja en el bundle |
|---|---|---|
| `builtin` | `python3 -m becwright.checks.X [args]` | el nombre del módulo (y los args) |
| `builtin` | `becwright run X [args]` | el nombre del módulo (y los args) |
| `script` | referencia un archivo del repo, p.ej. `.bec/checks/foo.py` | el código fuente del script, embebido |
| `command` | cualquier otra cosa | el string crudo del comando (se avisa al importar) |

La forma antigua `python3 -m becwright.checks.X` se sigue reconociendo al
importar, así que los bundles exportados por versiones previas siguen funcionando.

Un bundle `script` aterriza su código embebido en `.bec/checks/` del repo
destino, así un check propio viaja con su código. Un bundle `builtin` solo
necesita el nombre, porque ese código viene con el paquete becwright.
Expand Down
5 changes: 4 additions & 1 deletion documentation/portability.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,13 @@ When you export a rule, its `check` command is classified:

| Kind | When | What travels in the bundle |
|---|---|---|
| `builtin` | `python3 -m becwright.checks.X [args]` | the module name (and args) |
| `builtin` | `becwright run X [args]` | the module name (and args) |
| `script` | references a repo file, e.g. `.bec/checks/foo.py` | the script's source, embedded |
| `command` | anything else | the raw command string (a warning is shown on import) |

The legacy `python3 -m becwright.checks.X` form is still recognized on import,
so bundles exported by older versions keep working.

A `script` bundle lands its embedded code in `.bec/checks/` of the target repo,
so a custom check travels with its code. A `builtin` bundle only needs the name,
because that code ships with the becwright package.
Expand Down
40 changes: 40 additions & 0 deletions documentation/releasing.es.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Publicar una versión

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 cinco paquetes por plataforma
con `os`/`cpu` (`@becwright/<target>`), cada uno con un binario precompilado,
para que quien no usa Python pueda instalarlo.

## Configuración inicial (una vez)

- **PyPI**: vía Trusted Publishing (OIDC), sin token almacenado. Ver el job
`pypi` en [`.github/workflows/release.yml`](../.github/workflows/release.yml).
- **npm**:
- Crear el scope/org `@becwright` en npm y asegurar que la cuenta también sea
dueña del nombre sin scope `becwright`.
- Agregar un token de acceso de automatización como secreto del repositorio
`NPM_TOKEN`.

## Sacar una versión

1. Subir la versión en `pyproject.toml` (las versiones de npm se derivan del tag
de git al publicar, no hace falta editarlas).
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 cinco plataformas,
- 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,
- construye y publica el paquete de Python en PyPI.

## Notas

- Los paquetes de plataforma se publican antes que el lanzador para que sus
`optionalDependencies` resuelvan de inmediato.
- `npm publish` no es idempotente: re-ejecutar una versión ya publicada falla.
Subí la versión para volver a publicar.
- Para probar los binarios sin publicar, ejecutá el workflow **Build binaries**
manualmente (`workflow_dispatch`).
Loading
Loading