woodpecker-ci / woodpecker

Woodpecker is a simple, yet powerful CI/CD engine with great extensibility.
https://woodpecker-ci.org
Apache License 2.0
4.16k stars 359 forks source link

Workflow-level backend options #3802

Open zc-devs opened 3 months ago

zc-devs commented 3 months ago

Clear and concise description of the problem

Currently, we have plenty of backend options. Consider Kubernete, for example. While we can set them per-step:

steps:
  test:
    image: golang
    commands:
      - go test
    backend_options:
      kubernetes:
        nodeSelector:
          kubernetes.io/arch: amd64
        securityContext:
          runAsNonRoot: true
  build:
    image: golang
    commands:
      - go build
    backend_options:
      kubernetes:
        nodeSelector:
          kubernetes.io/arch: amd64
        securityContext:
          runAsNonRoot: true
  package:
    image: kaniko
    commands:
      - executor
    backend_options:
      kubernetes:
        nodeSelector:
          kubernetes.io/arch: amd64
        securityContext:
          runAsNonRoot: true

Suggested solution

it would be nice if we could set them per-workflow and override/refine in steps:

backend_options:
  kubernetes:
    nodeSelector:
      kubernetes.io/arch: amd64
    securityContext:
      runAsNonRoot: true

steps:
  test:
    image: golang
    commands:
      - go test
  build:
    image: golang
    commands:
      - go build
    backend_options:
      kubernetes:
        nodeSelector:
          beta.kubernetes.io/instance-type: p3.8xlarge
  package:
    image: buildx
    commands:
      - build

Alternative

  1. Copy-paste for each step.
  2. Use Advanced YAML syntax

Additional context

It would allow to implement backend-specific custom volumes per workflow, for example.

Validations

qwerty287 commented 3 months ago

Since we have a lot of issues like this, we should rather implement a way to set defaults for all steps. There was an issue for this too but I can't find it...

qwerty287 commented 3 months ago

Found it: https://github.com/woodpecker-ci/woodpecker/discussions/2294 Would this also be fine as implementation so we can close this issue?

zc-devs commented 3 months ago

In context of duplication, either #2294 or Advanced YAML syntax (I've updated Alternatives) would work, I think.

But I thought, about some per-pipeline functionality and came up with

It would allow to implement backend-specific custom volumes per workflow, for example.

Nor #2294, nor YAML substitution won't resolve this case.

See also #1594, #1595, #3345.

qwerty287 commented 3 months ago

So you would like to have both workflow and pipeline level? This is not what you wrote in the title 😉

zc-devs commented 3 months ago

some per-pipeline functionality

My bad. I meant file - workflow. For now volume is created per workflow anyway.

pipeline level

This is tempting :) I think I would want it, but let's eat elephant by pieces - start from workflow and see how it is going.

qwerty287 commented 3 months ago

My bad. I meant file - workflow.

Then I don't understand your points above.

It would allow to implement backend-specific custom volumes per workflow, for example.

Nor https://github.com/woodpecker-ci/woodpecker/discussions/2294, nor YAML substitution won't resolve this case.

Why not? You can define the backend options as default in the workflow and it is added to all steps with #2294?

zc-devs commented 3 months ago

Why not? You can define the backend options as default in the workflow and it is added to all steps with https://github.com/woodpecker-ci/woodpecker/discussions/2294?

Perhaps, I'm missing something. Consider an example

default:
  volumes:
    - storageClassName: local-ssd # K3s Local path provisioner
      resources:
        requests:
          storage: 512Mi
      mount: /mnt/local
    - storageClassName: nfs-hdd
      resources:
        requests:
          storage: 16Gi
      mount: /mnt/nfs

steps:
  one:
    commands:
      - echo "Hello" > /mnt/local/hello.txt
      - echo "world" > /mnt/nfs/world.txt
  two:
    commands:
      - cat /mnt/local/hello.txt
      - cat /mnt/nfs/world.txt

Would step two display

Hello
world

and two volumes be created (not 4)?

If yes, then #2294 completely suits.

Edit 1. I'm talking about creating the volumes, not just referencing.

qwerty287 commented 3 months ago

Here you need to explain some more about kubernetes to me...

It's just the same if you specify the same backend options/properties on every single step. If kubernetes creates new volumes if you have the same volumes defined on multiple steps, it will create 4, otherwise 2.

Your example would look like this if you want to achieve the same currently:

steps:
  one:
    commands:
      - echo "Hello" > /mnt/local/hello.txt
      - echo "world" > /mnt/nfs/world.txt
    volumes:
      - storageClassName: local-ssd # K3s Local path provisioner
        resources:
          requests:
            storage: 512Mi
        mount: /mnt/local
      - storageClassName: nfs-hdd
        resources:
          requests:
            storage: 16Gi
        mount: /mnt/nfs
  two:
    commands:
      - cat /mnt/local/hello.txt
      - cat /mnt/nfs/world.txt
    volumes:
      - storageClassName: local-ssd # K3s Local path provisioner
        resources:
          requests:
            storage: 512Mi
        mount: /mnt/local
      - storageClassName: nfs-hdd
        resources:
          requests:
            storage: 16Gi
        mount: /mnt/nfs
zc-devs commented 3 months ago

It's just the same if you specify the same backend options/properties on every single step.

Yeah, exactly.

If kubernetes creates new volumes

Currently, there is only one volume is created - WP workspace. You cannot create own.

Now, if I want to bring custom volumes functionality (persistence between steps). As a user, where should I define a volume? In each step? Why? It doesn't make sense to create volume per step. As a dev, how should I process it in the backend? Look over all steps, compare if volume definitions are equals?

Let me show an analogy - a service. You define it beyond the steps, only one service is created per workflow. While the service is universal syntax, I ~propose~ thought about K8s-specific syntax for volumes (which processed in the Agent).

qwerty287 commented 3 months ago

Ah I think I finally understood your point.

The workflow-level options should be different form the step ones, right? And not just a simple default value for all steps. So the handling of it happens before the steps are executed.

Then it's different from the default feature of course.