# Assign sequential numbers to prd-new-*.md files on merge to main. # # When a PR merges to main and includes prd-new-*.md files this workflow: # 1. Finds the next available NNNN number by scanning existing PRDs. # 2. Renames each prd-new-*.md to NNNN-.md. # 3. Updates the title header (# PRD prd-new: → # PRD NNNN:). # 4. Flips Status: Draft → Active when the merge commit also touched # files outside docs/prds/ (i.e. the implementation shipped together # with the PRD). # 5. Commits the renaming back to main. # # No-op if the push contained no prd-new-*.md files. name: prd-number on: push: branches: - main paths: - 'docs/prds/prd-new-*.md' jobs: assign-numbers: runs-on: ubuntu-latest permissions: contents: write steps: - name: Checkout uses: actions/checkout@v4 with: fetch-depth: 2 token: ${{ secrets.GITHUB_TOKEN }} - name: Set up Python uses: actions/setup-python@v5 with: python-version: "3.12" - name: Configure git run: | git config user.name "github-actions[bot]" git config user.email "github-actions[bot]@users.noreply.github.com" - name: Assign PRD numbers run: | python3 - <<'EOF' import os import re import subprocess import sys from pathlib import Path prds_dir = Path("docs/prds") # Files added in the latest commit (HEAD vs HEAD~1). result = subprocess.run( ["git", "diff", "--name-only", "--diff-filter=A", "HEAD~1", "HEAD"], capture_output=True, text=True, check=True, ) added = [Path(p) for p in result.stdout.splitlines()] new_prds = [p for p in added if p.parent == prds_dir and re.match(r"prd-new-.+\.md$", p.name)] if not new_prds: print("No prd-new-*.md files added in this commit — nothing to do.") sys.exit(0) # Determine whether non-PRD files were also changed (for Status flip). all_changed = subprocess.run( ["git", "diff", "--name-only", "HEAD~1", "HEAD"], capture_output=True, text=True, check=True, ).stdout.splitlines() non_prd_changed = any( not f.startswith("docs/prds/") for f in all_changed ) # Find next available number. existing = sorted( int(m.group(1)) for p in prds_dir.glob("*.md") if (m := re.match(r"^(\d{4})-", p.name)) ) next_num = (max(existing) + 1) if existing else 1 for prd_path in sorted(new_prds): slug = re.sub(r"^prd-new-", "", prd_path.stem) new_name = f"{next_num:04d}-{slug}.md" new_path = prds_dir / new_name print(f" {prd_path.name} → {new_name}") content = prd_path.read_text() # Update title header. content = re.sub( r"^(#\s+PRD\s+)prd-new(:)", rf"\g<1>{next_num:04d}\2", content, count=1, flags=re.MULTILINE, ) # Conditionally flip Status. if non_prd_changed: content = re.sub( r"(\*\*Status:\*\*\s*)Draft", r"\g<1>Active", content, count=1, ) new_path.write_text(content) subprocess.run(["git", "rm", str(prd_path)], check=True) subprocess.run(["git", "add", str(new_path)], check=True) next_num += 1 subprocess.run( ["git", "commit", "-m", "ci(prd): assign sequential numbers to new PRDs"], check=True, ) subprocess.run(["git", "push"], check=True) EOF