Inspiration
Blast started from one observation: DataHub already knows exactly what sits downstream of any table, but it has no opinion on whether a given change actually breaks any of it. That's the gap between a lineage graph and a code reviewer. A renamed column sails through CI and merges clean; the failure shows up two hops later, in a dashboard, days after the PR is closed and forgotten. Existing tools โ DataHub's own Impact Analysis included โ stop at "these are connected." Blast asks the harder question: does this actually break, who needs to know, and can it just be fixed โ and writes the answer back into DataHub itself.
What it does
Blast is two agents that share one job: catch the breakage before it ships, and don't let the org forget it happened.
๐งจ blast-scan โ catches it before merge
Runs on every pull request. It reads whatever file changed โ a dbt model, raw DDL, a Terraform resource, honestly almost anything โ asks an LLM what actually changed about it, resolves that thing to a DataHub URN, and walks DataHub's lineage graph for everything downstream. Then, instead of just listing what's connected, it asks a second question for each downstream asset: given this specific change, does this thing actually break?
- ๐ด Hard break โ a downstream model selects a column that no longer exists
- ๐ก Silent risk โ a type change a
SUM()runs over; nothing errors, the number is just wrong forever - ๐ข Safe โ nothing about this asset touches the change
- ๐ Needs review โ Blast can't confidently reason about it, so it says so instead of guessing
The report goes on the PR as a comment, with a color-coded Mermaid graph and a line most tools skip entirely:
"stg_orders has been flagged for 3 predicted breaking changes in the last 90 days."
That number isn't decoration โ it's read live from DataHub, because
blast-scan writes every finding back as an incident on the dataset, and
recomputes a blast_risk_score (0-100) as a real DataHub Structured
Property. You can go look at the entity in DataHub's own UI and watch that
score climb across two PRs. The institutional memory isn't a Blast-only
concept living in a PR comment โ it's on the asset itself.
๐ ๏ธ Splint โ turns the warning into a fix
Comment /blast-fix on a PR Blast flagged, and Splint re-runs the same
interpret โ resolve โ classify pipeline, pulls the real source file for
each broken downstream model, rewrites the SQL to match the upstream
change, and opens a follow-up PR for review. It's honest about partial
results too โ if it fixes two out of three flagged models, it says so and
lists the third with the actual reason it couldn't (source file not found,
fix was a no-op, whatever it is), instead of a vague "done."
A warning that nobody has to act on gets ignored eventually. A warning with a fix attached gets reviewed.
How I built it
- DataHub MCP Server for lineage reads and entity search, with a hand-rolled GraphQL client as the automatic fallback
- OpenAI for the actual reasoning โ interpreting diffs and classifying breakage
- Reusable GitHub Actions workflows so any repo can adopt Blast by dropping in a five-line YAML file instead of vendoring Python
- Mermaid for the dependency graph, rendered natively in the PR comment
- PyGithub for reading PR files, posting comments, and opening Splint's fix PRs
Adopting Blast
Adopting Blast doesn't mean vendoring any Python into your project. It's
two reusable GitHub Actions workflow files, copied in as-is: one that runs
blast-scan on every pull request, one that wires up the /blast-fix
comment trigger for Splint. Add three repository secrets โ
DATAHUB_SERVER, DATAHUB_TOKEN, OPENAI_API_KEY โ and that's the whole
install. There's no per-repo config file to maintain either, since entity
resolution goes straight through DataHub search instead of a local mapping
file someone has to keep in sync.
Accomplishments that I am proud of
Delivered as a reusable, drop-in workflow. Blast isn't a script someone
has to vendor and maintain โ it ships as two workflow_call GitHub Actions
files that any repo can adopt by pasting in a five-line wrapper and adding
three secrets. No per-repo config file, no local mapping to keep in sync.
Making it something another team could actually plug into their own CI, not
just a demo that runs on my machine, was a deliberate design goal from the
start.
Diagnoses the break, not just the connection. Blast doesn't just tell you two things are connected โ it tells you, in plain language, why the downstream thing breaks, quoting the actual column and the actual line of reasoning. That's the difference between a lineage viewer and a code reviewer, and it's the part that actually saves someone from having to trace the logic themselves at 6pm before a release.
A risk score computed from real incident history. It would have been
easy to hard-code a demo number that climbs on cue. Instead
blast_risk_score is recomputed from actual incident history every single
run, written as a real DataHub Structured Property, live-tested end to end
against a running instance โ including the bootstrap step that defines the
property in the first place. Watching that number visibly change in
DataHub's own UI because of something Blast wrote, not something I typed
into a demo script, was the moment this stopped feeling like a hackathon
toy.
What's next for Blast
Org-wide risk visibility. Every table Blast touches already carries a
live blast_risk_score in DataHub. Rolling those up into a single view
would let a platform team see which tables are quietly fragile across the
whole org, before the next migration touches them โ not just one PR at a
time.
Proactive owner notifications. Blast already resolves and names the team that owns a broken downstream asset right on the PR comment. The natural next step is pushing that straight to Slack or Teams the moment a hard break is found, so the right person hears about it before the PR is even reviewed, not after.
Built With
- datahub
- github-actions
- mcp
- mermaid
- openai
- python
Log in or sign up for Devpost to join the conversation.