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

New Resource: github_repository_project #115

Merged
merged 6 commits into from
Aug 10, 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
1 change: 1 addition & 0 deletions github/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ func Provider() terraform.ResourceProvider {
"github_repository": resourceGithubRepository(),
"github_repository_collaborator": resourceGithubRepositoryCollaborator(),
"github_repository_deploy_key": resourceGithubRepositoryDeployKey(),
"github_repository_project": resourceGithubRepositoryProject(),
"github_repository_webhook": resourceGithubRepositoryWebhook(),
"github_team": resourceGithubTeam(),
"github_team_membership": resourceGithubTeamMembership(),
Expand Down
131 changes: 131 additions & 0 deletions github/resource_github_repository_project.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
package github

import (
"context"
"fmt"
"strconv"
"strings"

"github.com/google/go-github/github"
"github.com/hashicorp/terraform/helper/schema"
)

func resourceGithubRepositoryProject() *schema.Resource {
return &schema.Resource{
Create: resourceGithubRepositoryProjectCreate,
Read: resourceGithubRepositoryProjectRead,
Update: resourceGithubRepositoryProjectUpdate,
Delete: resourceGithubRepositoryProjectDelete,
Importer: &schema.ResourceImporter{
State: func(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
parts := strings.Split(d.Id(), "/")
if len(parts) != 2 {
return nil, fmt.Errorf("Invalid ID specified. Supplied ID must be written as <repository>/<project_id>")
}
d.Set("repository", parts[0])
d.SetId(parts[1])
return []*schema.ResourceData{d}, nil
},
},

Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
},
"repository": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"body": {
Type: schema.TypeString,
Optional: true,
},
"url": {
Type: schema.TypeString,
Computed: true,
},
},
}
}

func resourceGithubRepositoryProjectCreate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*Organization).client

options := github.ProjectOptions{
Name: d.Get("name").(string),
Body: d.Get("body").(string),
}

project, _, err := client.Repositories.CreateProject(context.TODO(),
meta.(*Organization).name,
d.Get("repository").(string),
&options,
)
if err != nil {
return err
}
d.SetId(strconv.FormatInt(*project.ID, 10))

return resourceGithubRepositoryProjectRead(d, meta)
}

func resourceGithubRepositoryProjectRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*Organization).client
orgName := meta.(*Organization).name

projectID, err := strconv.ParseInt(d.Id(), 10, 64)
if err != nil {
return unconvertibleIdErr(d.Id(), err)
}

project, resp, err := client.Projects.GetProject(context.TODO(), projectID)
if err != nil {
if resp != nil && resp.StatusCode == 404 {
d.SetId("")
return nil
}
return err
}

d.Set("name", project.GetName())
d.Set("body", project.GetBody())
d.Set("url", fmt.Sprintf("https://github.com/%s/%s/projects/%d",
orgName, d.Get("repository"), project.GetNumber()))

return nil
}

func resourceGithubRepositoryProjectUpdate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*Organization).client

options := github.ProjectOptions{
Name: d.Get("name").(string),
Body: d.Get("body").(string),
}

projectID, err := strconv.ParseInt(d.Id(), 10, 64)
if err != nil {
return unconvertibleIdErr(d.Id(), err)
}

_, _, err = client.Projects.UpdateProject(context.TODO(), projectID, &options)
if err != nil {
return err
}

return resourceGithubRepositoryProjectRead(d, meta)
}

func resourceGithubRepositoryProjectDelete(d *schema.ResourceData, meta interface{}) error {
client := meta.(*Organization).client

projectID, err := strconv.ParseInt(d.Id(), 10, 64)
if err != nil {
return unconvertibleIdErr(d.Id(), err)
}

_, err = client.Projects.DeleteProject(context.TODO(), projectID)
return err
}
162 changes: 162 additions & 0 deletions github/resource_github_repository_project_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
package github

import (
"context"
"fmt"
"path"
"strconv"
"strings"
"testing"

"github.com/google/go-github/github"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)

func TestAccGithubRepositoryProject_basic(t *testing.T) {
randRepoName := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)
var project github.Project

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccGithubRepositoryProjectDestroy,
Steps: []resource.TestStep{
{
Config: testAccGithubRepositoryProjectConfig(randRepoName),
Check: resource.ComposeTestCheckFunc(
testAccCheckGithubRepositoryProjectExists("github_repository_project.test", &project),
testAccCheckGithubRepositoryProjectAttributes(&project, &testAccGithubRepositoryProjectExpectedAttributes{
Name: "test-project",
Repository: randRepoName,
Body: "this is a test project",
}),
),
},
},
})
}

