Skip to content

ci: auto-update OpenAPI snapshot on PRs#2521

Merged
vnv-varun merged 16 commits intomainfrom
chore/ci-auto-update-openapi-snapshot
Mar 5, 2026
Merged

ci: auto-update OpenAPI snapshot on PRs#2521
vnv-varun merged 16 commits intomainfrom
chore/ci-auto-update-openapi-snapshot

Conversation

@vnv-varun
Copy link
Copy Markdown
Contributor

@vnv-varun vnv-varun commented Mar 4, 2026

Summary

  • When the OpenAPI snapshot is out of date on a PR, CI now auto-regenerates it and commits the update back to the PR branch. The snapshot diff remains visible in the PR for code review.
  • Claude code review now also triggers on github-actions[bot] commits (e.g. the auto-updated snapshot).

Changes

ci.yml (OpenAPI snapshot auto-update):

  • Job-level contents: write permission on the ci job only (workflow default stays read)
  • Checkout uses github.head_ref on PRs so we can push back to the branch
  • Builds agents-api deps via turbo before running the snapshot update
  • Runs openapi:update-snapshot on PRs (skips fork PRs)
  • If snapshot changed: commits, checks branch still exists, pushes with 3-retry + rebase logic
  • Fails explicitly if all push retries are exhausted

claude-code-review.yml:

  • Added github-actions[bot] to the bot allow-list so review triggers on automated commits

Why

Developers sometimes skip or miss the pre-commit hook that auto-updates the OpenAPI snapshot, causing CI to fail. This catches that case automatically. The snapshot diff is still visible in the PR for reviewers to inspect.

Running Claude review on bot commits means automated changes (like the snapshot update) still get reviewed.

Closes PRD-6226

Tested

Verified end-to-end on this PR: pushed an intentionally stale snapshot (added a dummy field), CI detected the diff, regenerated the snapshot, and committed the fix back as github-actions[bot] (commit bdefee5). The dummy field was correctly removed.

Test plan

  • Push a stale snapshot to a PR branch
  • Verify CI auto-updates the snapshot and commits it back
  • Verify the snapshot diff is visible in the PR
  • Verify CI passes on main (snapshot steps are skipped)
  • Verify Claude review triggers on the bot's snapshot commit (blocked until claude-code-review.yml change lands on main)

@vercel
Copy link
Copy Markdown

vercel Bot commented Mar 4, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
agents-api Ready Ready Preview, Comment Mar 5, 2026 11:36pm
agents-manage-ui Ready Ready Preview, Comment Mar 5, 2026 11:36pm
1 Skipped Deployment
Project Deployment Actions Updated (UTC)
agents-docs Skipped Skipped Mar 5, 2026 11:36pm

Request Review

@pullfrog
Copy link
Copy Markdown
Contributor

pullfrog Bot commented Mar 4, 2026

Auto-updates the OpenAPI snapshot on PR branches so developers don't have to remember the pre-commit hook — CI regenerates it and pushes back if stale.

  • Elevated contents permission from read to write in .github/workflows/ci.yml to allow pushing commits
  • Checkout now targets github.head_ref on PRs so git push goes to the correct branch
  • Added a PR-only step that runs openapi:update-snapshot and, if the snapshot changed, commits and pushes it back using github-actions[bot]
  • Steps are gated on github.event_name == 'pull_request', so main and merge-queue runs are unaffected

Pullfrog  | View workflow run | Using Claude Code | Triggered by Pullfrogpullfrog.com𝕏

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Mar 4, 2026

⚠️ No Changeset found

Latest commit: 82617d1

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

Copy link
Copy Markdown
Contributor

@pullfrog pullfrog Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Medium urgency. The workflow achieves its goal but has a few concerns: overly broad contents: write at workflow level, snapshot commits happening before CI validation, and a CI double-run on every snapshot update.

Pullfrog  | Fix all ➔Fix 👍s ➔View workflow runpullfrog.com𝕏

Comment thread .github/workflows/ci.yml Outdated

