feat: unify CLI and add release pipeline#41
Conversation
Replace 3 legacy scripts with one 'perplexity-webui-scraper' command (token, api, mcp subcommands). Add Nuitka executable matrix (5 OS/arch), multi-arch GHCR Docker image, workflow_dispatch for testing, and CLI delegation tests. Docs migrated to unified commands.
PyInstaller 6.20: 3x faster builds, native Python 3.14 support, smaller binaries. Single --onefile command replaces verbose Nuitka-Action config. Removed nuitka/pillow/zstandard from build deps.
Replace dry_run with skip_pypi, skip_docker, and skip_gh_releases workflow inputs. Split publish side effects into separate jobs so manual runs can selectively publish Docker, PyPI, and GitHub Releases. Add target_commitish for manual GitHub Release creation and make Docker notes conditional.
Add Containerfile.mcp and publish mcp, X.Y.Z-mcp, and vX.Y.Z-mcp tags alongside the API image. Keep API latest/default unchanged and document the optional MCP container workflow.
Add macOS Intel (macos-26-intel) and Windows ARM runner targets to the executable build matrix. Also update the Unreleased changelog entries for the release workflow work.
Introduce release_mode for manual dispatch. Preview mode publishes by commit SHA (Docker tags, prerelease GH release, artifact names) while official mode publishes by version. PyPI is restricted to official mode and Docker/GH release notes adapt to preview vs official tags.
Remove preview/official release_mode complexity. Manual dispatch uses explicit version input or auto-detects from source. Skip flags remain for selective publishing control.
|
Thank you for your contribution and effort in unifying the CLI. I will review the changes in more detail later. Regarding binary generation: for this project, I prefer to use Nuitka instead of PyInstaller. Since Nuitka compiles the Python code directly to C, the final binary has better performance, a smaller size, and a near-zero false positive rate in antivirus software. I will check out your branch locally, test the images from ghcr.io, and apply the migration to Nuitka along with repository typing standardization before the merge. |
There was a problem hiding this comment.
Pull request overview
This PR replaces the legacy multi-entrypoint setup with a unified perplexity-webui-scraper CLI (subcommands: token, api, mcp) and adds a new release pipeline that builds PyPI artifacts, PyInstaller executables, and multi-arch GHCR images, alongside documentation updates to match the new distribution model.
Changes:
- Consolidate console scripts into a single Typer-based CLI with delegated subcommands and add delegation tests.
- Add a GitHub Actions publish pipeline for Python packages, multi-platform executables (PyInstaller), and multi-arch container publishing (API + optional MCP image).
- Update docs/changelog/container entrypoints to use the unified command surface.
Reviewed changes
Copilot reviewed 12 out of 16 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
uv.lock |
Adds build-time dependencies (PyInstaller and transitive deps) and moves typer into base deps. |
tests/test_cli.py |
Adds tests ensuring unified CLI help and subcommand delegation behavior. |
src/perplexity_webui_scraper/mcp/server.py |
Updates the missing-token guidance to the new unified CLI invocation. |
src/perplexity_webui_scraper/cli/__main__.py |
Introduces unified CLI with token/api/mcp subcommands and lazy imports. |
README.md |
Updates install/run docs to reference perplexity-webui-scraper <subcommand> and new container images. |
pyproject.toml |
Collapses scripts into a single entrypoint, adjusts extras/dependency groups for new CLI + build tooling. |
docs/mcp-server.md |
Updates MCP invocation examples to use unified CLI; adds optional MCP Docker image section. |
docs/getting-started.md |
Updates quickstart commands for MCP/API/token generator to unified CLI; adds MCP Docker option. |
docs/api-reference.md |
Updates API CLI docs to unified CLI and GHCR-based run instructions. |
Containerfile.mcp |
Adds a dedicated MCP container build and entrypoint for perplexity-webui-scraper mcp. |
Containerfile |
Updates container entrypoint to perplexity-webui-scraper api .... |
CHANGELOG.md |
Documents the unified CLI and new release/publish pipeline. |
.gitignore |
Ignores PyInstaller build artifacts (build/, dist/, *.spec). |
.github/workflows/publish.yml |
Replaces the old publish workflow with a multi-job release pipeline (package, executables, GHCR, PyPI, GH release). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| email: Annotated[str | None, typer.Argument(help="Your Perplexity account email.")] = None, | ||
| ) -> None: | ||
| """Generate a Perplexity session token via email OTP or magic link.""" | ||
| from perplexity_webui_scraper.cli.commands.get_session_token import run # noqa: PLC0415 |
| ) -> None: | ||
| """Start the OpenAI-compatible REST API server.""" | ||
| from perplexity_webui_scraper.api.launcher import main as run_api # noqa: PLC0415 | ||
|
|
||
| run_api(host=host, port=port, reload=reload, log_level=log_level) | ||
|
|
||
|
|
||
| @cli.command(name="mcp") | ||
| def mcp() -> None: | ||
| """Start the MCP server.""" | ||
| from perplexity_webui_scraper.mcp.server import main as run_mcp # noqa: PLC0415 | ||
|
|
||
| run_mcp() |
| LOGINS=$(git log $PREVIOUS_TAG..HEAD --format='%H' | while read sha; do | ||
| curl -s "https://api.github.com/repos/${{ github.repository }}/commits/$sha" \ | ||
| -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \ | ||
| | grep -oP '(?<="login": ")[^"]+' | head -1 | ||
| done | sort -u | grep -v '^$' | grep -v '\[bot\]') | ||
|
|
There was a problem hiding this comment.
@henrique-coder Yep, this is true, I tried changing it so contributors that have the option Keep my email addresses private enabled can also appear in the Contributors section, one single request instead of one per commit should be better and faster.
I tried both Nuitka and PyInstaller, but with Nuitka the performance improvement at startup is practically imperceptible, and the binary is larger, so in the end I decided to go with PyInstaller. |
Thanks for checking both out and sharing your feedback! I completely see where you're coming from regarding the initial size and startup perception, but I still want to stick with Nuitka for the release matrix. Here is why:
I've already integrated Nuitka into the pipeline on top of the awesome CLI unification you built, so we'll roll with this setup. Thanks again for doing the heavy lifting on the CLI structure. It makes the project a whole lot better! |
Summary
perplexity-webui-scraperCLI andtoken/api/mcpsubcommandsNotes
Testing
uv run pytestuv run ruff format --checkuv run ruff check --output-format=githubuv run ty checknpx --yes prettier --check .github/workflows/publish.yml README.md docs/getting-started.md docs/api-reference.md docs/mcp-server.mduv build