Sync README with actual repository state and add automation workflow - #20
Conversation
Co-authored-by: tuanductran <69758022+tuanductran@users.noreply.github.com>
|
@copilot Act as a DevOps engineer for this repository. I want to automate the maintenance of README.md. Your task is to: Create a GitHub Action workflow named auto-update-readme.yml in .github/workflows/. Logic: Whenever a new .md file is added to any subdirectory under skills/ on the main branch, this action should: Scan all subdirectories in skills/. Generate an organized list of all rules, categorized by their skill group (API, CLI, UI, Integrations). Find the markers and in README.md and inject the updated list between them. Automatically commit and push the changes back to the repository using stefanzweifel/git-auto-commit-action@v7. Requirements: Use a simple Python 3 script within the workflow to perform the directory parsing and file writing. Ensure the links created in README.md are relative paths to the rule files. Follow the case-police rules from CLAUDE.md (e.g., use NextDNS, CLI, API). |
Co-authored-by: tuanductran <69758022+tuanductran@users.noreply.github.com>
Created Implementation details:
Commit: 445d582 |
Co-authored-by: tuanductran <69758022+tuanductran@users.noreply.github.com>
|
@copilot pls use stefanzweifel/git-auto-commit-action@v7 |
There was a problem hiding this comment.
Pull request overview
Updates repository documentation to reflect the current set of skills/rules and introduces an automation workflow intended to keep the README’s “Available Skills” section in sync with future rule changes.
Changes:
- Updated README skill/rule counts and expanded documentation to include an “integrations” skill plus new examples/resources/contributing guidance.
- Added “integrations” coverage (skills overview + quick examples) and reorganized resources into official vs community links.
- Added a GitHub Actions workflow to regenerate the README skills section on rule/SKILL.md changes and auto-commit the result.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
| README.md | Updates counts, adds integrations docs/examples, adds contributing section, reorganizes resources. |
| .github/workflows/auto-update-readme.yml | Adds automation to regenerate the README “Available Skills” section and commit changes. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| for rule_file in sorted(rules_dir.glob('*.md')): | ||
| rule_meta = parse_yaml_frontmatter(rule_file) | ||
| if rule_meta: | ||
| rules.append({ | ||
| 'file': rule_file.name, | ||
| 'title': rule_meta.get('title', rule_file.stem), | ||
| 'type': rule_meta.get('type', 'capability'), | ||
| 'impact': rule_meta.get('impact', 'MEDIUM'), | ||
| 'tags': rule_meta.get('tags', ''), | ||
| 'path': str(rule_file.relative_to(Path.cwd())) | ||
| }) | ||
|
|
There was a problem hiding this comment.
Rules are gathered via sorted(rules_dir.glob('*.md')), so the “Examples” list is effectively based on filename sort order. This will cause unstable/less-meaningful example ordering (and README churn) compared to the curated ordering in each SKILL.md. Prefer deriving ordering (and maybe examples) from the SKILL.md rule tables, or an explicit ordering field in frontmatter.
| for rule_file in sorted(rules_dir.glob('*.md')): | |
| rule_meta = parse_yaml_frontmatter(rule_file) | |
| if rule_meta: | |
| rules.append({ | |
| 'file': rule_file.name, | |
| 'title': rule_meta.get('title', rule_file.stem), | |
| 'type': rule_meta.get('type', 'capability'), | |
| 'impact': rule_meta.get('impact', 'MEDIUM'), | |
| 'tags': rule_meta.get('tags', ''), | |
| 'path': str(rule_file.relative_to(Path.cwd())) | |
| }) | |
| for rule_file in rules_dir.glob('*.md'): | |
| rule_meta = parse_yaml_frontmatter(rule_file) | |
| if rule_meta: | |
| # Optional explicit ordering from rule frontmatter (e.g., "order: 1") | |
| raw_order = rule_meta.get('order') | |
| order_value = None | |
| if raw_order is not None: | |
| try: | |
| order_value = int(str(raw_order).strip()) | |
| except (TypeError, ValueError): | |
| order_value = None | |
| rules.append({ | |
| 'file': rule_file.name, | |
| 'title': rule_meta.get('title', rule_file.stem), | |
| 'type': rule_meta.get('type', 'capability'), | |
| 'impact': rule_meta.get('impact', 'MEDIUM'), | |
| 'tags': rule_meta.get('tags', ''), | |
| 'path': str(rule_file.relative_to(Path.cwd())), | |
| 'order': order_value, | |
| }) | |
| # Sort rules: first by explicit numeric 'order' if present, then by title for stability | |
| rules.sort(key=lambda r: ( | |
| r['order'] is None, | |
| r['order'] if r['order'] is not None else 0, | |
| r['title'], | |
| )) | |
| with open(skill_md, 'r', encoding='utf-8') as f: | ||
| skill_content = f.read() | ||
|
|
||
| # Parse skill frontmatter |
There was a problem hiding this comment.
skill_content is read from SKILL.md but never used (same for skill_desc). This extra read makes the script harder to follow; either remove it or use it to drive README content (e.g., description/order from SKILL.md).
| with open(skill_md, 'r', encoding='utf-8') as f: | |
| skill_content = f.read() | |
| # Parse skill frontmatter | |
| # Parse skill frontmatter directly from SKILL.md |
| display_name = skill_display_names.get(skill_name, skill_name) | ||
| total_count = len(rules) | ||
|
|
||
| output = f"### {skill_name} ({total_count} rules)\n\n" |
There was a problem hiding this comment.
display_name is computed from skill_display_names but the output header uses skill_name instead, so display_name is dead code. Remove it, or use display_name in the generated markdown if the intent is human-friendly titles.
| output = f"### {skill_name} ({total_count} rules)\n\n" | |
| output = f"### {display_name} ({total_count} rules)\n\n" |
| jobs: | ||
| update-readme: | ||
| runs-on: ubuntu-latest | ||
|
|
There was a problem hiding this comment.
The workflow commits back to main, but it doesn’t declare permissions: contents: write. If the repo/org default token permissions are read-only, the auto-commit step will fail. Add an explicit permissions block (workflow- or job-level) granting contents write (and only what’s needed).
| # Get all skill directories | ||
| skill_order = ['nextdns-api', 'nextdns-cli', 'nextdns-ui', 'integrations'] | ||
| skills_data = {} | ||
|
|
||
| for skill_dir in sorted(skills_dir.iterdir()): |
There was a problem hiding this comment.
skill_order hardcodes the set/order of skills rendered into README. This means adding a new skill directory won’t show up in the generated section unless this list is updated, which undermines the goal of automated README maintenance. Consider generating order dynamically (e.g., known skills first, then append any other skill dirs alphabetically) or deriving order from directory structure/metadata.
README.md reflected outdated rule counts and was missing the integrations skill entirely. Added GitHub Action workflow to automate future README maintenance.
Changes
.github/workflows/auto-update-readme.ymlthat automatically updates README.md when rule files change on main branchAutomation Workflow
The new GitHub Action workflow:
skills/**/rules/*.mdorskills/**/SKILL.mdfiles on main branchVerification
All counts verified against actual
skills/*/rules/*.mdfiles (44 total rules across 4 skills). Workflow YAML syntax validated and Python script tested locally.Original prompt
💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.