mirror of
https://github.com/MichaelMure/git-bug.git
synced 2024-12-14 17:51:44 +03:00
Merge pull request #274 from MichaelMure/gitlab-bridge
bridge/gitlab: support self-hosted GitLab instance
This commit is contained in:
commit
e96d8e6771
@ -35,6 +35,7 @@ type BridgeParams struct {
|
||||
Owner string
|
||||
Project string
|
||||
URL string
|
||||
BaseURL string
|
||||
CredPrefix string
|
||||
TokenRaw string
|
||||
}
|
||||
|
@ -44,6 +44,10 @@ var (
|
||||
)
|
||||
|
||||
func (g *Github) Configure(repo *cache.RepoCache, params core.BridgeParams) (core.Configuration, error) {
|
||||
if params.BaseURL != "" {
|
||||
fmt.Println("warning: --base-url is ineffective for a Github bridge")
|
||||
}
|
||||
|
||||
conf := make(core.Configuration)
|
||||
var err error
|
||||
|
||||
|
@ -42,6 +42,10 @@ func (g *Gitlab) Configure(repo *cache.RepoCache, params core.BridgeParams) (cor
|
||||
return nil, fmt.Errorf("you must provide a project URL to configure this bridge with a token")
|
||||
}
|
||||
|
||||
if params.URL == "" {
|
||||
params.URL = defaultBaseURL
|
||||
}
|
||||
|
||||
var url string
|
||||
|
||||
// get project url
|
||||
@ -56,6 +60,10 @@ func (g *Gitlab) Configure(repo *cache.RepoCache, params core.BridgeParams) (cor
|
||||
}
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(url, params.BaseURL) {
|
||||
return nil, fmt.Errorf("base URL (%s) doesn't match the project URL (%s)", params.BaseURL, url)
|
||||
}
|
||||
|
||||
user, err := repo.GetUserIdentity()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -87,13 +95,14 @@ func (g *Gitlab) Configure(repo *cache.RepoCache, params core.BridgeParams) (cor
|
||||
}
|
||||
|
||||
// validate project url and get its ID
|
||||
id, err := validateProjectURL(url, token)
|
||||
id, err := validateProjectURL(params.BaseURL, url, token)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "project validation")
|
||||
}
|
||||
|
||||
conf[core.ConfigKeyTarget] = target
|
||||
conf[keyProjectID] = strconv.Itoa(id)
|
||||
conf[keyGitlabBaseUrl] = params.BaseURL
|
||||
|
||||
err = g.ValidateConfig(conf)
|
||||
if err != nil {
|
||||
@ -302,13 +311,16 @@ func getValidGitlabRemoteURLs(remotes map[string]string) []string {
|
||||
return urls
|
||||
}
|
||||
|
||||
func validateProjectURL(url string, token *auth.Token) (int, error) {
|
||||
func validateProjectURL(baseURL, url string, token *auth.Token) (int, error) {
|
||||
projectPath, err := getProjectPath(url)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
client := buildClient(token)
|
||||
client, err := buildClient(baseURL, token)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
project, _, err := client.Projects.GetProject(projectPath, &gitlab.GetProjectOptions{})
|
||||
if err != nil {
|
||||
|
@ -62,7 +62,11 @@ func (ge *gitlabExporter) cacheAllClient(repo repository.RepoConfig) error {
|
||||
|
||||
for _, cred := range creds {
|
||||
if _, ok := ge.identityClient[cred.UserId()]; !ok {
|
||||
client := buildClient(creds[0].(*auth.Token))
|
||||
client, err := buildClient(ge.conf[keyGitlabBaseUrl], creds[0].(*auth.Token))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ge.identityClient[cred.UserId()] = client
|
||||
}
|
||||
}
|
||||
@ -133,6 +137,7 @@ func (ge *gitlabExporter) exportBug(ctx context.Context, b *cache.BugCache, sinc
|
||||
var err error
|
||||
var bugGitlabID int
|
||||
var bugGitlabIDString string
|
||||
var GitlabBaseUrl string
|
||||
var bugCreationId string
|
||||
|
||||
// Special case:
|
||||
@ -153,6 +158,12 @@ func (ge *gitlabExporter) exportBug(ctx context.Context, b *cache.BugCache, sinc
|
||||
// get gitlab bug ID
|
||||
gitlabID, ok := snapshot.GetCreateMetadata(metaKeyGitlabId)
|
||||
if ok {
|
||||
gitlabBaseUrl, ok := snapshot.GetCreateMetadata(metaKeyGitlabBaseUrl)
|
||||
if ok && gitlabBaseUrl != ge.conf[gitlabBaseUrl] {
|
||||
out <- core.NewExportNothing(b.Id(), "skipping issue imported from another Gitlab instance")
|
||||
return
|
||||
}
|
||||
|
||||
projectID, ok := snapshot.GetCreateMetadata(metaKeyGitlabProject)
|
||||
if !ok {
|
||||
err := fmt.Errorf("expected to find gitlab project id")
|
||||
@ -199,6 +210,7 @@ func (ge *gitlabExporter) exportBug(ctx context.Context, b *cache.BugCache, sinc
|
||||
metaKeyGitlabId: idString,
|
||||
metaKeyGitlabUrl: url,
|
||||
metaKeyGitlabProject: ge.repositoryID,
|
||||
metaKeyGitlabBaseUrl: GitlabBaseUrl,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
|
@ -188,7 +188,8 @@ func TestPushPull(t *testing.T) {
|
||||
// initialize exporter
|
||||
exporter := &gitlabExporter{}
|
||||
err = exporter.Init(backend, core.Configuration{
|
||||
keyProjectID: strconv.Itoa(projectID),
|
||||
keyProjectID: strconv.Itoa(projectID),
|
||||
keyGitlabBaseUrl: "https://gitlab.com/",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
@ -215,7 +216,8 @@ func TestPushPull(t *testing.T) {
|
||||
|
||||
importer := &gitlabImporter{}
|
||||
err = importer.Init(backend, core.Configuration{
|
||||
keyProjectID: strconv.Itoa(projectID),
|
||||
keyProjectID: strconv.Itoa(projectID),
|
||||
keyGitlabBaseUrl: "https://gitlab.com/",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
@ -280,7 +282,11 @@ func generateRepoName() string {
|
||||
|
||||
// create repository need a token with scope 'repo'
|
||||
func createRepository(ctx context.Context, name string, token *auth.Token) (int, error) {
|
||||
client := buildClient(token)
|
||||
client, err := buildClient("https://gitlab.com/", token)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
project, _, err := client.Projects.CreateProject(
|
||||
&gitlab.CreateProjectOptions{
|
||||
Name: gitlab.String(name),
|
||||
@ -296,7 +302,11 @@ func createRepository(ctx context.Context, name string, token *auth.Token) (int,
|
||||
|
||||
// delete repository need a token with scope 'delete_repo'
|
||||
func deleteRepository(ctx context.Context, project int, token *auth.Token) error {
|
||||
client := buildClient(token)
|
||||
_, err := client.Projects.DeleteProject(project, gitlab.WithContext(ctx))
|
||||
client, err := buildClient("https://gitlab.com/", token)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = client.Projects.DeleteProject(project, gitlab.WithContext(ctx))
|
||||
return err
|
||||
}
|
||||
|
@ -17,9 +17,12 @@ const (
|
||||
metaKeyGitlabUrl = "gitlab-url"
|
||||
metaKeyGitlabLogin = "gitlab-login"
|
||||
metaKeyGitlabProject = "gitlab-project-id"
|
||||
metaKeyGitlabBaseUrl = "gitlab-base-url"
|
||||
|
||||
keyProjectID = "project-id"
|
||||
keyProjectID = "project-id"
|
||||
keyGitlabBaseUrl = "base-url"
|
||||
|
||||
defaultBaseURL = "https://gitlab.com/"
|
||||
defaultTimeout = 60 * time.Second
|
||||
)
|
||||
|
||||
@ -37,10 +40,16 @@ func (*Gitlab) NewExporter() core.Exporter {
|
||||
return &gitlabExporter{}
|
||||
}
|
||||
|
||||
func buildClient(token *auth.Token) *gitlab.Client {
|
||||
client := &http.Client{
|
||||
func buildClient(baseURL string, token *auth.Token) (*gitlab.Client, error) {
|
||||
httpClient := &http.Client{
|
||||
Timeout: defaultTimeout,
|
||||
}
|
||||
|
||||
return gitlab.NewClient(client, token.Value)
|
||||
gitlabClient := gitlab.NewClient(httpClient, token.Value)
|
||||
err := gitlabClient.SetBaseURL(baseURL)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return gitlabClient, nil
|
||||
}
|
||||
|
@ -52,7 +52,10 @@ func (gi *gitlabImporter) Init(repo *cache.RepoCache, conf core.Configuration) e
|
||||
return ErrMissingIdentityToken
|
||||
}
|
||||
|
||||
gi.client = buildClient(creds[0].(*auth.Token))
|
||||
gi.client, err = buildClient(conf[keyGitlabBaseUrl], creds[0].(*auth.Token))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@ -151,6 +154,7 @@ func (gi *gitlabImporter) ensureIssue(repo *cache.RepoCache, issue *gitlab.Issue
|
||||
metaKeyGitlabId: parseID(issue.IID),
|
||||
metaKeyGitlabUrl: issue.WebURL,
|
||||
metaKeyGitlabProject: gi.conf[keyProjectID],
|
||||
metaKeyGitlabBaseUrl: gi.conf[keyGitlabBaseUrl],
|
||||
},
|
||||
)
|
||||
|
||||
|
@ -103,7 +103,8 @@ func TestImport(t *testing.T) {
|
||||
|
||||
importer := &gitlabImporter{}
|
||||
err = importer.Init(backend, core.Configuration{
|
||||
keyProjectID: projectID,
|
||||
keyProjectID: projectID,
|
||||
keyGitlabBaseUrl: "https://gitlab.com",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
|
@ -29,6 +29,9 @@ func (l *Launchpad) Configure(repo *cache.RepoCache, params core.BridgeParams) (
|
||||
if params.Owner != "" {
|
||||
fmt.Println("warning: --owner is ineffective for a Launchpad bridge")
|
||||
}
|
||||
if params.BaseURL != "" {
|
||||
fmt.Println("warning: --base-url is ineffective for a Launchpad bridge")
|
||||
}
|
||||
|
||||
conf := make(core.Configuration)
|
||||
var err error
|
||||
|
@ -216,6 +216,7 @@ func init() {
|
||||
bridgeConfigureCmd.Flags().StringVarP(&bridgeConfigureTarget, "target", "t", "",
|
||||
fmt.Sprintf("The target of the bridge. Valid values are [%s]", strings.Join(bridge.Targets(), ",")))
|
||||
bridgeConfigureCmd.Flags().StringVarP(&bridgeConfigureParams.URL, "url", "u", "", "The URL of the target repository")
|
||||
bridgeConfigureCmd.Flags().StringVarP(&bridgeConfigureParams.BaseURL, "base-url", "b", "", "The base URL of your issue tracker service")
|
||||
bridgeConfigureCmd.Flags().StringVarP(&bridgeConfigureParams.Owner, "owner", "o", "", "The owner of the target repository")
|
||||
bridgeConfigureCmd.Flags().StringVarP(&bridgeConfigureParams.CredPrefix, "credential", "c", "", "The identifier or prefix of an already known credential for the API (see \"git-bug bridge auth\")")
|
||||
bridgeConfigureCmd.Flags().StringVar(&bridgeConfigureToken, "token", "", "A raw authentication token for the API")
|
||||
|
@ -39,6 +39,10 @@ Token configuration can be directly passed with the \-\-token flag or in the ter
|
||||
\fB\-u\fP, \fB\-\-url\fP=""
|
||||
The URL of the target repository
|
||||
|
||||
.PP
|
||||
\fB\-b\fP, \fB\-\-base\-url\fP=""
|
||||
The base URL of your issue tracker service
|
||||
|
||||
.PP
|
||||
\fB\-o\fP, \fB\-\-owner\fP=""
|
||||
The owner of the target repository
|
||||
|
@ -73,6 +73,7 @@ git bug bridge configure \
|
||||
-n, --name string A distinctive name to identify the bridge
|
||||
-t, --target string The target of the bridge. Valid values are [github,gitlab,launchpad-preview]
|
||||
-u, --url string The URL of the target repository
|
||||
-b, --base-url string The base URL of your issue tracker service
|
||||
-o, --owner string The owner of the target repository
|
||||
-c, --credential string The identifier or prefix of an already known credential for the API (see "git-bug bridge auth")
|
||||
--token string A raw authentication token for the API
|
||||
|
@ -400,6 +400,10 @@ _git-bug_bridge_configure()
|
||||
two_word_flags+=("--url")
|
||||
two_word_flags+=("-u")
|
||||
local_nonpersistent_flags+=("--url=")
|
||||
flags+=("--base-url=")
|
||||
two_word_flags+=("--base-url")
|
||||
two_word_flags+=("-b")
|
||||
local_nonpersistent_flags+=("--base-url=")
|
||||
flags+=("--owner=")
|
||||
two_word_flags+=("--owner")
|
||||
two_word_flags+=("-o")
|
||||
|
@ -79,6 +79,8 @@ Register-ArgumentCompleter -Native -CommandName 'git-bug' -ScriptBlock {
|
||||
[CompletionResult]::new('--target', 'target', [CompletionResultType]::ParameterName, 'The target of the bridge. Valid values are [github,gitlab,launchpad-preview]')
|
||||
[CompletionResult]::new('-u', 'u', [CompletionResultType]::ParameterName, 'The URL of the target repository')
|
||||
[CompletionResult]::new('--url', 'url', [CompletionResultType]::ParameterName, 'The URL of the target repository')
|
||||
[CompletionResult]::new('-b', 'b', [CompletionResultType]::ParameterName, 'The base URL of your issue tracker service')
|
||||
[CompletionResult]::new('--base-url', 'base-url', [CompletionResultType]::ParameterName, 'The base URL of your issue tracker service')
|
||||
[CompletionResult]::new('-o', 'o', [CompletionResultType]::ParameterName, 'The owner of the target repository')
|
||||
[CompletionResult]::new('--owner', 'owner', [CompletionResultType]::ParameterName, 'The owner of the target repository')
|
||||
[CompletionResult]::new('-c', 'c', [CompletionResultType]::ParameterName, 'The identifier or prefix of an already known credential for the API (see "git-bug bridge auth")')
|
||||
|
@ -193,6 +193,7 @@ function _git-bug_bridge_configure {
|
||||
'(-n --name)'{-n,--name}'[A distinctive name to identify the bridge]:' \
|
||||
'(-t --target)'{-t,--target}'[The target of the bridge. Valid values are [github,gitlab,launchpad-preview]]:' \
|
||||
'(-u --url)'{-u,--url}'[The URL of the target repository]:' \
|
||||
'(-b --base-url)'{-b,--base-url}'[The base URL of your issue tracker service]:' \
|
||||
'(-o --owner)'{-o,--owner}'[The owner of the target repository]:' \
|
||||
'(-c --credential)'{-c,--credential}'[The identifier or prefix of an already known credential for the API (see "git-bug bridge auth")]:' \
|
||||
'--token[A raw authentication token for the API]:' \
|
||||
|
Loading…
Reference in New Issue
Block a user