permissions:
contents: read
contents: write
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Security / least-privilege: contents: write is set at the workflow level, so it applies to every job — including create-agents-e2e which doesn't need write access. On push and merge_group events, no commit-back is needed either. Consider scoping this to a job-level permissions block on just the ci job, so other jobs and non-PR events retain contents: read.

Comment thread .github/workflows/ci.yml
Comment on lines +33 to +34
with:
ref: ${{ github.head_ref || github.ref }}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Checkout ref change affects non-PR events. github.head_ref is empty on push events, so this falls back to github.ref (e.g. refs/heads/main). The default checkout for push events uses the exact commit SHA, not the branch ref — so this subtly changes behavior and introduces a theoretical race where a newer commit lands on main between trigger and checkout. Safer to only override the ref for PRs:

Suggested change
with:
ref: ${{ github.head_ref || github.ref }}
with:
ref: ${{ github.event_name == 'pull_request' && github.head_ref || '' }}

An empty string preserves the default checkout behavior for non-PR events.

Comment thread .github/workflows/ci.yml Outdated
Comment on lines +91 to +103
- name: Commit OpenAPI snapshot if changed
if: github.event_name == 'pull_request'
run: |
if git diff --quiet agents-api/__snapshots__/openapi.json 2>/dev/null; then
echo "OpenAPI snapshot is up to date"
else
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add agents-api/__snapshots__/openapi.json
git commit -m "chore: update OpenAPI snapshot"
git push
echo "::notice::OpenAPI snapshot was auto-updated and committed. This CI run will continue with the updated snapshot."
fi
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Snapshot committed even when CI fails. These steps run before Run CI checks, so a snapshot from broken code gets committed to the PR branch regardless of whether CI passes. If the intent is to only commit known-good snapshots, move these two steps after the CI checks step (or add if: ... && steps.ci-check.outcome == 'success').

Comment thread .github/workflows/ci.yml Outdated
Comment on lines +91 to +103
- name: Commit OpenAPI snapshot if changed
if: github.event_name == 'pull_request'
run: |
if git diff --quiet agents-api/__snapshots__/openapi.json 2>/dev/null; then
echo "OpenAPI snapshot is up to date"
else
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add agents-api/__snapshots__/openapi.json
git commit -m "chore: update OpenAPI snapshot"
git push
echo "::notice::OpenAPI snapshot was auto-updated and committed. This CI run will continue with the updated snapshot."
fi
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CI double-trigger. When git push adds a commit to the PR branch, the pull_request/synchronize event fires again, re-running the entire workflow. The second run finds the snapshot unchanged and terminates cleanly, but you still pay for a full redundant CI run (install, build, test). Adding [skip ci] to the auto-commit message is the simplest fix:

git commit -m "chore: update OpenAPI snapshot [skip ci]"

Copy link
Copy Markdown
Contributor

@claude claude Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR Review Summary

(5) Total Issues | Risk: Medium

🟠⚠️ Major (4) 🟠⚠️

🟠 1) .github/workflows/ci.yml:84-103 Missing fork protection for auto-commit steps

Issue: The auto-commit steps will fail silently or produce confusing CI output when PRs come from forks. Fork PRs cannot push back to the head branch because GITHUB_TOKEN is read-only for fork PRs by default.

Why: This is inconsistent with the established pattern in auto-format.yml which explicitly guards against fork PRs. Without this guard, the workflow will execute the snapshot update step on fork PRs, fail at git push, and produce confusing error messages. If repository settings ever evolve to allow write tokens for forks, this becomes a potential code injection vector.

Fix: Add a conditional check to skip the auto-commit steps for fork PRs, matching the pattern already established in this repo:

- name: Update OpenAPI snapshot
  if: |
    github.event_name == 'pull_request' &&
    github.event.pull_request.head.repo.full_name == github.repository
  run: pnpm --filter @inkeep/agents-api openapi:update-snapshot
  env:
    ENVIRONMENT: test
    CI: true

