From 001ecd3d0d2e9dc8b547be5bdf04e976d0511f12 Mon Sep 17 00:00:00 2001 From: Lauris B Date: Sun, 30 Aug 2026 15:38:43 +0300 Subject: [PATCH] Fix injecting additional variables for substituting (#7077) --- pipeline/frontend/builder/builder.go | 9 +++ pipeline/frontend/builder/builder_test.go | 94 +++++++++++++++++++++++ 2 files changed, 103 insertions(+) diff --git a/pipeline/frontend/builder/builder.go b/pipeline/frontend/builder/builder.go index d33a6d388..ff5e75685 100644 --- a/pipeline/frontend/builder/builder.go +++ b/pipeline/frontend/builder/builder.go @@ -101,6 +101,15 @@ func (b *PipelineBuilder) genItemForWorkflow(workflow *Workflow, axis matrix.Axi workflowMetadata := b.GetWorkflowMetadata(workflow) environ := b.environmentVariables(workflowMetadata, axis) + // add additional environment variables for substituting + for k, v := range b.AdditionalEnvs { + if _, exists := environ[k]; exists { + // don't override existing values + continue + } + environ[k] = v + } + // add global environment variables for substituting for k, v := range b.Envs { if _, exists := environ[k]; exists { diff --git a/pipeline/frontend/builder/builder_test.go b/pipeline/frontend/builder/builder_test.go index 5abe79aa8..43601fcd4 100644 --- a/pipeline/frontend/builder/builder_test.go +++ b/pipeline/frontend/builder/builder_test.go @@ -85,6 +85,100 @@ steps: assert.Error(t, err, "test erroneously succeeded") } +func TestAdditionalEnvsSubstitution(t *testing.T) { + t.Parallel() + + m := &testMetadata{ + pipelineEvent: "manual", + } + + b := PipelineBuilder{ + GetWorkflowMetadata: m.GetWorkflowMetadata, + AdditionalEnvs: map[string]string{ + "TAG": "1.2.3", + }, + RepoTrusted: &metadata.TrustedConfiguration{}, + TrustedClonePlugins: []string{"woodpeckerci/plugin-git"}, + Yamls: []*YamlFile{ + {Data: []byte(` +when: + event: manual +clone: + - name: clone + image: woodpeckerci/plugin-git + settings: + ref: refs/tags/${TAG} +steps: + - name: build + image: scratch + commands: + - go build +`)}, + }, + } + + items, err := b.Build() + assert.NoError(t, err) + assert.Len(t, items, 1) + cloneStep := items[0].Config.Stages[0].Steps[0] + assert.Equal(t, "clone", cloneStep.Name) + assert.Equal(t, "refs/tags/1.2.3", cloneStep.Environment["PLUGIN_REF"], + "additional (manual trigger) variables must be substituted in the yaml") +} + +func TestAdditionalAndMatrixEnvsNotInjectedIntoPlugins(t *testing.T) { + t.Parallel() + + m := &testMetadata{ + pipelineEvent: "manual", + } + + b := PipelineBuilder{ + GetWorkflowMetadata: m.GetWorkflowMetadata, + AdditionalEnvs: map[string]string{ + "TAG": "1.2.3", + }, + RepoTrusted: &metadata.TrustedConfiguration{}, + Yamls: []*YamlFile{ + {Data: []byte(` +when: + event: manual +skip_clone: true +matrix: + GO_VERSION: + - "1.22" +steps: + - name: build + image: scratch + commands: + - go build + - name: publish + image: scratch + settings: + ref: refs/tags/${TAG} +`)}, + }, + } + + items, err := b.Build() + assert.NoError(t, err) + assert.Len(t, items, 1) + + assert.Len(t, items[0].Config.Stages, 2) + buildStep := items[0].Config.Stages[0].Steps[0] + publishStep := items[0].Config.Stages[1].Steps[0] + assert.Equal(t, "build", buildStep.Name) + assert.Equal(t, "publish", publishStep.Name) + + // non-plugin steps get additional (manual trigger) and matrix envs + assert.Equal(t, "1.2.3", buildStep.Environment["TAG"]) + assert.Equal(t, "1.22", buildStep.Environment["GO_VERSION"]) + + // plugin steps must not have them injected to avoid smuggling settings + assert.NotContains(t, publishStep.Environment, "TAG") + assert.NotContains(t, publishStep.Environment, "GO_VERSION") +} + func TestMultilineEnvsubst(t *testing.T) { t.Parallel()