fix: make readme sync deterministic in CI
This commit is contained in:
@@ -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)
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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`
|
||||
|
||||
Reference in New Issue
Block a user