From 38931224a644ddb4adaaa3d3556e2eadf21d8bfe Mon Sep 17 00:00:00 2001 From: Thor Whalen <1906276+thorwhalen@users.noreply.github.com> Date: Tue, 22 Sep 2026 14:12:28 +0000 Subject: [PATCH] chore: remove stale setup.cfg/MANIFEST.in, fix CLAUDE.md CLI list, migrate CI to the stub setup.cfg's dependency pins had drifted badly from pyproject.toml (e.g. Sphinx>=3.3.1 vs the real sphinx>=9,<10) -- pure unmaintained legacy cruft, hatchling reads pyproject.toml only. MANIFEST.in referenced epythet/_static/docsrc/* files that no longer exist (templates.py/ scaffold.py generate that content now). Neither is read by anything in the repo (verified by grep) or by epythet's own config-loading fallback (which prefers pyproject.toml and only needs setup.cfg as a fallback for OTHER packages that lack a pyproject.toml). .claude/CLAUDE.md's cli.py summary line was missing three real top-level commands (repair, migrate-style, sweep) that 'epythet --help' lists. Then migrated the already-green Modern-uv-inline CI to the reusable stub, and fixed the empty tool.wads.ci.project_name. --- .claude/CLAUDE.md | 2 +- .github/workflows/ci.yml | 277 +++++++-------------------------------- MANIFEST.in | 5 - pyproject.toml | 2 +- setup.cfg | 52 -------- 5 files changed, 53 insertions(+), 285 deletions(-) delete mode 100644 MANIFEST.in delete mode 100644 setup.cfg diff --git a/.claude/CLAUDE.md b/.claude/CLAUDE.md index 13ed555..ad8a94c 100644 --- a/.claude/CLAUDE.md +++ b/.claude/CLAUDE.md @@ -15,7 +15,7 @@ This file is the map: where things are and which artifact to read for which task ``` epythet/ __init__.py # public API re-exports; quickstart() - cli.py # cw-based CLI: make-docsrc make-autodocs make quickstart check-pages configure-pages validate ai-artifacts ai-readme-check build-info; groups ledger, snippets + cli.py # cw-based CLI: make-docsrc make-autodocs make quickstart check-pages configure-pages validate ai-artifacts ai-readme-check build-info repair migrate-style sweep; groups ledger, snippets config.py # DocsConfig SSOT: pyproject [project] + [tool.epythet], setup.cfg fallback confgen.py # DocsConfig -> Sphinx conf namespace (sphinx_settings) sphinx_conf.py # the star-import target of the generated two-line conf.py diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 018ba59..a09825a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,231 +1,56 @@ -name: Continuous Integration (uv) -# MIGRATION NOTE: PyPI auth changed: set secrets.PYPI_PASSWORD to a PyPI API token (uv publish uses UV_PUBLISH_TOKEN, mapped from PYPI_PASSWORD) +# wads CI — calls the reusable workflow hosted in i2mint/wads. +# +# All configuration comes from this repo's pyproject.toml [tool.wads.ci.*]. +# To customize the workflow itself (rare), replace this file with the +# full inline template `wads/data/github_ci_uv.yml` from i2mint/wads. +# +# Pinning: `@master` floats with wads. If you need version stability for +# a release-sensitive repo, change `@master` to a wads tag (e.g. `@0.2.15`; +# tags have no `v` prefix). A stub whose `secrets:` block passes the JSON +# transport (the default below) needs a tag from a release after 0.2.14 — +# older tags don't declare that secret and GitHub then rejects the +# workflow at parse time. +# CI failure does not block a published release — it blocks the publish +# step itself — so floating master is generally safe. +# +# Permissions: GitHub validates that the caller grants AT LEAST the +# permissions any job in the called workflow requests — at workflow-parse +# time, not at run-time, even if the job would be skipped via `if:`. +# The reusable workflow needs: +# contents: write for the publish job's version-bump push-back +# and for the github-pages job's gh-pages branch push +# pages: write for the github-pages job's REST API Pages config +# Both default to `write` on org-account GITHUB_TOKEN and need to be +# granted explicitly on personal-account callers (where the default is +# read-only). No `id-token: write` needed — the publish-github-pages +# action uses peaceiris/actions-gh-pages (branch-based) + REST API, +# not the OIDC `actions/deploy-pages` flow. +name: Continuous Integration on: [push, pull_request] - -# Note: Environment variables (PROJECT_NAME and vars from [tool.wads.ci.env]) -# are set by the read-ci-config action in the setup job and made available -# to all subsequent jobs via GITHUB_ENV - jobs: - # First job: Read configuration from pyproject.toml - setup: - name: Read Configuration - runs-on: ubuntu-latest - outputs: - project-name: ${{ steps.config.outputs.project-name }} - python-versions: ${{ steps.config.outputs.python-versions }} - pytest-args: ${{ steps.config.outputs.pytest-args }} - coverage-enabled: ${{ steps.config.outputs.coverage-enabled }} - exclude-paths: ${{ steps.config.outputs.exclude-paths }} - test-on-windows: ${{ steps.config.outputs.test-on-windows }} - build-sdist: ${{ steps.config.outputs.build-sdist }} - build-wheel: ${{ steps.config.outputs.build-wheel }} - metrics-enabled: ${{ steps.config.outputs.metrics-enabled }} - metrics-config-path: ${{ steps.config.outputs.metrics-config-path }} - metrics-storage-branch: ${{ steps.config.outputs.metrics-storage-branch }} - metrics-python-version: ${{ steps.config.outputs.metrics-python-version }} - metrics-force-run: ${{ steps.config.outputs.metrics-force-run }} - ruff-enabled: ${{ steps.config.outputs.ruff-enabled }} - black-enabled: ${{ steps.config.outputs.black-enabled }} - mypy-enabled: ${{ steps.config.outputs.mypy-enabled }} - docs-enabled: ${{ steps.config.outputs.docs-enabled }} - - steps: - - uses: actions/checkout@v6 - - - name: Set up uv - uses: astral-sh/setup-uv@v7 - - - name: Set up Python - run: uv python install 3.11 - - - name: Read CI Config - id: config - uses: i2mint/wads/actions/read-ci-config@master - with: - pyproject-path: . - - # Second job: Validation using the config - validation: - name: Validation - if: "!contains(github.event.head_commit.message, '[skip ci]')" - needs: setup - runs-on: ubuntu-latest - strategy: - matrix: - python-version: ${{ fromJson(needs.setup.outputs.python-versions) }} - - steps: - - uses: actions/checkout@v6 - - - name: Set up uv - uses: astral-sh/setup-uv@v7 - with: - enable-cache: true - - - name: Set up Python ${{ matrix.python-version }} - uses: i2mint/wads/actions/setup-python-uv@master - with: - python-version: ${{ matrix.python-version }} - - - name: Install System Dependencies - uses: i2mint/wads/actions/install-system-deps@master - with: - pyproject-path: . - - - name: Install Dependencies - uses: i2mint/wads/actions/install-deps-uv@master - - - name: Format Source Code - if: needs.setup.outputs.ruff-enabled != 'false' - run: uvx ruff format . - - - name: Format Source Code (black) - if: needs.setup.outputs.black-enabled == 'true' - run: uvx black . - - - name: Lint Validation - if: needs.setup.outputs.ruff-enabled != 'false' - run: uvx ruff check --output-format=github ${{ needs.setup.outputs.project-name }} - - - name: Type Check (mypy) - if: needs.setup.outputs.mypy-enabled == 'true' - run: uvx mypy ${{ needs.setup.outputs.project-name }} - - - name: Run Tests - uses: i2mint/wads/actions/run-tests-uv@master - with: - root-dir: ${{ needs.setup.outputs.project-name }} - pytest-args: ${{ needs.setup.outputs.pytest-args }} - exclude-paths: ${{ needs.setup.outputs.exclude-paths }} - coverage: ${{ needs.setup.outputs.coverage-enabled }} - - - name: Track Code Metrics - if: needs.setup.outputs.metrics-enabled == 'true' - uses: i2mint/umpyre/actions/track-metrics@master - continue-on-error: true - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - config-path: ${{ needs.setup.outputs.metrics-config-path }} - storage-branch: ${{ needs.setup.outputs.metrics-storage-branch }} - python-version: ${{ needs.setup.outputs.metrics-python-version }} - force-run: ${{ needs.setup.outputs.metrics-force-run }} - - # Optional Windows testing (if enabled in config) - windows-validation: - name: Windows Tests - if: "!contains(github.event.head_commit.message, '[skip ci]') && needs.setup.outputs.test-on-windows == 'true'" - needs: setup - runs-on: windows-latest - continue-on-error: true - - steps: - - uses: actions/checkout@v6 - - - name: Set up uv - uses: astral-sh/setup-uv@v7 - with: - enable-cache: true - - - name: Set up Python - uses: i2mint/wads/actions/setup-python-uv@master - with: - python-version: ${{ fromJson(needs.setup.outputs.python-versions)[0] }} - - - name: Install System Dependencies - uses: i2mint/wads/actions/install-system-deps@master - with: - pyproject-path: . - - - name: Install Dependencies - uses: i2mint/wads/actions/install-deps-uv@master - - - name: Run Tests - uses: i2mint/wads/actions/run-tests-uv@master - with: - root-dir: ${{ needs.setup.outputs.project-name }} - pytest-args: ${{ needs.setup.outputs.pytest-args }} - exclude-paths: ${{ needs.setup.outputs.exclude-paths }} - - # Publishing job - publish: - name: Publish - permissions: - contents: write - if: "!contains(github.event.head_commit.message, '[skip ci]') && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/main')" - needs: [setup, validation] - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v6 - with: - fetch-depth: 0 - token: ${{ secrets.GITHUB_TOKEN }} - - - name: Set up uv - uses: astral-sh/setup-uv@v7 - - - name: Set up Python - uses: i2mint/wads/actions/setup-python-uv@master - with: - python-version: ${{ fromJson(needs.setup.outputs.python-versions)[0] }} - create-venv: "false" - - - name: Format Source Code - if: needs.setup.outputs.ruff-enabled != 'false' - run: uvx ruff format . - - - name: Format Source Code (black) - if: needs.setup.outputs.black-enabled == 'true' - run: uvx black . - - - name: Update Version Number - id: version - uses: i2mint/isee/actions/bump-version-number@master - - - name: Build Distribution - uses: i2mint/wads/actions/build-dist-uv@master - with: - sdist: ${{ needs.setup.outputs.build-sdist }} - wheel: ${{ needs.setup.outputs.build-wheel }} - - - name: Publish to PyPI - uses: i2mint/wads/actions/pypi-publish-uv@master - with: - pypi-token: ${{ secrets.PYPI_PASSWORD }} - - - name: Force SSH for git remote - run: git remote set-url origin git@github.com:${{ github.repository }}.git - - - name: Commit Changes - uses: i2mint/wads/actions/git-commit@master - with: - commit-message: "**CI** Formatted code + Updated version to ${{ env.VERSION }} [skip ci]" - ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }} - push: true - - - name: Tag Repository - uses: i2mint/wads/actions/git-tag@master - with: - tag: ${{ env.VERSION }} - message: "Release version ${{ env.VERSION }}" - push: true - - # Optional GitHub Pages (skipped when [tool.wads.ci.docs].enabled = false) - github-pages: - name: Publish GitHub Pages + ci: + uses: i2mint/wads/.github/workflows/uv-ci.yml@master permissions: contents: write pages: write - id-token: write - if: "!contains(github.event.head_commit.message, '[skip ci]') && github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && needs.setup.outputs.docs-enabled != 'false'" - needs: [setup, publish] - runs-on: ubuntu-latest - - steps: - - uses: i2mint/epythet/actions/publish-github-pages@master - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - ignore: "tests/,scrap/,examples/,ledger/" - # epythet's own site is the first v2 site (WP5 pilot, #16) - epythet-spec: "epythet>=0.2,<0.3" + # Transport: this repo's whole `secrets` context, serialized into the one + # secret the reusable workflow declares. Double-encoded (toJSON twice) so + # the value is a single line — a multiline secret would register its `{` + # and `}` lines as global log masks. Any secret name works; there is no + # fixed list to fall outside of. (Cross-owner `secrets: inherit` does not + # propagate secrets, so it cannot replace this.) + # + # Note this hands EVERY secret this repo can read — including org-level + # ones — to the called workflow. For a minimal secret surface (only the + # names you list), regenerate with + # wads-migrate ci-to-stub --transport named + # + # *Which* of these become job env vars — and which are required — is + # driven entirely by [tool.wads.ci.env] in pyproject.toml; nothing is + # exported unless declared there (`wads-secrets add VAR_NAME` declares + # one and can set its value). Non-sensitive values don't need a secret: + # use [tool.wads.ci.env].defaults (committed literals) or a repository + # *variable* (`gh variable set NAME`) — declared names fall back to + # repo variables automatically. + secrets: + WADS_CI_SECRETS_JSON: ${{ toJSON(toJSON(secrets)) }} diff --git a/MANIFEST.in b/MANIFEST.in deleted file mode 100644 index 95e6d89..0000000 --- a/MANIFEST.in +++ /dev/null @@ -1,5 +0,0 @@ -include LICENSE -include epythet/_static/docsrc/.gitignore -include epythet/_static/docsrc/conf.py -include epythet/_static/docsrc/make.bat -include epythet/_static/docsrc/Makefile diff --git a/pyproject.toml b/pyproject.toml index 7973c49..80510bc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -90,7 +90,7 @@ humor = true agentic_first = true [tool.wads.ci] -project_name = "" +project_name = "epythet" [tool.wads.ci.commands] pre_test = [] diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index dbd7557..0000000 --- a/setup.cfg +++ /dev/null @@ -1,52 +0,0 @@ -[metadata] -name = epythet -version = 0.2.12 -url = https://github.com/i2mint/epythet -platforms = any -description_file = README.md -long-description = file: README.md -long_description_content_type = text/markdown -root_url = https://github.com/i2mint -description = Tools for documentation and packaging -author_email = andie.phan@analog.com -license = Apache Software License -keywords = - documentation - publishing -display_name = Epythet - -[options] -packages = find: -include_package_data = True -zip_safe = False -install_requires = - Sphinx>=3.3.1 - myst_parser>=0.15.2 - cw>=0.1.1,<0.2 - commonmark>=0.9.1 - sphinx-toggleprompt>=0.0.5 - sphinx-copybutton>=0.4.0 - sphinx-rtd-theme>=1.0.0 - tomli - dol - requests - -[options.entry_points] -console_scripts = - epythet = epythet.cli:epythet_cli - -[options.extras_require] -dev = - pytest>=7.0 - pytest-cov>=4.0 - hubcap - pandas - ruff>=0.1.0 -docs = - sphinx>=6.0 - sphinx-rtd-theme>=1.0 - -[tool:pytest] -norecursedirs = - _static -