Skip to content

Feature: implement Slack integration and notification pipeline - #395

Open
Amit-max-ui wants to merge 4 commits into
Devlaner:mainfrom
Amit-max-ui:feat/slack_integration_devlane
Open

Feature: implement Slack integration and notification pipeline#395
Amit-max-ui wants to merge 4 commits into
Devlaner:mainfrom
Amit-max-ui:feat/slack_integration_devlane

Conversation

@Amit-max-ui

@Amit-max-ui Amit-max-ui commented Jul 28, 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 configuration for instance administrators.
    • Configure Slack client ID, client secret, and signing secret with secure show/hide controls.
    • Added the Slack OAuth redirect URL with quick setup guidance and copy support.
    • Added Slack to the integrations overview, with configuration status and navigation.
    • Added a web app start script for local development.
  • Bug Fixes

    • Ensured Slack settings remain available with correct defaults when not yet initialized.

@Amit-max-ui
Amit-max-ui requested a review from a team as a code owner July 28, 2026 18:14
@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Adds Slack app settings support to the API and a new instance-admin Slack integration flow, including credential management, OAuth redirect display, integration listing, routing, breadcrumbs, and Vite startup configuration.

Changes

Slack integration

Layer / File(s) Summary
Slack settings API
apps/api/internal/handler/instance.go
Adds the slack_app settings section, default values, secret-field handling, and encrypted credential updates with *_set flags.
Integration listing and route wiring
apps/web/src/api/types.ts, apps/web/src/pages/instance-admin/InstanceAdminIntegrationsPage.tsx, apps/web/src/pages/instance-admin/index.ts, apps/web/src/routes/index.tsx, apps/web/src/components/layout/InstanceAdminLayout.tsx, apps/web/package.json
Adds Slack settings typing, an integrations card, lazy-loaded admin routing, breadcrumb labeling, and a Vite start script.
Slack credential configuration
apps/web/src/pages/instance-admin/InstanceAdminIntegrationSlackPage.tsx
Adds credential loading, secret visibility controls, conditional updates, save feedback, setup instructions, and OAuth redirect URL display.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Admin
  participant SlackPage
  participant SettingsAPI
  participant SettingsStore
  Admin->>SlackPage: Open Slack integration
  SlackPage->>SettingsAPI: Load slack_app and auth config
  SettingsAPI-->>SlackPage: Return settings and redirect base
  Admin->>SlackPage: Submit credentials
  SlackPage->>SettingsAPI: Update slack_app
  SettingsAPI->>SettingsStore: Encrypt and save non-empty secrets
  SettingsStore-->>SettingsAPI: Return updated settings
  SettingsAPI-->>SlackPage: Return saved settings
Loading

Suggested reviewers: martian56

Poem

A bunny hops where Slack flags glow,
Secrets tuck safely down below.
The page now guides each setup track,
With OAuth paths and buttons back.
“Save!” cries the hare—credentials stack!

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description is still the default template and lacks the required filled-in summary, change details, test plan, rollout notes, and checklists. Replace the template placeholders with a real summary, linked issue, what changed, why, test plan, rollout notes, and completed checklist items.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.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 and matches the main change: adding Slack integration features.
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

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 golangci-lint (2.12.2)

level=error msg="[linters_context] typechecking error: pattern ./...: directory prefix . does not contain main module or its selected dependencies"


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: 4

🤖 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/handler/instance.go`:
- Line 287: Update the Slack secret registration near the "slack_app"
configuration so decrypted client_secret and signing_secret are excluded from
settings GET and PATCH responses. Preserve only the corresponding
client_secret_set and signing_secret_set flags in the API response, consistent
with the UI contract that plaintext secrets are never returned.
- Around line 523-557: Move the Slack-specific merge and secret-encryption logic
from the handler branch around the key "slack_app" into an instance-settings
service method, including the h.Settings.Get access. Update the handler to
delegate the Slack settings update to that service and use its returned value,
preserving default merging, client_id handling, and secret flags.

In `@apps/web/src/pages/instance-admin/InstanceAdminIntegrationsPage.tsx`:
- Around line 105-114: Update the integrations renderer in
InstanceAdminIntegrationsPage to group or filter providers by their category,
preserving the existing source-control section and adding a messaging section
for entries such as the Slack provider. Ensure the Slack integration is rendered
under messaging rather than beneath the static Source control heading, using the
existing category field.
- Around line 80-81: Update the Slack settings lookup in the page’s
settings-loading flow to read the backend’s `slack_app` section key instead of
`settings.slack`, while preserving the existing fallback to an empty object and
the subsequent setSlack call.
🪄 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: 22f82c41-dbe3-4cfa-92bf-0c440524ca3e

📥 Commits

Reviewing files that changed from the base of the PR and between dc8003c and 1d25fd2.

📒 Files selected for processing (8)
  • apps/api/internal/handler/instance.go
  • apps/web/package.json
  • apps/web/src/api/types.ts
  • apps/web/src/components/layout/InstanceAdminLayout.tsx
  • apps/web/src/pages/instance-admin/InstanceAdminIntegrationSlackPage.tsx
  • apps/web/src/pages/instance-admin/InstanceAdminIntegrationsPage.tsx
  • apps/web/src/pages/instance-admin/index.ts
  • apps/web/src/routes/index.tsx

"ai": {"api_key"},
"image": {"unsplash_access_key"},
"github_app": {"private_key", "client_secret", "webhook_secret"},
"slack_app": {"client_secret", "signing_secret"},

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.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Do not serialize decrypted Slack secrets.

Registering these fields makes both settings GET and PATCH responses return plaintext Slack credentials via decryptSectionSecretsInternal, despite the UI contract that secrets are never echoed. Redact secret fields from API responses and return only their *_set flags.

🤖 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/handler/instance.go` at line 287, Update the Slack secret
registration near the "slack_app" configuration so decrypted client_secret and
signing_secret are excluded from settings GET and PATCH responses. Preserve only
the corresponding client_secret_set and signing_secret_set flags in the API
response, consistent with the UI contract that plaintext secrets are never
returned.

Comment on lines +523 to +557
if key == "slack_app" {
existing, _ := h.Settings.Get(c.Request.Context(), "slack_app")
merged := model.JSONMap{}

if existing != nil {
for k, v := range existing.Value {
merged[k] = v
}
} else {
for k, v := range defaultSettingValue("slack_app") {
merged[k] = v
}
}

/* plain feilds */
for _, feild := range []string{"client_id"} {
if v, ok := req.Value[feild]; ok {
merged[feild] = v
}
}

/* Secret fields (Encrypt & Set flag) */
setSecret := func(feild, setKey string) {
if v, ok := req.Value[feild]; ok {
if s, ok := v.(string); ok && s != "" {
merged[feild] = crypto.EncryptOrPlain(s)
merged[setKey] = true
}
}
}

setSecret("client_secret", "client_secret_set")
setSecret("signing_secret", "signing_secret_set")
value = merged
}

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

Keep Slack settings updates in the service layer.

This new handler branch calls h.Settings.Get directly. Move Slack merge/encryption logic behind an instance-settings service so the handler delegates and the service owns store access.

As per path instructions, apps/api/**/*.go requires “handlers call services, services call stores.”

🤖 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/handler/instance.go` around lines 523 - 557, Move the
Slack-specific merge and secret-encryption logic from the handler branch around
the key "slack_app" into an instance-settings service method, including the
h.Settings.Get access. Update the handler to delegate the Slack settings update
to that service and use its returned value, preserving default merging,
client_id handling, and secret flags.

Source: Path instructions

Comment on lines +80 to +81
const sl = (settings.slack || {}) as InstanceSlackAppSection;
setSlack(sl);

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.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Read the API’s slack_app section key.

The backend returns slack_app, but this reads settings.slack; the list therefore always receives {} and shows Slack as “Not configured” after credentials are saved.

-const sl = (settings.slack || {}) as InstanceSlackAppSection;
+const sl = (settings.slack_app || {}) as InstanceSlackAppSection;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const sl = (settings.slack || {}) as InstanceSlackAppSection;
setSlack(sl);
const sl = (settings.slack_app || {}) as InstanceSlackAppSection;
setSlack(sl);
🤖 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/pages/instance-admin/InstanceAdminIntegrationsPage.tsx` around
lines 80 - 81, Update the Slack settings lookup in the page’s settings-loading
flow to read the backend’s `slack_app` section key instead of `settings.slack`,
while preserving the existing fallback to an empty object and the subsequent
setSlack call.

Comment on lines +105 to +114
category: 'source-control',
},
{
id: 'slack',
name: 'Slack',
desc: 'Post Devlane notifications (assigned, state changed, commented, mentioned) to a Slack channel per project.',
Icon: IconSlack,
editPath: '/instance-admin/integrations/slack',
configured: isSlackConfigured(slack),
category: 'messaging',

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.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Render Slack under a messaging section.

category: 'messaging' is unused: the renderer maps every provider beneath the static “Source control” heading. Filter/group by category and add a messaging section so Slack is not mislabeled.

🤖 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/pages/instance-admin/InstanceAdminIntegrationsPage.tsx` around
lines 105 - 114, Update the integrations renderer in
InstanceAdminIntegrationsPage to group or filter providers by their category,
preserving the existing source-control section and adding a messaging section
for entries such as the Slack provider. Ensure the Slack integration is rendered
under messaging rather than beneath the static Source control heading, using the
existing category field.

@martian56

Copy link
Copy Markdown
Member

@Amit-max-ui Please take a look at coderabbit's comments, Thank you for your contributions

@Amit-max-ui

Copy link
Copy Markdown
Author

@martian56 Alright, I will check these codeRabbit comments, resolve them, and create a PR fixing those.

@martian56

Copy link
Copy Markdown
Member

@martian56 Alright, I will check these codeRabbit comments, resolve them, and create a PR fixing those.

You can push the fixes to this PR as well, instead of creating a new PR. Thanks

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.

2 participants