Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .agents/skills/update-integrations/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ description: Update integration documentation links and API reference data by sy

This skill synchronizes the integration package catalog with documentation URL mappings and generates per-package API reference schemas. It ensures every NuGet package listed in the integrations data file has a corresponding documentation link and an up-to-date API reference JSON file.

> **Automation note:** The scheduled `update-integration-data` workflow (`.github/workflows/update-integration-data.yml`) runs this update deterministically — no agent/LLM. It executes `src/frontend/scripts/update-integration-data.ps1`, which runs `pnpm update:all`, detects `"version":` changes in `src/frontend/src/data/aspire-integrations.json`, and — only when a version actually moves — runs the C# and TypeScript API regeneration (and the twoslash bundle) before opening a PR via the Aspire bot GitHub App. You can reproduce the full flow locally with `pwsh src/frontend/scripts/update-integration-data.ps1` (add `-SkipRegen` for a fast data-only run). Use this skill for **manual or one-off runs that need judgment** — for example: adding a new integration, reconciling `integration-docs.json`, validating release-branch feed resolution, troubleshooting a regen failure flagged by the workflow's PR, or regenerating data outside the scheduled cadence.
> **Automation note:** The scheduled `update-integration-data` workflow (`.github/workflows/update-integration-data.yml`) runs this update deterministically — no agent/LLM. It executes `src/frontend/scripts/update-integration-data.ps1`, which runs `pnpm update:all`, detects `"version":` changes in `src/frontend/src/data/aspire-integrations.json`, and — only when a version actually moves — runs the C# and TypeScript API regeneration (and the twoslash bundle) before opening or refreshing a PR via the Aspire bot GitHub App. That PR is approved and squash-merged automatically by `.github/policies/auto-merge.yml` once the required `ci-gate` check passes; removing its `:octocat: auto-merge` label holds it for manual review. You can reproduce the full flow locally with `pwsh src/frontend/scripts/update-integration-data.ps1` (add `-SkipRegen` for a fast data-only run). Use this skill for **manual or one-off runs that need judgment** — for example: adding a new integration, reconciling `integration-docs.json`, validating release-branch feed resolution, troubleshooting a regen failure flagged by the workflow's PR, or regenerating data outside the scheduled cadence.

## Overview

Expand Down
40 changes: 40 additions & 0 deletions .github/policies/auto-merge.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
id: auto.merge
name: GitOps.PullRequestIssueManagement
description: Auto-merge the Integration Data Updater pull request after the required ci-gate check passes
owner:
resource: repository
disabled: false
where:
configuration:
resourceManagementConfiguration:
eventResponderTasks:

- description: >-
Approve and auto-squash-merge PRs to main labeled ':octocat: auto-merge'.
The label is only applied by the Aspire bot GitHub App when
update-integration-data.yml opens its PR. The sender check keeps
anyone else from self-approving a PR by adding the label, because
branch protection requires one approval. Branch protection also
requires ci-gate to pass on the PR branch without requiring it to be
up to date with main before merging.
if:
- payloadType: Pull_Request
- labelAdded:
label: ':octocat: auto-merge'
- targetsBranch:
branch: main
- isActivitySender:
user: aspire-repo-bot[bot]
then:
- enableAutoMerge:
mergeMethod: Squash
- approvePullRequest:
comment: "Approved; this PR will merge after the required ci-gate check passes."

