Add 260+ Claude Code skills from skills.sh
Complete collection of AI agent skills including: - Frontend Development (Vue, React, Next.js, Three.js) - Backend Development (NestJS, FastAPI, Node.js) - Mobile Development (React Native, Expo) - Testing (E2E, frontend, webapp) - DevOps (GitHub Actions, CI/CD) - Marketing (SEO, copywriting, analytics) - Security (binary analysis, vulnerability scanning) - And many more... Synchronized from: https://skills.sh/ Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
846
github-workflow-automation/skill.md
Normal file
846
github-workflow-automation/skill.md
Normal file
@@ -0,0 +1,846 @@
|
||||
---
|
||||
name: github-workflow-automation
|
||||
description: "Automate GitHub workflows with AI assistance. Includes PR reviews, issue triage, CI/CD integration, and Git operations. Use when automating GitHub workflows, setting up PR review automation, creating GitHub Actions, or triaging issues."
|
||||
---
|
||||
|
||||
# 🔧 GitHub Workflow Automation
|
||||
|
||||
> Patterns for automating GitHub workflows with AI assistance, inspired by [Gemini CLI](https://github.com/google-gemini/gemini-cli) and modern DevOps practices.
|
||||
|
||||
## When to Use This Skill
|
||||
|
||||
Use this skill when:
|
||||
|
||||
- Automating PR reviews with AI
|
||||
- Setting up issue triage automation
|
||||
- Creating GitHub Actions workflows
|
||||
- Integrating AI into CI/CD pipelines
|
||||
- Automating Git operations (rebases, cherry-picks)
|
||||
|
||||
---
|
||||
|
||||
## 1. Automated PR Review
|
||||
|
||||
### 1.1 PR Review Action
|
||||
|
||||
```yaml
|
||||
# .github/workflows/ai-review.yml
|
||||
name: AI Code Review
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, synchronize]
|
||||
|
||||
jobs:
|
||||
review:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Get changed files
|
||||
id: changed
|
||||
run: |
|
||||
files=$(git diff --name-only origin/${{ github.base_ref }}...HEAD)
|
||||
echo "files<<EOF" >> $GITHUB_OUTPUT
|
||||
echo "$files" >> $GITHUB_OUTPUT
|
||||
echo "EOF" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Get diff
|
||||
id: diff
|
||||
run: |
|
||||
diff=$(git diff origin/${{ github.base_ref }}...HEAD)
|
||||
echo "diff<<EOF" >> $GITHUB_OUTPUT
|
||||
echo "$diff" >> $GITHUB_OUTPUT
|
||||
echo "EOF" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: AI Review
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const { Anthropic } = require('@anthropic-ai/sdk');
|
||||
const client = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY });
|
||||
|
||||
const response = await client.messages.create({
|
||||
model: "claude-3-sonnet-20240229",
|
||||
max_tokens: 4096,
|
||||
messages: [{
|
||||
role: "user",
|
||||
content: `Review this PR diff and provide feedback:
|
||||
|
||||
Changed files: ${{ steps.changed.outputs.files }}
|
||||
|
||||
Diff:
|
||||
${{ steps.diff.outputs.diff }}
|
||||
|
||||
Provide:
|
||||
1. Summary of changes
|
||||
2. Potential issues or bugs
|
||||
3. Suggestions for improvement
|
||||
4. Security concerns if any
|
||||
|
||||
Format as GitHub markdown.`
|
||||
}]
|
||||
});
|
||||
|
||||
await github.rest.pulls.createReview({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number: context.issue.number,
|
||||
body: response.content[0].text,
|
||||
event: 'COMMENT'
|
||||
});
|
||||
env:
|
||||
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
|
||||
```
|
||||
|
||||
### 1.2 Review Comment Patterns
|
||||
|
||||
````markdown
|
||||
# AI Review Structure
|
||||
|
||||
## 📋 Summary
|
||||
|
||||
Brief description of what this PR does.
|
||||
|
||||
## ✅ What looks good
|
||||
|
||||
- Well-structured code
|
||||
- Good test coverage
|
||||
- Clear naming conventions
|
||||
|
||||
## ⚠️ Potential Issues
|
||||
|
||||
1. **Line 42**: Possible null pointer exception
|
||||
```javascript
|
||||
// Current
|
||||
user.profile.name;
|
||||
// Suggested
|
||||
user?.profile?.name ?? "Unknown";
|
||||
```
|
||||
````
|
||||
|
||||
2. **Line 78**: Consider error handling
|
||||
```javascript
|
||||
// Add try-catch or .catch()
|
||||
```
|
||||
|
||||
## 💡 Suggestions
|
||||
|
||||
- Consider extracting the validation logic into a separate function
|
||||
- Add JSDoc comments for public methods
|
||||
|
||||
## 🔒 Security Notes
|
||||
|
||||
- No sensitive data exposure detected
|
||||
- API key handling looks correct
|
||||
|
||||
````
|
||||
|
||||
### 1.3 Focused Reviews
|
||||
|
||||
```yaml
|
||||
# Review only specific file types
|
||||
- name: Filter code files
|
||||
run: |
|
||||
files=$(git diff --name-only origin/${{ github.base_ref }}...HEAD | \
|
||||
grep -E '\.(ts|tsx|js|jsx|py|go)$' || true)
|
||||
echo "code_files=$files" >> $GITHUB_OUTPUT
|
||||
|
||||
# Review with context
|
||||
- name: AI Review with context
|
||||
run: |
|
||||
# Include relevant context files
|
||||
context=""
|
||||
for file in ${{ steps.changed.outputs.files }}; do
|
||||
if [[ -f "$file" ]]; then
|
||||
context+="=== $file ===\n$(cat $file)\n\n"
|
||||
fi
|
||||
done
|
||||
|
||||
# Send to AI with full file context
|
||||
````
|
||||
|
||||
---
|
||||
|
||||
## 2. Issue Triage Automation
|
||||
|
||||
### 2.1 Auto-label Issues
|
||||
|
||||
```yaml
|
||||
# .github/workflows/issue-triage.yml
|
||||
name: Issue Triage
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [opened]
|
||||
|
||||
jobs:
|
||||
triage:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write
|
||||
|
||||
steps:
|
||||
- name: Analyze issue
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const issue = context.payload.issue;
|
||||
|
||||
// Call AI to analyze
|
||||
const analysis = await analyzeIssue(issue.title, issue.body);
|
||||
|
||||
// Apply labels
|
||||
const labels = [];
|
||||
|
||||
if (analysis.type === 'bug') {
|
||||
labels.push('bug');
|
||||
if (analysis.severity === 'high') labels.push('priority: high');
|
||||
} else if (analysis.type === 'feature') {
|
||||
labels.push('enhancement');
|
||||
} else if (analysis.type === 'question') {
|
||||
labels.push('question');
|
||||
}
|
||||
|
||||
if (analysis.area) {
|
||||
labels.push(`area: ${analysis.area}`);
|
||||
}
|
||||
|
||||
await github.rest.issues.addLabels({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issue.number,
|
||||
labels: labels
|
||||
});
|
||||
|
||||
// Add initial response
|
||||
if (analysis.type === 'bug' && !analysis.hasReproSteps) {
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issue.number,
|
||||
body: `Thanks for reporting this issue!
|
||||
|
||||
To help us investigate, could you please provide:
|
||||
- Steps to reproduce the issue
|
||||
- Expected behavior
|
||||
- Actual behavior
|
||||
- Environment (OS, version, etc.)
|
||||
|
||||
This will help us resolve your issue faster. 🙏`
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
### 2.2 Issue Analysis Prompt
|
||||
|
||||
```typescript
|
||||
const TRIAGE_PROMPT = `
|
||||
Analyze this GitHub issue and classify it:
|
||||
|
||||
Title: {title}
|
||||
Body: {body}
|
||||
|
||||
Return JSON with:
|
||||
{
|
||||
"type": "bug" | "feature" | "question" | "docs" | "other",
|
||||
"severity": "low" | "medium" | "high" | "critical",
|
||||
"area": "frontend" | "backend" | "api" | "docs" | "ci" | "other",
|
||||
"summary": "one-line summary",
|
||||
"hasReproSteps": boolean,
|
||||
"isFirstContribution": boolean,
|
||||
"suggestedLabels": ["label1", "label2"],
|
||||
"suggestedAssignees": ["username"] // based on area expertise
|
||||
}
|
||||
`;
|
||||
```
|
||||
|
||||
### 2.3 Stale Issue Management
|
||||
|
||||
```yaml
|
||||
# .github/workflows/stale.yml
|
||||
name: Manage Stale Issues
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 0 * * *" # Daily
|
||||
|
||||
jobs:
|
||||
stale:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/stale@v9
|
||||
with:
|
||||
stale-issue-message: |
|
||||
This issue has been automatically marked as stale because it has not had
|
||||
recent activity. It will be closed in 14 days if no further activity occurs.
|
||||
|
||||
If this issue is still relevant:
|
||||
- Add a comment with an update
|
||||
- Remove the `stale` label
|
||||
|
||||
Thank you for your contributions! 🙏
|
||||
|
||||
stale-pr-message: |
|
||||
This PR has been automatically marked as stale. Please update it or it
|
||||
will be closed in 14 days.
|
||||
|
||||
days-before-stale: 60
|
||||
days-before-close: 14
|
||||
stale-issue-label: "stale"
|
||||
stale-pr-label: "stale"
|
||||
exempt-issue-labels: "pinned,security,in-progress"
|
||||
exempt-pr-labels: "pinned,security"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. CI/CD Integration
|
||||
|
||||
### 3.1 Smart Test Selection
|
||||
|
||||
```yaml
|
||||
# .github/workflows/smart-tests.yml
|
||||
name: Smart Test Selection
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
test_suites: ${{ steps.analyze.outputs.suites }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Analyze changes
|
||||
id: analyze
|
||||
run: |
|
||||
# Get changed files
|
||||
changed=$(git diff --name-only origin/${{ github.base_ref }}...HEAD)
|
||||
|
||||
# Determine which test suites to run
|
||||
suites="[]"
|
||||
|
||||
if echo "$changed" | grep -q "^src/api/"; then
|
||||
suites=$(echo $suites | jq '. + ["api"]')
|
||||
fi
|
||||
|
||||
if echo "$changed" | grep -q "^src/frontend/"; then
|
||||
suites=$(echo $suites | jq '. + ["frontend"]')
|
||||
fi
|
||||
|
||||
if echo "$changed" | grep -q "^src/database/"; then
|
||||
suites=$(echo $suites | jq '. + ["database", "api"]')
|
||||
fi
|
||||
|
||||
# If nothing specific, run all
|
||||
if [ "$suites" = "[]" ]; then
|
||||
suites='["all"]'
|
||||
fi
|
||||
|
||||
echo "suites=$suites" >> $GITHUB_OUTPUT
|
||||
|
||||
test:
|
||||
needs: analyze
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
suite: ${{ fromJson(needs.analyze.outputs.test_suites) }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
if [ "${{ matrix.suite }}" = "all" ]; then
|
||||
npm test
|
||||
else
|
||||
npm test -- --suite ${{ matrix.suite }}
|
||||
fi
|
||||
```
|
||||
|
||||
### 3.2 Deployment with AI Validation
|
||||
|
||||
```yaml
|
||||
# .github/workflows/deploy.yml
|
||||
name: Deploy with AI Validation
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
|
||||
jobs:
|
||||
validate:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Get deployment changes
|
||||
id: changes
|
||||
run: |
|
||||
# Get commits since last deployment
|
||||
last_deploy=$(git describe --tags --abbrev=0 2>/dev/null || echo "")
|
||||
if [ -n "$last_deploy" ]; then
|
||||
changes=$(git log --oneline $last_deploy..HEAD)
|
||||
else
|
||||
changes=$(git log --oneline -10)
|
||||
fi
|
||||
echo "changes<<EOF" >> $GITHUB_OUTPUT
|
||||
echo "$changes" >> $GITHUB_OUTPUT
|
||||
echo "EOF" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: AI Risk Assessment
|
||||
id: assess
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
// Analyze changes for deployment risk
|
||||
const prompt = `
|
||||
Analyze these changes for deployment risk:
|
||||
|
||||
${process.env.CHANGES}
|
||||
|
||||
Return JSON:
|
||||
{
|
||||
"riskLevel": "low" | "medium" | "high",
|
||||
"concerns": ["concern1", "concern2"],
|
||||
"recommendations": ["rec1", "rec2"],
|
||||
"requiresManualApproval": boolean
|
||||
}
|
||||
`;
|
||||
|
||||
// Call AI and parse response
|
||||
const analysis = await callAI(prompt);
|
||||
|
||||
if (analysis.riskLevel === 'high') {
|
||||
core.setFailed('High-risk deployment detected. Manual review required.');
|
||||
}
|
||||
|
||||
return analysis;
|
||||
env:
|
||||
CHANGES: ${{ steps.changes.outputs.changes }}
|
||||
|
||||
deploy:
|
||||
needs: validate
|
||||
runs-on: ubuntu-latest
|
||||
environment: production
|
||||
steps:
|
||||
- name: Deploy
|
||||
run: |
|
||||
echo "Deploying to production..."
|
||||
# Deployment commands here
|
||||
```
|
||||
|
||||
### 3.3 Rollback Automation
|
||||
|
||||
```yaml
|
||||
# .github/workflows/rollback.yml
|
||||
name: Automated Rollback
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
reason:
|
||||
description: "Reason for rollback"
|
||||
required: true
|
||||
|
||||
jobs:
|
||||
rollback:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Find last stable version
|
||||
id: stable
|
||||
run: |
|
||||
# Find last successful deployment
|
||||
stable=$(git tag -l 'v*' --sort=-version:refname | head -1)
|
||||
echo "version=$stable" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Rollback
|
||||
run: |
|
||||
git checkout ${{ steps.stable.outputs.version }}
|
||||
# Deploy stable version
|
||||
npm run deploy
|
||||
|
||||
- name: Notify team
|
||||
uses: slackapi/slack-github-action@v1
|
||||
with:
|
||||
payload: |
|
||||
{
|
||||
"text": "🔄 Production rolled back to ${{ steps.stable.outputs.version }}",
|
||||
"blocks": [
|
||||
{
|
||||
"type": "section",
|
||||
"text": {
|
||||
"type": "mrkdwn",
|
||||
"text": "*Rollback executed*\n• Version: `${{ steps.stable.outputs.version }}`\n• Reason: ${{ inputs.reason }}\n• Triggered by: ${{ github.actor }}"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. Git Operations
|
||||
|
||||
### 4.1 Automated Rebasing
|
||||
|
||||
```yaml
|
||||
# .github/workflows/auto-rebase.yml
|
||||
name: Auto Rebase
|
||||
|
||||
on:
|
||||
issue_comment:
|
||||
types: [created]
|
||||
|
||||
jobs:
|
||||
rebase:
|
||||
if: github.event.issue.pull_request && contains(github.event.comment.body, '/rebase')
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Setup Git
|
||||
run: |
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "github-actions[bot]@users.noreply.github.com"
|
||||
|
||||
- name: Rebase PR
|
||||
run: |
|
||||
# Fetch PR branch
|
||||
gh pr checkout ${{ github.event.issue.number }}
|
||||
|
||||
# Rebase onto main
|
||||
git fetch origin main
|
||||
git rebase origin/main
|
||||
|
||||
# Force push
|
||||
git push --force-with-lease
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Comment result
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
body: '✅ Successfully rebased onto main!'
|
||||
})
|
||||
```
|
||||
|
||||
### 4.2 Smart Cherry-Pick
|
||||
|
||||
```typescript
|
||||
// AI-assisted cherry-pick that handles conflicts
|
||||
async function smartCherryPick(commitHash: string, targetBranch: string) {
|
||||
// Get commit info
|
||||
const commitInfo = await exec(`git show ${commitHash} --stat`);
|
||||
|
||||
// Check for potential conflicts
|
||||
const targetDiff = await exec(
|
||||
`git diff ${targetBranch}...HEAD -- ${affectedFiles}`
|
||||
);
|
||||
|
||||
// AI analysis
|
||||
const analysis = await ai.analyze(`
|
||||
I need to cherry-pick this commit to ${targetBranch}:
|
||||
|
||||
${commitInfo}
|
||||
|
||||
Current state of affected files on ${targetBranch}:
|
||||
${targetDiff}
|
||||
|
||||
Will there be conflicts? If so, suggest resolution strategy.
|
||||
`);
|
||||
|
||||
if (analysis.willConflict) {
|
||||
// Create branch for manual resolution
|
||||
await exec(
|
||||
`git checkout -b cherry-pick-${commitHash.slice(0, 7)} ${targetBranch}`
|
||||
);
|
||||
const result = await exec(`git cherry-pick ${commitHash}`, {
|
||||
allowFail: true,
|
||||
});
|
||||
|
||||
if (result.failed) {
|
||||
// AI-assisted conflict resolution
|
||||
const conflicts = await getConflicts();
|
||||
for (const conflict of conflicts) {
|
||||
const resolution = await ai.resolveConflict(conflict);
|
||||
await applyResolution(conflict.file, resolution);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
await exec(`git checkout ${targetBranch}`);
|
||||
await exec(`git cherry-pick ${commitHash}`);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 4.3 Branch Cleanup
|
||||
|
||||
```yaml
|
||||
# .github/workflows/branch-cleanup.yml
|
||||
name: Branch Cleanup
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 0 * * 0' # Weekly
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
cleanup:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Find stale branches
|
||||
id: stale
|
||||
run: |
|
||||
# Branches not updated in 30 days
|
||||
stale=$(git for-each-ref --sort=-committerdate refs/remotes/origin \
|
||||
--format='%(refname:short) %(committerdate:relative)' | \
|
||||
grep -E '[3-9][0-9]+ days|[0-9]+ months|[0-9]+ years' | \
|
||||
grep -v 'origin/main\|origin/develop' | \
|
||||
cut -d' ' -f1 | sed 's|origin/||')
|
||||
|
||||
echo "branches<<EOF" >> $GITHUB_OUTPUT
|
||||
echo "$stale" >> $GITHUB_OUTPUT
|
||||
echo "EOF" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Create cleanup PR
|
||||
if: steps.stale.outputs.branches != ''
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const branches = `${{ steps.stale.outputs.branches }}`.split('\n').filter(Boolean);
|
||||
|
||||
const body = `## 🧹 Stale Branch Cleanup
|
||||
|
||||
The following branches haven't been updated in over 30 days:
|
||||
|
||||
${branches.map(b => `- \`${b}\``).join('\n')}
|
||||
|
||||
### Actions:
|
||||
- [ ] Review each branch
|
||||
- [ ] Delete branches that are no longer needed
|
||||
- Comment \`/keep branch-name\` to preserve specific branches
|
||||
`;
|
||||
|
||||
await github.rest.issues.create({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
title: 'Stale Branch Cleanup',
|
||||
body: body,
|
||||
labels: ['housekeeping']
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. On-Demand Assistance
|
||||
|
||||
### 5.1 @mention Bot
|
||||
|
||||
```yaml
|
||||
# .github/workflows/mention-bot.yml
|
||||
name: AI Mention Bot
|
||||
|
||||
on:
|
||||
issue_comment:
|
||||
types: [created]
|
||||
pull_request_review_comment:
|
||||
types: [created]
|
||||
|
||||
jobs:
|
||||
respond:
|
||||
if: contains(github.event.comment.body, '@ai-helper')
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Extract question
|
||||
id: question
|
||||
run: |
|
||||
# Extract text after @ai-helper
|
||||
question=$(echo "${{ github.event.comment.body }}" | sed 's/.*@ai-helper//')
|
||||
echo "question=$question" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Get context
|
||||
id: context
|
||||
run: |
|
||||
if [ "${{ github.event.issue.pull_request }}" != "" ]; then
|
||||
# It's a PR - get diff
|
||||
gh pr diff ${{ github.event.issue.number }} > context.txt
|
||||
else
|
||||
# It's an issue - get description
|
||||
gh issue view ${{ github.event.issue.number }} --json body -q .body > context.txt
|
||||
fi
|
||||
echo "context=$(cat context.txt)" >> $GITHUB_OUTPUT
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: AI Response
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const response = await ai.chat(`
|
||||
Context: ${process.env.CONTEXT}
|
||||
|
||||
Question: ${process.env.QUESTION}
|
||||
|
||||
Provide a helpful, specific answer. Include code examples if relevant.
|
||||
`);
|
||||
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
body: response
|
||||
});
|
||||
env:
|
||||
CONTEXT: ${{ steps.context.outputs.context }}
|
||||
QUESTION: ${{ steps.question.outputs.question }}
|
||||
```
|
||||
|
||||
### 5.2 Command Patterns
|
||||
|
||||
```markdown
|
||||
## Available Commands
|
||||
|
||||
| Command | Description |
|
||||
| :------------------- | :-------------------------- |
|
||||
| `@ai-helper explain` | Explain the code in this PR |
|
||||
| `@ai-helper review` | Request AI code review |
|
||||
| `@ai-helper fix` | Suggest fixes for issues |
|
||||
| `@ai-helper test` | Generate test cases |
|
||||
| `@ai-helper docs` | Generate documentation |
|
||||
| `/rebase` | Rebase PR onto main |
|
||||
| `/update` | Update PR branch from main |
|
||||
| `/approve` | Mark as approved by bot |
|
||||
| `/label bug` | Add 'bug' label |
|
||||
| `/assign @user` | Assign to user |
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. Repository Configuration
|
||||
|
||||
### 6.1 CODEOWNERS
|
||||
|
||||
```
|
||||
# .github/CODEOWNERS
|
||||
|
||||
# Global owners
|
||||
* @org/core-team
|
||||
|
||||
# Frontend
|
||||
/src/frontend/ @org/frontend-team
|
||||
*.tsx @org/frontend-team
|
||||
*.css @org/frontend-team
|
||||
|
||||
# Backend
|
||||
/src/api/ @org/backend-team
|
||||
/src/database/ @org/backend-team
|
||||
|
||||
# Infrastructure
|
||||
/.github/ @org/devops-team
|
||||
/terraform/ @org/devops-team
|
||||
Dockerfile @org/devops-team
|
||||
|
||||
# Docs
|
||||
/docs/ @org/docs-team
|
||||
*.md @org/docs-team
|
||||
|
||||
# Security-sensitive
|
||||
/src/auth/ @org/security-team
|
||||
/src/crypto/ @org/security-team
|
||||
```
|
||||
|
||||
### 6.2 Branch Protection
|
||||
|
||||
```yaml
|
||||
# Set up via GitHub API
|
||||
- name: Configure branch protection
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
await github.rest.repos.updateBranchProtection({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
branch: 'main',
|
||||
required_status_checks: {
|
||||
strict: true,
|
||||
contexts: ['test', 'lint', 'ai-review']
|
||||
},
|
||||
enforce_admins: true,
|
||||
required_pull_request_reviews: {
|
||||
required_approving_review_count: 1,
|
||||
require_code_owner_reviews: true,
|
||||
dismiss_stale_reviews: true
|
||||
},
|
||||
restrictions: null,
|
||||
required_linear_history: true,
|
||||
allow_force_pushes: false,
|
||||
allow_deletions: false
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Security
|
||||
|
||||
- [ ] Store API keys in GitHub Secrets
|
||||
- [ ] Use minimal permissions in workflows
|
||||
- [ ] Validate all inputs
|
||||
- [ ] Don't expose sensitive data in logs
|
||||
|
||||
### Performance
|
||||
|
||||
- [ ] Cache dependencies
|
||||
- [ ] Use matrix builds for parallel testing
|
||||
- [ ] Skip unnecessary jobs with path filters
|
||||
- [ ] Use self-hosted runners for heavy workloads
|
||||
|
||||
### Reliability
|
||||
|
||||
- [ ] Add timeouts to jobs
|
||||
- [ ] Handle rate limits gracefully
|
||||
- [ ] Implement retry logic
|
||||
- [ ] Have rollback procedures
|
||||
|
||||
---
|
||||
|
||||
## Resources
|
||||
|
||||
- [Gemini CLI GitHub Action](https://github.com/google-github-actions/run-gemini-cli)
|
||||
- [GitHub Actions Documentation](https://docs.github.com/en/actions)
|
||||
- [GitHub REST API](https://docs.github.com/en/rest)
|
||||
- [CODEOWNERS Syntax](https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners)
|
||||
Reference in New Issue
Block a user