ci: use docker/cagent-action/.github/workflows/review-pr.yml

Signed-off-by: David Karlsson <35727626+dvdksn@users.noreply.github.com>
This commit is contained in:
David Karlsson
2026-02-11 15:55:30 +01:00
parent 88db8a35ad
commit 44692cc12f
2 changed files with 49 additions and 548 deletions

View File

@@ -5,7 +5,6 @@ on:
types: [created]
pull_request_review_comment:
types: [created]
# Auto-trigger when PR becomes ready for review (supports forks)
pull_request_target:
types: [ready_for_review, opened]
@@ -15,254 +14,64 @@ permissions:
issues: write
jobs:
# ==========================================================================
# AUTOMATIC REVIEW FOR DOCKER EMPLOYEES
# Triggers when a PR is marked ready for review or opened (non-draft)
# Only runs for Docker org members (supports fork-based workflow)
# ==========================================================================
auto-review:
if: |
github.event_name == 'pull_request_target' &&
!github.event.pull_request.draft
runs-on: ubuntu-latest
steps:
- name: Check if PR author is Docker org member
id: membership
uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7
with:
github-token: ${{ secrets.ORG_MEMBERSHIP_TOKEN }}
script: |
const org = 'docker';
const username = context.payload.pull_request.user.login;
review:
uses: docker/cagent-action/.github/workflows/review-pr.yml@latest
secrets: inherit
with:
add-prompt-files: STYLE.md,COMPONENTS.md
additional-prompt: |
## Documentation Review Focus
try {
await github.rest.orgs.checkMembershipForUser({
org: org,
username: username
});
core.setOutput('is_member', 'true');
console.log(`✅ ${username} is a Docker org member - proceeding with auto-review`);
} catch (error) {
if (error.status === 404 || error.status === 302) {
core.setOutput('is_member', 'false');
console.log(`⏭️ ${username} is not a Docker org member - skipping auto-review`);
} else if (error.status === 401) {
core.setFailed(
'❌ ORG_MEMBERSHIP_TOKEN secret is missing or invalid.\n\n' +
'This secret is required to check Docker org membership for auto-reviews.\n\n' +
'To fix this:\n' +
'1. Create a classic PAT with read:org scope at https://github.com/settings/tokens/new\n' +
'2. Add it as a repository secret named ORG_MEMBERSHIP_TOKEN:\n' +
' gh secret set ORG_MEMBERSHIP_TOKEN --repo docker/docs'
);
} else {
core.setFailed(`Failed to check org membership: ${error.message}`);
}
}
This is Docker's official documentation.
You are reviewing **DOCUMENTATION**, not code. Focus on documentation quality, not software bugs.
# Checkout PR head for content review, but restore agent config from base branch for security
- name: Checkout PR head
if: steps.membership.outputs.is_member == 'true'
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8
with:
fetch-depth: 0
ref: ${{ github.event.pull_request.head.sha }}
**Style guides are available via prompt files (STYLE.md, COMPONENTS.md)** - reference them when evaluating changes.
- name: Restore trusted agent config from base branch
if: steps.membership.outputs.is_member == 'true'
run: |
# Ensure we use the agent config from base branch, not PR head
# This prevents malicious PRs from modifying the agent to exfiltrate secrets
git checkout origin/${{ github.event.pull_request.base.ref }} -- .github/pr-reviewer.yml
## Priority Issues
- name: Restore reviewer memory
if: steps.membership.outputs.is_member == 'true'
uses: actions/cache/restore@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
with:
path: .github/pr-review-memory.db
key: pr-review-memory-${{ github.repository }}-${{ github.run_id }}
restore-keys: |
pr-review-memory-${{ github.repository }}-
### 1. Vendored/Generated Content (CRITICAL - Auto-reject)
Flag if changes touch:
- Any file in `_vendor/` directory (vendored from upstream repos)
- Any YAML file in `data/*/*.yaml` subdirectories (CLI reference data generated from upstream)
- Examples: `data/engine-cli/*.yaml`, `data/buildx/*.yaml`, `data/scout-cli/*.yaml`
- Exception: root-level data/ files are manually maintained (allow edits)
- name: Run Documentation PR Review
if: steps.membership.outputs.is_member == 'true'
uses: docker/cagent-action@latest
with:
cagent-version: v1.22.0
agent: .github/pr-reviewer.yml
prompt: |
Review PR #${{ github.event.pull_request.number }}
### 2. Missing Redirects When Removing/Moving Pages (HIGH)
When a PR removes or moves a page:
- Check if the PR adds an `aliases:` entry in the front matter of the target/replacement page
- Example: If `/old/path.md` is removed, there should be `aliases: ["/old/path/"]` in the new page
**Title:** ${{ github.event.pull_request.title }}
**Author:** ${{ github.event.pull_request.user.login }}
### 3. Markdown Formatting
- Poor markdown syntax (unclosed code blocks, broken lists, indentation issues, etc.)
- Line wrapping over 80 characters (except links, code blocks, tables)
Execute the review pipeline as documented in your instructions.
anthropic-api-key: ${{ secrets.ANTHROPIC_API_KEY }}
### 4. AI-Generated Patterns (HIGH PRIORITY)
Flag AI-isms from STYLE.md:
- Hedge words: simply, just, easily, quickly, seamlessly
- Redundant phrases: "in order to", "allows you to"
- Meta-commentary: "it's worth noting that"
- Marketing speak: "robust", "powerful", "cutting-edge"
- Passive voice: "is used by" → "uses"
- name: Save reviewer memory
if: steps.membership.outputs.is_member == 'true' && always()
uses: actions/cache/save@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
with:
path: .github/pr-review-memory.db
key: pr-review-memory-${{ github.repository }}-${{ github.run_id }}
### 5. Scope Preservation
Does the change match existing document's length and tone?
Check STYLE.md "Scope preservation".
- name: Clean up old memory caches
if: steps.membership.outputs.is_member == 'true' && always()
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
CACHE_PREFIX="pr-review-memory-${{ github.repository }}-"
### 6. Content Accuracy
- Factually incorrect information (wrong commands, wrong API endpoints)
- Broken links or references
- Contradictory content
- Mismatched information (e.g., code example shows X but text says Y)
- Security issues in example code
echo "🧹 Cleaning up old memory caches (keeping 5 most recent)"
### 7. Front Matter & Hugo Syntax
- Missing required fields: `title`, `description`, `keywords`
- Incorrect shortcode syntax (check COMPONENTS.md)
- Invalid component usage
OLD_CACHES=$(gh api "repos/${{ github.repository }}/actions/caches" \
--jq "[.actions_caches | map(select(.key | startswith(\"$CACHE_PREFIX\"))) | sort_by(.created_at) | reverse | .[5:] | .[].id] | .[]" \
2>/dev/null || echo "")
## Severity
- **high**: Will mislead users or break things (incorrect commands, wrong APIs, security issues, editing vendored files, missing redirects)
- **medium**: Could confuse users or violates style guide (AI-isms, scope inflation, unclear instructions, markdown formatting)
- **low**: Minor suggestions (rarely report)
if [ -z "$OLD_CACHES" ]; then
echo "✅ No old caches to clean up"
exit 0
fi
DELETED=0
for CACHE_ID in $OLD_CACHES; do
if gh api "repos/${{ github.repository }}/actions/caches/$CACHE_ID" -X DELETE 2>/dev/null; then
((DELETED++))
fi
done
echo "✅ Deleted $DELETED old cache(s)"
# ==========================================================================
# MANUAL REVIEW PIPELINE
# Triggers when someone comments /review on a PR
# Only runs for Docker org members
# ==========================================================================
run-review:
if: github.event.issue.pull_request && contains(github.event.comment.body, '/review')
runs-on: ubuntu-latest
steps:
- name: Check if commenter is Docker org member
id: membership
uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7
with:
github-token: ${{ secrets.ORG_MEMBERSHIP_TOKEN }}
script: |
const org = 'docker';
const username = context.payload.comment.user.login;
try {
await github.rest.orgs.checkMembershipForUser({
org: org,
username: username
});
core.setOutput('is_member', 'true');
console.log(`✅ ${username} is a Docker org member - proceeding with review`);
} catch (error) {
if (error.status === 404 || error.status === 302) {
core.setOutput('is_member', 'false');
console.log(`⏭️ ${username} is not a Docker org member - ignoring /review command`);
} else if (error.status === 401) {
core.setFailed(
'❌ ORG_MEMBERSHIP_TOKEN secret is missing or invalid.\n\n' +
'This secret is required to check Docker org membership.\n\n' +
'To fix this:\n' +
'1. Create a classic PAT with read:org scope at https://github.com/settings/tokens/new\n' +
'2. Add it as a repository secret named ORG_MEMBERSHIP_TOKEN:\n' +
' gh secret set ORG_MEMBERSHIP_TOKEN --repo docker/docs'
);
} else {
core.setFailed(`Failed to check org membership: ${error.message}`);
}
}
- name: Checkout repository
if: steps.membership.outputs.is_member == 'true'
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8
with:
fetch-depth: 0
- name: Restore trusted agent config from base branch
if: steps.membership.outputs.is_member == 'true'
run: |
# Get the PR's base branch and ensure agent config comes from there
PR_BASE=$(gh api repos/${{ github.repository }}/pulls/${{ github.event.issue.number }} --jq '.base.ref')
git fetch origin "$PR_BASE"
git checkout "origin/$PR_BASE" -- .github/pr-reviewer.yml
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Restore reviewer memory
if: steps.membership.outputs.is_member == 'true'
uses: actions/cache/restore@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
with:
path: .github/pr-review-memory.db
key: pr-review-memory-${{ github.repository }}-${{ github.run_id }}
restore-keys: |
pr-review-memory-${{ github.repository }}-
- name: Run Documentation PR Review
if: steps.membership.outputs.is_member == 'true'
uses: docker/cagent-action@latest
with:
cagent-version: v1.22.0
agent: .github/pr-reviewer.yml
prompt: |
Review PR #${{ github.event.issue.number }}
Triggered manually by @${{ github.event.comment.user.login }}
Execute the review pipeline as documented in your instructions.
anthropic-api-key: ${{ secrets.ANTHROPIC_API_KEY }}
- name: Save reviewer memory
if: steps.membership.outputs.is_member == 'true' && always()
uses: actions/cache/save@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
with:
path: .github/pr-review-memory.db
key: pr-review-memory-${{ github.repository }}-${{ github.run_id }}
- name: Clean up old memory caches
if: steps.membership.outputs.is_member == 'true' && always()
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
CACHE_PREFIX="pr-review-memory-${{ github.repository }}-"
echo "🧹 Cleaning up old memory caches (keeping 5 most recent)"
OLD_CACHES=$(gh api "repos/${{ github.repository }}/actions/caches" \
--jq "[.actions_caches | map(select(.key | startswith(\"$CACHE_PREFIX\"))) | sort_by(.created_at) | reverse | .[5:] | .[].id] | .[]" \
2>/dev/null || echo "")
if [ -z "$OLD_CACHES" ]; then
echo "✅ No old caches to clean up"
exit 0
fi
DELETED=0
for CACHE_ID in $OLD_CACHES; do
if gh api "repos/${{ github.repository }}/actions/caches/$CACHE_ID" -X DELETE 2>/dev/null; then
((DELETED++))
fi
done
echo "✅ Deleted $DELETED old cache(s)"
# ==========================================================================
# LEARN FROM FEEDBACK
# Processes replies to agent review comments for continuous improvement
# ==========================================================================
learn-from-feedback:
if: github.event_name == 'pull_request_review_comment' && github.event.comment.in_reply_to_id
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8
- name: Learn from user feedback
uses: docker/cagent-action/review-pr/learn@latest
with:
anthropic-api-key: ${{ secrets.ANTHROPIC_API_KEY }}
Most issues should be MEDIUM. HIGH is for critical problems only.