1
0
Fork 0

Add secrets and plugin settings

This commit is contained in:
Lauris BH 2022-07-29 02:11:24 +03:00
parent 0a65c9a464
commit 6c871d13d1
No known key found for this signature in database
GPG Key ID: DFDE60A0093EB926
9 changed files with 145 additions and 12 deletions

View File

@ -5,19 +5,32 @@
package core
import (
"fmt"
"strings"
)
type ValueOrSecret struct {
Value string
Secret string
}
// MapOrEnvArray represents a map or an array of strings as environment variables.
type MapOrEnvArray map[string]string
type MapOrEnvArray map[string]ValueOrSecret
// UnmarshalYAML implements the Unmarshaler interface.
func (m *MapOrEnvArray) UnmarshalYAML(unmarshal func(interface{}) error) error {
mv := make(MapOrEnvArray)
t := make(map[string]string)
t := make(map[string]interface{})
if err := unmarshal(&t); err == nil {
for k, v := range t {
mv[k] = v
switch vv := v.(type) {
case map[string]interface{}:
if val, ok := vv["from_secret"]; ok {
mv[k] = ValueOrSecret{Secret: fmt.Sprintf("%v", val)}
}
default:
mv[k] = ValueOrSecret{Value: fmt.Sprintf("%v", vv)}
}
}
*m = mv
return nil
@ -31,7 +44,7 @@ func (m *MapOrEnvArray) UnmarshalYAML(unmarshal func(interface{}) error) error {
if !ok {
continue
}
mv[k] = v
mv[k] = ValueOrSecret{Value: v}
}
*m = mv
return nil
@ -41,7 +54,7 @@ func (m *MapOrEnvArray) UnmarshalYAML(unmarshal func(interface{}) error) error {
func (m MapOrEnvArray) MarshalYAML() (interface{}, error) {
arr := make([]string, 0)
for k, v := range m {
arr = append(arr, k+"="+v)
arr = append(arr, k+"="+v.Value)
}
return arr, nil
}

View File

@ -15,11 +15,11 @@ func TestMapUnmarshal(t *testing.T) {
v := &struct {
Environment MapOrEnvArray `yaml:"environment"`
}{}
err := yaml.Unmarshal([]byte("environment:\n FOO: bar\n BAZ: qux\n"), v)
err := yaml.Unmarshal([]byte("environment:\n FOO:\n from_secret: bar\n BAZ: 2\n"), v)
assert.NoError(t, err)
assert.Equal(t, MapOrEnvArray{
"FOO": "bar",
"BAZ": "qux",
"FOO": ValueOrSecret{Secret: "bar"},
"BAZ": ValueOrSecret{Value: "2"},
}, v.Environment)
}
@ -30,7 +30,7 @@ func TestArrayUnmarshal(t *testing.T) {
err := yaml.Unmarshal([]byte("environment:\n- FOO=bar\n- BAZ=qux\n"), v)
assert.NoError(t, err)
assert.Equal(t, MapOrEnvArray{
"FOO": "bar",
"BAZ": "qux",
"FOO": ValueOrSecret{Value: "bar"},
"BAZ": ValueOrSecret{Value: "qux"},
}, v.Environment)
}

View File

@ -183,7 +183,20 @@ func (d DronePipeline) Convert(pipeline *Pipeline) (*transform.Pipeline, error)
for _, step := range pipeline.Steps {
env := make([]string, 0, len(step.Environment))
for k, v := range step.Environment {
env = append(env, k+"="+v)
if v.Secret != "" {
continue
}
env = append(env, k+"="+v.Value)
}
secrets := make(transform.Secrets, 0)
for k, v := range step.Environment {
if v.Secret == "" {
continue
}
secrets = append(secrets, transform.Secret{
Target: k,
Source: v.Secret,
})
}
when, err := d.ConvertConditions(step.When)
if err != nil {
@ -194,6 +207,8 @@ func (d DronePipeline) Convert(pipeline *Pipeline) (*transform.Pipeline, error)
Image: d.ConvertImage(step.Image),
Pull: step.Pull == "always",
Environment: env,
Secrets: secrets,
Settings: step.Settings,
Commands: step.Commands,
When: when,
DependsOn: step.DependsOn,

View File

@ -42,7 +42,7 @@ func TestTransformSimple(t *testing.T) {
pipeline := getPipelineByName(pipelines, "build")
require.NotNil(t, pipeline, "build pipeline not found")
require.Len(t, pipeline.Steps, 2)
require.Len(t, pipeline.Steps, 3)
assert.Equal(t, "test", pipeline.Steps[0].Name)
assert.Equal(t, "golang:1.18", pipeline.Steps[0].Image)
assert.ElementsMatch(t, []string{"CGO=0"}, pipeline.Steps[0].Environment)
@ -62,6 +62,20 @@ func TestTransformSimple(t *testing.T) {
assert.Nil(t, pipeline.Steps[1].When)
assert.ElementsMatch(t, []string{"test"}, pipeline.Steps[1].DependsOn)
assert.Equal(t, "docker", pipeline.Steps[2].Name)
assert.Equal(t, "plugin/docker", pipeline.Steps[2].Image)
assert.False(t, pipeline.Steps[2].Pull)
assert.ElementsMatch(t, []string{"build"}, pipeline.Steps[2].DependsOn)
assert.ElementsMatch(t, transform.Settings{
{Name: "repo", Value: "org/simple"},
{Name: "username", Value: map[string]interface{}{
"from_secret": "docker_username",
}},
{Name: "password", Value: map[string]interface{}{
"from_secret": "docker_password",
}},
}, pipeline.Steps[2].Settings)
assert.Len(t, pipeline.DependsOn, 0)
pipeline = getPipelineByName(pipelines, "deploy")
@ -72,6 +86,7 @@ func TestTransformSimple(t *testing.T) {
assert.Equal(t, "alpine:latest", pipeline.Steps[0].Image)
assert.False(t, pipeline.Steps[0].Pull)
assert.Len(t, pipeline.Steps[0].Commands, 1)
assert.ElementsMatch(t, transform.Secrets{{Target: "PASSWORD", Source: "password"}}, pipeline.Steps[0].Secrets)
require.NotNil(t, pipeline.Steps[0].When)
assert.ElementsMatch(t, []string{"success", "failure"}, pipeline.Steps[0].When.Status)
assert.ElementsMatch(t, []string{"tag"}, pipeline.Steps[0].When.Event)

View File

@ -5,6 +5,7 @@
package drone
import (
transform "codeberg.org/lafriks/woodpecker-pipeline-transform"
"codeberg.org/lafriks/woodpecker-pipeline-transform/core"
)
@ -24,6 +25,7 @@ type Step struct {
Image string `yaml:"image"`
Pull string `yaml:"pull"`
Environment core.MapOrEnvArray `yaml:"environment"`
Settings transform.Settings `yaml:"settings,omitempty"`
Commands []string `yaml:"commands"`
DependsOn []string `yaml:"depends_on"`
When *StepWhen `yaml:"when"`

View File

@ -31,6 +31,17 @@ steps:
depends_on:
- test
- name: docker
image: plugin/docker
settings:
repo: org/simple
username:
from_secret: docker_username
password:
from_secret: docker_password
depends_on:
- build
---
kind: pipeline
type: docker
@ -47,6 +58,9 @@ steps:
- name: deploy
image: alpine:latest
pull: if-not-exists
environment:
PASSWORD:
from_secret: password
commands:
- echo "Deploy"
when:

View File

@ -45,7 +45,9 @@ type Step struct {
Image string `yaml:"image"`
Pull bool `yaml:"pull,omitempty"`
Environment []string `yaml:"environment,omitempty"`
Secrets Secrets `yaml:"secrets,omitempty"`
Commands []string `yaml:"commands,omitempty"`
Settings Settings `yaml:"settings,omitempty"`
When *StepWhen `yaml:"when,omitempty"`
DependsOn []string `yaml:"depends_on,omitempty"`
}

29
secrets.go Normal file
View File

@ -0,0 +1,29 @@
// Copyright 2022 Lauris BH. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package transform
import "strings"
type Secret struct {
Source string `yaml:"source"`
Target string `yaml:"target"`
}
type Secrets []Secret
func (s Secrets) MarshalYAML() (interface{}, error) {
arr := make([]interface{}, 0, len(s))
for _, secret := range s {
if secret.Target == "" || strings.ToLower(secret.Source) == strings.ToLower(secret.Target) {
arr = append(arr, Secret{
Source: secret.Source,
Target: strings.ToLower(secret.Target),
})
} else {
arr = append(arr, secret)
}
}
return arr, nil
}

43
settings.go Normal file
View File

@ -0,0 +1,43 @@
// Copyright 2022 Lauris BH. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package transform
import (
"github.com/goccy/go-yaml"
)
type Setting struct {
Name string
Value interface{}
}
type Settings []Setting
func (s Settings) MarshalYAML() (interface{}, error) {
v := make(yaml.MapSlice, len(s))
for i, setting := range s {
v[i] = yaml.MapItem{
Key: setting.Name,
Value: setting.Value,
}
}
return v, nil
}
func (s *Settings) UnmarshalYAML(unmarshal func(interface{}) error) error {
var v yaml.MapSlice
if err := unmarshal(&v); err != nil {
return err
}
val := make(Settings, 0, len(v))
for _, item := range v {
val = append(val, Setting{
Name: item.Key.(string),
Value: item.Value,
})
}
*s = val
return nil
}