Added forking for repository resources to allow creation of repo from a fork

This commit is contained in:
Gavin Bunney
2019-11-01 16:17:49 -07:00
parent c951ecba46
commit 2b986da86b
3 changed files with 106 additions and 37 deletions

View File

@@ -26,16 +26,13 @@ type Repository struct {
} `json:"links,omitempty"`
}
type ForkRepositoryRequestBody struct {
type RepositoryForkProject struct {
Key string `json:"key,omitempty"`
}
type RepositoryFork struct {
Name string `json:"name,omitempty"`
Slug string `json:"slug,omitempty"`
Description string `json:"description,omitempty"`
Forkable bool `json:"forkable,omitempty"`
Public bool `json:"public,omitempty"`
Links struct {
Clone []CloneUrl `json:"clone,omitempty"`
} `json:"links,omitempty"`
Project Project `json:"project,omitempty"`
Project RepositoryForkProject `json:"project,omitempty"`
}
func resourceRepository() *schema.Resource {
@@ -79,10 +76,15 @@ func resourceRepository() *schema.Resource {
Optional: true,
Default: false,
},
"origin_slug_to_fork": {
"fork_repository_project": {
Type: schema.TypeString,
Optional: true,
Default: false,
ForceNew: true,
},
"fork_repository_slug": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
},
"enable_git_lfs": {
Type: schema.TypeBool,
@@ -113,19 +115,6 @@ func newRepositoryFromResource(d *schema.ResourceData) (Repo *Repository) {
return repo
}
func newForkedRepositoryFromResource(d *schema.ResourceData) (Repo *ForkRepositoryRequestBody) {
req := &ForkRepositoryRequestBody{
Name: d.Get("name").(string),
Slug: d.Get("slug").(string),
Description: d.Get("description").(string),
Forkable: d.Get("forkable").(bool),
Public: d.Get("public").(bool),
Project: Project{Key: d.Get("project").(string)},
}
return req
}
func resourceRepositoryUpdate(d *schema.ResourceData, m interface{}) error {
client := m.(*BitbucketServerProvider).BitbucketClient
project := d.Get("project").(string)
@@ -163,9 +152,14 @@ func resourceRepositoryCreate(d *schema.ResourceData, m interface{}) error {
repoSlug := determineSlug(d)
name := d.Get("name").(string)
forkSlug := d.Get("fork_slug").(string)
if forkSlug != "" {
err := createForkRepository(client, d, project, forkSlug)
forkProject := d.Get("fork_repository_project").(string)
forkRepo := d.Get("fork_repository_slug").(string)
if (forkProject != "" && forkRepo == "") || (forkRepo != "" && forkProject == "") {
return fmt.Errorf("both fork_repository_project and fork_repository_slug need to be specified when forking an existing repository")
}
if forkProject != "" {
err := createNewRepositoryFromFork(client, d, project, repoSlug, forkProject, forkRepo)
if err != nil {
return err
}
@@ -183,34 +177,51 @@ func resourceRepositoryCreate(d *schema.ResourceData, m interface{}) error {
return err
}
return resourceRepositoryRead(d, m)
if forkProject != "" {
// after forking a repository, run the update loop to update any names/descriptions etc of the forked repo
return resourceRepositoryUpdate(d, m)
} else {
return resourceRepositoryRead(d, m)
}
}
func createNewRepository(client *BitbucketClient, d *schema.ResourceData, project string) error {
repo := newRepositoryFromResource(d)
bytedata, err := json.Marshal(repo)
if err != nil {
return err
}
_, err = client.Post(fmt.Sprintf("/rest/api/1.0/projects/%s/repos",
project,
), bytes.NewBuffer(bytedata))
if err != nil {
return err
}
return nil
}
func createForkRepository(client *BitbucketClient, d *schema.ResourceData, project string, forkSlug string) error {
requestBody := newForkedRepositoryFromResource(d)
func createNewRepositoryFromFork(client *BitbucketClient, d *schema.ResourceData, project string, repository string, forkProject string, forkRepository string) error {
requestBody := &RepositoryFork{
Name: repository,
Project: RepositoryForkProject{
Key:forkProject,
},
}
bytedata, err := json.Marshal(requestBody)
if err != nil {
return err
}
_, err = client.Post(fmt.Sprintf("/rest/api/1.0/projects/%s/repos/%s", project, forkSlug), bytes.NewBuffer(bytedata))
_, err = client.Post(fmt.Sprintf("/rest/api/1.0/projects/%s/repos/%s", forkProject, forkRepository), bytes.NewBuffer(bytedata))
if err != nil {
return err
}
return nil
}

View File

@@ -87,6 +87,59 @@ func TestAccBitbucketRepository_namewithspaces(t *testing.T) {
})
}
func TestAccBitbucketRepository_fork(t *testing.T) {
var repo Repository
config := fmt.Sprintf(`
resource "bitbucketserver_project" "test" {
key = "TEST%v"
name = "Test-%v"
}
resource "bitbucketserver_repository" "test_repo" {
project = bitbucketserver_project.test.key
name = "test-repo-for-repository-test"
description = "My Repo"
}
resource "bitbucketserver_repository" "test_fork" {
project = bitbucketserver_repository.test_repo.project
name = "My Fork"
description = "My Repo Forked"
fork_repository_project = bitbucketserver_repository.test_repo.project
fork_repository_slug = bitbucketserver_repository.test_repo.slug
}
`, rand.New(rand.NewSource(time.Now().UnixNano())).Int(), rand.New(rand.NewSource(time.Now().UnixNano())).Int())
configModified := strings.ReplaceAll(config, "My Repo Forked", "My Updated Repo Forked")
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckBitbucketRepositoryDestroy,
Steps: []resource.TestStep{
{
Config: config,
Check: resource.ComposeTestCheckFunc(
testAccCheckBitbucketRepositoryExists("bitbucketserver_repository.test_fork", &repo),
resource.TestCheckResourceAttr("bitbucketserver_repository.test_fork", "slug", "my-fork"),
resource.TestCheckResourceAttr("bitbucketserver_repository.test_fork", "name", "My Fork"),
resource.TestCheckResourceAttr("bitbucketserver_repository.test_fork", "description", "My Repo Forked"),
),
},
{
Config: configModified,
Check: resource.ComposeTestCheckFunc(
testAccCheckBitbucketRepositoryExists("bitbucketserver_repository.test_fork", &repo),
resource.TestCheckResourceAttr("bitbucketserver_repository.test_fork", "slug", "my-fork"),
resource.TestCheckResourceAttr("bitbucketserver_repository.test_fork", "name", "My Fork"),
resource.TestCheckResourceAttr("bitbucketserver_repository.test_fork", "description", "My Updated Repo Forked"),
),
},
},
})
}
func TestAccBitbucketRepository_gitlfs(t *testing.T) {
var repo Repository

View File

@@ -15,17 +15,20 @@ resource "bitbucketserver_repository" "test" {
}
```
###### if you want to fork an existing repository in the same project
### Forking an existing repository
```hcl
resource "bitbucketserver_repository" "test" {
project = "MYPROJ"
name = "test-01"
description = "Test repository"
origin_slug_to_fork = "MYOLDPROJ"
project = "MYPROJ"
name = "test-01"
description = "Test repository"
fork_repository_project = "MY-ORIGIN-PROJ"
fork_repository_slug = "MY-ORIGIN-REPO"
}
```
> Note: Both `fork_repositiroy_project` and `fork_repository_slug` are required to specified the origin repository to fork.
## Argument Reference
* `project` - Required. Name of the project to create the repository in.
@@ -35,7 +38,9 @@ resource "bitbucketserver_repository" "test" {
* `forkable` - Optional. Enable/disable forks of this repository. Default `true`
* `public` - Optional. Determine if this repository is public. Default `false`
* `enable_git_lfs` - Optional. Enable git-lfs for this repository. Default `false`
* `origin_slug_to_fork` - Optional. Use this to fork an expisting repository in the same project. Default `false`
* `fork_repository_project` - Optional. Use this to fork an existing repository from the given project.
* `fork_repository_slug` - Optional. Use this to fork an existing repository from the given repository.
## Attribute Reference
Additional to the above, the following attributes are emitted: