diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..a5d8b5f --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,59 @@ +# Contributing + +This file covers the repository layout and the release process. If you just want to debug an Actor, +see the [root README](README.md) and the package READMEs it links to. + +## Repository layout + +- [`javascript/`](javascript/) — the npm package (`bin/`, `lib/`), its README, and a sample TS Actor + in `example-actor/`. +- [`python/`](python/) — the PyPI package (`src/actor_debugger/`) and its README. +- [`.github/workflows/`](.github/workflows/) — release automation, one manually started workflow per + package (see [Releasing](#releasing) below). + +## Releasing + +Each package is released independently by its own manually started workflow. Both workflows refuse +to run on any branch other than `master`, and both push their tag and create the GitHub release +themselves — do not create tags or releases by hand. + +### npm (`javascript/`) + +Publishing to npm is done by [`.github/workflows/publish.yml`](.github/workflows/publish.yml), +started manually from the Actions tab. It publishes via **npm Trusted Publishing** (OIDC) — no npm +token or repository secret, and provenance attestations are generated automatically. The trusted +publisher configured on npmjs.com is: repository `apify/actor-debugger`, workflow `publish.yml` +(the workflow file name must stay exactly that). To cut a release: + +1. Bump the version in `javascript/package.json` in a PR and merge it to `master`: + + ```bash + cd javascript + npm version patch --no-git-tag-version # or minor / major + ``` + +2. Open **Actions → Publish to npm → Run workflow** on `master`. + +The workflow refuses to run on any other branch, or if that version is already on npm or its +`vX.Y.Z` tag already exists. It then syntax-checks the sources, smoke-tests both modes (disabled +pass-through and the debug server with `/json/list` + DevTools frontend), checks the pack contents, +runs `npm publish` from `javascript/`, and finally **pushes the `vX.Y.Z` tag and creates the GitHub +release** with generated notes. + +### PyPI (`python/`) + +Publishing to PyPI is done by +[`.github/workflows/publish_to_pypi.yml`](.github/workflows/publish_to_pypi.yml), started manually +from the Actions tab. It publishes via **PyPI Trusted Publishing** (OIDC) — no API token or +repository secret. The trusted publisher configured on PyPI is: project `actor-debugger`, +repository `apify/actor-debugger`, workflow `publish_to_pypi.yml` (the workflow file name must stay +exactly that). To cut a release: + +1. Bump the version in `python/pyproject.toml` and `python/src/actor_debugger/__init__.py` in a + PR and merge it to `master`. +2. Open **Actions → Publish to PyPI → Run workflow** on `master`. + +The workflow refuses to run on any other branch, if the two version strings disagree, or if that +version is already on PyPI or its `py-vX.Y.Z` tag already exists. It then installs the package, +smoke tests the CLI and the served debugger UI, builds sdist+wheel, uploads them, and finally +**pushes the `py-vX.Y.Z` tag and creates the GitHub release** with generated notes. diff --git a/README.md b/README.md index 160ddbd..4298a9c 100644 --- a/README.md +++ b/README.md @@ -14,18 +14,6 @@ Both variants share the same architecture: your Actor runs under its native debu inspector, or debugpy for Python), and one HTTP server on `ACTOR_WEB_SERVER_PORT` serves the frontend and bridges the debug protocol to it. The run log prints the URL to open. -## Repository layout - -- [`javascript/`](javascript/) — the npm package (`bin/`, `lib/`), its README, and a sample TS Actor - in `example-actor/`. -- [`python/`](python/) — the PyPI package (`src/actor_debugger/`) and its README. -- [`.github/workflows/`](.github/workflows/) — release automation. Both workflows are started - manually from the Actions tab on `master`: `publish.yml` publishes the version in - `javascript/package.json` to npm and `publish_to_pypi.yml` the version in `python/pyproject.toml` - to PyPI. Each then creates its tag (`vX.Y.Z` for npm, `py-vX.Y.Z` for PyPI) and GitHub release - itself. Both use registry trusted publishing (OIDC), so there are no publishing secrets in the - repository. - ## Security The debug endpoint is unauthenticated: anyone who reaches the container URL can execute code in the diff --git a/javascript/README.md b/javascript/README.md index c8691f8..d5588c4 100644 --- a/javascript/README.md +++ b/javascript/README.md @@ -93,30 +93,6 @@ The debug endpoint is **unauthenticated** — anyone who reaches the container U never ship it in a published Actor, and gate the endpoint (owner-only) before any non-prototype use. -## Releasing - -Publishing to npm is done by -[`.github/workflows/publish.yml`](https://github.com/apify/actor-debugger/blob/master/.github/workflows/publish.yml), -started manually from the Actions tab. It publishes via **npm Trusted Publishing** (OIDC) — no npm -token or repository secret, and provenance attestations are generated automatically. The trusted -publisher configured on npmjs.com is: repository `apify/actor-debugger`, workflow `publish.yml` -(the workflow file name must stay exactly that). To cut a release: - -1. Bump the version in `javascript/package.json` in a PR and merge it to `master`: - - ```bash - cd javascript - npm version patch --no-git-tag-version # or minor / major - ``` - -2. Open **Actions → Publish to npm → Run workflow** on `master`. - -The workflow refuses to run on any other branch, or if that version is already on npm or its -`vX.Y.Z` tag already exists. It then syntax-checks the sources, smoke-tests both modes (disabled -pass-through and the debug server with `/json/list` + DevTools frontend), checks the pack contents, -runs `npm publish` from `javascript/`, and finally **pushes the `vX.Y.Z` tag and creates the GitHub -release** with generated notes. Do not create tags or releases by hand. - ## Notes - Depends on `chii` for the prebuilt DevTools frontend (~16 MB of static assets, no runtime browser). diff --git a/javascript/package-lock.json b/javascript/package-lock.json index fe60d11..a994069 100644 --- a/javascript/package-lock.json +++ b/javascript/package-lock.json @@ -1,12 +1,12 @@ { "name": "actor-debugger", - "version": "0.1.5", + "version": "0.1.6", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "actor-debugger", - "version": "0.1.5", + "version": "0.1.6", "license": "Apache-2.0", "dependencies": { "chii": "^1.14.0" diff --git a/javascript/package.json b/javascript/package.json index be14c55..6a954bd 100644 --- a/javascript/package.json +++ b/javascript/package.json @@ -1,6 +1,6 @@ { "name": "actor-debugger", - "version": "0.1.5", + "version": "0.1.6", "description": "Drop-in remote debugger for Apify Node/TS Actors: one Dockerfile CMD line launches your Actor under the Node inspector, reachable over the run's container URL. No local setup, no rebuild of your own code.", "type": "module", "bin": { diff --git a/python/README.md b/python/README.md index 3f8cde8..aceec7b 100644 --- a/python/README.md +++ b/python/README.md @@ -105,45 +105,6 @@ a restricted run/token, never ship it in a published Actor, and gate the endpoin before any non-prototype use. This matches the security posture of the Node version; both need the same hardening pass. -## Design notes: the routes considered - -The constraint was: **no platform/infrastructure changes, and nothing but a browser on the -debugging machine.** Everything must therefore run inside the Actor container and be served over -the one exposed web-server port. Options considered: - -| Approach | Verdict | -| --- | --- | -| **debugpy + served browser DAP client** (this package) | CPython unchanged, actor code and deps run exactly as in production; debugpy is the canonical Python debugger; image cost ~3 MB. The UI is ours to grow. **Chosen.** | -| **GraalPy `--inspect`** — GraalVM's Python speaks the Chrome DevTools Protocol natively, so the Node version's chii DevTools frontend + CDP proxy would work *unchanged* | Elegant symmetry, but it swaps the runtime under the Actor: a different base image, slower startup, and C-extension compatibility risk for real-world deps (`lxml`, `pydantic`, `cryptography`, …). Debugging a different interpreter than production undermines the point. | -| **DAP→CDP translation shim** — keep CPython + debugpy, translate DAP into the Chrome DevTools Protocol and serve the same chii DevTools frontend the Node version uses | Best possible UI for free, one frontend for both languages, but the DevTools frontend is picky about `Debugger`/`Runtime` lifecycle — a meaningful project on its own. The `/dap` WebSocket this package exposes is where such a shim would slot in later. | -| **code-server / openvscode-server in the container** | Great UX, zero custom code, but ~300 MB and a Node runtime in every Python Actor image, plus auth wiring. Overkill for "set a breakpoint in a run". | -| **`web-pdb` / xterm.js + pdb over WebSocket** | Tiny, but a terminal `pdb` UX (no gutter breakpoints, no variable tree) and pdb can't attach to a running program the way debugpy can. | -| **Jupyter server in the container** (JupyterLab's debugger also speaks debugpy) | The kernel model doesn't fit debugging an already-running script; heavyweight. | -| **[`dap-python`](https://pypi.org/project/dap-python/)** — a typed Python DAP *client* library | The DAP client here is the browser; the container side is a protocol-agnostic byte bridge. Useful only for a server-orchestrated variant, at the cost of a Pydantic dependency and a Python ≥3.12 floor. | - -The same architecture extends beyond Python: any language with a DAP adapter (Node via js-debug, -Go via Delve — which speaks DAP natively — Rust via lldb-dap, …) can sit behind the identical -bridge and frontend; only the adapter spawn command and entrypoint detection differ. - -## Releasing - -Publishing to PyPI is done by -[`.github/workflows/publish_to_pypi.yml`](https://github.com/apify/actor-debugger/blob/master/.github/workflows/publish_to_pypi.yml), -started manually from the Actions tab. It publishes via **PyPI Trusted Publishing** (OIDC) — no API -token or repository secret. The trusted publisher configured on PyPI is: project `actor-debugger`, -repository `apify/actor-debugger`, workflow `publish_to_pypi.yml` (the workflow file name must stay -exactly that). To cut a release: - -1. Bump the version in `python/pyproject.toml` and `python/src/actor_debugger/__init__.py` in a - PR and merge it to `master`. -2. Open **Actions → Publish to PyPI → Run workflow** on `master`. - -The workflow refuses to run on any other branch, if the two version strings disagree, or if that -version is already on PyPI or its `py-vX.Y.Z` tag already exists. It then installs the package, -smoke tests the CLI and the served debugger UI, builds sdist+wheel, uploads them, and finally -**pushes the `py-vX.Y.Z` tag and creates the GitHub release** with generated notes. Do not create -tags or releases by hand. - ## Notes - Only runtime dependency is `debugpy`; the HTTP server and the RFC 6455 WebSocket implementation diff --git a/python/pyproject.toml b/python/pyproject.toml index 3fffd81..e1fdd93 100644 --- a/python/pyproject.toml +++ b/python/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "actor-debugger" -version = "0.1.2" +version = "0.1.3" description = "Drop-in remote debugging for Apify Python Actors: debugpy plus a browser debugger UI served over the run's container URL." readme = "README.md" license = { text = "Apache-2.0" } diff --git a/python/src/actor_debugger/__init__.py b/python/src/actor_debugger/__init__.py index dc4d0d6..387b948 100644 --- a/python/src/actor_debugger/__init__.py +++ b/python/src/actor_debugger/__init__.py @@ -1,3 +1,3 @@ """actor-debugger: browser-based remote debugging for Apify Python Actors.""" -__version__ = "0.1.2" +__version__ = "0.1.3"