ci/praktika/infrastructure/native/README.md
This directory contains cloud components provided natively by praktika.
The Slack app integration consists of two AWS Lambda functions that work together to provide real-time CI/CD notifications and interactive features.
Main Lambda function that handles synchronous Slack interactions and must respond within Slack's 3-second limit:
/praktika subscribe [email], /praktika unsubscribeBackground worker Lambda that handles asynchronous processing:
response_urlpraktika/event.py (Event, EventFeed, FeedSubscription classes)graph TB
subgraph "Slack"
SlackUI[Slack UI]
end
subgraph "AWS Lambda"
App[lambda_slack_app
Slash Commands & Interactivity]
Worker[lambda_slack_worker
Background Processing]
end
subgraph "Storage"
S3[(S3 Bucket)]
end
subgraph "CI Workflows"
Workflow[Praktika Workflows
runner.py]
end
SlackUI -->|"POST /slack/events
(slash commands, home_opened)"| App
App -->|"Invoke async
(subscribe/unsubscribe)"| Worker
Worker -->|"views.publish
(home tab)"| SlackUI
Worker -->|"POST response_url
(slash command follow-up)"| SlackUI
Workflow -->|"EventFeed.update()
(workflow results as Event)"| S3
Workflow -->|"Lambda.invoke()
(notify subscribers)"| Worker
Worker -->|"EventFeed.from_s3()
FeedSubscription.get_user_ids()"| S3
Worker -->|"FeedSubscription.add_user_id()
FeedSubscription.remove_user_id()"| S3
S3 -->|"EventFeed data
(per commit author email)"| Worker
S3 -->|"FeedSubscription data
(Slack user mappings)"| Worker
style App fill:#e1f5ff
style Worker fill:#fff4e1
style S3 fill:#f0f0f0
style Workflow fill:#e8f5e9
User subscribes (Slack → Lambda App → Lambda Worker → S3)
/praktika subscribe [email] in Slacklambda_slack_app validates request signature, immediately ACKs Slack, and invokes lambda_slack_worker asynchronously with action="subscribe" (including response_url)FeedSubscription.add_user_id() to store mapping in S3, loads EventFeed.from_s3(), and publishes home viewresponse_urlCI workflow completes (Workflow → S3 → Lambda Worker → Slack)
Result.to_event() to convert workflow result to EventEventFeed.update() saves Event to S3 at {s3_path}/{email}.json.gzlambda_slack_worker with action="update"Home view display (Slack → Lambda App → Lambda Worker → Slack)
app_home_opened event)lambda_slack_app invokes lambda_slack_worker with action="update"views.publish to update home tabThe Home tab renders interactive toggle buttons (stored in FeedSubscription.user_prefs per Slack user id):
Merged PRs: On/Off (hide_merged_prs)
pr_number == 0) are still shown unless Merges is turned On.Merges: On/Off (hide_merges)
Auxilary PRs: On/Off (hide_secondary_prs)
parent_pr_number > 0 and pr_number > 0).< 7d: On/Off (show_last_7d)
Notify complete: On/Off (notify_on_complete)Notify failure: On/Off (notify_on_failure)When enabled per user:
type == completed.failure or error.result.results[*].name).s3://{bucket}/{prefix}/
├── {email}.json.gz # EventFeed: List of Events per commit author email
├── email_{email}.json # FeedSubscription: Slack user_ids subscribed to this email
└── slack_{slack_user_id}.json # Reverse lookup: Which email this Slack user subscribed to
Event:
- type: "running" | "completed"
- pr_number, pr_status, pr_title
- ci_status: "pending" | "running" | "success" | "failure"
- result: dict # Top-level workflow Result.to_dict()
- status, start_time, duration
- results: list[dict] # Individual job results
- ext: {"report_url": str}
- links: [PR_URL, RUN_URL]
Notes:
- Merge-result events use `pr_number == 0` and are treated as `pr_status == merged`.
- Merge-result events can reference `parent_pr_number` and `linked_pr_number`; corresponding PR entries in the feed are marked `pr_status == merged`.
Add Slack app Lambdas to your cloud infrastructure configuration:
from praktika import CloudInfrastructure
CLOUD = CloudInfrastructure.Config(
name="my_cloud_infra",
lambda_functions=[*CloudInfrastructure.SLACK_APP_LAMBDAS]
)
praktika infrastructure --deploy
Required secrets (automatically fetched during deployment):
praktika_slack_app_signing_secret → SIGN_SECRETpraktika_slack_app_token → SLACK_BOT_TOKENEVENT_FEED_S3_PATH → S3 bucket/prefix for EventFeed and FeedSubscription datafrom praktika import Workflow
workflow = Workflow.Config(
name="MyWorkflow",
enable_slack_feed=True, # Enable Event publishing and Lambda invocation
# ...
)
Future native components under consideration: