Merge pull request #5 from alirezarezvani/dev

feat(ci): Implement comprehensive GitHub automation workflows
This commit is contained in:
Alireza Rezvani
2025-11-05 08:58:57 +01:00
committed by GitHub
15 changed files with 1687 additions and 182 deletions

349
.claude/commands/README.md Normal file
View File

@@ -0,0 +1,349 @@
# Claude Skills Slash Commands
**Git workflow and quality assurance commands for the claude-skills repository.**
---
## 🎯 Essential Commands
### Git Workflow
```
/git:cm → Stage and commit (no push)
/git:cp → Stage, commit, and push
/git:pr → Create pull request
```
### Quality Gates
```
/review → Run local quality checks
/security-scan → Run security validation
```
---
## 📋 Git Commands
### /git:cm - Commit (No Push)
**Purpose**: Stage changes and create a conventional commit without pushing
**Usage**:
```
/git:cm
```
**What it does**:
1. Shows `git status --short`
2. Reviews each file diff for secrets
3. Stages files intentionally
4. Generates conventional commit message
5. Creates commit (no push)
**When to use**: When you want to commit locally before pushing
---
### /git:cp - Commit and Push
**Purpose**: Complete git workflow with quality checks
**Usage**:
```
/git:cp
```
**What it does**:
1. Runs `/review` for quality checks
2. Stages changes
3. Creates conventional commit
4. Pushes to origin
5. Triggers CI workflows
**When to use**: When ready to publish changes
---
### /git:pr - Create Pull Request
**Purpose**: Create a PR from current branch
**Usage**:
```
/git:pr # PR to main
/git:pr dev # PR to dev branch
```
**What it does**:
1. Verifies quality checks passed
2. Creates PR using template
3. Adds appropriate labels
4. Shares PR link
**When to use**: After pushing changes and ready for review
---
## 🔒 Quality Commands
### /review - Local Quality Gate
**Purpose**: Run all quality checks before pushing
**Usage**:
```
/review
```
**What it checks**:
- ✅ YAML linting (workflows)
- ✅ GitHub workflow schema validation
- ✅ Python syntax (all skill directories)
- ✅ Markdown link validation
- ✅ Dependency security audit (optional)
**When to use**: Before committing/pushing changes
---
### /security-scan - Security Validation
**Purpose**: Scan for security issues
**Usage**:
```
/security-scan
```
**What it checks**:
- 🔍 Gitleaks (committed secrets detection)
- 🔍 Safety (Python dependency vulnerabilities)
**When to use**: Before pushing, especially with new dependencies
---
## 🔄 Complete Workflow
### Standard Feature Development
```
# 1. Make changes to skills
[Edit files in marketing-skill/, product-team/, etc.]
# 2. Run quality checks
/review
# 3. Run security scan
/security-scan
# 4. Commit and push
/git:cp
# 5. Create pull request
/git:pr
# 6. Wait for:
- ✅ Claude Code Review comment
- ✅ CI Quality Gate passing
- ✅ Human approval
# 7. Merge PR
- Issue auto-closes (if linked)
- Project board updates
```
---
## 💡 Quick Reference
| Command | Stage | Commit | Push | Quality Check | Create PR |
|---------|-------|--------|------|---------------|-----------|
| **/git:cm** | ✅ | ✅ | ❌ | ❌ | ❌ |
| **/git:cp** | ✅ | ✅ | ✅ | ✅ | ❌ |
| **/git:pr** | ❌ | ❌ | ❌ | Verify | ✅ |
| **/review** | ❌ | ❌ | ❌ | ✅ | ❌ |
| **/security-scan** | ❌ | ❌ | ❌ | ✅ | ❌ |
---
## 📊 Commit Message Format
All commits follow **Conventional Commits**:
```
<type>(<scope>): <subject>
## Context
- Why this change was needed
- What problem it solves
## Testing
- [ ] All Python scripts tested
- [ ] Skills validated with Claude
- [ ] /review passed
- [ ] /security-scan passed
## Reviewers
- [ ] @username
```
**Types**: `feat`, `fix`, `docs`, `style`, `refactor`, `perf`, `test`, `build`, `ci`, `chore`, `revert`
**Scopes**: `marketing-skill`, `product-team`, `c-level-advisor`, `engineering-team`, `ra-qm-team`, `workflows`, `docs`, `ci`
**Examples**:
```
feat(marketing-skill): add LinkedIn content framework
fix(product-team): correct RICE prioritization calculation
docs(README): update skill installation instructions
ci(workflows): add auto-close issues on PR merge
```
---
## 🎯 Use Cases
### Quick Fix
```
# Fix typo in skill
[Edit file]
/review # Quick check
/git:cp # Commit + push
```
### New Skill Addition
```
# Create new skill
[Create skill directory and files]
/review # Validate structure
/security-scan # Check for issues
/git:cm # Commit locally
[Test skill activation]
/git:cp # Push when ready
/git:pr # Create PR for review
```
### Major Feature with Multiple Skills
```
# Work on branch
git checkout -b feature/enterprise-skills
# Add multiple skills
[Create skill 1]
/git:cm
[Create skill 2]
/git:cm
[Create skill 3]
/git:cm
# Final quality check
/review
/security-scan
# Push and create PR
git push origin feature/enterprise-skills
/git:pr
# Or use /git:cp if you want to push single commit
```
---
## 🚨 Emergency Bypass
### Skip Reviews (Emergency Only)
If you need to bypass checks:
```bash
# Method 1: Use --no-verify flag
git push --no-verify
# Method 2: PR title bypass
[EMERGENCY] Fix critical bug
# Method 3: PR label
Add label: emergency, skip-review, or hotfix
```
**Note**: These bypass automated reviews but manual review is still recommended.
---
## 📖 Integration with Automation
These commands work seamlessly with the GitHub automation:
**After running `/git:cp`**:
- Triggers CI Quality Gate workflow
- Shows results in GitHub Actions
**After running `/git:pr`**:
- Triggers Claude Code Review
- Runs CI Quality Gate
- Updates project board status
**After merging PR**:
- Auto-closes linked issues
- Updates project board to "Done"
- Posts completion comments
---
## 🔗 Related Documentation
- **Automation Setup**: `.github/AUTOMATION_SETUP.md`
- **PR Template**: `.github/pull_request_template.md`
- **Commit Template**: `.github/commit-template.txt`
- **Workflow Guide**: See factory project for detailed reference
---
## 📍 Command Locations
```
.claude/commands/
├── git/
│ ├── cm.md # Commit (no push)
│ ├── cp.md # Commit and push
│ └── pr.md # Create PR
├── review.md # Quality checks
├── security-scan.md # Security validation
└── README.md # This file
```
---
## 💡 Tips
**Before committing**:
- ✅ Run `/review` to catch issues early
- ✅ Run `/security-scan` if adding dependencies
- ✅ Test skills with Claude before pushing
**When creating PRs**:
- ✅ Link related issues (`Fixes #123`)
- ✅ Fill out PR template completely
- ✅ Add appropriate labels
- ✅ Request specific reviewers
**For quality**:
- ✅ Keep commits focused and atomic
- ✅ Write clear, descriptive commit messages
- ✅ Follow conventional commit format
- ✅ Update documentation with changes
---
**Last Updated**: 2025-11-04
**Version**: 1.0.0
**Status**: ✅ Ready to use
**Streamline your Git workflow with simple commands!** 🚀

