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
52 changes: 52 additions & 0 deletions .github/prompts/changelog-entries.prompt.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
messages:
- role: system
content: |-
You write CHANGELOG entries describing an automated API update to slack-ruby-client, a
Ruby gem whose Web API endpoint methods, argument validations, specs, and bin commands
are code-generated from JSON method definitions vendored from
https://github.com/slack-ruby/slack-api-ref (via a git submodule and rake task).

Given a diffstat and a diff of the regenerated files, respond with a JSON object:
{"entries": [string, ...]}

Rules for entries:
- Each entry is a single short line, imperative mood, no leading bullet/dash and no
trailing period (the caller adds both).
- Group related changes together into one entry per notable change or affected method
group (e.g. one entry for "Add chat.appendStream and chat.stopStream methods", one
entry for "Add a metadata argument to chat.postEphemeral, chat.postMessage,
chat.scheduleMessage, and chat.update"), rather than one entry per file.
- Focus on developer-visible API surface changes: new/removed/renamed methods, new/
removed/changed arguments (including required/mutually-exclusive validation changes),
new/removed error codes, and behavioral changes to generated code.
- Skip purely mechanical noise (e.g. reformatted docs/comments with no semantic change).
- Produce at most 8 entries. If there are no notable API surface changes, return a single
generic entry describing the update in one line.
- role: user
content: |-
Diffstat:
{{diff_stat}}

Diff (may be truncated):
{{diff}}
model: openai/gpt-4o-mini
responseFormat: json_schema
jsonSchema: |-
{
"name": "changelog_entries",
"strict": true,
"schema": {
"type": "object",
"properties": {
"entries": {
"type": "array",
"items": {
"type": "string"
},
"description": "1-8 short, imperative-mood CHANGELOG entry descriptions, no leading bullet or trailing period"
}
},
"additionalProperties": false,
"required": ["entries"]
}
}
68 changes: 63 additions & 5 deletions .github/workflows/update_api.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ jobs:
permissions:
contents: write
pull-requests: write
models: read
steps:
- uses: actions/checkout@v7
with:
Expand All @@ -32,6 +33,47 @@ jobs:
- name: Get slack-api-ref ref
id: api-ref
run: echo "api-ref=$(git rev-parse --short HEAD:lib/slack/web/api/slack-api-ref)" >> $GITHUB_OUTPUT
- name: Check for changes
id: changes
run: |
if git diff --quiet; then
echo "changed=false" >> "$GITHUB_OUTPUT"
else
echo "changed=true" >> "$GITHUB_OUTPUT"
fi
- name: Prepare diff for AI summary
if: steps.changes.outputs.changed == 'true'
run: |
git diff --stat > /tmp/diff_stat.txt
git diff | head -c 20000 > /tmp/diff.txt
- name: Generate changelog entries with AI
if: steps.changes.outputs.changed == 'true'
id: ai
uses: actions/ai-inference@v1
with:
prompt-file: ./.github/prompts/changelog-entries.prompt.yml
file_input: |
diff_stat: /tmp/diff_stat.txt
diff: /tmp/diff.txt
- name: Build changelog entries
id: entries
run: |
entries=""
if [ "${{ steps.changes.outputs.changed }}" = "true" ]; then
entries="$(jq -r '.entries[]? // empty' "${{ steps.ai.outputs.response-file }}" 2>/dev/null)"
fi
if [ -z "$entries" ]; then
entries="Update API from slack-api-ref@${{ steps.api-ref.outputs.api-ref }}"
fi
body_list="$(printf '%s\n' "$entries" | sed 's/^/- /')"
{
echo 'entries<<CHANGELOG_ENTRIES_EOF'
echo "$entries"
echo 'CHANGELOG_ENTRIES_EOF'
echo 'body_list<<CHANGELOG_BODY_EOF'
echo "$body_list"
echo 'CHANGELOG_BODY_EOF'
} >> "$GITHUB_OUTPUT"
- name: GitHub App token
if: ${{ github.repository == 'slack-ruby/slack-ruby-client' }}
id: github_app_token
Expand All @@ -52,6 +94,10 @@ jobs:
Update API from [slack-api-ref](https://github.com/slack-ruby/slack-api-ref).
Rev: ${{ steps.api-ref.outputs.api-ref }}
Date: ${{ steps.date.outputs.date }}

## Changes

${{ steps.entries.outputs.body_list }}
branch: automated-api-update
base: master
committer: slack-ruby-ci-bot <noreply@github.com>
Expand All @@ -62,12 +108,24 @@ jobs:
git fetch origin automated-api-update
git checkout automated-api-update
- name: Update CHANGELOG
uses: jacobtomlinson/gha-find-replace@v3
if: ${{ steps.cpr.outputs.pull-request-number != '' }}
with:
include: CHANGELOG.md
find: "\\* Your contribution here."
replace: "* [#${{steps.cpr.outputs.pull-request-number}}](https://github.com/slack-ruby/slack-ruby-client/pull/${{steps.cpr.outputs.pull-request-number}}): Update API from [slack-api-ref@${{ steps.api-ref.outputs.api-ref }}](https://github.com/slack-ruby/slack-api-ref/commit/${{ steps.api-ref.outputs.api-ref }}) - [@slack-ruby-ci-bot](https://github.com/apps/slack-ruby-ci-bot).\n* Your contribution here."
env:
PR_NUMBER: ${{ steps.cpr.outputs.pull-request-number }}
ENTRIES: ${{ steps.entries.outputs.entries }}
run: |
ruby - <<'RUBYEOF'
pr_number = ENV.fetch("PR_NUMBER")
pr_url = "https://github.com/slack-ruby/slack-ruby-client/pull/#{pr_number}"
entries = ENV.fetch("ENTRIES").each_line.map(&:strip).reject(&:empty?)

lines = entries.map do |entry|
"* [##{pr_number}](#{pr_url}): #{entry} - [@slack-ruby-ci-bot](https://github.com/apps/slack-ruby-ci-bot)."
end.join("\n")

content = File.read("CHANGELOG.md")
content = content.sub("* Your contribution here.", "#{lines}\n* Your contribution here.")
File.write("CHANGELOG.md", content)
RUBYEOF
- name: Commit and Push
if: ${{ steps.cpr.outputs.pull-request-number != '' }}
run: |
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
### 3.2.1 (Next)

* [#591](https://github.com/slack-ruby/slack-ruby-client/pull/591): Generate AI CHANGELOG entries and PR summaries for automated API update PRs, lock simplecov below 1.1.0 to avoid breaking Coveralls - [@dblock](https://github.com/dblock).
* Your contribution here.

### 3.2.0 (2026/07/05)
Expand Down
5 changes: 4 additions & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@ group :test do
gem 'rubocop-performance'
gem 'rubocop-rake'
gem 'rubocop-rspec'
gem 'simplecov'
# Lock below 1.1.0, which started writing float timestamps to
# coverage/.resultset.json, breaking coverallsapp/github-action's parser
# (coverallsapp/github-action#269, coverallsapp/coverage-reporter#191).
gem 'simplecov', '< 1.1.0'
gem 'simplecov-lcov'
gem 'timecop'
gem 'vcr'
Expand Down
Loading