Skip to content

Commit 0d5405f

Browse files
committed
Enhance version resolution process with repository support
This update introduces optional parameters for specifying the target repository and its URL in the version resolution function. The README is also updated to clarify the version detection process, including querying PyPI, TestPyPI, and Azure Artifacts for the latest published version. This enhancement improves the flexibility of version management and ensures accurate version calculations based on the actual published state of packages.
1 parent 88be4c3 commit 0d5405f

3 files changed

Lines changed: 281 additions & 57 deletions

File tree

‎README.md‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,8 +455,15 @@ The `--version` option:
455455

456456
When `--version` is not provided, the tool can automatically determine the next version using semantic-release. This requires Node.js, npm, and semantic-release to be installed.
457457

458+
**Version Detection:**
459+
- **Baseline version**:
460+
- **Registry Query (Preferred)**: When publishing to a repository (PyPI, TestPyPI, or Azure Artifacts), the tool queries the target registry for the latest published version and uses it as the baseline for version calculation. This ensures version calculations are based on what's actually published, not just git tags.
461+
- **Git Tags (Fallback)**: If the package doesn't exist on the registry yet (first release) or if registry query fails, the tool falls back to using git tags to determine the starting version.
462+
- **New version to publish**: After determining the baseline version, [`semantic-release`](https://semantic-release.gitbook.io/semantic-release/) analyzes commits since that version to calculate the next version bump (major, minor, or patch) based on [_conventional commit_](https://www.conventionalcommits.org/en/v1.0.0/) messages.
463+
458464
**For subfolder builds (Workflow 1):**
459465
- Uses per-package tags: `{package-name}-v{version}` (e.g., `my-package-v1.2.3`)
466+
- Queries the target registry for the latest published version of the subfolder package
460467
- Filters commits to only those affecting the subfolder path
461468
- **Commit filtering behavior**: Only commits that modify files within the subfolder path are considered for version calculation. Commits that only target files outside the subfolder are excluded. For example:
462469
- `fix: update my_subfolder/foo.py` → **Included** (affects subfolder)
@@ -466,8 +473,14 @@ When `--version` is not provided, the tool can automatically determine the next
466473

467474
**For main package builds (Workflow 2):**
468475
- Uses repo-level tags: `v{version}` (e.g., `v1.2.3`)
476+
- Queries the target registry for the latest published version when publishing
469477
- Analyzes all commits in the repository
470478

479+
**Registry Support:**
480+
- **PyPI**: Fully supported via JSON API (`https://pypi.org/pypi/{package-name}/json`)
481+
- **TestPyPI**: Fully supported via JSON API (`https://test.pypi.org/pypi/{package-name}/json`)
482+
- **Azure Artifacts**: Basic support with fallback to git tags. Azure Artifacts uses a different API format and may require authentication, so if the query fails, the tool automatically falls back to git tags.
483+
471484
**Setup:**
472485
```bash
473486
# Install semantic-release globally

‎src/python_package_folder/python_package_folder.py‎

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ def resolve_version_via_semantic_release(
2727
project_root: Path,
2828
subfolder_path: Path | None = None,
2929
package_name: str | None = None,
30+
repository: str | None = None,
31+
repository_url: str | None = None,
3032
) -> str | None:
3133
"""
3234
Resolve the next version using semantic-release via Node.js script.
@@ -35,6 +37,8 @@ def resolve_version_via_semantic_release(
3537
project_root: Root directory of the project
3638
subfolder_path: Optional path to subfolder (relative to project_root) for Workflow 1
3739
package_name: Optional package name for subfolder builds
40+
repository: Optional target repository ('pypi', 'testpypi', or 'azure')
41+
repository_url: Optional repository URL (required for Azure Artifacts)
3842
3943
Returns:
4044
Version string if a release is determined, None if no release or error
@@ -98,7 +102,17 @@ def resolve_version_via_semantic_release(
98102
else subfolder_path
99103
)
100104
cmd.extend([str(rel_path), package_name])
101-
# Workflow 2: main package (no additional args needed)
105+
elif package_name:
106+
# Main package build with package_name (for registry queries)
107+
# Pass null for subfolder_path, then package_name
108+
cmd.extend(["", package_name])
109+
# Workflow 2: main package without package_name (no additional args needed)
110+
111+
# Add repository information if provided
112+
if repository:
113+
cmd.append(repository)
114+
if repository_url:
115+
cmd.append(repository_url)
102116

103117
result = subprocess.run(
104118
cmd,
@@ -297,6 +311,10 @@ def build_cmd() -> None:
297311
# Version is needed for subfolder builds or when publishing main package
298312
if is_subfolder or args.publish:
299313
print("No --version provided, attempting to resolve via semantic-release...")
314+
# Get repository info if publishing
315+
repository = args.publish if args.publish else None
316+
repository_url = args.repository_url if args.publish else None
317+
300318
if is_subfolder:
301319
# Workflow 1: subfolder build
302320
# src_dir is guaranteed to be relative to project_root due to is_subfolder check
@@ -305,11 +323,34 @@ def build_cmd() -> None:
305323
).lower().strip("-")
306324
subfolder_rel_path = src_dir.relative_to(project_root)
307325
resolved_version = resolve_version_via_semantic_release(
308-
project_root, subfolder_rel_path, package_name
326+
project_root,
327+
subfolder_rel_path,
328+
package_name,
329+
repository=repository,
330+
repository_url=repository_url,
309331
)
310332
else:
311333
# Workflow 2: main package
312-
resolved_version = resolve_version_via_semantic_release(project_root)
334+
# For main package, we need package_name from pyproject.toml for registry queries
335+
package_name_for_registry = None
336+
if repository:
337+
try:
338+
import tomllib
339+
pyproject_path = project_root / "pyproject.toml"
340+
if pyproject_path.exists():
341+
with open(pyproject_path, "rb") as f:
342+
data = tomllib.load(f)
343+
package_name_for_registry = data.get("project", {}).get("name")
344+
except Exception:
345+
pass
346+
347+
resolved_version = resolve_version_via_semantic_release(
348+
project_root,
349+
subfolder_path=None,
350+
package_name=package_name_for_registry,
351+
repository=repository,
352+
repository_url=repository_url,
353+
)
313354

314355
if resolved_version:
315356
print(f"Resolved version via semantic-release: {resolved_version}")

0 commit comments

Comments
 (0)