Skip to content

feat: complete Slack integration UI and models - #396

Open
Amit-max-ui wants to merge 3 commits into
Devlaner:mainfrom
Amit-max-ui:feat/slack_integration_devlane2
Open

feat: complete Slack integration UI and models#396
Amit-max-ui wants to merge 3 commits into
Devlaner:mainfrom
Amit-max-ui:feat/slack_integration_devlane2

Conversation

@Amit-max-ui

@Amit-max-ui Amit-max-ui commented Jul 29, 2026

Copy link
Copy Markdown

Summary

Linked issues

Closes #

Type of change

  • Feature (feat:) — user-visible new capability
  • Bug fix (fix:) — corrects broken behavior
  • Refactor (refactor:) — no behavior change, internal only
  • Performance (perf:) — measurable improvement
  • Documentation (docs:) — README / CLAUDE.md / planning docs only
  • Tests (test:) — adds or corrects tests
  • Chore (chore:) — deps, tooling, CI, formatting
  • Style (style:) — visual / theming polish only

Surface

  • API (apps/api/)
  • UI (apps/web/)
  • Database migration (apps/api/migrations/)
  • Background jobs (RabbitMQ / queue)
  • Instance settings / Admin UI
  • Infra / Docker / CI

What changed

Why this approach

Database / migrations

  • Added apps/api/migrations/NNNNNN_<name>.up.sql AND matching .down.sql
  • Migration is idempotent / safe to re-run on a fresh DB
  • Migration applied cleanly via database.RunMigrations on startup

Breaking changes

  • No
  • Yes — described below

Test plan

  • npm run validate (root) — typecheck + lint + prettier + go vet + go test
  • [ ] Manual smoke test of the affected flow:

Screenshots / recordings (UI changes)

Before After

Rollout notes

AI assistance

  • No AI tools were used for this PR
  • AI tools were used — tool(s): ____ — and AI-assisted commits include a Co-Authored-By: trailer

Checklist

  • PR title follows Conventional Commits and is ≤ 100 chars
  • Hooks ran cleanly (no --no-verify bypass)
  • Trailing slashes on new routes match the surrounding pattern
  • New env vars added to internal/config/config.go and documented above
  • No secrets, tokens, or .env values committed

Summary by CodeRabbit

  • New Features
    • Added Slack integration with OAuth-based connection/disconnection.
    • Added workspace channel discovery and project-level channel linking with configurable event toggles.
    • Added Slack app configuration to instance administration settings.
    • Added background delivery of Slack notifications for project activity (including issue creation).
  • Bug Fixes
    • Improved integration redirect handling to support multiple providers.
    • Improved disconnect behavior to preserve other connected providers.
    • Escapes Slack message formatting content to prevent broken rendering.

@Amit-max-ui
Amit-max-ui requested a review from a team as a code owner July 29, 2026 21:59
@coderabbitai

coderabbitai Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@Amit-max-ui, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 8 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 40ac5125-4a93-4db8-9295-3cc6955a56d2

📥 Commits

Reviewing files that changed from the base of the PR and between dacfc95 and b26b80c.

📒 Files selected for processing (2)
  • apps/api/internal/queue/consumer.go
  • apps/web/src/components/integrations/SlackChannelSettingsModal.tsx
📝 Walkthrough

Walkthrough

Adds Slack OAuth installation, workspace channel linking, project notification settings, asynchronous Slack posting, and frontend controls for configuring and disconnecting Slack integrations.

Changes

Slack Integration

Layer / File(s) Summary
Slack OAuth and installation
apps/api/internal/oauth/slack.go, apps/api/internal/handler/integration.go, apps/api/internal/model/slack.go, apps/api/migrations/*
Adds Slack OAuth authorization and token exchange, installs workspace integrations, supports provider-specific redirects, and creates Slack channel-link persistence.
Channel linking and storage
apps/api/internal/service/integration.go, apps/api/internal/store/slack.go, apps/api/internal/router/router.go
Adds authenticated APIs and storage operations for listing, linking, updating, retrieving, and unlinking project Slack channels.
Slack notification delivery
apps/api/internal/service/notification.go, apps/api/internal/slack/*, apps/api/internal/queue/*, apps/api/cmd/api/main.go
Builds Slack messages, emits issue-created events, publishes Slack tasks to RabbitMQ, consumes them, and posts messages through Slack APIs.
Frontend configuration and controls
apps/web/src/components/integrations/*, apps/web/src/pages/instance-admin/*, apps/web/src/services/integrationService.ts, apps/web/src/api/types.ts
Adds Slack configuration display, OAuth connection controls, channel-link settings, event toggles, and API typings/client methods.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related PRs

  • Devlaner/devlane#395: Adds the Slack app settings consumed by this OAuth flow and instance-admin integration UI.

Suggested labels: enhancement, API, UI

Suggested reviewers: martian56

Poem

A rabbit hops where Slack bells ring,
Channels bloom with messages bright.
OAuth doors swing open wide,
Queues carry notes through moonlit night.
“Link a project!” the bunny sings.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description is just the default template with placeholders and no substantive summary, changes, rationale, or test plan. Fill in the Summary, What changed, Why this approach, Database/migrations, Test plan, Rollout notes, and checklist items with specific details.
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise, Conventional Commits-compliant, and accurately reflects the Slack UI/model integration work.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 8

🧹 Nitpick comments (1)
apps/web/src/components/integrations/IntegrationsSection.tsx (1)

24-28: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

IconSlack is duplicated verbatim in apps/web/src/pages/instance-admin/InstanceAdminIntegrationsPage.tsx (lines 17-21). Consider extracting IconSlack/IconGitHub into a shared provider-icon module so paths and sizing stay in sync.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/src/components/integrations/IntegrationsSection.tsx` around lines 24
- 28, IconSlack is duplicated across IntegrationsSection and
InstanceAdminIntegrationsPage, risking inconsistent provider icons. Extract
IconSlack and IconGitHub into a shared provider-icon module, then update both
consumers to import and reuse those shared components while preserving their
current paths, sizing, and accessibility attributes.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/api/internal/service/issue.go`:
- Around line 649-651: Update the issue-creation flow around IssueService so it
no longer calls NotificationService directly via s.notify.IssueCreated. Persist
a created-event or outbox record through the store, preferably within the issue
transaction, and leave notification delivery to the process that consumes that
record while preserving the services-call-stores boundary.

In `@apps/api/internal/service/notification.go`:
- Around line 525-530: Update the Slack publish flow around PublishSlackPost to
handle its returned error instead of discarding it. On failure, emit a warning
containing the relevant issue, project, and channel identifiers; if an existing
outbox or retry mechanism is available, persist the notification for retry as
well.
- Around line 516-530: Keep decrypted Slack credentials out of queued payloads
by passing only the integration/link identifier and message data. In
apps/api/internal/service/notification.go lines 516-530, remove Token from the
SlackPostPayload and include the identifier needed for resolution; update
apps/api/internal/queue/queue.go lines 56-62 to replace Token with that
identifier; in apps/api/internal/queue/consumer.go lines 163-192, resolve the
credential immediately before invoking Slack; and in apps/api/cmd/api/main.go
lines 129-130, inject the resolver/store into the Slack handler instead of
passing slack.PostMessage directly.

In `@apps/api/internal/slack/notification.go`:
- Around line 9-20: Update BuildSlackMessage to entity-escape dynamic mrkdwn
values—issueRef, title, actor, and action—before interpolating them into text
and block text, using the repository’s existing Slack escaping utility if
available. Preserve the intentional link markup around link and the existing
blocks return type.

In `@apps/web/src/components/integrations/SlackChannelSettingsModal.tsx`:
- Around line 78-84: Update the channel-linking flow around selectedChannelId
and slackLinkProjectChannel to use the existing translation mechanism for the
missing-channel error, return after setting that error, and avoid persisting a
placeholder channel name. Require a matching channel from channels before
calling slackLinkProjectChannel, using its actual name and preserving the
existing setError handling.
- Around line 193-238: Update handleSave so that when creating a new Slack
channel link, it follows the successful link request with
slackUpdateProjectChannel using the current eventCreated, eventStateChanged, and
eventCommented values. Ensure the modal only closes after both operations
succeed, while preserving the existing behavior for already-linked channels.

In `@apps/web/src/pages/instance-admin/InstanceAdminIntegrationsPage.tsx`:
- Around line 89-99: Update the integrations page sectioning around the Slack
entry and the existing source-control heading so Slack is not presented as a
source-control provider. Either categorize entries into separate Source control
and Communications sections using IntegrationsSection, or replace the heading
with a provider-agnostic label while preserving the existing integration rows.

In `@apps/web/src/services/integrationService.ts`:
- Around line 217-231: The slackGetProjectChannel method currently only
normalizes a 404 response, but the backend represents an unlinked channel with a
successful response whose data is null. Update the response handling in
slackGetProjectChannel to return null when the successful data value is null,
while preserving the existing 404 handling and rethrowing other errors.

---

Nitpick comments:
In `@apps/web/src/components/integrations/IntegrationsSection.tsx`:
- Around line 24-28: IconSlack is duplicated across IntegrationsSection and
InstanceAdminIntegrationsPage, risking inconsistent provider icons. Extract
IconSlack and IconGitHub into a shared provider-icon module, then update both
consumers to import and reuse those shared components while preserving their
current paths, sizing, and accessibility attributes.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 225327a1-43ae-4d65-945a-0c973cff3920

📥 Commits

Reviewing files that changed from the base of the PR and between dc8003c and 38e621c.

📒 Files selected for processing (22)
  • apps/api/cmd/api/main.go
  • apps/api/internal/handler/integration.go
  • apps/api/internal/model/notification.go
  • apps/api/internal/model/slack.go
  • apps/api/internal/oauth/slack.go
  • apps/api/internal/queue/consumer.go
  • apps/api/internal/queue/queue.go
  • apps/api/internal/router/router.go
  • apps/api/internal/service/integration.go
  • apps/api/internal/service/issue.go
  • apps/api/internal/service/notification.go
  • apps/api/internal/slack/client.go
  • apps/api/internal/slack/notification.go
  • apps/api/internal/store/integration.go
  • apps/api/internal/store/slack.go
  • apps/api/migrations/000013_slack_integration.down.sql
  • apps/api/migrations/000013_slack_integration.up.sql
  • apps/web/src/api/types.ts
  • apps/web/src/components/integrations/IntegrationsSection.tsx
  • apps/web/src/components/integrations/SlackChannelSettingsModal.tsx
  • apps/web/src/pages/instance-admin/InstanceAdminIntegrationsPage.tsx
  • apps/web/src/services/integrationService.ts

Comment on lines +649 to +651
if s.notify != nil {
s.notify.IssueCreated(ctx, issue, userID)
}

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.

📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy lift

Preserve the service/store boundary.

IssueService now invokes NotificationService directly. Persist a created-event/outbox row through a store (ideally in the issue transaction), then let notification delivery process that row.

As per coding guidelines, apps/api/**/*.go: “handlers call services, services call stores; handlers must never touch GORM directly, and stores must never call services.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/api/internal/service/issue.go` around lines 649 - 651, Update the
issue-creation flow around IssueService so it no longer calls
NotificationService directly via s.notify.IssueCreated. Persist a created-event
or outbox record through the store, preferably within the issue transaction, and
leave notification delivery to the process that consumes that record while
preserving the services-call-stores boundary.

Source: Coding guidelines

Comment thread apps/api/internal/service/notification.go
Comment thread apps/api/internal/service/notification.go Outdated
Comment thread apps/api/internal/slack/notification.go
Comment thread apps/web/src/components/integrations/SlackChannelSettingsModal.tsx
Comment thread apps/web/src/components/integrations/SlackChannelSettingsModal.tsx
Comment thread apps/web/src/pages/instance-admin/InstanceAdminIntegrationsPage.tsx
Comment thread apps/web/src/services/integrationService.ts

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/api/internal/queue/consumer.go`:
- Line 204: Update the message-posting flow around poster to derive a
per-message context with a finite timeout before invoking poster, and pass that
bounded context instead of the long-lived consumer context. Ensure the timeout
is always cancelled and retain the existing error handling and
message-processing behavior.

In `@apps/web/src/components/integrations/SlackChannelSettingsModal.tsx`:
- Around line 89-102: Update the save flow in SlackChannelSettingsModal so
onSaved is called immediately with the successful result from
slackLinkProjectChannel before invoking slackUpdateProjectChannel. Keep the
event-settings update afterward, and only call onSaved again with the updated
channel when that update succeeds.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 63d09e98-30bf-4fec-9284-0bd3bc8885fb

📥 Commits

Reviewing files that changed from the base of the PR and between 38e621c and dacfc95.

📒 Files selected for processing (10)
  • apps/api/cmd/api/main.go
  • apps/api/internal/queue/consumer.go
  • apps/api/internal/queue/queue.go
  • apps/api/internal/service/notification.go
  • apps/api/internal/slack/notification.go
  • apps/web/src/components/icons/IntegrationIcons.tsx
  • apps/web/src/components/integrations/IntegrationsSection.tsx
  • apps/web/src/components/integrations/SlackChannelSettingsModal.tsx
  • apps/web/src/pages/instance-admin/InstanceAdminIntegrationsPage.tsx
  • apps/web/src/services/integrationService.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/web/src/pages/instance-admin/InstanceAdminIntegrationsPage.tsx

Comment thread apps/api/internal/queue/consumer.go Outdated
Comment thread apps/web/src/components/integrations/SlackChannelSettingsModal.tsx Outdated
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.

1 participant