Skip to content

feat(skill): make aso_skill a real, tested, installable Python package #12

feat(skill): make aso_skill a real, tested, installable Python package

feat(skill): make aso_skill a real, tested, installable Python package #12

name: Claude Code Review
# Runs on every PR to `dev` and `main` to provide AI-driven review feedback
# and size-labeling. Heavier review happens for PRs to dev; main only sees
# minimal validation via claude-main-check.yml.
on:
pull_request:
types: [opened, synchronize, reopened]
branches: [dev, main]
permissions:
contents: read
pull-requests: write
issues: write
id-token: write
concurrency:
group: claude-code-review-${{ github.event.pull_request.number }}
cancel-in-progress: true
jobs:
pr-labeling:
name: Label PR Size
runs-on: ubuntu-latest
steps:
- name: Label PR by size
uses: actions/github-script@v7
with:
script: |
const pr = context.payload.pull_request;
const changes = (pr.additions || 0) + (pr.deletions || 0);
const sizeBuckets = [
{ name: 'size: XS', max: 50, color: '00ff7f', description: 'Tiny PR (<50 changes)' },
{ name: 'size: S', max: 200, color: '7fff00', description: 'Small PR (50-199 changes)' },
{ name: 'size: M', max: 500, color: 'ffff00', description: 'Medium PR (200-499 changes)' },
{ name: 'size: L', max: 1000, color: 'ffa500', description: 'Large PR (500-999 changes)' },
{ name: 'size: XL', max: Infinity, color: 'ff0000', description: 'Extra large PR (>=1000 changes)' },
];
const bucket = sizeBuckets.find(b => changes < b.max);
// Ensure the label exists (idempotent)
try {
await github.rest.issues.getLabel({
owner: context.repo.owner,
repo: context.repo.repo,
name: bucket.name,
});
} catch (e) {
if (e.status === 404) {
await github.rest.issues.createLabel({
owner: context.repo.owner,
repo: context.repo.repo,
name: bucket.name,
color: bucket.color,
description: bucket.description,
});
} else {
throw e;
}
}
// Remove any stale size labels
const { data: labels } = await github.rest.issues.listLabelsOnIssue({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: pr.number,
});
for (const label of labels) {
if (label.name.startsWith('size: ') && label.name !== bucket.name) {
await github.rest.issues.removeLabel({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: pr.number,
name: label.name,
});
}
}
// Add the new size label
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: pr.number,
labels: [bucket.name],
});
core.info(`Labeled PR #${pr.number} as ${bucket.name} (${changes} changes)`);
if (changes >= 500) {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: pr.number,
body: `**Large PR alert**: this PR has ${changes} changes. Consider splitting it into smaller PRs (<200 changes) for faster review and fewer conflicts.`,
});
}
claude-review:
name: Claude Code Review
runs-on: ubuntu-latest
# Heavier review only on PRs to dev. main gets minimal validation in claude-main-check.yml.
if: github.event.pull_request.base.ref == 'dev'
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Run Claude Code Review
id: claude-review
uses: anthropics/claude-code-action@v1
with:
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
prompt: |
REPO: ${{ github.repository }}
PR NUMBER: ${{ github.event.pull_request.number }}
Review this ASO skill PR. Be concise and actionable.
ASO-specific concerns:
- Character limit validation
(Apple: title 30, subtitle 30, keywords 100; Google: title 50, short desc 80)
- Platform-specific logic correctness (Apple App Store vs Google Play Store)
- Keyword analysis accuracy / relevance scoring
- Metadata optimization quality
- No external dependencies (standard library only)
Code quality:
- PEP 8 (ruff)
- Type hints + docstrings for public functions
- Error handling + edge cases
- Performance (especially iTunes API calls)
Security:
- No hardcoded credentials or API keys
- Safe URL handling and input validation
- Proper data sanitization
Documentation:
- README updated for feature changes
- CHANGELOG.md updated following Keep a Changelog
- Inline comments for complex ASO logic
Use CLAUDE.md for project context. Post your review with `gh pr comment`.
claude_args: '--allowed-tools "Bash(gh issue view:*),Bash(gh issue list:*),Bash(gh pr comment:*),Bash(gh pr diff:*),Bash(gh pr view:*),Bash(gh pr list:*),Bash(gh search:*)"'