Fix pipeline source information ()

This commit is contained in:
Robert Kaussow 2025-03-26 13:20:30 +01:00 committed by GitHub
parent c392250384
commit 23a7b2f17d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 58 additions and 98 deletions
cmd/agent/core
docs
docs
20-usage
30-administration/10-configuration/11-backends
src/pages
pipeline
server

View File

@ -247,12 +247,10 @@ func run(ctx context.Context, c *cli.Command, backends []types.Backend) error {
// set default labels ...
labels := make(map[string]string)
for label := range pipeline.ManagedLabels {
labels[label] = "*"
}
labels[pipeline.LabelHostname] = hostname
labels[pipeline.LabelPlatform] = engInfo.Platform
labels[pipeline.LabelBackend] = backendEngine.Name()
labels[pipeline.LabelFilterHostname] = hostname
labels[pipeline.LabelFilterPlatform] = engInfo.Platform
labels[pipeline.LabelFilterBackend] = backendEngine.Name()
labels[pipeline.LabelFilterRepo] = "*" // allow all repos by default
// ... and let it overwrite by custom ones
maps.Copy(labels, customLabels)

View File

@ -594,34 +594,24 @@ For more details check the [matrix build docs](./30-matrix-workflows.md).
## `labels`
Use labels to select the agent that executes your workflow. An agent will execute a workflow only if **all** its assigned labels match the workflow's labels. For Kubernetes agents, these labels propagate to any related resources created during pipeline execution, including pods and secrets.
To configure additional agent labels, see the [agent configuration options](../30-administration/10-configuration/30-agent.md#agent_labels). Agents have pre-configured filters for the following labels:
You can define labels for your workflow in order to select an agent to execute the workflow. An agent takes up a workflow and executes it if **every** label assigned to it matches the label of the agent.
| Label | Description | Woodpecker managed |
|------------------------------------|--------------------------------------------------------------------|--------------------|
| `woodpecker-ci.org/forge-id` | Internal Forge identifier | 🤖 yes |
| `woodpecker-ci.org/repo-forge-id` | Repository identifier from the Forge | 🤖 yes |
| `woodpecker-ci.org/repo-id` | Internal repository identifier | 🤖 yes |
| `woodpecker-ci.org/repo-name` | Repository display name (excluding project/organization) | 🤖 yes |
| `woodpecker-ci.org/repo-full-name` | Repository display name (including project/organization) | 🤖 yes |
| `woodpecker-ci.org/branch` | Git branch name | 🤖 yes |
| `woodpecker-ci.org/org-id` | Internal organization/project identifier | 🤖 yes |
| `repo` | (deprecated) Combined repository and project name (`org/git_repo`) | 🤖 yes |
| `platform` | (deprecated) Agent OS and CPU architecture (e.g., `linux/amd64`) | 🧑‍💻 no |
| `hostname` | Agent name | 🧑‍💻 no |
| `backend` | Agent's backend technology (kubernetes, docker, local) | 🧑‍💻 no |
| `org-id` | Internal organization/project identifier | 🤖 yes |
To specify additional agent labels, check the [Agent configuration options] (../30-administration/10-configuration/30-agent.md#agent_labels). The agents have at least four default labels: `platform=agent-os/agent-arch`, `hostname=my-agent`, `backend=docker` (type of agent backend) and `repo=*`. Agents can use an `*` as a placeholder for a label. For example, `repo=*` matches any repo.
You can add more labels as key-value pairs under the `labels` field in your pipeline. Labels marked as Woodpecker managed can not be set as part of the pipeline definition. Labels with empty values are ignored.
Workflow labels with an empty value are ignored.
By default, each workflow has at least the label `repo=your-user/your-repo-name`. If you have set the [platform attribute](#platform) for your workflow, it will also have a label such as `platform=your-os/your-arch`.
Specifying the [platform attribute](#platform) for your workflow automatically adds a corresponding `woodpecker-ci.org/platform` label, such as `woodpecker-ci.org/platform=your-os/your-arch`.
:::warning
Labels with the `woodpecker-ci.org` prefix are managed by Woodpecker and can not be set as part of the pipeline definition.
:::
You can add additional labels as a key value map:
```diff
+labels:
+ location: europe # Only agents with `location=europe` or `location=*` will execute this workflow.
+ location: europe # only agents with `location=europe` or `location=*` will be used
+ weather: sun
+ hostname: "" # Ignored because the value is empty.
+ woodpecker-ci.org/forge-id: 1 # Ignored because it sets a managed label.
+ hostname: "" # this label will be ignored as it is empty
steps:
- name: build

View File

@ -6,6 +6,20 @@ toc_max_heading_level: 2
The Kubernetes backend executes steps inside standalone Pods. A temporary PVC is created for the lifetime of the pipeline to transfer files between steps.
## Metadata labels
Woodpecker adds some labels to the pods to provide additional context to the workflow. These labels can be used for various purposes, e.g. for simple debugging or as selectors for network policies.
The following metadata labels are supported:
- `woodpecker-ci.org/forge-id`
- `woodpecker-ci.org/repo-forge-id`
- `woodpecker-ci.org/repo-id`
- `woodpecker-ci.org/repo-name`
- `woodpecker-ci.org/repo-full-name`
- `woodpecker-ci.org/branch`
- `woodpecker-ci.org/org-id`
## Private registries
In addition to [registries specified in the UI](../../../20-usage/41-registries.md), you may provide [registry credentials in Kubernetes Secrets](https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/) to pull private container images defined in your pipeline YAML.

View File

@ -5,16 +5,6 @@ To enhance the usability of Woodpecker and meet evolving security standards, occ
## `next`
- (Kubernetes) Deprecated `step` label on pod in favor of new namespaced label `woodpecker-ci.org/step`. The `step` label will be removed in a future update.
- Deprecated several labels in favor of equivalents with the `woodpecker-ci.org/` prefix. The deprecated labels will be removed in a future update.
The following labels are affected:
| Deprecated labels | New labels |
| ----------------- | ---------------------------------- |
| `repo` | `woodpecker-ci.org/repo-full-name` |
| `platform` | `woodpecker-ci.org/platform` |
| `hostname` | `woodpecker-ci.org/hostname` |
| `backend` | `woodpecker-ci.org/backend` |
| `org-id` | `woodpecker-ci.org/org-id` |
## 3.0.0

View File

@ -29,18 +29,9 @@ const (
LabelRepoFullName string = InternalLabelPrefix + "/repo-full-name"
LabelBranch string = InternalLabelPrefix + "/branch"
LabelOrgID string = InternalLabelPrefix + "/org-id"
LabelPlatform string = "platform"
LabelHostname string = "hostname"
LabelBackend string = "backend"
LabelFilterOrg string = "org-id"
LabelFilterRepo string = "repo"
LabelFilterPlatform string = "platform"
LabelFilterHostname string = "hostname"
LabelFilterBackend string = "backend"
)
// ManagedLabels is a list of all labels added automatically to tasks by Woodpecker.
var ManagedLabels = map[string]bool{
LabelForgeRemoteID: true,
LabelRepoForgeID: true,
LabelRepoID: true,
LabelRepoName: true,
LabelRepoFullName: true,
LabelBranch: true,
LabelOrgID: true,
}

View File

@ -15,6 +15,9 @@
package grpc
import (
"strings"
pipelineConsts "go.woodpecker-ci.org/woodpecker/v3/pipeline"
"go.woodpecker-ci.org/woodpecker/v3/pipeline/rpc"
"go.woodpecker-ci.org/woodpecker/v3/server/model"
"go.woodpecker-ci.org/woodpecker/v3/server/queue"
@ -22,6 +25,13 @@ import (
func createFilterFunc(agentFilter rpc.Filter) queue.FilterFn {
return func(task *model.Task) (bool, int) {
// ignore internal labels for filtering
for k := range task.Labels {
if strings.HasPrefix(k, pipelineConsts.InternalLabelPrefix) {
delete(task.Labels, k)
}
}
score := 0
for taskLabel, taskLabelValue := range task.Labels {
// if a task label is empty it will be ignored

View File

@ -28,7 +28,6 @@ import (
"github.com/rs/zerolog/log"
grpcMetadata "google.golang.org/grpc/metadata"
pipelineConsts "go.woodpecker-ci.org/woodpecker/v3/pipeline"
"go.woodpecker-ci.org/woodpecker/v3/pipeline/rpc"
"go.woodpecker-ci.org/woodpecker/v3/server"
"go.woodpecker-ci.org/woodpecker/v3/server/forge"
@ -52,44 +51,12 @@ type RPC struct {
pipelineCount *prometheus.CounterVec
}
// Replaces legacy filter labels with new ones.
func migrateFilterLabels(filter rpc.Filter) rpc.Filter {
if value, ok := filter.Labels["repo"]; ok {
filter.Labels[pipelineConsts.LabelRepoFullName] = value
delete(filter.Labels, "repo")
}
if value, ok := filter.Labels["platform"]; ok {
filter.Labels[pipelineConsts.LabelPlatform] = value
delete(filter.Labels, "platform")
}
if value, ok := filter.Labels["hostname"]; ok {
filter.Labels[pipelineConsts.LabelHostname] = value
delete(filter.Labels, "hostname")
}
if value, ok := filter.Labels["backend"]; ok {
filter.Labels[pipelineConsts.LabelBackend] = value
delete(filter.Labels, "backend")
}
if value, ok := filter.Labels["org-id"]; ok {
filter.Labels[pipelineConsts.LabelOrgID] = value
delete(filter.Labels, "org-id")
}
return filter
}
// Next blocks until it provides the next workflow to execute.
func (s *RPC) Next(c context.Context, agentFilter rpc.Filter) (*rpc.Workflow, error) {
if hostname, err := s.getHostnameFromContext(c); err == nil {
log.Debug().Msgf("agent connected: %s: polling", hostname)
}
agentFilter = migrateFilterLabels(agentFilter)
agent, err := s.getAgentFromContext(c)
if err != nil {
return nil, err

View File

@ -64,9 +64,9 @@ func (a *Agent) GetServerLabels() (map[string]string, error) {
// enforce filters for user and organization agents
if a.OrgID != IDNotSet {
filters[pipeline.LabelOrgID] = fmt.Sprintf("%d", a.OrgID)
filters[pipeline.LabelFilterOrg] = fmt.Sprintf("%d", a.OrgID)
} else {
filters[pipeline.LabelOrgID] = "*"
filters[pipeline.LabelFilterOrg] = "*"
}
return filters, nil

View File

@ -38,7 +38,7 @@ func TestAgent_GetServerLabels(t *testing.T) {
filters, err := agent.GetServerLabels()
assert.NoError(t, err)
assert.Equal(t, map[string]string{
pipeline.LabelOrgID: "0",
pipeline.LabelFilterOrg: "0",
}, filters)
})
@ -49,7 +49,7 @@ func TestAgent_GetServerLabels(t *testing.T) {
filters, err := agent.GetServerLabels()
assert.NoError(t, err)
assert.Equal(t, map[string]string{
pipeline.LabelOrgID: "*",
pipeline.LabelFilterOrg: "*",
}, filters)
})
@ -60,7 +60,7 @@ func TestAgent_GetServerLabels(t *testing.T) {
filters, err := agent.GetServerLabels()
assert.NoError(t, err)
assert.Equal(t, map[string]string{
pipeline.LabelOrgID: "123",
pipeline.LabelFilterOrg: "123",
}, filters)
})
}

View File

@ -50,8 +50,8 @@ func (t *Task) ApplyLabelsFromRepo(r *Repo) error {
if t.Labels == nil {
t.Labels = make(map[string]string)
}
t.Labels[pipeline.LabelRepoFullName] = r.FullName
t.Labels[pipeline.LabelOrgID] = fmt.Sprintf("%d", r.OrgID)
t.Labels[pipeline.LabelFilterRepo] = r.FullName
t.Labels[pipeline.LabelFilterOrg] = fmt.Sprintf("%d", r.OrgID)
return nil
}

View File

@ -41,8 +41,8 @@ func TestTask_GetLabels(t *testing.T) {
assert.NoError(t, err)
assert.NotNil(t, task.Labels)
assert.Equal(t, map[string]string{
pipeline.LabelRepoFullName: "",
pipeline.LabelOrgID: "0",
pipeline.LabelFilterRepo: "",
pipeline.LabelFilterOrg: "0",
}, task.Labels)
})
@ -59,8 +59,8 @@ func TestTask_GetLabels(t *testing.T) {
assert.NoError(t, err)
assert.NotNil(t, task.Labels)
assert.Equal(t, map[string]string{
pipeline.LabelRepoFullName: "test/repo",
pipeline.LabelOrgID: "456",
pipeline.LabelFilterRepo: "test/repo",
pipeline.LabelFilterOrg: "456",
}, task.Labels)
})
@ -81,9 +81,9 @@ func TestTask_GetLabels(t *testing.T) {
assert.NoError(t, err)
assert.NotNil(t, task.Labels)
assert.Equal(t, map[string]string{
"existing": "label",
pipeline.LabelRepoFullName: "test/repo",
pipeline.LabelOrgID: "456",
"existing": "label",
pipeline.LabelFilterRepo: "test/repo",
pipeline.LabelFilterOrg: "456",
}, task.Labels)
})
}