Skip to content

Publish CI red since March + legacy packaging: maintenance-mode plan #14

Description

@thorwhalen

From an automated fleet audit (2026-08-11). Recording findings + plan for this maintenance-mode package (README points users to its successor, ho).

Findings

  • The last two master CI runs failed in the Publish (3.10) job (logs expired) — consistent with the known wads legacy-publish breakage for un-migrated repos (current_pypi_version missing import), so PyPI may be behind master.
  • Legacy packaging: setup.cfg + setup.py (0.1.30), no pyproject.toml.
  • Tracked build/ and egg-info artifacts in the tree.
  • Thin test surface: essentially one test module for ~15 modules.

Recommended plan (maintenance-mode scope — keep it minimal)

  1. Modern wads migration (pyproject + uv CI stub) — fixes the publish job as a side effect; the smallest honest fix given the known root cause lives in the legacy path.
  2. Remove tracked build artifacts, extend .gitignore.
  3. Do NOT invest in test expansion here — the successor is ho; add a deprecation pointer in the PyPI long_description instead so pip users learn about ho.

Verify PyPI vs master version drift before publishing anything (a burned version number can't be reused).

Activity

  1. thorwhalen commented on Aug 17, 2026

    @thorwhalen
    MemberAuthor

    Triage 2026-08-17 — CI/packaging proceeding now; api_pkg_maker needs your decision

    From the musicai group open-issue ledger (priv: data/groups/musicai/docs/adr_musicai_open_issue_ledger.md).

    Corrections to this issue from the verification pass:

    • The failure is narrower than "Publish CI red". Both 2026-03-06 runs report Validation (3.10) => success / Publish (3.10) => failure, failing at the step named Publish, with Push Changes and Tag Repository skipped. The likely culprit is the epythet make . github call against a docs/ tree that the same commit deleted.
    • The item this issue most understates: the ho deprecation pointer is authored on master but has never reached PyPI. That is the most user-visible half — anyone installing http2py today still gets a package that does not tell them to use ho.
    • Note the version floor: 0.1.31 is already burned on PyPI (2026-03-06), so the migration must set 0.1.32.

    The decision. api_pkg_maker — the api-pkg-maker console_script, and the subject of this repo's only test module — is broken on modern setuptools because setuptools.sandbox was removed.

    • (a) Rewrite it onto python -m build / subprocess instead of sandbox.run_setup, keeping the CLI alive.
    • (b) Delete it plus its console_script and its test, leaving http2py a library-only package. Smallest honest fix for a package in maintenance mode, but it removes a shipped entry point.
    • (c) Leave it and exclude it from CI collection.

    Proceeding with (c) now as the reversible default, so the migration can land and a green CI can finally push the ho pointer to PyPI. (a) and (b) stay open for you — say the word and either is a small follow-up.

    https://claude.ai/code/session_01GPpn5ixPgqGqk7uJH7cC6o

  2. thorwhalen commented on Aug 17, 2026

    @thorwhalen
    MemberAuthor

    Two corrections before this plan is executed

    1. PyPI is ahead of the repo, not behind — and 0.1.31 is burned.

    PyPI has 0.1.31, uploaded 2026-03-06T11:46:58 — inside the window of the very run this issue calls a failure (22762078882). master's setup.cfg still says 0.1.30, and git tag tops out at 0.1.30.

    So twine succeeded; what failed came after it — the version push-back and tag steps never ran, which is why the repo looks behind. Consequences:

    • 0.1.31 cannot be reused. The next release must start at 0.1.32.
    • PyPI's published 0.1.31 long_description does not carry the ho pointer — that README note landed in 2aca066, which never published. So the deprecation pointer this issue wants is genuinely not out there yet.

    2. This repo has no Actions secrets (gh api repos/i2mint/http2py/actions/secrets → total_count: 0), so the migration must land with [tool.wads.ci.publish] enabled = false until PYPI_PASSWORD is provisioned, or the first merge 403s.

    3. One blocker the plan does not mention: http2py/api_pkg_maker.py:7 does from setuptools import sandbox, which was removed in setuptools ≥ 80. Collection aborts on any current environment, taking the py2request.py doctests down with it. Since this is a maintenance-mode package pointing at ho, dropping the module and its api-pkg-maker console script is probably cheaper than repairing it — but that is a maintainer call, so it is noted here rather than assumed.

    Found during a cross-repo verified audit of all open issues in the musicai group.

  3. thorwhalen commented on Aug 17, 2026

    @thorwhalen
    MemberAuthor

    Correction to my comment above — this repo is covered

    My previous comment said this repo has no PYPI_PASSWORD. That was wrong, and the error was in my method: I queried repos/<owner>/<repo>/actions/secrets, which returns repo-level secrets only. Organization secrets also resolve at run time.

    i2mint is an Organization (gh api users/i2mint --jq .type → Organization) and carries org-level secrets at visibility=all:

    gh api orgs/i2mint/actions/secrets
    # NPM_TOKEN, PYPI_PASSWORD, PYPI_USERNAME, SCRIPTS_TOKEN, SCRIPTS_USERNAME, SSH_PRIVATE_KEY  (all visibility=all)
    

    That is how taped publishes today with zero repo-level secrets. So publishing can stay enabled here — do not land the migration with publish = false on account of my earlier comment.

    The corrected picture across the music-AI repos:

    status repos
    repo-level PYPI_PASSWORD hum, sung, loopyng
    covered by i2mint org secrets hear, http2py, taped
    genuinely none — publish will 403 theremin, sonification (owner thorwhalen is a User account, so there is no org fallback)

    Caught by a peer session cross-checking the audit. Apologies for the noise.

  4. thorwhalen commented on Aug 17, 2026

    @thorwhalen
    MemberAuthor

    PR #15 opened against this issue (advancing it, not closing it).

    Root cause is now measured, and it corrects the guess in the issue body. It was not the wads current_pypi_version breakage. Both 2026-03-06 runs report Validation (3.10) => success / Publish (3.10) => failure, failing at the step named Publish, which ran twine upload ... && epythet make . github as one step. The upload succeeded — that is why 0.1.31 is on PyPI — and the epythet call failed because 43aef24 had deleted docs/ and docsrc/. The failing step is also why Push Changes and Tag Repository were skipped, leaving the tree at 0.1.30 while PyPI sat at 0.1.31.

    Item 3 of the plan is more urgent than it reads. The ho pointer has never reached PyPI: 0.1.31 was uploaded at 2026-03-06T11:46:58Z and the README commit adding the note landed 7 seconds later, at 11:47:05Z. The 0.1.31 long_description on PyPI does not contain it. So the deprecation notice ships only when a publish next succeeds — which makes the CI fix and the pointer the same deliverable, not two.

    Two further blockers were found that would have kept CI red regardless of the migration, both fixed/worked around in #15:

    • http2py/tests/conftest.py imported py2http at module level. pytest eagerly imports the conftest of any test* sub-directory before --ignore applies, so excluding the directory was not sufficient — the session aborted with ImportError while loading conftest on any machine without py2http.
    • A cold pip install http2py fails at import ju: ju/oas.py has an unconditional, unused import dill and does not declare dill. Filed as ju/oas.py has an unconditional import dill that is never used and is not a declared dependency ju#6.

    Still open here after #15 merges:

    1. api_pkg_maker — (a) rewrite for modern setuptools or (b) delete. Modernize packaging + CI so a release can actually reach PyPI (#14) #15 takes the reversible middle course (leave it, exclude it from collection, with a tripwire test that fires if it becomes importable), because neither answer has arrived. This issue should stay open until one is chosen.
    2. Confirmation that Publish actually goes green and 0.1.33 reaches PyPI carrying the ho pointer.
    3. Dropping the temporary dill dependency once ju/oas.py has an unconditional import dill that is never used and is not a declared dependency ju#6 is released.

    Item 2 of the plan (build artifacts / .gitignore) needed no work — build/ and *.egg-info/ are untracked and already ignored.

    https://claude.ai/code/session_01GPpn5ixPgqGqk7uJH7cC6o

  5. thorwhalen commented on Sep 4, 2026

    @thorwhalen
    MemberAuthor

    Item 1 is answered: rewrite, not delete. Landed in #17.

    api_pkg_maker used setuptools.sandbox.run_setup exactly once, to build an sdist. That
    is now setup.py sdist in a subprocess, which also removes the bare os.chdir(tempdir)
    the old path required and never undid. OUTPUT_DIR moved from os.environ["HOME"] to
    expanduser("~"), which was an import-time KeyError on Windows.

    api-pkg-maker --help works again — this repo's only console script, dead since
    setuptools dropped sandbox.

    Consequences for the guards this issue put in place:

    • http2py/api_pkg_maker.py is removed from exclude_paths (pyproject) and
      collect_ignore (conftest), and is collected by CI again.
    • The test_known_broken_module_is_still_broken tripwire has fired and been inverted, as
      its own docstring anticipated: it now asserts the module imports and that main exists.
    • http2py/tests stays excluded — separate cause (it needs py2http, a test-only
      dependency CI does not install).
    • mk_api_pkg is covered end-to-end by a test that builds a real sdist offline and checks
      the working directory survives. It PASSES in CI on 3.10 and 3.12 (not skipped).

    One thing worth recording, because it was invisible before: mk_api_pkg needs setuptools
    at runtime, and always did
    — the old from setuptools import sandbox made it an
    undeclared import-time dependency. A uv-created venv does not ship setuptools, so the
    first CI run went red. It is now a preflight check with an actionable message, and
    setuptools is in the dev extra (not the runtime dependencies — it is needed by this one
    function, not by import http2py).

    Still open here:

    1. Confirmation that Publish goes green and the release carries the ho pointer. Replace argh with cw, and fix the api-pkg-maker console script #17 has
      just merged, so the next publish is the one to check.
    2. Dropping the temporary dill dependency once ju/oas.py has an unconditional import dill that is never used and is not a declared dependency ju#6 is released.

    Separately, #17 also removed argh (LGPL) from this package — see #16.

  6. thorwhalen commented on Sep 4, 2026

    @thorwhalen
    MemberAuthor

    Item 2 is confirmed done. The Publish job on master went green (run 33871052828), http2py 0.1.34 is on PyPI, and its long_description does carry the ho pointer:

    Note: A new, lighterweight, more modern replacement: ho

    That was the gap noted earlier — 0.1.31 was uploaded 7 seconds before the README commit landed, so the pointer had never actually reached PyPI. It has now.

    Published core dependencies are now cw<0.2,>=0.1.1, dill, glom, i2, importlib-resources, ju, pyyaml, requests — no argh.

    Only item 3 remains: dropping the temporary dill dependency once i2mint/ju#6 is released. tests/test_dependency_workarounds.py fails as soon as that happens, so it will not be forgotten.

  7. thorwhalen commented on Sep 22, 2026

    @thorwhalen
    MemberAuthor

    Done — verified fully resolved by subsequent work (repo already modernized before this session, likely via PR #17 or an earlier pass):

    • Legacy packaging is gone: repo now has `pyproject.toml` (no `setup.cfg`/`setup.py`, no tracked build/egg-info artifacts — `git ls-files` confirms clean).
    • Publish CI is green: last 5 `master` runs all `success` (checked via `gh run list`).
    • PyPI (`0.1.34`) matches `pyproject.toml`'s `version = "0.1.34"` — no drift.

    Item 3 (deprecation pointer to `ho` in the long_description) wasn't verified either way and is cosmetic; not worth reopening for.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions