Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ jobs:
shell: sh
env:
SET_ENV_SCRIPT: IyAvLy8gc2NyaXB0CiMgcmVxdWlyZXMtcHl0aG9uID0gIj09My4xMiIKIyBkZXBlbmRlbmNpZXMgPSBbCiMgICAgICJweXlhbWw9PTYuMC4yIiwKIyBdCiMgLy8vCmltcG9ydCBqc29uCmltcG9ydCBvcwppbXBvcnQgc3lzCgppbXBvcnQgeWFtbAoKR0lUSFVCX0VOViA9IG9zLmdldGVudigiR0lUSFVCX0VOViIpCmlmIEdJVEhVQl9FTlYgaXMgTm9uZToKICAgIHJhaXNlIFZhbHVlRXJyb3IoIkdJVEhVQl9FTlYgbm90IHNldC4gTXVzdCBiZSBydW4gaW5zaWRlIEdpdEh1YiBBY3Rpb25zLiIpCgpERUxJTUlURVIgPSAiRU9GIgoKCmRlZiBzZXRfZW52KGVudik6CgogICAgZW52ID0geWFtbC5sb2FkKGVudiwgTG9hZGVyPXlhbWwuQmFzZUxvYWRlcikKICAgIHByaW50KGpzb24uZHVtcHMoZW52LCBpbmRlbnQ9MikpCgogICAgaWYgbm90IGlzaW5zdGFuY2UoZW52LCBkaWN0KToKICAgICAgICB0aXRsZSA9ICJgZW52YCBtdXN0IGJlIG1hcHBpbmciCiAgICAgICAgbWVzc2FnZSA9IGYiYGVudmAgbXVzdCBiZSBtYXBwaW5nIG9mIGVudiB2YXJpYWJsZXMgdG8gdmFsdWVzLCBnb3QgdHlwZSB7dHlwZShlbnYpfSIKICAgICAgICBwcmludChmIjo6ZXJyb3IgdGl0bGU9e3RpdGxlfTo6e21lc3NhZ2V9IikKICAgICAgICBleGl0KDEpCgogICAgZm9yIGssIHYgaW4gZW52Lml0ZW1zKCk6CgogICAgICAgIGlmIG5vdCBpc2luc3RhbmNlKHYsIHN0cik6CiAgICAgICAgICAgIHRpdGxlID0gImBlbnZgIHZhbHVlcyBtdXN0IGJlIHN0cmluZ3MiCiAgICAgICAgICAgIG1lc3NhZ2UgPSBmImBlbnZgIHZhbHVlcyBtdXN0IGJlIHN0cmluZ3MsIGJ1dCB2YWx1ZSBvZiB7a30gaGFzIHR5cGUge3R5cGUodil9IgogICAgICAgICAgICBwcmludChmIjo6ZXJyb3IgdGl0bGU9e3RpdGxlfTo6e21lc3NhZ2V9IikKICAgICAgICAgICAgZXhpdCgxKQoKICAgICAgICB2ID0gdi5zcGxpdCgiXG4iKQoKICAgICAgICB3aXRoIG9wZW4oR0lUSFVCX0VOViwgImEiKSBhcyBmOgogICAgICAgICAgICBpZiBsZW4odikgPT0gMToKICAgICAgICAgICAgICAgIGYud3JpdGUoZiJ7a309e3ZbMF19XG4iKQogICAgICAgICAgICBlbHNlOgogICAgICAgICAgICAgICAgZm9yIGxpbmUgaW4gdjoKICAgICAgICAgICAgICAgICAgICBhc3NlcnQgbGluZS5zdHJpcCgpICE9IERFTElNSVRFUgogICAgICAgICAgICAgICAgZi53cml0ZShmIntrfTw8e0RFTElNSVRFUn1cbiIpCiAgICAgICAgICAgICAgICBmb3IgbGluZSBpbiB2OgogICAgICAgICAgICAgICAgICAgIGYud3JpdGUoZiJ7bGluZX1cbiIpCiAgICAgICAgICAgICAgICBmLndyaXRlKGYie0RFTElNSVRFUn1cbiIpCgogICAgICAgIHByaW50KGYie2t9IHdyaXR0ZW4gdG8gR0lUSFVCX0VOViIpCgoKaWYgX19uYW1lX18gPT0gIl9fbWFpbl9fIjoKICAgIHNldF9lbnYoc3lzLmFyZ3ZbMV0pCg==
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
fetch-depth: 0
lfs: true
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/publish_pure_python.yml
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ jobs:
shell: sh
env:
SET_ENV_SCRIPT: IyAvLy8gc2NyaXB0CiMgcmVxdWlyZXMtcHl0aG9uID0gIj09My4xMiIKIyBkZXBlbmRlbmNpZXMgPSBbCiMgICAgICJweXlhbWw9PTYuMC4yIiwKIyBdCiMgLy8vCmltcG9ydCBqc29uCmltcG9ydCBvcwppbXBvcnQgc3lzCgppbXBvcnQgeWFtbAoKR0lUSFVCX0VOViA9IG9zLmdldGVudigiR0lUSFVCX0VOViIpCmlmIEdJVEhVQl9FTlYgaXMgTm9uZToKICAgIHJhaXNlIFZhbHVlRXJyb3IoIkdJVEhVQl9FTlYgbm90IHNldC4gTXVzdCBiZSBydW4gaW5zaWRlIEdpdEh1YiBBY3Rpb25zLiIpCgpERUxJTUlURVIgPSAiRU9GIgoKCmRlZiBzZXRfZW52KGVudik6CgogICAgZW52ID0geWFtbC5sb2FkKGVudiwgTG9hZGVyPXlhbWwuQmFzZUxvYWRlcikKICAgIHByaW50KGpzb24uZHVtcHMoZW52LCBpbmRlbnQ9MikpCgogICAgaWYgbm90IGlzaW5zdGFuY2UoZW52LCBkaWN0KToKICAgICAgICB0aXRsZSA9ICJgZW52YCBtdXN0IGJlIG1hcHBpbmciCiAgICAgICAgbWVzc2FnZSA9IGYiYGVudmAgbXVzdCBiZSBtYXBwaW5nIG9mIGVudiB2YXJpYWJsZXMgdG8gdmFsdWVzLCBnb3QgdHlwZSB7dHlwZShlbnYpfSIKICAgICAgICBwcmludChmIjo6ZXJyb3IgdGl0bGU9e3RpdGxlfTo6e21lc3NhZ2V9IikKICAgICAgICBleGl0KDEpCgogICAgZm9yIGssIHYgaW4gZW52Lml0ZW1zKCk6CgogICAgICAgIGlmIG5vdCBpc2luc3RhbmNlKHYsIHN0cik6CiAgICAgICAgICAgIHRpdGxlID0gImBlbnZgIHZhbHVlcyBtdXN0IGJlIHN0cmluZ3MiCiAgICAgICAgICAgIG1lc3NhZ2UgPSBmImBlbnZgIHZhbHVlcyBtdXN0IGJlIHN0cmluZ3MsIGJ1dCB2YWx1ZSBvZiB7a30gaGFzIHR5cGUge3R5cGUodil9IgogICAgICAgICAgICBwcmludChmIjo6ZXJyb3IgdGl0bGU9e3RpdGxlfTo6e21lc3NhZ2V9IikKICAgICAgICAgICAgZXhpdCgxKQoKICAgICAgICB2ID0gdi5zcGxpdCgiXG4iKQoKICAgICAgICB3aXRoIG9wZW4oR0lUSFVCX0VOViwgImEiKSBhcyBmOgogICAgICAgICAgICBpZiBsZW4odikgPT0gMToKICAgICAgICAgICAgICAgIGYud3JpdGUoZiJ7a309e3ZbMF19XG4iKQogICAgICAgICAgICBlbHNlOgogICAgICAgICAgICAgICAgZm9yIGxpbmUgaW4gdjoKICAgICAgICAgICAgICAgICAgICBhc3NlcnQgbGluZS5zdHJpcCgpICE9IERFTElNSVRFUgogICAgICAgICAgICAgICAgZi53cml0ZShmIntrfTw8e0RFTElNSVRFUn1cbiIpCiAgICAgICAgICAgICAgICBmb3IgbGluZSBpbiB2OgogICAgICAgICAgICAgICAgICAgIGYud3JpdGUoZiJ7bGluZX1cbiIpCiAgICAgICAgICAgICAgICBmLndyaXRlKGYie0RFTElNSVRFUn1cbiIpCgogICAgICAgIHByaW50KGYie2t9IHdyaXR0ZW4gdG8gR0lUSFVCX0VOViIpCgoKaWYgX19uYW1lX18gPT0gIl9fbWFpbl9fIjoKICAgIHNldF9lbnYoc3lzLmFyZ3ZbMV0pCg==
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
fetch-depth: 0
lfs: true
Expand Down
21 changes: 21 additions & 0 deletions .github/workflows/test_publish_to_testpypi.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
name: Test publish to Test PyPI

on:
workflow_dispatch:

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
test_publish:
uses: ./.github/workflows/publish.yml
with:
test_groups: test, concurrency
test_extras: recommended
test_command: pytest --pyargs test_package
repository_url: https://test.pypi.org/legacy/
upload_to_pypi: 'true'
timeout-minutes: 30
secrets:
pypi_token: ${{ secrets.TEST_PYPI_API_TOKEN }}
Empty file added a/b/c/test.txt
Empty file.
5 changes: 5 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ test = [
"hypothesis>=6.113.0",
"pytest>=8.3.5",
]
publish = [
{include-group = "test"},
"build>=1.0.0",
"twine>=5.0.0",
]

[tool.setuptools]
include-package-data = false
Expand Down
81 changes: 81 additions & 0 deletions test_package/tests/test_publish_pypi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import os
import subprocess
import sys
from pathlib import Path


def test_build_package():
"""Test that the package can be built successfully."""
result = subprocess.run(
[sys.executable, "-m", "build", "--outdir", "dist"],
capture_output=True,
text=True
)
assert result.returncode == 0, f"Build failed: {result.stderr}"

# Check that distribution files were created
dist_dir = Path("dist")
assert dist_dir.exists(), "dist directory not created"

dist_files = list(dist_dir.glob("*.whl")) + list(dist_dir.glob("*.tar.gz"))
assert len(dist_files) > 0, "No distribution files created"


def test_publish_to_test_pypi():
"""Test publishing package to Test PyPI.

This test requires TWINE_USERNAME and TWINE_PASSWORD environment variables
to be set for Test PyPI authentication.

To run this test:
1. Set TWINE_USERNAME (usually '__token__')
2. Set TWINE_PASSWORD (your Test PyPI API token)
3. Run: pytest test_package/tests/test_publish_pypi.py::test_publish_to_test_pypi
"""
# Skip if credentials are not available
if not os.getenv("TWINE_USERNAME") or not os.getenv("TWINE_PASSWORD"):
import pytest
pytest.skip("TWINE_USERNAME and TWINE_PASSWORD not set")

# First build the package
build_result = subprocess.run(
[sys.executable, "-m", "build", "--outdir", "dist"],
capture_output=True,
text=True
)
assert build_result.returncode == 0, f"Build failed: {build_result.stderr}"

# Upload to Test PyPI
upload_result = subprocess.run(
[
sys.executable, "-m", "twine", "upload",
"--repository", "testpypi",
"--skip-existing",
"dist/*"
],
capture_output=True,
text=True
)

# Check result (skip-existing means it's ok if already uploaded)
assert upload_result.returncode == 0, f"Upload failed: {upload_result.stderr}"
print(f"Upload output: {upload_result.stdout}")


def test_check_package_metadata():
"""Test that package metadata is valid for PyPI."""
# Build first
subprocess.run(
[sys.executable, "-m", "build", "--outdir", "dist"],
capture_output=True,
text=True
)

# Check with twine
result = subprocess.run(
[sys.executable, "-m", "twine", "check", "dist/*"],
capture_output=True,
text=True
)
assert result.returncode == 0, f"Package check failed: {result.stderr}"
assert "PASSED" in result.stdout, "Package metadata validation failed"
14 changes: 14 additions & 0 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,17 @@ commands =
conda: python -c "import os, sys; assert os.path.exists(os.path.join(sys.prefix, 'conda-meta', 'history'))"
conda: micromamba list
pytest --pyargs test_package {posargs}

[testenv:publish-test]
description = test building and publishing to Test PyPI
skip_install = false
dependency_groups = publish
passenv =
TWINE_USERNAME
TWINE_PASSWORD
commands =
# Run build and metadata check tests (always)
pytest test_package/tests/test_publish_pypi.py::test_build_package -v
pytest test_package/tests/test_publish_pypi.py::test_check_package_metadata -v
# Run actual publish test (only if credentials are set)
pytest test_package/tests/test_publish_pypi.py::test_publish_to_test_pypi -v
Loading