- name: Commit OpenAPI snapshot if changed
  if: |
    github.event_name == 'pull_request' &&
    github.event.pull_request.head.repo.full_name == github.repository
  run: |
    # ... existing logic

Refs:


🟠 2) .github/workflows/ci.yml:12-14 Workflow-level write permissions broader than necessary

Issue: The contents: write permission is set at the workflow level (line 13), which means it applies to all triggers (push, pull_request, merge_group) and all jobs (including create-agents-e2e), not just the PR snapshot steps that need it.

Why: This violates the principle of least privilege. The elevated permission grants unnecessary write access to: (1) CI runs on main after merge that don't need write access, (2) the create-agents-e2e job which only runs tests. If vulnerabilities are introduced in other steps or jobs are added later, they inherit write access unnecessarily.

Fix: Move the elevated permission to job-level for only the ci job, keeping the workflow default at contents: read:

permissions:
  contents: read
  actions: read

jobs:
  ci:
    permissions:
      contents: write
    runs-on: ubuntu-32gb
    # ... rest of job

Refs:


🟠 3) .github/workflows/ci.yml:101 Git push without retry logic risks silent failures

Issue: The git push command has no retry mechanism. If the push fails due to a transient network issue or a concurrent push from auto-format.yml, the command will fail and CI will fail without clear indication of why.

Why: Both ci.yml and auto-format.yml workflows run on pull_request events and can push commits back to the PR branch. While each workflow has its own concurrency group, they are separate workflows that can run concurrently. The existing auto-format.yml workflow (lines 125-135) demonstrates a robust pattern with 3 retries, exponential backoff, and pull --rebase between attempts. This new code lacks that resilience.

Fix: Add retry logic similar to auto-format.yml:

for i in 1 2 3; do
  if git push; then
    break
  fi
  echo "Push failed, attempting pull --rebase and retry ($i/3)"
  git pull --rebase origin "${{ github.head_ref }}" || exit 1
  sleep $((i * 2))
done

Refs:


🟠 4) scope Race condition between ci.yml and auto-format.yml

Issue: Both workflows can run concurrently on the same PR and attempt to push commits, creating a race condition where one may fail with a non-fast-forward error.

Why: ci.yml uses concurrency group CI-${{ github.ref }} and auto-format.yml uses Auto Format-${{ github.ref }}. These are separate groups, so both workflows can run simultaneously. If auto-format.yml pushes a formatting commit while ci.yml is also trying to push the snapshot, one will fail. The retry logic in fix #3 would mitigate this, but it's worth being aware that these workflows can interact.

Fix: The retry logic suggested in issue #3 addresses this. Alternatively, consider unifying the concurrency groups across auto-commit workflows, or moving the snapshot update into the auto-format.yml workflow itself since they serve similar purposes (auto-fixing generated artifacts).

Refs:

🟡 Minor (1) 🟡

Inline Comments:

  • 🟡 Minor: ci.yml:97 Missing branch existence check before push

💭 Consider (2) 💭

💭 1) .github/workflows/ci.yml:34 Checkout ref change affects all triggers

Issue: The checkout step now uses ref: ${{ github.head_ref || github.ref }} which changes behavior for all event types, not just PRs. On push events to main, github.head_ref is empty so it falls back to github.ref.

Why: This is likely correct behavior (explicit ref matching implicit), but the change has broader scope than the PR description suggests. Worth confirming main branch CI continues to work as expected.

Fix: Consider adding a note to the PR description acknowledging this affects all triggers, not just PRs.

💭 2) .github/workflows/ci.yml:99 Consider [skip ci] to prevent re-trigger loops

Issue: Pushing a commit back to the PR branch will re-trigger CI. While the git diff --quiet check should prevent an infinite loop (assuming snapshot generation is deterministic), adding [skip ci] to the commit message would make the intent explicit.

Why: The existing auto-format.yml doesn't use [skip ci] and works fine in practice, so this is likely not needed. However, if snapshot generation ever becomes non-deterministic (e.g., includes timestamps), this could cause repeated CI runs.