- description: Disable auto-merge when the auto-merge label is removed
if:
- payloadType: Pull_Request
- labelRemoved:
label: ':octocat: auto-merge'
then:
- disableAutoMerge
62 changes: 16 additions & 46 deletions .github/workflows/update-integration-data.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ name: Integration Data Updater
# update scripts directly (no LLM inference, no agent timeout, no PAT auth) and
# opens a PR through the Aspire bot GitHub App when the generated data changes.
#
# The bot owns the rolling `chore/update-integration-data` branch and force-pushes
# it on every run, so nobody should commit to it. The PR is labeled
# `:octocat: auto-merge`, which .github/policies/auto-merge.yml turns into an
# approval and a squash auto-merge once the required `ci-gate` check passes.
# Remove the label to hold a PR for manual review.
#
# All logic lives in src/frontend/scripts/update-integration-data.ps1 so the
# exact same flow can be reproduced locally:
# pwsh src/frontend/scripts/update-integration-data.ps1
Expand Down Expand Up @@ -84,13 +90,6 @@ jobs:
GITHUB_TOKEN: ${{ github.token }}
run: ./src/frontend/scripts/update-integration-data.ps1

- name: Configure git identity
if: ${{ steps.update.outputs.changed == 'true' }}
shell: bash
run: |
git config user.name "aspire-repo-bot[bot]"
git config user.email "aspire-repo-bot[bot]@users.noreply.github.com"

- name: Commit and refresh automation branch
if: ${{ steps.update.outputs.changed == 'true' }}
id: push
Expand All @@ -101,26 +100,11 @@ jobs:
set -euo pipefail

# Single long-lived automation branch. Each run force-pushes one commit
# with the latest generated data on top of the freshest main, so an
# unreviewed PR is refreshed in place instead of piling up a new PR (and
# a new branch) every day. The rolling commit is always a single snapshot
# with the latest generated data on top of the freshest main, so the
# open PR is refreshed in place instead of piling up a new PR (and a new
# branch) every day. The rolling commit is always a single snapshot
# rebased onto current main, which also keeps the PR conflict-free.
branch="chore/update-integration-data"
bot_email="aspire-repo-bot[bot]@users.noreply.github.com"

# Refuse to replace a rolling branch that contains maintainer changes.
# The exact lease below also protects commits pushed after this check.
remote_tip=$(git ls-remote --heads origin "refs/heads/$branch" | awk '{print $1}')
if [ -n "$remote_tip" ]; then
git fetch --no-tags origin "refs/heads/$branch:refs/remotes/origin/$branch"
non_bot_commits=$(git log --format='%H %ae %ce' "origin/main..origin/$branch" |
awk -v bot="$bot_email" '$2 != bot || $3 != bot')
if [ -n "$non_bot_commits" ]; then
echo "::error::Refusing to replace $branch because it contains non-bot commits:"
echo "$non_bot_commits"
exit 1
fi
fi

# Stage only the allowed generated data files — never workflow files,
# source, manifests, or docs. Directories with no changes are no-ops.
Expand All @@ -144,16 +128,16 @@ jobs:
fi

# Reset the branch to a single fresh commit on top of the current main
# and force-push, so the open PR (if any) updates in place.
# and force-push, so the open PR (if any) updates in place. The lease
# fails the push if the branch moved since checkout instead of
# overwriting it.
git config user.name "aspire-repo-bot[bot]"
git config user.email "aspire-repo-bot[bot]@users.noreply.github.com"
git checkout -B "$branch"
git commit \
-m "$PR_TITLE" \
-m "Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>"
if [ -n "$remote_tip" ]; then
git push --force-with-lease="refs/heads/$branch:$remote_tip" origin "HEAD:refs/heads/$branch"
else
git push origin "HEAD:refs/heads/$branch"
fi
git push --force-with-lease origin "HEAD:refs/heads/$branch"
echo "branch=$branch" >> "$GITHUB_OUTPUT"
echo "pushed=true" >> "$GITHUB_OUTPUT"

Expand All @@ -171,6 +155,7 @@ jobs:

