Skip to content

feat(distribution): pip-installable package + PyPI publish workflow (closes #54 phase-1)#144

Closed
Wolfvin wants to merge 1 commit into
mainfrom
feat/issue-54-python-package-pypi
Closed

feat(distribution): pip-installable package + PyPI publish workflow (closes #54 phase-1)#144
Wolfvin wants to merge 1 commit into
mainfrom
feat/issue-54-python-package-pypi

Conversation

@Wolfvin

@Wolfvin Wolfvin commented Jul 1, 2026

Copy link
Copy Markdown
Owner

Closes #54 (Phase 1 only — Python package + PyPI)

What

Implements Phase 1 of issue #54: makes CodeLens pip-installable and adds a PyPI publish workflow.

Changes

New: codelens/ package

  • codelens/__init__.py — thin wrapper that delegates to scripts/codelens.py
  • codelens/__main__.py — enables python -m codelens
  • Resolves scripts/ dir at runtime (works in source checkout AND installed package)
  • main() function loads legacy codelens.py via importlib
  • Exports __version__ = "8.2.0" for programmatic access

pyproject.toml

  • [project.scripts] codelens = "codelens:main" — console entry point
  • [tool.setuptools.packages.find] includes both codelens/ and scripts/ subpackages (commands, formatters, parsers, plugins)
  • scripts/codelens.py excluded from auto-discovery (would shadow the package)

setup.py (new)

  • Explicitly lists top-level .py modules from scripts/ (excluding codelens.py)
  • Prevents setuptools from creating a conflicting codelens module

scripts/codelens.py

  • Legacy mode (python3 scripts/codelens.py) now prints a DeprecationWarning pointing to the codelens console command
  • Fully backward compatible — legacy mode still works

.github/workflows/publish-pypi.yml (new)

  • Triggers on tag push (v*.*.*)
  • Builds sdist + wheel via python -m build
  • Publishes to PyPI via trusted publishing (OIDC) — no API token needed
  • TestPyPI publish on manual workflow_dispatch
  • Requires configuring trusted publishing at https://pypi.org/manage/account/publishing/

docs/install.md (new)

  • Documents 4 install methods: pip install, pipx install, python -m codelens, from source
  • Optional extras table (grammars, rules, watch, lsp, dev, all)
  • Troubleshooting section (PATH, Unicode on Windows, grammar not found)

Synced docs

  • README.md, SKILL.md, SKILL-QUICK.md, scripts/graph_model.py — command count 68→69, MCP tools 66→67 (from prior PRs, needed for consistent package metadata before PyPI publish)

Verification

All 4 install methods tested and working:

# 1. Console command (after pip install)
$ codelens --command-count
69

# 2. python -m codelens
$ python -m codelens --command-count
69

# 3. import codelens
$ python -c "import codelens; print(codelens.__version__)"
8.2.0

# 4. Legacy mode (with deprecation warning)
$ python3 scripts/codelens.py --command-count
DeprecationWarning: Running codelens via 'python3 scripts/codelens.py' is the legacy mode...
69

End-to-end scan via pip install:

$ codelens init /tmp/test && codelens scan /tmp/test
{"status": "ok", ...}

Test suite: 1347 passed, 76 skipped, 0 failed (no regressions)

Acceptance criteria status

  • pip install codelens works on Python 3.8+ (tested 3.12)
  • PyPI publish workflow triggers on tag push (will verify after first tag)
  • Backward compat: python3 scripts/codelens.py still works (with deprecation warning)
  • GitHub Actions publish-pypi.yaml on tag push

Not in this PR (future phases)

  • Phase 2: Docker image (docker run ghcr.io/wolfvin/codelens)
  • Phase 3: Self-contained binary via PyInstaller
  • Phase 4: Homebrew, Scoop, Nix
  • Phase 5: Release signing (minisign + Cosign + SBOM + SLSA)
  • Phase 6: Auto-update command (codelens upgrade)

Test plan

  • codelens console command works after pip install -e .
  • python -m codelens works
  • import codelens returns correct __version__
  • Legacy python3 scripts/codelens.py works with deprecation warning
  • codelens init + codelens scan end-to-end works
  • Full test suite: 1347 passed, 0 failed
  • CI: full test suite passes
  • First tag push triggers PyPI publish workflow

Setup required before first PyPI publish

  1. Configure trusted publishing at https://pypi.org/manage/project/codelens/publishing/
    • GitHub workflow: Wolfvin/CodeLens
    • Workflow name: Publish to PyPI
    • Environment: pypi
  2. Create the pypi environment in GitHub repo settings (Settings → Environments)
  3. Tag a release: git tag v8.3.0 && git push --tags

…loses #54 phase-1)

Issue #54 Phase 1 — Python package + PyPI distribution:

1. codelens/ package (codelens/__init__.py, codelens/__main__.py):
   - Thin wrapper that delegates to scripts/codelens.py
   - Resolves scripts/ dir at runtime (source checkout or installed)
   - main() function loads legacy codelens.py via importlib
   - __version__ = '8.2.0' for programmatic access

2. pyproject.toml updates:
   - [project.scripts] codelens = codelens:main entry point
   - [tool.setuptools.packages.find] includes codelens/ + scripts/ subpackages
   - scripts/codelens.py excluded from py-modules (would shadow package)

3. setup.py:
   - Explicitly lists top-level .py modules from scripts/ (excluding codelens.py)
   - Prevents setuptools auto-discovery from creating conflicting 'codelens' module

4. scripts/codelens.py:
   - Legacy mode (python3 scripts/codelens.py) prints DeprecationWarning
   - Points users to 'codelens' console command after pip install
   - Fully backward compatible — legacy mode still works

5. .github/workflows/publish-pypi.yml:
   - Triggers on tag push (v*.*.*)
   - Builds sdist + wheel via 'python -m build'
   - Publishes to PyPI via trusted publishing (OIDC, no token needed)
   - TestPyCI publish on manual dispatch

6. docs/install.md:
   - Documents 4 install methods: pip, pipx, python -m, from source
   - Optional extras table (grammars, rules, watch, lsp, dev, all)
   - Troubleshooting section

7. Synced docs (README, SKILL.md, SKILL-QUICK.md, graph_model.py):
   - Command count 68 -> 69, MCP tools 66 -> 67 (from prior PRs)

Verified:
- 'codelens --command-count' works (69 commands)
- 'python -m codelens --command-count' works
- 'import codelens; codelens.__version__' works (8.2.0)
- 'python3 scripts/codelens.py' works with deprecation warning
- 'codelens init/scan' end-to-end works via pip install
- Test suite: 1347 passed, 76 skipped, 0 failed (no regressions)
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@sonarqubecloud

sonarqubecloud Bot commented Jul 1, 2026

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
C Security Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

@Wolfvin

Wolfvin commented Jul 3, 2026

Copy link
Copy Markdown
Owner Author

Closing as duplicate — #145 has more complete implementation (MANIFEST.in, packaging tests, CHANGELOG). Merge #145 instead.

@Wolfvin Wolfvin closed this Jul 3, 2026
Wolfvin added a commit that referenced this pull request Jul 3, 2026
…ulti-arch (refs #54)

Phase 2 of issue #54 — container image distribution for CodeLens.

Files added:
- Dockerfile (minimal): python:3.11-slim + tree-sitter core + 6 grammars +
  watchdog + PyYAML. Non-root codelens user (UID 1000). HEALTHCHECK via
  'codelens --command-count' (exercises full command-registry import path).
  ENTRYPOINT is a /usr/local/bin/codelens wrapper -> python3 scripts/codelens.py
  (forward-compatible: Phase 1 PR #144 will replace with console script).
- Dockerfile.maximal: minimal + all Python extras (grammars/watch/rules/lsp/dev)
  + pre-installed LSP servers (python-lsp-server, ruff-lsp, pyright,
  typescript-language-server) + Node.js LTS. Enables '--deep' out of the box
  for Python and JS/TS. Full LSP coverage pending native LSP server issue.
- .dockerignore: excludes .git, tests, benchmarks, vscode-codelens, __pycache__,
  .codelens runtime state, build artifacts to keep build context lean.
- .github/workflows/docker-publish.yml: multi-arch (linux/amd64 + linux/arm64)
  buildx pipeline. Matrix builds minimal + maximal. Pushes to GHCR
  (ghcr.io/wolfvin/codelens) with tags: :latest, :sha-<short>, :v<x.y.z>,
  :maximal-latest. GHA cache per variant. Smoke-test step on minimal.
  Triggers: push to main (Dockerfile/scripts changes), tags v*, workflow_dispatch.
- docs/installation/docker.md: usage guide — quick start, image variants,
  persistence volume, shell alias, --deep LSP mode, MCP server, health check,
  multi-arch, local build, tagging strategy, troubleshooting.

Acceptance criterion met:
  docker run --rm -v "$(pwd):/workspace" ghcr.io/wolfvin/codelens scan /workspace

Test baseline: 1398 passed, 76 skipped, 1 failed (pre-existing
test_codelensignore failure, unrelated to this change — only new files added,
no Python modifications). Docker build not tested locally (docker not in
sandbox); CI workflow will validate on push.

Phase 1 (PR #144 pip-installable) not yet merged — Dockerfile built on current
main (entry point python3 scripts/codelens.py). When Phase 1 merges, update
Dockerfile to 'pip install .' + drop wrapper script. Noted in Dockerfile header.

Findings:
- pyproject.toml lines 77-79 confirm no console-script entry point exists yet
  (Phase 1 will add [project.scripts] codelens = ...). Wrapper script bridges
  this gap so the acceptance-criterion command works today.
- No --version flag on codelens CLI; used --command-count for HEALTHCHECK
  (deeper check — verifies command registry + grammar imports load).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEATURE] Distribution & packaging overhaul — PyPI + Docker + Homebrew + binary + signing

1 participant