-
Notifications
You must be signed in to change notification settings - Fork 8
Examples: Add PR review, multi-repo migration, and security audit use cases #290
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| # PR Review Spawner | ||
|
|
||
| Automatically review open pull requests using an AI agent. The spawner | ||
| discovers PRs with a specific label and creates a Task for each one. The | ||
| agent reads the diff, checks for common issues, and posts a review comment. | ||
|
|
||
| ## How It Works | ||
|
|
||
| 1. A developer opens a PR and adds the `needs-ai-review` label. | ||
| 2. TaskSpawner discovers the labeled PR and creates a Task. | ||
| 3. The agent clones the repo, reads the PR diff and description, and posts | ||
| a review via the `gh` CLI. | ||
| 4. After the review, the agent removes the trigger label and adds | ||
| `ai-reviewed` so it is not picked up again. | ||
|
|
||
| ## Resources | ||
|
|
||
| | File | Description | | ||
| |------|-------------| | ||
| | `workspace.yaml` | Git repo the agent clones | | ||
| | `credentials-secret.yaml` | Agent credentials (OAuth token) | | ||
| | `github-token-secret.yaml` | GitHub token for cloning and `gh` CLI | | ||
| | `agentconfig.yaml` | Review instructions and skill | | ||
| | `taskspawner.yaml` | TaskSpawner watching for labeled PRs | | ||
|
|
||
| ## Setup | ||
|
|
||
| 1. Replace all `# TODO:` placeholders in the YAML files. | ||
| 2. Create the GitHub labels `needs-ai-review` and `ai-reviewed` in your repo. | ||
| 3. Apply all resources: | ||
|
|
||
| ```bash | ||
| kubectl apply -f examples/05-pr-review-spawner/ | ||
| ``` | ||
|
|
||
| 4. Label a PR with `needs-ai-review` and watch the agent pick it up: | ||
|
|
||
| ```bash | ||
| axon get tasks -w | ||
| ``` |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| apiVersion: axon.io/v1alpha1 | ||
| kind: AgentConfig | ||
| metadata: | ||
| name: pr-reviewer-config | ||
| spec: | ||
| agentsMD: | | ||
| You are a code reviewer. Your job is to review pull requests thoroughly | ||
| and leave constructive, actionable feedback. | ||
|
|
||
| Guidelines: | ||
| - Focus on correctness, security, performance, and maintainability. | ||
| - Point out specific lines when suggesting changes. | ||
| - Acknowledge good patterns, not just problems. | ||
| - If the PR looks good, approve it with a short summary of what you checked. | ||
| - Do not nitpick style issues that a linter would catch. | ||
| plugins: | ||
| - name: reviewer | ||
| skills: | ||
| - name: review-pr | ||
| content: | | ||
| --- | ||
| name: review-pr | ||
| description: Review a pull request and post feedback | ||
| --- | ||
| To review a PR: | ||
| 1. Fetch the PR branch: `gh pr checkout <number>` | ||
| 2. Read the diff: `git diff main...HEAD` | ||
| 3. Read the PR description: `gh pr view <number>` | ||
| 4. Read any existing review comments: `gh api repos/{owner}/{repo}/pulls/<number>/comments` | ||
| 5. Post your review: `gh pr review <number> --comment --body "<review>"` | ||
| 6. Swap the labels: `gh pr edit <number> --remove-label needs-ai-review --add-label ai-reviewed` | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| apiVersion: v1 | ||
| kind: Secret | ||
| metadata: | ||
| name: claude-credentials | ||
| type: Opaque | ||
| stringData: | ||
| oauthToken: "" # TODO: replace with your Claude OAuth token |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| apiVersion: v1 | ||
| kind: Secret | ||
| metadata: | ||
| name: github-token | ||
| type: Opaque | ||
| stringData: | ||
| GITHUB_TOKEN: "" # TODO: replace with a GitHub token that has repo scope |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| apiVersion: axon.io/v1alpha1 | ||
| kind: TaskSpawner | ||
| metadata: | ||
| name: pr-reviewer | ||
| spec: | ||
| when: | ||
| githubIssues: | ||
| types: | ||
| - pulls | ||
| labels: | ||
| - needs-ai-review | ||
| excludeLabels: | ||
| - ai-reviewed | ||
| state: open | ||
| taskTemplate: | ||
| type: claude-code | ||
| workspaceRef: | ||
| name: review-workspace | ||
| agentConfigRef: | ||
| name: pr-reviewer-config | ||
| credentials: | ||
| type: oauth | ||
| secretRef: | ||
| name: claude-credentials | ||
| promptTemplate: | | ||
| Review PR #{{.Number}}: {{.Title}} | ||
|
|
||
| Description: | ||
| {{.Body}} | ||
|
|
||
| Steps: | ||
| 1. Check out the PR branch and read the full diff against main. | ||
| 2. /review-pr {{.Number}} | ||
|
|
||
| After reviewing, remove the "needs-ai-review" label and add "ai-reviewed": | ||
| gh pr edit {{.Number}} --remove-label needs-ai-review --add-label ai-reviewed | ||
| ttlSecondsAfterFinished: 3600 | ||
| pollInterval: 5m | ||
| maxConcurrency: 3 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| apiVersion: axon.io/v1alpha1 | ||
| kind: Workspace | ||
| metadata: | ||
| name: review-workspace | ||
| spec: | ||
| repo: https://github.com/your-org/your-repo.git # TODO: replace with your repo | ||
| ref: main | ||
| secretRef: | ||
| name: github-token |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,53 @@ | ||
| # Multi-Repo Migration | ||
|
|
||
| Apply a repetitive change across multiple repositories using parallel agent | ||
| Tasks. This pattern is useful for fleet-wide refactoring, dependency bumps, | ||
| or API migration across microservices. | ||
|
|
||
| ## How It Works | ||
|
|
||
| Each repository gets its own Workspace resource. A single TaskSpawner on | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P2: The "How It Works" section opens with "A single TaskSpawner" which contradicts the actual pattern (one TaskSpawner per repo) clarified two paragraphs later. This will confuse readers. Consider rewriting the opening to accurately describe the architecture from the start. Prompt for AI agents |
||
| a cron schedule creates one Task per Workspace. Axon handles the | ||
| parallelism β all agents run concurrently in isolated Pods. | ||
|
|
||
| This example shows three repos, but the pattern scales to any number. | ||
| Add more Workspace resources and corresponding TaskSpawner entries. | ||
|
|
||
| Since TaskSpawner currently supports one Workspace per spawner, this | ||
| example uses one TaskSpawner per repository. A shared AgentConfig ensures | ||
| consistent behavior across all agents. | ||
|
|
||
| ## Resources | ||
|
|
||
| | File | Description | | ||
| |------|-------------| | ||
| | `workspaces.yaml` | Workspace resources for each target repo | | ||
| | `credentials-secret.yaml` | Agent credentials (shared) | | ||
| | `github-token-secret.yaml` | GitHub token for cloning and pushing | | ||
| | `agentconfig.yaml` | Shared migration instructions | | ||
| | `taskspawners.yaml` | One TaskSpawner per repo, all on the same cron | | ||
|
|
||
| ## Setup | ||
|
|
||
| 1. Replace all `# TODO:` placeholders. | ||
| 2. Add or remove Workspace/TaskSpawner pairs to match your repo list. | ||
| 3. Apply: | ||
|
|
||
| ```bash | ||
| kubectl apply -f examples/06-multi-repo-migration/ | ||
| ``` | ||
|
|
||
| 4. Monitor progress: | ||
|
|
||
| ```bash | ||
| axon get tasks -w | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P2: Inconsistent CLI usage: this example uses Prompt for AI agents |
||
| ``` | ||
|
|
||
| ## Tips | ||
|
|
||
| - Set `maxConcurrency: 1` on each TaskSpawner to ensure only one migration | ||
| attempt per repo at a time. | ||
| - Use `ttlSecondsAfterFinished: 0` if you want immediate cleanup after | ||
| each run. | ||
| - The cron schedule `"0 9 * * 1"` runs once a week (Monday 9 AM UTC). | ||
| Adjust to run once (`"0 9 12 2 *"`) for a one-time migration. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| apiVersion: axon.io/v1alpha1 | ||
| kind: AgentConfig | ||
| metadata: | ||
| name: migration-config | ||
| spec: | ||
| agentsMD: | | ||
| You are performing a fleet-wide migration. Follow the migration | ||
| instructions exactly and do not make unrelated changes. If the | ||
| migration does not apply to this repo (e.g., the dependency is not | ||
| used), exit without creating a PR. | ||
|
|
||
| After making changes: | ||
| 1. Run the project's test suite to verify nothing is broken. | ||
| 2. Create a PR with a clear title prefixed with "[Migration]". | ||
| 3. Include a summary of what changed and why in the PR description. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| apiVersion: v1 | ||
| kind: Secret | ||
| metadata: | ||
| name: claude-credentials | ||
| type: Opaque | ||
| stringData: | ||
| oauthToken: "" # TODO: replace with your Claude OAuth token |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| apiVersion: v1 | ||
| kind: Secret | ||
| metadata: | ||
| name: github-token | ||
| type: Opaque | ||
| stringData: | ||
| GITHUB_TOKEN: "" # TODO: replace with a GitHub token that has repo scope |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,106 @@ | ||
| # One TaskSpawner per repository, all sharing the same migration prompt | ||
| # and AgentConfig. Add or remove entries to match your repo list. | ||
| apiVersion: axon.io/v1alpha1 | ||
| kind: TaskSpawner | ||
| metadata: | ||
| name: migrate-service-a | ||
| spec: | ||
| when: | ||
| cron: | ||
| schedule: "0 9 12 2 *" # TODO: adjust schedule (this runs Feb 12 at 9 AM UTC) | ||
| taskTemplate: | ||
| type: claude-code | ||
| workspaceRef: | ||
| name: service-a | ||
| agentConfigRef: | ||
| name: migration-config | ||
| credentials: | ||
| type: oauth | ||
| secretRef: | ||
| name: claude-credentials | ||
| promptTemplate: | | ||
| Migrate this repository from the deprecated `log/v1` package to `log/v2`. | ||
|
|
||
| Steps: | ||
| 1. Find all imports of `github.com/your-org/log/v1`. # TODO: replace with actual migration | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P2: Prompt for AI agents |
||
| 2. Replace them with `github.com/your-org/log/v2`. | ||
| 3. Update any changed API calls (see migration guide below). | ||
| 4. Run tests and fix any compilation errors. | ||
| 5. Open a PR with the changes. | ||
|
|
||
| Migration guide: | ||
| - `log.Info(msg)` -> `log.Info(msg, nil)` (second arg is now required attrs) | ||
| - `log.WithField(k, v)` -> `log.With(k, v)` | ||
| - `log.Fatal(msg)` is removed; use `log.Error(msg, nil); os.Exit(1)` | ||
| ttlSecondsAfterFinished: 3600 | ||
| maxConcurrency: 1 | ||
| --- | ||
| apiVersion: axon.io/v1alpha1 | ||
| kind: TaskSpawner | ||
| metadata: | ||
| name: migrate-service-b | ||
| spec: | ||
| when: | ||
| cron: | ||
| schedule: "0 9 12 2 *" # TODO: adjust schedule | ||
| taskTemplate: | ||
| type: claude-code | ||
| workspaceRef: | ||
| name: service-b | ||
| agentConfigRef: | ||
| name: migration-config | ||
| credentials: | ||
| type: oauth | ||
| secretRef: | ||
| name: claude-credentials | ||
| promptTemplate: | | ||
| Migrate this repository from the deprecated `log/v1` package to `log/v2`. | ||
|
|
||
| Steps: | ||
| 1. Find all imports of `github.com/your-org/log/v1`. # TODO: replace with actual migration | ||
| 2. Replace them with `github.com/your-org/log/v2`. | ||
| 3. Update any changed API calls (see migration guide below). | ||
| 4. Run tests and fix any compilation errors. | ||
| 5. Open a PR with the changes. | ||
|
|
||
| Migration guide: | ||
| - `log.Info(msg)` -> `log.Info(msg, nil)` (second arg is now required attrs) | ||
| - `log.WithField(k, v)` -> `log.With(k, v)` | ||
| - `log.Fatal(msg)` is removed; use `log.Error(msg, nil); os.Exit(1)` | ||
| ttlSecondsAfterFinished: 3600 | ||
| maxConcurrency: 1 | ||
| --- | ||
| apiVersion: axon.io/v1alpha1 | ||
| kind: TaskSpawner | ||
| metadata: | ||
| name: migrate-service-c | ||
| spec: | ||
| when: | ||
| cron: | ||
| schedule: "0 9 12 2 *" # TODO: adjust schedule | ||
| taskTemplate: | ||
| type: claude-code | ||
| workspaceRef: | ||
| name: service-c | ||
| agentConfigRef: | ||
| name: migration-config | ||
| credentials: | ||
| type: oauth | ||
| secretRef: | ||
| name: claude-credentials | ||
| promptTemplate: | | ||
| Migrate this repository from the deprecated `log/v1` package to `log/v2`. | ||
|
|
||
| Steps: | ||
| 1. Find all imports of `github.com/your-org/log/v1`. # TODO: replace with actual migration | ||
| 2. Replace them with `github.com/your-org/log/v2`. | ||
| 3. Update any changed API calls (see migration guide below). | ||
| 4. Run tests and fix any compilation errors. | ||
| 5. Open a PR with the changes. | ||
|
|
||
| Migration guide: | ||
| - `log.Info(msg)` -> `log.Info(msg, nil)` (second arg is now required attrs) | ||
| - `log.WithField(k, v)` -> `log.With(k, v)` | ||
| - `log.Fatal(msg)` is removed; use `log.Error(msg, nil); os.Exit(1)` | ||
| ttlSecondsAfterFinished: 3600 | ||
| maxConcurrency: 1 | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| apiVersion: axon.io/v1alpha1 | ||
| kind: Workspace | ||
| metadata: | ||
| name: service-a | ||
| spec: | ||
| repo: https://github.com/your-org/service-a.git # TODO: replace | ||
| ref: main | ||
| secretRef: | ||
| name: github-token | ||
| --- | ||
| apiVersion: axon.io/v1alpha1 | ||
| kind: Workspace | ||
| metadata: | ||
| name: service-b | ||
| spec: | ||
| repo: https://github.com/your-org/service-b.git # TODO: replace | ||
| ref: main | ||
| secretRef: | ||
| name: github-token | ||
| --- | ||
| apiVersion: axon.io/v1alpha1 | ||
| kind: Workspace | ||
| metadata: | ||
| name: service-c | ||
| spec: | ||
| repo: https://github.com/your-org/service-c.git # TODO: replace | ||
| ref: main | ||
| secretRef: | ||
| name: github-token |
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
P2: Using
--body "<review>"is fragile β code reviews routinely contain double quotes, backticks, and other shell metacharacters that will break this command. Prefer--body-fileto avoid shell quoting issues.Prompt for AI agents