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
12 changes: 9 additions & 3 deletions .github/workflows/rubocop.yml
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
---
name: lint
on: [push, pull_request]
permissions:
contents: read
concurrency:
group: rubocop-${{ github.ref }}
cancel-in-progress: true
jobs:
lint:
name: RuboCop
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
timeout-minutes: 10
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v7
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: 3.4
ruby-version: '4.0'
bundler-cache: true
- name: Run RuboCop
run: bundle exec rubocop
70 changes: 43 additions & 27 deletions .github/workflows/test-mongodb.yml
Original file line number Diff line number Diff line change
@@ -1,40 +1,56 @@
---
name: test
name: MongoDB
on: [push, pull_request]
permissions:
contents: read
concurrency:
group: mongodb-${{ github.ref }}
cancel-in-progress: true
jobs:
test:
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
timeout-minutes: 20
env:
DATABASE_ADAPTER: mongoid
MONGOID_VERSION: ${{ matrix.entry.mongoid }}
GRAPE_VERSION: ${{ matrix.entry.grape || '>= 0' }}
JSON_VERSION: ${{ matrix.entry.json }}
strategy:
fail-fast: false
matrix:
entry:
- { ruby: 3.2, mongoid: 6.4.8, mongodb: 4.4 }
- { ruby: 3.2, mongoid: 7.2.3, mongodb: 4.4 }
- { ruby: 3.2, mongoid: 7.3.0, mongodb: 4.4 }
- { ruby: 3.2, mongoid: 7.3.0, mongodb: 4.4 }
- { ruby: 3.3, mongoid: 7.3.0, mongodb: 5.0 }
- { ruby: 3.4, mongoid: 7.5.2, mongodb: 5.0 }
- { ruby: 3.4, mongoid: 8.1.11, mongodb: 6.0 }
- { ruby: 3.4, mongoid: 8.1.11, mongodb: 7.0 }
- { ruby: 3.4, mongoid: 8.1.11, mongodb: 8.0 }
name: test (ruby=${{ matrix.entry.ruby }}, mongoid=${{ matrix.entry.mongoid }}, mongodb=${{ matrix.entry.mongodb }})
# These Active Support versions pass quirks_mode, removed in JSON 3.
- { ruby: '3.2', mongoid: '6.4.8', mongodb: '4.4', json: '~> 2.0' }
- { ruby: '3.2', mongoid: '7.2.3', mongodb: '4.4', json: '~> 2.0' }
- { ruby: '3.2', mongoid: '7.3.0', mongodb: '4.4', json: '~> 2.0' }
- { ruby: '3.3', mongoid: '7.3.0', mongodb: '5.0', json: '~> 2.0' }
- { ruby: '3.4', mongoid: '7.5.2', mongodb: '5.0', json: '~> 2.0' }
- { ruby: '3.4', mongoid: '8.1.11', mongodb: '6.0', json: '~> 2.0' }
- { ruby: '3.4', mongoid: '8.1.11', mongodb: '7.0', json: '~> 2.0' }
- { ruby: '3.4', mongoid: '8.1.11', mongodb: '8.0', json: '~> 2.0' }
- { ruby: '3.3', mongoid: '~> 9.1', mongodb: '8.0', grape: '~> 3.2', json: '~> 3.0' }
- { ruby: '3.4', mongoid: '~> 9.1', mongodb: '8.0', grape: '~> 4.0', json: '~> 3.0' }
- { ruby: '4.0', mongoid: '~> 9.1', mongodb: '8.0', grape: '~> 4.0', json: '~> 3.0' }
name: test (ruby=${{ matrix.entry.ruby }}, mongoid=${{ matrix.entry.mongoid }}, mongodb=${{ matrix.entry.mongodb }}, grape=${{ matrix.entry.grape || 'auto' }}, json=${{ matrix.entry.json }})
services:
mongodb:
image: mongo:${{ matrix.entry.mongodb }}
ports:
- 27017:27017
options: >-
--health-cmd "mongosh --quiet --eval 'db.adminCommand({ ping: 1 })' || mongo --quiet --eval 'db.adminCommand({ ping: 1 })'"
--health-interval 10s
--health-timeout 5s
--health-retries 10
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v7
- uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.entry.ruby }}
- uses: browser-actions/setup-geckodriver@latest
bundler-cache: true
cache-version: mongoid-${{ matrix.entry.mongoid }}-grape-${{ matrix.entry.grape || 'auto' }}-json-${{ matrix.entry.json }}
- uses: browser-actions/setup-firefox@v1.7.2
with:
token: ${{ secrets.GITHUB_TOKEN }}
- run: geckodriver --version
- uses: supercharge/mongodb-github-action@1.7.0
with:
mongodb-version: ${{ matrix.entry.mongodb }}
firefox-version: latest
- name: Test
uses: GabrielBB/xvfb-action@v1
env:
DATABASE_ADAPTER: mongoid
MONGOID_VERSION: ${{ matrix.entry.mongoid }}
with:
run: |
bundle install
bundle exec rake spec
run: xvfb-run --auto-servernum bundle exec rake spec
78 changes: 48 additions & 30 deletions .github/workflows/test-postgresql.yml
Original file line number Diff line number Diff line change
@@ -1,43 +1,61 @@
---
name: test
name: PostgreSQL
on: [push, pull_request]
permissions:
contents: read
concurrency:
group: postgresql-${{ github.ref }}
cancel-in-progress: true
jobs:
test:
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
timeout-minutes: 20
env:
DATABASE_ADAPTER: activerecord
ACTIVERECORD_VERSION: ${{ matrix.entry.active_record }}
GRAPE_VERSION: ${{ matrix.entry.grape || '>= 0' }}
JSON_VERSION: ${{ matrix.entry.json }}
DATABASE_URL: postgres://test:password@localhost/slack_ruby_bot_server_test
strategy:
fail-fast: false
matrix:
entry:
- { ruby: 3.2, postgresql: 11, active_record: '~> 6.0.0' }
- { ruby: 3.2, postgresql: 11, active_record: '~> 6.1.0' }
- { ruby: 3.2, postgresql: 14, active_record: '~> 7.0.0' }
- { ruby: 3.3, postgresql: 14, active_record: '~> 7.2.0' }
- { ruby: 3.4, postgresql: 14, active_record: '~> 7.2.0' }
- { ruby: 3.4, postgresql: 15, active_record: '~> 8.0.2' }
- { ruby: 3.4, postgresql: 16, active_record: '~> 8.0.2' }
- { ruby: 3.4, postgresql: 17, active_record: '~> 8.0.2' }
name: test (ruby=${{ matrix.entry.ruby }}, postgresql=${{ matrix.entry.postgresql }}, active_record=${{ matrix.entry.active_record }})
# Active Support 6.x, 7.0, and 8.0 pass quirks_mode, removed in JSON 3.
- { ruby: '3.2', postgresql: '11', active_record: '~> 6.0.0', json: '~> 2.0' }
- { ruby: '3.2', postgresql: '11', active_record: '~> 6.1.0', json: '~> 2.0' }
- { ruby: '3.2', postgresql: '14', active_record: '~> 7.0.0', json: '~> 2.0' }
- { ruby: '3.3', postgresql: '14', active_record: '~> 7.2.0', json: '~> 3.0' }
- { ruby: '3.4', postgresql: '14', active_record: '~> 7.2.0', json: '~> 3.0' }
- { ruby: '3.4', postgresql: '15', active_record: '~> 8.0.2', json: '~> 2.0' }
- { ruby: '3.4', postgresql: '16', active_record: '~> 8.0.2', json: '~> 2.0' }
- { ruby: '3.4', postgresql: '17', active_record: '~> 8.0.2', json: '~> 2.0' }
- { ruby: '3.3', postgresql: '18', active_record: '~> 8.1', grape: '~> 3.2', json: '~> 3.0' }
- { ruby: '3.4', postgresql: '18', active_record: '~> 8.1', grape: '~> 4.0', json: '~> 3.0' }
- { ruby: '4.0', postgresql: '18', active_record: '~> 8.1', grape: '~> 4.0', json: '~> 3.0' }
name: test (ruby=${{ matrix.entry.ruby }}, postgresql=${{ matrix.entry.postgresql }}, active_record=${{ matrix.entry.active_record }}, grape=${{ matrix.entry.grape || 'auto' }}, json=${{ matrix.entry.json }})
services:
postgresql:
image: postgres:${{ matrix.entry.postgresql }}
env:
POSTGRES_DB: slack_ruby_bot_server_test
POSTGRES_USER: test
POSTGRES_PASSWORD: password
ports:
- 5432:5432
options: >-
--health-cmd "pg_isready -U test -d slack_ruby_bot_server_test"
--health-interval 10s
--health-timeout 5s
--health-retries 10
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v7
- uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.entry.ruby }}
- uses: browser-actions/setup-geckodriver@latest
with:
token: ${{ secrets.GITHUB_TOKEN }}
- run: geckodriver --version
- uses: harmon758/postgresql-action@v1
bundler-cache: true
cache-version: activerecord-${{ matrix.entry.active_record }}-grape-${{ matrix.entry.grape || 'auto' }}-json-${{ matrix.entry.json }}
- uses: browser-actions/setup-firefox@v1.7.2
with:
postgresql version: ${{ matrix.entry.postgresql }}
postgresql db: slack_ruby_bot_server_test
postgresql user: test
postgresql password: password
firefox-version: latest
- name: Test
uses: GabrielBB/xvfb-action@v1
env:
DATABASE_ADAPTER: activerecord
ACTIVERECORD_VERSION: ${{ matrix.entry.active_record }}
DATABASE_URL: postgres://test:password@localhost/slack_ruby_bot_server_test
with:
run: |
bundle install
bundle exec rake spec
run: xvfb-run --auto-servernum bundle exec rake spec
55 changes: 55 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Agent Instructions

