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

Add repository topics #97

Merged
merged 3 commits into from
Jun 1, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 28 additions & 2 deletions github/resource_github_repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,11 @@ func resourceGithubRepository() *schema.Resource {
Optional: true,
Default: false,
},
"topics": {
Type: schema.TypeList,
Elem: &schema.Schema{Type: schema.TypeString},
Optional: true,
},

"full_name": {
Type: schema.TypeString,
Expand Down Expand Up @@ -137,6 +142,7 @@ func resourceGithubRepositoryObject(d *schema.ResourceData) *github.Repository {
licenseTemplate := d.Get("license_template").(string)
gitIgnoreTemplate := d.Get("gitignore_template").(string)
archived := d.Get("archived").(bool)
topics := expandStringList(d.Get("topics").([]interface{}))

repo := &github.Repository{
Name: &name,
Expand All @@ -154,26 +160,36 @@ func resourceGithubRepositoryObject(d *schema.ResourceData) *github.Repository {
LicenseTemplate: &licenseTemplate,
GitignoreTemplate: &gitIgnoreTemplate,
Archived: &archived,
Topics: topics,
}

return repo
}

func resourceGithubRepositoryCreate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*Organization).client
ctx := context.TODO()

if _, ok := d.GetOk("default_branch"); ok {
return fmt.Errorf("Cannot set the default branch on a new repository.")
}

repoReq := resourceGithubRepositoryObject(d)
log.Printf("[DEBUG] create github repository %s/%s", meta.(*Organization).name, *repoReq.Name)
repo, _, err := client.Repositories.Create(context.TODO(), meta.(*Organization).name, repoReq)
repo, _, err := client.Repositories.Create(ctx, meta.(*Organization).name, repoReq)
if err != nil {
return err
}
d.SetId(*repo.Name)

topics := repoReq.Topics
if len(topics) > 0 {
_, _, err = client.Repositories.ReplaceAllTopics(ctx, meta.(*Organization).name, *repoReq.Name, topics)
if err != nil {
return err
}
}

return resourceGithubRepositoryUpdate(d, meta)
}

Expand Down Expand Up @@ -214,11 +230,13 @@ func resourceGithubRepositoryRead(d *schema.ResourceData, meta interface{}) erro
d.Set("git_clone_url", repo.GitURL)
d.Set("http_clone_url", repo.CloneURL)
d.Set("archived", repo.Archived)
d.Set("topics", flattenStringList(repo.Topics))
return nil
}

func resourceGithubRepositoryUpdate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*Organization).client
ctx := context.TODO()
repoReq := resourceGithubRepositoryObject(d)
// Can only set `default_branch` on an already created repository with the target branches ref already in-place
if v, ok := d.GetOk("default_branch"); ok {
Expand All @@ -231,12 +249,20 @@ func resourceGithubRepositoryUpdate(d *schema.ResourceData, meta interface{}) er

repoName := d.Id()
log.Printf("[DEBUG] update github repository %s/%s", meta.(*Organization).name, repoName)
repo, _, err := client.Repositories.Edit(context.TODO(), meta.(*Organization).name, repoName, repoReq)
repo, _, err := client.Repositories.Edit(ctx, meta.(*Organization).name, repoName, repoReq)
if err != nil {
return err
}
d.SetId(*repo.Name)

if d.HasChange("topics") {
topics := repoReq.Topics
_, _, err = client.Repositories.ReplaceAllTopics(ctx, meta.(*Organization).name, *repo.Name, topics)
if err != nil {
return err
}
}

return resourceGithubRepositoryRead(d, meta)
}

Expand Down
95 changes: 94 additions & 1 deletion github/resource_github_repository_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,75 @@ func TestAccGithubRepository_templates(t *testing.T) {
})
}

