The Wrike side¶
A bot account exists under dpsmith@bcm.edu ("Cluster Bot", KUAYXHNY),
distinct from Daniel's normal Daniel.Smith@bcm.edu account.
The bot is a regular user, so it holds a license seat and everything in this
system runs as it: commenting, attaching files, writing custom fields, setting
task status, and creating tasks — which is what lets run file a request
on a caller's behalf rather than making every user bring a token of their own.
It was a Collaborator until August 2026. That costs no seat, but Collaborators
may not create tasks (403 not_allowed, a license restriction rather than a
permission grantable on the folder) or edit custom fields — and a rejected
custom field write comes back 200 with the change quietly dropped, which is why
set_wrike_custom_field reads the reply back and warns when Wrike did not
apply what it was asked for.
To check which account a token belongs to:
curl -sS -H "Authorization: bearer $WRIKE_API_TOKEN" "https://www.wrike.com/api/v4/contacts?me=true" | jq '.data[0].profiles'
A "Nextflow Pipelines" space holds the "Dashboards" folder that tracks every submitted job, and the "Bioinformatics Pipeline" request form that creates tasks in it — see the Wrike API responses for the form's definition. Everything the bot sees, it sees because the request form put it in that folder.
The request form's questions¶
Every question is listed in WRIKE_FORM_ANSWERS in
wrike_api.sh, as
key | title in Wrike | custom field ID | allowed answers:
| Key | Custom field | Answers |
|---|---|---|
pipeline |
Nextflow Pipeline | ampliseq, taxprofiler, prev_run_id |
retention |
Dashboard Retention | 1, 3, 6, 12, 24 Months, or Unlimited |
previous_run |
Nextflow Previous Run ID | a run's uid — checked by shape, not by list |
dada_ref_taxonomy |
Ampliseq --dada_ref_taxonomy | 11 values, SILVA as silva=138.2 |
qiime_ref_taxonomy |
Ampliseq --qiime_ref_taxonomy | silva=138, greengenes2=2024.09 |
kraken2_ref_taxonomy |
Ampliseq --kraken2_ref_taxonomy | silva=138, rdp=18, greengenes=13.5, standard=20240904 |
picrust |
Ampliseq --picrust | No, Yes |
exclude_taxa |
Ampliseq --exclude_taxa | mitochondria, chloroplast, Francisella |
hostremoval_reference |
Taxprofiler --hostremoval_reference | None, PhiX, Human + PhiX, Mouse + PhiX |
Every key but the first three names the nextflow parameter its field is titled after, so a pipeline applies one by asking for its own parameter name — see the form's answers.
An optional question the requester leaves at its default is not on the task at
all. That is what the form's Settings: Default does, and it is why an absent
answer means "the pipeline's own default" rather than an error. There is no
Settings field for the system to read, and none is needed.
Answers are checked twice¶
Every answer ends up in a nextflow parameters file, so wrike_task_handler.sh
rejects the request unless it passes both of:
- Shape. Only the characters that appear in the answers above, plus the
:and/of a results link —[A-Za-z0-9 ,.:+=/_-], no.., at most 256 characters. This one applies to every answer, includingprevious_run, which has no list of its own. - The list. Exact membership, naming the answers that would have worked. A multiple-choice answer arrives comma-separated and every part has to be allowed.
The first check is the one that does not trust Wrike. The lists are
exact-match, so while Wrike sends only what its dropdowns offer the character
check adds nothing — but that is an assumption rather than a guarantee. A
dropdown can be switched to free text in one click, Nextflow Pipeline already
accepts values outside its list (allowOtherValues), and a custom field can be
written by anything holding a token. Neither check is load-bearing alone.
A malformed answer is refused without being quoted back on the task, so nothing
unchecked is reflected into a Wrike comment; .request in the run's
run_state.json has it if you need to see it.
There is no free-text parameter field: what a requester can ask for is exactly what is listed above.
Checked answers are recorded verbatim under .answers in the run's state file
and left there. Nothing in the handler interprets one — pipelines read them with
form_answer, so which answers mean anything stays a
pipeline's business.
Fields are addressed by ID, not by title. The account carries over a hundred custom fields from every CMMR workflow and several share a title, so matching on one can silently read another team's field. These nine all live in the "Nextflow Pipelines" space:
Adding a question is: create the custom field, point the form at it, and add a
row to WRIKE_FORM_ANSWERS. A row with an empty ID reads as never answered, and
the handler warns once per request naming it.
.request in the run's state file records which field each question resolved
through and what came back, so an answer that did not arrive can be told from one
that was never given.
Two more fields the system writes are not questions, so they have IDs of their
own rather than rows in that table: WRIKE_DASHBOARD_URL_CFID ("Dashboard URL")
and WRIKE_EXPIRATION_CFID ("Dashboard Expiration").
The pipeline question¶
Its options carry a description after the name:
ampliseq :: 16S full length or variable region amplicons
taxprofiler :: WGS metagenomic profiling
prev_run_id :: process new data using the same settings as before
Only the first word is read, so the descriptions can be reworded freely. The
first two resolve to pipelines/AMPLISEQ.sh and pipelines/TAXPROFILER.sh; the
third names no pipeline, and means the settings come from the run named in
"Nextflow Previous Run ID".
Adding a fourth option means adding pipelines/<NAME>.sh and the option to both
the form and WRIKE_FORM_ANSWERS — see
Adding a pipeline.
Dashboard Retention¶
The one answer besides "Nextflow Pipeline" that the handler reads rather than
leaving to a pipeline. wrike_task_handler.sh turns it into a date — today plus
the number of months it names — and writes that to the task's "Dashboard
Expiration" field (WRIKE_EXPIRATION_CFID); "Unlimited" leaves that blank,
which means kept indefinitely. It is also recorded in the run's manifest.
wrike_expiration.sh reads that date off every task in "Dashboards" once a day:
two weeks out it comments, mentioning the author and the task's followers; on the
date it deletes the published results, leaves an expired page in their place, and
sets the task's Status to Expired. The date on the task is what it acts on,
so editing "Dashboard Expiration" is how a dashboard is kept longer. See
Expiring a dashboard.