adagio-cli 0.1.0a1__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.
- adagio_cli-0.1.0a1/LICENSE +21 -0
- adagio_cli-0.1.0a1/PKG-INFO +310 -0
- adagio_cli-0.1.0a1/README.md +278 -0
- adagio_cli-0.1.0a1/pyproject.toml +83 -0
- adagio_cli-0.1.0a1/src/adagio/__init__.py +15 -0
- adagio_cli-0.1.0a1/src/adagio/app/parsers/pipeline.py +89 -0
- adagio_cli-0.1.0a1/src/adagio/check.py +16 -0
- adagio_cli-0.1.0a1/src/adagio/cli/__init__.py +1 -0
- adagio_cli-0.1.0a1/src/adagio/cli/args.py +62 -0
- adagio_cli-0.1.0a1/src/adagio/cli/cache.py +82 -0
- adagio_cli-0.1.0a1/src/adagio/cli/config.py +39 -0
- adagio_cli-0.1.0a1/src/adagio/cli/dynamic.py +618 -0
- adagio_cli-0.1.0a1/src/adagio/cli/main.py +263 -0
- adagio_cli-0.1.0a1/src/adagio/cli/pipeline.py +27 -0
- adagio_cli-0.1.0a1/src/adagio/cli/qapi.py +172 -0
- adagio_cli-0.1.0a1/src/adagio/cli/runner.py +285 -0
- adagio_cli-0.1.0a1/src/adagio/cli/runtime.py +388 -0
- adagio_cli-0.1.0a1/src/adagio/cli/task_exec.py +289 -0
- adagio_cli-0.1.0a1/src/adagio/convert.py +0 -0
- adagio_cli-0.1.0a1/src/adagio/describe.py +366 -0
- adagio_cli-0.1.0a1/src/adagio/execute.py +65 -0
- adagio_cli-0.1.0a1/src/adagio/execution/context.py +102 -0
- adagio_cli-0.1.0a1/src/adagio/execution/proxy.py +243 -0
- adagio_cli-0.1.0a1/src/adagio/executors/__init__.py +29 -0
- adagio_cli-0.1.0a1/src/adagio/executors/apptainer.py +214 -0
- adagio_cli-0.1.0a1/src/adagio/executors/base.py +78 -0
- adagio_cli-0.1.0a1/src/adagio/executors/cache_support.py +55 -0
- adagio_cli-0.1.0a1/src/adagio/executors/common.py +55 -0
- adagio_cli-0.1.0a1/src/adagio/executors/container_support.py +169 -0
- adagio_cli-0.1.0a1/src/adagio/executors/defaults.py +115 -0
- adagio_cli-0.1.0a1/src/adagio/executors/docker.py +184 -0
- adagio_cli-0.1.0a1/src/adagio/executors/path_utils.py +47 -0
- adagio_cli-0.1.0a1/src/adagio/executors/serial_runner.py +135 -0
- adagio_cli-0.1.0a1/src/adagio/executors/task_contract.py +88 -0
- adagio_cli-0.1.0a1/src/adagio/executors/task_environments.py +225 -0
- adagio_cli-0.1.0a1/src/adagio/io.py +41 -0
- adagio_cli-0.1.0a1/src/adagio/model/__init__.py +0 -0
- adagio_cli-0.1.0a1/src/adagio/model/arguments.py +39 -0
- adagio_cli-0.1.0a1/src/adagio/model/ast.py +55 -0
- adagio_cli-0.1.0a1/src/adagio/model/pipeline.py +134 -0
- adagio_cli-0.1.0a1/src/adagio/model/task.py +135 -0
- adagio_cli-0.1.0a1/src/adagio/monitor/__init__.py +0 -0
- adagio_cli-0.1.0a1/src/adagio/monitor/api.py +60 -0
- adagio_cli-0.1.0a1/src/adagio/monitor/base.py +0 -0
- adagio_cli-0.1.0a1/src/adagio/monitor/composite.py +74 -0
- adagio_cli-0.1.0a1/src/adagio/monitor/connected.py +106 -0
- adagio_cli-0.1.0a1/src/adagio/monitor/log.py +72 -0
- adagio_cli-0.1.0a1/src/adagio/monitor/tty.py +293 -0
- adagio_cli-0.1.0a1/src/adagio/protocol/__init__.py +0 -0
- adagio_cli-0.1.0a1/src/adagio/protocol/base.py +0 -0
- adagio_cli-0.1.0a1/src/adagio/protocol/file.py +0 -0
- adagio_cli-0.1.0a1/src/adagio/protocol/http.py +0 -0
- adagio_cli-0.1.0a1/src/adagio/protocol/s3.py +0 -0
- adagio_cli-0.1.0a1/src/adagio/qapi/__init__.py +8 -0
- adagio_cli-0.1.0a1/src/adagio/qapi/build.py +158 -0
- adagio_cli-0.1.0a1/src/adagio/qapi/client.py +56 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Cymis
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: adagio-cli
|
|
3
|
+
Version: 0.1.0a1
|
|
4
|
+
Summary: Command-line runner for Adagio pipeline files.
|
|
5
|
+
Keywords: adagio,bioinformatics,cli,pipelines,qiime2,workflow
|
|
6
|
+
Author: Cymis
|
|
7
|
+
License-Expression: MIT
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Classifier: Development Status :: 3 - Alpha
|
|
10
|
+
Classifier: Environment :: Console
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: Intended Audience :: Science/Research
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
|
|
20
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
21
|
+
Requires-Dist: cyclopts>=4.5.3
|
|
22
|
+
Requires-Dist: pydantic>=2.12.5
|
|
23
|
+
Requires-Dist: rich>=14.1.0
|
|
24
|
+
Requires-Dist: parsl>=2024.12.16
|
|
25
|
+
Requires-Dist: tomli>=2.2.1 ; python_full_version < '3.11'
|
|
26
|
+
Requires-Python: >=3.10
|
|
27
|
+
Project-URL: Changelog, https://github.com/cymis/adagio-cli/blob/dev/CHANGELOG.md
|
|
28
|
+
Project-URL: Homepage, https://github.com/cymis/adagio-cli
|
|
29
|
+
Project-URL: Issues, https://github.com/cymis/adagio-cli/issues
|
|
30
|
+
Project-URL: Repository, https://github.com/cymis/adagio-cli
|
|
31
|
+
Description-Content-Type: text/markdown
|
|
32
|
+
|
|
33
|
+
# Adagio CLI
|
|
34
|
+
|
|
35
|
+
Command-line runner for Adagio pipeline files
|
|
36
|
+
|
|
37
|
+
## Requirements
|
|
38
|
+
|
|
39
|
+
- Python 3.10+
|
|
40
|
+
- `uv` (recommended for development)
|
|
41
|
+
- Docker for the default task runtime
|
|
42
|
+
- Apptainer or Singularity when using `kind = "apptainer"` with local `.sif` images
|
|
43
|
+
|
|
44
|
+
## Installation
|
|
45
|
+
|
|
46
|
+
Install from PyPI:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
pip install adagio-cli
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Install a prerelease from TestPyPI while validating a release candidate:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
pip install \
|
|
56
|
+
--index-url https://test.pypi.org/simple/ \
|
|
57
|
+
--extra-index-url https://pypi.org/simple \
|
|
58
|
+
adagio-cli
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Install from the current checkout:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
pip install .
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Or with `uv`:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
uv pip install .
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Verify install:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
adagio --version
|
|
77
|
+
adagio --help
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Usage
|
|
81
|
+
|
|
82
|
+
### Run a pipeline
|
|
83
|
+
|
|
84
|
+
Show command help:
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
adagio run --help
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Run with a pipeline file:
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
adagio run --pipeline path/to/pipeline.json --cache-dir /path/to/cache
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
`adagio run` executes each plugin task in its own task environment.
|
|
97
|
+
The default task environment is a Docker image in GHCR derived from the plugin
|
|
98
|
+
name in the pipeline spec, for example `dada2` -> `ghcr.io/cymis/qiime2-plugin-dada2:2026.1`.
|
|
99
|
+
Runtime config can override that per default/plugin/task and switch selected work to
|
|
100
|
+
Apptainer/Singularity with a local `.sif` image path. The cache directory is required
|
|
101
|
+
and is reused across reruns by default so unchanged successful tasks can be replayed.
|
|
102
|
+
|
|
103
|
+
Equivalent positional form:
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
adagio run path/to/pipeline.json --cache-dir /path/to/cache
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Use an arguments file:
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
adagio run --pipeline path/to/pipeline.json --cache-dir /path/to/cache --arguments path/to/arguments.json
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Use a runtime config file with defaults, plugin-level overrides, and optional task overrides:
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
adagio run --pipeline path/to/pipeline.json --cache-dir /path/to/cache --config path/to/runtime.toml
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
Control which dynamic flags are shown in help:
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
adagio run --pipeline path/to/pipeline.json --cache-dir /path/to/cache --show-params required
|
|
125
|
+
# choices: all | missing | required
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Disable reuse for a run while still writing outputs into the selected cache directory:
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
adagio run --pipeline path/to/pipeline.json --cache-dir /path/to/cache --no-reuse
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
The same boolean pair is available as `--reuse` / `--no-reuse`. `--reuse` is the default.
|
|
135
|
+
|
|
136
|
+
Clear an existing cache directory:
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
adagio cache clear --cache-dir /path/to/cache
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Inspect a pipeline
|
|
143
|
+
|
|
144
|
+
Print a dependency-ordered summary of the plugin actions in a pipeline:
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
adagio pipeline show path/to/pipeline.json
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### Arguments file format
|
|
151
|
+
|
|
152
|
+
`--arguments` can be downloaded from Adagio directly in the "Run" workflow :
|
|
153
|
+
|
|
154
|
+
```json
|
|
155
|
+
{
|
|
156
|
+
"version": 1,
|
|
157
|
+
"inputs": {
|
|
158
|
+
"input_name": "/path/to/input.qza"
|
|
159
|
+
},
|
|
160
|
+
"parameters": {
|
|
161
|
+
"param_name": "value"
|
|
162
|
+
},
|
|
163
|
+
"outputs": "/path/to/output-dir"
|
|
164
|
+
}
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
`outputs` may also be a map keyed by output name (WIP: not currently generated by Adagio):
|
|
168
|
+
|
|
169
|
+
```json
|
|
170
|
+
{
|
|
171
|
+
"outputs": {
|
|
172
|
+
"output_a": "/path/to/output-a",
|
|
173
|
+
"output_b": "/path/to/output-b"
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
If outputs are omitted, defaults are generated under `./adagio-outputs`.
|
|
179
|
+
|
|
180
|
+
### Runtime config format
|
|
181
|
+
|
|
182
|
+
`--config` accepts TOML. Defaults apply first, then plugin keys, then task keys:
|
|
183
|
+
|
|
184
|
+
```toml
|
|
185
|
+
version = 1
|
|
186
|
+
|
|
187
|
+
[defaults]
|
|
188
|
+
platform = "linux/amd64"
|
|
189
|
+
|
|
190
|
+
[plugins]
|
|
191
|
+
dada2 = { image = "ghcr.io/cymis/qiime2-plugin-dada2:2026.1" }
|
|
192
|
+
demux = { image = "ghcr.io/cymis/qiime2-plugin-demux:2026.1" }
|
|
193
|
+
|
|
194
|
+
[tasks]
|
|
195
|
+
"dada2.denoise_single" = { image = "registry.internal/custom-dada2:1.0", platform = "linux/amd64" }
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
`kind`, `image`, and `platform` are all optional on defaults, plugin entries, and task entries.
|
|
199
|
+
`kind` may be `docker` or `apptainer`. `image` remains the environment reference:
|
|
200
|
+
for Docker it is the container image, and for Apptainer it must be a local `.sif` path.
|
|
201
|
+
|
|
202
|
+
Precedence is `task override > plugin override > defaults > default resolver`.
|
|
203
|
+
|
|
204
|
+
Task lookup supports graph node `id`, optional task `name` when present in the
|
|
205
|
+
pipeline, and `plugin.action` as a fallback. Plugin lookup uses the pipeline's
|
|
206
|
+
plugin name. If `platform` is omitted all the way through, Adagio uses normal
|
|
207
|
+
Docker platform resolution with no implicit fallback. Anything not listed in the
|
|
208
|
+
config uses the default plugin image resolver.
|
|
209
|
+
|
|
210
|
+
Concrete Apptainer example:
|
|
211
|
+
|
|
212
|
+
```toml
|
|
213
|
+
version = 1
|
|
214
|
+
|
|
215
|
+
[defaults]
|
|
216
|
+
kind = "docker"
|
|
217
|
+
|
|
218
|
+
[plugins]
|
|
219
|
+
bowtie2 = { kind = "apptainer", image = "/shared/qiime-images/q2-bowtie2-test.sif" }
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
For `kind = "apptainer"`, Adagio prefers the `apptainer` executable and falls back to
|
|
223
|
+
`singularity`. The current implementation supports only local `.sif` paths and runs
|
|
224
|
+
tasks serially; no scheduler submission or remote image pull behavior is included.
|
|
225
|
+
|
|
226
|
+
### QAPI generation/submission
|
|
227
|
+
|
|
228
|
+
Generate and submit plugin metadata from the active QIIME environment:
|
|
229
|
+
|
|
230
|
+
```bash
|
|
231
|
+
adagio qapi build --action-url http://localhost:81/api/v1
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
Submit to a protected deployment such as `adagio.run` with a scoped submission token:
|
|
235
|
+
|
|
236
|
+
```bash
|
|
237
|
+
export ACTION_URL=https://adagio.run/api/v1
|
|
238
|
+
export QAPI_SUBMISSION_TOKEN=<token copied from https://adagio.run/app/profile>
|
|
239
|
+
uv run adagio qapi build
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
You can also pass `--submission-token`, but the environment variable is safer because it does
|
|
243
|
+
not end up in shell history.
|
|
244
|
+
|
|
245
|
+
Write payload to disk without submitting:
|
|
246
|
+
|
|
247
|
+
```bash
|
|
248
|
+
adagio qapi build --output qapi.json --dry-run
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
Submit selected plugins only:
|
|
252
|
+
|
|
253
|
+
```bash
|
|
254
|
+
adagio qapi build --plugin dada2 --plugin feature-table
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
## Development
|
|
258
|
+
|
|
259
|
+
### Setup
|
|
260
|
+
|
|
261
|
+
Install runtime and dev dependencies:
|
|
262
|
+
|
|
263
|
+
```bash
|
|
264
|
+
uv sync --group dev
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
Run commands inside the project environment:
|
|
268
|
+
|
|
269
|
+
```bash
|
|
270
|
+
uv run adagio --help
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
### Linting
|
|
274
|
+
|
|
275
|
+
```bash
|
|
276
|
+
uv run ruff check .
|
|
277
|
+
uv run ruff format --check .
|
|
278
|
+
uv run ruff format .
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
### Tests
|
|
282
|
+
|
|
283
|
+
```bash
|
|
284
|
+
uv run pytest
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
### Build distributions
|
|
288
|
+
|
|
289
|
+
```bash
|
|
290
|
+
uv run python -m build
|
|
291
|
+
uv run python -m twine check dist/*
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
### Running locally during development
|
|
295
|
+
|
|
296
|
+
```bash
|
|
297
|
+
uv run adagio run --pipeline path/to/pipeline.json --cache-dir /path/to/cache
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
### Runtime entrypoint (container/integration use)
|
|
301
|
+
|
|
302
|
+
The `runtime` subcommand is intended for runtime-adapter jobs:
|
|
303
|
+
|
|
304
|
+
```bash
|
|
305
|
+
uv run adagio runtime --spec spec.json --config runtime.toml --arguments arguments.json --cache-dir /path/to/cache
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
### Releasing
|
|
309
|
+
|
|
310
|
+
See [RELEASING.md](RELEASING.md) for the one-time PyPI/GitHub setup, version/tag workflow, and TestPyPI/PyPI publishing steps.
|
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
# Adagio CLI
|
|
2
|
+
|
|
3
|
+
Command-line runner for Adagio pipeline files
|
|
4
|
+
|
|
5
|
+
## Requirements
|
|
6
|
+
|
|
7
|
+
- Python 3.10+
|
|
8
|
+
- `uv` (recommended for development)
|
|
9
|
+
- Docker for the default task runtime
|
|
10
|
+
- Apptainer or Singularity when using `kind = "apptainer"` with local `.sif` images
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
Install from PyPI:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
pip install adagio-cli
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Install a prerelease from TestPyPI while validating a release candidate:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
pip install \
|
|
24
|
+
--index-url https://test.pypi.org/simple/ \
|
|
25
|
+
--extra-index-url https://pypi.org/simple \
|
|
26
|
+
adagio-cli
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Install from the current checkout:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
pip install .
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Or with `uv`:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
uv pip install .
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Verify install:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
adagio --version
|
|
45
|
+
adagio --help
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Usage
|
|
49
|
+
|
|
50
|
+
### Run a pipeline
|
|
51
|
+
|
|
52
|
+
Show command help:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
adagio run --help
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Run with a pipeline file:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
adagio run --pipeline path/to/pipeline.json --cache-dir /path/to/cache
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
`adagio run` executes each plugin task in its own task environment.
|
|
65
|
+
The default task environment is a Docker image in GHCR derived from the plugin
|
|
66
|
+
name in the pipeline spec, for example `dada2` -> `ghcr.io/cymis/qiime2-plugin-dada2:2026.1`.
|
|
67
|
+
Runtime config can override that per default/plugin/task and switch selected work to
|
|
68
|
+
Apptainer/Singularity with a local `.sif` image path. The cache directory is required
|
|
69
|
+
and is reused across reruns by default so unchanged successful tasks can be replayed.
|
|
70
|
+
|
|
71
|
+
Equivalent positional form:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
adagio run path/to/pipeline.json --cache-dir /path/to/cache
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Use an arguments file:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
adagio run --pipeline path/to/pipeline.json --cache-dir /path/to/cache --arguments path/to/arguments.json
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Use a runtime config file with defaults, plugin-level overrides, and optional task overrides:
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
adagio run --pipeline path/to/pipeline.json --cache-dir /path/to/cache --config path/to/runtime.toml
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Control which dynamic flags are shown in help:
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
adagio run --pipeline path/to/pipeline.json --cache-dir /path/to/cache --show-params required
|
|
93
|
+
# choices: all | missing | required
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Disable reuse for a run while still writing outputs into the selected cache directory:
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
adagio run --pipeline path/to/pipeline.json --cache-dir /path/to/cache --no-reuse
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
The same boolean pair is available as `--reuse` / `--no-reuse`. `--reuse` is the default.
|
|
103
|
+
|
|
104
|
+
Clear an existing cache directory:
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
adagio cache clear --cache-dir /path/to/cache
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Inspect a pipeline
|
|
111
|
+
|
|
112
|
+
Print a dependency-ordered summary of the plugin actions in a pipeline:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
adagio pipeline show path/to/pipeline.json
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Arguments file format
|
|
119
|
+
|
|
120
|
+
`--arguments` can be downloaded from Adagio directly in the "Run" workflow :
|
|
121
|
+
|
|
122
|
+
```json
|
|
123
|
+
{
|
|
124
|
+
"version": 1,
|
|
125
|
+
"inputs": {
|
|
126
|
+
"input_name": "/path/to/input.qza"
|
|
127
|
+
},
|
|
128
|
+
"parameters": {
|
|
129
|
+
"param_name": "value"
|
|
130
|
+
},
|
|
131
|
+
"outputs": "/path/to/output-dir"
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
`outputs` may also be a map keyed by output name (WIP: not currently generated by Adagio):
|
|
136
|
+
|
|
137
|
+
```json
|
|
138
|
+
{
|
|
139
|
+
"outputs": {
|
|
140
|
+
"output_a": "/path/to/output-a",
|
|
141
|
+
"output_b": "/path/to/output-b"
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
If outputs are omitted, defaults are generated under `./adagio-outputs`.
|
|
147
|
+
|
|
148
|
+
### Runtime config format
|
|
149
|
+
|
|
150
|
+
`--config` accepts TOML. Defaults apply first, then plugin keys, then task keys:
|
|
151
|
+
|
|
152
|
+
```toml
|
|
153
|
+
version = 1
|
|
154
|
+
|
|
155
|
+
[defaults]
|
|
156
|
+
platform = "linux/amd64"
|
|
157
|
+
|
|
158
|
+
[plugins]
|
|
159
|
+
dada2 = { image = "ghcr.io/cymis/qiime2-plugin-dada2:2026.1" }
|
|
160
|
+
demux = { image = "ghcr.io/cymis/qiime2-plugin-demux:2026.1" }
|
|
161
|
+
|
|
162
|
+
[tasks]
|
|
163
|
+
"dada2.denoise_single" = { image = "registry.internal/custom-dada2:1.0", platform = "linux/amd64" }
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
`kind`, `image`, and `platform` are all optional on defaults, plugin entries, and task entries.
|
|
167
|
+
`kind` may be `docker` or `apptainer`. `image` remains the environment reference:
|
|
168
|
+
for Docker it is the container image, and for Apptainer it must be a local `.sif` path.
|
|
169
|
+
|
|
170
|
+
Precedence is `task override > plugin override > defaults > default resolver`.
|
|
171
|
+
|
|
172
|
+
Task lookup supports graph node `id`, optional task `name` when present in the
|
|
173
|
+
pipeline, and `plugin.action` as a fallback. Plugin lookup uses the pipeline's
|
|
174
|
+
plugin name. If `platform` is omitted all the way through, Adagio uses normal
|
|
175
|
+
Docker platform resolution with no implicit fallback. Anything not listed in the
|
|
176
|
+
config uses the default plugin image resolver.
|
|
177
|
+
|
|
178
|
+
Concrete Apptainer example:
|
|
179
|
+
|
|
180
|
+
```toml
|
|
181
|
+
version = 1
|
|
182
|
+
|
|
183
|
+
[defaults]
|
|
184
|
+
kind = "docker"
|
|
185
|
+
|
|
186
|
+
[plugins]
|
|
187
|
+
bowtie2 = { kind = "apptainer", image = "/shared/qiime-images/q2-bowtie2-test.sif" }
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
For `kind = "apptainer"`, Adagio prefers the `apptainer` executable and falls back to
|
|
191
|
+
`singularity`. The current implementation supports only local `.sif` paths and runs
|
|
192
|
+
tasks serially; no scheduler submission or remote image pull behavior is included.
|
|
193
|
+
|
|
194
|
+
### QAPI generation/submission
|
|
195
|
+
|
|
196
|
+
Generate and submit plugin metadata from the active QIIME environment:
|
|
197
|
+
|
|
198
|
+
```bash
|
|
199
|
+
adagio qapi build --action-url http://localhost:81/api/v1
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
Submit to a protected deployment such as `adagio.run` with a scoped submission token:
|
|
203
|
+
|
|
204
|
+
```bash
|
|
205
|
+
export ACTION_URL=https://adagio.run/api/v1
|
|
206
|
+
export QAPI_SUBMISSION_TOKEN=<token copied from https://adagio.run/app/profile>
|
|
207
|
+
uv run adagio qapi build
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
You can also pass `--submission-token`, but the environment variable is safer because it does
|
|
211
|
+
not end up in shell history.
|
|
212
|
+
|
|
213
|
+
Write payload to disk without submitting:
|
|
214
|
+
|
|
215
|
+
```bash
|
|
216
|
+
adagio qapi build --output qapi.json --dry-run
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
Submit selected plugins only:
|
|
220
|
+
|
|
221
|
+
```bash
|
|
222
|
+
adagio qapi build --plugin dada2 --plugin feature-table
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
## Development
|
|
226
|
+
|
|
227
|
+
### Setup
|
|
228
|
+
|
|
229
|
+
Install runtime and dev dependencies:
|
|
230
|
+
|
|
231
|
+
```bash
|
|
232
|
+
uv sync --group dev
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
Run commands inside the project environment:
|
|
236
|
+
|
|
237
|
+
```bash
|
|
238
|
+
uv run adagio --help
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### Linting
|
|
242
|
+
|
|
243
|
+
```bash
|
|
244
|
+
uv run ruff check .
|
|
245
|
+
uv run ruff format --check .
|
|
246
|
+
uv run ruff format .
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
### Tests
|
|
250
|
+
|
|
251
|
+
```bash
|
|
252
|
+
uv run pytest
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
### Build distributions
|
|
256
|
+
|
|
257
|
+
```bash
|
|
258
|
+
uv run python -m build
|
|
259
|
+
uv run python -m twine check dist/*
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
### Running locally during development
|
|
263
|
+
|
|
264
|
+
```bash
|
|
265
|
+
uv run adagio run --pipeline path/to/pipeline.json --cache-dir /path/to/cache
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
### Runtime entrypoint (container/integration use)
|
|
269
|
+
|
|
270
|
+
The `runtime` subcommand is intended for runtime-adapter jobs:
|
|
271
|
+
|
|
272
|
+
```bash
|
|
273
|
+
uv run adagio runtime --spec spec.json --config runtime.toml --arguments arguments.json --cache-dir /path/to/cache
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
### Releasing
|
|
277
|
+
|
|
278
|
+
See [RELEASING.md](RELEASING.md) for the one-time PyPI/GitHub setup, version/tag workflow, and TestPyPI/PyPI publishing steps.
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "adagio-cli"
|
|
3
|
+
version = "0.1.0a1"
|
|
4
|
+
description = "Command-line runner for Adagio pipeline files."
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.10"
|
|
7
|
+
authors = [{ name = "Cymis" }]
|
|
8
|
+
license = "MIT"
|
|
9
|
+
license-files = ["LICENSE"]
|
|
10
|
+
keywords = ["adagio", "bioinformatics", "cli", "pipelines", "qiime2", "workflow"]
|
|
11
|
+
classifiers = [
|
|
12
|
+
"Development Status :: 3 - Alpha",
|
|
13
|
+
"Environment :: Console",
|
|
14
|
+
"Intended Audience :: Developers",
|
|
15
|
+
"Intended Audience :: Science/Research",
|
|
16
|
+
"License :: OSI Approved :: MIT License",
|
|
17
|
+
"Programming Language :: Python :: 3",
|
|
18
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
19
|
+
"Programming Language :: Python :: 3.10",
|
|
20
|
+
"Programming Language :: Python :: 3.11",
|
|
21
|
+
"Programming Language :: Python :: 3.12",
|
|
22
|
+
"Topic :: Scientific/Engineering :: Bio-Informatics",
|
|
23
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
24
|
+
]
|
|
25
|
+
dependencies = [
|
|
26
|
+
"cyclopts>=4.5.3",
|
|
27
|
+
"pydantic>=2.12.5",
|
|
28
|
+
"rich>=14.1.0",
|
|
29
|
+
"parsl>=2024.12.16",
|
|
30
|
+
"tomli>=2.2.1; python_version < '3.11'",
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
[project.urls]
|
|
34
|
+
Homepage = "https://github.com/cymis/adagio-cli"
|
|
35
|
+
Repository = "https://github.com/cymis/adagio-cli"
|
|
36
|
+
Issues = "https://github.com/cymis/adagio-cli/issues"
|
|
37
|
+
Changelog = "https://github.com/cymis/adagio-cli/blob/dev/CHANGELOG.md"
|
|
38
|
+
|
|
39
|
+
[dependency-groups]
|
|
40
|
+
dev = [
|
|
41
|
+
"build>=1.2.2",
|
|
42
|
+
"pytest>=8.4.0",
|
|
43
|
+
"ruff>=0.13.0",
|
|
44
|
+
"twine>=6.2.0",
|
|
45
|
+
]
|
|
46
|
+
|
|
47
|
+
[project.scripts]
|
|
48
|
+
adagio = "adagio.cli.main:main"
|
|
49
|
+
|
|
50
|
+
[build-system]
|
|
51
|
+
requires = ["uv_build>=0.8.17,<0.9.0"]
|
|
52
|
+
build-backend = "uv_build"
|
|
53
|
+
|
|
54
|
+
[tool.uv.build-backend]
|
|
55
|
+
module-name = "adagio"
|
|
56
|
+
|
|
57
|
+
[tool.ruff.format]
|
|
58
|
+
quote-style = "double"
|
|
59
|
+
indent-style = "space"
|
|
60
|
+
docstring-code-format = true
|
|
61
|
+
|
|
62
|
+
[tool.ruff.lint.isort]
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
known-first-party = ["adagio"]
|
|
66
|
+
section-order = [
|
|
67
|
+
"future",
|
|
68
|
+
"standard-library",
|
|
69
|
+
"third-party",
|
|
70
|
+
"first-party",
|
|
71
|
+
"local-folder",
|
|
72
|
+
]
|
|
73
|
+
[tool.mypy]
|
|
74
|
+
plugins = ['pydantic.mypy']
|
|
75
|
+
|
|
76
|
+
[[tool.mypy.overrides]]
|
|
77
|
+
|
|
78
|
+
module = ["qiime2.*"]
|
|
79
|
+
ignore_missing_imports = true
|
|
80
|
+
|
|
81
|
+
[tool.pytest.ini_options]
|
|
82
|
+
addopts = "-ra"
|
|
83
|
+
testpaths = ["tests"]
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from importlib.metadata import PackageNotFoundError, version
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def _resolve_version() -> str:
|
|
5
|
+
for dist_name in ("adagio-cli", "adagio"):
|
|
6
|
+
try:
|
|
7
|
+
return version(dist_name)
|
|
8
|
+
except PackageNotFoundError:
|
|
9
|
+
continue
|
|
10
|
+
return "0.0.0"
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
__version__ = _resolve_version()
|
|
14
|
+
|
|
15
|
+
__all__ = ["__version__"]
|