func TestAccGithubRepository_topics(t *testing.T) {
var repo github.Repository
randString := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)
name := fmt.Sprintf("tf-acc-test-%s", randString)
description := fmt.Sprintf("Terraform acceptance tests %s", randString)

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckGithubRepositoryDestroy,
Steps: []resource.TestStep{
{
Config: testAccGithubRepositoryConfigTopics(randString, `"topic1", "topic2"`),
Check: resource.ComposeTestCheckFunc(
testAccCheckGithubRepositoryExists("github_repository.foo", &repo),
testAccCheckGithubRepositoryAttributes(&repo, &testAccGithubRepositoryExpectedAttributes{
Name: name,
Description: description,
Homepage: "http://example.com/",
Topics: []string{"topic1", "topic2"},

// non-zero defaults
DefaultBranch: "master",
AllowMergeCommit: true,
AllowSquashMerge: true,
AllowRebaseMerge: true,
}),
),
},
{
Config: testAccGithubRepositoryConfigTopics(randString, `"topic1", "topic2", "topic3"`),
Check: resource.ComposeTestCheckFunc(
testAccCheckGithubRepositoryExists("github_repository.foo", &repo),
testAccCheckGithubRepositoryAttributes(&repo, &testAccGithubRepositoryExpectedAttributes{
Name: name,
Description: description,
Homepage: "http://example.com/",
Topics: []string{"topic1", "topic2", "topic3"},

// non-zero defaults
DefaultBranch: "master",
AllowMergeCommit: true,
AllowSquashMerge: true,
AllowRebaseMerge: true,
}),
),
},
{
Config: testAccGithubRepositoryConfigTopics(randString, ``),
Check: resource.ComposeTestCheckFunc(
testAccCheckGithubRepositoryExists("github_repository.foo", &repo),
testAccCheckGithubRepositoryAttributes(&repo, &testAccGithubRepositoryExpectedAttributes{
Name: name,
Description: description,
Homepage: "http://example.com/",
Topics: []string{},

// non-zero defaults
DefaultBranch: "master",
AllowMergeCommit: true,
AllowSquashMerge: true,
AllowRebaseMerge: true,
}),
),
},
},
})
}

func testAccCheckGithubRepositoryExists(n string, repo *github.Repository) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[n]
Expand Down Expand Up @@ -342,6 +411,7 @@ type testAccGithubRepositoryExpectedAttributes struct {
LicenseTemplate string
GitignoreTemplate string
Archived bool
Topics []string
}

func testAccCheckGithubRepositoryAttributes(repo *github.Repository, want *testAccGithubRepositoryExpectedAttributes) resource.TestCheckFunc {
Expand Down Expand Up @@ -377,7 +447,14 @@ func testAccCheckGithubRepositoryAttributes(repo *github.Repository, want *testA
if *repo.HasDownloads != want.HasDownloads {
return fmt.Errorf("got has downloads %#v; want %#v", *repo.HasDownloads, want.HasDownloads)
}

if len(want.Topics) != len(repo.Topics) {
return fmt.Errorf("got topics %#v; want %#v", repo.Topics, want.Topics)
}
for i := range want.Topics {
if repo.Topics[i] != want.Topics[i] {
return fmt.Errorf("got topics %#v; want %#v", repo.Topics, want.Topics)
}
}
if *repo.DefaultBranch != want.DefaultBranch {
return fmt.Errorf("got default branch %q; want %q", *repo.DefaultBranch, want.DefaultBranch)
}
Expand Down Expand Up @@ -628,3 +705,19 @@ resource "github_repository" "foo" {
}
`, randString, randString)
}

func testAccGithubRepositoryConfigTopics(randString string, topicList string) string {
return fmt.Sprintf(`
resource "github_repository" "foo" {
name = "tf-acc-test-%s"
description = "Terraform acceptance tests %s"
homepage_url = "http://example.com/"
# So that acceptance tests can be run in a github organization
# with no billing
private = false
topics = [%s]
}
`, randString, randString, topicList)
}
19 changes: 19 additions & 0 deletions github/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,22 @@ func validateTwoPartID(id string) error {
func buildTwoPartID(a, b *string) string {
return fmt.Sprintf("%s:%s", *a, *b)
}

func expandStringList(configured []interface{}) []string {
vs := make([]string, 0, len(configured))
for _, v := range configured {
val, ok := v.(string)
if ok && val != "" {
vs = append(vs, val)
}
}
return vs
}

func flattenStringList(v []string) []interface{} {
c := make([]interface{}, 0, len(v))
for _, s := range v {
c = append(c, s)
}
return c
}