Skip to content

Commit

Permalink
Merge pull request #24 from LinuxSuRen/gitlab-support
Browse files Browse the repository at this point in the history
Add gitlab and gitea support
  • Loading branch information
LinuxSuRen authored Nov 5, 2021
2 parents 7ebe5e1 + c6141f7 commit 3a0d076
Show file tree
Hide file tree
Showing 10 changed files with 203 additions and 96 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,4 @@
bin/
tmp/
.idea/
data/
1 change: 1 addition & 0 deletions api/v1alpha1/releaser_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ const (
ProviderGitlab Provider = "gitlab"
ProviderBitbucket Provider = "bitbucket"
ProviderGitee Provider = "gitee"
ProviderGitea Provider = "gitea"
ProviderUnknown Provider = "unknown"
)

Expand Down
3 changes: 2 additions & 1 deletion api/v1alpha1/releaser_webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package v1alpha1
import (
"errors"
"k8s.io/apimachinery/pkg/runtime"
"reflect"
ctrl "sigs.k8s.io/controller-runtime"
logf "sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/webhook"
Expand Down Expand Up @@ -107,7 +108,7 @@ func (r *Releaser) ValidateUpdate(old runtime.Object) error {
releaserlog.Info("validate update", "name", r.Name)

oldReleaser := old.(*Releaser)
if oldReleaser.Spec.Phase == PhaseDone {
if oldReleaser.Spec.Phase == PhaseDone && !reflect.DeepEqual(oldReleaser.Spec, r.Spec) {
return errors.New("not allow to manipulate this release any more once the phase is done")
}
return nil
Expand Down
49 changes: 31 additions & 18 deletions controllers/git.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package controllers

import (
"errors"
"fmt"
"github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/config"
Expand Down Expand Up @@ -65,37 +64,46 @@ func release(repo devopsv1alpha1.Repository, secret *v1.Secret, user string) (er

var gitRepo *git.Repository
if gitRepo, err = clone(repo.Address, repo.Branch, auth, "tmp"); err != nil {
err = fmt.Errorf("failed to clone %s, error: %v", repo.Address, err)
return
}

if repo.Message == "" {
repo.Message = "released by ks-releaser"
}
if _, err = setTag(gitRepo, repo.Version, repo.Message, user); err != nil {
err = fmt.Errorf("failed to create tag %s for %s, error: %v", repo.Version, repo.Address, err)
return
}

if err = pushTags(gitRepo, repo.Version, auth); err != nil {
err = fmt.Errorf("failed to push tag %s into %s, error: %v", repo.Version, repo.Address, err)
return
}

token := string(secret.Data[v1.BasicAuthPasswordKey])
server := string(secret.Data["server"])
var orgAndRepo string
switch repo.Provider {
case devopsv1alpha1.ProviderGitHub:
orgAndRepo = strings.ReplaceAll(repo.Address, "https://github.com/", "")
case devopsv1alpha1.ProviderGitlab:
orgAndRepo = strings.ReplaceAll(repo.Address, "https://gitlab.com/", "")
orgAndRepo = strings.ReplaceAll(orgAndRepo, ".git", "")
case devopsv1alpha1.ProviderGitea:
orgAndRepo = strings.ReplaceAll(repo.Address, server, "")
}

provider := internal_scm.GetGitProvider(string(repo.Provider), server, orgAndRepo, token)
if provider == nil {
return
}

switch repo.Action {
case devopsv1alpha1.ActionPreRelease:
provider := internal_scm.GetGitProvider(string(repo.Provider), orgAndRepo, string(secret.Data[v1.BasicAuthPasswordKey]))
if provider != nil {
err = provider.Release(repo.Version, repo.Branch, false, true)
}
err = provider.Release(repo.Version, repo.Branch, false, true)
case devopsv1alpha1.ActionRelease:
provider := internal_scm.GetGitProvider(string(repo.Provider), orgAndRepo, string(secret.Data[v1.BasicAuthPasswordKey]))
if provider != nil {
err = provider.Release(repo.Version, repo.Branch, false, false)
}
err = provider.Release(repo.Version, repo.Branch, false, false)
}
return
}
Expand Down Expand Up @@ -164,17 +172,22 @@ func tagExists(tag string, r *git.Repository) bool {
var err error
var tags storer.ReferenceIter
if tags, err = r.Tags(); err == nil {
err = tags.ForEach(func(reference *plumbing.Reference) error {
tagRef := reference.Name()
if tagRef.IsTag() && !tagRef.IsRemote() {
_ = r.DeleteTag(tag)
} else if tagRef.IsTag() && tagRef.IsRemote() && tagRef.String() == tag {
return nil
var ref *plumbing.Reference
for ref, _ = tags.Next(); ref != nil; ref, _ = tags.Next() {
if !ref.Target().IsTag() {
continue
}
return errors.New("not found tag")
})

if ref.Target().String() == tag {
if !ref.Target().IsRemote() {
_ = r.DeleteTag(tag)
return false
}
return true
}
}
}
return err == nil || (err != nil && err.Error() != "not found tag")
return false
}

func setTag(r *git.Repository, tag, message, user string) (bool, error) {
Expand Down
42 changes: 40 additions & 2 deletions controllers/internal_scm/factory.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,54 @@
package internal_scm

import "github.com/kubesphere-sigs/ks-releaser/api/v1alpha1"
import (
"context"
"github.com/jenkins-x/go-scm/scm"
"github.com/kubesphere-sigs/ks-releaser/api/v1alpha1"
)

type GitReleaser interface {
Release(version, commitish string, draft, prerelease bool) (err error)
}

func release(client *scm.Client, repo, version, commitish string, draft, prerelease bool) (err error) {
releaseInput := &scm.ReleaseInput{
Title: version,
Tag: version,
Commitish: commitish,
Draft: draft,
Prerelease: prerelease,
}

// just publish the draft release if it is existing
release := findRelease(client, repo, version)
if release == nil {
_, _, err = client.Releases.Create(context.TODO(), repo, releaseInput)
} else if release.Draft {
releaseInput.Description = release.Description
releaseInput.Title = release.Title
_, _, err = client.Releases.Update(context.TODO(), repo, release.ID, releaseInput)
}
// ignore the existing release
return
}

func findRelease(client *scm.Client, repo, version string) (release *scm.Release) {
var err error
if release, _, err = client.Releases.FindByTag(context.TODO(), repo, version); err != nil {
release = nil
}
return
}

// GetGitProvider returns the GitReleaser implement by kind
func GetGitProvider(kind, repo, token string) GitReleaser {
func GetGitProvider(kind, server, repo, token string) GitReleaser {
switch v1alpha1.Provider(kind) {
case v1alpha1.ProviderGitHub:
return NewGitHub(repo, token)
case v1alpha1.ProviderGitlab:
return NewGitlab(repo, token)
case v1alpha1.ProviderGitea:
return NewGitea(server, repo, token)
}
return nil
}
33 changes: 33 additions & 0 deletions controllers/internal_scm/gitea.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package internal_scm

import (
"fmt"
"github.com/jenkins-x/go-scm/scm"
"github.com/jenkins-x/go-scm/scm/driver/gitea"
)

type Gitea struct {
server string
repo string
token string

client *scm.Client
}

func NewGitea(server, repo, token string) *Gitea {
return &Gitea{
server: server,
repo: repo,
token: token,
}
}

func (r *Gitea) Release(version, commitish string, draft, prerelease bool) (err error) {
var client *scm.Client
if client, err = gitea.NewWithToken(r.server, r.token); err != nil || client == nil {
err = fmt.Errorf("failed to create gitea client, error: %v", err)
} else {
err = release(client, r.repo, version, commitish, draft, prerelease)
}
return
}
45 changes: 2 additions & 43 deletions controllers/internal_scm/github.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package internal_scm

import (
"context"
"github.com/jenkins-x/go-scm/scm"
"github.com/jenkins-x/go-scm/scm/driver/github"
"github.com/jenkins-x/go-scm/scm/transport"
"net/http"
Expand All @@ -22,51 +20,12 @@ func NewGitHub(repo, token string) *GitHub {
}

func (r *GitHub) Release(version, commitish string, draft, prerelease bool) (err error) {
client := r.getClient()

releaseInput := &scm.ReleaseInput{
Title: version,
Tag: version,
Commitish: commitish,
Draft: draft,
Prerelease: prerelease,
}

// just publish the draft release if it is existing
release := r.findDraftRelease(version)
if release != nil {
releaseInput.Description = release.Description
releaseInput.Title = release.Title
_, _, err = client.Releases.Update(context.TODO(), r.repo, release.ID, releaseInput)
} else {
_, _, err = client.Releases.Create(context.TODO(), r.repo, releaseInput)
}
return
}

func (r *GitHub) getClient() (client *scm.Client) {
client = github.NewDefault()
client := github.NewDefault()
client.Client = &http.Client{
Transport: &transport.BearerToken{
Token: r.token,
},
}
err = release(client, r.repo, version, commitish, draft, prerelease)
return
}

func (r *GitHub) findDraftRelease(version string) *scm.Release {
client := r.getClient()

if releaseList, _, err := client.Releases.List(context.TODO(), r.repo, scm.ReleaseListOptions{
Page: 1,
Size: 50,
}); err == nil {
for i, _ := range releaseList {
release := releaseList[i]
if release.Draft && release.Tag == version {
return release
}
}
}
return nil
}
31 changes: 31 additions & 0 deletions controllers/internal_scm/gitlab.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package internal_scm

import (
"github.com/jenkins-x/go-scm/scm/driver/gitlab"
"github.com/jenkins-x/go-scm/scm/transport"
"net/http"
)

type Gitlab struct {
repo string
token string
}

// NewGitlab creates a new instance
func NewGitlab(repo, token string) *Gitlab {
return &Gitlab{
repo: repo,
token: token,
}
}

func (r *Gitlab) Release(version, commitish string, draft, prerelease bool) (err error) {
client := gitlab.NewDefault()
client.Client = &http.Client{
Transport: &transport.BearerToken{
Token: r.token,
},
}
err = release(client, r.repo, version, commitish, draft, prerelease)
return
}
Loading

0 comments on commit 3a0d076

Please sign in to comment.