## Project

Slack Ruby Bot Server is a Ruby gem providing a Grape API and multi-team Slack bot lifecycle management. Read [CONTRIBUTING.md](CONTRIBUTING.md) before making changes.

- `lib/slack-ruby-bot-server/api/`: endpoints, presenters, helpers, and middleware.
- `lib/slack-ruby-bot-server/models/` and `lib/slack-ruby-bot-server/ext/`: models and database-specific behavior.
- `lib/slack-ruby-bot-server/app.rb` and `service.rb`: application setup and service lifecycle.
- `public/`: registration UI and static assets.
- `spec/`: RSpec API, model, service, and browser integration tests.
- `spec/database_adapters/`: adapter setup, test schemas, and database cleanup.
- `.github/workflows/`: compatibility matrices, lint, and Danger.

## Dependencies and Tests

Set the adapter and version selectors before installing dependencies. Use a Ruby version covered by CI; the examples below match the current Ruby 4/Grape 4 jobs.

Start MongoDB locally, then run:

```sh
export DATABASE_ADAPTER=mongoid MONGOID_VERSION='~> 9.1' GRAPE_VERSION='~> 4.0' JSON_VERSION='~> 3.0'
export DATABASE_URL=mongodb://localhost/slack_ruby_bot_server_test
bundle install
bundle exec rake
```

