tangle-cli 0.1.9__tar.gz → 0.1.11__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.
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/PKG-INFO +103 -3
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/README.md +102 -2
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/packages/tangle-cli/src/tangle_cli/__init__.py +1 -1
- tangle_cli-0.1.11/packages/tangle-cli/src/tangle_cli/args_container.py +518 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/packages/tangle-cli/src/tangle_cli/openapi/codegen.py +37 -15
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/packages/tangle-cli/src/tangle_cli/python_pipeline/emit.py +179 -3
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/packages/tangle-cli/src/tangle_cli/python_pipeline/graph.py +12 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/packages/tangle-cli/src/tangle_cli/python_pipeline/ref.py +20 -2
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/packages/tangle-cli/src/tangle_cli/python_pipeline/subpipeline.py +18 -2
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/packages/tangle-cli/src/tangle_cli/schemas/dehydrated_pipeline_schema.json +4 -5
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/pyproject.toml +1 -1
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/pyproject.toml.orig +1 -1
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/skills/tangent/OSS-CONVENTIONS.md +1 -1
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/skills/tangent/references/tangle-tools.md +1 -1
- tangle_cli-0.1.9/packages/tangle-cli/src/tangle_cli/args_container.py +0 -244
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/packages/tangle-cli/src/tangle_cli/api_cli.py +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/packages/tangle-cli/src/tangle_cli/api_schema.py +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/packages/tangle-cli/src/tangle_cli/api_transport.py +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/packages/tangle-cli/src/tangle_cli/artifacts.py +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/packages/tangle-cli/src/tangle_cli/artifacts_cli.py +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/packages/tangle-cli/src/tangle_cli/cli.py +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/packages/tangle-cli/src/tangle_cli/cli_helpers.py +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/packages/tangle-cli/src/tangle_cli/cli_options.py +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/packages/tangle-cli/src/tangle_cli/client.py +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/packages/tangle-cli/src/tangle_cli/component_from_func.py +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/packages/tangle-cli/src/tangle_cli/component_generator.py +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/packages/tangle-cli/src/tangle_cli/component_inspector.py +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/packages/tangle-cli/src/tangle_cli/component_publisher.py +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/packages/tangle-cli/src/tangle_cli/components_cli.py +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/packages/tangle-cli/src/tangle_cli/dynamic_discovery_client.py +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/packages/tangle-cli/src/tangle_cli/generated_model_extensions.py +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/packages/tangle-cli/src/tangle_cli/handler.py +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/packages/tangle-cli/src/tangle_cli/hydration_trust.py +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/packages/tangle-cli/src/tangle_cli/logger.py +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/packages/tangle-cli/src/tangle_cli/models.py +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/packages/tangle-cli/src/tangle_cli/module_bundler.py +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/packages/tangle-cli/src/tangle_cli/openapi/__init__.py +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/packages/tangle-cli/src/tangle_cli/openapi/parser.py +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/packages/tangle-cli/src/tangle_cli/pipeline_compiler.py +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/packages/tangle-cli/src/tangle_cli/pipeline_dehydrator.py +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/packages/tangle-cli/src/tangle_cli/pipeline_hydrator.py +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/packages/tangle-cli/src/tangle_cli/pipeline_run_annotations.py +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/packages/tangle-cli/src/tangle_cli/pipeline_run_details.py +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/packages/tangle-cli/src/tangle_cli/pipeline_run_manager.py +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/packages/tangle-cli/src/tangle_cli/pipeline_run_search.py +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/packages/tangle-cli/src/tangle_cli/pipeline_runner.py +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/packages/tangle-cli/src/tangle_cli/pipeline_runs_cli.py +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/packages/tangle-cli/src/tangle_cli/pipeline_spec_utils.py +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/packages/tangle-cli/src/tangle_cli/pipeline_validation.py +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/packages/tangle-cli/src/tangle_cli/pipelines.py +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/packages/tangle-cli/src/tangle_cli/pipelines_cli.py +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/packages/tangle-cli/src/tangle_cli/published_components_cli.py +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/packages/tangle-cli/src/tangle_cli/py.typed +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/packages/tangle-cli/src/tangle_cli/python_pipeline/__init__.py +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/packages/tangle-cli/src/tangle_cli/python_pipeline/cfg.py +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/packages/tangle-cli/src/tangle_cli/python_pipeline/compiler_context.py +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/packages/tangle-cli/src/tangle_cli/python_pipeline/dynamic_data.py +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/packages/tangle-cli/src/tangle_cli/python_pipeline/errors.py +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/packages/tangle-cli/src/tangle_cli/python_pipeline/ids.py +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/packages/tangle-cli/src/tangle_cli/python_pipeline/pipeline.py +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/packages/tangle-cli/src/tangle_cli/python_pipeline/placeholders.py +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/packages/tangle-cli/src/tangle_cli/python_pipeline/raw.py +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/packages/tangle-cli/src/tangle_cli/python_pipeline/registered.py +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/packages/tangle-cli/src/tangle_cli/python_pipeline/task.py +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/packages/tangle-cli/src/tangle_cli/python_pipeline/task_env.py +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/packages/tangle-cli/src/tangle_cli/python_pipeline/trace.py +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/packages/tangle-cli/src/tangle_cli/python_pipeline/types.py +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/packages/tangle-cli/src/tangle_cli/quickstart.py +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/packages/tangle-cli/src/tangle_cli/schema_validation.py +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/packages/tangle-cli/src/tangle_cli/schemas/__init__.py +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/packages/tangle-cli/src/tangle_cli/schemas/pipeline_schema.json +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/packages/tangle-cli/src/tangle_cli/secrets.py +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/packages/tangle-cli/src/tangle_cli/secrets_cli.py +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/packages/tangle-cli/src/tangle_cli/utils.py +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/packages/tangle-cli/src/tangle_cli/version_manager.py +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/skills/tangent/PORT-README.md +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/skills/tangent/SKILL.md +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/skills/tangent/agents/auth-wizard.md +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/skills/tangent/agents/builder.md +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/skills/tangent/agents/debugger.md +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/skills/tangent/agents/reporter.md +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/skills/tangent/agents/researcher.md +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/skills/tangent/agents/reviewer.md +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/skills/tangent/agents/scenario-builder.md +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/skills/tangent/references/data-sources.md +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/skills/tangent/references/event-log.md +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/skills/tangent/references/example-scenarios/01-mslr-ranking.md +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/skills/tangent/references/example-scenarios/02-text-classification.md +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/skills/tangent/references/example-scenarios/INDEX.md +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/skills/tangent/references/iterating-on-runs.md +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/skills/tangent/references/knowledge-corpus.md +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/skills/tangent/references/secrets.md +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/skills/tangent/references/setup.md +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/skills/tangent/references/step-0-initialize.md +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/skills/tangent/references/step-1-analyze.md +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/skills/tangent/references/step-2-hypothesize.md +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/skills/tangent/references/step-3-submit.md +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/skills/tangent/references/step-4-monitor.md +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/skills/tangent/references/step-5-evaluate.md +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/skills/tangent/references/step-6-synthesize.md +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/skills/tangent/references/step-7-decide.md +0 -0
- {tangle_cli-0.1.9 → tangle_cli-0.1.11}/skills/tangent/references/uploading-artifacts.md +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: tangle-cli
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.11
|
|
4
4
|
Summary: CLI for Tangle, the open-source ML pipeline orchestration platform
|
|
5
5
|
Author: Alexey Volkov, Tangle authors, Volv Grebennikov
|
|
6
6
|
Author-email: Alexey Volkov <alexey.volkov@ark-kun.com>, Volv Grebennikov <volv.grebennikov@shopify.com>
|
|
@@ -83,7 +83,7 @@ API-backed commands commonly accept these options. Explicit CLI options win over
|
|
|
83
83
|
| `--token`, `TANGLE_API_TOKEN` | Bearer token shorthand. |
|
|
84
84
|
| `--auth-header`, `TANGLE_API_AUTH_HEADER`, `TANGLE_AUTH_HEADER` | Full `Authorization` value such as `Bearer ...` or `Basic ...`. |
|
|
85
85
|
| `-H`, `--header`, `TANGLE_API_HEADERS` | Extra headers. Repeatable as CLI flags; env accepts a JSON object or newline-separated `Name: value` entries. |
|
|
86
|
-
| `--config` | YAML/JSON defaults. Many commands accept a single object, a list of objects, or `_defaults` + `configs
|
|
86
|
+
| `--config` | YAML/JSON defaults. Many commands accept a single object, a list of objects, or `_defaults` + `configs`, optionally wrapped in a top-level `_select` environment selector. |
|
|
87
87
|
| `--log-type` | SDK progress logs: `console`, `none`, or `file`. Logs go to stderr or a temp log file so structured stdout stays parseable. |
|
|
88
88
|
| `TANGLE_VERBOSE=1` | Redacted HTTP request/response diagnostics only. This is separate from normal progress logging. |
|
|
89
89
|
| `--ca-bundle` | Global CLI flag: path to a PEM CA bundle used as the TLS trust store for every transport. Overrides `TANGLE_API_CA_BUNDLE`. Place before the subcommand. |
|
|
@@ -256,6 +256,56 @@ uv run tangle sdk pipeline-runs submit --config submit.yaml
|
|
|
256
256
|
|
|
257
257
|
For generated `tangle api` commands, config keys use generated CLI parameter names such as `base_url`, `schema_source`, `body`, and endpoint parameters like `limit`, `filter`, or `id`.
|
|
258
258
|
|
|
259
|
+
### Environment-selected configs (`_select`)
|
|
260
|
+
|
|
261
|
+
Any command that accepts `--config` can pick one of several config documents from an environment variable by making `_select` the top-level node:
|
|
262
|
+
|
|
263
|
+
```yaml
|
|
264
|
+
_shared: &shared
|
|
265
|
+
log_type: none
|
|
266
|
+
|
|
267
|
+
_select:
|
|
268
|
+
env: TANGLE_ENV
|
|
269
|
+
cases:
|
|
270
|
+
dev:
|
|
271
|
+
<<: *shared
|
|
272
|
+
base_url: https://api.dev
|
|
273
|
+
prod:
|
|
274
|
+
_defaults:
|
|
275
|
+
<<: *shared
|
|
276
|
+
base_url: https://api.prod
|
|
277
|
+
configs:
|
|
278
|
+
- filter: active
|
|
279
|
+
- filter: finished
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
The selected branch is a complete config document — a single object, a list of objects, or `_defaults` + `configs` — and is then loaded exactly as if it had been written on its own. A branch may itself be another `_select` node, which composes multiple dimensions (for example environment and region).
|
|
283
|
+
|
|
284
|
+
Selection fails closed by default. To opt into a fallback, author an explicit `default` branch:
|
|
285
|
+
|
|
286
|
+
```yaml
|
|
287
|
+
_select:
|
|
288
|
+
env: TANGLE_ENV
|
|
289
|
+
cases:
|
|
290
|
+
prod:
|
|
291
|
+
base_url: https://api.prod
|
|
292
|
+
default:
|
|
293
|
+
base_url: https://api.dev
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
With `default`, an unset variable or a value matching no case resolves to that branch; an exact case match always wins over it. Without `default`, both remain errors. `default` is a sibling of `cases`, not an entry inside it: a case *named* `default` stays an ordinary exact-match case. Like any branch, `default` must be a complete valid config shape and may itself be another `_select`; an inner selector does not inherit the outer `default`.
|
|
297
|
+
|
|
298
|
+
Rules:
|
|
299
|
+
|
|
300
|
+
- `_select` is the only newly reserved key, and it is an exact key name rather than a prefix. Configs without `_select` are unchanged byte-for-byte and semantically.
|
|
301
|
+
- At a `_select` node, only `_select` and other underscore-prefixed helper keys (YAML anchor holders such as `_shared`) may appear; ordinary sibling keys are rejected.
|
|
302
|
+
- `_select` accepts only `env`, `cases`, and the optional `default`. There are no aliases: `else`, `fallback`, and `defaults` are rejected.
|
|
303
|
+
- The selector shape, the `env` name, every `cases` key, and every case and `default` branch are validated before the environment is read, so a malformed selector fails identically in every environment. Branches are checked as complete config documents with the same rules the loader applies to a whole file, and nested selectors are validated recursively.
|
|
304
|
+
- Only environment *lookups* are lazy. A dormant branch is fully shape-checked, but its `env` variable is never required unless that branch is actually selected. Command-specific field names and types are still validated later, against the selected branch only.
|
|
305
|
+
- Selector nesting is capped at 32 levels, which also stops a self-referential YAML alias. A node shared by several anchors is validated once, so anchor-heavy files stay fast.
|
|
306
|
+
- Matching uses `os.environ[NAME]` exactly: case sensitive, with no trimming, case folding, or interpolation.
|
|
307
|
+
- Fallback exists only where it is authored. Without `default`, an unset variable or an unmatched value is an error; there is never an implicit default or implicit production branch. The raw environment value is never echoed — diagnostics list only the configured case names.
|
|
308
|
+
|
|
259
309
|
## API schema cache and dynamic commands
|
|
260
310
|
|
|
261
311
|
Refresh the local schema cache for a live backend with:
|
|
@@ -331,7 +381,7 @@ uv run tangle sdk published-components deprecate sha256:old --superseded-by sha2
|
|
|
331
381
|
|
|
332
382
|
`publish` accepts `--image`, `--name`, `--description`, `--annotations` (JSON), `--dry-run`, `--published-by`, generic git metadata fields, generic API auth fields, `--log-type`, and `--config`. By default it scopes version checks and automatic old-version deprecation to the current authenticated user via `users_me()`; use `--published-by` to supply an explicit owner/publisher filter. Publishing fails closed if no owner can be determined.
|
|
333
383
|
|
|
334
|
-
There is no separate OSS `publish-all` command. To publish multiple components, pass a YAML/JSON config list, or `_defaults` + `configs`, to the same `published-components publish` command; the command aggregates results and exits nonzero if any component errors.
|
|
384
|
+
There is no separate OSS `publish-all` command. To publish multiple components, pass a YAML/JSON config list, or `_defaults` + `configs`, to the same `published-components publish` command; the command aggregates results and exits nonzero if any component errors. A top-level `_select` node can choose between such documents per environment (see [Environment-selected configs](#environment-selected-configs-_select)).
|
|
335
385
|
|
|
336
386
|
```yaml
|
|
337
387
|
_defaults:
|
|
@@ -439,6 +489,56 @@ def collision(runtime_condition: In[str]) -> Out[str]:
|
|
|
439
489
|
|
|
440
490
|
The bound value remains under `arguments.is_enabled`; the call-site value emits as `isEnabled`. Tangle does not evaluate conditions on graph-component tasks, so `subpipeline(...)(is_enabled=...)` is rejected with guidance to condition tasks inside the child pipeline. A child graph input with that name remains available through `subpipeline(...).bind(is_enabled=...)(...)`. There is no `condition` alias.
|
|
441
491
|
|
|
492
|
+
##### Task execution options and caching
|
|
493
|
+
|
|
494
|
+
Tangle caches task results, so a task that reads state which changes between runs (a run's `createdBy`, wall-clock time, an external table that the graph does not depend on) must opt out of caching explicitly. Use the reserved task-call metadata keyword `max_cache_staleness=`:
|
|
495
|
+
|
|
496
|
+
```python
|
|
497
|
+
@pipeline("Scheduled-run gate")
|
|
498
|
+
def scheduled_gate() -> Out[str]:
|
|
499
|
+
is_scheduled = read_runtime_state(
|
|
500
|
+
name="CLOUD_PIPELINES_PIPELINE_RUN_CREATED_BY",
|
|
501
|
+
max_cache_staleness="P0D",
|
|
502
|
+
)
|
|
503
|
+
return is_scheduled.Output
|
|
504
|
+
```
|
|
505
|
+
|
|
506
|
+
This emits the canonical task field rather than a component argument:
|
|
507
|
+
|
|
508
|
+
```yaml
|
|
509
|
+
executionOptions:
|
|
510
|
+
cachingStrategy:
|
|
511
|
+
maxCacheStaleness: P0D
|
|
512
|
+
```
|
|
513
|
+
|
|
514
|
+
`P0D` means "never reuse a cached result"; any other ISO-8601 duration (`P7D`) caps how stale a reusable result may be. For the rest of `ExecutionOptionsSpec`, use the general `execution_options=` passthrough:
|
|
515
|
+
|
|
516
|
+
```python
|
|
517
|
+
uploaded = flaky_upload(
|
|
518
|
+
payload=data.Output,
|
|
519
|
+
execution_options={"retryStrategy": {"maxRetries": 3}},
|
|
520
|
+
)
|
|
521
|
+
```
|
|
522
|
+
|
|
523
|
+
Both keywords may be combined; `max_cache_staleness=` wins over a `cachingStrategy.maxCacheStaleness` supplied through `execution_options=`, and every other passthrough field is preserved. A mapping passed as `execution_options=` is never mutated, so one shared constant can be reused across tasks.
|
|
524
|
+
|
|
525
|
+
Tangle models exactly two execution-option groups today — `cachingStrategy.maxCacheStaleness` and `retryStrategy.maxRetries` (required whenever `retryStrategy` is present). Any other key is rejected at compile time: the backend ignores unmodeled keys silently, so accepting one would advertise a setting that never takes effect.
|
|
526
|
+
|
|
527
|
+
Execution options are STATIC compile-time settings, so `max_cache_staleness` takes an RFC3339 duration string and `retryStrategy.maxRetries` a non-negative integer. Graph inputs, task outputs, `dynamic_secret(...)`, and `raw(...)` values are rejected because the backend does not resolve them for `executionOptions`. Passing an empty `execution_options={}` is an error — omit the keyword instead.
|
|
528
|
+
|
|
529
|
+
If a component itself declares an input named `max_cache_staleness` or `execution_options`, bind that component argument separately while using the call-site keyword for task metadata:
|
|
530
|
+
|
|
531
|
+
```python
|
|
532
|
+
result = work.bind(max_cache_staleness="component-input-value")(
|
|
533
|
+
message="hello",
|
|
534
|
+
max_cache_staleness="P0D",
|
|
535
|
+
)
|
|
536
|
+
```
|
|
537
|
+
|
|
538
|
+
The bound value remains under `arguments.max_cache_staleness`; the call-site value emits as `executionOptions`. Tangle applies caching and retries to container-component tasks, so `subpipeline(...)(max_cache_staleness=...)` and `subpipeline(...)(execution_options=...)` are rejected with guidance to set them on tasks inside the child pipeline. A child graph input with either name remains available through `subpipeline(...).bind(...)`.
|
|
539
|
+
|
|
540
|
+
See `examples/python_pipeline/execution_options_pipeline.py` for a runnable example.
|
|
541
|
+
|
|
442
542
|
##### Task images, dependencies, and image IDs
|
|
443
543
|
|
|
444
544
|
Use `@task(image="...")` to write the component image directly. Use `dependencies_from="pyproject.toml"` when generated components need to install Python dependencies. Several tasks can share one authoring-only `TaskEnv`:
|
|
@@ -57,7 +57,7 @@ API-backed commands commonly accept these options. Explicit CLI options win over
|
|
|
57
57
|
| `--token`, `TANGLE_API_TOKEN` | Bearer token shorthand. |
|
|
58
58
|
| `--auth-header`, `TANGLE_API_AUTH_HEADER`, `TANGLE_AUTH_HEADER` | Full `Authorization` value such as `Bearer ...` or `Basic ...`. |
|
|
59
59
|
| `-H`, `--header`, `TANGLE_API_HEADERS` | Extra headers. Repeatable as CLI flags; env accepts a JSON object or newline-separated `Name: value` entries. |
|
|
60
|
-
| `--config` | YAML/JSON defaults. Many commands accept a single object, a list of objects, or `_defaults` + `configs
|
|
60
|
+
| `--config` | YAML/JSON defaults. Many commands accept a single object, a list of objects, or `_defaults` + `configs`, optionally wrapped in a top-level `_select` environment selector. |
|
|
61
61
|
| `--log-type` | SDK progress logs: `console`, `none`, or `file`. Logs go to stderr or a temp log file so structured stdout stays parseable. |
|
|
62
62
|
| `TANGLE_VERBOSE=1` | Redacted HTTP request/response diagnostics only. This is separate from normal progress logging. |
|
|
63
63
|
| `--ca-bundle` | Global CLI flag: path to a PEM CA bundle used as the TLS trust store for every transport. Overrides `TANGLE_API_CA_BUNDLE`. Place before the subcommand. |
|
|
@@ -230,6 +230,56 @@ uv run tangle sdk pipeline-runs submit --config submit.yaml
|
|
|
230
230
|
|
|
231
231
|
For generated `tangle api` commands, config keys use generated CLI parameter names such as `base_url`, `schema_source`, `body`, and endpoint parameters like `limit`, `filter`, or `id`.
|
|
232
232
|
|
|
233
|
+
### Environment-selected configs (`_select`)
|
|
234
|
+
|
|
235
|
+
Any command that accepts `--config` can pick one of several config documents from an environment variable by making `_select` the top-level node:
|
|
236
|
+
|
|
237
|
+
```yaml
|
|
238
|
+
_shared: &shared
|
|
239
|
+
log_type: none
|
|
240
|
+
|
|
241
|
+
_select:
|
|
242
|
+
env: TANGLE_ENV
|
|
243
|
+
cases:
|
|
244
|
+
dev:
|
|
245
|
+
<<: *shared
|
|
246
|
+
base_url: https://api.dev
|
|
247
|
+
prod:
|
|
248
|
+
_defaults:
|
|
249
|
+
<<: *shared
|
|
250
|
+
base_url: https://api.prod
|
|
251
|
+
configs:
|
|
252
|
+
- filter: active
|
|
253
|
+
- filter: finished
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
The selected branch is a complete config document — a single object, a list of objects, or `_defaults` + `configs` — and is then loaded exactly as if it had been written on its own. A branch may itself be another `_select` node, which composes multiple dimensions (for example environment and region).
|
|
257
|
+
|
|
258
|
+
Selection fails closed by default. To opt into a fallback, author an explicit `default` branch:
|
|
259
|
+
|
|
260
|
+
```yaml
|
|
261
|
+
_select:
|
|
262
|
+
env: TANGLE_ENV
|
|
263
|
+
cases:
|
|
264
|
+
prod:
|
|
265
|
+
base_url: https://api.prod
|
|
266
|
+
default:
|
|
267
|
+
base_url: https://api.dev
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
With `default`, an unset variable or a value matching no case resolves to that branch; an exact case match always wins over it. Without `default`, both remain errors. `default` is a sibling of `cases`, not an entry inside it: a case *named* `default` stays an ordinary exact-match case. Like any branch, `default` must be a complete valid config shape and may itself be another `_select`; an inner selector does not inherit the outer `default`.
|
|
271
|
+
|
|
272
|
+
Rules:
|
|
273
|
+
|
|
274
|
+
- `_select` is the only newly reserved key, and it is an exact key name rather than a prefix. Configs without `_select` are unchanged byte-for-byte and semantically.
|
|
275
|
+
- At a `_select` node, only `_select` and other underscore-prefixed helper keys (YAML anchor holders such as `_shared`) may appear; ordinary sibling keys are rejected.
|
|
276
|
+
- `_select` accepts only `env`, `cases`, and the optional `default`. There are no aliases: `else`, `fallback`, and `defaults` are rejected.
|
|
277
|
+
- The selector shape, the `env` name, every `cases` key, and every case and `default` branch are validated before the environment is read, so a malformed selector fails identically in every environment. Branches are checked as complete config documents with the same rules the loader applies to a whole file, and nested selectors are validated recursively.
|
|
278
|
+
- Only environment *lookups* are lazy. A dormant branch is fully shape-checked, but its `env` variable is never required unless that branch is actually selected. Command-specific field names and types are still validated later, against the selected branch only.
|
|
279
|
+
- Selector nesting is capped at 32 levels, which also stops a self-referential YAML alias. A node shared by several anchors is validated once, so anchor-heavy files stay fast.
|
|
280
|
+
- Matching uses `os.environ[NAME]` exactly: case sensitive, with no trimming, case folding, or interpolation.
|
|
281
|
+
- Fallback exists only where it is authored. Without `default`, an unset variable or an unmatched value is an error; there is never an implicit default or implicit production branch. The raw environment value is never echoed — diagnostics list only the configured case names.
|
|
282
|
+
|
|
233
283
|
## API schema cache and dynamic commands
|
|
234
284
|
|
|
235
285
|
Refresh the local schema cache for a live backend with:
|
|
@@ -305,7 +355,7 @@ uv run tangle sdk published-components deprecate sha256:old --superseded-by sha2
|
|
|
305
355
|
|
|
306
356
|
`publish` accepts `--image`, `--name`, `--description`, `--annotations` (JSON), `--dry-run`, `--published-by`, generic git metadata fields, generic API auth fields, `--log-type`, and `--config`. By default it scopes version checks and automatic old-version deprecation to the current authenticated user via `users_me()`; use `--published-by` to supply an explicit owner/publisher filter. Publishing fails closed if no owner can be determined.
|
|
307
357
|
|
|
308
|
-
There is no separate OSS `publish-all` command. To publish multiple components, pass a YAML/JSON config list, or `_defaults` + `configs`, to the same `published-components publish` command; the command aggregates results and exits nonzero if any component errors.
|
|
358
|
+
There is no separate OSS `publish-all` command. To publish multiple components, pass a YAML/JSON config list, or `_defaults` + `configs`, to the same `published-components publish` command; the command aggregates results and exits nonzero if any component errors. A top-level `_select` node can choose between such documents per environment (see [Environment-selected configs](#environment-selected-configs-_select)).
|
|
309
359
|
|
|
310
360
|
```yaml
|
|
311
361
|
_defaults:
|
|
@@ -413,6 +463,56 @@ def collision(runtime_condition: In[str]) -> Out[str]:
|
|
|
413
463
|
|
|
414
464
|
The bound value remains under `arguments.is_enabled`; the call-site value emits as `isEnabled`. Tangle does not evaluate conditions on graph-component tasks, so `subpipeline(...)(is_enabled=...)` is rejected with guidance to condition tasks inside the child pipeline. A child graph input with that name remains available through `subpipeline(...).bind(is_enabled=...)(...)`. There is no `condition` alias.
|
|
415
465
|
|
|
466
|
+
##### Task execution options and caching
|
|
467
|
+
|
|
468
|
+
Tangle caches task results, so a task that reads state which changes between runs (a run's `createdBy`, wall-clock time, an external table that the graph does not depend on) must opt out of caching explicitly. Use the reserved task-call metadata keyword `max_cache_staleness=`:
|
|
469
|
+
|
|
470
|
+
```python
|
|
471
|
+
@pipeline("Scheduled-run gate")
|
|
472
|
+
def scheduled_gate() -> Out[str]:
|
|
473
|
+
is_scheduled = read_runtime_state(
|
|
474
|
+
name="CLOUD_PIPELINES_PIPELINE_RUN_CREATED_BY",
|
|
475
|
+
max_cache_staleness="P0D",
|
|
476
|
+
)
|
|
477
|
+
return is_scheduled.Output
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
This emits the canonical task field rather than a component argument:
|
|
481
|
+
|
|
482
|
+
```yaml
|
|
483
|
+
executionOptions:
|
|
484
|
+
cachingStrategy:
|
|
485
|
+
maxCacheStaleness: P0D
|
|
486
|
+
```
|
|
487
|
+
|
|
488
|
+
`P0D` means "never reuse a cached result"; any other ISO-8601 duration (`P7D`) caps how stale a reusable result may be. For the rest of `ExecutionOptionsSpec`, use the general `execution_options=` passthrough:
|
|
489
|
+
|
|
490
|
+
```python
|
|
491
|
+
uploaded = flaky_upload(
|
|
492
|
+
payload=data.Output,
|
|
493
|
+
execution_options={"retryStrategy": {"maxRetries": 3}},
|
|
494
|
+
)
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
Both keywords may be combined; `max_cache_staleness=` wins over a `cachingStrategy.maxCacheStaleness` supplied through `execution_options=`, and every other passthrough field is preserved. A mapping passed as `execution_options=` is never mutated, so one shared constant can be reused across tasks.
|
|
498
|
+
|
|
499
|
+
Tangle models exactly two execution-option groups today — `cachingStrategy.maxCacheStaleness` and `retryStrategy.maxRetries` (required whenever `retryStrategy` is present). Any other key is rejected at compile time: the backend ignores unmodeled keys silently, so accepting one would advertise a setting that never takes effect.
|
|
500
|
+
|
|
501
|
+
Execution options are STATIC compile-time settings, so `max_cache_staleness` takes an RFC3339 duration string and `retryStrategy.maxRetries` a non-negative integer. Graph inputs, task outputs, `dynamic_secret(...)`, and `raw(...)` values are rejected because the backend does not resolve them for `executionOptions`. Passing an empty `execution_options={}` is an error — omit the keyword instead.
|
|
502
|
+
|
|
503
|
+
If a component itself declares an input named `max_cache_staleness` or `execution_options`, bind that component argument separately while using the call-site keyword for task metadata:
|
|
504
|
+
|
|
505
|
+
```python
|
|
506
|
+
result = work.bind(max_cache_staleness="component-input-value")(
|
|
507
|
+
message="hello",
|
|
508
|
+
max_cache_staleness="P0D",
|
|
509
|
+
)
|
|
510
|
+
```
|
|
511
|
+
|
|
512
|
+
The bound value remains under `arguments.max_cache_staleness`; the call-site value emits as `executionOptions`. Tangle applies caching and retries to container-component tasks, so `subpipeline(...)(max_cache_staleness=...)` and `subpipeline(...)(execution_options=...)` are rejected with guidance to set them on tasks inside the child pipeline. A child graph input with either name remains available through `subpipeline(...).bind(...)`.
|
|
513
|
+
|
|
514
|
+
See `examples/python_pipeline/execution_options_pipeline.py` for a runnable example.
|
|
515
|
+
|
|
416
516
|
##### Task images, dependencies, and image IDs
|
|
417
517
|
|
|
418
518
|
Use `@task(image="...")` to write the component image directly. Use `dependencies_from="pyproject.toml"` when generated components need to install Python dependencies. Several tasks can share one authoring-only `TaskEnv`:
|
|
@@ -14,6 +14,6 @@ from tangle_cli.dynamic_discovery_client import TangleDynamicDiscoveryClient
|
|
|
14
14
|
try:
|
|
15
15
|
__version__ = metadata_version("tangle-cli")
|
|
16
16
|
except PackageNotFoundError:
|
|
17
|
-
__version__ = "0.1.
|
|
17
|
+
__version__ = "0.1.11"
|
|
18
18
|
|
|
19
19
|
__all__ = ["TangleDynamicDiscoveryClient", "__version__"]
|