Swirls

SWIRLS_

  • How it works
  • Pricing

56 matches

OverviewDeliver client operations10Win and grow accounts8Resolve customer issues6Create and distribute content9Run people and operations5Review money and agreements3Monitor systems and data9Compose dependable work6

56 matches

OverviewDeliver client operations10Win and grow accounts8Resolve customer issues6Create and distribute content9Run people and operations5Review money and agreements3Monitor systems and data9Compose dependable work6
← DevOpsWebhookView on GitHub

PR Review Notifier

Receives GitHub PR webhooks, summarizes changes with AI, and posts to Slack.

aihttpswitch

Source

/**
 * Receives GitHub PR webhook events, summarizes changes with AI,
 * and posts a review summary to Slack.
 */

secret pr_config {
  vars: [SLACK_WEBHOOK_URL]
}

webhook github_pr {
  label: "GitHub PR Event"
  schema: @json {
    {
      "type": "object",
      "required": ["action", "pull_request"],
      "properties": {
        "action": { "type": "string" },
        "pull_request": {
          "type": "object",
          "properties": {
            "title": { "type": "string" },
            "body": { "type": "string" },
            "user": { "type": "object" },
            "html_url": { "type": "string" },
            "additions": { "type": "number" },
            "deletions": { "type": "number" },
            "changed_files": { "type": "number" }
          }
        }
      }
    }
  }
}

workflow notify_pr {
  label: "Notify PR"

  root {
    type: code
    label: "Extract PR data"
    code: @ts {
      const input = context.nodes.root.input
      const pr = input.pull_request || {}
      return {
        action: input.action,
        title: pr.title || "Untitled",
        body: pr.body || "",
        author: pr.user ? pr.user.login : "unknown",
        url: pr.html_url || "",
        additions: pr.additions || 0,
        deletions: pr.deletions || 0,
        changed_files: pr.changed_files || 0
      }
    }
    outputSchema: @json {
      {
        "type": "object",
        "properties": {
          "action": { "type": "string" },
          "title": { "type": "string" },
          "body": { "type": "string" },
          "author": { "type": "string" },
          "url": { "type": "string" },
          "additions": { "type": "number" },
          "deletions": { "type": "number" },
          "changed_files": { "type": "number" }
        }
      }
    }
  }

  node route_action {
    type: switch
    label: "Filter action"
    cases: ["opened", "ignore"]
    router: @ts {
      const action = context.nodes.root.output.action
      if (action === "opened" || action === "ready_for_review") return "opened"
      return "ignore"
    }
  }

  node summarize {
    type: ai
    label: "Summarize PR"
    kind: text
    model: "google/gemini-2.5-flash"
    prompt: @ts {
      const pr = context.nodes.root.output
      return "Write a 1-2 sentence summary of this pull request for a Slack notification.\n\nTitle: " + pr.title + "\nDescription: " + pr.body + "\nFiles changed: " + pr.changed_files + " (+" + pr.additions + " -" + pr.deletions + ")"
    }
    maxTokens: 150
  }

  node post_slack {
    type: http
    label: "Post to Slack"
    method: "POST"
    url: @ts { return context.secrets.pr_config.SLACK_WEBHOOK_URL }
    headers: @ts { return { "Content-Type": "application/json" } }
    body: @ts {
      const pr = context.nodes.root.output
      const summary = context.nodes.summarize.output
      return JSON.stringify({
        text: "*New PR:* " + pr.title + " by " + pr.author + "\n" + summary + "\n<" + pr.url + "|View PR>"
      })
    }
    secrets: {
      pr_config: [SLACK_WEBHOOK_URL]
    }
  }

  node skip {
    type: code
    label: "Skip"
    code: @ts {
      return { skipped: true, action: context.nodes.root.output.action }
    }
  }

  flow {
    root -> route_action
    route_action -["opened"]-> summarize
    summarize -> post_slack
    route_action -["ignore"]-> skip
  }
}

trigger on_pr {
  webhook:github_pr -> notify_pr
  enabled: true
}

Flow

Trigger to workflow

github_prwebhook
notify_pr
Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

Workflow nodes

CODE
Code Node
Extract PR data
SWITCH
Switch Node
Filter action
AI
AI Node
Summarize PR
HTTP
HTTP Node
Post to Slack
CODE
Code Node
Skip
Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.