Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
56 changes: 56 additions & 0 deletions api/v1alpha1/taskspawner_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ type When struct {
// LinearWebhook triggers task spawning on Linear webhook events.
// +optional
LinearWebhook *LinearWebhook `json:"linearWebhook,omitempty"`

// Slack discovers work items from Slack messages via Socket Mode.
// The spawner connects to Slack via an outbound WebSocket (no ingress
// required) and listens for messages in the channels the bot is invited to.
// +optional
Slack *Slack `json:"slack,omitempty"`
}

// Cron triggers task spawning on a cron schedule.
Expand Down Expand Up @@ -394,6 +400,56 @@ type LinearWebhookFilter struct {
ExcludeLabels []string `json:"excludeLabels,omitempty"`
}

// Slack discovers work items from Slack messages via Socket Mode.
// The spawner connects to Slack using an App-Level Token (Socket Mode) and
// listens for messages in configured channels. No ingress, LoadBalancer, or
// public URL is required — the connection is outbound only.
//
// Authentication is provided via a Secret that must contain two keys:
// - SLACK_BOT_TOKEN: Bot User OAuth Token (xoxb-...)
// - SLACK_APP_TOKEN: App-Level Token for Socket Mode (xapp-...)
//
// The bot must be invited to each channel it should listen in.
type Slack struct {
// SecretRef references a Secret containing "SLACK_BOT_TOKEN" and
// "SLACK_APP_TOKEN" keys.
// +kubebuilder:validation:Required
SecretRef SecretReference `json:"secretRef"`

// TriggerCommand is an optional slash command or message prefix that
// triggers task creation (e.g., "/kelos", "!fix"). When set, only
// messages starting with this prefix trigger tasks and the prefix is
// stripped from the prompt. When empty, every non-threaded message in
// the channel triggers a task.
// +optional
TriggerCommand string `json:"triggerCommand,omitempty"`

// Channels optionally restricts which Slack channels the bot listens in.
// Values are channel IDs (e.g., "C0123456789"). When empty, the bot
// listens in every channel it has been invited to.
// +optional
Channels []string `json:"channels,omitempty"`

// AllowedUsers optionally restricts which Slack users can trigger tasks.
// Values are Slack user IDs (e.g., "U0123456789"). When empty, any user
// in the channel can trigger tasks.
// +optional
AllowedUsers []string `json:"allowedUsers,omitempty"`

// ResponseChannel optionally specifies a channel to post task status
// updates to (created, succeeded, failed). When empty, responses are
// posted as thread replies in the channel where the message was posted.
// +optional
ResponseChannel string `json:"responseChannel,omitempty"`

// PollInterval overrides spec.pollInterval for this source (e.g., "30s", "5m").
// Slack uses Socket Mode (real-time), but Discover() is still called on
// this interval to drain accumulated events. When empty, spec.pollInterval
// is used.
// +optional
PollInterval string `json:"pollInterval,omitempty"`
}

// TaskTemplateMetadata holds optional labels and annotations for spawned Tasks.
type TaskTemplateMetadata struct {
// Labels are merged into the spawned Task's labels. Values support Go
Expand Down
31 changes: 31 additions & 0 deletions api/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -955,6 +955,63 @@ spec:
required:
- types
type: object
slack:
description: |-
Slack discovers work items from Slack messages via Socket Mode.
The spawner connects to Slack via an outbound WebSocket (no ingress
required) and listens for messages in the channels the bot is invited to.
properties:
allowedUsers:
description: |-
AllowedUsers optionally restricts which Slack users can trigger tasks.
Values are Slack user IDs (e.g., "U0123456789"). When empty, any user
in the channel can trigger tasks.
items:
type: string
type: array
channels:
description: |-
Channels optionally restricts which Slack channels the bot listens in.
Values are channel IDs (e.g., "C0123456789"). When empty, the bot
listens in every channel it has been invited to.
items:
type: string
type: array
pollInterval:
description: |-
PollInterval overrides spec.pollInterval for this source (e.g., "30s", "5m").
Slack uses Socket Mode (real-time), but Discover() is still called on
this interval to drain accumulated events. When empty, spec.pollInterval
is used.
type: string
responseChannel:
description: |-
ResponseChannel optionally specifies a channel to post task status
updates to (created, succeeded, failed). When empty, responses are
posted as thread replies in the channel where the message was posted.
type: string
secretRef:
description: |-
SecretRef references a Secret containing "SLACK_BOT_TOKEN" and
"SLACK_APP_TOKEN" keys.
properties:
name:
description: Name is the name of the secret.
type: string
required:
- name
type: object
triggerCommand:
description: |-
TriggerCommand is an optional slash command or message prefix that
triggers task creation (e.g., "/kelos", "!fix"). When set, only
messages starting with this prefix trigger tasks and the prefix is
stripped from the prompt. When empty, every non-threaded message in
the channel triggers a task.
type: string
required:
- secretRef
type: object
type: object
required:
- taskTemplate
Expand Down
57 changes: 57 additions & 0 deletions internal/manifests/install-crd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1634,6 +1634,63 @@ spec:
required:
- types
type: object
slack:
description: |-
Slack discovers work items from Slack messages via Socket Mode.
The spawner connects to Slack via an outbound WebSocket (no ingress
required) and listens for messages in the channels the bot is invited to.
properties:
allowedUsers:
description: |-
AllowedUsers optionally restricts which Slack users can trigger tasks.
Values are Slack user IDs (e.g., "U0123456789"). When empty, any user
in the channel can trigger tasks.
items:
type: string
type: array
channels:
description: |-
Channels optionally restricts which Slack channels the bot listens in.
Values are channel IDs (e.g., "C0123456789"). When empty, the bot
listens in every channel it has been invited to.
items:
type: string
type: array
pollInterval:
description: |-
PollInterval overrides spec.pollInterval for this source (e.g., "30s", "5m").
Slack uses Socket Mode (real-time), but Discover() is still called on
this interval to drain accumulated events. When empty, spec.pollInterval
is used.
type: string
responseChannel:
description: |-
ResponseChannel optionally specifies a channel to post task status
updates to (created, succeeded, failed). When empty, responses are
posted as thread replies in the channel where the message was posted.
type: string
secretRef:
description: |-
SecretRef references a Secret containing "SLACK_BOT_TOKEN" and
"SLACK_APP_TOKEN" keys.
properties:
name:
description: Name is the name of the secret.
type: string
required:
- name
type: object
triggerCommand:
description: |-
TriggerCommand is an optional slash command or message prefix that
triggers task creation (e.g., "/kelos", "!fix"). When set, only
messages starting with this prefix trigger tasks and the prefix is
stripped from the prompt. When empty, every non-threaded message in
the channel triggers a task.
type: string
required:
- secretRef
type: object
type: object
required:
- taskTemplate
Expand Down
Loading