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.
Files changed (216) hide show
  1. dirigent_examples-0.15.0/LICENSE +18 -0
  2. dirigent_examples-0.15.0/PKG-INFO +21 -0
  3. dirigent_examples-0.15.0/README.md +10 -0
  4. dirigent_examples-0.15.0/pyproject.toml +25 -0
  5. dirigent_examples-0.15.0/pyproject.toml.orig +24 -0
  6. dirigent_examples-0.15.0/src/dirigent_examples/__init__.py +22 -0
  7. dirigent_examples-0.15.0/src/dirigent_examples/py.typed +0 -0
  8. dirigent_examples-0.15.0/src/dirigent_examples/shelves/README.md +299 -0
  9. dirigent_examples-0.15.0/src/dirigent_examples/shelves/composition/README.md +18 -0
  10. dirigent_examples-0.15.0/src/dirigent_examples/shelves/composition/chained-instances.yaml +97 -0
  11. dirigent_examples-0.15.0/src/dirigent_examples/shelves/composition/composition-child.yaml +64 -0
  12. dirigent_examples-0.15.0/src/dirigent_examples/shelves/composition/composition-parent.yaml +89 -0
  13. dirigent_examples-0.15.0/src/dirigent_examples/shelves/connections.yaml +52 -0
  14. dirigent_examples-0.15.0/src/dirigent_examples/shelves/demo/README.md +19 -0
  15. dirigent_examples-0.15.0/src/dirigent_examples/shelves/demo/markdown-showcase.yaml +117 -0
  16. dirigent_examples-0.15.0/src/dirigent_examples/shelves/demo/params-showcase.yaml +92 -0
  17. dirigent_examples-0.15.0/src/dirigent_examples/shelves/demo/requires.yaml +65 -0
  18. dirigent_examples-0.15.0/src/dirigent_examples/shelves/demo/weekly-import-malawi.yaml +54 -0
  19. dirigent_examples-0.15.0/src/dirigent_examples/shelves/demo/weekly-import-nepal.yaml +75 -0
  20. dirigent_examples-0.15.0/src/dirigent_examples/shelves/docker/README.md +29 -0
  21. dirigent_examples-0.15.0/src/dirigent_examples/shelves/docker/docker-build-push.yaml +110 -0
  22. dirigent_examples-0.15.0/src/dirigent_examples/shelves/docker/docker-build-run.yaml +106 -0
  23. dirigent_examples-0.15.0/src/dirigent_examples/shelves/docker/docker-compose-database.yaml +124 -0
  24. dirigent_examples-0.15.0/src/dirigent_examples/shelves/docker/docker-compose-failing-up.yaml +83 -0
  25. dirigent_examples-0.15.0/src/dirigent_examples/shelves/docker/docker-compose-file.yaml +117 -0
  26. dirigent_examples-0.15.0/src/dirigent_examples/shelves/docker/docker-compose-profiles-env.yaml +133 -0
  27. dirigent_examples-0.15.0/src/dirigent_examples/shelves/docker/docker-compose-stack.yaml +70 -0
  28. dirigent_examples-0.15.0/src/dirigent_examples/shelves/docker/docker-hello.yaml +53 -0
  29. dirigent_examples-0.15.0/src/dirigent_examples/shelves/docker/docker-remote-daemon.yaml +92 -0
  30. dirigent_examples-0.15.0/src/dirigent_examples/shelves/docker/docker-run-failing-teardown.yaml +94 -0
  31. dirigent_examples-0.15.0/src/dirigent_examples/shelves/docker/docker-ticker.yaml +49 -0
  32. dirigent_examples-0.15.0/src/dirigent_examples/shelves/execute/README.md +16 -0
  33. dirigent_examples-0.15.0/src/dirigent_examples/shelves/execute/long-log.yaml +89 -0
  34. dirigent_examples-0.15.0/src/dirigent_examples/shelves/failure/README.md +20 -0
  35. dirigent_examples-0.15.0/src/dirigent_examples/shelves/failure/error-handler.yaml +89 -0
  36. dirigent_examples-0.15.0/src/dirigent_examples/shelves/failure/optional-step.yaml +82 -0
  37. dirigent_examples-0.15.0/src/dirigent_examples/shelves/failure/retries.yaml +75 -0
  38. dirigent_examples-0.15.0/src/dirigent_examples/shelves/failure/retry-budget.yaml +82 -0
  39. dirigent_examples-0.15.0/src/dirigent_examples/shelves/failure/step-timeout.yaml +96 -0
  40. dirigent_examples-0.15.0/src/dirigent_examples/shelves/git/README.md +32 -0
  41. dirigent_examples-0.15.0/src/dirigent_examples/shelves/git/git-checkout-build.yaml +125 -0
  42. dirigent_examples-0.15.0/src/dirigent_examples/shelves/git/git-checkout-compose.yaml +138 -0
  43. dirigent_examples-0.15.0/src/dirigent_examples/shelves/git/git-checkout-public.yaml +84 -0
  44. dirigent_examples-0.15.0/src/dirigent_examples/shelves/graph/README.md +22 -0
  45. dirigent_examples-0.15.0/src/dirigent_examples/shelves/graph/deep-chain.yaml +119 -0
  46. dirigent_examples-0.15.0/src/dirigent_examples/shelves/graph/fan-in.yaml +80 -0
  47. dirigent_examples-0.15.0/src/dirigent_examples/shelves/graph/fan-out.yaml +66 -0
  48. dirigent_examples-0.15.0/src/dirigent_examples/shelves/graph/linear.yaml +66 -0
  49. dirigent_examples-0.15.0/src/dirigent_examples/shelves/graph/parallel-branches.yaml +57 -0
  50. dirigent_examples-0.15.0/src/dirigent_examples/shelves/graph/parallel-sleep.yaml +55 -0
  51. dirigent_examples-0.15.0/src/dirigent_examples/shelves/graph/skip-diamond.yaml +105 -0
  52. dirigent_examples-0.15.0/src/dirigent_examples/shelves/graph/wide-fan.yaml +147 -0
  53. dirigent_examples-0.15.0/src/dirigent_examples/shelves/hello-world.yaml +30 -0
  54. dirigent_examples-0.15.0/src/dirigent_examples/shelves/open-data/README.md +67 -0
  55. dirigent_examples-0.15.0/src/dirigent_examples/shelves/open-data/feeds-composition.yaml +120 -0
  56. dirigent_examples-0.15.0/src/dirigent_examples/shelves/open-data/gdacs-disaster-updates.yaml +230 -0
  57. dirigent_examples-0.15.0/src/dirigent_examples/shelves/open-data/github-releases-relay.yaml +225 -0
  58. dirigent_examples-0.15.0/src/dirigent_examples/shelves/open-data/hdx-dataset-watch.yaml +211 -0
  59. dirigent_examples-0.15.0/src/dirigent_examples/shelves/open-data/kobo-submissions-to-csv.yaml +149 -0
  60. dirigent_examples-0.15.0/src/dirigent_examples/shelves/open-data/nominatim-geocode-facilities.yaml +169 -0
  61. dirigent_examples-0.15.0/src/dirigent_examples/shelves/open-data/odk-central-submissions.yaml +146 -0
  62. dirigent_examples-0.15.0/src/dirigent_examples/shelves/open-data/open-meteo-weekly-report.yaml +142 -0
  63. dirigent_examples-0.15.0/src/dirigent_examples/shelves/open-data/overpass-health-facilities.yaml +154 -0
  64. dirigent_examples-0.15.0/src/dirigent_examples/shelves/open-data/usgs-earthquakes-alert.yaml +208 -0
  65. dirigent_examples-0.15.0/src/dirigent_examples/shelves/open-data/who-gho-indicators-to-parquet.yaml +163 -0
  66. dirigent_examples-0.15.0/src/dirigent_examples/shelves/open-data/wikidata-country-reference.yaml +146 -0
  67. dirigent_examples-0.15.0/src/dirigent_examples/shelves/open-data/world-bank-population-trend.yaml +166 -0
  68. dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/README.md +144 -0
  69. dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/concurrency-queue.yaml +89 -0
  70. dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/concurrency-replace.yaml +92 -0
  71. dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/concurrency-skip.yaml +97 -0
  72. dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/connections-referenced-vs-carried.yaml +140 -0
  73. dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/deadline-on-a-sensor.yaml +106 -0
  74. dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/fan-out-continue.yaml +88 -0
  75. dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/fan-out-fail-fast.yaml +80 -0
  76. dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/fan-out-from-params.yaml +84 -0
  77. dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/fan-out-item-wise.yaml +111 -0
  78. dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/fan-out-literal-list.yaml +81 -0
  79. dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/fan-out-nested-objects.yaml +107 -0
  80. dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/fan-out-then-join.yaml +86 -0
  81. dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/log-levels.yaml +119 -0
  82. dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/outputs-inline-vs-storage.yaml +140 -0
  83. dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/params-every-type.yaml +259 -0
  84. dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/params-validation-refuses.yaml +131 -0
  85. dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/pipeline-run-child.yaml +96 -0
  86. dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/pipeline-run-fire-and-forget.yaml +99 -0
  87. dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/pipeline-run-strict.yaml +103 -0
  88. dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/pipeline-run-wait.yaml +107 -0
  89. dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/pipeline-run-with-params.yaml +124 -0
  90. dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/poll-cadence.yaml +102 -0
  91. dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/priority-layered.yaml +120 -0
  92. dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/references-cheat-sheet.yaml +186 -0
  93. dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/retry-budget-exhausted.yaml +92 -0
  94. dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/retry-exponential-backoff.yaml +88 -0
  95. dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/retry-only-transient.yaml +108 -0
  96. dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/retry-with-jitter.yaml +102 -0
  97. dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/rule-all-done.yaml +83 -0
  98. dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/rule-all-success.yaml +79 -0
  99. dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/rule-always.yaml +92 -0
  100. dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/rule-one-failed.yaml +86 -0
  101. dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/schedule-at-once.yaml +110 -0
  102. dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/schedule-cron-timezone.yaml +121 -0
  103. dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/schedule-interval.yaml +109 -0
  104. dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/schedule-window-half-open.yaml +105 -0
  105. dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/sensor-http-ready.yaml +121 -0
  106. dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/sensor-storage-exists.yaml +134 -0
  107. dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/step-names-and-keys.yaml +99 -0
  108. dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/timeout-fails-the-step.yaml +94 -0
  109. dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/timeout-skips-the-step.yaml +102 -0
  110. dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/webhook-mapping-nested-payload.yaml +125 -0
  111. dirigent_examples-0.15.0/src/dirigent_examples/shelves/patterns/webhook-signed.yaml +144 -0
  112. dirigent_examples-0.15.0/src/dirigent_examples/shelves/preview/s3-parquet-to-ingestion.yaml +92 -0
  113. dirigent_examples-0.15.0/src/dirigent_examples/shelves/python/README.md +31 -0
  114. dirigent_examples-0.15.0/src/dirigent_examples/shelves/python/apply_and_run.py +52 -0
  115. dirigent_examples-0.15.0/src/dirigent_examples/shelves/python/ci_gate.py +76 -0
  116. dirigent_examples-0.15.0/src/dirigent_examples/shelves/python/connections.py +61 -0
  117. dirigent_examples-0.15.0/src/dirigent_examples/shelves/python/error_handling.py +84 -0
  118. dirigent_examples-0.15.0/src/dirigent_examples/shelves/python/follow_logs.py +39 -0
  119. dirigent_examples-0.15.0/src/dirigent_examples/shelves/python/list_and_filter.py +52 -0
  120. dirigent_examples-0.15.0/src/dirigent_examples/shelves/queues/README.md +59 -0
  121. dirigent_examples-0.15.0/src/dirigent_examples/shelves/queues/kafka-consume-then-transform.yaml +105 -0
  122. dirigent_examples-0.15.0/src/dirigent_examples/shelves/queues/kafka-produce-then-consume.yaml +124 -0
  123. dirigent_examples-0.15.0/src/dirigent_examples/shelves/queues/rabbitmq-consume-ack-on-success.yaml +102 -0
  124. dirigent_examples-0.15.0/src/dirigent_examples/shelves/queues/report-to-kafka.yaml +105 -0
  125. dirigent_examples-0.15.0/src/dirigent_examples/shelves/queues/report-to-rabbitmq.yaml +105 -0
  126. dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/README.md +130 -0
  127. dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/csv-header-rules.yaml +147 -0
  128. dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/csv-to-ndjson.yaml +107 -0
  129. dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/etl-csv-clean-validate-parquet.yaml +207 -0
  130. dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/filter-by-predicate.yaml +116 -0
  131. dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/filter-then-map-then-reduce.yaml +109 -0
  132. dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/http-fetch-validate-post.yaml +142 -0
  133. dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/http-follow-redirects.yaml +100 -0
  134. dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/http-get-with-query.yaml +96 -0
  135. dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/http-headers-and-auth-connection.yaml +110 -0
  136. dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/http-post-file-from-storage.yaml +117 -0
  137. dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/http-post-json-echo.yaml +105 -0
  138. dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/http-post-report.yaml +183 -0
  139. dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/http-save-body-to-storage.yaml +106 -0
  140. dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/http-success-status-list.yaml +80 -0
  141. dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/http-timeout-override.yaml +104 -0
  142. dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/jq-dedupe-by-key.yaml +78 -0
  143. dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/jq-defaults-and-nulls.yaml +91 -0
  144. dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/jq-group-by-and-sum.yaml +74 -0
  145. dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/jq-join-two-lists.yaml +77 -0
  146. dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/jq-long-to-wide.yaml +76 -0
  147. dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/jq-nested-to-flat.yaml +89 -0
  148. dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/jq-pivot-wide-to-long.yaml +65 -0
  149. dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/jq-running-totals.yaml +82 -0
  150. dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/jq-string-cleaning.yaml +88 -0
  151. dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/jq-top-n.yaml +85 -0
  152. dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/jq-validate-in-jq-vs-schema.yaml +124 -0
  153. dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/jq-window-dates.yaml +82 -0
  154. dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/json-to-csv-flattening.yaml +141 -0
  155. dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/large-output-to-storage.yaml +134 -0
  156. dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/map-enrich-with-lookup.yaml +96 -0
  157. dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/ndjson-to-parquet.yaml +130 -0
  158. dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/pagination-by-fan-out.yaml +115 -0
  159. dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/parquet-round-trip-types.yaml +163 -0
  160. dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/reconcile-two-sources.yaml +159 -0
  161. dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/report-built-in.yaml +72 -0
  162. dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/report-daily-digest.yaml +186 -0
  163. dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/report-to-file.yaml +131 -0
  164. dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/report-to-webhook.yaml +136 -0
  165. dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/schema-carried.yaml +112 -0
  166. dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/schema-formats.yaml +107 -0
  167. dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/schema-referenced.yaml +86 -0
  168. dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/schema-refuses-then-rule.yaml +127 -0
  169. dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/storage-copy-dated-archive.yaml +114 -0
  170. dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/storage-exists-gate.yaml +127 -0
  171. dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/storage-manifest-of-a-fan-out.yaml +104 -0
  172. dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/storage-write-then-read.yaml +119 -0
  173. dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/webhook-post-hmac.yaml +132 -0
  174. dirigent_examples-0.15.0/src/dirigent_examples/shelves/recipes/webhook-post-summary.yaml +142 -0
  175. dirigent_examples-0.15.0/src/dirigent_examples/shelves/s3/README.md +34 -0
  176. dirigent_examples-0.15.0/src/dirigent_examples/shelves/s3/report-to-s3.yaml +93 -0
  177. dirigent_examples-0.15.0/src/dirigent_examples/shelves/s3/s3-copy-and-verify.yaml +105 -0
  178. dirigent_examples-0.15.0/src/dirigent_examples/shelves/s3/s3-csv-report.yaml +87 -0
  179. dirigent_examples-0.15.0/src/dirigent_examples/shelves/s3/s3-parquet-report.yaml +77 -0
  180. dirigent_examples-0.15.0/src/dirigent_examples/shelves/s3/s3-round-trip.yaml +125 -0
  181. dirigent_examples-0.15.0/src/dirigent_examples/shelves/schemas/README.md +36 -0
  182. dirigent_examples-0.15.0/src/dirigent_examples/shelves/schemas/echo-reading.json +18 -0
  183. dirigent_examples-0.15.0/src/dirigent_examples/shelves/schemas/ou-record.json +13 -0
  184. dirigent_examples-0.15.0/src/dirigent_examples/shelves/schemas/station-reading.json +13 -0
  185. dirigent_examples-0.15.0/src/dirigent_examples/shelves/sensors/README.md +16 -0
  186. dirigent_examples-0.15.0/src/dirigent_examples/shelves/sensors/sensor-gate.yaml +65 -0
  187. dirigent_examples-0.15.0/src/dirigent_examples/shelves/sensors/time-window.yaml +61 -0
  188. dirigent_examples-0.15.0/src/dirigent_examples/shelves/sql/README.md +52 -0
  189. dirigent_examples-0.15.0/src/dirigent_examples/shelves/sql/duckdb-parquet-to-report.yaml +146 -0
  190. dirigent_examples-0.15.0/src/dirigent_examples/shelves/sql/sql-postgres-readonly.yaml +111 -0
  191. dirigent_examples-0.15.0/src/dirigent_examples/shelves/sql/sql-query-to-storage.yaml +85 -0
  192. dirigent_examples-0.15.0/src/dirigent_examples/shelves/sql/sql-sqlite-roundtrip.yaml +114 -0
  193. dirigent_examples-0.15.0/src/dirigent_examples/shelves/sql/warehouse.sql +42 -0
  194. dirigent_examples-0.15.0/src/dirigent_examples/shelves/transform/README.md +36 -0
  195. dirigent_examples-0.15.0/src/dirigent_examples/shelves/transform/csv-report.yaml +55 -0
  196. dirigent_examples-0.15.0/src/dirigent_examples/shelves/transform/jq-filter-and-map.yaml +70 -0
  197. dirigent_examples-0.15.0/src/dirigent_examples/shelves/transform/jq-group-and-aggregate.yaml +70 -0
  198. dirigent_examples-0.15.0/src/dirigent_examples/shelves/transform/jq-join-two-sources.yaml +98 -0
  199. dirigent_examples-0.15.0/src/dirigent_examples/shelves/transform/jq-reshape.yaml +91 -0
  200. dirigent_examples-0.15.0/src/dirigent_examples/shelves/transform/jq-stream-through-storage.yaml +112 -0
  201. dirigent_examples-0.15.0/src/dirigent_examples/shelves/transform/ndjson-round-trip.yaml +56 -0
  202. dirigent_examples-0.15.0/src/dirigent_examples/shelves/transform/parquet-round-trip.yaml +68 -0
  203. dirigent_examples-0.15.0/src/dirigent_examples/shelves/transform/std-convert-fan-out.yaml +142 -0
  204. dirigent_examples-0.15.0/src/dirigent_examples/shelves/transform/xml-feed-to-ndjson.yaml +116 -0
  205. dirigent_examples-0.15.0/src/dirigent_examples/shelves/transform/yaml-config-to-json.yaml +104 -0
  206. dirigent_examples-0.15.0/src/dirigent_examples/shelves/triggers/README.md +45 -0
  207. dirigent_examples-0.15.0/src/dirigent_examples/shelves/triggers/at-one-time.yaml +78 -0
  208. dirigent_examples-0.15.0/src/dirigent_examples/shelves/triggers/cron-nightly.yaml +79 -0
  209. dirigent_examples-0.15.0/src/dirigent_examples/shelves/triggers/cron-windowed.yaml +86 -0
  210. dirigent_examples-0.15.0/src/dirigent_examples/shelves/triggers/document-nightly.yaml +80 -0
  211. dirigent_examples-0.15.0/src/dirigent_examples/shelves/triggers/interval-rolling.yaml +88 -0
  212. dirigent_examples-0.15.0/src/dirigent_examples/shelves/triggers/managed-and-manual.yaml +109 -0
  213. dirigent_examples-0.15.0/src/dirigent_examples/shelves/triggers/webhook-trigger.yaml +75 -0
  214. dirigent_examples-0.15.0/src/dirigent_examples/shelves/validate/README.md +31 -0
  215. dirigent_examples-0.15.0/src/dirigent_examples/shelves/validate/expects-a-shape.yaml +56 -0
  216. 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()
@@ -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"