# Reuse the existing open PR for the rolling branch if there is one, so
# its review threads and history carry over; otherwise open a fresh PR.
# Adding the label at creation is what triggers the auto-merge policy.
existing=$(gh pr list \
--state open \
--head "$BRANCH" \
Expand All @@ -192,21 +177,6 @@ jobs:
echo "Created $new_pr"
fi

# Close any stray older automation PRs (e.g. legacy timestamped branches
# from before the rolling-branch model) so only the single PR remains.
strays=$(gh pr list \
--state open \
--limit 30 \
--json number,headRefName \
--jq '.[] | select(.headRefName | startswith("chore/update-integration-data-")) | select(.headRefName != env.BRANCH) | .number')

for pr in $strays; do
echo "Closing stray automation PR #$pr"
gh pr close "$pr" \
--delete-branch \
--comment "Superseded by the rolling Integration Data Updater PR."
done

- name: Summary
if: ${{ always() }}
shell: bash
Expand Down
8 changes: 5 additions & 3 deletions src/frontend/scripts/update-integration-data.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -504,7 +504,7 @@ if ($versionsChanged -and -not $SkipRegen) {
}
if ($tsToleratedPackages) {
$toleratedWarning = "TypeScript modules were generated despite known ATS scanner diagnostics for: $tsToleratedPackages. " +
"Their APIs may be incomplete until the Aspire CLI includes microsoft/aspire#20443; review them before merging."
"Their APIs may be incomplete until the Aspire CLI includes microsoft/aspire#20443. The automation PR auto-merges once CI passes. Remove its auto-merge label to review these modules first."
Write-Warning $toleratedWarning
foreach ($diagnostic in $tsToleratedDiagnostics) {
Write-Warning " $diagnostic"
Expand Down Expand Up @@ -617,6 +617,8 @@ $sb = [System.Text.StringBuilder]::new()
[void]$sb.AppendLine("")
[void]$sb.AppendLine("Generated deterministically by ``src/frontend/scripts/update-integration-data.ps1`` (no agent inference).")
[void]$sb.AppendLine("")
[void]$sb.AppendLine("This PR is approved and squash-merged automatically once ``ci-gate`` passes, as configured in ``.github/policies/auto-merge.yml``. Remove the ``:octocat: auto-merge`` label to hold it for manual review.")
[void]$sb.AppendLine("")
[void]$sb.AppendLine("### What's updated")
[void]$sb.AppendLine("- ``src/frontend/src/data/aspire-integrations.json`` — latest package information")
[void]$sb.AppendLine("- ``src/frontend/src/data/integration-docs.json`` — documentation mappings, when packages are removed")
Expand Down Expand Up @@ -664,7 +666,7 @@ if ($regenRan) {
[void]$sb.AppendLine("")
[void]$sb.AppendLine("### :warning: Tolerated ATS scanner diagnostics")
[void]$sb.AppendLine("")
[void]$sb.AppendLine("The Aspire CLI reported known duplicate inherited-capability diagnostics for the packages below. Their TypeScript modules were generated anyway, so the APIs named in these diagnostics may be incomplete until the CLI includes the scanner fix from microsoft/aspire#20443. **Review these modules before merging.**")
[void]$sb.AppendLine("The Aspire CLI reported known duplicate inherited-capability diagnostics for the packages below. Their TypeScript modules were generated anyway, so the APIs named in these diagnostics may be incomplete until the CLI includes the scanner fix from microsoft/aspire#20443. **Remove the ``:octocat: auto-merge`` label to review these modules before this PR merges.**")
[void]$sb.AppendLine("")
foreach ($packageName in $tsToleratedPackages -split ',\s*') {
[void]$sb.AppendLine("- ``$packageName``")
Expand Down Expand Up @@ -694,7 +696,7 @@ if ($iconWarnings) {
[void]$sb.AppendLine("``$iconWarnings``")
[void]$sb.AppendLine("")
}
[void]$sb.AppendLine("### Review checklist")
[void]$sb.AppendLine("### Manual review checklist")
[void]$sb.AppendLine("")
[void]$sb.AppendLine("- [ ] Integration data looks reasonable (no suspicious anomalies)")
[void]$sb.AppendLine("- [ ] Package counts and versions updated appropriately")
Expand Down
Loading