Skip to content

Commit

Permalink
DRONE_ and CI_ variable references must convert to a Harness expressi…
Browse files Browse the repository at this point in the history
…ons (#118)

* drone and ci variables references convert to harness expressions

---------

Co-authored-by: Jim Sheldon <jim.sheldon@gmail.com>
  • Loading branch information
eoinmcafee00 and jimsheldon committed Jun 26, 2023
1 parent c1069a6 commit adea84d
Show file tree
Hide file tree
Showing 4 changed files with 207 additions and 2 deletions.
39 changes: 37 additions & 2 deletions convert/drone/convert.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,24 @@ type Converter struct {
orgSecrets []string
}

var variableMap = map[string]string{
"DRONE_BRANCH": "<+codebase.branch>",
"DRONE_BUILD_NUMBER": "<+pipeline.sequenceId>",
"DRONE_COMMIT_AUTHOR": "<+codebase.gitUserId>",
"DRONE_COMMIT_BRANCH": "<+codebase.branch>",
"DRONE_COMMIT_SHA": "<+codebase.commitSha>",
"DRONE_PULL_REQUEST": "<+codebase.prNumber>",
"DRONE_PULL_REQUEST_TITLE": "<+codebase.prTitle>",
"DRONE_REMOTE_URL": "<+codebase.repoUrl>",
"DRONE_REPO_NAME": "<+<+codebase.repoUrl>.substring(<+codebase.repoUrl>.lastIndexOf('/') + 1)>",
"CI_BUILD_NUMBER": "<+pipeline.sequenceId>",
"CI_COMMIT_AUTHOR": "<+codebase.gitUserId>",
"CI_COMMIT_BRANCH": "<+codebase.branch>",
"CI_COMMIT_SHA": "<+codebase.commitSha>",
"CI_REMOTE_URL": "<+codebase.repoUrl>",
"CI_REPO_NAME": "<+<+codebase.repoUrl>.substring(<+codebase.repoUrl>.lastIndexOf('/') + 1)>",
}

// New creates a new Converter that converts a Drone
// pipeline to a Harness v1 pipeline.
func New(options ...Option) *Converter {
Expand Down Expand Up @@ -430,6 +448,8 @@ func convertSettings(src map[string]*v1.Parameter, orgSecrets []string) map[stri

func convertInterface(i interface{}) interface{} {
switch v := i.(type) {
case string:
return replaceVars(v)
case map[interface{}]interface{}:
newMap := make(map[string]interface{})
for key, value := range v {
Expand All @@ -448,12 +468,27 @@ func convertInterface(i interface{}) interface{} {
return i
}

func replaceVars(val string) string {
var re = regexp.MustCompile(`\$\$?({)?(\w+)(})?`)
return re.ReplaceAllStringFunc(val, func(match string) string {
varName := strings.Trim(match, "${}$")
if harnessVar, ok := variableMap[varName]; ok {
return harnessVar
}
return match
})
}

func convertScript(src []string) string {
if len(src) == 0 {
return ""
} else {
return strings.Join(src, "\n")
}

for i, cmd := range src {
src[i] = replaceVars(cmd)
}

return strings.Join(src, "\n")
}

func convertArgs(src1, src2 []string) []string {
Expand Down
105 changes: 105 additions & 0 deletions convert/drone/convert_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,108 @@ func TestConvert(t *testing.T) {
})
}
}

func TestReplaceVars(t *testing.T) {
tests := []struct {
name string
input string
expected string
}{
{
name: "DRONE_COMMIT_SHA",
input: "${DRONE_COMMIT_SHA}",
expected: "<+codebase.commitSha>",
},
{
name: "DRONE_COMMIT_SHA without braces",
input: "$DRONE_COMMIT_SHA",
expected: "<+codebase.commitSha>",
},
{
name: "CI_COMMIT_SHA",
input: "${CI_COMMIT_SHA}",
expected: "<+codebase.commitSha>",
},
{
name: "CI_COMMIT_SHA without braces",
input: "$CI_COMMIT_SHA",
expected: "<+codebase.commitSha>",
},
{
name: "Escaped DRONE_COMMIT_SHA",
input: "$${DRONE_COMMIT_SHA}",
expected: "<+codebase.commitSha>",
},
{
name: "Escaped DRONE_COMMIT_SHA without braces",
input: "$$DRONE_COMMIT_SHA",
expected: "<+codebase.commitSha>",
},
{
name: "Non-mapped variable",
input: "${DRONE_BUILD_ACTION}",
expected: "${DRONE_BUILD_ACTION}",
},
// Known Mappings
{
name: "DRONE_BRANCH",
input: "${DRONE_BRANCH}",
expected: "<+codebase.branch>",
},
{
name: "DRONE_BUILD_NUMBER",
input: "${DRONE_BUILD_NUMBER}",
expected: "<+pipeline.sequenceId>",
},
{
name: "DRONE_COMMIT_AUTHOR",
input: "${DRONE_COMMIT_AUTHOR}",
expected: "<+codebase.gitUserId>",
},
{
name: "DRONE_COMMIT_BRANCH",
input: "${DRONE_COMMIT_BRANCH}",
expected: "<+codebase.branch>",
},
{
name: "DRONE_COMMIT_SHA",
input: "${DRONE_COMMIT_SHA}",
expected: "<+codebase.commitSha>",
},
{
name: "DRONE_PULL_REQUEST",
input: "${DRONE_PULL_REQUEST}",
expected: "<+codebase.prNumber>",
},
{
name: "DRONE_PULL_REQUEST_TITLE",
input: "${DRONE_PULL_REQUEST_TITLE}",
expected: "<+codebase.prTitle>",
},
{
name: "DRONE_REMOTE_URL",
input: "${DRONE_REMOTE_URL}",
expected: "<+codebase.repoUrl>",
},
{
name: "DRONE_REPO_NAME",
input: "${DRONE_REPO_NAME}",
expected: "<+<+codebase.repoUrl>.substring(<+codebase.repoUrl>.lastIndexOf('/') + 1)>",
},
// Unknown Mappings
{
name: "DRONE_BUILD_ACTION",
input: "${DRONE_BUILD_ACTION}",
expected: "${DRONE_BUILD_ACTION}", // Expect same input string for unknown mappings
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
output := replaceVars(tt.input)
if output != tt.expected {
t.Errorf("Expected %q, got %q", tt.expected, output)
}
})
}
}
27 changes: 27 additions & 0 deletions convert/drone/testdata/examples/variable.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: default
type: docker
kind: pipeline

steps:
- name: example
image: busybox
commands:
- echo this is build number $DRONE_BUILD_NUMBER
- echo commit author is $DRONE_COMMIT_AUTHOR
- echo branch is $DRONE_BRANCH
- echo this is pull request number $DRONE_PULL_REQUEST
- echo repo name is $DRONE_REPO_NAME

- name: publish
image: plugins/docker
settings:
repo: gcr.io/example/repo
tags:
- 1.0.${DRONE_BUILD_NUMBER}
- ${DRONE_BRANCH}-${DRONE_COMMIT_SHA}

- name: notify
image: plugins/slack
settings:
channel: builds
message: Build $DRONE_BUILD_NUMBER completed
38 changes: 38 additions & 0 deletions convert/drone/testdata/examples/variable.yaml.golden
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: default
options: {}
stages:
- name: default
spec:
clone: {}
runtime:
spec: {}
type: machine
steps:
- name: example
spec:
image: busybox
run: |-
echo this is build number <+pipeline.sequenceId>
echo commit author is <+codebase.gitUserId>
echo branch is <+codebase.branch>
echo this is pull request number <+codebase.prNumber>
echo repo name is <+<+codebase.repoUrl>.substring(<+codebase.repoUrl>.lastIndexOf('/') + 1)>
type: script
- name: publish
spec:
image: plugins/docker
with:
repo: gcr.io/example/repo
tags:
- 1.0.<+pipeline.sequenceId>
- <+codebase.branch>-<+codebase.commitSha>
type: plugin
- name: notify
spec:
image: plugins/slack
with:
channel: builds
message: Build <+pipeline.sequenceId> completed
type: plugin
type: ci
version: 1

0 comments on commit adea84d

Please sign in to comment.