Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(provider): support gitlab-ci #74

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ jobs:
- [multiple plugins published from one repo](https://github.com/ahmetb/kubectx/blob/master/.github/workflows/release.yml)
- [circle-ci](examples/circleci.yml)
- [travis-ci](examples/travis.yml)
- [gitlab-ci](examples/gitabci.yml)

# Testing the template file

Expand Down
18 changes: 18 additions & 0 deletions examples/gitlabci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
variables:
## KREW_RELEASE_BOT_WEBHOOK_URL env helps you test your setup without actually publishing to kubernetes-sigs/krew-index
## remove this env when you are ready for real release
KREW_RELEASE_BOT_WEBHOOK_URL: "https://krew-release-bot-dryrun.rajatjindal.com/github-action-webhook2"
KREW_RELEASE_BOT_VERSION: "v0.0.46"

stages:
- release

update-krew-index:
stage: release
script:
- echo "using krew-release-bot version ${KREW_RELEASE_BOT_VERSION}"
- curl -LO https://github.com/rajatjindal/krew-release-bot/releases/download/${KREW_RELEASE_BOT_VERSION}/krew-release-bot_${KREW_RELEASE_BOT_VERSION}_linux_amd64.tar.gz
- tar -xvf krew-release-bot_${KREW_RELEASE_BOT_VERSION}_linux_amd64.tar.gz
- ./krew-release-bot action
rules:
- if: '$CI_COMMIT_TAG =~ /^v[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9-\.]+)?$/'
76 changes: 76 additions & 0 deletions pkg/cicd/gitlabci/gitlabci.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package gitlabci

import (
"fmt"
"os"
"path/filepath"
"strings"
)

// Provider implements provider interface
type Provider struct{}

func (p *Provider) IsPreRelease(owner, repo, tag string) (bool, error) {
// gitlab doesn't have Prerelease.
return false, nil
}

// GetTag returns tag
func (p *Provider) GetTag() (string, error) {
ref := os.Getenv("CI_COMMIT_TAG")
if ref == "" {
return "", fmt.Errorf("CI_COMMIT_TAG env variable not found")
}

return ref, nil
}

// GetOwnerAndRepo gets the owner and repo from the env
func (p *Provider) GetOwnerAndRepo() (string, string, error) {
owner := os.Getenv("CI_PROJECT_NAMESPACE")
if owner == "" {
return "", "", fmt.Errorf("env CI_PROJECT_NAMESPACE not set")
}

repo := os.Getenv("CI_PROJECT_NAME")
if repo == "" {
return "", "", fmt.Errorf("env CI_PROJECT_NAME not set")
}

return owner, repo, nil
}

// GetActor gets the owner and repo from the env
func (p *Provider) GetActor() (string, error) {
actor := os.Getenv("GITLAB_USER_LOGIN")
if actor == "" {
return "", fmt.Errorf("env GITLAB_USER_LOGIN not set")
}

return actor, nil
}

// getInputForAction gets input to action
func getInputForAction(key string) string {
return os.Getenv(fmt.Sprintf("INPUT_%s", strings.ToUpper(key)))
}

// GetWorkDirectory gets workdir
func (p *Provider) GetWorkDirectory() string {
workdirInput := getInputForAction("workdir")
if workdirInput != "" {
return workdirInput
}

return os.Getenv("CI_PROJECT_DIR")
}

// GetTemplateFile returns the template file
func (p *Provider) GetTemplateFile() string {
templateFile := getInputForAction("krew_template_file")
if templateFile != "" {
return filepath.Join(p.GetWorkDirectory(), templateFile)
}

return filepath.Join(p.GetWorkDirectory(), ".krew.yaml")
}
228 changes: 228 additions & 0 deletions pkg/cicd/gitlabci/gitlabci_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,228 @@
package gitlabci

import (
"os"
"testing"

"github.com/stretchr/testify/assert"
)

func TestGetOwnerAndRepo(t *testing.T) {
testcases := []struct {
name string
setup func()
expectedOwner string
expectedRepo string
expectedError string
}{
{
name: "CI_PROJECT_NAMESPACE and CI_PROJECT_NAME is set as expected",
setup: func() {
os.Setenv("CI_PROJECT_NAMESPACE", "foo-bar")
os.Setenv("CI_PROJECT_NAME", "my-awesome-repo")
},
expectedOwner: "foo-bar",
expectedRepo: "my-awesome-repo",
},
{
name: "CI_PROJECT_NAMESPACE is not set",
setup: func() {
os.Unsetenv("CI_PROJECT_NAMESPACE")
os.Setenv("CI_PROJECT_NAME", "my-awesome-repo")
},
expectedError: `env CI_PROJECT_NAMESPACE not set`,
},
{
name: "CI_PROJECT_NAME is not set",
setup: func() {
os.Setenv("CI_PROJECT_NAMESPACE", "foo-bar")
os.Unsetenv("CI_PROJECT_NAME")
},
expectedError: `env CI_PROJECT_NAME not set`,
},
}

p := &Provider{}
for _, tc := range testcases {
t.Run(tc.name, func(t *testing.T) {
os.Clearenv()

if tc.setup != nil {
tc.setup()
}

owner, repo, err := p.GetOwnerAndRepo()

assert.Equal(t, tc.expectedOwner, owner)
assert.Equal(t, tc.expectedRepo, repo)
assertError(t, tc.expectedError, err)
})
}
}

func TestGetActionActor(t *testing.T) {
testcases := []struct {
name string
setup func()
expectedActor string
expectedError string
}{
{
name: "env GITLAB_USER_LOGIN is set as expected",
setup: func() {
os.Setenv("GITLAB_USER_LOGIN", "foo-bar")
},
expectedActor: "foo-bar",
},
{
name: "env GITLAB_USER_LOGIN is not set",
expectedError: "env GITLAB_USER_LOGIN not set",
},
}

p := &Provider{}
for _, tc := range testcases {
t.Run(tc.name, func(t *testing.T) {
os.Clearenv()

if tc.setup != nil {
tc.setup()
}

actor, err := p.GetActor()
assert.Equal(t, tc.expectedActor, actor)
assertError(t, tc.expectedError, err)
})
}
}

func TestGetTag(t *testing.T) {
testcases := []struct {
name string
setup func()
expectedTag string
expectedError string
}{
{
name: "env CI_COMMIT_TAG is setup",
setup: func() {
os.Setenv("CI_COMMIT_TAG", "v5.0.0")
},
expectedTag: "v5.0.0",
},
{
name: "CI_COMMIT_TAG is not set",
setup: func() {
os.Unsetenv("CI_COMMIT_TAG")
},
expectedError: `CI_COMMIT_TAG env variable not found`,
},
}

p := &Provider{}
for _, tc := range testcases {
t.Run(tc.name, func(t *testing.T) {
os.Clearenv()

if tc.setup != nil {
tc.setup()
}

tag, err := p.GetTag()
assert.Equal(t, tc.expectedTag, tag)
assertError(t, tc.expectedError, err)
})
}
}

func assertError(t *testing.T, expectedError string, err error) {
if expectedError == "" {
assert.Nil(t, err)
}

if expectedError != "" {
assert.NotNil(t, err)
if err != nil {
assert.Equal(t, expectedError, err.Error())
}
}
}

func TestGetWorkingDirectory(t *testing.T) {
testcases := []struct {
name string
setup func()
expectedDir string
}{
{
name: "env CI_PROJECT_DIR is setup",
setup: func() {
os.Setenv("CI_PROJECT_DIR", "/builds/foo-bar/my-awesome-repo")
},
expectedDir: "/builds/foo-bar/my-awesome-repo",
}, {
name: "env CI_PROJECT_DIR is setup",
setup: func() {
os.Setenv("CI_PROJECT_DIR", "/builds/foo-bar/my-awesome-repo")
os.Setenv("INPUT_WORKDIR", "/my-workdir")
},
expectedDir: "/my-workdir",
}, {
name: "env CI_PROJECT_DIR is not set",
setup: func() {
os.Unsetenv("CI_PROJECT_DIR")
},
expectedDir: "",
},
}

p := &Provider{}
for _, tc := range testcases {
t.Run(tc.name, func(t *testing.T) {
os.Clearenv()

if tc.setup != nil {
tc.setup()
}

dir := p.GetWorkDirectory()
assert.Equal(t, tc.expectedDir, dir)
})
}
}

func TestGetTemplateFile(t *testing.T) {
testcases := []struct {
name string
setup func()
expectFile string
}{
{
name: "env INPUT_KREW_TEMPLATE_FILE is setup",
setup: func() {
os.Setenv("INPUT_KREW_TEMPLATE_FILE", "my-awesome-plugin.yaml")
},
expectFile: "my-awesome-plugin.yaml",
}, {
name: "env INPUT_KREW_TEMPLATE_FILE is not set",
setup: func() {
os.Unsetenv("INPUT_KREW_TEMPLATE_FILE")
},
expectFile: ".krew.yaml",
},
}

p := &Provider{}
for _, tc := range testcases {
t.Run(tc.name, func(t *testing.T) {
os.Clearenv()

if tc.setup != nil {
tc.setup()
}

dir := p.GetTemplateFile()
assert.Equal(t, tc.expectFile, dir)
})
}
}
7 changes: 6 additions & 1 deletion pkg/cicd/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (

"github.com/rajatjindal/krew-release-bot/pkg/cicd/circleci"
"github.com/rajatjindal/krew-release-bot/pkg/cicd/github"
"github.com/rajatjindal/krew-release-bot/pkg/cicd/gitlabci"
"github.com/rajatjindal/krew-release-bot/pkg/cicd/travisci"
)

Expand All @@ -19,8 +20,12 @@ type Provider interface {
}

// GetProvider returns the CI/CD provider
// e.g. github-actions or circle-ci
// e.g. github-actions, travis-ci, circle-ci or gitlab-ci
func GetProvider() Provider {
if os.Getenv("GITLAB_CI") == "true" {
return &gitlabci.Provider{}
}

if os.Getenv("GITHUB_ACTIONS") == "true" {
return &github.Actions{}
}
Expand Down