fix: make readme sync deterministic in CI

This commit is contained in:
sck_0
2026-03-13 09:24:36 +01:00
parent 663c4464a8
commit 608ef0ac9a
3 changed files with 73 additions and 9 deletions

View File

@@ -52,18 +52,25 @@ def parse_args() -> argparse.Namespace:
description="Synchronize repository metadata across README and package.json."
)
parser.add_argument("--dry-run", action="store_true", help="Preview updates without writing files.")
parser.add_argument(
"--refresh-volatile",
action="store_true",
help="Refresh live star count and updated_at when syncing README metadata.",
)
return parser.parse_args()
def main() -> int:
args = parse_args()
base_dir = find_repo_root(os.path.dirname(__file__))
metadata = load_metadata(base_dir)
metadata = load_metadata(base_dir, refresh_volatile=args.refresh_volatile)
print("Repository metadata")
print(json.dumps(metadata, indent=2))
readme_metadata = update_readme(dry_run=args.dry_run)
readme_metadata = update_readme(
dry_run=args.dry_run, refresh_volatile=args.refresh_volatile
)
package_updated = update_package_description(base_dir, metadata, args.dry_run)
print_manual_github_about(readme_metadata)

View File

@@ -11,6 +11,10 @@ from datetime import datetime, timezone
GITHUB_REPO = "sickn33/antigravity-awesome-skills"
SYNC_COMMENT_RE = re.compile(r"<!-- registry-sync: .*? -->")
SYNC_COMMENT_FIELDS_RE = re.compile(
r"<!-- registry-sync: version=(?P<version>[^;]+); skills=(?P<skills>\d+); "
r"stars=(?P<stars>\d+); updated_at=(?P<updated_at>[^ ]+) -->"
)
def configure_utf8_output() -> None:
@@ -91,7 +95,22 @@ def fetch_star_count(repo: str) -> int | None:
return int(stars) if isinstance(stars, int) else None
def load_metadata(base_dir: str, repo: str = GITHUB_REPO) -> dict:
def parse_existing_sync_metadata(current_readme: str) -> dict[str, str | int] | None:
match = SYNC_COMMENT_FIELDS_RE.search(current_readme)
if not match:
return None
return {
"version": match.group("version"),
"skills": int(match.group("skills")),
"stars": int(match.group("stars")),
"updated_at": match.group("updated_at"),
}
def load_metadata(
base_dir: str, repo: str = GITHUB_REPO, refresh_volatile: bool = False
) -> dict:
readme_path = os.path.join(base_dir, "README.md")
package_path = os.path.join(base_dir, "package.json")
index_path = os.path.join(base_dir, "skills_index.json")
@@ -105,6 +124,7 @@ def load_metadata(base_dir: str, repo: str = GITHUB_REPO) -> dict:
with open(readme_path, "r", encoding="utf-8") as file:
current_readme = file.read()
existing_sync_metadata = parse_existing_sync_metadata(current_readme)
current_star_match = re.search(r"%20([\d%2C\+]+)%20Stars", current_readme)
current_stars = None
if current_star_match:
@@ -113,8 +133,29 @@ def load_metadata(base_dir: str, repo: str = GITHUB_REPO) -> dict:
if compact.isdigit():
current_stars = int(compact)
live_stars = fetch_star_count(repo)
total_stars = live_stars if live_stars is not None else current_stars or 0
existing_stars = None
existing_updated_at = None
if existing_sync_metadata:
stars = existing_sync_metadata.get("stars")
updated_at = existing_sync_metadata.get("updated_at")
if isinstance(stars, int):
existing_stars = stars
if isinstance(updated_at, str):
existing_updated_at = updated_at
live_stars = fetch_star_count(repo) if refresh_volatile else None
total_stars = (
live_stars
if live_stars is not None
else existing_stars
if existing_stars is not None
else current_stars or 0
)
updated_at = (
datetime.now(timezone.utc).replace(microsecond=0).isoformat()
if refresh_volatile or existing_updated_at is None
else existing_updated_at
)
return {
"repo": repo,
@@ -125,8 +166,9 @@ def load_metadata(base_dir: str, repo: str = GITHUB_REPO) -> dict:
"star_badge_count": format_star_badge_count(total_stars),
"star_milestone": format_star_milestone(total_stars),
"star_celebration": format_star_celebration(total_stars),
"updated_at": datetime.now(timezone.utc).replace(microsecond=0).isoformat(),
"updated_at": updated_at,
"used_live_star_count": live_stars is not None,
"refreshed_volatile": refresh_volatile,
}
@@ -221,10 +263,10 @@ def apply_metadata(content: str, metadata: dict) -> str:
return f"{sync_comment}\n{content.lstrip()}"
def update_readme(dry_run: bool = False) -> dict:
def update_readme(dry_run: bool = False, refresh_volatile: bool = False) -> dict:
base_dir = find_repo_root(os.path.dirname(__file__))
readme_path = os.path.join(base_dir, "README.md")
metadata = load_metadata(base_dir)
metadata = load_metadata(base_dir, refresh_volatile=refresh_volatile)
print(f"📖 Reading README from: {readme_path}")
print(f"🔢 Total skills found: {metadata['total_skills']}")
@@ -252,10 +294,15 @@ def update_readme(dry_run: bool = False) -> dict:
def parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser(description="Sync generated metadata into README.md.")
parser.add_argument("--dry-run", action="store_true", help="Compute metadata without writing files.")
parser.add_argument(
"--refresh-volatile",
action="store_true",
help="Refresh live star count and updated_at instead of preserving existing values.",
)
return parser.parse_args()
if __name__ == "__main__":
configure_utf8_output()
args = parse_args()
update_readme(dry_run=args.dry_run)
update_readme(dry_run=args.dry_run, refresh_volatile=args.refresh_volatile)

View File

@@ -12,3 +12,13 @@
- `npm run chain`
- `npm run catalog`
- Final release prep, issue closure comments, and verification were completed on `main`.
# Maintenance Walkthrough - 2026-03-13
- Fixed `tools/scripts/update_readme.py` so normal `npm run readme` runs preserve the existing `registry-sync` star/timestamp values instead of rewriting them on every execution, which was causing non-deterministic PR drift failures in CI.
- Updated `tools/scripts/sync_repo_metadata.py` to expose the same explicit `--refresh-volatile` behavior for live star/timestamp refreshes, keeping release/metadata refresh flows available without destabilizing contributor PR checks.
- Verified the fix with:
- `python3 tools/scripts/update_readme.py --dry-run`
- `python3 tools/scripts/sync_repo_metadata.py --dry-run`
- `npm run readme`
- `npm run validate:references`