woodpecker-ci/woodpecker

Allow notification plugins to notify about the pipeline status

Opened this issue · 18 comments

xoxys commented

Clear and concise description of the problem

The env var CI_PIPELINE_STATUS war broken already and has always reported success but was now removed completely in #3846

Right now, I don't see any way to use a notification plugin in pipelines to send build status notifications to an external system.

Suggested solution

Add back CI_PIPELINE_STATUS and populate the correct status. We have the correct pipeline status in the UI/API already, why can't we just populate it to the env?

Alternative

No response

Additional context

No response

Validations

  • Checked that the feature isn't part of the next version already [https://woodpecker-ci.org/faq#which-version-of-woodpecker-should-i-use]
  • Read the docs.
  • Check that there isn't already an issue that request the same feature to avoid creating a duplicate.

CI_PIPELINE_STATUS and populate the correct status

Will always be running :)

xoxys commented

Well coming from Drone I can at least tell you there was a working and stable implementation.

there was a working and stable implementation

Sure. I didn't say that it is impossible. Do you know how it's implemented there?

Could you show an example pipeline? Does watched step have to define failure: ignore?

If we are using failure: ignore on watched step and notification step within the same pipeline, then one of implementations could be var like CI_STEPS_STATUSES with value like clone:success,test:success,build:fail. Or separate variables like CI_STEP_CLONE_STATUS:success and so on.

Another solution could be webhooks to external notification service.


We have the correct pipeline status in the UI/API already, why can't we just populate it to the env?

Yet another one: use special step type likeservice, but notification. It would always run after pipeline finishes and yes can contain correct CI_PIPELINE_STATUS.

xoxys commented

Sure. I didn't say that it is impossible. Do you know how it's implemented there?

Drone uses some kind of hooks https://github.com/harness/harness/blob/drone/operator/runner/runner.go#L380-L402 which looks kinda similar to what we had in place already. That's why I'm wondering why it was broken in Woodpecker...

Could you show an example pipeline? Does watched step have to define failure: ignore?

https://github.com/thegeeklab/wp-matrix/blob/main/.woodpecker/notify.yml

Yet another one: use special step type likeservice, but notification. It would always run after pipeline finishes and yes can contain correct CI_PIPELINE_STATUS.

Sure could be done this way also.

Thank you for an example. Wasn't aware of runs_on. It's like my special step type :)

Agree that it was/is a bug and should be fixed. But in the example it is still the same pipeline, pipeline status is running. Maybe there could be var like CI_WORKFLOW_STATUSES.


Drone has status trigger. Seems it was when.status in previous versions.
Besides runs_on there is when.status in Woodpecker. Assuming it works as described in the docs, there should be some env var in the step, carrying the status of "entity", used in when.status.

 steps:
   - name: slack
     image: plugins/slack
     settings:
       channel: dev
     when:
       - status: [ success, failure ]
 steps:
   - name: notify
     image: debian:stable-slim
     commands:
       - echo notifying
runs_on: [ success, failure ]

Related to drone: DRONE_BUILD_STATUS, DRONE_STAGE_STATUS, DRONE_BUILD_FINISHED, DRONE_STAGE_FINISHED.

xoxys commented

The agent is pulling the next workflow to execute from the queue but I cant see any way to access the parent pipeline information from the agent. Do I miss something? Is there any existing way to look up the pipeline with the given information from rpc.Workflow on the agent?

You can probably look it up via REST and even make custom GRPC method, but why. It's the server responsibility to set (almost) all vars. And this map sends to the agent.

xoxys commented

This map is only set once during the pipeline creation and can only contain static values that dont change during workflow executions. For the pipeline state it must be looked up before a workflow is pulled from the queue and executed.

Notifications have to be executed after all ... what actually (steps in workflow or workflows)? Do you want notification per workflow or per pipeline?

  1. Per pipeline. I think you can now define the separate notifications workflow as depends_on others in a way it executes the last (after workflows you want notifications about). So at the time the notifications workflow is ready to execute, the Server will know the statuses of all other executed workflows. The server sets up env CI_WORKFLOW_STATUSES (or separate ones) and sends the notifications workflow into queue. Agent picks it up and all works.
  2. It actually works for both workflows statuses and pipeline. So you have statuses of each workflow. And if all workflows are success, then the pipeline is also success -> you can set PIPELINE_STATUS on the server a bit in advance.

Anyway, how the example works now?

 steps:
   - name: slack
     image: plugins/slack
     settings:
       channel: dev
     when:
       - status: [ success, failure ]

Server should defer this last step, wait for other steps (?), get status of workflow (?) and then depending on condition run the step. Right?

xoxys commented

Maybe I miss something, but I don't see how your approach should work:

  1. Pipeline is triggered by event
  2. Pipeline config will be parsed, and all workflows will be compiled and added to the queue. At this point all static env vars from the location you have linked are already added to the workflow metadata before they are added to the queue.
  3. Workflows are executed, one or more failed but the notification workflow which is already in the queue at this point doesnt know about the changed pipeline state (how should it?)

all workflows will be compiled and added to the queue
the notification workflow which is already in the queue

All except notifications. Compile ... maybe, but not put in queue. Before scheduling, statuses should be set. That was the point in my approach. Agree, that now it might not work, but it could be some mark in syntax to define such workflows.


And still, I wonder

  1. Does the examples work at all?
  2. How do they work then? Because before we (server?) run a step with when.status:failure we need failure of some "entity".

Edit
What we can do now is

  1. Define notification step or workflow-with-depend-on.
  2. Make notifications plugin to call the Server via REST for whatever statuses (step, workflow) we want. The whole pipeline status can be interpolated a little bit in advance as I mentioned before.
6543 commented

the current pipeline status is just technically undefined till it has finished.

and CI_PREV_PIPELINE_STATUS is still here ... so i dont get what the problem is ...

also taling abaut notification plugin you might wana have a look into CI_PREV_STEP_STATUS

xoxys commented

Goal: At the end of a pipeline I want to have a step that sends the current pipeline (not workflow, not step) status (success or failure) to an external system. Is this possible right now?

and CI_PREV_PIPELINE_STATUS is still here ... so i dont get what the problem is ...

How does the previous pipeline status helps here? Some pipelines are running very long. Checking the web UI or forge PR status frequently is annoying. That's why I want a way to send a notification with the pipeline status as the last step of a pipeline to an external system e.g. mail, chat, push gateway etc. Using Drone CI this was easily possible, see my comments above.

the current pipeline status is just technically undefined till it has finished.

Well, no. The pipeline status can be success or failure. It is set to success by default and changed to failure after the first step in a pipeline has failed (unless the step is configured to ignore failures). Again, as a former Drone user I can just tell you that this feature was easy to use and stable since years without needing a too complicated mechanism see https://docs.drone.io/pipeline/environment/reference/drone-build-status/

From the Drone docs:

Please note this is point in time snapshot. This value may not accurately reflect the overall build status when multiple pipelines are running in parallel.

While that's obvious, we have already a mechanism in Woodpecker as well to ensure that the notification step is the last step executed in a pipeline, but it also allows users to get the point in time pipeline status as well if required.

Is this possible right now?

It should have been possible with

# build.yaml
skip_clone: true
steps:
  build:
    image: alpine
    commands:
      - echo 'Building the app'
      - exit 1 # 0 - success, 1 - fail
# notifications.yaml
skip_clone: true
depends_on: [build]
runs_on: [success, failure]
steps:
  fail-notification:
    when:
      - status: [failure]
    image: alpine
    commands:
      - echo 'Build failed'
  success-notification:
    when:
      - status: [success]
    image: alpine
    commands:
      - echo 'Build succeed'

But it doesn't work
Screenshot 2024-11-11 1

Tested on 2.7.1 and next. Looks like a bug to me. Should I file it as separate bug-issue?

xoxys commented

This is a separate bug IMO. But to make it a bit more clear, even if this bug doesn't exist, this way is more a hack and not a proper solution for notifications.

When did CI_PIPELINE_STATUS stop working? It's been working reliably for me since before 2.0 and still is on 2.7.3 (I use it as part of a notifier script, running both on failure and success).

xoxys commented

See the linked PR in the issue description.

I first found the PR thanks to the release notes of the 3.0 release candidate, and then this issue: I didn't see any bisection/mention of when the variable was broken.