-
Notifications
You must be signed in to change notification settings - Fork 0
V0.5.4/ci automation #23
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,26 +1,30 @@ | ||
| #!/usr/bin/env python3 | ||
| """ | ||
| Simplified package bumping for Codebelt service updates (Option B). | ||
| Package bumping for Codebelt service updates. | ||
|
|
||
| Only updates packages published by the triggering source repo. | ||
| Updates packages published by the triggering source repo to the specified version. | ||
| Additionally fetches the latest stable version from NuGet for all other Codebelt-related | ||
| packages and updates them as well. | ||
| Does NOT update Microsoft.Extensions.*, BenchmarkDotNet, or other third-party packages. | ||
| Does NOT parse TFM conditions - only bumps Codebelt/Cuemon/Savvyio packages to the triggering version. | ||
|
|
||
| Usage: | ||
| TRIGGER_SOURCE=cuemon TRIGGER_VERSION=10.3.0 python3 bump-nuget.py | ||
|
|
||
| Behavior: | ||
| - If TRIGGER_SOURCE is "cuemon" and TRIGGER_VERSION is "10.3.0": | ||
| - Cuemon.Core: 10.2.1 → 10.3.0 | ||
| - Cuemon.Extensions.IO: 10.2.1 → 10.3.0 | ||
| - Cuemon.Core: 10.2.1 → 10.3.0 (triggered source, set to given version) | ||
| - Cuemon.Extensions.IO: 10.2.1 → 10.3.0 (triggered source, set to given version) | ||
| - Codebelt.Extensions.BenchmarkDotNet.*: 1.2.3 → <latest from NuGet> (other Codebelt) | ||
| - Microsoft.Extensions.Hosting: 9.0.13 → UNCHANGED (not a Codebelt package) | ||
| - BenchmarkDotNet: 0.15.8 → UNCHANGED (not a Codebelt package) | ||
| """ | ||
|
|
||
| import json | ||
| import re | ||
| import os | ||
| import sys | ||
| from typing import Dict, List | ||
| import urllib.request | ||
| from typing import Dict, List, Optional | ||
|
|
||
| TRIGGER_SOURCE = os.environ.get("TRIGGER_SOURCE", "") | ||
| TRIGGER_VERSION = os.environ.get("TRIGGER_VERSION", "") | ||
|
|
@@ -31,21 +35,24 @@ | |
| "xunit": ["Codebelt.Extensions.Xunit"], | ||
| "benchmarkdotnet": ["Codebelt.Extensions.BenchmarkDotNet"], | ||
| "bootstrapper": ["Codebelt.Bootstrapper"], | ||
| "carter": ["Codebelt.Extensions.Carter"], | ||
| "newtonsoft-json": [ | ||
| "Codebelt.Extensions.Newtonsoft.Json", | ||
| "Codebelt.Extensions.AspNetCore.Newtonsoft.Json", | ||
| "Codebelt.Extensions.AspNetCore.Mvc.Formatters.Newtonsoft", | ||
| ], | ||
| "aws-signature-v4": ["Codebelt.Extensions.AspNetCore.Authentication.AwsSignature"], | ||
| "unitify": ["Codebelt.Unitify"], | ||
| "yamldotnet": [ | ||
| "Codebelt.Extensions.YamlDotNet", | ||
| "Codebelt.Extensions.AspNetCore.Text.Yaml", | ||
| "Codebelt.Extensions.AspNetCore.Mvc.Formatters.Text.Yaml", | ||
| ], | ||
| "globalization": ["Codebelt.Extensions.Globalization"], | ||
| "asp-versioning": ["Codebelt.Extensions.Asp.Versioning"], | ||
| "swashbuckle-aspnetcore": ["Codebelt.Extensions.Swashbuckle"], | ||
| "savvyio": ["Savvyio."], | ||
| "shared-kernel": [], | ||
| "shared-kernel": ["Codebelt.SharedKernel"], | ||
| } | ||
|
|
||
|
|
||
|
|
@@ -57,6 +64,38 @@ def is_triggered_package(package_name: str) -> bool: | |
| return any(package_name.startswith(prefix) for prefix in prefixes) | ||
|
|
||
|
|
||
| def is_codebelt_package(package_name: str) -> bool: | ||
| """Check if package belongs to any Codebelt repo (regardless of trigger source).""" | ||
| for repo_prefixes in SOURCE_PACKAGE_MAP.values(): | ||
| if any(package_name.startswith(prefix) for prefix in repo_prefixes if prefix): | ||
| return True | ||
| return False | ||
|
|
||
|
|
||
| _nuget_version_cache: Dict[str, Optional[str]] = {} | ||
|
|
||
|
|
||
| def get_latest_nuget_version(package_name: str) -> Optional[str]: | ||
| """Fetch the latest stable version of a package from NuGet.""" | ||
| if package_name in _nuget_version_cache: | ||
| return _nuget_version_cache[package_name] | ||
|
|
||
| url = f"https://api.nuget.org/v3-flatcontainer/{package_name.lower()}/index.json" | ||
| try: | ||
| with urllib.request.urlopen(url, timeout=15) as response: | ||
| data = json.loads(response.read()) | ||
| versions = data.get("versions", []) | ||
| # Stable versions have no hyphen (no pre-release suffix) | ||
| stable = [v for v in versions if "-" not in v] | ||
| result = stable[-1] if stable else (versions[-1] if versions else None) | ||
| except Exception as exc: | ||
| print(f" Warning: Could not fetch latest version for {package_name}: {exc}") | ||
| result = None | ||
|
|
||
| _nuget_version_cache[package_name] = result | ||
| return result | ||
|
|
||
|
|
||
| def main(): | ||
| if not TRIGGER_SOURCE or not TRIGGER_VERSION: | ||
| print( | ||
|
|
@@ -70,7 +109,7 @@ def main(): | |
| target_version = TRIGGER_VERSION.lstrip("v") | ||
|
|
||
| print(f"Trigger: {TRIGGER_SOURCE} @ {target_version}") | ||
| print(f"Only updating packages from: {TRIGGER_SOURCE}") | ||
| print(f"Triggered packages set to {target_version}; other Codebelt packages fetched from NuGet.") | ||
| print() | ||
|
Comment on lines
109
to
113
|
||
|
|
||
| try: | ||
|
|
@@ -87,16 +126,24 @@ def replace_version(m: re.Match) -> str: | |
| pkg = m.group(1) | ||
| current = m.group(2) | ||
|
|
||
| if not is_triggered_package(pkg): | ||
| skipped_third_party.append(f" {pkg} (skipped - not from {TRIGGER_SOURCE})") | ||
| if is_triggered_package(pkg): | ||
| if target_version != current: | ||
| changes.append(f" {pkg}: {current} → {target_version}") | ||
| return m.group(0).replace( | ||
| f'Version="{current}"', f'Version="{target_version}"' | ||
| ) | ||
| return m.group(0) | ||
|
|
||
| if target_version != current: | ||
| changes.append(f" {pkg}: {current} → {target_version}") | ||
| return m.group(0).replace( | ||
| f'Version="{current}"', f'Version="{target_version}"' | ||
| ) | ||
| if is_codebelt_package(pkg): | ||
| latest = get_latest_nuget_version(pkg) | ||
| if latest and latest != current: | ||
| changes.append(f" {pkg}: {current} → {latest} (latest from NuGet)") | ||
| return m.group(0).replace( | ||
| f'Version="{current}"', f'Version="{latest}"' | ||
| ) | ||
| return m.group(0) | ||
|
|
||
| skipped_third_party.append(f" {pkg} (skipped - not a Codebelt package)") | ||
| return m.group(0) | ||
|
|
||
| # Match PackageVersion elements (handles multiline) | ||
|
|
@@ -111,10 +158,10 @@ def replace_version(m: re.Match) -> str: | |
|
|
||
| # Show results | ||
| if changes: | ||
| print(f"Updated {len(changes)} package(s) from {TRIGGER_SOURCE}:") | ||
| print(f"Updated {len(changes)} package(s):") | ||
| print("\n".join(changes)) | ||
| else: | ||
| print(f"No packages from {TRIGGER_SOURCE} needed updating.") | ||
| print("No Codebelt packages needed updating.") | ||
|
|
||
| if skipped_third_party: | ||
| print() | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do not fall back to prerelease when “latest stable” is required.
Current logic can select a prerelease when no stable version exists, which conflicts with the function contract and PR objective.
Suggested fix
🤖 Prompt for AI Agents