1
0
mirror of https://github.com/woodpecker-ci/woodpecker.git synced 2026-06-03 16:35:37 +02:00

Move skip pipeline by commit message into pipeline/frontend package (#6437)

and add some custom types for events and failure in metadata package.

no logic change at all.
This commit is contained in:
6543
2026-04-15 09:50:03 +02:00
committed by GitHub
parent 09c193bc51
commit 66e221b4b1
17 changed files with 113 additions and 56 deletions
+2 -2
View File
@@ -97,7 +97,7 @@ func metadataFromContext(_ context.Context, c *cli.Command, axis matrix.Axis, w
metadataFileAndOverrideOrDefault(c, "pipeline-started", func(i int64) { m.Curr.Started = i }, c.Int64)
metadataFileAndOverrideOrDefault(c, "pipeline-finished", func(i int64) { m.Curr.Finished = i }, c.Int64)
metadataFileAndOverrideOrDefault(c, "pipeline-status", func(s string) { m.Curr.Status = s }, c.String)
metadataFileAndOverrideOrDefault(c, "pipeline-event", func(s string) { m.Curr.Event = s }, c.String)
metadataFileAndOverrideOrDefault(c, "pipeline-event", func(s string) { m.Curr.Event = metadata.Event(s) }, c.String)
metadataFileAndOverrideOrDefault(c, "pipeline-url", func(s string) { m.Curr.ForgeURL = s }, c.String)
metadataFileAndOverrideOrDefault(c, "pipeline-deploy-to", func(s string) { m.Curr.DeployTo = s }, c.String)
metadataFileAndOverrideOrDefault(c, "pipeline-deploy-task", func(s string) { m.Curr.DeployTask = s }, c.String)
@@ -123,7 +123,7 @@ func metadataFromContext(_ context.Context, c *cli.Command, axis matrix.Axis, w
metadataFileAndOverrideOrDefault(c, "prev-pipeline-started", func(i int64) { m.Prev.Started = i }, c.Int64)
metadataFileAndOverrideOrDefault(c, "prev-pipeline-finished", func(i int64) { m.Prev.Finished = i }, c.Int64)
metadataFileAndOverrideOrDefault(c, "prev-pipeline-status", func(s string) { m.Prev.Status = s }, c.String)
metadataFileAndOverrideOrDefault(c, "prev-pipeline-event", func(s string) { m.Prev.Event = s }, c.String)
metadataFileAndOverrideOrDefault(c, "prev-pipeline-event", func(s string) { m.Prev.Event = metadata.Event(s) }, c.String)
metadataFileAndOverrideOrDefault(c, "prev-pipeline-url", func(s string) { m.Prev.ForgeURL = s }, c.String)
// Previous Pipeline Commit
+26 -1
View File
@@ -5891,6 +5891,31 @@ const docTemplate = `{
}
}
},
"metadata.Event": {
"type": "string",
"enum": [
"push",
"pull_request",
"pull_request_closed",
"pull_request_metadata",
"tag",
"release",
"deployment",
"cron",
"manual"
],
"x-enum-varnames": [
"EventPush",
"EventPull",
"EventPullClosed",
"EventPullMetadata",
"EventTag",
"EventRelease",
"EventDeploy",
"EventCron",
"EventManual"
]
},
"metadata.Forge": {
"type": "object",
"properties": {
@@ -5950,7 +5975,7 @@ const docTemplate = `{
"type": "string"
},
"event": {
"type": "string"
"$ref": "#/definitions/metadata.Event"
},
"event_reason": {
"type": "array",
+17 -15
View File
@@ -14,20 +14,22 @@
package metadata
type Event string
// Event types corresponding to forge hooks.
const (
EventPush = "push"
EventPull = "pull_request"
EventPullClosed = "pull_request_closed"
EventPullMetadata = "pull_request_metadata"
EventTag = "tag"
EventRelease = "release"
EventDeploy = "deployment"
EventCron = "cron"
EventManual = "manual"
EventPush Event = "push"
EventPull Event = "pull_request"
EventPullClosed Event = "pull_request_closed"
EventPullMetadata Event = "pull_request_metadata"
EventTag Event = "tag"
EventRelease Event = "release"
EventDeploy Event = "deployment"
EventCron Event = "cron"
EventManual Event = "manual"
)
func EventIsPull(event string) bool {
func (event Event) IsPull() bool {
switch event {
case EventPull,
EventPullClosed,
@@ -37,11 +39,11 @@ func EventIsPull(event string) bool {
return false
}
type Failure string
// Different ways to handle failure states.
const (
FailureIgnore = "ignore"
FailureFail = "fail"
//nolint:godot
// TODO: Not implemented yet.
// FailureCancel = "cancel"
FailureIgnore Failure = "ignore"
FailureFail Failure = "fail"
FailureCancel Failure = "cancel"
)
+4 -4
View File
@@ -67,7 +67,7 @@ func (m *Metadata) Environ() map[string]string {
pipeline := m.Curr
setNonEmptyEnvVar(params, "CI_PIPELINE_NUMBER", strconv.FormatInt(pipeline.Number, 10))
setNonEmptyEnvVar(params, "CI_PIPELINE_PARENT", strconv.FormatInt(pipeline.Parent, 10))
setNonEmptyEnvVar(params, "CI_PIPELINE_EVENT", pipeline.Event)
setNonEmptyEnvVar(params, "CI_PIPELINE_EVENT", string(pipeline.Event))
setNonEmptyEnvVar(params, "CI_PIPELINE_EVENT_REASON", strings.Join(pipeline.EventReason, ","))
setNonEmptyEnvVar(params, "CI_PIPELINE_URL", m.getPipelineWebURL(pipeline, 0))
setNonEmptyEnvVar(params, "CI_PIPELINE_FORGE_URL", pipeline.ForgeURL)
@@ -102,7 +102,7 @@ func (m *Metadata) Environ() map[string]string {
if pipeline.Event == EventRelease {
setNonEmptyEnvVar(params, "CI_COMMIT_PRERELEASE", strconv.FormatBool(pipeline.Commit.IsPrerelease))
}
if EventIsPull(pipeline.Event) {
if pipeline.Event.IsPull() {
sourceBranch, targetBranch := getSourceTargetBranches(commit.Refspec)
setNonEmptyEnvVar(params, "CI_COMMIT_SOURCE_BRANCH", sourceBranch)
setNonEmptyEnvVar(params, "CI_COMMIT_TARGET_BRANCH", targetBranch)
@@ -127,7 +127,7 @@ func (m *Metadata) Environ() map[string]string {
prevPipeline := m.Prev
setNonEmptyEnvVar(params, "CI_PREV_PIPELINE_NUMBER", strconv.FormatInt(prevPipeline.Number, 10))
setNonEmptyEnvVar(params, "CI_PREV_PIPELINE_PARENT", strconv.FormatInt(prevPipeline.Parent, 10))
setNonEmptyEnvVar(params, "CI_PREV_PIPELINE_EVENT", prevPipeline.Event)
setNonEmptyEnvVar(params, "CI_PREV_PIPELINE_EVENT", string(prevPipeline.Event))
setNonEmptyEnvVar(params, "CI_PREV_PIPELINE_EVENT_REASON", strings.Join(prevPipeline.EventReason, ","))
setNonEmptyEnvVar(params, "CI_PREV_PIPELINE_URL", m.getPipelineWebURL(prevPipeline, 0))
setNonEmptyEnvVar(params, "CI_PREV_PIPELINE_FORGE_URL", prevPipeline.ForgeURL)
@@ -149,7 +149,7 @@ func (m *Metadata) Environ() map[string]string {
setNonEmptyEnvVar(params, "CI_PREV_COMMIT_BRANCH", prevCommit.Branch)
setNonEmptyEnvVar(params, "CI_PREV_COMMIT_AUTHOR", prevCommit.Author.Name)
setNonEmptyEnvVar(params, "CI_PREV_COMMIT_AUTHOR_EMAIL", prevCommit.Author.Email)
if EventIsPull(prevPipeline.Event) {
if prevPipeline.Event.IsPull() {
prevSourceBranch, prevTargetBranch := getSourceTargetBranches(prevCommit.Refspec)
setNonEmptyEnvVar(params, "CI_PREV_COMMIT_SOURCE_BRANCH", prevSourceBranch)
setNonEmptyEnvVar(params, "CI_PREV_COMMIT_TARGET_BRANCH", prevTargetBranch)
+1 -1
View File
@@ -48,7 +48,7 @@ type (
Started int64 `json:"started,omitempty"`
Finished int64 `json:"finished,omitempty"`
Status string `json:"status,omitempty"`
Event string `json:"event,omitempty"`
Event Event `json:"event,omitempty"`
EventReason []string `json:"event_reason,omitempty"`
ForgeURL string `json:"forge_url,omitempty"`
DeployTo string `json:"target,omitempty"`
+4 -4
View File
@@ -42,10 +42,10 @@ type Secret struct {
Name string
Value string
AllowedPlugins []string
Events []string
Events []metadata.Event
}
func (s *Secret) Available(event string, container *yaml_types.Container) error {
func (s *Secret) Available(event metadata.Event, container *yaml_types.Container) error {
onlyAllowSecretForPlugins := len(s.AllowedPlugins) > 0
if onlyAllowSecretForPlugins && !container.IsPlugin() {
return fmt.Errorf("secret %q is only allowed to be used by plugins (a filter has been set on the secret). Note: Image filters do not work for normal steps", s.Name)
@@ -64,13 +64,13 @@ func (s *Secret) Available(event string, container *yaml_types.Container) error
// Match returns true if an image and event match the restricted list.
// Note that EventPullClosed are treated as EventPull.
func (s *Secret) Match(event string) bool {
func (s *Secret) Match(event metadata.Event) bool {
// if there is no filter set secret matches all webhook events
if len(s.Events) == 0 {
return true
}
// treat all pull events the same way
if metadata.EventIsPull(event) {
if event.IsPull() {
event = metadata.EventPull
}
// one match is enough
@@ -29,7 +29,7 @@ import (
func TestSecretAvailable(t *testing.T) {
secret := Secret{
AllowedPlugins: []string{},
Events: []string{"push"},
Events: []metadata.Event{"push"},
}
assert.NoError(t, secret.Available("push", &yaml_types.Container{
Image: "golang",
@@ -40,7 +40,7 @@ func TestSecretAvailable(t *testing.T) {
secret = Secret{
Name: "foo",
AllowedPlugins: []string{"golang"},
Events: []string{"push"},
Events: []metadata.Event{"push"},
}
assert.NoError(t, secret.Available("push", &yaml_types.Container{
Name: "step",
@@ -440,18 +440,18 @@ func TestSecretMatch(t *testing.T) {
tcl := []*struct {
name string
secret Secret
event string
event metadata.Event
match bool
}{
{
name: "should match event",
secret: Secret{Events: []string{"pull_request"}},
secret: Secret{Events: []metadata.Event{"pull_request"}},
event: "pull_request",
match: true,
},
{
name: "should not match event",
secret: Secret{Events: []string{"pull_request"}},
secret: Secret{Events: []metadata.Event{"pull_request"}},
event: "push",
match: false,
},
@@ -463,13 +463,13 @@ func TestSecretMatch(t *testing.T) {
},
{
name: "pull close should match pull",
secret: Secret{Events: []string{"pull_request"}},
secret: Secret{Events: []metadata.Event{"pull_request"}},
event: "pull_request_closed",
match: true,
},
{
name: "pull metadata change should match pull",
secret: Secret{Events: []string{"pull_request"}},
secret: Secret{Events: []metadata.Event{"pull_request"}},
event: "pull_request_metadata",
match: true,
},
+1 -1
View File
@@ -153,7 +153,7 @@ func (c *Compiler) createProcess(container *yaml_types.Container, workflow *yaml
failure := container.Failure
if container.Failure == "" {
failure = metadata.FailureFail
failure = string(metadata.FailureFail)
}
return &backend_types.Step{
@@ -172,13 +172,13 @@ func (c *Constraint) Match(m metadata.Metadata, global bool, env map[string]stri
}
match = match && c.Platform.Match(m.Sys.Platform) &&
(len(c.Event) == 0 || slices.Contains(c.Event, m.Curr.Event)) &&
(len(c.Event) == 0 || slices.Contains(c.Event, string(m.Curr.Event))) &&
c.Repo.Match(path.Join(m.Repo.Owner, m.Repo.Name)) &&
c.Ref.Match(m.Curr.Commit.Ref) &&
c.Instance.Match(m.Sys.Host)
// changed files filter apply only for pull-request and push events
if metadata.EventIsPull(m.Curr.Event) || m.Curr.Event == metadata.EventPush {
if m.Curr.Event.IsPull() || m.Curr.Event == metadata.EventPush {
match = match && c.Path.Match(m.Curr.Commit.ChangedFiles, m.Curr.Commit.Message)
}
+33
View File
@@ -0,0 +1,33 @@
// Copyright 2026 Woodpecker Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package constraint
import (
"regexp"
"go.woodpecker-ci.org/woodpecker/v3/pipeline/frontend/metadata"
)
var skipPipelineRegex = regexp.MustCompile(`\[(?i:ci *skip|skip *ci)\]`)
func IsSkipCommitMessage(event metadata.Event, commitMessage string) bool {
if event == metadata.EventPush || event.IsPull() {
skipMatch := skipPipelineRegex.FindString(commitMessage)
if len(skipMatch) > 0 {
return true
}
}
return false
}
+1 -1
View File
@@ -62,7 +62,7 @@ func withExitCode(code int) func(*backend_types.Step) {
}
func withIgnoreFailure() func(*backend_types.Step) {
return func(s *backend_types.Step) { s.Failure = metadata.FailureIgnore }
return func(s *backend_types.Step) { s.Failure = string(metadata.FailureIgnore) }
}
func withOnFailure() func(*backend_types.Step) {
+1 -1
View File
@@ -186,7 +186,7 @@ func (r *Runtime) runBlockingStep(runnerCtx context.Context, step *backend_types
}
err = r.traceStep(processState, err, step)
if err != nil && step.Failure == metadata.FailureIgnore {
if err != nil && metadata.Failure(step.Failure) == metadata.FailureIgnore {
return nil
}
return err
+1 -1
View File
@@ -553,7 +553,7 @@ func TestRunBlockingStep(t *testing.T) {
t.Parallel()
r := newDummyRuntime(t, newTestTracer(t))
step := dummyStep("s1")
step.Failure = metadata.FailureIgnore
step.Failure = string(metadata.FailureIgnore)
step.Environment[dummy.EnvKeyStepExitCode] = "1"
err := r.runBlockingStep(t.Context(), step)
+2 -1
View File
@@ -17,6 +17,7 @@ package model
import (
"go.woodpecker-ci.org/woodpecker/v3/pipeline/errors"
"go.woodpecker-ci.org/woodpecker/v3/pipeline/frontend/metadata"
)
type Pipeline struct {
@@ -100,7 +101,7 @@ func (p Pipeline) IsMultiPipeline() bool {
// IsPullRequest checks if it's a PR event.
func (p Pipeline) IsPullRequest() bool {
return p.Event == EventPull || p.Event == EventPullClosed || p.Event == EventPullMetadata
return metadata.Event(p.Event).IsPull()
}
type PipelineOptions struct {
+8 -12
View File
@@ -18,11 +18,12 @@ import (
"context"
"errors"
"fmt"
"regexp"
"github.com/rs/zerolog/log"
pipeline_errors "go.woodpecker-ci.org/woodpecker/v3/pipeline/errors"
"go.woodpecker-ci.org/woodpecker/v3/pipeline/frontend/metadata"
"go.woodpecker-ci.org/woodpecker/v3/pipeline/frontend/yaml/constraint"
"go.woodpecker-ci.org/woodpecker/v3/server"
"go.woodpecker-ci.org/woodpecker/v3/server/forge"
forge_types "go.woodpecker-ci.org/woodpecker/v3/server/forge/types"
@@ -31,8 +32,6 @@ import (
"go.woodpecker-ci.org/woodpecker/v3/version"
)
var skipPipelineRegex = regexp.MustCompile(`\[(?i:ci *skip|skip *ci)\]`)
// Create a new pipeline and start it.
func Create(ctx context.Context, _store store.Store, repo *model.Repo, pipeline *model.Pipeline) (*model.Pipeline, error) {
repoUser, err := _store.GetUser(repo.UserID)
@@ -42,16 +41,13 @@ func Create(ctx context.Context, _store store.Store, repo *model.Repo, pipeline
return nil, errors.New(msg)
}
if pipeline.Event == model.EventPush || pipeline.IsPullRequest() {
skipMatch := skipPipelineRegex.FindString(pipeline.Message)
if len(skipMatch) > 0 {
ref := pipeline.Commit
if len(ref) == 0 {
ref = pipeline.Ref
}
log.Debug().Str("repo", repo.FullName).Msgf("ignoring pipeline as skip-ci was found in the commit (%s) message '%s'", ref, pipeline.Message)
return nil, ErrFiltered
if constraint.IsSkipCommitMessage(metadata.Event(pipeline.Event), pipeline.Message) {
ref := pipeline.Commit
if len(ref) == 0 {
ref = pipeline.Ref
}
log.Debug().Str("repo", repo.FullName).Msgf("ignoring pipeline as skip-ci was found in the commit (%s) message '%s'", ref, pipeline.Message)
return nil, ErrFiltered
}
_forge, err := server.Config.Services.Manager.ForgeFromRepo(repo)
+2 -2
View File
@@ -53,9 +53,9 @@ func parsePipeline(ctx context.Context, forge forge.Forge, store store.Store, cu
var secrets []compiler.Secret
for _, sec := range secs {
var events []string
var events []pipeline_metadata.Event
for _, event := range sec.Events {
events = append(events, string(event))
events = append(events, pipeline_metadata.Event(event))
}
secrets = append(secrets, compiler.Secret{
+1 -1
View File
@@ -112,7 +112,7 @@ func metadataPipelineFromModelPipeline(pipeline *model.Pipeline, includeParent b
Started: pipeline.Started,
Finished: pipeline.Finished,
Status: string(pipeline.Status),
Event: string(pipeline.Event),
Event: metadata.Event(pipeline.Event),
EventReason: pipeline.EventReason,
ForgeURL: pipeline.ForgeURL,
DeployTo: pipeline.DeployTo,