JSON Schema Data Contract Validation and Parquet Lake Landing Quarantine
Enforces JSON Schema data contracts on incoming event batches, converts valid records to Snappy-compressed Parquet, and isolates contract breaches to dead-letter quarantine.
Build SQLMesh changes in dev, run data audits, then promote the exact audited build to prod. Failing audits block the release. Runs with no setup.
Ship SQLMesh changes to production only after the data audits pass. The flow clones a SQLMesh project, adds a data contract as standalone audits, builds the changes in the isolated dev environment, then audits that build. When every audit passes, it promotes the same build to prod. SQLMesh reuses the tables built in dev, so promotion is a virtual layer swap and not a rebuild. When an audit fails, production is untouched and the run ends as FAILED with the names of the failing audits.
It runs with no setup on the public Tobiko sushi example (DuckDB), with Slack off. To watch the gate block a release, run it with max_waiter_daily_revenue set to 500.
stage_and_audit (io.kestra.plugin.core.flow.WorkingDirectory) keeps one checkout for the next three tasks.clone (io.kestra.plugin.git.Clone) checks out the project.plan_staging (io.kestra.plugin.sqlmesh.cli.SQLMeshCLI) writes two standalone audits through inputFiles, then runs sqlmesh plan dev --auto-apply.assert_top_waiters_have_names: no row in top_waiters has a null name.assert_waiter_daily_revenue_in_range: daily revenue per waiter is between 0 and max_waiter_daily_revenue.audit runs sqlmesh audit and emits audit_status (passed or failed) plus failed_audits. It exports the project directory, including the DuckDB file that holds the data and the SQLMesh state, through outputFiles.promotion_gate (io.kestra.plugin.core.flow.If) branches on audit_status.promote_production restores the exported project with inputFiles and runs sqlmesh plan prod --auto-apply. The log shows No model batches to execute and Virtual layer updated. It then prints sushisimple.top_waiters from prod.block_release (io.kestra.plugin.core.execution.Fail) ends the run as FAILED with the failing audit names.notify_slack is true, each branch also posts to Slack.on_merge (io.kestra.plugin.core.trigger.Webhook) lets CI start the gate after every merge.alert_flow_failure (errors) posts to Slack when a task fails.project_git_url (STRING, default the sushi examples repo): the SQLMesh project repository.project_branch (STRING, default main): the branch to build and promote.project_subdir (STRING, default 001_sushi/1_simple): the folder that holds config.yaml.max_waiter_daily_revenue (INT, default 1000): the upper bound used by the revenue audit.notify_slack (BOOL, default false): post the result to Slack.SQLMeshCLI uses the ghcr.io/kestra-io/sqlmesh image by default.SLACK_WEBHOOK_URL: Slack incoming webhook. Used by alert_flow_failure and by the result posts when notify_slack is true.max_waiter_daily_revenue set to 500. Two days break the rule, assert_waiter_daily_revenue_in_range fails and the run ends as FAILED without touching prod.plan_staging with your own or commit them to the project audits/ folder.key, remove disabled: true from on_merge, then call /api/v1/main/executions/webhook/company.team/sqlmesh-audit-gated-promotion/<key> from CI after a merge.outputs.audit.vars.audit_status: passed or failed.outputs.audit.vars.failed_audits: comma-separated names of failing audits.The sushi example keeps its data and state in a local DuckDB file, so the audit step exports the project and the promote step restores it. With a warehouse gateway such as Snowflake, BigQuery or Postgres the data and state live in the warehouse, so the export is small. Add the credentials to the SQLMesh tasks with env and {{ secret('NAME') }}.
