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

fix: Define new git provider interface #2450

Merged
merged 11 commits into from
Mar 22, 2023
Merged

Conversation

yitsushi
Copy link
Contributor

@yitsushi yitsushi commented Feb 23, 2023

Closes #2413

What changed?
A few wrapper git provider insider. This one is totally independent from
go-git-providers. It uses go-git-providers for our existing provider
implementations, but uses jenkins-x/go-scm for Azure.

Adds a new provider: Azure GitOps.

Why was this change made?
To make it easier to switch to a different git provider library.

How was this change implemented?
With sweat and tears and blood. A new package (pkg/git) creates a new wrapper and factory, the whole system can use then and what library is used behind given provider is not their business. The rest of the codebase just wants to create a PR and they should not care about what provider is used for that.

How did you validate the change?

  • Existing tests passed
  • Manual tested GitHub and BitBucket flow.
  • Manual test on Azure through the UI is blocked on oauth stuff, but using the provider in a test go app I could create a PR.

Release notes

Documentation Changes

@yitsushi yitsushi force-pushed the 2413-git-provider-interface branch 3 times, most recently from 553f75f to ff03538 Compare March 13, 2023 11:15
@yitsushi yitsushi added the enhancement New feature or request label Mar 13, 2023
@yitsushi yitsushi force-pushed the 2413-git-provider-interface branch 2 times, most recently from 3464fb6 to c903c25 Compare March 14, 2023 14:38
@yitsushi
Copy link
Contributor Author

yitsushi commented Mar 14, 2023

Test go app:

func main() {
	providerFactory := git.NewFactory(logr.Discard())
	providerOpts := []git.ProviderWithFn{
		git.WithToken("pat", "**a token**"),
	}

	provider, err := providerFactory.Create(git.AzureGitOpsProviderName, providerOpts...)
	if err != nil {
		log.Println(err)
		return
	}

	fileContent := "#!/usr/bin/env zsh\n\necho 'niiice'\n"

	pr, err := provider.CreatePullRequest(context.Background(), git.PullRequestInput{
		RepositoryURL: "https://dev.azure.com/weaveworks/weave-gitops-integration/_git/sunglow-test-repo",
		Title:         "New PR Title",
		Body:          "This is a fancy body message",
		Head:          fmt.Sprintf("new-branch-%d", rand.Int()),
		Base:          "main",
		Commits: []git.Commit{
			{
				CommitMessage: "Commit message :)",
				Files: []git.CommitFile{
					{
						Path:    "/fancy.sh",
						Content: &fileContent,
					},
				},
			},
		},

	})
	if err != nil {
		log.Println(err)
		return
	}

	log.Println(pr.Link)
}

image

@yitsushi yitsushi marked this pull request as ready for review March 14, 2023 16:02
yiannistri and others added 4 commits March 16, 2023 18:17
A few wrapper git provider insider. This one is totally independent from
go-git-providers. It uses go-git-providers for our existing provider
implementations, but uses jenkins-x/go-scm for Azure.

Signed-off-by: Balazs Nadasdi <balazs@weave.works>
Co-authored-by: Yiannis <yiannis@weave.works>
Signed-off-by: Balazs Nadasdi <balazs@weave.works>
Co-authored-by: Yiannis <yiannis@weave.works>
Signed-off-by: Balazs Nadasdi <balazs@weave.works>
Signed-off-by: Balazs Nadasdi <balazs@weave.works>
@yitsushi yitsushi force-pushed the 2413-git-provider-interface branch from 8e312ed to 0aec605 Compare March 16, 2023 17:21
@yiannistri
Copy link
Collaborator

Tested this on BitBucket Server and got the following error

failed to access repo https://stash.stashtestserver.link:7990/scm/~yiannis-user/bitbucket.git: unable to get a git provider client for "bitbucket-server": unable to apply options on provider &{{%!q(*zapr.zapLogger=&{0xc000876700 error false true}) '\x00'} %!q(*stash.ProviderClient=<nil>)}: option Domain already configured: invalid options given to NewClient()

@yiannistri
Copy link
Collaborator

yiannistri commented Mar 20, 2023

Writing down some notes as part of reviewing this PR:
In
cmd/clusters-service/pkg/server/clusters.go,
cmd/clusters-service/pkg/server/automations.go,
cmd/clusters-service/pkg/server/templates.go and
cmd/clusters-service/pkg/server/helpers.go

  • github.com/fluxcd/go-git-providers/gitprovider.CommitFile has been replaced by github.com/weaveworks/weave-gitops-enterprise/pkg/git.CommitFile