func TestAccGithubRepositoryProject_importBasic(t *testing.T) {
randRepoName := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccGithubRepositoryProjectDestroy,
Steps: []resource.TestStep{
{
Config: testAccGithubRepositoryProjectConfig(randRepoName),
},
{
ResourceName: "github_repository_project.test",
ImportState: true,
ImportStateVerify: true,
ImportStateIdPrefix: randRepoName + `/`,
},
},
})
}

func testAccGithubRepositoryProjectDestroy(s *terraform.State) error {
conn := testAccProvider.Meta().(*Organization).client

for _, rs := range s.RootModule().Resources {
if rs.Type != "github_repository_project" {
continue
}

projectID, err := strconv.ParseInt(rs.Primary.ID, 10, 64)
if err != nil {
return err
}

project, res, err := conn.Projects.GetProject(context.TODO(), projectID)
if err == nil {
if project != nil &&
project.GetID() == projectID {
return fmt.Errorf("Repository project still exists")
}
}
if res.StatusCode != 404 {
return err
}
return nil
}
return nil
}

func testAccCheckGithubRepositoryProjectExists(n string, project *github.Project) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[n]
if !ok {
return fmt.Errorf("Not Found: %s", n)
}

projectID, err := strconv.ParseInt(rs.Primary.ID, 10, 64)
if err != nil {
return err
}

conn := testAccProvider.Meta().(*Organization).client
gotProject, _, err := conn.Projects.GetProject(context.TODO(), projectID)
if err != nil {
return err
}
*project = *gotProject
return nil
}
}

type testAccGithubRepositoryProjectExpectedAttributes struct {
Name string
Repository string
Body string
}

func testAccCheckGithubRepositoryProjectAttributes(project *github.Project, want *testAccGithubRepositoryProjectExpectedAttributes) resource.TestCheckFunc {
return func(s *terraform.State) error {

if *project.Name != want.Name {
return fmt.Errorf("got project %q; want %q", *project.Name, want.Name)
}
if got := path.Base(project.GetOwnerURL()); got != want.Repository {
return fmt.Errorf("got project %q; want %q", got, want.Repository)
}
if *project.Body != want.Body {
return fmt.Errorf("got project n%q; want %q", *project.Body, want.Body)
}
if !strings.HasPrefix(*project.URL, "https://") {
return fmt.Errorf("got http URL %q; want to start with 'https://'", *project.URL)
}

return nil
}
}

func testAccGithubRepositoryProjectConfig(repoName string) string {
return fmt.Sprintf(`
resource "github_repository" "foo" {
name = "%[1]s"
description = "Terraform acceptance tests"
homepage_url = "http://example.com/"

# So that acceptance tests can be run in a github organization
# with no billing
private = false

has_projects = true
has_issues = true
has_wiki = true
has_downloads = true
}

resource "github_repository_project" "test" {
depends_on = ["github_repository.foo"]

name = "test-project"
repository = "%[1]s"
body = "this is a test project"
}`, repoName)
}
43 changes: 43 additions & 0 deletions website/docs/r/repository_project.html.markdown
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
---
layout: "github"
page_title: "GitHub: github_repository_project"
sidebar_current: "docs-github-resource-repository-project"
description: |-
Creates and manages projects for Github repositories
---

# github_repository_project

This resource allows you to create and manage projects for Github repository.

## Example Usage

```hcl
resource "github_repository" "example" {
name = "example"
description = "My awesome codebase"
has_projects = true
}

resource "github_repository_project" "project" {
name = "A Repository Project"
repository = "${github_repository.example.name}"
body = "This is a repository project."
}
```

## Argument Reference

The following arguments are supported:

* `name` - (Required) The name of the project.

* `repository` - (Required) The repository of the project.

* `body` - (Optional) The body of the project.

## Attributes Reference

The following additional attributes are exported:

* `url` - URL of the project
3 changes: 3 additions & 0 deletions website/github.erb
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@
<li<%= sidebar_current("docs-github-resource-repository-deploy-key") %>>
<a href="/docs/providers/github/r/repository_deploy_key.html">github_repository_deploy_key</a>
</li>
<li<%= sidebar_current("docs-github-resource-repository-project") %>>
<a href="/docs/providers/github/r/repository_project.html">github_repository_project</a>
</li>
<li<%= sidebar_current("docs-github-resource-repository-webhook") %>>
<a href="/docs/providers/github/r/repository_webhook.html">github_repository_webhook</a>
</li>
Expand Down