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>
847 lines
21 KiB
Markdown
847 lines
21 KiB
Markdown
---
|
|
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)
|