refactor(agents): enrich sdlc-compliance-auditor and sdlc-reviewer wi… #21
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Create Release on Tag | |
| on: | |
| push: | |
| tags: | |
| - 'v*' | |
| permissions: | |
| contents: write | |
| jobs: | |
| release: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 # Full history for tag comparison | |
| - name: Get previous tag | |
| id: prev_tag | |
| run: | | |
| CURRENT_TAG="${GITHUB_REF_NAME}" | |
| # Explicitly exclude current tag to avoid race conditions | |
| PREV_TAG=$(git tag --sort=-v:refname | grep -E '^v' | grep -v "^${CURRENT_TAG}$" | head -1) | |
| if [ -z "$PREV_TAG" ]; then | |
| # First release — use initial commit | |
| PREV_TAG=$(git rev-list --max-parents=0 HEAD) | |
| fi | |
| echo "Previous tag: $PREV_TAG (current: $CURRENT_TAG)" | |
| echo "tag=$PREV_TAG" >> "$GITHUB_OUTPUT" | |
| - name: Generate codename | |
| id: codename | |
| run: | | |
| ADJECTIVES=( | |
| "Argent" "Blazing" "Celestial" "Divine" "Eternal" | |
| "Fated" "Golden" "Hallowed" "Immortal" "Jovian" | |
| "Kronian" "Labyrinthine" "Mystic" "Nectared" "Olympian" | |
| "Primordial" "Questing" "Resplendent" "Stygian" "Titanic" | |
| "Undying" "Venerable" "Wrathful" "Exalted" "Zealous" | |
| ) | |
| NOUNS=( | |
| "Apollo" "Athena" "Cerberus" "Daedalus" "Erebus" | |
| "Furies" "Gorgon" "Hermes" "Icarus" "Janus" | |
| "Kronos" "Labyrinth" "Medusa" "Nemesis" "Orpheus" | |
| "Pegasus" "Prometheus" "Rhea" "Siren" "Tartarus" | |
| "Typhon" "Ulysses" "Chimera" "Xanthos" "Zeus" | |
| ) | |
| # Deterministic pick from version numbers | |
| VERSION="${GITHUB_REF_NAME#v}" | |
| MAJOR=$(echo "$VERSION" | cut -d. -f1) | |
| MINOR=$(echo "$VERSION" | cut -d. -f2) | |
| PATCH=$(echo "$VERSION" | cut -d. -f3) | |
| PATCH=${PATCH:-0} | |
| ADJ_IDX=$(( (MAJOR * 7 + MINOR * 13 + PATCH * 3) % ${#ADJECTIVES[@]} )) | |
| NOUN_IDX=$(( (MAJOR * 3 + MINOR * 7 + PATCH * 13) % ${#NOUNS[@]} )) | |
| CODENAME="${ADJECTIVES[$ADJ_IDX]} ${NOUNS[$NOUN_IDX]}" | |
| echo "name=$CODENAME" >> "$GITHUB_OUTPUT" | |
| - name: Extract changelog entries since last tag | |
| id: changelog | |
| run: | | |
| PREV_TAG="${{ steps.prev_tag.outputs.tag }}" | |
| CURRENT_TAG="${GITHUB_REF_NAME}" | |
| echo "Extracting changelog entries added since $PREV_TAG" | |
| # Use git diff to find entries added between tags (handles same-day releases) | |
| NOTES=$(python3 << PYEOF | |
| import sys | |
| import re | |
| import subprocess | |
| prev_tag = "$PREV_TAG" | |
| # Get the changelog content at the previous tag | |
| try: | |
| prev_content = subprocess.check_output( | |
| ["git", "show", f"{prev_tag}:process/sdlc_changelog.md"], | |
| stderr=subprocess.DEVNULL, | |
| text=True | |
| ) | |
| except subprocess.CalledProcessError: | |
| prev_content = "" # First release or file didn't exist | |
| # Get current changelog content | |
| with open("process/sdlc_changelog.md", "r") as f: | |
| current_content = f.read() | |
| # Parse entries from both versions | |
| def parse_entries(content): | |
| blocks = re.split(r'\n---\n', content) | |
| entries = {} | |
| for block in blocks: | |
| match = re.match(r'\s*## (\d{4}-\d{2}-\d{2}):\s*(.*)', block.strip()) | |
| if match: | |
| date = match.group(1) | |
| title = match.group(2).strip() | |
| key = f"{date}: {title}" | |
| entries[key] = (date, title, block.strip()) | |
| return entries | |
| prev_entries = parse_entries(prev_content) | |
| current_entries = parse_entries(current_content) | |
| # Find new entries (in current but not in previous) | |
| new_keys = set(current_entries.keys()) - set(prev_entries.keys()) | |
| new_entries = [current_entries[k] for k in new_keys] | |
| if not new_entries: | |
| print("No changelog entries found for this release period.") | |
| sys.exit(0) | |
| # Sort newest first | |
| new_entries.sort(key=lambda e: e[0], reverse=True) | |
| # Build release notes — summarized | |
| for date, title, body in new_entries: | |
| print(f"### {date}: {title}\n") | |
| # Extract the "Changes made" section for a concise summary | |
| changes_match = re.search( | |
| r'\*\*Changes made:\*\*\s*\n(.*?)(?=\n\*\*Rationale|\Z)', | |
| body, | |
| re.DOTALL | |
| ) | |
| if changes_match: | |
| changes = changes_match.group(1).strip() | |
| print(changes) | |
| else: | |
| # Fallback: print everything after the header | |
| lines = body.split('\n') | |
| print('\n'.join(lines[1:]).strip()) | |
| print() | |
| PYEOF | |
| ) | |
| # Write to file to preserve formatting | |
| echo "$NOTES" > /tmp/release_notes.md | |
| # Also set as output (escaped for GH Actions) | |
| { | |
| echo "notes<<GHEOF" | |
| echo "$NOTES" | |
| echo "GHEOF" | |
| } >> "$GITHUB_OUTPUT" | |
| - name: Create GitHub Release | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| tag_name: ${{ github.ref_name }} | |
| name: "${{ github.ref_name }} — ${{ steps.codename.outputs.name }}" | |
| body: | | |
| ${{ steps.changelog.outputs.notes }} | |
| --- | |
| *Release notes generated from [SDLC Changelog](process/sdlc_changelog.md)* | |
| draft: false | |
| prerelease: ${{ contains(github.ref_name, '-rc') || contains(github.ref_name, '-beta') || contains(github.ref_name, '-alpha') }} |