For PostgreSQL, start the server and adjust local credentials in `DATABASE_URL` as needed:

```sh
export DATABASE_ADAPTER=activerecord ACTIVERECORD_VERSION='~> 8.1' GRAPE_VERSION='~> 4.0' JSON_VERSION='~> 3.0'
export DATABASE_URL=postgresql://localhost/slack_ruby_bot_server_test
bundle install
bundle exec rake
```

Use only a dedicated local test database. The suite deletes or truncates records, and the Active Record schema recreates the teams table.

`bundle exec rake` runs RuboCop and the full RSpec suite. Use `bundle exec rspec path/to/spec.rb` for focused checks. Validate shared behavior against both adapters before committing; batch final checks rather than repeatedly running full suites during editing.

Browser tests require Firefox. Selenium Manager provisions geckodriver when needed. On Linux, install Xvfb and run `xvfb-run --auto-servernum bundle exec rake`. Adapter suites must run sequentially on one host because Capybara uses port 9293.

`Gemfile.lock` is intentionally ignored. Re-resolve dependencies when switching adapter/version combinations; do not add the lockfile to the gem repository.

## Changes and Compatibility

Preserve both database adapters and the existing unique CI matrix combinations, including explicit Grape 3/4 coverage. Quote version strings in workflow YAML and validate workflow changes with `actionlint`.

Keep JSON 2 constraints scoped to affected legacy matrix jobs through `JSON_VERSION`; modern jobs explicitly test JSON 3. Do not add a blanket JSON upper bound to the Gemfile or gemspec.

Follow existing Ruby conventions and `.rubocop.yml`; do not relax cops or add exclusions just to make checks pass. Add focused regression tests for changed behavior and update directly related documentation. Keep Markdown paragraphs on one line.

Add a changelog entry under the next release, with contributor attribution and the linked PR number once available. Danger checks the changelog and table of contents.

Keep each PR branch to one logical commit. Include `Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>` for Copilot contributions, and identify AI-authored GitHub descriptions/comments as posted on behalf of the requesting user. Never force-push `master`. Do not publish a release or push a release tag without explicit authorization.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
### 2.2.1 (Next)

