From 9992407ab80968925c39b09e7c30ac3b4dacbe5f Mon Sep 17 00:00:00 2001 From: Zahiar Ahmed Date: Fri, 12 Nov 2021 19:02:31 +0000 Subject: [PATCH] Fix issue with `fork_policy` not being updated Due to an undocumented quirk in Bitbucket's API, when updating a repository, you have to pass in two additional fields which are then used together, to match the string representation of the fork_policy (which the API returns - the other two fields are not returned). Here is a link to an oustanding bug ticket filed with Atlassian: https://jira.atlassian.com/browse/BCLOUD-13093 Also added tests to cover the behaviour above, as well as an additional one for creating a repository, to ensure this functionality was not broken with the changes introduced. --- repository.go | 14 ++++ tests/repository_test.go | 144 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 158 insertions(+) diff --git a/repository.go b/repository.go index b3ac8ea..48c64be 100644 --- a/repository.go +++ b/repository.go @@ -774,6 +774,20 @@ func (r *Repository) buildRepositoryBody(ro *RepositoryOptions) string { } if ro.ForkPolicy != "" { body["fork_policy"] = ro.ForkPolicy + + // Due to this undocumented asymmetric behaviour (https://jira.atlassian.com/browse/BCLOUD-13093) + // we have to do this, to allow `fork_policy` to be updated after initial creation (i.e. PUT/POST requests) + switch ro.ForkPolicy { + case "allow_forks": + body["no_forks"] = false + body["no_public_forks"] = false + case "no_public_forks": + body["no_forks"] = false + body["no_public_forks"] = true + case "no_forks": + body["no_forks"] = true + body["no_public_forks"] = true + } } if ro.Language != "" { body["language"] = ro.Language diff --git a/tests/repository_test.go b/tests/repository_test.go index 3a89bf9..263c6d3 100644 --- a/tests/repository_test.go +++ b/tests/repository_test.go @@ -5,6 +5,7 @@ import ( "testing" _ "github.com/k0kubun/pp" + "github.com/ktrysmt/go-bitbucket" ) @@ -45,6 +46,149 @@ func TestGetRepositoryRepositories(t *testing.T) { } } +func TestCreateRepositoryRepositories(t *testing.T) { + user := os.Getenv("BITBUCKET_TEST_USERNAME") + pass := os.Getenv("BITBUCKET_TEST_PASSWORD") + owner := os.Getenv("BITBUCKET_TEST_OWNER") + + if user == "" { + t.Error("BITBUCKET_TEST_USERNAME is empty.") + } + if pass == "" { + t.Error("BITBUCKET_TEST_PASSWORD is empty.") + } + if owner == "" { + t.Error("BITBUCKET_TEST_OWNER is empty.") + } + + c := bitbucket.NewBasicAuth(user, pass) + + // Create project - needed prior to creating repo + projOpt := &bitbucket.ProjectOptions{ + Owner: owner, + Name: "go-bitbucket-test-project", + Key: "GO_BB_TEST_PROJECT", + IsPrivate: true, + } + project, err := c.Workspaces.CreateProject(projOpt) + if err != nil { + t.Error("The project could not be created.", err) + } + + repoSlug := "go-bb-test-repo-create" + forkPolicy := "no_forks" + repoOpt := &bitbucket.RepositoryOptions{ + Owner: owner, + RepoSlug: repoSlug, + ForkPolicy: forkPolicy, + Project: project.Key, + IsPrivate: "true", + } + + res, err := c.Repositories.Repository.Create(repoOpt) + if err != nil { + t.Error("The project could not be created.", err) + } + + if res.Full_name != owner+"/"+repoSlug { + t.Error("The repository `Full_name` attribute does not match the expected value.") + } + if res.Fork_policy != forkPolicy { + t.Error("The repository `Fork_policy` attribute does not match the expected value.") + } + + // Clean up + _, err = c.Repositories.Repository.Delete(repoOpt) + if err != nil { + t.Error("The repository could not be deleted.", err) + } + + _, err = c.Workspaces.DeleteProject(projOpt) + if err != nil { + t.Error("The project could not be deleted.", err) + } +} + +func TestRepositoryUpdateForkPolicy(t *testing.T) { + user := os.Getenv("BITBUCKET_TEST_USERNAME") + pass := os.Getenv("BITBUCKET_TEST_PASSWORD") + owner := os.Getenv("BITBUCKET_TEST_OWNER") + repo := os.Getenv("BITBUCKET_TEST_REPOSLUG") + + if user == "" { + t.Error("BITBUCKET_TEST_USERNAME is empty.") + } + if pass == "" { + t.Error("BITBUCKET_TEST_PASSWORD is empty.") + } + if owner == "" { + t.Error("BITBUCKET_TEST_OWNER is empty.") + } + if repo == "" { + t.Error("BITBUCKET_TEST_REPOSLUG is empty.") + } + + c := bitbucket.NewBasicAuth(user, pass) + + opt := &bitbucket.RepositoryOptions{ + Owner: owner, + RepoSlug: repo, + } + + res, err := c.Repositories.Repository.Get(opt) + if err != nil { + t.Error("The repository is not found.", err) + } + + forkPolicy := "allow_forks" + opt = &bitbucket.RepositoryOptions{ + Uuid: res.Uuid, + Owner: owner, + RepoSlug: res.Slug, + ForkPolicy: forkPolicy, + } + res, err = c.Repositories.Repository.Update(opt) + if err != nil { + t.Error("The repository could not be updated.", err) + } + + if res.Fork_policy != forkPolicy { + t.Errorf("The repository's fork_policy did not match the expected: '%s'.", forkPolicy) + } + + forkPolicy = "no_public_forks" + opt = &bitbucket.RepositoryOptions{ + Uuid: res.Uuid, + Owner: owner, + RepoSlug: res.Slug, + ForkPolicy: forkPolicy, + } + res, err = c.Repositories.Repository.Update(opt) + if err != nil { + t.Error("The repository could not be updated.", err) + } + + if res.Fork_policy != forkPolicy { + t.Errorf("The repository's fork_policy did not match the expected: '%s'.", forkPolicy) + } + + forkPolicy = "no_forks" + opt = &bitbucket.RepositoryOptions{ + Uuid: res.Uuid, + Owner: owner, + RepoSlug: res.Slug, + ForkPolicy: forkPolicy, + } + res, err = c.Repositories.Repository.Update(opt) + if err != nil { + t.Error("The repository could not be updated.", err) + } + + if res.Fork_policy != forkPolicy { + t.Errorf("The repository's fork_policy did not match the expected: '%s'.", forkPolicy) + } +} + func TestGetRepositoryPipelineVariables(t *testing.T) { user := os.Getenv("BITBUCKET_TEST_USERNAME")