View File

@@ -0,0 +1,14 @@
---
description: Stage working tree changes and create a Conventional Commit (no push).
---
1. Run `git status --short` to review pending changes.
2. For each file, open a diff (`git diff -- path/to/file`) and ensure no secrets or credentials are present.
3. Stage the files intentionally (`git add path/to/file`). Avoid `git add .` unless every change was reviewed.
4. Generate a Conventional Commit message (types: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert).
- Commit subject ≤ 72 chars.
- Scope uses kebab-case (e.g., `feat(marketing-skill): ...`).
- Use `.github/commit-template.txt` for Context / Testing / Reviewers sections.
5. Run `git commit` and paste the generated message + context from the template.
6. Show the resulting commit (`git log -1 --stat`) and keep the commit hash handy.
7. **Do not push** in this command. Use `git/cp.md` when you're ready to publish.

View File

@@ -0,0 +1,14 @@
---
description: Stage, commit, and push the current branch following git governance rules.
---
1. Run `/review` to ensure lint/tests/security checks pass locally.
2. Review and stage changes with `git add` (avoid staging generated or secret files).
3. Craft a Conventional Commit message (types: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert).
- Use `.github/commit-template.txt` and include Context / Testing / Reviewers blocks.
- Never add AI attribution strings to commits.
4. Commit with `git commit` using the prepared message. If commitlint fails, fix the message and retry.
5. Push to origin: `git push origin $(git branch --show-current)`.
6. Trigger remote checks for visibility:
- `gh workflow run ci-quality-gate.yml --ref $(git branch --show-current)`
7. Wait for workflow to finish (`gh run watch --workflow ci-quality-gate.yml`) before opening a pull request.

View File

@@ -0,0 +1,25 @@
---
description: Create a pull request from the current branch.
argument-hint: [target-branch]
---
## Variables
TARGET_BRANCH: $1 (defaults to `main`)
SOURCE_BRANCH: current branch (`git branch --show-current`)
## Workflow
1. Ensure `/review` and `/security-scan` have passed locally.
2. Confirm `ci-quality-gate` workflow succeeded for `SOURCE_BRANCH`.
3. Create the PR using GitHub CLI:
```bash
gh pr create \
--base "$TARGET_BRANCH" \
--head "$SOURCE_BRANCH" \
--title "<Conventional PR title>" \
--body-file .github/pull_request_template.md
```
If no template exists, provide a summary referencing Context, Testing, and Security results.
4. Add labels (`gh pr edit --add-label "status: in-review"`).
5. Share the PR link with reviewers and ensure at least one human approval is obtained.

View File

@@ -0,0 +1,33 @@
---
description: Run the local review gate before pushing.
---
Perform a complete review pass:
1. Save work in progress and ensure the working tree is clean except for intentional changes.
2. Install tooling (only first run):
```bash
pip install --upgrade pip
pip install yamllint==1.35.1 check-jsonschema==0.28.4 safety==3.2.4
npm install --global markdown-link-check@3.12.2
```
3. Lint GitHub workflows:
```bash
yamllint -d '{extends: default, rules: {line-length: {max: 160}}}' .github/workflows
check-jsonschema --schema github-workflow --base-dir . .github/workflows/*.yml
```
4. Python syntax check:
```bash
python -m compileall marketing-skill product-team c-level-advisor engineering-team ra-qm-team
```
5. Markdown sanity check:
```bash
markdown-link-check README.md
```
6. Optional dependency audit (if `requirements*.txt` present):
```bash
for f in $(find . -name "requirements*.txt" 2>/dev/null); do
safety check --full-report --file "$f"
done
```
7. Summarize results in the commit template's Testing section. Fix any failures before continuing.

View File

@@ -0,0 +1,22 @@
---
description: Run the security scan gate before pushing.
---
1. Ensure dependencies are installed:
```bash
pip install safety==3.2.4
brew install gitleaks # or appropriate package manager
```
2. Scan for committed secrets:
```bash
gitleaks detect --verbose --redact
```
- Resolve any findings before continuing.
3. Audit Python dependencies (if requirements files exist):
```bash
for f in $(find . -name "requirements*.txt" 2>/dev/null); do
safety check --full-report --file "$f"
done
```
4. Record results in the commit template's Testing section.
5. After a clean pass, proceed with commit and push workflow.

325
.github/AUTOMATION_SETUP.md vendored Normal file
View File