Fix: Optionally add [skip ci] to the commit message: git commit -m "chore: update OpenAPI snapshot [skip ci]"


🚫 REQUEST CHANGES

Summary: This PR introduces a useful automation for keeping OpenAPI snapshots in sync, but it needs a few defensive improvements before merging. The most critical issues are: (1) missing fork protection that's already established in auto-format.yml, (2) workflow-level permissions that are broader than necessary, and (3) missing retry logic that could cause flaky CI failures when racing with the auto-format workflow. These are all straightforward fixes that align with existing patterns in the repo.

Discarded (3)
Location Issue Reason Discarded
ci.yml:32 Actions pinned to mutable tags rather than SHAs Pre-existing pattern across all workflows, not introduced by this PR
ci.yml:17 Concurrency group may cancel in-progress runs Pre-existing concurrency behavior, not changed by this PR
N/A Security concerns about fork write tokens The pull_request event already provides protection (GITHUB_TOKEN is read-only for forks by default); the fork protection suggestion is defense-in-depth, not critical security
Reviewers (3)
Reviewer Returned Main Findings Consider While You're Here Inline Comments Pending Recs Discarded
pr-review-sre 5 2 1 0 1 0 1
pr-review-devops 5 2 1 0 0 0 2
pr-review-security-iam 2 0 0 0 0 0 2
Total 12 4 2 0 1 0 5

Note: Security and DevOps findings on fork protection and permissions were merged into single findings (counted under DevOps/SRE in final output).

Comment thread .github/workflows/ci.yml Outdated
if git diff --quiet agents-api/__snapshots__/openapi.json 2>/dev/null; then
echo "OpenAPI snapshot is up to date"
else
git config user.name "github-actions[bot]"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Minor: Missing branch existence check before push

Issue: If a PR is merged or closed while CI is running, the head branch may be deleted and git push will fail with a confusing error.

Why: The existing auto-format.yml workflow defensively checks branch existence before pushing (lines 120-123). This new code lacks that guard, leading to inconsistent error handling patterns across workflows.

Fix:

# Add before git push:
if ! git ls-remote --exit-code --heads origin "${{ github.head_ref }}" > /dev/null 2>&1; then
  echo "::notice::Remote branch '${{ github.head_ref }}' no longer exists. Skipping push."
  exit 0
fi

Refs:

@github-actions github-actions Bot deleted a comment from claude Bot Mar 4, 2026
Copy link
Copy Markdown
Contributor

@claude claude Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR Review Summary

(4) Total Issues | Risk: Medium

Re-review scoped to delta. This review covers only the changes since the previous review. The delta adds a branch existence check before pushing (commit 9d7d3935f).

✅ Delta Assessment

The new commit addresses Minor issue #5 from the previous review ("Missing branch existence check before push"). The implementation is correct:

  • Uses the same git ls-remote --exit-code --heads pattern as auto-format.yml:120-123
  • Correctly exits with 0 to avoid failing CI when the branch is deleted
  • Uses ::notice:: annotation for visibility
  • Variable quoting is correct

The TOCTOU (time-of-check-to-time-of-use) race between the check and push is acceptable — the window is milliseconds, and the worst case is a failed push which is the same outcome as not having the check at all.

No new issues found in the delta.

🕐 Pending Recommendations (4)

The following issues from the previous review remain unaddressed:

  • 🟠 ci.yml:84-103 Missing fork protection for auto-commit steps — fork PRs will fail at git push with confusing errors
  • 🟠 ci.yml:12-14 Workflow-level contents: write permission broader than necessary — should be scoped to job-level
  • 🟠 ci.yml:108 Git push without retry logic risks silent failures — race with auto-format.yml can cause non-fast-forward errors
  • 🟠 scope Race condition between ci.yml and auto-format.yml — both can push simultaneously due to separate concurrency groups

🚫 REQUEST CHANGES

Summary: The delta is well-implemented and addresses the branch existence check concern. However, the 4 Major issues from the previous review remain unaddressed. The most critical are the missing fork protection (will cause confusing CI failures for external contributors) and the lack of retry logic (can cause intermittent failures when racing with auto-format.yml). These should be addressed before merging.

