feat(repo): Add GitHub About sync command

Expose an explicit sync:github-about workflow that updates the remote GitHub About description, homepage, and topics from the repository metadata source of truth.

Add regression coverage for the generated gh commands and document the new maintainer path in the changelog and walkthrough.
This commit is contained in:
sickn33
2026-03-21 10:31:07 +01:00
parent 37f46505ff
commit 4a8e52276a
5 changed files with 116 additions and 1 deletions

View File

@@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Realigned README, package metadata, user docs, and GitHub About guidance to the current `1,304+` catalog state and `v8.4.0` release copy.
- Automated metadata propagation for curated docs and package copy so `npm run chain` now keeps README, package description, and the main count-sensitive user/maintainer docs aligned when the skill catalog changes.
- Added an explicit `sync:github-about` automation path so GitHub About description, homepage, and topics can be refreshed from the same metadata source instead of being updated manually.
## [8.4.0] - 2026-03-20 - "Discovery, Metadata, and Release Hardening"

View File

@@ -16,6 +16,7 @@
"index": "node tools/scripts/run-python.js tools/scripts/generate_index.py",
"readme": "node tools/scripts/run-python.js tools/scripts/update_readme.py",
"sync:metadata": "node tools/scripts/run-python.js tools/scripts/sync_repo_metadata.py",
"sync:github-about": "node tools/scripts/run-python.js tools/scripts/sync_repo_metadata.py --apply-github-about",
"chain": "npm run validate && npm run index && npm run sync:metadata",
"sync:all": "npm run chain",
"catalog": "node tools/scripts/build-catalog.js",

View File

@@ -3,6 +3,7 @@ import argparse
import json
import os
import re
import subprocess
import sys
from pathlib import Path
@@ -10,6 +11,29 @@ from update_readme import configure_utf8_output, find_repo_root, load_metadata,
ABOUT_DESCRIPTION_RE = re.compile(r'"description"\s*:\s*"([^"]*)"')
GITHUB_HOMEPAGE_URL = "https://sickn33.github.io/antigravity-awesome-skills/"
RECOMMENDED_TOPICS = [
"agentic-skills",
"agent-skills",
"ai-agents",
"ai-agent-skills",
"awesome-list",
"awesome-lists",
"antigravity",
"antigravity-skills",
"autonomous-coding",
"claude-code",
"claude-code-skills",
"codex-cli",
"codex-skills",
"cursor-skills",
"developer-tools",
"gemini-cli",
"gemini-skills",
"mcp",
"ai-workflows",
"skill-library",
]
README_TAGLINE_RE = re.compile(
r"^> \*\*Installable GitHub library of \d[\d,]*\+ agentic skills for Claude Code, Cursor, Codex CLI, Gemini CLI, Antigravity, and other AI coding assistants\.\*\*$",
re.MULTILINE,
@@ -44,6 +68,55 @@ def build_about_description(metadata: dict) -> str:
)
def build_about_topics() -> list[str]:
return list(RECOMMENDED_TOPICS)
def run_cli_command(args: list[str], dry_run: bool = False) -> None:
if dry_run:
print(f"[dry-run] {' '.join(args)}")
return
subprocess.run(args, check=True)
def sync_github_about(
metadata: dict,
dry_run: bool,
runner=run_cli_command,
) -> None:
description = build_about_description(metadata)
repo = metadata["repo"]
runner(
[
"gh",
"repo",
"edit",
repo,
"--description",
description,
"--homepage",
GITHUB_HOMEPAGE_URL,
],
dry_run=dry_run,
)
topic_command = [
"gh",
"api",
f"repos/{repo}/topics",
"--method",
"PUT",
]
for topic in build_about_topics():
topic_command.extend(["-f", f"names[]={topic}"])
runner(topic_command, dry_run=dry_run)
if not dry_run:
print(f"✅ Synced GitHub About settings for {repo}")
def replace_if_present(content: str, pattern: re.Pattern[str], replacement: str) -> tuple[str, bool]:
updated_content, count = pattern.subn(replacement, content, count=1)
return updated_content, count > 0
@@ -271,7 +344,8 @@ def print_manual_github_about(metadata: dict) -> None:
description = build_about_description(metadata)
print("\nManual GitHub repo settings update:")
print(f"- About description: {description}")
print("- Suggested topics: claude-code, cursor, gemini-cli, codex-cli, github-copilot, antigravity")
print(f"- Homepage: {GITHUB_HOMEPAGE_URL}")
print(f"- Suggested topics: {', '.join(build_about_topics())}")
def parse_args() -> argparse.Namespace:
@@ -284,6 +358,11 @@ def parse_args() -> argparse.Namespace:
action="store_true",
help="Refresh live star count and updated_at when syncing README metadata.",
)
parser.add_argument(
"--apply-github-about",
action="store_true",
help="Apply the GitHub About description, homepage, and topics to the remote repository via gh CLI.",
)
return parser.parse_args()
@@ -300,6 +379,8 @@ def main() -> int:
)
package_updated = update_package_description(base_dir, metadata, args.dry_run)
docs_updated = sync_curated_docs(base_dir, metadata, args.dry_run)
if args.apply_github_about:
sync_github_about(metadata, dry_run=args.dry_run)
print_manual_github_about(readme_metadata)
if args.dry_run and not package_updated:

View File

@@ -120,6 +120,37 @@ If you want a faster answer than "browse all 1,273+ skills", start with a tool-s
self.assertIn("1,304+ agentic skills", description)
self.assertIn("installer CLI", description)
def test_sync_github_about_builds_expected_commands(self):
calls = []
def fake_runner(args, dry_run=False):
calls.append((args, dry_run))
sync_repo_metadata.sync_github_about(
{
"repo": "sickn33/antigravity-awesome-skills",
"total_skills_label": "1,304+",
},
dry_run=True,
runner=fake_runner,
)
self.assertEqual(len(calls), 2)
repo_edit_args, repo_edit_dry_run = calls[0]
topics_args, topics_dry_run = calls[1]
self.assertTrue(repo_edit_dry_run)
self.assertTrue(topics_dry_run)
self.assertEqual(repo_edit_args[:4], ["gh", "repo", "edit", "sickn33/antigravity-awesome-skills"])
self.assertIn("--description", repo_edit_args)
self.assertIn("--homepage", repo_edit_args)
self.assertIn("https://sickn33.github.io/antigravity-awesome-skills/", repo_edit_args)
self.assertEqual(topics_args[:4], ["gh", "api", "repos/sickn33/antigravity-awesome-skills/topics", "--method"])
self.assertIn("PUT", topics_args)
self.assertIn("names[]=claude-code", topics_args)
self.assertIn("names[]=skill-library", topics_args)
if __name__ == "__main__":
unittest.main()

View File

@@ -126,3 +126,4 @@
- `docs/maintainers/skills-update-guide.md`
- Updated the changelog `Unreleased` section so the post-`v8.4.0` main branch state documents both the imported skill families and the docs/About realignment.
- Automated the recurring docs metadata maintenance by extending `tools/scripts/sync_repo_metadata.py`, wiring it into `npm run chain`, and adding a regression test so future skill-count/version updates propagate through the curated docs surface without manual patching.
- Added a remote GitHub About sync path (`npm run sync:github-about`) backed by `gh repo edit` + `gh api .../topics` so the public repository metadata can be refreshed from the same source of truth on demand.