task icon indicating copy to clipboard operation
task copied to clipboard

Allowing assigning the STDOUT result of a task to a variable

Open dischello opened this issue 6 years ago • 11 comments

Set value of the task to the var:

task-B:
    vars:
        ARG1:
        ARG2:
task-A:
    vars:
      VAR-A: 
        - task-B: 
          vars: {ARG1: "first", ARG2: "second"}

it would be nice to have such thing to reuse existing tasks more efficiently or is there way to pass variable/values/data between task?

dischello avatar Feb 22 '19 13:02 dischello

Hi @dischello,

Sorry, I'm not sure I understood the request. Do you want to assign the result of a task (STDOUT) to a variable?

andreynering avatar Feb 24 '19 14:02 andreynering

Hi @andreynering,

Sorry for confusion. I found solution. Basically when i am calling task like this

task-B:
    vars:
        ARG1:
        ARG2:
task-A:
    vars:
      VAR-A: 
        - task task-B "ARG1=agr1" "ARG2=arg2"

worked perfectly fine for me.

dischello avatar Feb 25 '19 14:02 dischello

@dischello Yeah, that's not ideal, but recursively calling task works.

I'll keep this open in order to maybe allow this in the future:

vars:
  FOO: {task: foobar}

This can be tricky though, since it can in theory allow a recursive dependency (i.e. a var depending on a task and this task depending on the same variable).

For now you can just use sh:.

andreynering avatar Mar 03 '19 17:03 andreynering

@andreynering I think this feature could be great but my use case would be a bit different.

I think if the output of any generic command (or task) could be assigned to a variable within the scope (or perhaps global) it would greatly improve the flexibility and allow variables to be generated only after preconditions, something I cannot figure out how to do now.

Here's an example of something I'm trying to transition from our own internal Go task runner.

tasks:
  install:
    desc: Create a user with accounts
    vars:
      GIT_USER_EMAIL:
        sh: git config user.email
      EMAIL: "{{.EMAIL | default (.GIT_USER_EMAIL)}}"
    cmds:
      - kubectl rollout status deployment/app
      - echo "Creating Accounts for {{.EMAIL}}"
      - cmd: kubectl get po -lapp=app -o jsonpath='{.items[*].metadata.name}' | cut -d" " -f1
        assign: POD
      - kubectl exec -it {{.POD}} -c app -- bin/console dev:install {{.EMAIL}}
      - task: prepare
        vars: { POD_NAME: "{{.POD}}" }
      - echo -e "\nSuccess! You can now login."

The reason I find this important is that the POD information can't be collected until after the rollout completes. For many things is possible to just do a variable in the same command block, but this provides greater flexibility. And right now I know of no way to pass a command output to another task.

As far as the original poster, I imagine creating a task to assign could also be helpful.

tasks:
  get-data:
    cmds:
      - echo "my data"
  run:
    cmds:
      - task: get-data
        assign: DATA
      - 'echo "{{.DATA}}" | jq | etc'

In this scenario there are considerations on what kind of output is expected with multiple commands and how to merge those together if necessary.

Let me know what you think. If this is something you think we can add I'll be more than happy to make a PR.

Thanks!

dolfelt avatar Jul 07 '21 19:07 dolfelt

@dolfelt where you able to get the assign working?

I have been trying to get it working for something I am doing, and have bumped into an issue reading from Stdout.

If you have would you be able to share your code please?

russellseymour avatar Sep 07 '21 08:09 russellseymour

I also have a case where assigning stdout of another command would help. This is the shell command:

sudo docker run -d --publish 8043 --volume ${CREDS}:/srv/http \
    --name secrets-server pierrezemb/gostatic
secrets_ip=$(sudo docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' secrets-server)
sudo docker build ... --add-host=secrets-server:${secrets_ip} ...

Here, secrets_ip can be set only after the first command is executed and before executing the next one. In the current task version, if I translate it as is, the created environment variable is not available in the next command.

orsinium avatar Sep 23 '21 08:09 orsinium

Something like this would be great! I'm currently looking for a way to have one cmd or task save output to env or var that can be referenced in the next cmd or task. Any news on this?

timharris777 avatar Jun 02 '23 15:06 timharris777

Throwing this out there: would it make more sense to attack this problem from the opposite end? eg:

tasks:
  get-data:
    cmds:
      - echo "my data"

  use-data:
    vars:
      DATA:
        task: get-data
    cmds:
      - 'echo "{{.DATA}}" | jq | etc'

this strategy would conflict with the any-variables experiment, but I think it's cleaner this way.

amancevice avatar Mar 10 '24 19:03 amancevice

another workaround I've been playing with using a scripts section and YAML anchors to re-use bits of code:

scripts:
  AUTO_SCALING_GROUP: &AUTO_SCALING_GROUP
    sh: >-
      aws autoscaling describe-auto-scaling-groups
      | jq -r '.AutoScalingGroups[].AutoScalingGroupName'
      | fzf --prompt '{{.PROMPT | default "Pick Auto Scaling Group > "}}'

tasks:
  list-instances:
    desc: List instance IDs in auto scaling group
    vars:
      PROMPT: "This overrides the prompt below > "
      AUTO_SCALING_GROUP: *AUTO_SCALING_GROUP
    cmds:
      - >-
        aws autoscaling describe-auto-scaling-groups
        --auto-scaling-group-names {{.AUTO_SCALING_GROUP}}
        | jq -r '.AutoScalingGroups[].Instances[].InstanceId

amancevice avatar Mar 17 '24 20:03 amancevice