* Your contribution here.
* [#182](https://github.com/slack-ruby/slack-ruby-bot-server/pull/182): Modernize CI with current actions, native database services, dependency caching, and explicit Ruby 4, Mongoid 9, Active Record 8.1, PostgreSQL 18, Grape 3/4, and JSON 2/3 coverage while retaining existing compatibility combinations - [@dblock](https://github.com/dblock), [@Copilot](https://github.com/apps/copilot-swe-agent).
* [#181](https://github.com/slack-ruby/slack-ruby-bot-server/pull/181): Migrated Danger to `danger-pr-comment` workflow - [@dblock](https://github.com/dblock).
* [#180](https://github.com/slack-ruby/slack-ruby-bot-server/pull/180): Add support for Grape v3 - [@markokajzer](https://github.com/markokajzer).

Expand Down
15 changes: 10 additions & 5 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,20 @@ git checkout -b my-feature-branch

## Bundle Install and Test

Ensure that you can build the project and run tests.
Select a database adapter before installing dependencies. For example, to match the Ruby 4 MongoDB/Grape 4 job, start MongoDB locally and run:

```
```sh
export DATABASE_ADAPTER=mongoid MONGOID_VERSION='~> 9.1' GRAPE_VERSION='~> 4.0' JSON_VERSION='~> 3.0'
export DATABASE_URL=mongodb://localhost/slack_ruby_bot_server_test
bundle install
bundle exec rake
```

If you are a linux user, you will need to install [geckodriver](https://github.com/mozilla/geckodriver/releases), [firefox](https://download-installer.cdn.mozilla.net/pub/firefox/releases/), and `Xvfb`.
And, to get a display for the headless browser, run `Xvfb` manually. You can see more explanations [here](http://elementalselenium.com/tips/38-headless).
For PostgreSQL, set `DATABASE_ADAPTER=activerecord`, `ACTIVERECORD_VERSION`, and `DATABASE_URL` instead. `GRAPE_VERSION` optionally constrains the Grape version for either adapter; without it, Bundler selects a compatible version. CI preserves the older compatibility combinations and adds explicit Grape 3 and 4 jobs with current ORM versions, including Ruby 4. Each database runs in a health-checked service container, while Firefox runs under Xvfb. Selenium Manager provisions the matching driver.

`JSON_VERSION` optionally constrains the development/test JSON dependency; otherwise it is unrestricted. CI uses JSON 2 for Mongoid 6-8 and Active Record 6.x, 7.0, and 8.0 because their Active Support versions pass `quirks_mode`, removed in JSON 3. Mongoid 9, Active Record 7.2, and Active Record 8.1 jobs explicitly test JSON 3. These selectors do not restrict the published gem's runtime dependencies.

On Linux, install [Firefox](https://www.mozilla.org/firefox/) and `Xvfb`, then run:

```
xvfb-run --auto-servernum bundle exec rake
Expand Down Expand Up @@ -121,7 +126,7 @@ git push origin my-feature-branch -f

## Check on Your Pull Request

Go back to your pull request after a few minutes and see whether it passed muster with Travis-CI. Everything should look green, otherwise fix issues and amend your commit as described above.
Go back to your pull request after a few minutes and check its GitHub Actions results. Everything should look green, otherwise fix issues and update your commit as described above.

## Be Patient

Expand Down
2 changes: 2 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ gem 'fabrication'
gem 'faker'
gem 'faraday'
gem 'faraday-rack'
gem 'grape', ENV.fetch('GRAPE_VERSION', '>= 0')
gem 'hyperclient'
gem 'json', ENV.fetch('JSON_VERSION', '>= 0')
gem 'mutex_m'
gem 'rack'
gem 'rack-server-pages'
Expand Down
4 changes: 2 additions & 2 deletions spec/support/api/endpoints/it_behaves_like_a_cursor_api.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
models_ids.concat(response.map { |instance| instance._links.self._url.gsub("http://example.org/api/#{model_ps}/", '') })
break unless response._links[:next]

next_cursor = CGI.parse(URI.parse(response._links.next._url).query).map { |a| [a[0], a[1][0]] }.to_h
next_cursor = URI.decode_www_form(URI.parse(response._links.next._url).query).to_h
end
expect(models_ids.uniq.count).to eq model.all.count
end
Expand All @@ -44,7 +44,7 @@
models_ids.concat(response.map { |instance| instance._links.self._url.gsub("http://example.org/api/#{model_ps}/", '') })
break unless response._links[:next]

next_cursor = CGI.parse(URI.parse(response._links.next._url).query).map { |a| [a[0], a[1][0]] }.to_h
next_cursor = URI.decode_www_form(URI.parse(response._links.next._url).query).to_h
end
expect(models_ids.uniq.count).to eq model.all.count - 3
end
Expand Down
Loading