Reviewers (2)
Reviewer Returned Main Findings Consider While You're Here Inline Comments Pending Recs Discarded
pr-review-devops 0 0 0 0 0 0 0
pr-review-sre 0 0 0 0 0 0 0
Total 0 0 0 0 0 0 0

Note: Delta was minimal and both reviewers confirmed the implementation follows established patterns with no new issues.

@github-actions github-actions Bot deleted a comment from claude Bot Mar 4, 2026
Copy link
Copy Markdown
Contributor

@claude claude Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR Review Summary

(0) Total Issues | Risk: Low

Re-review scoped to delta. This review covers only the changes since the previous review (commit 9d7d3935f2dc86021f).

✅ Delta Assessment

The delta commit (2dc86021f ci: add fork protection, job-level perms, push retry logic) correctly addresses all 4 Major issues from the previous review:

Previous Issue Resolution Verified
🟠 Fork protection missing Added github.event.pull_request.head.repo.full_name == github.repository to both step conditions ✅ Matches auto-format.yml:17-19
🟠 Workflow-level write perms too broad Changed workflow-level contents: read, added job-level contents: write on ci job only ✅ Least-privilege principle applied
🟠 No retry logic for git push Added 3-retry loop with exponential backoff (sleep $((i * 2))) ✅ Matches auto-format.yml:125-135
🟠 Race condition with auto-format.yml Added branch existence check within retry loop ✅ Same defensive pattern as auto-format.yml

Implementation quality:

  • Comment updated to explain fork protection: # Auto-update OpenAPI snapshot on PRs (skip fork PRs since GITHUB_TOKEN is read-only)
  • Branch existence check runs before initial push AND within each retry iteration
  • Notice annotations provide good visibility: ::notice::Remote branch '$PUSH_REF' was deleted during retry. Skipping.
  • Variable quoting is correct throughout ("$PUSH_REF")

No new issues introduced by this delta.

💭 Consider (1) 💭

💭 1) ci.yml:114-126 Retry loop exits silently after exhausted retries

Issue: If all 3 push attempts fail, the script falls through with exit code 0 rather than failing the step.

Why: This matches the identical pattern in auto-format.yml:125-135, so it's consistent behavior. The rationale is likely that a failed snapshot push shouldn't block CI entirely—the snapshot will be updated on the next push. However, this does mean snapshot update failures can go unnoticed.

Refs: auto-format.yml:125-135 — same pattern


✅ APPROVE

Summary: All 4 Major issues from the previous review have been correctly addressed. The implementation follows established patterns from auto-format.yml and applies the principle of least privilege for permissions. This is ready to merge. 🎉

Reviewers (1)
Reviewer Returned Main Findings Consider While You're Here Inline Comments Pending Recs Discarded
pr-review-devops 1 0 1 0 0 0 0
Total 1 0 1 0 0 0 0

@github-actions github-actions Bot deleted a comment from claude Bot Mar 4, 2026
Copy link
Copy Markdown
Contributor

@claude claude Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR Review Summary

(0) Total Issues | Risk: Low

Re-review scoped to delta. This review covers only the changes since the previous review (commit 2dc86021fe6cfc7e6f).

✅ Delta Assessment

The delta commit (e6cfc7e6f ci: build deps before snapshot update, fail on exhausted retries) adds two improvements:

Change Assessment
Build dependencies step ✅ Correct — uses --filter=@inkeep/agents-api... (Turborepo ellipsis syntax) to build the package and all its transitive dependencies before snapshot generation. Same conditional guards as other snapshot steps.
Explicit failure on exhausted retries ✅ Addresses prior "Consider" item — tracks push_succeeded=false and explicitly exits with exit 1 + ::error:: annotation after 3 failed attempts. This is actually an improvement over auto-format.yml which falls through silently.