@yitsushi
Copy link
Contributor Author

yitsushi commented Mar 21, 2023

Tested this on BitBucket Server and got the following error

failed to access repo https://stash.stashtestserver.link:7990/scm/~yiannis-user/bitbucket.git: unable to get a git provider client for "bitbucket-server": unable to apply options on provider &{{%!q(*zapr.zapLogger=&{0xc000876700 error false true}) '\x00'} %!q(*stash.ProviderClient=)}: option Domain already configured: invalid options given to NewClient()

That's weird. This error message can only come from pkg/git/factory.go. Specifically from func (f *ProviderFactory) Create, and that creates a new go-git-provider stash.NewStashClient client.

The error message should be:

-fmt.Errorf("unable to apply options on provider %q: %w", provider, err)
+fmt.Errorf("unable to apply options on provider %q: %w", providerName, err)

@yitsushi
Copy link
Contributor Author

Ok I found the issue 🤦‍♀️

ggpOpts := []gitprovider.ClientOption{
	gitprovider.WithDomain(opts.Hostname),
// ...

if opts.Hostname != "" {
	ggpOpts = append(ggpOpts, gitprovider.WithDomain(opts.Hostname))
}

Signed-off-by: Balazs Nadasdi <balazs@weave.works>
…orks/weave-gitops-enterprise into 2413-git-provider-interface

Signed-off-by: Balazs Nadasdi <balazs@weave.works>
…erface

Signed-off-by: Balazs Nadasdi <balazs@weave.works>
Copy link
Collaborator

@yiannistri yiannistri left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks again for pushing through this 💯 I've reviewed the code and it looks like we've covered all the weird edge cases that have been added over time. I especially liked how we eliminated some if/else statements. This PR brings more structure to the git provider handling code and gives us a way to simplify this even further through (hopefully) easier refactoring. Well done!

cmd/clusters-service/pkg/server/clusters.go Outdated Show resolved Hide resolved
pkg/git/azure.go Outdated Show resolved Hide resolved
pkg/git/azure.go Outdated Show resolved Hide resolved

var err error

p.client, err = gitlab.NewClient(opts.Token, opts.TokenType, ggpOpts...)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the default value for TokenType?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Empty string.

In most cases we don't use the "type", only here, that's why the WithToken has two arguments.

Copy link
Contributor Author

@yitsushi yitsushi Mar 21, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

its value is coming directly from "request" struct as before.

cmd/clusters-service/pkg/git/git.go
164:            providerOpts = append(providerOpts, git.WithToken(gpi.TokenType, gpi.Token))
171:            providerOpts = append(providerOpts, git.WithToken(gpi.TokenType, gpi.Token))
175:            providerOpts = append(providerOpts, git.WithToken(gpi.TokenType, gpi.Token))
// cmd/clusters-service/pkg/git/git.go
// This is "gpi"
type GitProvider struct {
	Token     string
	TokenType string
	Type      string
	Hostname  string
}

pkg/git/gitprovider.go Outdated Show resolved Hide resolved

func (g goGitProvider) WriteFilesToBranch(ctx context.Context, log logr.Logger, req writeFilesToBranchRequest, repo gitprovider.OrgRepository) error {
if req.CreateBranch {
if err := g.CreateBranch(ctx, log, repo, req.BaseBranch, req.HeadBranch); err != nil {
Copy link
Collaborator

@yiannistri yiannistri Mar 21, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add a couple of comments to indicate which providers (Gitlab?) need this (CreateBranch: true) and why?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not provider specific, it's whether we have to create the branch or it already exists. Right not this logic is used only with gitlab, but that's visible from the logic there. From the point of this function, it's up the to the user if they want to create the branch with this call or not (they already have a branch created by a human, or from code).

yitsushi and others added 2 commits March 21, 2023 16:40
Co-authored-by: Yiannis <8741709+yiannistri@users.noreply.github.com>
@yitsushi yitsushi merged commit d269690 into main Mar 22, 2023
@yitsushi yitsushi deleted the 2413-git-provider-interface branch March 22, 2023 11:15
yitsushi added a commit that referenced this pull request Mar 22, 2023
The root cause was a misused pointer reference in
`pkg/git/gitprovider.go`. For some reasons `go-git-providers` (GGP) expects a
reference to a string as filename. That wouldn't be an issue in most
cases, but we tried to convert WGE internal `CommitFile` to GGP's
`CommitFile`. In that loop we assigned a reference, but that reference
gets updated while we are in the loop:

```go
for _, f := range c.Files {
  adapted = append(adapted, gitprovider.CommitFile{
    Path:    &f.Path,
    Content: f.Content,
  })
}
```

As a result we end up with the same filename for all files, therefore we
commit only one file.

Other changes:
 - Updated go-git-providers from 0.14 to 0.15

References:
* Previous PR: #2450
* Issue: #2413

Signed-off-by: Balazs Nadasdi <balazs@weave.works>
yitsushi added a commit that referenced this pull request Mar 22, 2023
The root cause was a misused pointer reference in
`pkg/git/gitprovider.go`. For some reasons `go-git-providers` (GGP) expects a
reference to a string as filename. That wouldn't be an issue in most
cases, but we tried to convert WGE internal `CommitFile` to GGP's
`CommitFile`. In that loop we assigned a reference, but that reference
gets updated while we are in the loop:

```go
for _, f := range c.Files {
  adapted = append(adapted, gitprovider.CommitFile{
    Path:    &f.Path,
    Content: f.Content,
  })
}
```

As a result we end up with the same filename for all files, therefore we
commit only one file.

Other changes:
 - Updated go-git-providers from 0.14 to 0.15

References:
* Previous PR: #2450
* Issue: #2413

Signed-off-by: Balazs Nadasdi <balazs@weave.works>
yitsushi added a commit that referenced this pull request Mar 22, 2023
The root cause was a misused pointer reference in
`pkg/git/gitprovider.go`. For some reasons `go-git-providers` (GGP) expects a
reference to a string as filename. That wouldn't be an issue in most
cases, but we tried to convert WGE internal `CommitFile` to GGP's
`CommitFile`. In that loop we assigned a reference, but that reference
gets updated while we are in the loop:

```go
for _, f := range c.Files {
  adapted = append(adapted, gitprovider.CommitFile{
    Path:    &f.Path,
    Content: f.Content,
  })
}
```

As a result we end up with the same filename for all files, therefore we
commit only one file.

References:
* Previous PR: #2450
* Issue: #2413

Signed-off-by: Balazs Nadasdi <balazs@weave.works>
yitsushi added a commit that referenced this pull request Mar 22, 2023
The root cause was a misused pointer reference in
`pkg/git/gitprovider.go`. For some reasons `go-git-providers` (GGP) expects a
reference to a string as filename. That wouldn't be an issue in most
cases, but we tried to convert WGE internal `CommitFile` to GGP's
`CommitFile`. In that loop we assigned a reference, but that reference
gets updated while we are in the loop:

```go
for _, f := range c.Files {
  adapted = append(adapted, gitprovider.CommitFile{
    Path:    &f.Path,
    Content: f.Content,
  })
}
```

As a result we end up with the same filename for all files, therefore we
commit only one file.

References:
* Previous PR: #2450
* Issue: #2413

Signed-off-by: Balazs Nadasdi <balazs@weave.works>
yitsushi added a commit that referenced this pull request Mar 22, 2023
The root cause was a misused pointer reference in
`pkg/git/gitprovider.go`. For some reasons `go-git-providers` (GGP) expects a
reference to a string as filename. That wouldn't be an issue in most
cases, but we tried to convert WGE internal `CommitFile` to GGP's
`CommitFile`. In that loop we assigned a reference, but that reference
gets updated while we are in the loop:

```go
for _, f := range c.Files {
  adapted = append(adapted, gitprovider.CommitFile{
    Path:    &f.Path,
    Content: f.Content,
  })
}
```

As a result we end up with the same filename for all files, therefore we
commit only one file.

References:
* Previous PR: #2450
* Issue: #2413

Signed-off-by: Balazs Nadasdi <balazs@weave.works>
joshri pushed a commit that referenced this pull request Mar 23, 2023
The root cause was a misused pointer reference in
`pkg/git/gitprovider.go`. For some reasons `go-git-providers` (GGP) expects a
reference to a string as filename. That wouldn't be an issue in most
cases, but we tried to convert WGE internal `CommitFile` to GGP's
`CommitFile`. In that loop we assigned a reference, but that reference
gets updated while we are in the loop:

```go
for _, f := range c.Files {
  adapted = append(adapted, gitprovider.CommitFile{
    Path:    &f.Path,
    Content: f.Content,
  })
}
```

As a result we end up with the same filename for all files, therefore we
commit only one file.

References:
* Previous PR: #2450
* Issue: #2413

Signed-off-by: Balazs Nadasdi <balazs@weave.works>
yitsushi added a commit to weaveworks/pipeline-controller that referenced this pull request Mar 31, 2023
This change-set adds Azure DevOps support to pipeline promotions. Based
on discussions (on Slack) we decided to go with a "copy as it is"
solution to use the new GitProvider used in WGE (PR[^1] with 2 fixes[^2][^3]).

It's a simple copy-paste what we have in WGE, but with a few addition
and changes:

* [addition] List Pull Requests.
  If we can't create a PR, we try to find an existing one with
  Pipelines. That logic does not exist in WGE.
* [change] Do not create branch if we have no additional commits.
  On WGE we create a branch with the CreatePullRequest call (except in
  on case[^4]), but with pipelines we already have the branch with all
  required files and changes using pure git operations with clone and
  push. In this case we don't have additional commits, we only have to
  create the new branch if `len(input.commits) > 0`.
* [addition] `Name()` and `SupportedDomain()`.
  These new functions were added to make it easier to verify or test
  given properties hidden behind the implementation of a Provder interface.
  We may want to port them back to WGE with extra testing.

Closes #170

[^1]: weaveworks/weave-gitops-enterprise#2450
[^2]: weaveworks/weave-gitops-enterprise#2585
[^3]: weaveworks/weave-gitops-enterprise#2625
[^4]: https://github.com/weaveworks/weave-gitops-enterprise/blob/main/pkg/git/gitlab.go#L108

Signed-off-by: Balazs Nadasdi <balazs@weave.works>
yitsushi added a commit to weaveworks/pipeline-controller that referenced this pull request Mar 31, 2023
This change-set adds Azure DevOps support to pipeline promotions. Based
on discussions (on Slack) we decided to go with a "copy as it is"
solution to use the new GitProvider used in WGE (PR[^1] with 2 fixes[^2][^3]).

It's a simple copy-paste what we have in WGE, but with a few addition
and changes:

* [addition] List Pull Requests.
  If we can't create a PR, we try to find an existing one with
  Pipelines. That logic does not exist in WGE.
* [change] Do not create branch if we have no additional commits.
  On WGE we create a branch with the CreatePullRequest call (except in
  on case[^4]), but with pipelines we already have the branch with all
  required files and changes using pure git operations with clone and
  push. In this case we don't have additional commits, we only have to
  create the new branch if `len(input.commits) > 0`.
* [addition] `Name()` and `SupportedDomain()`.
  These new functions were added to make it easier to verify or test
  given properties hidden behind the implementation of a Provder interface.
  We may want to port them back to WGE with extra testing.

Additional changes:
* Set Go version to 1.20 to match with WGE.

Closes #170

[^1]: weaveworks/weave-gitops-enterprise#2450
[^2]: weaveworks/weave-gitops-enterprise#2585
[^3]: weaveworks/weave-gitops-enterprise#2625
[^4]: https://github.com/weaveworks/weave-gitops-enterprise/blob/main/pkg/git/gitlab.go#L108

Signed-off-by: Balazs Nadasdi <balazs@weave.works>
yitsushi added a commit to weaveworks/pipeline-controller that referenced this pull request Mar 31, 2023
This change-set adds Azure DevOps support to pipeline promotions. Based
on discussions (on Slack) we decided to go with a "copy as it is"
solution to use the new GitProvider used in WGE (PR[^1] with 2 fixes[^2][^3]).

It's a simple copy-paste what we have in WGE, but with a few addition
and changes:

* [addition] List Pull Requests.
  If we can't create a PR, we try to find an existing one with
  Pipelines. That logic does not exist in WGE.
* [change] Do not create branch if we have no additional commits.
  On WGE we create a branch with the CreatePullRequest call (except in
  on case[^4]), but with pipelines we already have the branch with all
  required files and changes using pure git operations with clone and
  push. In this case we don't have additional commits, we only have to
  create the new branch if `len(input.commits) > 0`.
* [addition] `Name()` and `SupportedDomain()`.
  These new functions were added to make it easier to verify or test
  given properties hidden behind the implementation of a Provder interface.
  We may want to port them back to WGE with extra testing.

Additional changes:
* Set Go version to 1.20 to match with WGE.

Closes #170

[^1]: weaveworks/weave-gitops-enterprise#2450
[^2]: weaveworks/weave-gitops-enterprise#2585
[^3]: weaveworks/weave-gitops-enterprise#2625
[^4]: https://github.com/weaveworks/weave-gitops-enterprise/blob/main/pkg/git/gitlab.go#L108

Signed-off-by: Balazs Nadasdi <balazs@weave.works>
yitsushi added a commit to weaveworks/pipeline-controller that referenced this pull request Mar 31, 2023
This change-set adds Azure DevOps support to pipeline promotions. Based
on discussions (on Slack) we decided to go with a "copy as it is"
solution to use the new GitProvider used in WGE (PR[^1] with 2 fixes[^2][^3]).

It's a simple copy-paste what we have in WGE, but with a few addition
and changes:

* [addition] List Pull Requests.
  If we can't create a PR, we try to find an existing one with
  Pipelines. That logic does not exist in WGE.
* [change] Do not create branch if we have no additional commits.
  On WGE we create a branch with the CreatePullRequest call (except in
  on case[^4]), but with pipelines we already have the branch with all
  required files and changes using pure git operations with clone and
  push. In this case we don't have additional commits, we only have to
  create the new branch if `len(input.commits) > 0`.
* [addition] `Name()` and `SupportedDomain()`.
  These new functions were added to make it easier to verify or test
  given properties hidden behind the implementation of a Provder interface.
  We may want to port them back to WGE with extra testing.

Additional changes:
* Set Go version to 1.20 to match with WGE.

Closes #170

[^1]: weaveworks/weave-gitops-enterprise#2450
[^2]: weaveworks/weave-gitops-enterprise#2585
[^3]: weaveworks/weave-gitops-enterprise#2625
[^4]: https://github.com/weaveworks/weave-gitops-enterprise/blob/main/pkg/git/gitlab.go#L108

Signed-off-by: Balazs Nadasdi <balazs@weave.works>
yitsushi added a commit to weaveworks/pipeline-controller that referenced this pull request Mar 31, 2023
This change-set adds Azure DevOps support to pipeline promotions. Based
on discussions (on Slack) we decided to go with a "copy as it is"
solution to use the new GitProvider used in WGE (PR[^1] with 2 fixes[^2][^3]).

It's a simple copy-paste what we have in WGE, but with a few addition
and changes:

* [addition] List Pull Requests.
  If we can't create a PR, we try to find an existing one with
  Pipelines. That logic does not exist in WGE.
* [change] Do not create branch if we have no additional commits.
  On WGE we create a branch with the CreatePullRequest call (except in
  on case[^4]), but with pipelines we already have the branch with all
  required files and changes using pure git operations with clone and
  push. In this case we don't have additional commits, we only have to
  create the new branch if `len(input.commits) > 0`.
* [addition] `Name()` and `SupportedDomain()`.
  These new functions were added to make it easier to verify or test
  given properties hidden behind the implementation of a Provder interface.
  We may want to port them back to WGE with extra testing.

Additional changes:
* Set Go version to 1.20 to match with WGE.

Closes #170

[^1]: weaveworks/weave-gitops-enterprise#2450
[^2]: weaveworks/weave-gitops-enterprise#2585
[^3]: weaveworks/weave-gitops-enterprise#2625
[^4]: https://github.com/weaveworks/weave-gitops-enterprise/blob/main/pkg/git/gitlab.go#L108

Signed-off-by: Balazs Nadasdi <balazs@weave.works>
yitsushi added a commit to weaveworks/pipeline-controller that referenced this pull request Apr 4, 2023
This change-set adds Azure DevOps support to pipeline promotions. Based
on discussions (on Slack) we decided to go with a "copy as it is"
solution to use the new GitProvider used in WGE (PR[^1] with 2 fixes[^2][^3]).

It's a simple copy-paste what we have in WGE, but with a few addition
and changes:

* [addition] List Pull Requests.
  If we can't create a PR, we try to find an existing one with
  Pipelines. That logic does not exist in WGE.
* [change] Do not create branch if we have no additional commits.
  On WGE we create a branch with the CreatePullRequest call (except in
  on case[^4]), but with pipelines we already have the branch with all
  required files and changes using pure git operations with clone and
  push. In this case we don't have additional commits, we only have to
  create the new branch if `len(input.commits) > 0`.
* [addition] `Name()` and `SupportedDomain()`.
  These new functions were added to make it easier to verify or test
  given properties hidden behind the implementation of a Provder interface.
  We may want to port them back to WGE with extra testing.

Additional changes:
* Set Go version to 1.20 to match with WGE.

Closes #170

[^1]: weaveworks/weave-gitops-enterprise#2450
[^2]: weaveworks/weave-gitops-enterprise#2585
[^3]: weaveworks/weave-gitops-enterprise#2625
[^4]: https://github.com/weaveworks/weave-gitops-enterprise/blob/main/pkg/git/gitlab.go#L108

Signed-off-by: Balazs Nadasdi <balazs@weave.works>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Define new interface for git providers in WGE and implement it for existing providers
2 participants