diff --git a/.band/changelog.yml b/.band/changelog.yml new file mode 100644 index 000000000..df4c918b1 --- /dev/null +++ b/.band/changelog.yml @@ -0,0 +1,17 @@ +# Per-repo config for the changelog-generator skill +# (changelog-generator@private-agent-skills), read from this repo's working tree +# at run time. NON-SECRET values only — secrets come from the workflow env: +# LINEAR_API_KEY, SLACK_WEBHOOK_URL, DISCORD_DRAFT_WEBHOOK_URL. + +# Fern docs repo that receives the changelog PR (opened as a DRAFT for a human to review and merge). +fern_repo: band-ai/fern +# Path within the Fern repo where changelog entries live. Match the layout of the +# newest existing entry in that repo. +fern_changelog_path: fern/changelog/sdks + +# Linear: how to find the issues that belong to this SDK's releases. The skill +# queries the Linear GraphQL API and also matches issue identifiers (e.g. SDK-123) +# found in the release's merged PRs. Set at least the team key. +linear: + team_key: INT + # project: "Python SDK" # optional: narrow further by project name diff --git a/.github/workflows/changelog.yml b/.github/workflows/changelog.yml new file mode 100644 index 000000000..d15efb111 --- /dev/null +++ b/.github/workflows/changelog.yml @@ -0,0 +1,82 @@ +name: Changelog + +# Publishes the release changelog when a GitHub Release is published (i.e. after +# release-please's release PR is merged on main). Runs the shared +# `changelog-generator` skill via the Claude Code Action, which: +# - reads merged Linear issues for the version (Linear GraphQL API) +# - opens a DRAFT PR to the Fern docs repo for a human to review and merge +# - posts the announcement to Slack (incoming webhook) +# - drafts the announcement into the private Discord review channel (webhook) +# - writes back a Linear Release + release notes (Linear GraphQL API) + +on: + release: + types: [published] + workflow_dispatch: + inputs: + tag: + description: "Release tag to generate the changelog for (defaults to latest release)" + required: false + type: string + +# Never run two changelog jobs for the same ref at once. +concurrency: + group: changelog-${{ github.ref }} + cancel-in-progress: false + +permissions: + contents: read + +jobs: + changelog: + runs-on: ubuntu-latest + timeout-minutes: 20 + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + fetch-depth: 0 # full history so the skill can diff the release range + + - name: Generate GitHub App token + id: app-token + uses: actions/create-github-app-token@v3 + with: + client-id: ${{ secrets.APP_CLIENT_ID }} + private-key: ${{ secrets.APP_PRIVATE_KEY }} + owner: band-ai + # Scope the token to exactly the repos the skill touches. The App must + # be installed on every repo listed here. + repositories: | + band-sdk-python + fern # Fern docs repo (github.com/band-ai/fern) + private-agent-skills # private marketplace repo the skill is installed from + + # The marketplace repo is private, so the action needs credentials to clone + # it. Rewrite only that repo's URL to use the App token (scoped narrowly so + # other github.com fetches are unaffected). + - name: Allow cloning the private marketplace repo + run: | + git config --global \ + url."https://x-access-token:${{ steps.app-token.outputs.token }}@github.com/band-ai/private-agent-skills".insteadOf \ + "https://github.com/band-ai/private-agent-skills" + + - name: Generate and publish changelog + uses: anthropics/claude-code-action@v1 + with: + anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} + github_token: ${{ steps.app-token.outputs.token }} + plugin_marketplaces: "https://github.com/band-ai/private-agent-skills.git" + plugins: "changelog-generator@private-agent-skills" + prompt: "/changelog-generator:generate ${{ github.event.release.tag_name || inputs.tag }}" + claude_args: | + --allowedTools "Bash,Read,Write,Edit,Glob,Grep" + --max-turns 30 + env: + # gh CLI + git use this token for the source repo and the Fern docs repo. + GH_TOKEN: ${{ steps.app-token.outputs.token }} + # Slack: posted live to the announcement channel. + SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} + # Discord: drafted into the private review channel for a human to forward. + DISCORD_DRAFT_WEBHOOK_URL: ${{ secrets.DISCORD_DRAFT_WEBHOOK_URL }} + # Linear: read issues + write the Release entry via GraphQL. + LINEAR_API_KEY: ${{ secrets.LINEAR_API_KEY }}