tasks outputs that enrich context of dependent downstream tasks
Description
Usecase
Consider a setup where many tasks needs same credentials for different operations.
Therefore, the logical thing is to have a task that reads creds that MUST NOT be persisted on disk from some secret manager, and passes them in-memory to all its dependents.
Current state
The only way I could find how to do it now - is have the "reader" task print something that the downstream stasks have to pass to eval - e.g. a step like - eval $(task creds).
version: '3' tasks: creds: cmds: - echo "export USR=me; export PWD=top-secret!!;" operation1: cmds: - > eval $(task creds); some-cli-tool -u $USR -p $PWD some operation1 operation2: deps: [creds] cmds: - > eval $(task creds); some-cli-tool -u $USR -p $PWD some operation2
That is less than ideal.
Firstly because it is platform-dependent and shell dependent.
Second - if I want to debug something - I should print it to >&2 - and that's also a shell specific thing.
Third - the eval must happen on every command - it is not persisted even on the task level... If I want to pass it to env - it gets very clunky:
tasks: creds: cmds: - vault read ... operation1: vars: USR: { sh: task creds | jq.USR } PWD: { sh: task creds | jq.PWD} cmds: - some-cli-tool-expects-ENV-vars operation3
this negates all the reuse beause the operation<#>.vars is coppied between all the operations that depend on creds :(
Proposal
I would propose tasks to have "outputs", similar to how outputs work in GitHub actions, just less cumbersome...
e.g:
version: '3' tasks: creds: vars: JSON: sh: aws sts get-parameter .... | jq -r .Parameter.Value USR: sh: echo {{.JSON}} | jq .USR output: true # makes $USR available on context of dependent tasks PWD: sh: echo {{.JSON}} | jq .PWD output: { as: SVC_API_KEY } # makes it available on context of dependent tasks as `SVC_API_KEY` operation1: deps: [creds] cmds: - some-cli-tool -u $USR some operation1 # assumes SVC_API_KEY
Mind that on operation1 - it explicitly uses $USR and not {{.USR}} so that the value is not spat to screen.
It would be nice to support secret mode if the scope allows it:
creds: vars: JSON: sh: aws sts get-parameter .... | jq -r .Parameter.Value USR: sh: echo {{.JSON}} | jq .USR output: true # make it available on contexts of dependent tasks PWD: sh: echo {{.JSON}} | jq .PWD output: true secret: true # truncates the secret from being print, replacing it with `<secret>` # more suggested forms that worth considering to be supported: # (but if it makes the scope too big - it can be dealt in a separate feature PR) # secret: { replace: '..shh!!' } - when print to logs - replaces each secret with `...shh!!` (you control the string) # secret: { mask: '*' } - replaces every character with a `*`, so the length of the secret is visible # secret: { peek: 4, replace: true } - keeps the first `peek` character visible # and replaces all the rest with `replace` so the output confirms you got the right secret, # but it is never spat raw. # secret: { peek: 4, replace: '<truncated>' } - same like previous, but you control the replacement string # secret: { peek: 4, mask: '*' } - keeps the first `peek` character visible and replaces the rest of characters with `mask` # so the secret can be identified also by the length as an additional confirmation # but it is never spat raw.