Beta sign in

Pipe library / github-releases-digest

github-releases-digest

New GitHub releases across a set of repos since the last successful run.

Developer monitoring

github.com

CLI

pipes run examples/github-releases.pipe.yaml

MCP call

{
  "name": "pipe__github-releases-digest",
  "arguments": {}
}

Pipe file

examples/github-releases.pipe.yaml

# Example (a): GitHub releases (Atom) for a few repos -> dedupe -> diff_since_last -> format -> stdout
pipes: 0
name: github-releases-digest
version: 0.1.0
description: New GitHub releases across a set of repos since the last successful run.
permissions:
  network: [github.com]
schedule:                                      # run by `pipes serve` / Asipipes once published
  - cron: "0 8 * * 1-5"
    tz: America/Denver
    inputs: {}                                 # uses the default repos
    catch_up: latest
inputs:
  type: object
  properties:
    repos:
      type: array
      items: { type: string, pattern: "^[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+$" }
      minItems: 1
      maxItems: 20
      default: [tokio-rs/tokio, modelcontextprotocol/rust-sdk, bytecodealliance/wasmtime]
  required: [repos]
outputs:
  type: object
  properties:
    text:  { type: string }
    count: { type: integer }
  required: [text, count]
output:
  text:  "${steps.format.text}"
  count: "${steps.format.count}"

steps:
  - id: fetch
    block: fetch_http
    for_each: "${inputs.repos}"                  # one request per repo; outputs a list of responses
    with:
      url: "https://github.com/${item}/releases.atom"
      max_bytes: 2000000
    retry: { max: 2, backoff_ms: 500 }
    timeout_ms: 10000

  - id: entries
    block: parse_rss                           # Atom/RSS -> normalized records
    in: "${steps.fetch}"

  - id: with_repo
    block: regex_extract
    in: "${steps.entries}"
    with:
      field: link
      pattern: "github\\.com/([^/]+/[^/]+)/releases/tag/(.+)$"
      into: { repo: 1, tag: 2 }
    on_item_error: drop

  - id: unique
    block: dedupe
    in: "${steps.with_repo}"
    with: { key: [id], keep: first }

  - id: new
    block: diff_since_last
    in: "${steps.unique}"
    with:
      key: [id]
      compare: [id]                            # only care about never-seen releases
      emit: [added]
      first_run: all

  - id: ordered
    block: sort
    in: "${steps.new}"
    with:
      by: [{ field: published, desc: true }, { field: repo }]

  - id: format
    block: format
    in: "${steps.ordered}"
    with:
      header: "New releases:\n"
      item_template: "- ${item.repo} ${item.tag} (${item.published}) ${item.link}"
      separator: "\n"
      footer: ""

  - id: print
    block: emit_stdout
    in: "${steps.format.text}"
    with: { format: text }