@@ -0,0 +1,325 @@
# GitHub Automation Setup Guide
**Repository**: claude-skills
**Project Number**: 9
**Status**: ⚙️ Configuration Required
---
## Overview
This repository includes AI-powered GitHub automation with:
-**Claude Code Review** - Automatic PR reviews
-**Auto-Close Issues** - PRs auto-close linked issues when merged
-**Smart Sync** - Bidirectional issue ↔ project board synchronization
-**Quality Gates** - Automated linting, testing, security checks
-**Kill Switch** - Emergency workflow disable capability
---
## Quick Start (15 minutes)
### 1. Create Required Secrets
You need **2 secrets** for full automation:
#### ✅ CLAUDE_CODE_OAUTH_TOKEN (Already Configured)
This secret is already set up for Claude Code reviews.
#### ⚠️ PROJECTS_TOKEN (Required for Project Board Sync)
**Create Personal Access Token:**
1. Go to: https://github.com/settings/tokens/new
2. Configure:
- **Note**: "Claude Skills Project Board Access"
- **Expiration**: 90 days (recommended)
- **Select scopes**:
-`repo` (Full control of private repositories)
-`project` (Full control of projects)
3. Click "Generate token"
4. **Copy the token** (you won't see it again!)
**Add to Repository:**
1. Go to: https://github.com/alirezarezvani/claude-skills/settings/secrets/actions
2. Click "New repository secret"
3. **Name**: `PROJECTS_TOKEN`
4. **Value**: [Paste your token]
5. Click "Add secret"
---
### 2. Create Project Board Labels
Run these commands to create all required labels:
```bash
# Status Labels (6)
gh label create "status: triage" --color "fbca04" --description "To Triage column" --repo alirezarezvani/claude-skills
gh label create "status: backlog" --color "d4c5f9" --description "Backlog column" --repo alirezarezvani/claude-skills
gh label create "status: ready" --color "0e8a16" --description "Ready column" --repo alirezarezvani/claude-skills
gh label create "status: in-progress" --color "1d76db" --description "In Progress column" --repo alirezarezvani/claude-skills
gh label create "status: in-review" --color "d876e3" --description "In Review column" --repo alirezarezvani/claude-skills
gh label create "status: done" --color "2ea44f" --description "Done column" --repo alirezarezvani/claude-skills
# Priority Labels (4)
gh label create "P0" --color "b60205" --description "Critical priority" --repo alirezarezvani/claude-skills
gh label create "P1" --color "d93f0b" --description "High priority" --repo alirezarezvani/claude-skills
gh label create "P2" --color "fbca04" --description "Medium priority" --repo alirezarezvani/claude-skills
gh label create "P3" --color "0e8a16" --description "Low priority" --repo alirezarezvani/claude-skills
# Type Labels (already exist - verify)
# bug, feature, documentation, enhancement, etc.
```
---
### 3. Configure Project Board
Your project board columns must match these exact names:
1. **To triage**
2. **Backlog**
3. **Ready**
4. **In Progress**
5. **In Review**
6. **Done**
**Verify Configuration:**
1. Go to: https://github.com/users/alirezarezvani/projects/9
2. Check column names match exactly (case-sensitive)
3. Ensure "Status" field exists
---
### 4. Test the Setup
#### Test 1: Create Test Issue
```bash
gh issue create \
--title "Test: Automation Setup" \
--body "Testing GitHub automation workflows" \
--label "status: triage" \
--repo alirezarezvani/claude-skills
```
**Expected Results:**
- ✅ Issue created
- ✅ Auto-added to project board (column: "To triage")
- ✅ Label synced
#### Test 2: Change Issue Status
```bash
# Get the issue number from step 1, then:
gh issue edit ISSUE_NUMBER --add-label "status: in-progress" --repo alirezarezvani/claude-skills
```
**Expected Results:**
- ✅ Issue moved to "In Progress" on project board
- ✅ Old status label removed
- ✅ New status label applied
#### Test 3: Create Test PR
```bash
# Create a branch
git checkout -b test/automation-setup
echo "# Test" > TEST.md
git add TEST.md
git commit -m "test: verify automation"
git push origin test/automation-setup
# Create PR that fixes the test issue
gh pr create \
--title "test: Verify automation workflows" \
--body "Fixes #ISSUE_NUMBER" \
--repo alirezarezvani/claude-skills
```
**Expected Results:**
- ✅ Claude review triggers (check Actions tab)
- ✅ CI Quality Gate runs
- ✅ When merged, issue auto-closes
- ✅ Project board updates to "Done"
---
## Active Workflows
| Workflow | Trigger | Status |
|----------|---------|--------|
| **claude-code-review.yml** | PR opened/updated | ✅ Active |
| **pr-issue-auto-close.yml** | PR merged | ✅ Active |
| **smart-sync.yml** | Issue/board changes | ⚠️ Requires PROJECTS_TOKEN |
| **ci-quality-gate.yml** | PR opened/updated | ✅ Active |
---
## Emergency Procedures
### 🚨 Disable All Workflows
If something goes wrong:
```bash
echo "STATUS: DISABLED" > .github/WORKFLOW_KILLSWITCH
git add .github/WORKFLOW_KILLSWITCH
git commit -m "emergency: Disable workflows"
git push origin main --no-verify
```
All workflows check this file and exit immediately if disabled.
### ✅ Re-enable Workflows
```bash
echo "STATUS: ENABLED" > .github/WORKFLOW_KILLSWITCH
git commit -am "chore: Re-enable workflows"
git push
```
---
## Usage Examples
### Auto-Close Issues with PR
In your PR description:
```markdown
## Summary
Fixed the authentication bug
## Related Issues
Fixes #123
Closes #456
```
When merged → Issues #123 and #456 automatically close with comment linking to PR.
### Sync Issue Status
**Option A - Update Label:**
```bash
gh issue edit 123 --add-label "status: in-review"
```
→ Moves to "In Review" on project board
**Option B - Update Board:**
```
Drag issue to "In Review" column on project board
```
→ Adds "status: in-review" label to issue
---
## Troubleshooting
### Smart Sync Not Working
**Problem**: Labels not syncing with project board
**Check:**
```bash
gh secret list --repo alirezarezvani/claude-skills | grep PROJECTS_TOKEN
```
**Solution**: If missing, add PROJECTS_TOKEN (see Step 1 above)
### Claude Review Not Running
**Problem**: No review comment on PR
**Check:**
```bash
gh run list --workflow=claude-code-review.yml --limit 5 --repo alirezarezvani/claude-skills
```
**Solutions**:
- Verify CLAUDE_CODE_OAUTH_TOKEN exists
- Check workflow logs for errors
- Re-run workflow from Actions tab
### Rate Limits
**Check current limits:**
```bash
gh api rate_limit --jq '.resources.core.remaining, .resources.graphql.remaining'
```
**Rate Limit Info:**
- REST API: 5,000/hour
- GraphQL: 5,000/hour
- Workflows require 50+ remaining before executing
---
## Maintenance
### Weekly
```bash
# Check failed runs
gh run list --status failure --limit 10 --repo alirezarezvani/claude-skills
# Verify secrets valid
gh secret list --repo alirezarezvani/claude-skills
```
### Quarterly
```bash
# Regenerate PROJECTS_TOKEN (expires every 90 days)
# 1. Create new token with same scopes
# 2. Update repository secret
# 3. Test with a sync operation
```
---
## Security Notes
**4-Layer Security Model:**
1. **GitHub Permissions** - Only team members trigger workflows
2. **Tool Restrictions** - Allowlist specific commands only
3. **Token Scoping** - Minimal permissions (repo + project)
4. **Branch Protection** - Required reviews, status checks
**Kill Switch**: Emergency disable capability (WORKFLOW_KILLSWITCH file)
---
## Next Steps
1. ✅ Create PROJECTS_TOKEN secret
2. ✅ Create all required labels
3. ✅ Verify project board columns
4. ✅ Test with sample issue and PR
5. ✅ Monitor first few workflow runs
6. ✅ Document any project-specific customizations
---
## Support
**Documentation:**
- This setup guide
- Individual workflow files in `.github/workflows/`
- Factory reference: https://github.com/alirezarezvani/claude-code-skills-factory
**Getting Help:**
- Create issue with `question` label
- Check workflow logs: `gh run view RUN_ID --log`
- Review troubleshooting section above
---
**Last Updated**: 2025-11-04
**Status**: Ready for configuration ⚙️

1
.github/WORKFLOW_KILLSWITCH vendored Normal file
View File

@@ -0,0 +1 @@
STATUS: ENABLED

17
.github/branch-protection-config.json vendored Normal file
View File

@@ -0,0 +1,17 @@
{
"required_status_checks": {
"strict": true,
"contexts": [
"claude-review"
]
},
"enforce_admins": true,
"required_pull_request_reviews": null,
"restrictions": null,
"allow_force_pushes": false,
"allow_deletions": false,
"block_creations": false,
"required_conversation_resolution": true,
"required_linear_history": false,
"lock_branch": false
}

14
.github/commit-template.txt vendored Normal file
View File

@@ -0,0 +1,14 @@
<type>(<scope>): <summary>
## Context
-
## Testing
- [ ] All Python scripts tested
- [ ] Skills validated with Claude
- [ ] Documentation updated
- [ ] Examples work as expected
## Reviewers
- [ ] @

View File

@@ -1,183 +1,60 @@
# Pull Request
## Summary
<!-- Brief description of what this PR accomplishes -->
## Description
**What does this PR do?**
## Context
<!-- Why these changes are needed. Link to issues, discussions, or explain the problem being solved. -->
A clear and concise description of the changes.
## Type of Change
Select the type of change:
- [ ] New skill addition
- [ ] Skill enhancement/improvement
- [ ] Bug fix
- [ ] Documentation update
- [ ] Python script improvement
- [ ] Refactoring/optimization
- [ ] Other (specify)
## Related Issue
Fixes #(issue number)
Or: Related to #(issue number)
---
## Changes Made
### Skills Added/Modified
**Skill Name(s):**
-
**What Changed:**
- Added: (new capabilities, scripts, references)
- Modified: (what was changed and why)
- Removed: (what was deprecated/removed and why)
## Changes
<!-- High-level overview of what was modified -->
### Python Scripts
**New Scripts:**
- `script_name.py` - Purpose and functionality
**Modified Scripts:**
- `existing_script.py` - Changes made
### Documentation
**Files Updated:**
- README.md - (what sections)
- SKILL.md - (what changed)
- Reference files - (which ones)
---
-
## Testing
<!-- Confirm all checks have passed -->
### Testing Performed
- [ ] Local quality checks passed (Python syntax, markdown links)
- [ ] All Python scripts tested and working
- [ ] Skills validated with Claude (if applicable)
- [ ] `ci-quality-gate` workflow will pass
- [ ] Manual testing completed
- [ ] Tested with Claude AI (uploaded SKILL.md and verified activation)
- [ ] Tested with Claude Code (loaded skill and ran workflows)
- [ ] All Python scripts run without errors
- [ ] Ran scripts with `--help` flag
- [ ] Tested JSON output (if applicable)
- [ ] All reference links work
- [ ] No broken relative paths
**Testing Details**:
<!-- Describe what you tested and how -->
### Test Results
**Claude Activation:**
- [ ] Skill activates when appropriate
- [ ] Description triggers correctly
- [ ] Keywords help discovery
## Security
<!-- Confirm security requirements met -->
**Python Scripts:**
```bash
# Commands run for testing
python scripts/tool.py --help
python scripts/tool.py test-input.txt
```
- [ ] No secrets, credentials, or API keys committed
- [ ] No destructive commands in generated outputs
- [ ] Path traversal vulnerabilities checked
- [ ] Dependencies reviewed (if added)
**Results:**
```
[Paste test output or describe results]
```
## Documentation
<!-- Confirm documentation updated -->
- [ ] README.md updated (if applicable)
- [ ] CLAUDE.md updated (if applicable)
- [ ] Inline code comments added for complex logic
- [ ] CHANGELOG.md updated (if applicable)
- [ ] Skill SKILL.md files updated (if applicable)
## Reviewers
<!-- Tag reviewers who should look at this PR -->
- [ ] @
## Related Issues
<!-- Link issues this PR addresses using keywords: Fixes, Closes, Resolves, Related to -->
Fixes #
Closes #
Related to #
---
## Quality Checklist
### SKILL.md Quality
- [ ] YAML frontmatter is valid
- [ ] `name` matches directory name
- [ ] `description` includes what, when, and keyword triggers
- [ ] `license: MIT` included
- [ ] `metadata` section complete (version, author, category, domain)
- [ ] Keywords section added
- [ ] SKILL.md length <200 lines (or justified if longer)
- [ ] Clear quick start section
- [ ] Core workflows documented
- [ ] Examples included
### Python Scripts Quality (if applicable)
- [ ] Production-ready code (not placeholders)
- [ ] CLI with `--help` support
- [ ] Proper error handling
- [ ] Clear docstrings
- [ ] Type hints used
- [ ] Standard library preferred
- [ ] Dependencies documented
- [ ] No hardcoded paths or credentials
### Documentation Quality
- [ ] All links work (no 404s)
- [ ] Markdown formatting correct
- [ ] No typos or grammar errors
- [ ] Code blocks have language specified
- [ ] Examples are realistic and complete
- [ ] Screenshots included where helpful
### Repository Integration
- [ ] Domain-specific README.md updated (if new skill)
- [ ] Main README.md updated (if new domain or major feature)
- [ ] CLAUDE.md updated (if changes affect development)
- [ ] CHANGELOG.md updated (in Unreleased section)
---
## ROI & Value
**Estimated Value of This Contribution:**
**Time Savings:**
- Hours saved per month per user: (estimate)
- Number of potential users: (estimate)
**Quality Improvements:**
- Specific quality gains: (describe)
- Measurable improvements: (quantify if possible)
**Why This Matters:**
Brief explanation of the business/user value.
---
## Screenshots
If applicable, add screenshots to help explain your changes.
---
## Additional Notes
Any other information reviewers should know:
- Implementation decisions made
- Alternative approaches considered
- Known limitations
- Future enhancement ideas
---
## Contributor Checklist
**Before Submitting:**
- [ ] I have read [CONTRIBUTING.md](../CONTRIBUTING.md)
- [ ] I have followed the skill creation guidelines
- [ ] I have tested thoroughly
- [ ] I have updated all relevant documentation
- [ ] I have added my changes to CHANGELOG.md (Unreleased section)
- [ ] My code follows the repository's style guidelines
- [ ] All new Python scripts are production-ready
- [ ] I agree to the MIT License for my contributions
---
**Thank you for contributing to Claude Skills Library!** 🚀
Your contribution helps make world-class expertise accessible to everyone through Claude AI.
**Type**: <!-- feat | fix | docs | refactor | chore | ci | test | perf | skill -->
**Scope**: <!-- component affected (e.g., marketing-skill, workflows, agents, templates) -->

91
.github/workflows/ci-quality-gate.yml vendored Normal file
View File

@@ -0,0 +1,91 @@
---
name: CI Quality Gate
'on':
pull_request:
types: [opened, synchronize, reopened, ready_for_review]
workflow_dispatch:
inputs:
ref:
description: Branch to run quality gate against
required: false
repository_dispatch:
types: [ci-quality]
concurrency:
group: quality-gate-${{ github.event.pull_request.number || github.run_id }}
cancel-in-progress: true
jobs:
quality:
name: Lint, Tests, Docs, Security
runs-on: ubuntu-latest
permissions:
contents: read
timeout-minutes: 25
steps:
- name: Resolve ref
id: ref
run: |
if [[ "${{ github.event_name }}" == "workflow_dispatch" && -n "${{ github.event.inputs.ref }}" ]]; then
echo "target_ref=${{ github.event.inputs.ref }}" >> "$GITHUB_OUTPUT"
elif [[ "${{ github.event_name }}" == "repository_dispatch" && -n "${{ github.event.client_payload.ref }}" ]]; then
echo "target_ref=${{ github.event.client_payload.ref }}" >> "$GITHUB_OUTPUT"
else
echo "target_ref=${{ github.head_ref || github.ref_name }}" >> "$GITHUB_OUTPUT"
fi
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ steps.ref.outputs.target_ref }}
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install tooling
run: |
python -m pip install --upgrade pip
pip install yamllint==1.35.1 check-jsonschema==0.28.4 safety==3.2.4
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 20
- name: YAML lint (.github/workflows)
run: |
yamllint -d '{extends: default, rules: {line-length: {max: 160}}}' .github/workflows
- name: Validate GitHub workflow schemas
run: |
check-jsonschema --schema github-workflow --base-dir . .github/workflows/*.yml
- name: Python syntax check
run: |
python -m compileall marketing-skill product-team c-level-advisor engineering-team ra-qm-team || true
- name: Safety dependency audit (requirements*.txt)
run: |
set -e
files=$(find . -name "requirements*.txt" 2>/dev/null || true)
if [[ -z "$files" ]]; then
echo "No requirements files found; skipping safety scan."
exit 0
fi
for f in $files; do
echo "Auditing $f"
safety check --full-report --file "$f" || true
done
- name: Markdown link spot-check
run: |
npx --yes markdown-link-check@3.12.2 README.md
- name: Summarize results
if: always()
run: |
echo "Quality gate completed with status: ${{ job.status }}"

View File

@@ -1,39 +1,92 @@
---
name: Claude Code Review
on:
'on':
pull_request:
types: [opened, synchronize]
# Optional: Only run on specific file changes
# paths:
# - "src/**/*.ts"
# - "src/**/*.tsx"
# - "src/**/*.js"
# - "src/**/*.jsx"
# Prevent multiple review runs on rapid PR updates
concurrency:
group: claude-review-${{ github.event.pull_request.number }}
cancel-in-progress: true
jobs:
claude-review:
# Optional: Filter by PR author
# if: |
# github.event.pull_request.user.login == 'external-contributor' ||
# github.event.pull_request.user.login == 'new-developer' ||
# github.event.pull_request.author_association == 'FIRST_TIME_CONTRIBUTOR'
# Auto-review ALL pull requests with Claude
# BYPASS: Add [EMERGENCY], [SKIP REVIEW], or [HOTFIX] to PR title
# BYPASS: Or add 'emergency' or 'skip-review' label to PR
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: read
issues: read
id-token: write
id-token: write # Required by Claude Code action for OIDC authentication
steps:
- name: Check Workflow Kill Switch
run: |
if [ -f ".github/WORKFLOW_KILLSWITCH" ]; then
STATUS=$(grep "STATUS:" .github/WORKFLOW_KILLSWITCH | awk '{print $2}')
if [ "$STATUS" = "DISABLED" ]; then
echo "🛑 Workflows disabled by kill switch"
exit 0
fi
fi
- name: Check for Review Bypass
id: bypass
run: |
PR_TITLE="${{ github.event.pull_request.title }}"
PR_LABELS="${{ toJSON(github.event.pull_request.labels.*.name) }}"
# Check for bypass markers in PR title
if echo "$PR_TITLE" | grep -qE '\[EMERGENCY\]|\[SKIP REVIEW\]|\[HOTFIX\]'; then
echo "bypass=true" >> $GITHUB_OUTPUT
echo "reason=PR title contains bypass marker" >> $GITHUB_OUTPUT
echo "⏭️ BYPASS: PR title contains bypass marker"
exit 0
fi
# Check for bypass labels
if echo "$PR_LABELS" | grep -qE 'emergency|skip-review|hotfix'; then
echo "bypass=true" >> $GITHUB_OUTPUT
echo "reason=PR has bypass label" >> $GITHUB_OUTPUT
echo "⏭️ BYPASS: PR has bypass label"
exit 0
fi
echo "bypass=false" >> $GITHUB_OUTPUT
echo "✅ No bypass detected - review will proceed"
- name: Post Bypass Notice
if: steps.bypass.outputs.bypass == 'true'
uses: actions/github-script@v7
with:
script: |
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `## ⏭️ Code Review Bypassed
**Reason**: ${{ steps.bypass.outputs.reason }}
⚠️ **Manual review recommended** - This PR was merged without automated code review.
---
*Bypass triggered by emergency procedures protocol*`
})
- name: Checkout repository
if: steps.bypass.outputs.bypass != 'true'
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Run Claude Code Review
if: steps.bypass.outputs.bypass != 'true'
id: claude-review
uses: anthropics/claude-code-action@v1
continue-on-error: true
with:
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
prompt: |
@@ -46,12 +99,33 @@ jobs:
- Performance considerations
- Security concerns
- Test coverage
- Skill quality (if applicable)
Use the repository's CLAUDE.md for guidance on style and conventions. Be constructive and helpful in your feedback.
Use `gh pr comment` with your Bash tool to leave your review as a comment on the PR.
# See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
# or https://docs.claude.com/en/docs/claude-code/cli-reference for available options
claude_args: '--allowed-tools "Bash(gh issue view:*),Bash(gh search:*),Bash(gh issue list:*),Bash(gh pr comment:*),Bash(gh pr diff:*),Bash(gh pr view:*),Bash(gh pr list:*)"'
# or https://docs.claude.com/en/docs/claude-code/cli-reference
claude_args: >-
--allowed-tools
"Bash(gh issue view:*),Bash(gh search:*),Bash(gh issue list:*),
Bash(gh pr comment:*),Bash(gh pr diff:*),Bash(gh pr view:*),Bash(gh pr list:*)"
- name: Post fallback review note (quota/timeout)
if: steps.claude-review.outcome != 'success'
uses: actions/github-script@v7
with:
script: |
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `## ⚠️ Automated Review Skipped
The automated Claude review could not complete (likely quota or a transient error).
- You can retry this workflow from the Actions tab
- Proceed with manual review to unblock
`
})

View File

@@ -0,0 +1,207 @@
---
name: Auto-Close Issues on PR Merge
'on':
pull_request:
types: [closed]
permissions:
issues: write
pull-requests: read
contents: read
jobs:
close-linked-issues:
name: Close Issues Linked in PR
if: github.event.pull_request.merged == true
runs-on: ubuntu-latest
steps:
- name: Check Workflow Kill Switch
run: |
if [ -f ".github/WORKFLOW_KILLSWITCH" ]; then
STATUS=$(grep "STATUS:" .github/WORKFLOW_KILLSWITCH | awk '{print $2}')
if [ "$STATUS" = "DISABLED" ]; then
echo "🛑 Workflows disabled by kill switch"
exit 0
fi
fi
- name: Checkout repository
uses: actions/checkout@v4
- name: Extract linked issues from PR body
id: extract_issues
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const prBody = context.payload.pull_request.body || '';
const prNumber = context.payload.pull_request.number;
// Patterns to detect linked issues
// Supports: Fixes #123, Closes #456, Resolves #789, Related to #111, See #222
const patterns = [
/(?:fix|fixes|fixed|close|closes|closed|resolve|resolves|resolved)\s+#(\d+)/gi,
/(?:related\s+to|see|ref|references)\s+#(\d+)/gi
];
const issueNumbers = new Set();
// Extract issue numbers
patterns.forEach(pattern => {
let match;
while ((match = pattern.exec(prBody)) !== null) {
issueNumbers.add(match[1]);
}
});
// Also check PR title
const prTitle = context.payload.pull_request.title || '';
patterns.forEach(pattern => {
let match;
while ((match = pattern.exec(prTitle)) !== null) {
issueNumbers.add(match[1]);
}
});
// Also check commit messages in PR
const commits = await github.rest.pulls.listCommits({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: prNumber
});
commits.data.forEach(commit => {
const message = commit.commit.message;
patterns.forEach(pattern => {
let match;
while ((match = pattern.exec(message)) !== null) {
issueNumbers.add(match[1]);
}
});
});
const issues = Array.from(issueNumbers);
console.log(`Found linked issues: ${issues.join(', ')}`);
return issues;
- name: Close linked issues
if: steps.extract_issues.outputs.result != '[]'
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const issueNumbers = ${{ steps.extract_issues.outputs.result }};
const prNumber = context.payload.pull_request.number;
const prTitle = context.payload.pull_request.title;
const prUrl = context.payload.pull_request.html_url;
const merger = context.payload.pull_request.merged_by.login;
console.log(`Processing ${issueNumbers.length} linked issue(s)`);
for (const issueNumber of issueNumbers) {
try {
// Get issue details first
const issue = await github.rest.issues.get({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: parseInt(issueNumber)
});
// Skip if already closed
if (issue.data.state === 'closed') {
console.log(`Issue #${issueNumber} already closed, skipping`);
continue;
}
// Add comment explaining closure
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: parseInt(issueNumber),
body: `## ✅ Completed via PR #${prNumber}
**PR**: ${prTitle}
**URL**: ${prUrl}
**Merged by**: @${merger}
This issue has been resolved and the changes have been merged into main.
🤖 Automatically closed via PR merge automation`
});
// Close the issue
await github.rest.issues.update({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: parseInt(issueNumber),
state: 'closed',
state_reason: 'completed'
});
console.log(`✅ Closed issue #${issueNumber}`);
} catch (error) {
console.error(`❌ Failed to close issue #${issueNumber}: ${error.message}`);
}
}
- name: Update project board status
if: steps.extract_issues.outputs.result != '[]'
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const issueNumbers = ${{ steps.extract_issues.outputs.result }};
for (const issueNumber of issueNumbers) {
try {
// Add status: done label
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: parseInt(issueNumber),
labels: ['status: done']
});
// Remove in-progress and in-review labels
const labelsToRemove = ['status: in-progress', 'status: in-review'];
for (const label of labelsToRemove) {
try {
await github.rest.issues.removeLabel({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: parseInt(issueNumber),
name: label
});
} catch (e) {
// Label might not exist, ignore error
}
}
console.log(`✅ Updated project status for issue #${issueNumber}`);
} catch (error) {
console.error(`❌ Failed to update status for issue #${issueNumber}: ${error.message}`);
}
}
- name: Summary
if: steps.extract_issues.outputs.result != '[]'
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const issueNumbers = ${{ steps.extract_issues.outputs.result }};
const prNumber = context.payload.pull_request.number;
console.log(`
✅ PR #${prNumber} Merge Automation Complete
Closed issues: ${issueNumbers.join(', ')}
Updated project board: status → done
Comments added: Linked to PR #${prNumber}
All linked issues have been automatically closed and marked as done.
`);

