dirigent-examples 0.15.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- dirigent_examples-0.15.0/LICENSE +18 -0
- dirigent_examples-0.15.0/PKG-INFO +21 -0
- dirigent_examples-0.15.0/README.md +10 -0
- dirigent_examples-0.15.0/pyproject.toml +25 -0
- dirigent_examples-0.15.0/pyproject.toml.orig +24 -0
- dirigent_examples-0.15.0/src/dirigent_examples/__init__.py +22 -0
- dirigent_examples-0.15.0/src/dirigent_examples/py.typed +0 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/README.md +299 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/composition/README.md +18 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/composition/chained-instances.yaml +97 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/composition/composition-child.yaml +64 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/composition/composition-parent.yaml +89 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/connections.yaml +52 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/demo/README.md +19 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/demo/markdown-showcase.yaml +117 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/demo/params-showcase.yaml +92 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/demo/requires.yaml +65 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/demo/weekly-import-malawi.yaml +54 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/demo/weekly-import-nepal.yaml +75 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/docker/README.md +29 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/docker/docker-build-push.yaml +110 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/docker/docker-build-run.yaml +106 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/docker/docker-compose-database.yaml +124 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/docker/docker-compose-failing-up.yaml +83 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/docker/docker-compose-file.yaml +117 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/docker/docker-compose-profiles-env.yaml +133 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/docker/docker-compose-stack.yaml +70 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/docker/docker-hello.yaml +53 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/docker/docker-remote-daemon.yaml +92 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/docker/docker-run-failing-teardown.yaml +94 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/docker/docker-ticker.yaml +49 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/execute/README.md +16 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/execute/long-log.yaml +89 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/failure/README.md +20 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/failure/error-handler.yaml +89 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/failure/optional-step.yaml +82 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/failure/retries.yaml +75 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/failure/retry-budget.yaml +82 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/failure/step-timeout.yaml +96 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/git/README.md +32 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/git/git-checkout-build.yaml +125 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/git/git-checkout-compose.yaml +138 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/git/git-checkout-public.yaml +84 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/graph/README.md +22 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/graph/deep-chain.yaml +119 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/graph/fan-in.yaml +80 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/graph/fan-out.yaml +66 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/graph/linear.yaml +66 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/graph/parallel-branches.yaml +57 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/graph/parallel-sleep.yaml +55 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/graph/skip-diamond.yaml +105 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/graph/wide-fan.yaml +147 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/hello-world.yaml +30 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/open-data/README.md +67 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/open-data/feeds-composition.yaml +120 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/open-data/gdacs-disaster-updates.yaml +230 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/open-data/github-releases-relay.yaml +225 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/open-data/hdx-dataset-watch.yaml +211 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/open-data/kobo-submissions-to-csv.yaml +149 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/open-data/nominatim-geocode-facilities.yaml +169 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/open-data/odk-central-submissions.yaml +146 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/open-data/open-meteo-weekly-report.yaml +142 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/open-data/overpass-health-facilities.yaml +154 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/open-data/usgs-earthquakes-alert.yaml +208 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/open-data/who-gho-indicators-to-parquet.yaml +163 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/open-data/wikidata-country-reference.yaml +146 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/open-data/world-bank-population-trend.yaml +166 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/README.md +144 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/concurrency-queue.yaml +89 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/concurrency-replace.yaml +92 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/concurrency-skip.yaml +97 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/connections-referenced-vs-carried.yaml +140 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/deadline-on-a-sensor.yaml +106 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/fan-out-continue.yaml +88 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/fan-out-fail-fast.yaml +80 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/fan-out-from-params.yaml +84 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/fan-out-item-wise.yaml +111 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/fan-out-literal-list.yaml +81 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/fan-out-nested-objects.yaml +107 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/fan-out-then-join.yaml +86 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/log-levels.yaml +119 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/outputs-inline-vs-storage.yaml +140 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/params-every-type.yaml +259 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/params-validation-refuses.yaml +131 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/pipeline-run-child.yaml +96 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/pipeline-run-fire-and-forget.yaml +99 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/pipeline-run-strict.yaml +103 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/pipeline-run-wait.yaml +107 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/pipeline-run-with-params.yaml +124 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/poll-cadence.yaml +102 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/priority-layered.yaml +120 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/references-cheat-sheet.yaml +186 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/retry-budget-exhausted.yaml +92 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/retry-exponential-backoff.yaml +88 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/retry-only-transient.yaml +108 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/retry-with-jitter.yaml +102 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/rule-all-done.yaml +83 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/rule-all-success.yaml +79 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/rule-always.yaml +92 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/rule-one-failed.yaml +86 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/schedule-at-once.yaml +110 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/schedule-cron-timezone.yaml +121 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/schedule-interval.yaml +109 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/schedule-window-half-open.yaml +105 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/sensor-http-ready.yaml +121 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/sensor-storage-exists.yaml +134 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/step-names-and-keys.yaml +99 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/timeout-fails-the-step.yaml +94 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/timeout-skips-the-step.yaml +102 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/webhook-mapping-nested-payload.yaml +125 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/webhook-signed.yaml +144 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/preview/s3-parquet-to-ingestion.yaml +92 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/python/README.md +31 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/python/apply_and_run.py +52 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/python/ci_gate.py +76 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/python/connections.py +61 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/python/error_handling.py +84 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/python/follow_logs.py +39 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/python/list_and_filter.py +52 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/queues/README.md +59 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/queues/kafka-consume-then-transform.yaml +105 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/queues/kafka-produce-then-consume.yaml +124 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/queues/rabbitmq-consume-ack-on-success.yaml +102 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/queues/report-to-kafka.yaml +105 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/queues/report-to-rabbitmq.yaml +105 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/README.md +130 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/csv-header-rules.yaml +147 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/csv-to-ndjson.yaml +107 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/etl-csv-clean-validate-parquet.yaml +207 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/filter-by-predicate.yaml +116 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/filter-then-map-then-reduce.yaml +109 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/http-fetch-validate-post.yaml +142 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/http-follow-redirects.yaml +100 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/http-get-with-query.yaml +96 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/http-headers-and-auth-connection.yaml +110 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/http-post-file-from-storage.yaml +117 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/http-post-json-echo.yaml +105 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/http-post-report.yaml +183 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/http-save-body-to-storage.yaml +106 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/http-success-status-list.yaml +80 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/http-timeout-override.yaml +104 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/jq-dedupe-by-key.yaml +78 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/jq-defaults-and-nulls.yaml +91 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/jq-group-by-and-sum.yaml +74 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/jq-join-two-lists.yaml +77 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/jq-long-to-wide.yaml +76 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/jq-nested-to-flat.yaml +89 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/jq-pivot-wide-to-long.yaml +65 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/jq-running-totals.yaml +82 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/jq-string-cleaning.yaml +88 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/jq-top-n.yaml +85 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/jq-validate-in-jq-vs-schema.yaml +124 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/jq-window-dates.yaml +82 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/json-to-csv-flattening.yaml +141 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/large-output-to-storage.yaml +134 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/map-enrich-with-lookup.yaml +96 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/ndjson-to-parquet.yaml +130 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/pagination-by-fan-out.yaml +115 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/parquet-round-trip-types.yaml +163 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/reconcile-two-sources.yaml +159 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/report-built-in.yaml +72 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/report-daily-digest.yaml +186 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/report-to-file.yaml +131 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/report-to-webhook.yaml +136 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/schema-carried.yaml +112 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/schema-formats.yaml +107 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/schema-referenced.yaml +86 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/schema-refuses-then-rule.yaml +127 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/storage-copy-dated-archive.yaml +114 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/storage-exists-gate.yaml +127 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/storage-manifest-of-a-fan-out.yaml +104 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/storage-write-then-read.yaml +119 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/webhook-post-hmac.yaml +132 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/webhook-post-summary.yaml +142 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/s3/README.md +34 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/s3/report-to-s3.yaml +93 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/s3/s3-copy-and-verify.yaml +105 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/s3/s3-csv-report.yaml +87 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/s3/s3-parquet-report.yaml +77 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/s3/s3-round-trip.yaml +125 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/schemas/README.md +36 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/schemas/echo-reading.json +18 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/schemas/ou-record.json +13 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/schemas/station-reading.json +13 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/sensors/README.md +16 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/sensors/sensor-gate.yaml +65 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/sensors/time-window.yaml +61 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/sql/README.md +52 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/sql/duckdb-parquet-to-report.yaml +146 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/sql/sql-postgres-readonly.yaml +111 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/sql/sql-query-to-storage.yaml +85 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/sql/sql-sqlite-roundtrip.yaml +114 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/sql/warehouse.sql +42 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/transform/README.md +36 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/transform/csv-report.yaml +55 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/transform/jq-filter-and-map.yaml +70 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/transform/jq-group-and-aggregate.yaml +70 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/transform/jq-join-two-sources.yaml +98 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/transform/jq-reshape.yaml +91 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/transform/jq-stream-through-storage.yaml +112 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/transform/ndjson-round-trip.yaml +56 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/transform/parquet-round-trip.yaml +68 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/transform/std-convert-fan-out.yaml +142 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/transform/xml-feed-to-ndjson.yaml +116 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/transform/yaml-config-to-json.yaml +104 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/triggers/README.md +45 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/triggers/at-one-time.yaml +78 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/triggers/cron-nightly.yaml +79 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/triggers/cron-windowed.yaml +86 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/triggers/document-nightly.yaml +80 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/triggers/interval-rolling.yaml +88 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/triggers/managed-and-manual.yaml +109 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/triggers/webhook-trigger.yaml +75 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/validate/README.md +31 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/validate/expects-a-shape.yaml +56 -0
- dirigent_examples-0.15.0/src/dirigent_examples/shelves/validate/the-shape-is-wrong.yaml +46 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
Copyright (c) 2026 Morten Olav Hansen <morten@winterop.com>. All rights reserved.
|
|
2
|
+
|
|
3
|
+
This source code and accompanying documentation are the property of
|
|
4
|
+
Morten Olav Hansen. No license, express or implied, is granted to use, copy,
|
|
5
|
+
modify, merge, publish, distribute, sublicense, or sell copies of this
|
|
6
|
+
software or its derivatives.
|
|
7
|
+
|
|
8
|
+
The source is published for reference only. Any use beyond reading
|
|
9
|
+
requires written permission from the copyright holder.
|
|
10
|
+
|
|
11
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
12
|
+
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
13
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT.
|
|
14
|
+
IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES,
|
|
15
|
+
OR OTHER LIABILITY ARISING FROM THE USE OF THE SOFTWARE.
|
|
16
|
+
|
|
17
|
+
Third-party components redistributed with this software, and the licences they
|
|
18
|
+
carry, are listed in THIRD_PARTY_NOTICES.md.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: dirigent-examples
|
|
3
|
+
Version: 0.15.0
|
|
4
|
+
Summary: The dirigent example corpus: the shelves of runnable documents, installed.
|
|
5
|
+
License-Expression: LicenseRef-Proprietary
|
|
6
|
+
License-File: LICENSE
|
|
7
|
+
Requires-Dist: dirigent-client
|
|
8
|
+
Requires-Dist: dirigent-plugin
|
|
9
|
+
Requires-Python: >=3.13
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
|
|
12
|
+
# dirigent-examples
|
|
13
|
+
|
|
14
|
+
The dirigent example corpus as an installed distribution: 22 topic shelves of runnable
|
|
15
|
+
`dirigent/v1` documents, contributed to a host through the `examples()` extension point and
|
|
16
|
+
read by `dg examples`, `dg pipeline new`, and the instance's Examples screen.
|
|
17
|
+
|
|
18
|
+
The shelves are the repository's `examples/` directory; the root path is a symlink to the
|
|
19
|
+
real files here, so every `dg run --local examples/...` line keeps working in a checkout.
|
|
20
|
+
[`shelves/README.md`](src/dirigent_examples/shelves/README.md) is the corpus's own guide: the
|
|
21
|
+
shelves, the tag vocabulary, and what each document needs to run.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# dirigent-examples
|
|
2
|
+
|
|
3
|
+
The dirigent example corpus as an installed distribution: 22 topic shelves of runnable
|
|
4
|
+
`dirigent/v1` documents, contributed to a host through the `examples()` extension point and
|
|
5
|
+
read by `dg examples`, `dg pipeline new`, and the instance's Examples screen.
|
|
6
|
+
|
|
7
|
+
The shelves are the repository's `examples/` directory; the root path is a symlink to the
|
|
8
|
+
real files here, so every `dg run --local examples/...` line keeps working in a checkout.
|
|
9
|
+
[`shelves/README.md`](src/dirigent_examples/shelves/README.md) is the corpus's own guide: the
|
|
10
|
+
shelves, the tag vocabulary, and what each document needs to run.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "dirigent-examples"
|
|
3
|
+
version = "0.15.0"
|
|
4
|
+
description = "The dirigent example corpus: the shelves of runnable documents, installed."
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.13"
|
|
7
|
+
license = "LicenseRef-Proprietary"
|
|
8
|
+
license-files = ["LICENSE"]
|
|
9
|
+
dependencies = [
|
|
10
|
+
"dirigent-client",
|
|
11
|
+
"dirigent-plugin",
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
[project.entry-points."dirigent.plugins.v1"]
|
|
15
|
+
examples = "dirigent_examples:plugin"
|
|
16
|
+
|
|
17
|
+
[build-system]
|
|
18
|
+
requires = ["uv_build>=0.12.0,<0.13.0"]
|
|
19
|
+
build-backend = "uv_build"
|
|
20
|
+
|
|
21
|
+
[tool.uv.sources.dirigent-client]
|
|
22
|
+
workspace = true
|
|
23
|
+
|
|
24
|
+
[tool.uv.sources.dirigent-plugin]
|
|
25
|
+
workspace = true
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "dirigent-examples"
|
|
3
|
+
version = "0.15.0"
|
|
4
|
+
description = "The dirigent example corpus: the shelves of runnable documents, installed."
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.13"
|
|
7
|
+
license = "LicenseRef-Proprietary"
|
|
8
|
+
license-files = ["LICENSE"]
|
|
9
|
+
dependencies = [
|
|
10
|
+
# The python/ shelf is SDK scripts a reader runs, so the corpus carries the client.
|
|
11
|
+
"dirigent-client",
|
|
12
|
+
"dirigent-plugin",
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
[project.entry-points."dirigent.plugins.v1"]
|
|
16
|
+
examples = "dirigent_examples:plugin"
|
|
17
|
+
|
|
18
|
+
[build-system]
|
|
19
|
+
requires = ["uv_build>=0.12.0,<0.13.0"]
|
|
20
|
+
build-backend = "uv_build"
|
|
21
|
+
|
|
22
|
+
[tool.uv.sources]
|
|
23
|
+
dirigent-client = { workspace = true }
|
|
24
|
+
dirigent-plugin = { workspace = true }
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"""The dirigent example corpus, installed: shelves of runnable ``dirigent/v1`` documents."""
|
|
2
|
+
|
|
3
|
+
from collections.abc import Sequence
|
|
4
|
+
from importlib.resources import files
|
|
5
|
+
from importlib.resources.abc import Traversable
|
|
6
|
+
|
|
7
|
+
from dirigent_plugin import extension
|
|
8
|
+
|
|
9
|
+
#: The directory the topic shelves live in, inside this distribution.
|
|
10
|
+
SHELVES_DIRECTORY = "shelves"
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class ExamplesPlugin:
|
|
14
|
+
"""The plugin object the host discovers under the dirigent.plugins.v1 entry-point group."""
|
|
15
|
+
|
|
16
|
+
@extension
|
|
17
|
+
def examples(self) -> Sequence[Traversable]:
|
|
18
|
+
"""Contribute the shelves this distribution carries, and nothing else."""
|
|
19
|
+
return [files(__package__ or "dirigent_examples") / SHELVES_DIRECTORY]
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
plugin = ExamplesPlugin()
|
|
File without changes
|
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
# Example pipelines
|
|
2
|
+
|
|
3
|
+
Every file here is a real `dirigent/v1` document, and every one of them runs. A test walks
|
|
4
|
+
this directory on every CI run: the documents in `examples/` are validated against the real
|
|
5
|
+
block catalog, and every document, including the previews, must survive a
|
|
6
|
+
parse-export-reparse round trip unchanged.
|
|
7
|
+
|
|
8
|
+
[`python/`](python) is the other half of the corpus: the documents here describe pipelines,
|
|
9
|
+
and the scripts there drive an instance that holds them, through the `dirigent-client` SDK.
|
|
10
|
+
|
|
11
|
+
The documents live on topic shelves, each with its own README:
|
|
12
|
+
|
|
13
|
+
| Shelf | What lives there |
|
|
14
|
+
| --- | --- |
|
|
15
|
+
| [`graph/`](graph) | The shapes a DAG takes: lines, branches, fans, joins, and skips. |
|
|
16
|
+
| [`patterns/`](patterns) | One engine behaviour per file: rules, retries, the two clocks, item policies, triggers, concurrency, and the reference language. |
|
|
17
|
+
| [`failure/`](failure) | Retries, budgets, timeouts, tolerated failures, and the cleanup edge. |
|
|
18
|
+
| [`transform/`](transform) | The reshaping verbs: jq programs and the `convert.std` codec, no allowlist anywhere. |
|
|
19
|
+
| [`recipes/`](recipes) | One question per file: how to group, join, pivot, clean, convert, check, store, and call. |
|
|
20
|
+
| [`triggers/`](triggers) | What starts a run on its own: the three clocks, and the inbound webhook. |
|
|
21
|
+
| [`sensors/`](sensors) | Steps that wait for the world: a drop landing, a clock window opening. |
|
|
22
|
+
| [`queues/`](queues) | A run started by a message: a Kafka topic and a RabbitMQ queue, waited on as sensors. |
|
|
23
|
+
| [`execute/`](execute) | Code on the worker: a shell step behind the allowlist. |
|
|
24
|
+
| [`docker/`](docker) | The container family: run one, watch it live, build an image and push it, and bring a whole compose stack up and down, on the worker's daemon or one a connection names. |
|
|
25
|
+
| [`git/`](git) | An existing project brought into a run: a repository checked out, then built and brought up from what it ships. |
|
|
26
|
+
| [`sql/`](sql) | A database read and written: bound parameters, one transaction, and a result handed to storage when it belongs in a file. |
|
|
27
|
+
| [`composition/`](composition) | Pipelines made of pipelines, and the handoff to a second instance. |
|
|
28
|
+
| [`s3/`](s3) | Object storage through the `s3://` scheme, with no S3 block anywhere. |
|
|
29
|
+
| [`demo/`](demo) | Surfaces shown off: the run form, rendered markdown, the requires preflight, the weekly-import shared-name pair. |
|
|
30
|
+
| [`open-data/`](open-data) | Real feeds against public, mostly keyless APIs: acme, health indicators, maps, earthquakes, humanitarian data. |
|
|
31
|
+
| [`validate/`](validate) | A gate that checks a value's shape and passes it through: `validate.schema`, with the shape carried and named. |
|
|
32
|
+
|
|
33
|
+
**The tag rule.** Every document's `tags:` is drawn from one vocabulary of three groups and
|
|
34
|
+
nothing else. The **shelf** is the directory the file sits in, exactly one, and every document
|
|
35
|
+
wears it. The **block families** are what its steps use, read off the block ids: `http`,
|
|
36
|
+
`transform` (the jq verbs and the `convert.std` codec), `storage` (a storage block, or a
|
|
37
|
+
converter's `source` and `target`), `execute` (shell and docker), `sql`, `git`, `webhook`
|
|
38
|
+
(`webhook.post`, or an inbound webhook trigger), `kafka`, `rabbitmq`, `pipeline`, `validate`,
|
|
39
|
+
and `sensor` for any sensor block. The **behaviours** are what the document teaches and what a
|
|
40
|
+
reader filters by: `schedule`, `fan-out`, `graph`, `failure`, `retry`, `timeout`,
|
|
41
|
+
`concurrency`, `params`, `references`, `rules`, `priority`, `window`, `composition`,
|
|
42
|
+
`credential`, `outputs`, `filter`, `map`, `relay`, `csv`, `parquet`, `jq`, `sparql`,
|
|
43
|
+
`geocode`, `briefing`, `observability`, `conventions`, `report` for a document that
|
|
44
|
+
declares a `report:` section, so every run of it writes its own account of itself, or renders
|
|
45
|
+
a page of its own with `report.render`, and `starter` for a document `dg pipeline new` may
|
|
46
|
+
copy into a project: a real multi-step flow on a real source, carrying nothing. A source's
|
|
47
|
+
name is never a tag: the pipeline's `code` and `name` already say it is USGS or WHO GHO, and a
|
|
48
|
+
word one document wears is a filter nobody can use.
|
|
49
|
+
|
|
50
|
+
**The starter rule.** `starter` is the one tag a document opts into rather than wears by
|
|
51
|
+
description, and it is the narrowest. A document earns it by being a real multi-step flow on
|
|
52
|
+
a real source -- a public endpoint, or a service a connection names. What disqualifies one is
|
|
53
|
+
a top-level `connections:` or `schemas:` section, which an instance refuses at apply; a run
|
|
54
|
+
that fails by design; a single step; and a hello-world. `dg pipeline new <code>` copies a
|
|
55
|
+
starter's text verbatim into `pipelines/`, rewriting only the `code:` line and dropping
|
|
56
|
+
`starter` from the `tags:` line, so the comments come with it and its `requires` is the list
|
|
57
|
+
of what to create first.
|
|
58
|
+
|
|
59
|
+
**The tiering rule.** `examples/` is what runs: every document there is runnable, though some
|
|
60
|
+
need infrastructure whose setup their headers document -- the [`docker/`](docker) shelf needs a
|
|
61
|
+
Docker socket or a daemon a connection names, [`queues/`](queues) needs the brokers
|
|
62
|
+
`infra/compose.queues.yaml` starts, `sql-postgres-readonly.yaml` needs a PostgreSQL, and
|
|
63
|
+
`s3-round-trip.yaml` needs an S3-compatible endpoint and a connection to it.
|
|
64
|
+
`preview/` is for what cannot run yet because the *code* does not exist: documents whose block
|
|
65
|
+
ids belong to adapter packs nobody has written. A missing credential is not a preview; a
|
|
66
|
+
missing package is.
|
|
67
|
+
|
|
68
|
+
The HTTP examples call [Postman Echo](https://postman-echo.com), a public request-and-
|
|
69
|
+
response service, so you can run any of them for real without standing anything up:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
dg run --local examples/hello-world.yaml
|
|
73
|
+
dg run --local examples/graph/linear.yaml -p day=2026-01-01 --enable-unsafe shell.run
|
|
74
|
+
dg run --local examples/failure/retries.yaml # watch the retry policy fire
|
|
75
|
+
dg run --local examples/composition/chained-instances.yaml \
|
|
76
|
+
--connections examples/connections.yaml -p day=2026-01-01
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Most of these use `shell.run`, which executes code on the worker and is refused unless the
|
|
80
|
+
instance allowlists it. `--enable-unsafe shell.run` allows it for one command; the instance
|
|
81
|
+
setting allows it for good:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
export DIRIGENT_ENABLED_UNSAFE_BLOCKS='["shell.run"]'
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Not every one of them succeeds, and that is the point of three of them:
|
|
88
|
+
|
|
89
|
+
| Example | Ends as | Because |
|
|
90
|
+
| --- | --- | --- |
|
|
91
|
+
| `failure/retries.yaml` | `completed_with_errors` | The publish endpoint refuses three times; the failure is tolerated |
|
|
92
|
+
| `failure/error-handler.yaml` | `failed` | The load fails, so the alert branch runs and the success branch is skipped |
|
|
93
|
+
| `sensors/sensor-gate.yaml` | `succeeded` | The drop never lands, so the sensor skips and the branch skips with it |
|
|
94
|
+
| `failure/optional-step.yaml` | `completed_with_errors` | The metrics push exits 3 and is tolerated, so the branch below it still runs |
|
|
95
|
+
| `failure/retry-budget.yaml` | `failed` | A command that always exits 1, given three attempts to prove it |
|
|
96
|
+
| `failure/step-timeout.yaml` | `failed` | A thirty-second sleep against a two-second budget, so it fails in about two |
|
|
97
|
+
| `graph/skip-diamond.yaml` | `succeeded` | Green, with one step skipped: the handler had nothing to handle |
|
|
98
|
+
|
|
99
|
+
`dg run --local` applies and runs the document in a throwaway SQLite instance that is
|
|
100
|
+
deleted afterwards -- no server, no Docker, no database. When a step fails it prints the
|
|
101
|
+
failing step, its block, the error class, the message, and that attempt's log lines before
|
|
102
|
+
the database goes away. Against a real instance it is the same two commands:
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
dg apply examples/graph/linear.yaml
|
|
106
|
+
dg run linear -p day=2026-01-01 --watch
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
The CI lane that walks these files never touches the network: it validates the documents
|
|
110
|
+
and round-trips them, and the execution tests elsewhere use a mock transport. Postman Echo
|
|
111
|
+
is for humans running the examples for real.
|
|
112
|
+
|
|
113
|
+
## Engine patterns
|
|
114
|
+
|
|
115
|
+
[`patterns/`](patterns) is the reference shelf. Every other shelf is organised by what a
|
|
116
|
+
pipeline is *for*; that one is organised by what the engine *does*, one behaviour per file,
|
|
117
|
+
named for what it shows: the four trigger rules, the retry policy's five fields, `timeout`
|
|
118
|
+
against `deadline` against `on_timeout`, the two item policies, the three clocks a trigger can
|
|
119
|
+
be, the four concurrency policies, the four questions `pipeline.run` answers, and every
|
|
120
|
+
`${...}` form the reference language allows.
|
|
121
|
+
|
|
122
|
+
Each header says what to expect before you run it, because several of them fail on purpose:
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
dg run --local examples/patterns/rule-one-failed.yaml # failed, and the alert branch ran
|
|
126
|
+
dg run --local examples/patterns/fan-out-continue.yaml # completed_with_errors, two items of three
|
|
127
|
+
dg run --local examples/patterns/timeout-skips-the-step.yaml # succeeded, having skipped the branch
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Nothing on that shelf runs code on the worker, so none of it needs `--enable-unsafe`. Four
|
|
131
|
+
files are handed something a bare local run does not have -- a window, a connections file, a
|
|
132
|
+
child document -- and [patterns/README.md](patterns/README.md) indexes all of them with the
|
|
133
|
+
outcome each one settles as.
|
|
134
|
+
|
|
135
|
+
## Connections
|
|
136
|
+
|
|
137
|
+
Three of the examples reference a connection by code. Documents are portable precisely because
|
|
138
|
+
they name credentials rather than carrying them, so the credential has to exist wherever the
|
|
139
|
+
document is applied. On a server, create it once:
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
dg connection create http postman-echo --set base_url=https://postman-echo.com
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
A local run has no server to hold it, so it is handed the connection instead:
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
dg run --local examples/demo/requires.yaml --connections examples/connections.yaml
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
[connections.yaml](connections.yaml) is that file. The basic-auth credentials in it are
|
|
152
|
+
Postman's own public demo pair. `basic_password` is a `SecretStr`, so it is encrypted at
|
|
153
|
+
rest and redacted in every API response.
|
|
154
|
+
|
|
155
|
+
## Schemas
|
|
156
|
+
|
|
157
|
+
[`schemas/`](schemas) holds a few named JSON Schemas: the shape a read is expected to return,
|
|
158
|
+
written down so a pipeline can be refused the moment it sees a payload that moved. A schema is
|
|
159
|
+
locally authored -- it is a picture you hold of the payload, never something fetched from the
|
|
160
|
+
source -- so it lives here as a plain JSON Schema and is applied on its own, not as part of a
|
|
161
|
+
pipeline document:
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
dg schema create examples/schemas/ou-record.json
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
A schema reads its own identity from its keywords: `$id` becomes the `code` it is addressed
|
|
168
|
+
by, `title` its name, and `description` its body. A server that applies a directory at boot
|
|
169
|
+
stores the schemas it finds there too, before the pipelines that require them, so mounting this
|
|
170
|
+
whole directory lands the schemas as well as the documents. See
|
|
171
|
+
[schemas/README.md](schemas/README.md) and the [JSON Schema guide](../docs/json-schema.md).
|
|
172
|
+
|
|
173
|
+
## Recipes
|
|
174
|
+
|
|
175
|
+
[`recipes/`](recipes) is the widest shelf and the one to read while doing the work rather
|
|
176
|
+
than while learning the format. Each file answers one question a person doing data work
|
|
177
|
+
actually asks -- how do I group and sum, how do I join two lists, which types survive a
|
|
178
|
+
parquet round trip, where do credentials live -- in a complete pipeline whose header comment
|
|
179
|
+
is the lesson. Nothing on the shelf needs infrastructure, a credential, or an allowlist
|
|
180
|
+
entry: the data is inline, generated by a jq program, or fetched from Postman Echo.
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
dg run --local examples/recipes/jq-group-by-and-sum.yaml
|
|
184
|
+
dg run --local examples/recipes/etl-csv-clean-validate-parquet.yaml
|
|
185
|
+
dg run --local examples/recipes/schema-refuses-then-rule.yaml # fails, by design
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
Two of them end `failed` on purpose and say so in their headers:
|
|
189
|
+
`recipes/schema-refuses-then-rule.yaml`, where a gate refuses and the error branch runs, and
|
|
190
|
+
`recipes/reconcile-two-sources.yaml`, where the two sources disagree past the tolerance the
|
|
191
|
+
run was given. [recipes/README.md](recipes/README.md) indexes all forty-seven by the question
|
|
192
|
+
each one answers.
|
|
193
|
+
|
|
194
|
+
## The examples
|
|
195
|
+
|
|
196
|
+
Each shelf's README indexes its own documents; what stays at the root is the front door:
|
|
197
|
+
|
|
198
|
+
| File | What it demonstrates |
|
|
199
|
+
| --- | --- |
|
|
200
|
+
| [hello-world.yaml](hello-world.yaml) | The smallest runnable document: one step, no parameters, nothing granted |
|
|
201
|
+
| [connections.yaml](connections.yaml) | The credential file a `--local` run is handed |
|
|
202
|
+
|
|
203
|
+
Two of them are worth running twice, because a parameter flips which branch is taken:
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
dg run --local examples/failure/retries.yaml -p status=200 # publish succeeds; still completed_with_errors as the cache times out
|
|
207
|
+
dg run --local examples/failure/error-handler.yaml -p status=200 # the success branch, not the alert
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
## Preview documents
|
|
211
|
+
|
|
212
|
+
[`preview/`](preview) holds documents whose blocks or packages an instance may not have. They
|
|
213
|
+
are valid `dirigent/v1` and they round-trip, but applying one to an instance without what it
|
|
214
|
+
names is refused by the `requires` preflight with a list of what is missing. They are here to
|
|
215
|
+
show that the format never grows per-integration syntax: everything domain-specific lives
|
|
216
|
+
inside `config`, which the format treats as opaque and each block validates against its own
|
|
217
|
+
published schema.
|
|
218
|
+
|
|
219
|
+
[`preview/s3-parquet-to-ingestion.yaml`](preview/s3-parquet-to-ingestion.yaml) is the one on
|
|
220
|
+
the shelf today: every block it names is installed, and what it needs is the
|
|
221
|
+
`dirigent-storage-s3` package and an endpoint for the `s3://` scheme it addresses.
|
|
222
|
+
|
|
223
|
+
## Composing pipelines
|
|
224
|
+
|
|
225
|
+
A dirigent document holds exactly one pipeline, so a parent and its child are two files, and
|
|
226
|
+
the apply order matters: the child has to exist before the parent will apply at all. The
|
|
227
|
+
parent says so in `requires.pipelines`, so a missing child is refused up front, with the
|
|
228
|
+
code to apply first, rather than failing at the step.
|
|
229
|
+
|
|
230
|
+
```bash
|
|
231
|
+
dg apply examples/composition/composition-child.yaml
|
|
232
|
+
dg apply examples/composition/composition-parent.yaml
|
|
233
|
+
dg run composition-parent -p day=2026-01-01 --watch
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
A local run starts on an empty throwaway instance, so the child is handed over with
|
|
237
|
+
`--also-apply`, which applies a document without running it:
|
|
238
|
+
|
|
239
|
+
```bash
|
|
240
|
+
dg run --local examples/composition/composition-parent.yaml \
|
|
241
|
+
--also-apply examples/composition/composition-child.yaml \
|
|
242
|
+
-p day=2026-01-01 --enable-unsafe shell.run
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
## Why every example is self-contained
|
|
246
|
+
|
|
247
|
+
Almost every document here defines the pipeline it schedules or hooks, because a pipeline
|
|
248
|
+
document carries its own `triggers:` section and one file is then one deployable unit. That
|
|
249
|
+
is what keeps the schedule examples runnable on their own: each teaches one clock, and a
|
|
250
|
+
reader can fire it ad hoc without applying anything else first.
|
|
251
|
+
|
|
252
|
+
The other form has its own example. A `kind: triggers` document declares clocks and webhooks
|
|
253
|
+
for a pipeline defined somewhere else and names it -- the ops team's clock file over a
|
|
254
|
+
pipeline another team owns. [triggers/document-nightly.yaml](triggers/document-nightly.yaml)
|
|
255
|
+
is that document, and it targets the pipeline in
|
|
256
|
+
[triggers/managed-and-manual.yaml](triggers/managed-and-manual.yaml), so the two teach
|
|
257
|
+
together: apply the pipeline, then apply its clocks.
|
|
258
|
+
|
|
259
|
+
## Putting the whole corpus into one instance
|
|
260
|
+
|
|
261
|
+
`make dev-seeded` boots a `dg dev --seed examples` with everything on this page already
|
|
262
|
+
applied, so there is something to look at without applying forty documents by hand. The
|
|
263
|
+
instance walks this directory for `dirigent/v1` documents, creates the connections
|
|
264
|
+
[connections.yaml](connections.yaml) carries, applies each document with its schedules
|
|
265
|
+
paused, and creates what a document carries for its own standalone run before applying it
|
|
266
|
+
without that section. The target adds what only the demo wants: the object store
|
|
267
|
+
`s3-round-trip.yaml` names, a document pointed at a connection nothing holds, six runs, and
|
|
268
|
+
one health check per connection. Then it hands the terminal to `dg dev`; one ctrl-c ends both.
|
|
269
|
+
|
|
270
|
+
```bash
|
|
271
|
+
make dev-seeded | dg format
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
**Seeing failures is the point.** An instance where everything is green teaches nothing about
|
|
275
|
+
what a failure looks like, so the seeded one is deliberately mixed:
|
|
276
|
+
|
|
277
|
+
| What lands | How many | Why |
|
|
278
|
+
| --- | --- | --- |
|
|
279
|
+
| Pipelines stored | 159 | Every document here that an instance will hold, including the ones that carry their own connections or schemas: the seed creates what they carry and applies the rest, which is the only form an instance stores |
|
|
280
|
+
| Documents refused | 18 | Nine in [docker/](docker) and two in [git/](git) name a compose or a build block the seed does not allowlist, some of them also a connection it does not create; four name a connection that does not exist, one of them (`warehouse-nobody-created`) built by the seed on purpose; one names a schema no instance here holds; and two require a pipeline or a target applied after them |
|
|
281
|
+
| Schedules | 17, all paused | `--paused` is what stops seventeen clocks starting to fire at somebody who has not looked at them |
|
|
282
|
+
| Runs | 3 succeeded, 1 with errors, 2 failed | `hello-world`, `transform/jq-reshape.yaml` and `triggers/cron-windowed.yaml` settle green; `optional-step.yaml` settles `completed_with_errors`, which is a third status rather than a shade of failed; `error-handler.yaml` fails by design, and `s3-round-trip.yaml` cannot reach an object store nobody started |
|
|
283
|
+
| Connections | 10 healthy, 4 red | The ten that answer are `postman-echo` and the public endpoints the documents carry for their own standalone runs; `artifacts` points at `127.0.0.1:9000`, `work-db` at a database nobody started, and `orders-topic` and `shop-queue` at the two brokers in `infra/compose.queues.yaml`, where nothing is listening unless you started what their headers document |
|
|
284
|
+
|
|
285
|
+
The refusals are reported by code with the reason the instance gave, and the seeding carries
|
|
286
|
+
on past each one -- a refusal is a thing to look at, not an error to fix.
|
|
287
|
+
|
|
288
|
+
State lands in `.dirigent/state` under the working directory: the SQLite database and the
|
|
289
|
+
artifacts. `dg dev` empties that directory on every start, so each seeding builds a fresh
|
|
290
|
+
instance and the key its connections are sealed with is minted per run and thrown away with
|
|
291
|
+
them. `SEED_ROOT=/somewhere/else` puts it elsewhere, and `SEED_PORT` moves the instance off
|
|
292
|
+
3333.
|
|
293
|
+
|
|
294
|
+
Re-running is safe, and it starts over: the instance is emptied first, so every apply is a
|
|
295
|
+
`created` against a database with nothing in it, nothing accumulates between seedings, and a
|
|
296
|
+
schedule you resumed by hand is gone with the rest. That is the trade the target makes for
|
|
297
|
+
never answering out of an older schema.
|
|
298
|
+
|
|
299
|
+
The target is for looking at things by hand. Nothing in `make check` or CI runs it.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Composition examples
|
|
2
|
+
|
|
3
|
+
Pipelines made of pipelines: a child that stands on its own, a parent that runs it per
|
|
4
|
+
region, and a handoff to a second instance when the next stage belongs to somebody else.
|
|
5
|
+
`pipeline.run` keeps the child a first-class run -- its own id, its own log, its own row --
|
|
6
|
+
rather than steps inlined into the parent.
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
dg run --local examples/composition/composition-parent.yaml --also-apply examples/composition/composition-child.yaml -p day=2026-01-01 --enable-unsafe shell.run
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## Pipelines
|
|
13
|
+
|
|
14
|
+
| File | What it teaches |
|
|
15
|
+
| --- | --- |
|
|
16
|
+
| [composition-child.yaml](composition-child.yaml) | The reusable unit: callable on its own, or by whatever composes it. |
|
|
17
|
+
| [composition-parent.yaml](composition-parent.yaml) | `pipeline.run` per region: one child waited for, one fired and left to finish alone. |
|
|
18
|
+
| [chained-instances.yaml](chained-instances.yaml) | Across the boundary: the result handed to another dirigent instance as a signed webhook, because the next stage is theirs. |
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# Handing work to another dirigent instance, signed the way that instance verifies it.
|
|
2
|
+
#
|
|
3
|
+
# pipeline.run composes pipelines on one instance. This is the other shape: two instances,
|
|
4
|
+
# each with its own database, schedules, and operators, where one hands the next a payload
|
|
5
|
+
# and stops caring. The receiving side is an ordinary inbound webhook -- `dg webhook create`
|
|
6
|
+
# on that instance -- whose token is the whole credential and whose params_from_payload maps
|
|
7
|
+
# the body onto its own parameter schema.
|
|
8
|
+
#
|
|
9
|
+
# What webhook.post adds over http.request with method: POST is the signature, and that is
|
|
10
|
+
# the only reason to reach for it. It renders the JSON body itself and computes an HMAC over
|
|
11
|
+
# exactly those bytes, sent as X-Dirigent-Signature, in the format dirigent's own
|
|
12
|
+
# /hooks/{token} intake verifies. Posting a body nobody signs is http.request's job.
|
|
13
|
+
#
|
|
14
|
+
# The secret is the connection's hmac_secret, named by sign_with. The receiving webhook is
|
|
15
|
+
# declared with the same one:
|
|
16
|
+
# dg webhook create downstream-pipeline handoff --hmac-secret "$SHARED_SECRET"
|
|
17
|
+
#
|
|
18
|
+
# The secret lives on the connection, never in this file: a document names a credential, it
|
|
19
|
+
# does not carry one.
|
|
20
|
+
#
|
|
21
|
+
# The receiver here is Postman Echo, which reflects whatever it is posted, so this runs
|
|
22
|
+
# against no instance at all and the reflected body shows what went on the wire, signature
|
|
23
|
+
# header included:
|
|
24
|
+
# dg run --local examples/composition/chained-instances.yaml \
|
|
25
|
+
# --connections examples/connections.yaml -p day=2026-01-01
|
|
26
|
+
#
|
|
27
|
+
# Against a real peer the only change is the connection: base_url becomes that instance's
|
|
28
|
+
# URL, path becomes /hooks/<the token it minted>, and sign_with names the same connection.
|
|
29
|
+
|
|
30
|
+
format: dirigent/v1
|
|
31
|
+
kind: pipeline
|
|
32
|
+
code: chained-instances
|
|
33
|
+
name: One instance triggers another
|
|
34
|
+
description: Produce a result, then hand it to another dirigent instance as a signed webhook.
|
|
35
|
+
|
|
36
|
+
tags: [composition, http, webhook]
|
|
37
|
+
|
|
38
|
+
requires:
|
|
39
|
+
blocks:
|
|
40
|
+
- http.request
|
|
41
|
+
- webhook.post
|
|
42
|
+
connections:
|
|
43
|
+
- postman-echo
|
|
44
|
+
|
|
45
|
+
params:
|
|
46
|
+
type: object
|
|
47
|
+
required: [day]
|
|
48
|
+
additionalProperties: false
|
|
49
|
+
properties:
|
|
50
|
+
day:
|
|
51
|
+
type: string
|
|
52
|
+
format: date
|
|
53
|
+
description: The day whose result is handed downstream.
|
|
54
|
+
|
|
55
|
+
steps:
|
|
56
|
+
produce:
|
|
57
|
+
block: http.request
|
|
58
|
+
config:
|
|
59
|
+
connection: postman-echo
|
|
60
|
+
path: /post
|
|
61
|
+
method: POST
|
|
62
|
+
body:
|
|
63
|
+
day: "${params.day}"
|
|
64
|
+
rows: 4200
|
|
65
|
+
|
|
66
|
+
hand_off:
|
|
67
|
+
block: webhook.post
|
|
68
|
+
depends_on: [produce]
|
|
69
|
+
retry:
|
|
70
|
+
max_attempts: 3
|
|
71
|
+
backoff: 5s
|
|
72
|
+
config:
|
|
73
|
+
connection: postman-echo
|
|
74
|
+
path: /post
|
|
75
|
+
# The receiving instance verifies the signature against the same secret, so a handoff
|
|
76
|
+
# cannot be forged by anything that merely knows the URL.
|
|
77
|
+
sign_with: postman-echo
|
|
78
|
+
# A receiver that queues the work answers 202, which is a success here even though the
|
|
79
|
+
# work has not happened yet: the handoff is what this step is responsible for.
|
|
80
|
+
success_status: [200, 201, 202]
|
|
81
|
+
headers:
|
|
82
|
+
X-Dirigent-Source: chained-instances
|
|
83
|
+
body:
|
|
84
|
+
day: "${params.day}"
|
|
85
|
+
upstream_run: "${run.id}"
|
|
86
|
+
rows: "${steps.produce.output.body.json.rows}"
|
|
87
|
+
|
|
88
|
+
confirm:
|
|
89
|
+
block: http.request
|
|
90
|
+
depends_on: [hand_off]
|
|
91
|
+
config:
|
|
92
|
+
connection: postman-echo
|
|
93
|
+
path: /post
|
|
94
|
+
method: POST
|
|
95
|
+
body:
|
|
96
|
+
handed_off_with_status: "${steps.hand_off.output.status}"
|
|
97
|
+
signed: "${steps.hand_off.output.signed}"
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# The child half of a composed pair: an ordinary pipeline that knows nothing about parents.
|
|
2
|
+
#
|
|
3
|
+
# Nothing here says it is a child: it has its own name, its own parameter schema, and its
|
|
4
|
+
# own run history, and it can be run on its own, scheduled on its own, or called by three
|
|
5
|
+
# different parents. Being callable is not something a document opts into.
|
|
6
|
+
#
|
|
7
|
+
# The parameter schema is the interface. composition-parent.yaml writes these parameters out
|
|
8
|
+
# explicitly rather than forwarding whatever it was run with.
|
|
9
|
+
#
|
|
10
|
+
# Apply this one first -- composition-parent.yaml requires it by name:
|
|
11
|
+
# dg apply examples/composition/composition-child.yaml
|
|
12
|
+
# dg apply examples/composition/composition-parent.yaml
|
|
13
|
+
#
|
|
14
|
+
# Or run the parent locally, which applies this one into the throwaway instance for you:
|
|
15
|
+
# dg run --local examples/composition/composition-parent.yaml --also-apply examples/composition/composition-child.yaml
|
|
16
|
+
|
|
17
|
+
format: dirigent/v1
|
|
18
|
+
kind: pipeline
|
|
19
|
+
code: composition-child
|
|
20
|
+
name: The called pipeline
|
|
21
|
+
description: Load one region's data for one day; callable on its own or by a parent pipeline.
|
|
22
|
+
|
|
23
|
+
tags: [composition, http, storage]
|
|
24
|
+
|
|
25
|
+
params:
|
|
26
|
+
type: object
|
|
27
|
+
required: [region, day]
|
|
28
|
+
additionalProperties: false
|
|
29
|
+
properties:
|
|
30
|
+
region:
|
|
31
|
+
type: string
|
|
32
|
+
description: Which region this run loads.
|
|
33
|
+
day:
|
|
34
|
+
type: string
|
|
35
|
+
format: date
|
|
36
|
+
description: The day being loaded.
|
|
37
|
+
|
|
38
|
+
steps:
|
|
39
|
+
fetch:
|
|
40
|
+
block: http.request
|
|
41
|
+
retry:
|
|
42
|
+
max_attempts: 3
|
|
43
|
+
config:
|
|
44
|
+
url: https://postman-echo.com/post
|
|
45
|
+
method: POST
|
|
46
|
+
body:
|
|
47
|
+
region: "${params.region}"
|
|
48
|
+
day: "${params.day}"
|
|
49
|
+
|
|
50
|
+
store:
|
|
51
|
+
block: storage.write
|
|
52
|
+
depends_on: [fetch]
|
|
53
|
+
config:
|
|
54
|
+
# The child writes under its own run's scratch, so two children of the same parent
|
|
55
|
+
# never write to the same place, whatever region they were given.
|
|
56
|
+
target: "${run.scratch}/regions/${params.region}.json"
|
|
57
|
+
value: "${steps.fetch.output.body}"
|
|
58
|
+
|
|
59
|
+
archive:
|
|
60
|
+
block: storage.copy
|
|
61
|
+
depends_on: [store]
|
|
62
|
+
config:
|
|
63
|
+
source: "${steps.store.output.uri}"
|
|
64
|
+
target: "${run.scratch}/archive/${params.day}/${params.region}.json"
|