Implementation quality:

  • Build step uses consistent fork protection pattern
  • Environment variables match existing steps (ENVIRONMENT: test, CI: true)
  • Error message is actionable: "Failed to push OpenAPI snapshot update after 3 attempts."
  • Uses ::error:: annotation for visibility in GitHub Actions UI

No new issues introduced by this delta.

🧹 While You're Here (optional)

Consider backporting the explicit failure handling pattern to auto-format.yml for consistency — currently that workflow falls through silently after exhausted retries (lines 125-135). This is out of scope for this PR but worth a follow-up.


✅ APPROVE

Summary: The delta is clean and addresses the "Consider" item from the previous review. The build step ensures dependencies are available, and the explicit failure handling is an improvement over existing patterns. Ready to merge! 🚀

Reviewers (2)
Reviewer Returned Main Findings Consider While You're Here Inline Comments Pending Recs Discarded
pr-review-devops 2 0 0 1 0 0 0
pr-review-sre 0 0 0 0 0 0 0
Total 2 0 0 1 0 0 0

Note: Both reviewers confirmed the delta follows established patterns and introduces no new issues. DevOps noted the error handling is an improvement over auto-format.yml.

@github-actions github-actions Bot deleted a comment from claude Bot Mar 4, 2026
Copy link
Copy Markdown
Contributor

@claude claude Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR Review Summary

(0) Total Issues | Risk: Low

Re-review scoped to delta. This review covers only the changes since the previous review (commit e6cfc7e6fcd6663ed6).

✅ Delta Assessment

The delta commit (cd6663ed6 ci: add database URL env vars to build and snapshot steps) adds 4 lines — two database URL environment variables to each of the "Build dependencies for snapshot update" and "Update OpenAPI snapshot" steps:

INKEEP_AGENTS_MANAGE_DATABASE_URL: postgresql://appuser:password@localhost:5432/inkeep_agents
INKEEP_AGENTS_RUN_DATABASE_URL: postgresql://appuser:password@localhost:5433/inkeep_agents
Criterion Assessment
Values consistent? ✅ Identical to all other usages in the workflow (lines 169-170 in "Run CI checks", lines 341-342 and 347-348 in create-agents-e2e)
Security concern? ✅ None — these are CI-specific localhost credentials for GitHub Actions service containers, not real credentials. Hardcoding localhost CI credentials is an established pattern in this repo.
Necessary? ✅ Required for correctness — agents-api/src/env.ts requires these variables (they are not optional in the Zod schema). Without them, the build step would fail during env schema parsing.

No new issues introduced by this delta.


✅ APPROVE

Summary: Clean delta that adds required database URL environment variables to the snapshot update steps. The values match the existing pattern used throughout the workflow, and are necessary for the env schema parsing to succeed. This PR is ready to ship! 🚀

Reviewers (1)
Reviewer Returned Main Findings Consider While You're Here Inline Comments Pending Recs Discarded
pr-review-devops 0 0 0 0 0 0 0
Total 0 0 0 0 0 0 0

Note: Delta was minimal (4 lines adding env vars). DevOps reviewer confirmed the values are consistent with existing patterns and necessary for correctness.

@github-actions github-actions Bot deleted a comment from claude Bot Mar 4, 2026
When the OpenAPI snapshot is out of date on a PR, CI now
automatically regenerates it and commits the update back to the
PR branch. The snapshot diff remains visible in the PR for review.

Only runs on pull_request events, not on main.

Closes PRD-6226
- Move contents:write to job-level (ci only), keep workflow default read
- Skip snapshot steps on fork PRs (GITHUB_TOKEN is read-only for forks)
- Add 3-retry push with pull --rebase, matching auto-format.yml pattern
- Re-check branch existence between retries
- Add turbo build step for agents-api deps before running snapshot
  update (vitest needs built packages to resolve imports)
- Fail the step explicitly if all 3 push retries are exhausted
Allow Claude code review to trigger on commits from
github-actions[bot], such as the auto-updated OpenAPI snapshot.
@vnv-varun
Copy link
Copy Markdown
Contributor Author