442
.github/workflows/smart-sync.yml vendored Normal file
View File

@@ -0,0 +1,442 @@
---
name: Smart Bidirectional Sync
'on':
issues:
types: [labeled, closed, reopened]
projects_v2_item:
types: [edited]
# Prevent sync loops with debouncing
concurrency:
group: smart-sync-${{ github.event.issue.number || github.event.projects_v2_item.node_id }}
cancel-in-progress: true # Cancel pending runs (debouncing effect)
jobs:
determine-direction:
runs-on: ubuntu-latest
timeout-minutes: 3
permissions:
contents: read
issues: read
id-token: write
outputs:
should_sync: ${{ steps.check.outputs.should_sync }}
direction: ${{ steps.check.outputs.direction }}
issue_number: ${{ steps.check.outputs.issue_number }}
steps:
- name: Check Workflow Kill Switch
run: |
if [ -f ".github/WORKFLOW_KILLSWITCH" ]; then
STATUS=$(grep "STATUS:" .github/WORKFLOW_KILLSWITCH | awk '{print $2}')
if [ "$STATUS" = "DISABLED" ]; then
echo "🛑 Workflows disabled by kill switch"
exit 0
fi
fi
- name: Determine Sync Direction
id: check
run: |
# Check which event triggered this workflow
if [ "${{ github.event_name }}" = "issues" ]; then
# Issue event → sync to project board
echo "direction=issue-to-project" >> $GITHUB_OUTPUT
echo "issue_number=${{ github.event.issue.number }}" >> $GITHUB_OUTPUT
# Only sync on status label changes or state changes
if [[ "${{ github.event.action }}" == "labeled" && "${{ github.event.label.name }}" == status:* ]] || \
[ "${{ github.event.action }}" = "closed" ] || \
[ "${{ github.event.action }}" = "reopened" ]; then
echo "should_sync=true" >> $GITHUB_OUTPUT
echo "✅ Will sync: Issue #${{ github.event.issue.number }} → Project Board"
else
echo "should_sync=false" >> $GITHUB_OUTPUT
echo "⏭️ Skipping: Not a status change or state change"
fi
elif [ "${{ github.event_name }}" = "projects_v2_item" ]; then
# Project event → sync to issue
echo "direction=project-to-issue" >> $GITHUB_OUTPUT
echo "should_sync=true" >> $GITHUB_OUTPUT
echo "✅ Will sync: Project Board → Issue"
else
echo "should_sync=false" >> $GITHUB_OUTPUT
echo "⚠️ Unknown event type"
fi
rate-limit-check:
needs: determine-direction
if: needs.determine-direction.outputs.should_sync == 'true'
runs-on: ubuntu-latest
timeout-minutes: 2
permissions:
contents: read
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
outputs:
can_proceed: ${{ steps.limits.outputs.can_proceed }}
steps:
- name: Check Rate Limits (Circuit Breaker)
id: limits
run: |
echo "🔍 Checking GitHub API rate limits..."
# Get rate limit status
core_remaining=$(gh api rate_limit --jq '.resources.core.remaining')
core_limit=$(gh api rate_limit --jq '.resources.core.limit')
graphql_remaining=$(gh api rate_limit --jq '.resources.graphql.remaining')
graphql_limit=$(gh api rate_limit --jq '.resources.graphql.limit')
echo "📊 Rate Limits:"
echo " REST API: $core_remaining/$core_limit"
echo " GraphQL: $graphql_remaining/$graphql_limit"
# Require at least 50 remaining for sync operations
if [ "$core_remaining" -lt 50 ] || [ "$graphql_remaining" -lt 50 ]; then
echo "can_proceed=false" >> $GITHUB_OUTPUT
echo "⚠️ Rate limits too low. Skipping sync to prevent violations."
exit 0
fi
echo "can_proceed=true" >> $GITHUB_OUTPUT
echo "✅ Rate limits sufficient for sync operation"
# 10-second debounce delay
debounce:
needs: [determine-direction, rate-limit-check]
if: |
needs.determine-direction.outputs.should_sync == 'true' &&
needs.rate-limit-check.outputs.can_proceed == 'true'
runs-on: ubuntu-latest
timeout-minutes: 1
steps:
- name: Debounce Delay
run: |
echo "⏱️ Applying 10-second debounce..."
sleep 10
echo "✅ Debounce complete. Proceeding with sync."
sync-issue-to-project:
needs: [determine-direction, rate-limit-check, debounce]
if: |
needs.determine-direction.outputs.direction == 'issue-to-project' &&
needs.rate-limit-check.outputs.can_proceed == 'true'
runs-on: ubuntu-latest
timeout-minutes: 5
permissions:
contents: read
issues: read
id-token: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Sync Issue to Project Board
uses: anthropics/claude-code-action@v1
env:
GH_TOKEN: ${{ secrets.PROJECTS_TOKEN }}
with:
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
prompt: |
# Issue → Project Board Sync
**Issue**: #${{ github.event.issue.number }} "${{ github.event.issue.title }}"
**State**: ${{ github.event.issue.state }}
**Action**: ${{ github.event.action }}
## Task: Sync issue status to project board
### Step 1: Check if in Project
```bash
PROJECT_ITEM=$(gh api graphql -f query='
query {
repository(owner: "alirezarezvani", name: "claude-skills") {
issue(number: ${{ github.event.issue.number }}) {
projectItems(first: 10) {
nodes {
id
project { number }
}
}
}
}
}
' --jq '.data.repository.issue.projectItems.nodes[] | select(.project.number == 9) | .id')
if [ -z "$PROJECT_ITEM" ]; then
echo "Adding to project..."
gh project item-add 9 --owner alirezarezvani --url ${{ github.event.issue.html_url }}
sleep 2
PROJECT_ITEM=$(gh api graphql -f query='
query {
repository(owner: "alirezarezvani", name: "claude-skills") {
issue(number: ${{ github.event.issue.number }}) {
projectItems(first: 10) {
nodes {
id
project { number }
}
}
}
}
}
' --jq '.data.repository.issue.projectItems.nodes[] | select(.project.number == 9) | .id')
fi
echo "Project Item ID: $PROJECT_ITEM"
```
### Step 2: Determine Target Status
```bash
LABELS=$(gh issue view ${{ github.event.issue.number }} --json labels --jq '[.labels[].name] | join(",")')
ISSUE_STATE="${{ github.event.issue.state }}"
# Priority order: closed state > status labels > default
if [ "$ISSUE_STATE" = "closed" ]; then
TARGET_STATUS="Done"
elif echo "$LABELS" | grep -q "status: done"; then
TARGET_STATUS="Done"
elif echo "$LABELS" | grep -q "status: in-review"; then
TARGET_STATUS="In Review"
elif echo "$LABELS" | grep -q "status: in-progress"; then
TARGET_STATUS="In Progress"
elif echo "$LABELS" | grep -q "status: ready"; then
TARGET_STATUS="Ready"
elif echo "$LABELS" | grep -q "status: backlog"; then
TARGET_STATUS="Backlog"
elif echo "$LABELS" | grep -q "status: triage"; then
TARGET_STATUS="To triage"
else
TARGET_STATUS=$([ "$ISSUE_STATE" = "open" ] && echo "To triage" || echo "Done")
fi
echo "Target Status: $TARGET_STATUS"
```
### Step 3: Get Project IDs
```bash
PROJECT_DATA=$(gh api graphql -f query='
query {
user(login: "alirezarezvani") {
projectV2(number: 9) {
id
fields(first: 20) {
nodes {
... on ProjectV2SingleSelectField {
id
name
options {
id
name
}
}
}
}
}
}
}
')
PROJECT_ID=$(echo "$PROJECT_DATA" | jq -r '.data.user.projectV2.id')
STATUS_FIELD_ID=$(echo "$PROJECT_DATA" | \
jq -r '.data.user.projectV2.fields.nodes[] | select(.name == "Status") | .id')
STATUS_OPTION_ID=$(echo "$PROJECT_DATA" | jq -r --arg status "$TARGET_STATUS" \
'.data.user.projectV2.fields.nodes[] | select(.name == "Status") | .options[] | select(.name == $status) | .id')
```
### Step 4: Update Project Board
```bash
if [ -n "$PROJECT_ITEM" ] && [ -n "$STATUS_OPTION_ID" ]; then
gh api graphql -f query='
mutation {
updateProjectV2ItemFieldValue(
input: {
projectId: "'"$PROJECT_ID"'"
itemId: "'"$PROJECT_ITEM"'"
fieldId: "'"$STATUS_FIELD_ID"'"
value: { singleSelectOptionId: "'"$STATUS_OPTION_ID"'" }
}
) {
projectV2Item { id }
}
}
'
echo "✅ Project board updated to: $TARGET_STATUS"
else
echo "⚠️ Could not update (missing IDs)"
fi
```
## Rules
- DO NOT comment on issue (prevents notification spam)
- DO NOT modify issue labels (prevents sync loop)
- Only update project board status
claude_args: '--allowed-tools "Bash(gh issue:*),Bash(gh api:*),Bash(gh project:*),Bash(echo:*),Bash(sleep:*)"'
sync-project-to-issue:
needs: [determine-direction, rate-limit-check, debounce]
if: |
needs.determine-direction.outputs.direction == 'project-to-issue' &&
needs.rate-limit-check.outputs.can_proceed == 'true'
runs-on: ubuntu-latest
timeout-minutes: 5
permissions:
contents: read
issues: write
id-token: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Sync Project Board to Issue
uses: anthropics/claude-code-action@v1
env:
GH_TOKEN: ${{ secrets.PROJECTS_TOKEN }}
with:
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
prompt: |
# Project Board → Issue Sync
**Project Item**: ${{ github.event.projects_v2_item.node_id }}
**Content**: ${{ github.event.projects_v2_item.content_node_id }}
**Changed By**: @${{ github.event.sender.login }}
## Task: Sync project board status to issue
### Step 1: Get Issue Number
```bash
CONTENT_ID="${{ github.event.projects_v2_item.content_node_id }}"
ISSUE_DATA=$(gh api graphql -f query='
query {
node(id: "${{ github.event.projects_v2_item.node_id }}") {
... on ProjectV2Item {
content {
... on Issue {
number
url
state
title
}
}
}
}
}
')
ISSUE_NUMBER=$(echo "$ISSUE_DATA" | jq -r '.data.node.content.number')
if [ -z "$ISSUE_NUMBER" ] || [ "$ISSUE_NUMBER" = "null" ]; then
echo "⏭️ Not an issue (might be PR or other content)"
exit 0
fi
echo "Issue Number: $ISSUE_NUMBER"
```
### Step 2: Get Project Status
```bash
STATUS=$(gh api graphql -f query='
query {
node(id: "${{ github.event.projects_v2_item.node_id }}") {
... on ProjectV2Item {
fieldValues(first: 20) {
nodes {
... on ProjectV2ItemFieldSingleSelectValue {
name
field {
... on ProjectV2SingleSelectField {
name
}
}
}
}
}
}
}
}
' --jq '.data.node.fieldValues.nodes[] | select(.field.name == "Status") | .name')
if [ -z "$STATUS" ]; then
echo "⏭️ No status field found"
exit 0
fi
echo "Project Status: $STATUS"
```
### Step 3: Map Status to Label
```bash
case "$STATUS" in
"To triage") NEW_LABEL="status: triage" ;;
"Backlog") NEW_LABEL="status: backlog" ;;
"Ready") NEW_LABEL="status: ready" ;;
"In Progress") NEW_LABEL="status: in-progress" ;;
"In Review") NEW_LABEL="status: in-review" ;;
"Done") NEW_LABEL="status: done" ;;
*)
echo "⏭️ Unknown status: $STATUS"
exit 0
;;
esac
echo "Target Label: $NEW_LABEL"
```
### Step 4: Update Issue Labels
```bash
CURRENT_LABELS=$(gh issue view $ISSUE_NUMBER --json labels --jq '[.labels[].name] | join(",")')
# Remove all status: labels
for label in "status: triage" "status: backlog" "status: ready" "status: in-progress" "status: in-review" "status: done"; do
if echo "$CURRENT_LABELS" | grep -q "$label"; then
gh issue edit $ISSUE_NUMBER --remove-label "$label" 2>/dev/null || true
fi
done
# Add new status label
gh issue edit $ISSUE_NUMBER --add-label "$NEW_LABEL"
echo "✅ Label updated to: $NEW_LABEL"
```
### Step 5: Handle Issue State
```bash
CURRENT_STATE=$(gh issue view $ISSUE_NUMBER --json state --jq '.state')
if [ "$STATUS" = "Done" ] && [ "$CURRENT_STATE" = "OPEN" ]; then
gh issue close $ISSUE_NUMBER --reason completed
echo "✅ Issue closed (moved to Done)"
elif [ "$STATUS" != "Done" ] && [ "$CURRENT_STATE" = "CLOSED" ]; then
gh issue reopen $ISSUE_NUMBER
echo "✅ Issue reopened (moved from Done)"
fi
```
### Step 6: Silent Completion
```bash
echo "✅ Sync complete: Issue #$ISSUE_NUMBER updated to $STATUS"
```
## Rules
- DO NOT comment on issue (prevents notification spam)
- DO NOT modify project board (prevents sync loop)
- Only update issue labels and state
claude_args: '--allowed-tools "Bash(gh issue:*),Bash(gh api:*),Bash(echo:*)"'