Provide global environment variables for pipeline substitution (#968)

* make global environment variables available for pipeline substitution

* lint fixes

* global env support in cli exec; procBuilder tests

* drop GLOBAL_ prefix

* docs

* documentation typo

* Update docs/docs/20-usage/50-environment.md

as suggested by anbraten

Co-authored-by: Anbraten <anton@ju60.de>

Co-authored-by: 6543 <6543@obermui.de>
Co-authored-by: Anbraten <anton@ju60.de>
This commit is contained in:
Arno Hautala 2022-07-30 02:06:03 -04:00 committed by GitHub
parent 6351684070
commit d5e31dc187
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 97 additions and 2 deletions

View file

@ -110,6 +110,11 @@ func execWithAxis(c *cli.Context, file, repoPath string, axis matrix.Axis) error
for _, env := range c.StringSlice("env") {
envs := strings.SplitN(env, "=", 2)
droneEnv[envs[0]] = envs[1]
if _, exists := environ[envs[0]]; exists {
// don't override existing values
continue
}
environ[envs[0]] = envs[1]
}
tmpl, err := envsubst.ParseFile(file)

View file

@ -125,9 +125,9 @@ This is the reference list of all environment variables available to your pipeli
## Global environment variables
If you want specific environment variables to be available in all of your builds use the `WOODPECKER_ENVIRONMENT` setting on the Woodpecker server.
If you want specific environment variables to be available in all of your builds use the `WOODPECKER_ENVIRONMENT` setting on the Woodpecker server. Note that these can't overwrite any existing, built-in variables.
```.diff
```diff
services:
woodpecker-server:
[...]
@ -136,6 +136,19 @@ services:
+ - WOODPECKER_ENVIRONMENT=first_var:value1,second_var:value2
```
These can be used, for example, to manage the image tag used by multiple projects.
```diff
pipeline:
build:
- image: golang:1.18
+ image: golang:${GOLANG_VERSION}
commands:
- [...]
environment:
- [...]
+ - WOODPECKER_ENVIRONMENT=GOLANG_VERSION:1.18
## String Substitution
Woodpecker provides the ability to substitute environment variables at runtime. This gives us the ability to use dynamic build or commit details in our pipeline configuration.

View file

@ -89,6 +89,15 @@ func (b *ProcBuilder) Build() ([]*BuildItem, error) {
metadata := metadataFromStruct(b.Repo, b.Curr, b.Last, proc, b.Link)
environ := b.environmentVariables(metadata, axis)
// add global environment variables for substituting
for k, v := range b.Envs {
if _, exists := environ[k]; exists {
// don't override existing values
continue
}
environ[k] = v
}
// substitute vars
substituted, err := b.envsubst(string(y.Data), environ)
if err != nil {

View file

@ -24,6 +24,74 @@ import (
// TODO(974) move to pipeline/*
func TestGlobalEnvsubst(t *testing.T) {
t.Parallel()
b := ProcBuilder{
Envs: map[string]string{
"KEY_K": "VALUE_V",
"IMAGE": "scratch",
},
Repo: &model.Repo{},
Curr: &model.Build{
Message: "aaa",
},
Last: &model.Build{},
Netrc: &model.Netrc{},
Secs: []*model.Secret{},
Regs: []*model.Registry{},
Link: "",
Yamls: []*remote.FileMeta{
{Data: []byte(`
pipeline:
build:
image: ${IMAGE}
yyy: ${CI_COMMIT_MESSAGE}
`)},
},
}
if buildItems, err := b.Build(); err != nil {
t.Fatal(err)
} else {
fmt.Println(buildItems)
}
}
func TestMissingGlobalEnvsubst(t *testing.T) {
t.Parallel()
b := ProcBuilder{
Envs: map[string]string{
"KEY_K": "VALUE_V",
"NO_IMAGE": "scratch",
},
Repo: &model.Repo{},
Curr: &model.Build{
Message: "aaa",
},
Last: &model.Build{},
Netrc: &model.Netrc{},
Secs: []*model.Secret{},
Regs: []*model.Registry{},
Link: "",
Yamls: []*remote.FileMeta{
{Data: []byte(`
pipeline:
build:
image: ${IMAGE}
yyy: ${CI_COMMIT_MESSAGE}
`)},
},
}
if _, err := b.Build(); err != nil {
fmt.Println("test rightfully failed")
} else {
t.Fatal("test erroneously succeeded")
}
}
func TestMultilineEnvsubst(t *testing.T) {
t.Parallel()