Files
pkgmgr/tests/integration/test_publish_integration.py
Kevin Veen-Birkenbach 9456ad4475
Some checks failed
Mark stable commit / test-unit (push) Has been cancelled
Mark stable commit / test-integration (push) Has been cancelled
Mark stable commit / test-env-virtual (push) Has been cancelled
Mark stable commit / test-env-nix (push) Has been cancelled
Mark stable commit / test-e2e (push) Has been cancelled
Mark stable commit / test-virgin-user (push) Has been cancelled
Mark stable commit / test-virgin-root (push) Has been cancelled
Mark stable commit / linter-shell (push) Has been cancelled
Mark stable commit / linter-python (push) Has been cancelled
Mark stable commit / mark-stable (push) Has been cancelled
feat(publish): add PyPI publish workflow, CLI command, parser integration, and tests
* Introduce publish action with PyPI target detection via MIRRORS
* Resolve version from SemVer git tags on HEAD
* Support preview mode and non-interactive CI usage
* Build and upload artifacts using build + twine with token resolution
* Add CLI wiring (dispatch, command handler, parser)
* Add E2E publish help tests for pkgmgr and nix run
* Add integration tests for publish preview and mirror handling
* Add unit tests for git tag parsing, PyPI URL parsing, workflow preview, and CLI handler
* Clean up dispatch and parser structure while integrating publish

https://chatgpt.com/share/693f0f00-af68-800f-8846-193dca69bd2e
2025-12-14 20:24:01 +01:00

120 lines
3.4 KiB
Python

from __future__ import annotations
import io
import os
import shutil
import subprocess
import tempfile
import unittest
from contextlib import redirect_stdout
from types import SimpleNamespace
from pkgmgr.cli.commands.publish import handle_publish
def _run(cmd: list[str], cwd: str) -> None:
subprocess.run(
cmd,
cwd=cwd,
check=True,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
)
class TestIntegrationPublish(unittest.TestCase):
def setUp(self) -> None:
if shutil.which("git") is None:
self.skipTest("git is required for this integration test")
self.tmp = tempfile.TemporaryDirectory()
self.repo_dir = self.tmp.name
# Initialize git repository
_run(["git", "init"], cwd=self.repo_dir)
_run(["git", "config", "user.email", "ci@example.invalid"], cwd=self.repo_dir)
_run(["git", "config", "user.name", "CI"], cwd=self.repo_dir)
with open(os.path.join(self.repo_dir, "README.md"), "w", encoding="utf-8") as f:
f.write("test\n")
_run(["git", "add", "README.md"], cwd=self.repo_dir)
_run(["git", "commit", "-m", "init"], cwd=self.repo_dir)
_run(["git", "tag", "-a", "v1.2.3", "-m", "v1.2.3"], cwd=self.repo_dir)
# Create MIRRORS file with PyPI target
with open(os.path.join(self.repo_dir, "MIRRORS"), "w", encoding="utf-8") as f:
f.write("https://pypi.org/project/pkgmgr/\n")
def tearDown(self) -> None:
self.tmp.cleanup()
def test_publish_preview_end_to_end(self) -> None:
ctx = SimpleNamespace(
repositories_base_dir=self.repo_dir,
all_repositories=[
{
"name": "pkgmgr",
"directory": self.repo_dir,
}
],
)
selected = [
{
"name": "pkgmgr",
"directory": self.repo_dir,
}
]
args = SimpleNamespace(
preview=True,
non_interactive=False,
)
buf = io.StringIO()
with redirect_stdout(buf):
handle_publish(args=args, ctx=ctx, selected=selected)
out = buf.getvalue()
self.assertIn("[pkgmgr] Publishing repository", out)
self.assertIn("[INFO] Publishing pkgmgr for tag v1.2.3", out)
self.assertIn("[PREVIEW] Would build and upload to PyPI.", out)
# Preview must not create dist/
self.assertFalse(os.path.isdir(os.path.join(self.repo_dir, "dist")))
def test_publish_skips_without_pypi_mirror(self) -> None:
with open(os.path.join(self.repo_dir, "MIRRORS"), "w", encoding="utf-8") as f:
f.write("git@github.com:example/example.git\n")
ctx = SimpleNamespace(
repositories_base_dir=self.repo_dir,
all_repositories=[
{
"name": "pkgmgr",
"directory": self.repo_dir,
}
],
)
selected = [
{
"name": "pkgmgr",
"directory": self.repo_dir,
}
]
args = SimpleNamespace(
preview=True,
non_interactive=False,
)
buf = io.StringIO()
with redirect_stdout(buf):
handle_publish(args=args, ctx=ctx, selected=selected)
out = buf.getvalue()
self.assertIn("[INFO] No PyPI mirror found. Skipping publish.", out)