A couple of notes:

Snapshot gating: The snapshot update runs on every PR without path filtering. We could gate it to only run when files that affect the OpenAPI spec change (route files, openapi.ts, createApp.ts), but we'd need to update that list whenever new files start affecting the spec. Open to either approach - keeping it ungated is simpler and only adds ~5-15s.

Claude review on bot commits: We discussed having all bot commits on PRs trigger Claude review (not just the current allow-list of inkeep-internal-ci and github-actions). Holding off on that broader change for now since it could increase review costs. Currently only the two bots we care about are allow-listed.

@vercel vercel Bot temporarily deployed to Preview – agents-docs March 5, 2026 21:30 Inactive
@vercel vercel Bot temporarily deployed to Preview – agents-docs March 5, 2026 21:31 Inactive
- Move git identity (name/email) to job-level env vars
- Extract branch check, retry, and push logic into
  scripts/ci-commit-and-push.sh (reusable by other workflows)
- Replaces ~35 lines of inline bash with a single script call
@inkeep-internal-ci
Copy link
Copy Markdown
Contributor

inkeep-internal-ci Bot commented Mar 5, 2026

Claude finished @vnv-varun's task in 1m 8s —— View job


Code Review

  • Read current state of changed files
  • Review ci.yml changes
  • Review scripts/ci-commit-and-push.sh
  • Review claude-code-review.yml changes
  • Post review summary

Overall Assessment: Looks good to merge

The PR is well-structured and iteratively addressed all prior review feedback. The extracted ci-commit-and-push.sh script is a nice improvement over the inline approach. Here are my thoughts:

What's done well

  1. Proper permission scopingcontents: write is correctly set at the job level on only the ci job (line 24-25), while the workflow default stays contents: read (line 13). The create-agents-e2e job inherits the safer default.

  2. Fork protection — All three snapshot steps correctly gate on github.event.pull_request.head.repo.full_name == github.repository, matching the established pattern in auto-format.yml.

  3. Reusable script extractionscripts/ci-commit-and-push.sh consolidates the commit-and-push logic (branch check, 3-retry with rebase, explicit failure on exhaustion) into a single reusable script. This is cleaner than duplicating the logic inline and is actually an improvement over auto-format.yml's inline version.

  4. Explicit failure on retry exhaustion — Unlike auto-format.yml which silently falls through after 3 failed pushes, this script exits with exit 1 and an ::error:: annotation (line 48-49). Good improvement.

Minor observations

1. auto-format.yml could adopt the shared script too

auto-format.yml lines 109-135 duplicate the same commit-and-push logic that ci-commit-and-push.sh now encapsulates. Consider a follow-up PR to have auto-format.yml call the shared script as well — this would also give it the explicit failure handling it currently lacks. Not blocking for this PR.

2. Checkout ref on non-PR events (ci.yml:38)

ref: ${{ github.head_ref || github.ref }}

On push events, github.head_ref is empty so this falls back to github.ref (e.g. refs/heads/main). The default checkout behavior for push events uses the exact commit SHA, so this subtly changes behavior — there's a theoretical race where a newer commit lands on main between trigger and checkout. In practice this is unlikely to cause issues (the concurrency group would cancel the stale run), but the safer pattern from auto-format.yml:49 is:

ref: ${{ github.event_name == 'pull_request' && github.head_ref || github.ref }}

This was flagged in earlier reviews too. Low risk but worth considering.

3. CI double-trigger consideration

When the script pushes a snapshot commit back to the PR branch, it triggers a new pull_request:synchronize event, causing a full redundant CI run. The second run will find the snapshot unchanged and complete normally, but you pay for the full install/build/test cycle. Adding [skip ci] to the commit message would avoid this:

git commit -m "$COMMIT_MSG [skip ci]"

The tradeoff is that the snapshot commit itself wouldn't be CI-validated, but since it was generated during a CI run that validates everything, this seems acceptable. This was discussed in earlier reviews — up to you whether the ~5min saved per snapshot update is worth it.

