Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add global preconditions #294

Open
tommyalatalo opened this issue Feb 11, 2020 · 7 comments
Open

Add global preconditions #294

tommyalatalo opened this issue Feb 11, 2020 · 7 comments

Comments

@tommyalatalo
Copy link

tommyalatalo commented Feb 11, 2020

It would be great to be able to set global preconditions to prevent running any tasks in a Taskfile and its children if the precondition is not met. This would be a simple way to add a precondition to all tasks without having to add the same precondition to every task individually.

The use case for this is for example to enforce that a repository has been initialized somehow before allowing to run any other tasks, like setting up release targets for goreleaser or similar. In this example I would have the .goreleaser.yml contain a string like "INIT_PACKAGE" which should be replaced by the package name of the repository, and until that's done all tasks should fail (precondition greps for "INIT_PACKAGE"), and return the same message "This repository hasn't been initialized, please run 'task init'".

Obviously to be able to run the initial task init there needs to be a property to disable the global precondition for that specific task. So the Taskfile would end up something like this:

version: '2'

preconditions:
    - grep INIT_PACKAGE .goreleaser.yml
      msg: "this repository needs to be initialized, run 'task init' to continue"

tasks:
  build:
    desc: build go project
    cmds:
      - go build .
  
  init:
    desc: initalize repository
    cmds:
      - sed -i 's/INIT_PACKAGE/myPackage/g' .goreleaser.yml
    ignore_preconditions: yes

Also the logic should probably be that any preconditions from the parent Taskfile which includes other taskfiles should be applied on all the child taskfiles' tasks as well, i.e. they inherit the parent's global preconditions. The preconditions should only be propagated downwards in the hierarchy meaning that the parent Taskfile doesn't inherit global preconditions from it's children. Or maybe there should be a property to select this behavior as well, "include_preconditions: yes/no"?

@andreynering andreynering added the type: feature A new feature or functionality. label Feb 14, 2020
@andreynering
Copy link
Member

Hi @tommyalatalo,

This seems like an useful feature request, but shouldn't be my priority for the near future, unless someone else decides to contribute with this.

@sylv-io
Copy link
Contributor

sylv-io commented Oct 15, 2022

Since #405 is a duplication, let me paste my workaround [1, 2] here too:

There is already a way to reuse preconditions by the use of YAML anchors:

tasks:

  task1:
    cmds:
      - "echo task1"
    preconditions:
      - &test-precondition
        sh: "[ 1 = 0 ]"
        msg: "One doesn't equal Zero, Halting"

  task2:
    cmds:
      - "echo task2"
    preconditions:
      - *test-precondition

  task3:
    cmds:
      - "echo task3"
    preconditions:
      - *test-precondition

However, the anchor have to be on the same YAML file.
Adding global preconditions would only reduce duplications, if they are used on multiple imported taskfiles.

Since we do not use strict YAML unmarshal, even this is possible:

preconditions:
  <<: &test-precondition
    sh: "[ 1 = 0 ]"
    msg: "One doesn't equal Zero, Halting"

tasks:

  task1:
    cmds:
      - "echo task1"
    preconditions:
      - *test-precondition

  task2:
    cmds:
      - "echo task2"
    preconditions:
      - *test-precondition

  task3:
    cmds:
      - "echo task3"
    preconditions:
      - *test-precondition

@tommyalatalo
Copy link
Author

I'm aware of yaml anchors, but as you said yourself, it doesn't work across multiple taskfiles, and it requires a lot of duplication which is error prone.

@sylv-io
Copy link
Contributor

sylv-io commented Oct 15, 2022

I'm aware of yaml anchors, but as you said yourself, it doesn't work across multiple taskfiles, and it requires a lot of duplication which is error prone.

sure, I understand. I prefer a proper solution for this issue, too. This is just a comment for anyone who is not aware of yaml anchors and are looking for a workaround solution.

@dark06
Copy link

dark06 commented May 10, 2024

I prefer to initially advocate for seeking a solution that doesn't rely on anchors.
If that's not possible, having a key to store anchors would be helpful to prevent syntax highlighting errors.

image

@onedr0p
Copy link
Contributor

onedr0p commented May 14, 2024

I just came across a use-case that would have made my taskfiles so much more DRY, do not let the taskfile be run as root.

preconditions:
  - msg: must not be run as root
    sh: '[[ $LOGNAME != "root" ]]'

The anchor solution works in basic use cases but since you cannot use them across files it makes that solution less than ideal for me.

@firstmustburn
Copy link

firstmustburn commented Dec 16, 2024

I'll tack a comment onto this that if we're going to add preconditions, we should add requires as well. I've got imported taskfiles that depend on global variables (from the importing taskfile), and I'd like to be able to ensure those are set at the taskfile level.

If I can carve out a little time, I will try to make a PR for this, but I'm leaving a comment here for future me or in case someone else picks it up first.

Example use case:

  • REMOTE_DOCKER_NAME_STUB is common across many included taskfiles, so I want it to be defined at the top level.
  • REMOTE_DOCKER_IMAGE_NAME is shared among tasks in one of the included taskfiles, so I want to define it once at the top of that taskfile.
  • As a workaround, I can include REMOTE_DOCKER_NAME_STUB in the requires for each task, but this breaks the DRY. If I change the way REMOTE_DOCKER_IMAGE_NAME is defined, I also have to go update all those tasks.

including file:

vars:
  REMOTE_DOCKER_NAME_STUB: somerepo.example.com/argyle


includes:
  foo:
    taskfile: ./foo/Taskfile.yml

included file:

vars: #alphabetical list
  REMOTE_DOCKER_IMAGE_NAME: "{{.REMOTE_DOCKER_NAME_STUB}}/myimagename:latest"

tasks:
  docker-build:
    desc: build the docker image
    requires:
      vars: [ REMOTE_DOCKER_IMAGE_NAME]
    cmds:
      - docker build -t "{{.REMOTE_DOCKER_IMAGE_NAME}}" ./src/
docker-push-remote:
    desc: push the pg-backup docker image to the 
    requires:
      vars: [ REMOTE_DOCKER_IMAGE_NAME]
    cmds:
      - docker push "{{.REMOTE_DOCKER_IMAGE_NAME}}"

desired included file:

requires: [ REMOTE_DOCKER_NAME_STUB ]

vars: #alphabetical list
  REMOTE_DOCKER_IMAGE_NAME: "{{.REMOTE_DOCKER_NAME_STUB}}/myimagename:latest"

tasks:
  docker-build:
    desc: build the docker image
    requires:
      vars: [ REMOTE_DOCKER_IMAGE_NAME]
    cmds:
      - docker build -t "{{.REMOTE_DOCKER_IMAGE_NAME}}" ./src/
docker-push-remote:
    desc: push the pg-backup docker image to the 
    requires:
      vars: [ REMOTE_DOCKER_IMAGE_NAME]
    cmds:
      - docker push "{{.REMOTE_DOCKER_IMAGE_NAME}}"

@pd93 pd93 removed the type: feature A new feature or functionality. label Dec 16, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants