The Rootly Pulumi Provider enables you to manage Rootly resources using infrastructure-as-code. Rootly is a comprehensive incident management and workflow automation platform that helps teams respond to and learn from incidents.
See the v4 migration guide for service lookup changes, typed schedule rotation attributes, and the new Go SDK import path.
npm install @rootly/pulumior
yarn add @rootly/pulumirootly:apiToken(environment:ROOTLY_API_TOKEN) - API token from your Rootly account settingsrootly:baseUrl(environment:ROOTLY_BASE_URL) - Base URL for the Rootly API (optional, defaults to https://api.rootly.io)
import * as rootly from "@rootly/pulumi";
const sev0 = new rootly.Severity("sev0", {
name: "SEV0",
color: "#FF0000",
notifyEmails: ["oncall@acme.com"],
slackChannels: [{ id: "C06A4RZR9", name: "incidents-critical" }],
});
const sev1 = new rootly.Severity("sev1", {
name: "SEV1",
color: "#FFA500",
});
const production = new rootly.Environment("production", {
name: "Production",
color: "#FF0000",
slackChannels: [{ id: "C06A4RZR9", name: "incidents-prod" }],
});
const api = new rootly.Service("api", {
name: "api-gateway",
color: "#800080",
notifyEmails: ["platform@acme.com"],
});
const checkout = new rootly.Functionality("checkout", {
name: "Checkout Flow",
color: "#800080",
});const sre = new rootly.Team("sre", {
name: "SRE",
});const regionsAffected = new rootly.FormField("regions-affected", {
name: "Regions affected",
kind: "custom",
inputKind: "multi_select",
showns: ["web_new_incident_form", "web_update_incident_form"],
requireds: ["web_new_incident_form", "web_update_incident_form"],
});
new rootly.FormFieldOption("asia", {
formFieldId: regionsAffected.id,
value: "Asia",
});
new rootly.FormFieldOption("europe", {
formFieldId: regionsAffected.id,
value: "Europe",
});const overview = new rootly.Dashboard("overview", {
name: "Incident Overview",
});
new rootly.DashboardPanel("incidents-by-severity", {
dashboardId: overview.id,
name: "Incidents by Severity",
params: {
display: "line_chart",
datasets: [{
collection: "incidents",
filter: {
operation: "and",
rules: [{
operation: "and",
condition: "=",
key: "status",
value: "started",
}],
},
groupBy: "severity",
aggregate: {
cumulative: false,
key: "results",
operation: "count",
},
}],
},
});const titleField = rootly.getAlertFieldOutput({ kind: "title" });
const descField = rootly.getAlertFieldOutput({ kind: "description" });
const urlField = rootly.getAlertFieldOutput({ kind: "external_url" });
new rootly.AlertsSource("webhook-source", {
name: "Generic webhook source",
sourceType: "generic_webhook",
alertSourceFieldsAttributes: [
{ alertFieldId: titleField.id, templateBody: "Server alert" },
{ alertFieldId: descField.id, templateBody: "Alert triggered" },
{ alertFieldId: urlField.id, templateBody: "https://rootly.com" },
],
sourceableAttributes: {
autoResolve: true,
resolveState: "$.status",
fieldMappingsAttributes: [
{ field: "state", jsonPath: "$.my_group_attribute" },
{ field: "external_id", jsonPath: "$.my_id_attribute" },
],
},
});const jiraWorkflow = new rootly.WorkflowIncident("jira-on-incident", {
name: "Create a Jira Issue",
description: "Open Jira ticket whenever incident starts",
triggerParams: {
triggers: ["incident_created"],
incidentConditionKind: "IS",
incidentKinds: ["normal"],
incidentConditionStatus: "IS",
incidentStatuses: ["started"],
},
enabled: true,
});
new rootly.WorkflowTaskCreateJiraIssue("jira-task", {
workflowId: jiraWorkflow.id,
taskParams: {
title: "{{ incident.title }}",
description: "{{ incident.summary }}",
projectKey: "ROOT",
issueType: { id: "10001", name: "Task" },
status: { id: "10000", name: "To Do" },
labels: '{{ incident.environment_slugs | concat: incident.service_slugs | join: "," }}',
},
});const notifyWorkflow = new rootly.WorkflowIncident("notify-slack", {
name: "Notify teams on Slack",
description: "Send a message to teams on Slack about the incident",
triggerParams: {
triggers: ["incident_created"],
incidentConditionStatus: "IS",
incidentStatuses: ["started"],
},
enabled: true,
});
new rootly.WorkflowTaskSendSlackMessage("notify-slack-task", {
workflowId: notifyWorkflow.id,
taskParams: {
channels: [{
id: "{{ incident.slack_channel_id }}",
name: "{{ incident.slack_channel_id }}",
}],
text: "Heads up - we have an active incident.",
},
});const pageWorkflow = new rootly.WorkflowIncident("page-pagerduty", {
name: "Page responders via PagerDuty",
description: "Automatically page responders when incident starts",
triggerParams: {
triggers: ["incident_created"],
incidentConditionStatus: "IS",
incidentStatuses: ["started"],
},
enabled: true,
});
new rootly.WorkflowTaskPagePagerdutyOnCallResponders("page-pd-task", {
workflowId: pageWorkflow.id,
taskParams: {},
});const critical = rootly.getSeverityOutput({ slug: "sev0" });
const smsWorkflow = new rootly.WorkflowIncident("sms-on-critical", {
name: "SMS on-call for critical incidents",
description: "Send SMS when critical incident starts",
triggerParams: {
triggers: ["incident_created"],
incidentConditionKind: "IS",
incidentKinds: ["normal"],
incidentConditionStatus: "IS",
incidentStatuses: ["started"],
severityIds: [critical.id],
},
enabled: true,
});
new rootly.WorkflowTaskSendSms("sms-task", {
workflowId: smsWorkflow.id,
taskParams: {
phoneNumbers: ["+11231231234"],
content: "Critical incident started",
},
});const schedule = new rootly.Schedule("primary", {
name: "Primary On-Call Schedule",
});
const weekdays = new rootly.ScheduleRotation("weekdays", {
scheduleId: schedule.id,
name: "Weekdays",
activeAllWeek: false,
activeDays: ["M", "T", "W", "R", "F"],
activeTimeType: "custom",
position: 1,
scheduleRotationableAttributes: { handoffTime: "10:00" },
scheduleRotationableType: "ScheduleDailyRotation",
timeZone: "America/Toronto",
});
const policy = new rootly.EscalationPolicy("primary", {
name: "Primary",
});
const defaultPath = new rootly.EscalationPath("default", {
name: "Default",
default: true,
escalationPolicyId: policy.id,
});
new rootly.EscalationLevel("first", {
escalationPolicyPathId: defaultPath.id,
escalationPolicyId: policy.id,
position: 1,
notificationTargetParams: [
{ type: "schedule", id: schedule.id, teamMembers: "all" },
],
});pulumi preview # Preview changes
pulumi up # Deploy resources
pulumi stack # View current stack- Incident Management: Severities, Services, Teams, Incident Types, Incident Roles, SLAs
- Catalog: Catalogs, Catalog Entities, Catalog Properties
- Workflow Automation: Workflows, Workflow Tasks (50+ task types including Jira, Slack, PagerDuty, email, SMS, and more)
- On-Call: Schedules, Rotations, Escalation Policies, Escalation Paths
- Alerts: Alert Sources, Alert Groups, Alert Routes, Alert Urgencies
- Configuration: Custom Fields, Forms, Environments, Functionalities
- Communications: Communications Groups, Stages, Templates, Types
- Integrations: Webhooks, Secrets, Heartbeats, Edge Connectors
- Access Control: Roles, Permissions, API Keys
- Dashboards: Dashboard Panels, Status Pages
make update_provider # Update upstream Terraform provider
make development # Build provider + SDKs + lint
make build_nodejs # Build Node.js SDK only
make lint_provider # Lint provider code
make test # Run integration tests (requires ROOTLY_API_TOKEN)For detailed API documentation, visit the Pulumi Registry.