Skip to main content

emberpost

pytest ruff release PyPI prek


Introduction

emberpost keeps Slack and Microsoft Teams aligned with the current PagerDuty on-call rotation. It reads a YAML schedule definition, resolves the active on-call users from PagerDuty, and publishes each schedule group to its effective provider destination.

Use it to post an on-call summary to Slack or Microsoft Teams, update a Slack channel topic, or keep a Slack user group in sync with the people currently carrying the pager. Schedule files can be marked as daily, weekly, or manual, which makes the same command safe to run from automation while only processing the rotations due for that run.

Start with examples/01-minimal.yaml for the smallest working schedule shape, then add channel topics, user groups, headers, or footers as needed.

Usage

Install the project and its dependencies with uv:

uv sync

Commands can then be run through uv run, which uses the project environment automatically. The --frequency flag is an automation guardrail: a weekly schedule is skipped during a daily run. For a Slack provider, set destination.provider.options.set_channel_topic: true to update a channel topic instead of posting a message.

Run a dry run before writing to a destination provider:

uv run emberpost --schedule-file schedules/oncall.yaml --frequency weekly --dry-run

Run the weekly schedule and update its configured destinations:

uv run emberpost --schedule-file schedules/oncall.yaml --frequency weekly

Process more than one schedule file in a single run:

uv run emberpost --schedule-file schedules/oncall.yaml examples/03-full.yaml --frequency weekly

Run a manual schedule file:

uv run emberpost --schedule-file examples/01-minimal.yaml --frequency manual --dry-run

Run with more logging while troubleshooting:

uv run emberpost --schedule-file schedules/oncall.yaml --frequency weekly --dry-run --log-level DEBUG

The top-level destination is used by every schedule group that does not define a complete override. Provider-specific settings live under provider.options:

pagerduty_tenant: example.pagerduty.com

destination:
  provider:
    name: slack
    options:
      space: example.slack.com
      channel_id: C0123456789
      set_channel_topic: false

schedule_groups:
  Platform Coverage:
    entries:
      - schedule_id: PEXAMPLE1
        label: "Primary Responder"

Add slack_group_id to a group using an effective Slack destination to synchronize that group's resolved users to a Slack user group. A group may replace the default with another complete Slack or Microsoft Teams destination:

pagerduty_tenant: example.pagerduty.com

destination:
  provider:
    name: slack
    options:
      space: example.slack.com
      channel_id: C0123456789
      set_channel_topic: false

schedule_groups:
  Platform Coverage:
    slack_group_id: S0123456789
    entries:
      - schedule_id: PEXAMPLE1
        label: "Primary Responder"
  Database Coverage:
    destination:
      provider:
        name: slack
        options:
          space: database-team.slack.com
          channel_id: C0987654321
          set_channel_topic: true
    entries:
      - schedule_id: PEXAMPLE2
        label: "Database Responder"
  Incident Coverage:
    destination:
      provider:
        name: msteams
        options:
          webhook_env: MSTEAMS_WEBHOOK_INCIDENT
    entries:
      - schedule_id: PEXAMPLE3
        label: "Incident Commander"

Here, Platform Coverage uses the default Slack destination, Database Coverage replaces it with another Slack channel topic, and Incident Coverage posts through a Microsoft Teams Workflows webhook.

Setting up your Slack Bot

Bot Information

This section is just an example manifest, to show what is needed to get the bot working for the posting use.

display_information:
  name: Notification
  description: Notification webhook/app
  background_color: "#2c2d30"
features:
  bot_user:
    display_name: Notification
    always_online: false
oauth_config:
  scopes:
    bot:
      - channels:write.topic
      - chat:write
      - chat:write.customize
      - chat:write.public
      - files:read
      - files:write
      - users:read
      - users:read.email
      - groups:write.topic
      - mpim:history
      - im:write.topic
      - mpim:write.topic
      - usergroups:write
  pkce_enabled: false
settings:
  interactivity:
    is_enabled: true
    request_url: https://example.com/ignore
  org_deploy_enabled: false
  socket_mode_enabled: false
  token_rotation_enabled: false
  is_mcp_enabled: false

Create a slack app

  1. Set Up Your App
    1. Go to the Slack API portal.
    2. Click Create New App.
    3. Choose From scratch and give your app a name and select the workspace where it will be installed.
      1. Or if you are choosing to copy one of the above templates/manifests then you can choose From a manifest and speed up the process.
  2. Configure App Features
    1. Depending on what your app needs to do, you can enable features like:
      1. Bot Token: For sending messages and interacting with users.
      2. Event Subscriptions: To listen for events like messages or reactions.
  3. Set Permissions (Scopes)
    1. Go to OAuth & Permissions.
    2. Add the necessary OAuth scopes (e.g., chat:write, commands, users:read).
      1. These define what your app is allowed to do in the workspace.
  4. Install the App
    1. Still in the OAuth & Permissions section, click "Install to Workspace".
    2. Authorize the app to access your workspace.
    3. A Slack Admin for your organization will need to review the request
    4. You’ll receive a Bot User OAuth Token once approved
      1. save this securely.

Configure Slack credentials

For each configured Slack workspace, uppercase the hostname and replace non-alphanumeric characters with underscores. Store its bot token in the resulting environment variable:

example.slack.com -> SLACK_API_KEY_EXAMPLE_SLACK_COM

To find a channel ID, copy the Slack channel link. The final path segment beginning with C is the channel ID.

Setting up Microsoft Teams

In Teams, open Workflows, search for an incoming-webhook template, and choose the template that posts to your intended channel or chat. Microsoft provides separate templates for channels, chats, and different authentication modes; these Teams webhook templates do not require a premium license. Select Anyone as the trigger authentication mode because Emberpost authenticates with the secret webhook URL and does not send an OAuth token. Choose the destination, save the workflow, add co-owners for operational continuity, and copy the generated webhook URL.

Store the URL in the environment variable named by webhook_env:

destination:
  provider:
    name: msteams
    options:
      webhook_env: MSTEAMS_WEBHOOK_INCIDENT

Do not store a Teams webhook URL directly in schedule YAML. Each Teams Workflows webhook is bound to the chat or channel selected in its workflow, so no separate Team or channel ID is required. See Microsoft's incoming webhook setup guide for the current template flow.

Metadata

Release files for emberpost 0.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for emberpost 0.3.0
File Size Uploaded
emberpost-0.3.0.tar.gz 14.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for emberpost 0.3.0
File Interpreter ABI Platform
emberpost-0.3.0-py3-none-any.whl Python 3 none any Details

Total release size: 30.9 kB

Release files / emberpost-0.3.0.tar.gz

Download URL emberpost-0.3.0.tar.gz
Size 14.0 kB
Tags Source
SHA-256 checksum
How to use checksums
7b105f69e973db8d0bbb1a9135e2a7eb42fe2b63fae327a48d37971241849e6d
BLAKE2b-256 checksum
How to use checksums
3e5484ceed240370a2ff24ebd6b06c90a078250e52eb4f09eb769e92f040b7cd
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.15 {"installer":{"name":"uv","version":"0.12.15","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / emberpost-0.3.0-py3-none-any.whl

Download URL emberpost-0.3.0-py3-none-any.whl
Size 17.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
493dae82b8fb33b784394f027bf0ad22946bc9c88aa62f14299f34068a395419
BLAKE2b-256 checksum
How to use checksums
576d68c576d388fd1c614cbf75cd8069e772e365d2e4f106befc0809aa9a7e35
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.15 {"installer":{"name":"uv","version":"0.12.15","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

This release

0.3.0 This release

2 release files

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page