4. Script isn't executable in the repo

The script scripts/ci-commit-and-push.sh is called directly in the workflow. Make sure it has the executable bit set (chmod +x). If it was added without it, the bash scripts/ci-commit-and-push.sh invocation in the YAML would need to explicitly use bash as the shell (which GitHub Actions does by default for run: steps, so this works either way). Just noting for completeness — if anyone tries to run it locally without bash prefix, they'd need the executable bit.

Summary

The PR is solid. All major review feedback from previous rounds has been addressed. The reusable script is a clean pattern. The remaining items above are all minor/optional improvements that could be done in follow-ups.


|

@vercel vercel Bot temporarily deployed to Preview – agents-docs March 5, 2026 23:32 Inactive
@vercel vercel Bot temporarily deployed to Preview – agents-docs March 5, 2026 23:32 Inactive
@vercel vercel Bot temporarily deployed to Preview – agents-docs March 5, 2026 23:33 Inactive
@vercel vercel Bot temporarily deployed to Preview – agents-docs March 5, 2026 23:34 Inactive
@vnv-varun vnv-varun added this pull request to the merge queue Mar 5, 2026
Merged via the queue into main with commit 32952ce Mar 5, 2026
4 checks passed
@vnv-varun vnv-varun deleted the chore/ci-auto-update-openapi-snapshot branch March 5, 2026 23:43
@claude claude Bot mentioned this pull request Mar 6, 2026
@itoqa
Copy link
Copy Markdown

itoqa Bot commented Mar 6, 2026

Ito Test Report ✅

16 test cases ran. 16 passed.

🔍 Verification of CI workflow behavior, branch safety, diff-gate precision, and permission boundaries shows the implemented OpenAPI auto-update and bot-review gating paths behave consistently with the intended design in the code reviewed.

✅ Passed (16)
Test Case Summary Timestamp Screenshot
ROUTE-1 CI run completed with OpenAPI snapshot auto-updated and committed, with snapshot diff visible on the bot commit. 0:00 ROUTE-1_0-00.png
ROUTE-2 Non-target PR changes correctly skipped OpenAPI snapshot build/update/commit path. 4:11 ROUTE-2_4-11.png
ROUTE-3 Push-triggered main-branch CI correctly excluded PR-only OpenAPI auto-update behavior. 9:27 ROUTE-3_9-27.png
ROUTE-4 Fork PR guard correctly prevented writeback path from executing. 11:57 ROUTE-4_11-57.png
LOGIC-1 Snapshot auto-commit landed on PR head branch as intended. 0:00 LOGIC-1_0-00.png
LOGIC-2 OpenAPI gate, dependency build, update, and commit-step ordering executed correctly. 0:00 LOGIC-2_0-00.png
LOGIC-3 Up-to-date snapshot path correctly produced no additional bot commit. 4:11 LOGIC-3_4-11.png
EDGE-1 Branch-deleted race condition was handled gracefully while run still completed successfully. 25:21 EDGE-1_25-21.png
EDGE-2 Push conflict recovery path retried with rebase and completed successfully. 25:21 EDGE-2_25-21.png
EDGE-4 Diff-gate regex correctly matched intended path families. 35:09 EDGE-4_35-09.png
EDGE-5 Diff-gate correctly avoided false-positive trigger on lookalike non-target paths. 7:51 EDGE-5_7-51.png
EDGE-6 Rapid commit bursts converged to a coherent latest-run terminal state. 25:21 EDGE-6_25-21.png
ADV-1 Fork-origin abuse attempt remained blocked from snapshot writeback path. 11:57 ADV-1_11-57.png
ADV-2 Branch-name payload was safely handled as quoted input without shell injection behavior. 11:57 ADV-2_11-57.png
ADV-3 Non-allowlisted bot senders remained blocked from triggering Claude review. 11:57 ADV-3_11-57.png
ADV-4 Workflow permission boundaries remained minimal and scoped as intended. 9:33 ADV-4_9-33.png
📋 View Recording

Screen Recording

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants