-
Notifications
You must be signed in to change notification settings - Fork 1
Automation/bug fixing #55
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,116 +1,133 @@ | ||||||||||||||||
| #!/usr/bin/env python3 | ||||||||||||||||
| """ | ||||||||||||||||
| Bumps PackageVersion entries in Directory.Packages.props. | ||||||||||||||||
| - For packages published by the triggering source repo: uses the known TRIGGER_VERSION. | ||||||||||||||||
| - For all other packages: queries NuGet API for latest stable version. | ||||||||||||||||
| - Preserves all XML formatting via regex (no ElementTree rewriting). | ||||||||||||||||
| Simplified package bumping for Codebelt service updates (Option B). | ||||||||||||||||
|
|
||||||||||||||||
| Only updates packages published by the triggering source repo. | ||||||||||||||||
| 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 | ||||||||||||||||
| - Microsoft.Extensions.Hosting: 9.0.13 → UNCHANGED (not a Codebelt package) | ||||||||||||||||
| - BenchmarkDotNet: 0.15.8 → UNCHANGED (not a Codebelt package) | ||||||||||||||||
| """ | ||||||||||||||||
|
|
||||||||||||||||
| import re, os, urllib.request, json, sys | ||||||||||||||||
| import re | ||||||||||||||||
| import os | ||||||||||||||||
| import sys | ||||||||||||||||
| from typing import Dict, List | ||||||||||||||||
|
|
||||||||||||||||
| TRIGGER_SOURCE = os.environ.get("TRIGGER_SOURCE", "") | ||||||||||||||||
| TRIGGER_VERSION = os.environ.get("TRIGGER_VERSION", "") | ||||||||||||||||
|
|
||||||||||||||||
| # Maps source repo name → NuGet package ID prefixes published by that repo. | ||||||||||||||||
| # Keep this aligned with what each repo actually publishes. | ||||||||||||||||
| # Map of source repos to their package ID prefixes | ||||||||||||||||
| SOURCE_PACKAGE_MAP: Dict[str, List[str]] = { | ||||||||||||||||
| "cuemon": [ | ||||||||||||||||
| "Cuemon.", | ||||||||||||||||
| ], | ||||||||||||||||
| "xunit": [ | ||||||||||||||||
| "Codebelt.Extensions.Xunit", | ||||||||||||||||
| ], | ||||||||||||||||
| "benchmarkdotnet": [ | ||||||||||||||||
| "Codebelt.Extensions.BenchmarkDotNet", | ||||||||||||||||
| ], | ||||||||||||||||
| "bootstrapper": [ | ||||||||||||||||
| "Codebelt.Bootstrapper", | ||||||||||||||||
| ], | ||||||||||||||||
| "cuemon": ["Cuemon."], | ||||||||||||||||
| "xunit": ["Codebelt.Extensions.Xunit"], | ||||||||||||||||
| "benchmarkdotnet": ["Codebelt.Extensions.BenchmarkDotNet"], | ||||||||||||||||
| "bootstrapper": ["Codebelt.Bootstrapper"], | ||||||||||||||||
| "newtonsoft-json": [ | ||||||||||||||||
| "Codebelt.Extensions.Newtonsoft.Json", | ||||||||||||||||
| "Codebelt.Extensions.AspNetCore.Mvc.Formatters.Newtonsoft", | ||||||||||||||||
| ], | ||||||||||||||||
| "aws-signature-v4": [ | ||||||||||||||||
| "Codebelt.Extensions.AspNetCore.Authentication.AwsSignature", | ||||||||||||||||
| ], | ||||||||||||||||
| "unitify": [ | ||||||||||||||||
| "Codebelt.Unitify", | ||||||||||||||||
| ], | ||||||||||||||||
| "aws-signature-v4": ["Codebelt.Extensions.AspNetCore.Authentication.AwsSignature"], | ||||||||||||||||
| "unitify": ["Codebelt.Unitify"], | ||||||||||||||||
| "yamldotnet": [ | ||||||||||||||||
| "Codebelt.Extensions.YamlDotNet", | ||||||||||||||||
| "Codebelt.Extensions.AspNetCore.Mvc.Formatters.Text.Yaml", | ||||||||||||||||
| ], | ||||||||||||||||
| "globalization": [ | ||||||||||||||||
| "Codebelt.Extensions.Globalization", | ||||||||||||||||
| ], | ||||||||||||||||
| "asp-versioning": [ | ||||||||||||||||
| "Codebelt.Extensions.Asp.Versioning", | ||||||||||||||||
| ], | ||||||||||||||||
| "swashbuckle-aspnetcore": [ | ||||||||||||||||
| "Codebelt.Extensions.Swashbuckle", | ||||||||||||||||
| ], | ||||||||||||||||
| "savvyio": [ | ||||||||||||||||
| "Savvyio.", | ||||||||||||||||
| ], | ||||||||||||||||
| "globalization": ["Codebelt.Extensions.Globalization"], | ||||||||||||||||
| "asp-versioning": ["Codebelt.Extensions.Asp.Versioning"], | ||||||||||||||||
| "swashbuckle-aspnetcore": ["Codebelt.Extensions.Swashbuckle"], | ||||||||||||||||
| "savvyio": ["Savvyio."], | ||||||||||||||||
| "shared-kernel": [], | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
|
|
||||||||||||||||
| def nuget_latest(pkg: str) -> str | None: | ||||||||||||||||
| """Query NuGet flat container API for the latest stable version.""" | ||||||||||||||||
| try: | ||||||||||||||||
| url = f"https://api.nuget.org/v3-flatcontainer/{pkg.lower()}/index.json" | ||||||||||||||||
| with urllib.request.urlopen(url, timeout=15) as r: | ||||||||||||||||
| versions = json.loads(r.read())["versions"] | ||||||||||||||||
| stable = [v for v in versions if not re.search(r"-", v)] | ||||||||||||||||
| return stable[-1] if stable else None | ||||||||||||||||
| except Exception as e: | ||||||||||||||||
| print(f" SKIP {pkg}: {e}", file=sys.stderr) | ||||||||||||||||
| return None | ||||||||||||||||
|
|
||||||||||||||||
|
|
||||||||||||||||
| def triggered_version(pkg: str) -> str | None: | ||||||||||||||||
| """Return TRIGGER_VERSION if pkg is published by the triggering source repo.""" | ||||||||||||||||
| if not TRIGGER_VERSION or not TRIGGER_SOURCE: | ||||||||||||||||
| return None | ||||||||||||||||
| def is_triggered_package(package_name: str) -> bool: | ||||||||||||||||
| """Check if package is published by the triggering source repo.""" | ||||||||||||||||
| if not TRIGGER_SOURCE: | ||||||||||||||||
| return False | ||||||||||||||||
| prefixes = SOURCE_PACKAGE_MAP.get(TRIGGER_SOURCE, []) | ||||||||||||||||
| if any(pkg.startswith(p) for p in prefixes): | ||||||||||||||||
| return TRIGGER_VERSION | ||||||||||||||||
| return None | ||||||||||||||||
|
|
||||||||||||||||
|
|
||||||||||||||||
| with open("Directory.Packages.props", "r") as f: | ||||||||||||||||
| content = f.read() | ||||||||||||||||
| return any(package_name.startswith(prefix) for prefix in prefixes) | ||||||||||||||||
|
|
||||||||||||||||
| changes = [] | ||||||||||||||||
|
|
||||||||||||||||
| def main(): | ||||||||||||||||
| if not TRIGGER_SOURCE or not TRIGGER_VERSION: | ||||||||||||||||
| print( | ||||||||||||||||
| "Error: TRIGGER_SOURCE and TRIGGER_VERSION environment variables required" | ||||||||||||||||
| ) | ||||||||||||||||
| print(f" TRIGGER_SOURCE={TRIGGER_SOURCE}") | ||||||||||||||||
| print(f" TRIGGER_VERSION={TRIGGER_VERSION}") | ||||||||||||||||
| sys.exit(1) | ||||||||||||||||
|
|
||||||||||||||||
| def replace_version(m: re.Match) -> str: | ||||||||||||||||
| pkg = m.group(1) | ||||||||||||||||
| current = m.group(2) | ||||||||||||||||
| # Strip 'v' prefix if present in version | ||||||||||||||||
| target_version = TRIGGER_VERSION.lstrip("v") | ||||||||||||||||
|
|
||||||||||||||||
|
||||||||||||||||
| # Validate that the target version looks like a semantic version (e.g. 1.2.3 or 1.2.3-beta) | |
| if not re.match(r"^\d+\.\d+\.\d+(-[\w.]+)?$", target_version): | |
| print(f"Error: Invalid TRIGGER_VERSION format: {TRIGGER_VERSION!r}") | |
| print(" Expected a semantic version like '1.2.3' or '1.2.3-beta'.") | |
| sys.exit(1) |
Copilot
AI
Feb 18, 2026
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.
The regex pattern correctly uses re.DOTALL to match multiline PackageVersion elements, but it will match ALL PackageVersion elements regardless of ItemGroup conditions (e.g., those within Condition="$(TargetFramework.StartsWith('net9'))" blocks). This means if a Cuemon package appears in multiple conditional ItemGroups with different versions for different target frameworks, they will ALL be updated to the same TRIGGER_VERSION. This may be intentional per the script's documentation ("Does NOT parse TFM conditions"), but could lead to issues if different TFMs should have different package versions. Consider documenting this behavior more explicitly or adding a warning if conditional ItemGroups are detected.
Copilot
AI
Feb 18, 2026
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.
The return statement is redundant since both branches return 0. This could be simplified to just return 0.
| return 0 if changes else 0 # Return 0 even if no changes (not an error) | |
| return 0 # Return 0 even if no changes (not an error) |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -93,33 +93,9 @@ jobs: | |||||
| env: | ||||||
| NEW_VERSION: ${{ steps.newver.outputs.new }} | ||||||
|
|
||||||
| - name: Bump test runner Docker tag | ||||||
| run: | | ||||||
| [ -f testenvironments.json ] || exit 0 | ||||||
| LATEST=$(curl -sf "https://hub.docker.com/v2/repositories/codebeltnet/ubuntu-testrunner/tags/?page_size=10&ordering=last_updated" \ | ||||||
| | python3 -c " | ||||||
| import sys, json | ||||||
| tags = [t['name'] for t in json.load(sys.stdin)['results'] if 'latest' not in t['name']] | ||||||
| print(tags[0] if tags else '') | ||||||
| ") | ||||||
| [ -n "$LATEST" ] && \ | ||||||
| sed -i "s|codebeltnet/ubuntu-testrunner:[^\"]*|codebeltnet/ubuntu-testrunner:${LATEST}|g" \ | ||||||
| testenvironments.json && echo "Bumped to $LATEST" | ||||||
|
|
||||||
| - name: Bump NGINX Alpine version | ||||||
| run: | | ||||||
| [ -f .docfx/Dockerfile.docfx ] || exit 0 | ||||||
| LATEST=$(curl -sf "https://hub.docker.com/v2/repositories/library/nginx/tags/?page_size=50&name=alpine&ordering=last_updated" \ | ||||||
| | python3 -c " | ||||||
| import sys, json, re | ||||||
| data = json.load(sys.stdin) | ||||||
| tags = [t['name'] for t in data['results'] if re.match(r'^\d+\.\d+\.\d+-alpine$', t['name'])] | ||||||
| if tags: | ||||||
| print(sorted(tags, key=lambda v: list(map(int, v.replace('-alpine','').split('.'))))[-1]) | ||||||
| ") | ||||||
| [ -n "$LATEST" ] && \ | ||||||
| sed -i "s|NGINX_VERSION=.*|NGINX_VERSION=${LATEST}|g" \ | ||||||
| .docfx/Dockerfile.docfx && echo "Bumped NGINX to $LATEST" | ||||||
| # Note: Docker image bumps removed in favor of manual updates | ||||||
| # The automated selection was picking wrong variants (e.g., mono-* instead of standard) | ||||||
| # TODO: Move to hosted service for smarter image selection | ||||||
|
||||||
| # TODO: Move to hosted service for smarter image selection | |
| # TODO: Move to a hosted service that selects Docker images by architecture, excludes mono-* and other unwanted variants, and applies maintainer-defined filter rules for tag selection. |
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.
When TRIGGER_SOURCE is provided but doesn't exist in SOURCE_PACKAGE_MAP, the function
is_triggered_packagewill return False for all packages (sinceprefixeswill be an empty list from.get(TRIGGER_SOURCE, [])). This means the script will skip all packages and produce no changes. While this is safe, it would be better to add validation at the start ofmain()to check if TRIGGER_SOURCE exists in SOURCE_PACKAGE_MAP and exit with a clear error message if not. This would help catch configuration errors early.