From 03a77e9c92d3e003eaea1b97656fb2d0bc5ecf56 Mon Sep 17 00:00:00 2001 From: Brett Kuhlman Date: Wed, 21 Sep 2022 16:14:21 -0400 Subject: [PATCH] Adding resource github_organization_settings to provider closes#1125 (#1298) * adding resouce github_settings to provider * Spacing and comment changes Co-authored-by: Keegan Campbell --- github/provider.go | 1 + .../resource_github_organization_settings.go | 370 ++++++++++++++++++ ...ource_github_organization_settings_test.go | 183 +++++++++ ...source_github_repository_tag_protection.go | 2 +- go.mod | 2 +- go.sum | 4 + .../github.com/google/go-cmp/cmp/compare.go | 64 +-- .../google/go-cmp/cmp/internal/diff/diff.go | 44 ++- .../google/go-cmp/cmp/internal/value/zero.go | 48 --- .../github.com/google/go-cmp/cmp/options.go | 10 +- vendor/github.com/google/go-cmp/cmp/path.go | 20 +- .../google/go-cmp/cmp/report_compare.go | 10 +- .../google/go-cmp/cmp/report_reflect.go | 11 +- .../google/go-cmp/cmp/report_slices.go | 25 +- .../google/go-cmp/cmp/report_text.go | 1 + .../go-github/v47/github/actions_artifacts.go | 4 + .../google/go-github/v47/github/apps.go | 2 + .../google/go-github/v47/github/git_refs.go | 2 +- .../go-github/v47/github/github-accessors.go | 88 +++++ .../google/go-github/v47/github/orgs.go | 14 + .../google/go-github/v47/github/repos.go | 2 +- .../go-github/v47/github/repos_autolinks.go | 12 +- .../go-github/v47/github/repos_contents.go | 6 +- .../go-github/v47/github/repos_forks.go | 4 +- .../go-github/v47/github/repos_releases.go | 5 +- .../go-github/v47/github/secret_scanning.go | 8 + vendor/modules.txt | 4 +- .../r/organization_settings.html.markdown | 91 +++++ .../r/repository_tag_protection.html.markdown | 2 +- website/github.erb | 3 + 30 files changed, 894 insertions(+), 148 deletions(-) create mode 100644 github/resource_github_organization_settings.go create mode 100644 github/resource_github_organization_settings_test.go delete mode 100644 vendor/github.com/google/go-cmp/cmp/internal/value/zero.go create mode 100644 website/docs/r/organization_settings.html.markdown diff --git a/github/provider.go b/github/provider.go index 7e74993cd6..7990b420c6 100644 --- a/github/provider.go +++ b/github/provider.go @@ -109,6 +109,7 @@ func Provider() terraform.ResourceProvider { "github_membership": resourceGithubMembership(), "github_organization_block": resourceOrganizationBlock(), "github_organization_project": resourceGithubOrganizationProject(), + "github_organization_settings": resouceGithubOrganizationSettings(), "github_organization_webhook": resourceGithubOrganizationWebhook(), "github_project_card": resourceGithubProjectCard(), "github_project_column": resourceGithubProjectColumn(), diff --git a/github/resource_github_organization_settings.go b/github/resource_github_organization_settings.go new file mode 100644 index 0000000000..c8b0d1112d --- /dev/null +++ b/github/resource_github_organization_settings.go @@ -0,0 +1,370 @@ +package github + +import ( + "context" + "log" + "strconv" + + "github.com/google/go-github/v47/github" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/helper/validation" +) + +func resouceGithubOrganizationSettings() *schema.Resource { + return &schema.Resource{ + Create: resourceGithubOrganizationSettingsCreateOrUpdate, + Read: resourceGithubOrganizationSettingsRead, + Update: resourceGithubOrganizationSettingsCreateOrUpdate, + Delete: resourceGithubOrganizationSettingsDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + Schema: map[string]*schema.Schema{ + "billing_email": { + Type: schema.TypeString, + Required: true, + }, + "company": { + Type: schema.TypeString, + Optional: true, + }, + "email": { + Type: schema.TypeString, + Optional: true, + }, + "twitter_username": { + Type: schema.TypeString, + Optional: true, + }, + "location": { + Type: schema.TypeString, + Optional: true, + }, + "name": { + Type: schema.TypeString, + Optional: true, + }, + "description": { + Type: schema.TypeString, + Optional: true, + }, + "has_organization_projects": { + Type: schema.TypeBool, + Optional: true, + Default: true, + }, + "has_repository_projects": { + Type: schema.TypeBool, + Optional: true, + Default: true, + }, + "default_repository_permission": { + Type: schema.TypeString, + Optional: true, + Default: "read", + ValidateFunc: validation.StringInSlice([]string{"read", "write", "admin", "none"}, false), + }, + "members_can_create_repositories": { + Type: schema.TypeBool, + Optional: true, + Default: true, + }, + "members_can_create_internal_repositories": { + Type: schema.TypeBool, + Optional: true, + Description: "Setting to true allows organization members to create internal repositories. Only available to Enterprise Organizations.", + }, + "members_can_create_private_repositories": { + Type: schema.TypeBool, + Optional: true, + Default: true, + }, + "members_can_create_public_repositories": { + Type: schema.TypeBool, + Optional: true, + Default: true, + }, + "members_can_create_pages": { + Type: schema.TypeBool, + Optional: true, + Default: true, + }, + "members_can_create_public_pages": { + Type: schema.TypeBool, + Optional: true, + Default: true, + }, + "members_can_create_private_pages": { + Type: schema.TypeBool, + Optional: true, + Default: true, + }, + "members_can_fork_private_repositories": { + Type: schema.TypeBool, + Optional: true, + Default: false, + }, + "web_commit_signoff_required": { + Type: schema.TypeBool, + Optional: true, + Default: false, + }, + "blog": { + Type: schema.TypeString, + Optional: true, + }, + "advanced_security_enabled_for_new_repositories": { + Type: schema.TypeBool, + Optional: true, + Default: false, + }, + "dependabot_alerts_enabled_for_new_repositories": { + Type: schema.TypeBool, + Optional: true, + Default: false, + }, + "dependabot_security_updates_enabled_for_new_repositories": { + Type: schema.TypeBool, + Optional: true, + Default: false, + }, + "dependency_graph_enabled_for_new_repositories": { + Type: schema.TypeBool, + Optional: true, + Default: false, + }, + "secret_scanning_enabled_for_new_repositories": { + Type: schema.TypeBool, + Optional: true, + Default: false, + }, + "secret_scanning_push_protection_enabled_for_new_repositories": { + Type: schema.TypeBool, + Optional: true, + Default: false, + }, + }, + } +} + +func resourceGithubOrganizationSettingsCreateOrUpdate(d *schema.ResourceData, meta interface{}) error { + err := checkOrganization(meta) + if err != nil { + return err + } + client := meta.(*Owner).v3client + ctx := context.WithValue(context.Background(), ctxId, d.Id()) + org := meta.(*Owner).name + + settings := github.Organization{ + BillingEmail: github.String(d.Get("billing_email").(string)), + Company: github.String(d.Get("company").(string)), + Email: github.String(d.Get("email").(string)), + TwitterUsername: github.String(d.Get("twitter_username").(string)), + Location: github.String(d.Get("location").(string)), + Name: github.String(d.Get("name").(string)), + Description: github.String(d.Get("description").(string)), + HasOrganizationProjects: github.Bool(d.Get("has_organization_projects").(bool)), + HasRepositoryProjects: github.Bool(d.Get("has_repository_projects").(bool)), + DefaultRepoPermission: github.String(d.Get("default_repository_permission").(string)), + MembersCanCreateRepos: github.Bool(d.Get("members_can_create_repositories").(bool)), + MembersCanCreatePrivateRepos: github.Bool(d.Get("members_can_create_private_repositories").(bool)), + MembersCanCreatePublicRepos: github.Bool(d.Get("members_can_create_public_repositories").(bool)), + MembersCanCreatePages: github.Bool(d.Get("members_can_create_pages").(bool)), + MembersCanCreatePublicPages: github.Bool(d.Get("members_can_create_public_pages").(bool)), + MembersCanCreatePrivatePages: github.Bool(d.Get("members_can_create_private_pages").(bool)), + MembersCanForkPrivateRepos: github.Bool(d.Get("members_can_fork_private_repositories").(bool)), + WebCommitSignoffRequired: github.Bool(d.Get("web_commit_signoff_required").(bool)), + Blog: github.String(d.Get("blog").(string)), + AdvancedSecurityEnabledForNewRepos: github.Bool(d.Get("advanced_security_enabled_for_new_repositories").(bool)), + DependabotAlertsEnabledForNewRepos: github.Bool(d.Get("dependabot_alerts_enabled_for_new_repositories").(bool)), + DependabotSecurityUpdatesEnabledForNewRepos: github.Bool(d.Get("dependabot_security_updates_enabled_for_new_repositories").(bool)), + DependencyGraphEnabledForNewRepos: github.Bool(d.Get("dependency_graph_enabled_for_new_repositories").(bool)), + SecretScanningEnabledForNewRepos: github.Bool(d.Get("secret_scanning_enabled_for_new_repositories").(bool)), + SecretScanningPushProtectionEnabledForNewRepos: github.Bool(d.Get("secret_scanning_push_protection_enabled_for_new_repositories").(bool)), + } + + enterpriseSettings := github.Organization{ + BillingEmail: github.String(d.Get("billing_email").(string)), + Company: github.String(d.Get("company").(string)), + Email: github.String(d.Get("email").(string)), + TwitterUsername: github.String(d.Get("twitter_username").(string)), + Location: github.String(d.Get("location").(string)), + Name: github.String(d.Get("name").(string)), + Description: github.String(d.Get("description").(string)), + HasOrganizationProjects: github.Bool(d.Get("has_organization_projects").(bool)), + HasRepositoryProjects: github.Bool(d.Get("has_repository_projects").(bool)), + DefaultRepoPermission: github.String(d.Get("default_repository_permission").(string)), + MembersCanCreateRepos: github.Bool(d.Get("members_can_create_repositories").(bool)), + MembersCanCreateInternalRepos: github.Bool(d.Get("members_can_create_internal_repositories").(bool)), + MembersCanCreatePrivateRepos: github.Bool(d.Get("members_can_create_private_repositories").(bool)), + MembersCanCreatePublicRepos: github.Bool(d.Get("members_can_create_public_repositories").(bool)), + MembersCanCreatePages: github.Bool(d.Get("members_can_create_pages").(bool)), + MembersCanCreatePublicPages: github.Bool(d.Get("members_can_create_public_pages").(bool)), + MembersCanCreatePrivatePages: github.Bool(d.Get("members_can_create_private_pages").(bool)), + MembersCanForkPrivateRepos: github.Bool(d.Get("members_can_fork_private_repositories").(bool)), + WebCommitSignoffRequired: github.Bool(d.Get("web_commit_signoff_required").(bool)), + Blog: github.String(d.Get("blog").(string)), + AdvancedSecurityEnabledForNewRepos: github.Bool(d.Get("advanced_security_enabled_for_new_repositories").(bool)), + DependabotAlertsEnabledForNewRepos: github.Bool(d.Get("dependabot_alerts_enabled_for_new_repositories").(bool)), + DependabotSecurityUpdatesEnabledForNewRepos: github.Bool(d.Get("dependabot_security_updates_enabled_for_new_repositories").(bool)), + DependencyGraphEnabledForNewRepos: github.Bool(d.Get("dependency_graph_enabled_for_new_repositories").(bool)), + SecretScanningEnabledForNewRepos: github.Bool(d.Get("secret_scanning_enabled_for_new_repositories").(bool)), + SecretScanningPushProtectionEnabledForNewRepos: github.Bool(d.Get("secret_scanning_push_protection_enabled_for_new_repositories").(bool)), + } + + orgPlan, _, err := client.Organizations.Edit(ctx, org, nil) + if err != nil { + return err + } + + if orgPlan.GetPlan().GetName() == "free" { + orgSettings, _, err := client.Organizations.Edit(ctx, org, &settings) + if err != nil { + return err + } + id := strconv.FormatInt(orgSettings.GetID(), 10) + d.SetId(id) + } else { + orgSettings, _, err := client.Organizations.Edit(ctx, org, &enterpriseSettings) + if err != nil { + return err + } + id := strconv.FormatInt(orgSettings.GetID(), 10) + d.SetId(id) + } + + return resourceGithubOrganizationSettingsRead(d, meta) +} + +func resourceGithubOrganizationSettingsRead(d *schema.ResourceData, meta interface{}) error { + err := checkOrganization(meta) + if err != nil { + return err + } + client := meta.(*Owner).v3client + ctx := context.Background() + org := meta.(*Owner).name + + orgSettings, _, err := client.Organizations.Edit(ctx, org, nil) + if err != nil { + return err + } + + d.Set("billing_email", orgSettings.GetBillingEmail()) + d.Set("company", orgSettings.GetCompany()) + d.Set("email", orgSettings.GetEmail()) + d.Set("twitter_username", orgSettings.GetTwitterUsername()) + d.Set("location", orgSettings.GetLocation()) + d.Set("name", orgSettings.GetName()) + d.Set("description", orgSettings.GetDescription()) + d.Set("has_organization_projects", orgSettings.GetHasOrganizationProjects()) + d.Set("has_repository_projects", orgSettings.GetHasRepositoryProjects()) + d.Set("default_repository_permission", orgSettings.GetDefaultRepoPermission()) + d.Set("members_can_create_repositories", orgSettings.GetMembersCanCreateRepos()) + d.Set("members_can_create_internal_repositories", orgSettings.GetMembersCanCreateInternalRepos()) + d.Set("members_can_create_private_repositories", orgSettings.GetMembersCanCreatePrivateRepos()) + d.Set("members_can_create_public_repositories", orgSettings.GetMembersCanCreatePublicRepos()) + d.Set("members_can_create_pages", orgSettings.GetMembersCanCreatePages()) + d.Set("members_can_create_public_pages", orgSettings.GetMembersCanCreatePublicPages()) + d.Set("members_can_create_private_pages", orgSettings.GetMembersCanCreatePrivatePages()) + d.Set("members_can_fork_private_repositories", orgSettings.GetMembersCanForkPrivateRepos()) + d.Set("web_commit_signoff_required", orgSettings.GetWebCommitSignoffRequired()) + d.Set("blog", orgSettings.GetBlog()) + d.Set("advanced_security_enabled_for_new_repositories", orgSettings.GetAdvancedSecurityEnabledForNewRepos()) + d.Set("dependabot_alerts_enabled_for_new_repositories", orgSettings.GetDependabotAlertsEnabledForNewRepos()) + d.Set("dependabot_security_updates_enabled_for_new_repositories", orgSettings.GetDependabotSecurityUpdatesEnabledForNewRepos()) + d.Set("dependency_graph_enabled_for_new_repositories", orgSettings.GetDependencyGraphEnabledForNewRepos()) + d.Set("secret_scanning_enabled_for_new_repositories", orgSettings.GetSecretScanningEnabledForNewRepos()) + d.Set("secret_scanning_push_protection_enabled_for_new_repositories", orgSettings.GetSecretScanningPushProtectionEnabledForNewRepos()) + + return nil +} + +func resourceGithubOrganizationSettingsDelete(d *schema.ResourceData, meta interface{}) error { + err := checkOrganization(meta) + if err != nil { + return err + } + + client := meta.(*Owner).v3client + ctx := context.WithValue(context.Background(), ctxId, d.Id()) + org := meta.(*Owner).name + + // This will set org settings to default values + settings := github.Organization{ + BillingEmail: github.String("email@example.com"), + Company: github.String(""), + Email: github.String(""), + TwitterUsername: github.String(""), + Location: github.String(""), + Name: github.String(""), + Description: github.String(""), + HasOrganizationProjects: github.Bool(true), + HasRepositoryProjects: github.Bool(true), + DefaultRepoPermission: github.String("read"), + MembersCanCreateRepos: github.Bool(true), + MembersCanCreatePrivateRepos: github.Bool(true), + MembersCanCreatePublicRepos: github.Bool(true), + MembersCanCreatePages: github.Bool(false), + MembersCanCreatePublicPages: github.Bool(true), + MembersCanCreatePrivatePages: github.Bool(true), + MembersCanForkPrivateRepos: github.Bool(false), + WebCommitSignoffRequired: github.Bool(false), + Blog: github.String(""), + AdvancedSecurityEnabledForNewRepos: github.Bool(false), + DependabotAlertsEnabledForNewRepos: github.Bool(false), + DependabotSecurityUpdatesEnabledForNewRepos: github.Bool(false), + DependencyGraphEnabledForNewRepos: github.Bool(false), + SecretScanningEnabledForNewRepos: github.Bool(false), + SecretScanningPushProtectionEnabledForNewRepos: github.Bool(false), + } + + enterpriseSettings := github.Organization{ + BillingEmail: github.String("email@example.com"), + Company: github.String(""), + Email: github.String(""), + TwitterUsername: github.String(""), + Location: github.String(""), + Name: github.String(""), + Description: github.String(""), + HasOrganizationProjects: github.Bool(true), + HasRepositoryProjects: github.Bool(true), + DefaultRepoPermission: github.String("read"), + MembersCanCreateRepos: github.Bool(true), + MembersCanCreatePrivateRepos: github.Bool(true), + MembersCanCreateInternalRepos: github.Bool(true), + MembersCanCreatePublicRepos: github.Bool(true), + MembersCanCreatePages: github.Bool(false), + MembersCanCreatePublicPages: github.Bool(true), + MembersCanCreatePrivatePages: github.Bool(true), + MembersCanForkPrivateRepos: github.Bool(false), + WebCommitSignoffRequired: github.Bool(false), + Blog: github.String(""), + AdvancedSecurityEnabledForNewRepos: github.Bool(false), + DependabotAlertsEnabledForNewRepos: github.Bool(false), + DependabotSecurityUpdatesEnabledForNewRepos: github.Bool(false), + DependencyGraphEnabledForNewRepos: github.Bool(false), + SecretScanningEnabledForNewRepos: github.Bool(false), + SecretScanningPushProtectionEnabledForNewRepos: github.Bool(false), + } + + log.Printf("[DEBUG] Reverting Organization Settings to default values: %s", org) + orgPlan, _, err := client.Organizations.Edit(ctx, org, nil) + if err != nil { + return err + } + if orgPlan.GetPlan().GetName() == "free" { + _, _, err := client.Organizations.Edit(ctx, org, &settings) + if err != nil { + return err + } + } else { + _, _, err := client.Organizations.Edit(ctx, org, &enterpriseSettings) + if err != nil { + return err + } + } + + return nil +} diff --git a/github/resource_github_organization_settings_test.go b/github/resource_github_organization_settings_test.go new file mode 100644 index 0000000000..fc63b7b800 --- /dev/null +++ b/github/resource_github_organization_settings_test.go @@ -0,0 +1,183 @@ +package github + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" +) + +func TestAccGithubOrganizationSettings(t *testing.T) { + t.Run("creates organization settings without error", func(t *testing.T) { + + config := ` + resource "github_organization_settings" "test" { + billing_email = "test@example.com" + company = "Test Company" + blog = "https://example.com" + email = "test@example.com" + twitter_username = "Test" + location = "Test Location" + name = "Test Name" + description = "Test Description" + has_organization_projects = true + has_repository_projects = true + default_repository_permission = "read" + members_can_create_repositories = true + members_can_create_public_repositories = true + members_can_create_private_repositories = true + members_can_create_internal_repositories = false + members_can_create_pages = true + members_can_create_public_pages = true + members_can_create_private_pages = true + members_can_fork_private_repositories = true + web_commit_signoff_required = true + advanced_security_enabled_for_new_repositories = false + dependabot_alerts_enabled_for_new_repositories= false + dependabot_security_updates_enabled_for_new_repositories = false + dependency_graph_enabled_for_new_repositories = false + secret_scanning_enabled_for_new_repositories = false + secret_scanning_push_protection_enabled_for_new_repositories = false + }` + + check := resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "github_organization_settings.test", + "billing_email", "test@example.com", + ), + ) + testCase := func(t *testing.T, mode string) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { skipUnlessMode(t, mode) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: config, + Check: check, + }, + }, + }) + } + t.Run("run with an anonymous account", func(t *testing.T) { + t.Skip("anonymous account not supported for this operation") + }) + t.Run("run with an individual account", func(t *testing.T) { + t.Skip("individual account not supported for this operation") + }) + t.Run("run with an organization account", func(t *testing.T) { + testCase(t, organization) + }) + + }) + t.Run("updates organization settings without error", func(t *testing.T) { + billingEmail := "test1@example.com" + company := "Test Company" + blog := "https://test.com" + updatedBillingEmail := "test2@example.com" + updatedCompany := "Test Company 2" + updatedBlog := "https://test2.com" + + configs := map[string]string{ + "before": fmt.Sprintf(` + resource "github_organization_settings" "test" { + billing_email = "%s" + company = "%s" + blog = "%s" + }`, billingEmail, company, blog), + + "after": fmt.Sprintf(` + resource "github_organization_settings" "test" { + billing_email = "%s" + company = "%s" + blog = "%s" + }`, updatedBillingEmail, updatedCompany, updatedBlog), + } + checks := map[string]resource.TestCheckFunc{ + "before": resource.TestCheckResourceAttr( + "github_organization_settings.test", + "billing_email", billingEmail, + ), + "after": resource.TestCheckResourceAttr( + "github_organization_settings.test", + "billing_email", updatedBillingEmail, + ), + } + testCase := func(t *testing.T, mode string) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { skipUnlessMode(t, mode) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: configs["before"], + Check: checks["before"], + }, + { + Config: configs["after"], + Check: checks["after"], + }, + }, + }) + } + + t.Run("with an anonymous account", func(t *testing.T) { + t.Skip("anonymous account not supported for this operation") + }) + + t.Run("with an individual account", func(t *testing.T) { + t.Skip("individual account not supported for this operation") + }) + + t.Run("with an organization account", func(t *testing.T) { + testCase(t, organization) + }) + }) + + t.Run("imports organization settings without error", func(t *testing.T) { + billingEmail := "test@example.com" + company := "Test Company" + blog := "https://example.com" + + config := fmt.Sprintf(` + resource "github_organization_settings" "test" { + billing_email = "%s" + company = "%s" + blog = "%s" + }`, billingEmail, company, blog) + + check := resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "github_organization_settings.test", + "billing_email", billingEmail, + ), + ) + + testCase := func(t *testing.T, mode string) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { skipUnlessMode(t, mode) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: config, + Check: check, + }, + { + ResourceName: "github_organization_settings.test", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) + } + t.Run("with an anonymous account", func(t *testing.T) { + t.Skip("anonymous account not supported for this operation") + }) + + t.Run("with an individual account", func(t *testing.T) { + t.Skip("individual account not supported for this operation") + }) + + t.Run("with an organization account", func(t *testing.T) { + testCase(t, organization) + }) + }) +} diff --git a/github/resource_github_repository_tag_protection.go b/github/resource_github_repository_tag_protection.go index 83af3b10db..489730ce48 100644 --- a/github/resource_github_repository_tag_protection.go +++ b/github/resource_github_repository_tag_protection.go @@ -21,7 +21,7 @@ func resourceGithubRepositoryTagProtection() *schema.Resource { 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 /") + return nil, fmt.Errorf("Invalid ID specified. Supplied ID must be written as /") } d.Set("repository", parts[0]) d.Set("tag_protection_id", parts[1]) diff --git a/go.mod b/go.mod index b91d281892..6625dfac5a 100644 --- a/go.mod +++ b/go.mod @@ -18,7 +18,7 @@ require ( github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0 // indirect github.com/golangci/misspell v0.3.5 // indirect github.com/golangci/revgrep v0.0.0-20220804021717-745bb2f7c2e6 // indirect - github.com/google/go-github/v47 v47.0.0 + github.com/google/go-github/v47 v47.1.0 github.com/google/uuid v1.3.0 // indirect github.com/gostaticanalysis/analysisutil v0.7.1 // indirect github.com/gostaticanalysis/testutil v0.4.0 // indirect diff --git a/go.sum b/go.sum index f132c35c16..268f72ed99 100644 --- a/go.sum +++ b/go.sum @@ -315,8 +315,12 @@ github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-github/v47 v47.0.0 h1:eQap5bIRZibukP0VhngWgpuM0zhY4xntqOzn6DhdkE4= github.com/google/go-github/v47 v47.0.0/go.mod h1:DRjdvizXE876j0YOZwInB1ESpOcU/xFBClNiQLSdorE= +github.com/google/go-github/v47 v47.1.0 h1:Cacm/WxQBOa9lF0FT0EMjZ2BWMetQ1TQfyurn4yF1z8= +github.com/google/go-github/v47 v47.1.0/go.mod h1:VPZBXNbFSJGjyjFRUKo9vZGawTajnWzC/YjGw/oFKi0= github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no= diff --git a/vendor/github.com/google/go-cmp/cmp/compare.go b/vendor/github.com/google/go-cmp/cmp/compare.go index fd2b3a42b2..087320da7f 100644 --- a/vendor/github.com/google/go-cmp/cmp/compare.go +++ b/vendor/github.com/google/go-cmp/cmp/compare.go @@ -13,21 +13,21 @@ // // The primary features of cmp are: // -// • When the default behavior of equality does not suit the needs of the test, -// custom equality functions can override the equality operation. -// For example, an equality function may report floats as equal so long as they -// are within some tolerance of each other. +// - When the default behavior of equality does not suit the test's needs, +// custom equality functions can override the equality operation. +// For example, an equality function may report floats as equal so long as +// they are within some tolerance of each other. // -// • Types that have an Equal method may use that method to determine equality. -// This allows package authors to determine the equality operation for the types -// that they define. +// - Types with an Equal method may use that method to determine equality. +// This allows package authors to determine the equality operation +// for the types that they define. // -// • If no custom equality functions are used and no Equal method is defined, -// equality is determined by recursively comparing the primitive kinds on both -// values, much like reflect.DeepEqual. Unlike reflect.DeepEqual, unexported -// fields are not compared by default; they result in panics unless suppressed -// by using an Ignore option (see cmpopts.IgnoreUnexported) or explicitly -// compared using the Exporter option. +// - If no custom equality functions are used and no Equal method is defined, +// equality is determined by recursively comparing the primitive kinds on +// both values, much like reflect.DeepEqual. Unlike reflect.DeepEqual, +// unexported fields are not compared by default; they result in panics +// unless suppressed by using an Ignore option (see cmpopts.IgnoreUnexported) +// or explicitly compared using the Exporter option. package cmp import ( @@ -45,25 +45,25 @@ import ( // Equal reports whether x and y are equal by recursively applying the // following rules in the given order to x and y and all of their sub-values: // -// • Let S be the set of all Ignore, Transformer, and Comparer options that -// remain after applying all path filters, value filters, and type filters. -// If at least one Ignore exists in S, then the comparison is ignored. -// If the number of Transformer and Comparer options in S is greater than one, -// then Equal panics because it is ambiguous which option to use. -// If S contains a single Transformer, then use that to transform the current -// values and recursively call Equal on the output values. -// If S contains a single Comparer, then use that to compare the current values. -// Otherwise, evaluation proceeds to the next rule. +// - Let S be the set of all Ignore, Transformer, and Comparer options that +// remain after applying all path filters, value filters, and type filters. +// If at least one Ignore exists in S, then the comparison is ignored. +// If the number of Transformer and Comparer options in S is non-zero, +// then Equal panics because it is ambiguous which option to use. +// If S contains a single Transformer, then use that to transform +// the current values and recursively call Equal on the output values. +// If S contains a single Comparer, then use that to compare the current values. +// Otherwise, evaluation proceeds to the next rule. // -// • If the values have an Equal method of the form "(T) Equal(T) bool" or -// "(T) Equal(I) bool" where T is assignable to I, then use the result of -// x.Equal(y) even if x or y is nil. Otherwise, no such method exists and -// evaluation proceeds to the next rule. +// - If the values have an Equal method of the form "(T) Equal(T) bool" or +// "(T) Equal(I) bool" where T is assignable to I, then use the result of +// x.Equal(y) even if x or y is nil. Otherwise, no such method exists and +// evaluation proceeds to the next rule. // -// • Lastly, try to compare x and y based on their basic kinds. -// Simple kinds like booleans, integers, floats, complex numbers, strings, and -// channels are compared using the equivalent of the == operator in Go. -// Functions are only equal if they are both nil, otherwise they are unequal. +// - Lastly, try to compare x and y based on their basic kinds. +// Simple kinds like booleans, integers, floats, complex numbers, strings, +// and channels are compared using the equivalent of the == operator in Go. +// Functions are only equal if they are both nil, otherwise they are unequal. // // Structs are equal if recursively calling Equal on all fields report equal. // If a struct contains unexported fields, Equal panics unless an Ignore option @@ -144,7 +144,7 @@ func rootStep(x, y interface{}) PathStep { // so that they have the same parent type. var t reflect.Type if !vx.IsValid() || !vy.IsValid() || vx.Type() != vy.Type() { - t = reflect.TypeOf((*interface{})(nil)).Elem() + t = anyType if vx.IsValid() { vvx := reflect.New(t).Elem() vvx.Set(vx) @@ -639,7 +639,9 @@ type dynChecker struct{ curr, next int } // Next increments the state and reports whether a check should be performed. // // Checks occur every Nth function call, where N is a triangular number: +// // 0 1 3 6 10 15 21 28 36 45 55 66 78 91 105 120 136 153 171 190 ... +// // See https://en.wikipedia.org/wiki/Triangular_number // // This sequence ensures that the cost of checks drops significantly as diff --git a/vendor/github.com/google/go-cmp/cmp/internal/diff/diff.go b/vendor/github.com/google/go-cmp/cmp/internal/diff/diff.go index bc196b16cf..a248e5436d 100644 --- a/vendor/github.com/google/go-cmp/cmp/internal/diff/diff.go +++ b/vendor/github.com/google/go-cmp/cmp/internal/diff/diff.go @@ -127,9 +127,9 @@ var randBool = rand.New(rand.NewSource(time.Now().Unix())).Intn(2) == 0 // This function returns an edit-script, which is a sequence of operations // needed to convert one list into the other. The following invariants for // the edit-script are maintained: -// • eq == (es.Dist()==0) -// • nx == es.LenX() -// • ny == es.LenY() +// - eq == (es.Dist()==0) +// - nx == es.LenX() +// - ny == es.LenY() // // This algorithm is not guaranteed to be an optimal solution (i.e., one that // produces an edit-script with a minimal Levenshtein distance). This algorithm @@ -169,12 +169,13 @@ func Difference(nx, ny int, f EqualFunc) (es EditScript) { // A diagonal edge is equivalent to a matching symbol between both X and Y. // Invariants: - // • 0 ≤ fwdPath.X ≤ (fwdFrontier.X, revFrontier.X) ≤ revPath.X ≤ nx - // • 0 ≤ fwdPath.Y ≤ (fwdFrontier.Y, revFrontier.Y) ≤ revPath.Y ≤ ny + // - 0 ≤ fwdPath.X ≤ (fwdFrontier.X, revFrontier.X) ≤ revPath.X ≤ nx + // - 0 ≤ fwdPath.Y ≤ (fwdFrontier.Y, revFrontier.Y) ≤ revPath.Y ≤ ny // // In general: - // • fwdFrontier.X < revFrontier.X - // • fwdFrontier.Y < revFrontier.Y + // - fwdFrontier.X < revFrontier.X + // - fwdFrontier.Y < revFrontier.Y + // // Unless, it is time for the algorithm to terminate. fwdPath := path{+1, point{0, 0}, make(EditScript, 0, (nx+ny)/2)} revPath := path{-1, point{nx, ny}, make(EditScript, 0)} @@ -195,19 +196,21 @@ func Difference(nx, ny int, f EqualFunc) (es EditScript) { // computing sub-optimal edit-scripts between two lists. // // The algorithm is approximately as follows: - // • Searching for differences switches back-and-forth between - // a search that starts at the beginning (the top-left corner), and - // a search that starts at the end (the bottom-right corner). The goal of - // the search is connect with the search from the opposite corner. - // • As we search, we build a path in a greedy manner, where the first - // match seen is added to the path (this is sub-optimal, but provides a - // decent result in practice). When matches are found, we try the next pair - // of symbols in the lists and follow all matches as far as possible. - // • When searching for matches, we search along a diagonal going through - // through the "frontier" point. If no matches are found, we advance the - // frontier towards the opposite corner. - // • This algorithm terminates when either the X coordinates or the - // Y coordinates of the forward and reverse frontier points ever intersect. + // - Searching for differences switches back-and-forth between + // a search that starts at the beginning (the top-left corner), and + // a search that starts at the end (the bottom-right corner). + // The goal of the search is connect with the search + // from the opposite corner. + // - As we search, we build a path in a greedy manner, + // where the first match seen is added to the path (this is sub-optimal, + // but provides a decent result in practice). When matches are found, + // we try the next pair of symbols in the lists and follow all matches + // as far as possible. + // - When searching for matches, we search along a diagonal going through + // through the "frontier" point. If no matches are found, + // we advance the frontier towards the opposite corner. + // - This algorithm terminates when either the X coordinates or the + // Y coordinates of the forward and reverse frontier points ever intersect. // This algorithm is correct even if searching only in the forward direction // or in the reverse direction. We do both because it is commonly observed @@ -389,6 +392,7 @@ type point struct{ X, Y int } func (p *point) add(dx, dy int) { p.X += dx; p.Y += dy } // zigzag maps a consecutive sequence of integers to a zig-zag sequence. +// // [0 1 2 3 4 5 ...] => [0 -1 +1 -2 +2 ...] func zigzag(x int) int { if x&1 != 0 { diff --git a/vendor/github.com/google/go-cmp/cmp/internal/value/zero.go b/vendor/github.com/google/go-cmp/cmp/internal/value/zero.go deleted file mode 100644 index 9147a29973..0000000000 --- a/vendor/github.com/google/go-cmp/cmp/internal/value/zero.go +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2017, The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package value - -import ( - "math" - "reflect" -) - -// IsZero reports whether v is the zero value. -// This does not rely on Interface and so can be used on unexported fields. -func IsZero(v reflect.Value) bool { - switch v.Kind() { - case reflect.Bool: - return v.Bool() == false - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - return v.Int() == 0 - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - return v.Uint() == 0 - case reflect.Float32, reflect.Float64: - return math.Float64bits(v.Float()) == 0 - case reflect.Complex64, reflect.Complex128: - return math.Float64bits(real(v.Complex())) == 0 && math.Float64bits(imag(v.Complex())) == 0 - case reflect.String: - return v.String() == "" - case reflect.UnsafePointer: - return v.Pointer() == 0 - case reflect.Chan, reflect.Func, reflect.Interface, reflect.Ptr, reflect.Map, reflect.Slice: - return v.IsNil() - case reflect.Array: - for i := 0; i < v.Len(); i++ { - if !IsZero(v.Index(i)) { - return false - } - } - return true - case reflect.Struct: - for i := 0; i < v.NumField(); i++ { - if !IsZero(v.Field(i)) { - return false - } - } - return true - } - return false -} diff --git a/vendor/github.com/google/go-cmp/cmp/options.go b/vendor/github.com/google/go-cmp/cmp/options.go index e57b9eb539..1f9ca9c489 100644 --- a/vendor/github.com/google/go-cmp/cmp/options.go +++ b/vendor/github.com/google/go-cmp/cmp/options.go @@ -33,6 +33,7 @@ type Option interface { } // applicableOption represents the following types: +// // Fundamental: ignore | validator | *comparer | *transformer // Grouping: Options type applicableOption interface { @@ -43,6 +44,7 @@ type applicableOption interface { } // coreOption represents the following types: +// // Fundamental: ignore | validator | *comparer | *transformer // Filters: *pathFilter | *valuesFilter type coreOption interface { @@ -336,9 +338,9 @@ func (tr transformer) String() string { // both implement T. // // The equality function must be: -// • Symmetric: equal(x, y) == equal(y, x) -// • Deterministic: equal(x, y) == equal(x, y) -// • Pure: equal(x, y) does not modify x or y +// - Symmetric: equal(x, y) == equal(y, x) +// - Deterministic: equal(x, y) == equal(x, y) +// - Pure: equal(x, y) does not modify x or y func Comparer(f interface{}) Option { v := reflect.ValueOf(f) if !function.IsType(v.Type(), function.Equal) || v.IsNil() { @@ -430,7 +432,7 @@ func AllowUnexported(types ...interface{}) Option { } // Result represents the comparison result for a single node and -// is provided by cmp when calling Result (see Reporter). +// is provided by cmp when calling Report (see Reporter). type Result struct { _ [0]func() // Make Result incomparable flags resultFlags diff --git a/vendor/github.com/google/go-cmp/cmp/path.go b/vendor/github.com/google/go-cmp/cmp/path.go index c710034632..a0a588502e 100644 --- a/vendor/github.com/google/go-cmp/cmp/path.go +++ b/vendor/github.com/google/go-cmp/cmp/path.go @@ -41,13 +41,13 @@ type PathStep interface { // The type of each valid value is guaranteed to be identical to Type. // // In some cases, one or both may be invalid or have restrictions: - // • For StructField, both are not interface-able if the current field - // is unexported and the struct type is not explicitly permitted by - // an Exporter to traverse unexported fields. - // • For SliceIndex, one may be invalid if an element is missing from - // either the x or y slice. - // • For MapIndex, one may be invalid if an entry is missing from - // either the x or y map. + // - For StructField, both are not interface-able if the current field + // is unexported and the struct type is not explicitly permitted by + // an Exporter to traverse unexported fields. + // - For SliceIndex, one may be invalid if an element is missing from + // either the x or y slice. + // - For MapIndex, one may be invalid if an entry is missing from + // either the x or y map. // // The provided values must not be mutated. Values() (vx, vy reflect.Value) @@ -94,6 +94,7 @@ func (pa Path) Index(i int) PathStep { // The simplified path only contains struct field accesses. // // For example: +// // MyMap.MySlices.MyField func (pa Path) String() string { var ss []string @@ -108,6 +109,7 @@ func (pa Path) String() string { // GoString returns the path to a specific node using Go syntax. // // For example: +// // (*root.MyMap["key"].(*mypkg.MyStruct).MySlices)[2][3].MyField func (pa Path) GoString() string { var ssPre, ssPost []string @@ -159,7 +161,7 @@ func (ps pathStep) String() string { if ps.typ == nil { return "" } - s := ps.typ.String() + s := value.TypeString(ps.typ, false) if s == "" || strings.ContainsAny(s, "{}\n") { return "root" // Type too simple or complex to print } @@ -282,7 +284,7 @@ type typeAssertion struct { func (ta TypeAssertion) Type() reflect.Type { return ta.typ } func (ta TypeAssertion) Values() (vx, vy reflect.Value) { return ta.vx, ta.vy } -func (ta TypeAssertion) String() string { return fmt.Sprintf(".(%v)", ta.typ) } +func (ta TypeAssertion) String() string { return fmt.Sprintf(".(%v)", value.TypeString(ta.typ, false)) } // Transform is a transformation from the parent type to the current type. type Transform struct{ *transform } diff --git a/vendor/github.com/google/go-cmp/cmp/report_compare.go b/vendor/github.com/google/go-cmp/cmp/report_compare.go index 1ef65ac1db..2050bf6b46 100644 --- a/vendor/github.com/google/go-cmp/cmp/report_compare.go +++ b/vendor/github.com/google/go-cmp/cmp/report_compare.go @@ -7,8 +7,6 @@ package cmp import ( "fmt" "reflect" - - "github.com/google/go-cmp/cmp/internal/value" ) // numContextRecords is the number of surrounding equal records to print. @@ -117,7 +115,7 @@ func (opts formatOptions) FormatDiff(v *valueNode, ptrs *pointerReferences) (out // For leaf nodes, format the value based on the reflect.Values alone. // As a special case, treat equal []byte as a leaf nodes. - isBytes := v.Type.Kind() == reflect.Slice && v.Type.Elem() == reflect.TypeOf(byte(0)) + isBytes := v.Type.Kind() == reflect.Slice && v.Type.Elem() == byteType isEqualBytes := isBytes && v.NumDiff+v.NumIgnored+v.NumTransformed == 0 if v.MaxDepth == 0 || isEqualBytes { switch opts.DiffMode { @@ -248,11 +246,11 @@ func (opts formatOptions) formatDiffList(recs []reportRecord, k reflect.Kind, pt var isZero bool switch opts.DiffMode { case diffIdentical: - isZero = value.IsZero(r.Value.ValueX) || value.IsZero(r.Value.ValueY) + isZero = r.Value.ValueX.IsZero() || r.Value.ValueY.IsZero() case diffRemoved: - isZero = value.IsZero(r.Value.ValueX) + isZero = r.Value.ValueX.IsZero() case diffInserted: - isZero = value.IsZero(r.Value.ValueY) + isZero = r.Value.ValueY.IsZero() } if isZero { continue diff --git a/vendor/github.com/google/go-cmp/cmp/report_reflect.go b/vendor/github.com/google/go-cmp/cmp/report_reflect.go index 287b893588..2ab41fad3f 100644 --- a/vendor/github.com/google/go-cmp/cmp/report_reflect.go +++ b/vendor/github.com/google/go-cmp/cmp/report_reflect.go @@ -16,6 +16,13 @@ import ( "github.com/google/go-cmp/cmp/internal/value" ) +var ( + anyType = reflect.TypeOf((*interface{})(nil)).Elem() + stringType = reflect.TypeOf((*string)(nil)).Elem() + bytesType = reflect.TypeOf((*[]byte)(nil)).Elem() + byteType = reflect.TypeOf((*byte)(nil)).Elem() +) + type formatValueOptions struct { // AvoidStringer controls whether to avoid calling custom stringer // methods like error.Error or fmt.Stringer.String. @@ -184,7 +191,7 @@ func (opts formatOptions) FormatValue(v reflect.Value, parentKind reflect.Kind, } for i := 0; i < v.NumField(); i++ { vv := v.Field(i) - if value.IsZero(vv) { + if vv.IsZero() { continue // Elide fields with zero values } if len(list) == maxLen { @@ -205,7 +212,7 @@ func (opts formatOptions) FormatValue(v reflect.Value, parentKind reflect.Kind, } // Check whether this is a []byte of text data. - if t.Elem() == reflect.TypeOf(byte(0)) { + if t.Elem() == byteType { b := v.Bytes() isPrintSpace := func(r rune) bool { return unicode.IsPrint(r) || unicode.IsSpace(r) } if len(b) > 0 && utf8.Valid(b) && len(bytes.TrimFunc(b, isPrintSpace)) == 0 { diff --git a/vendor/github.com/google/go-cmp/cmp/report_slices.go b/vendor/github.com/google/go-cmp/cmp/report_slices.go index 68b5c1ae16..23e444f62f 100644 --- a/vendor/github.com/google/go-cmp/cmp/report_slices.go +++ b/vendor/github.com/google/go-cmp/cmp/report_slices.go @@ -104,7 +104,7 @@ func (opts formatOptions) FormatDiffSlice(v *valueNode) textNode { case t.Kind() == reflect.String: sx, sy = vx.String(), vy.String() isString = true - case t.Kind() == reflect.Slice && t.Elem() == reflect.TypeOf(byte(0)): + case t.Kind() == reflect.Slice && t.Elem() == byteType: sx, sy = string(vx.Bytes()), string(vy.Bytes()) isString = true case t.Kind() == reflect.Array: @@ -147,7 +147,10 @@ func (opts formatOptions) FormatDiffSlice(v *valueNode) textNode { }) efficiencyLines := float64(esLines.Dist()) / float64(len(esLines)) efficiencyBytes := float64(esBytes.Dist()) / float64(len(esBytes)) - isPureLinedText = efficiencyLines < 4*efficiencyBytes + quotedLength := len(strconv.Quote(sx + sy)) + unquotedLength := len(sx) + len(sy) + escapeExpansionRatio := float64(quotedLength) / float64(unquotedLength) + isPureLinedText = efficiencyLines < 4*efficiencyBytes || escapeExpansionRatio > 1.1 } } @@ -171,12 +174,13 @@ func (opts formatOptions) FormatDiffSlice(v *valueNode) textNode { // differences in a string literal. This format is more readable, // but has edge-cases where differences are visually indistinguishable. // This format is avoided under the following conditions: - // • A line starts with `"""` - // • A line starts with "..." - // • A line contains non-printable characters - // • Adjacent different lines differ only by whitespace + // - A line starts with `"""` + // - A line starts with "..." + // - A line contains non-printable characters + // - Adjacent different lines differ only by whitespace // // For example: + // // """ // ... // 3 identical lines // foo @@ -231,7 +235,7 @@ func (opts formatOptions) FormatDiffSlice(v *valueNode) textNode { var out textNode = &textWrap{Prefix: "(", Value: list2, Suffix: ")"} switch t.Kind() { case reflect.String: - if t != reflect.TypeOf(string("")) { + if t != stringType { out = opts.FormatType(t, out) } case reflect.Slice: @@ -326,12 +330,12 @@ func (opts formatOptions) FormatDiffSlice(v *valueNode) textNode { switch t.Kind() { case reflect.String: out = &textWrap{Prefix: "strings.Join(", Value: out, Suffix: fmt.Sprintf(", %q)", delim)} - if t != reflect.TypeOf(string("")) { + if t != stringType { out = opts.FormatType(t, out) } case reflect.Slice: out = &textWrap{Prefix: "bytes.Join(", Value: out, Suffix: fmt.Sprintf(", %q)", delim)} - if t != reflect.TypeOf([]byte(nil)) { + if t != bytesType { out = opts.FormatType(t, out) } } @@ -446,7 +450,6 @@ func (opts formatOptions) formatDiffSlice( // {NumIdentical: 3}, // {NumInserted: 1}, // ] -// func coalesceAdjacentEdits(name string, es diff.EditScript) (groups []diffStats) { var prevMode byte lastStats := func(mode byte) *diffStats { @@ -503,7 +506,6 @@ func coalesceAdjacentEdits(name string, es diff.EditScript) (groups []diffStats) // {NumIdentical: 8, NumRemoved: 12, NumInserted: 3}, // {NumIdentical: 63}, // ] -// func coalesceInterveningIdentical(groups []diffStats, windowSize int) []diffStats { groups, groupsOrig := groups[:0], groups for i, ds := range groupsOrig { @@ -548,7 +550,6 @@ func coalesceInterveningIdentical(groups []diffStats, windowSize int) []diffStat // {NumRemoved: 9}, // {NumIdentical: 64}, // incremented by 10 // ] -// func cleanupSurroundingIdentical(groups []diffStats, eq func(i, j int) bool) []diffStats { var ix, iy int // indexes into sequence x and y for i, ds := range groups { diff --git a/vendor/github.com/google/go-cmp/cmp/report_text.go b/vendor/github.com/google/go-cmp/cmp/report_text.go index 0fd46d7ffb..388fcf5712 100644 --- a/vendor/github.com/google/go-cmp/cmp/report_text.go +++ b/vendor/github.com/google/go-cmp/cmp/report_text.go @@ -393,6 +393,7 @@ func (s diffStats) Append(ds diffStats) diffStats { // String prints a humanly-readable summary of coalesced records. // // Example: +// // diffStats{Name: "Field", NumIgnored: 5}.String() => "5 ignored fields" func (s diffStats) String() string { var ss []string diff --git a/vendor/github.com/google/go-github/v47/github/actions_artifacts.go b/vendor/github.com/google/go-github/v47/github/actions_artifacts.go index 3b9c83c490..99329d989d 100644 --- a/vendor/github.com/google/go-github/v47/github/actions_artifacts.go +++ b/vendor/github.com/google/go-github/v47/github/actions_artifacts.go @@ -121,6 +121,10 @@ func (s *ActionsService) DownloadArtifact(ctx context.Context, owner, repo strin } parsedURL, err := url.Parse(resp.Header.Get("Location")) + if err != nil { + return nil, newResponse(resp), err + } + return parsedURL, newResponse(resp), nil } diff --git a/vendor/github.com/google/go-github/v47/github/apps.go b/vendor/github.com/google/go-github/v47/github/apps.go index 0e92f7b719..98d8a6fda3 100644 --- a/vendor/github.com/google/go-github/v47/github/apps.go +++ b/vendor/github.com/google/go-github/v47/github/apps.go @@ -77,7 +77,9 @@ type InstallationPermissions struct { Metadata *string `json:"metadata,omitempty"` Members *string `json:"members,omitempty"` OrganizationAdministration *string `json:"organization_administration,omitempty"` + OrganizationCustomRoles *string `json:"organization_custom_roles,omitempty"` OrganizationHooks *string `json:"organization_hooks,omitempty"` + OrganizationPackages *string `json:"organization_packages,omitempty"` OrganizationPlan *string `json:"organization_plan,omitempty"` OrganizationPreReceiveHooks *string `json:"organization_pre_receive_hooks,omitempty"` OrganizationProjects *string `json:"organization_projects,omitempty"` diff --git a/vendor/github.com/google/go-github/v47/github/git_refs.go b/vendor/github.com/google/go-github/v47/github/git_refs.go index 883975cc0f..e839c30f66 100644 --- a/vendor/github.com/google/go-github/v47/github/git_refs.go +++ b/vendor/github.com/google/go-github/v47/github/git_refs.go @@ -142,7 +142,7 @@ func (s *GitService) CreateRef(ctx context.Context, owner string, repo string, r // GitHub API docs: https://docs.github.com/en/rest/git/refs#update-a-reference func (s *GitService) UpdateRef(ctx context.Context, owner string, repo string, ref *Reference, force bool) (*Reference, *Response, error) { refPath := strings.TrimPrefix(*ref.Ref, "refs/") - u := fmt.Sprintf("repos/%v/%v/git/refs/%v", owner, repo, refPath) + u := fmt.Sprintf("repos/%v/%v/git/refs/%v", owner, repo, refURLEscape(refPath)) req, err := s.client.NewRequest("PATCH", u, &updateRefRequest{ SHA: ref.Object.SHA, Force: &force, diff --git a/vendor/github.com/google/go-github/v47/github/github-accessors.go b/vendor/github.com/google/go-github/v47/github/github-accessors.go index 1b1c9d9511..398ed7a3b4 100644 --- a/vendor/github.com/google/go-github/v47/github/github-accessors.go +++ b/vendor/github.com/google/go-github/v47/github/github-accessors.go @@ -1374,6 +1374,14 @@ func (a *Autolink) GetID() int64 { return *a.ID } +// GetIsAlphanumeric returns the IsAlphanumeric field if it's non-nil, zero value otherwise. +func (a *Autolink) GetIsAlphanumeric() bool { + if a == nil || a.IsAlphanumeric == nil { + return false + } + return *a.IsAlphanumeric +} + // GetKeyPrefix returns the KeyPrefix field if it's non-nil, zero value otherwise. func (a *Autolink) GetKeyPrefix() string { if a == nil || a.KeyPrefix == nil { @@ -1390,6 +1398,14 @@ func (a *Autolink) GetURLTemplate() string { return *a.URLTemplate } +// GetIsAlphanumeric returns the IsAlphanumeric field if it's non-nil, zero value otherwise. +func (a *AutolinkOptions) GetIsAlphanumeric() bool { + if a == nil || a.IsAlphanumeric == nil { + return false + } + return *a.IsAlphanumeric +} + // GetKeyPrefix returns the KeyPrefix field if it's non-nil, zero value otherwise. func (a *AutolinkOptions) GetKeyPrefix() string { if a == nil || a.KeyPrefix == nil { @@ -6574,6 +6590,14 @@ func (i *InstallationPermissions) GetOrganizationAdministration() string { return *i.OrganizationAdministration } +// GetOrganizationCustomRoles returns the OrganizationCustomRoles field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetOrganizationCustomRoles() string { + if i == nil || i.OrganizationCustomRoles == nil { + return "" + } + return *i.OrganizationCustomRoles +} + // GetOrganizationHooks returns the OrganizationHooks field if it's non-nil, zero value otherwise. func (i *InstallationPermissions) GetOrganizationHooks() string { if i == nil || i.OrganizationHooks == nil { @@ -6582,6 +6606,14 @@ func (i *InstallationPermissions) GetOrganizationHooks() string { return *i.OrganizationHooks } +// GetOrganizationPackages returns the OrganizationPackages field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetOrganizationPackages() string { + if i == nil || i.OrganizationPackages == nil { + return "" + } + return *i.OrganizationPackages +} + // GetOrganizationPlan returns the OrganizationPlan field if it's non-nil, zero value otherwise. func (i *InstallationPermissions) GetOrganizationPlan() string { if i == nil || i.OrganizationPlan == nil { @@ -9398,6 +9430,14 @@ func (o *OAuthAPP) GetURL() string { return *o.URL } +// GetAdvancedSecurityEnabledForNewRepos returns the AdvancedSecurityEnabledForNewRepos field if it's non-nil, zero value otherwise. +func (o *Organization) GetAdvancedSecurityEnabledForNewRepos() bool { + if o == nil || o.AdvancedSecurityEnabledForNewRepos == nil { + return false + } + return *o.AdvancedSecurityEnabledForNewRepos +} + // GetAvatarURL returns the AvatarURL field if it's non-nil, zero value otherwise. func (o *Organization) GetAvatarURL() string { if o == nil || o.AvatarURL == nil { @@ -9462,6 +9502,30 @@ func (o *Organization) GetDefaultRepoSettings() string { return *o.DefaultRepoSettings } +// GetDependabotAlertsEnabledForNewRepos returns the DependabotAlertsEnabledForNewRepos field if it's non-nil, zero value otherwise. +func (o *Organization) GetDependabotAlertsEnabledForNewRepos() bool { + if o == nil || o.DependabotAlertsEnabledForNewRepos == nil { + return false + } + return *o.DependabotAlertsEnabledForNewRepos +} + +// GetDependabotSecurityUpdatesEnabledForNewRepos returns the DependabotSecurityUpdatesEnabledForNewRepos field if it's non-nil, zero value otherwise. +func (o *Organization) GetDependabotSecurityUpdatesEnabledForNewRepos() bool { + if o == nil || o.DependabotSecurityUpdatesEnabledForNewRepos == nil { + return false + } + return *o.DependabotSecurityUpdatesEnabledForNewRepos +} + +// GetDependencyGraphEnabledForNewRepos returns the DependencyGraphEnabledForNewRepos field if it's non-nil, zero value otherwise. +func (o *Organization) GetDependencyGraphEnabledForNewRepos() bool { + if o == nil || o.DependencyGraphEnabledForNewRepos == nil { + return false + } + return *o.DependencyGraphEnabledForNewRepos +} + // GetDescription returns the Description field if it's non-nil, zero value otherwise. func (o *Organization) GetDescription() string { if o == nil || o.Description == nil { @@ -9734,6 +9798,22 @@ func (o *Organization) GetReposURL() string { return *o.ReposURL } +// GetSecretScanningEnabledForNewRepos returns the SecretScanningEnabledForNewRepos field if it's non-nil, zero value otherwise. +func (o *Organization) GetSecretScanningEnabledForNewRepos() bool { + if o == nil || o.SecretScanningEnabledForNewRepos == nil { + return false + } + return *o.SecretScanningEnabledForNewRepos +} + +// GetSecretScanningPushProtectionEnabledForNewRepos returns the SecretScanningPushProtectionEnabledForNewRepos field if it's non-nil, zero value otherwise. +func (o *Organization) GetSecretScanningPushProtectionEnabledForNewRepos() bool { + if o == nil || o.SecretScanningPushProtectionEnabledForNewRepos == nil { + return false + } + return *o.SecretScanningPushProtectionEnabledForNewRepos +} + // GetTotalPrivateRepos returns the TotalPrivateRepos field if it's non-nil, zero value otherwise. func (o *Organization) GetTotalPrivateRepos() int { if o == nil || o.TotalPrivateRepos == nil { @@ -9782,6 +9862,14 @@ func (o *Organization) GetURL() string { return *o.URL } +// GetWebCommitSignoffRequired returns the WebCommitSignoffRequired field if it's non-nil, zero value otherwise. +func (o *Organization) GetWebCommitSignoffRequired() bool { + if o == nil || o.WebCommitSignoffRequired == nil { + return false + } + return *o.WebCommitSignoffRequired +} + // GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise. func (o *OrganizationCustomRepoRoles) GetTotalCount() int { if o == nil || o.TotalCount == nil { diff --git a/vendor/github.com/google/go-github/v47/github/orgs.go b/vendor/github.com/google/go-github/v47/github/orgs.go index 26b55c62d0..8105afad38 100644 --- a/vendor/github.com/google/go-github/v47/github/orgs.go +++ b/vendor/github.com/google/go-github/v47/github/orgs.go @@ -82,6 +82,20 @@ type Organization struct { MembersCanCreatePublicPages *bool `json:"members_can_create_public_pages,omitempty"` // MembersCanCreatePrivatePages toggles whether organization members can create private GitHub Pages sites. MembersCanCreatePrivatePages *bool `json:"members_can_create_private_pages,omitempty"` + // WebCommitSignoffRequire toggles + WebCommitSignoffRequired *bool `json:"web_commit_signoff_required,omitempty"` + // AdvancedSecurityAuditLogEnabled toggles whether the advanced security audit log is enabled. + AdvancedSecurityEnabledForNewRepos *bool `json:"advanced_security_enabled_for_new_repositories,omitempty"` + // DependabotAlertsEnabled toggles whether dependabot alerts are enabled. + DependabotAlertsEnabledForNewRepos *bool `json:"dependabot_alerts_enabled_for_new_repositories,omitempty"` + // DependabotSecurityUpdatesEnabled toggles whether dependabot security updates are enabled. + DependabotSecurityUpdatesEnabledForNewRepos *bool `json:"dependabot_security_updates_enabled_for_new_repositories,omitempty"` + // DependabotGraphEnabledForNewRepos toggles whether dependabot graph is enabled on new repositories. + DependencyGraphEnabledForNewRepos *bool `json:"dependency_graph_enabled_for_new_repositories,omitempty"` + // SecretScanningEnabled toggles whether secret scanning is enabled on new repositories. + SecretScanningEnabledForNewRepos *bool `json:"secret_scanning_enabled_for_new_repositories,omitempty"` + // SecretScanningPushProtectionEnabledForNewRepos toggles whether secret scanning push protection is enabled on new repositories. + SecretScanningPushProtectionEnabledForNewRepos *bool `json:"secret_scanning_push_protection_enabled_for_new_repositories,omitempty"` // API URLs URL *string `json:"url,omitempty"` diff --git a/vendor/github.com/google/go-github/v47/github/repos.go b/vendor/github.com/google/go-github/v47/github/repos.go index 499ed67786..45fd1888d5 100644 --- a/vendor/github.com/google/go-github/v47/github/repos.go +++ b/vendor/github.com/google/go-github/v47/github/repos.go @@ -905,7 +905,7 @@ type RequiredStatusChecks struct { Contexts []string `json:"contexts,omitempty"` // The list of status checks to require in order to merge into this // branch. - Checks []*RequiredStatusCheck `json:"checks,omitempty"` + Checks []*RequiredStatusCheck `json:"checks"` } // RequiredStatusChecksRequest represents a request to edit a protected branch's status checks. diff --git a/vendor/github.com/google/go-github/v47/github/repos_autolinks.go b/vendor/github.com/google/go-github/v47/github/repos_autolinks.go index 8fa916eac2..0d2cec618f 100644 --- a/vendor/github.com/google/go-github/v47/github/repos_autolinks.go +++ b/vendor/github.com/google/go-github/v47/github/repos_autolinks.go @@ -12,15 +12,17 @@ import ( // AutolinkOptions specifies parameters for RepositoriesService.AddAutolink method. type AutolinkOptions struct { - KeyPrefix *string `json:"key_prefix,omitempty"` - URLTemplate *string `json:"url_template,omitempty"` + KeyPrefix *string `json:"key_prefix,omitempty"` + URLTemplate *string `json:"url_template,omitempty"` + IsAlphanumeric *bool `json:"is_alphanumeric,omitempty"` } // Autolink represents autolinks to external resources like JIRA issues and Zendesk tickets. type Autolink struct { - ID *int64 `json:"id,omitempty"` - KeyPrefix *string `json:"key_prefix,omitempty"` - URLTemplate *string `json:"url_template,omitempty"` + ID *int64 `json:"id,omitempty"` + KeyPrefix *string `json:"key_prefix,omitempty"` + URLTemplate *string `json:"url_template,omitempty"` + IsAlphanumeric *bool `json:"is_alphanumeric,omitempty"` } // ListAutolinks returns a list of autolinks configured for the given repository. diff --git a/vendor/github.com/google/go-github/v47/github/repos_contents.go b/vendor/github.com/google/go-github/v47/github/repos_contents.go index 431d4b12dc..be58fd52f6 100644 --- a/vendor/github.com/google/go-github/v47/github/repos_contents.go +++ b/vendor/github.com/google/go-github/v47/github/repos_contents.go @@ -317,5 +317,9 @@ func (s *RepositoriesService) GetArchiveLink(ctx context.Context, owner, repo st } parsedURL, err := url.Parse(resp.Header.Get("Location")) - return parsedURL, newResponse(resp), err + if err != nil { + return nil, newResponse(resp), err + } + + return parsedURL, newResponse(resp), nil } diff --git a/vendor/github.com/google/go-github/v47/github/repos_forks.go b/vendor/github.com/google/go-github/v47/github/repos_forks.go index 97bb328ffb..5c7d5dbd78 100644 --- a/vendor/github.com/google/go-github/v47/github/repos_forks.go +++ b/vendor/github.com/google/go-github/v47/github/repos_forks.go @@ -53,7 +53,9 @@ func (s *RepositoriesService) ListForks(ctx context.Context, owner, repo string, // RepositoriesService.CreateFork method. type RepositoryCreateForkOptions struct { // The organization to fork the repository into. - Organization string `url:"organization,omitempty"` + Organization string `url:"organization,omitempty"` + Name string `url:"name,omitempty"` + DefaultBranchOnly bool `url:"default_branch_only,omitempty"` } // CreateFork creates a fork of the specified repository. diff --git a/vendor/github.com/google/go-github/v47/github/repos_releases.go b/vendor/github.com/google/go-github/v47/github/repos_releases.go index f1ab65c185..c030f04d9a 100644 --- a/vendor/github.com/google/go-github/v47/github/repos_releases.go +++ b/vendor/github.com/google/go-github/v47/github/repos_releases.go @@ -26,7 +26,9 @@ type RepositoryRelease struct { Draft *bool `json:"draft,omitempty"` Prerelease *bool `json:"prerelease,omitempty"` DiscussionCategoryName *string `json:"discussion_category_name,omitempty"` - GenerateReleaseNotes *bool `json:"generate_release_notes,omitempty"` + + // The following fields are not used in EditRelease: + GenerateReleaseNotes *bool `json:"generate_release_notes,omitempty"` // The following fields are not used in CreateRelease or EditRelease: ID *int64 `json:"id,omitempty"` @@ -228,7 +230,6 @@ func (s *RepositoriesService) EditRelease(ctx context.Context, owner, repo strin Draft: release.Draft, Prerelease: release.Prerelease, DiscussionCategoryName: release.DiscussionCategoryName, - GenerateReleaseNotes: release.GenerateReleaseNotes, } req, err := s.client.NewRequest("PATCH", u, releaseReq) diff --git a/vendor/github.com/google/go-github/v47/github/secret_scanning.go b/vendor/github.com/google/go-github/v47/github/secret_scanning.go index ec64950a67..d512560d9f 100644 --- a/vendor/github.com/google/go-github/v47/github/secret_scanning.go +++ b/vendor/github.com/google/go-github/v47/github/secret_scanning.go @@ -61,6 +61,14 @@ type SecretScanningAlertListOptions struct { Resolution string `url:"resolution,omitempty"` ListCursorOptions + + // List options can vary on the Enterprise type. + // On Enterprise Cloud, Secret Scan alerts support requesting by page number + // along with providing a cursor for an "after" param. + // See: https://docs.github.com/en/enterprise-cloud@latest/rest/secret-scanning#list-secret-scanning-alerts-for-an-organization + // Whereas on Enterprise Server, pagination is by index. + // See: https://docs.github.com/en/enterprise-server@3.6/rest/secret-scanning#list-secret-scanning-alerts-for-an-organization + ListOptions } // SecretScanningAlertUpdateOptions specifies optional parameters to the SecretScanningService.UpdateAlert method. diff --git a/vendor/modules.txt b/vendor/modules.txt index 27263f4192..f87e2ec521 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -234,13 +234,13 @@ github.com/golangci/prealloc github.com/golangci/revgrep # github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4 github.com/golangci/unconvert -# github.com/google/go-cmp v0.5.8 +# github.com/google/go-cmp v0.5.9 github.com/google/go-cmp/cmp github.com/google/go-cmp/cmp/internal/diff github.com/google/go-cmp/cmp/internal/flags github.com/google/go-cmp/cmp/internal/function github.com/google/go-cmp/cmp/internal/value -# github.com/google/go-github/v47 v47.0.0 +# github.com/google/go-github/v47 v47.1.0 ## explicit github.com/google/go-github/v47/github # github.com/google/go-querystring v1.1.0 diff --git a/website/docs/r/organization_settings.html.markdown b/website/docs/r/organization_settings.html.markdown new file mode 100644 index 0000000000..c8a4db54a6 --- /dev/null +++ b/website/docs/r/organization_settings.html.markdown @@ -0,0 +1,91 @@ +--- +layout: "github" +page_title: "GitHub: github_organization_settings" +description: |- + Creates and manages settings for a GitHub Organization. +--- + +# github_organization_settings + +This resource allows you to create and manage settings for a GitHub Organization. + +## Example Usage + +```hcl +resource "github_organization_settings" "test" { + billing_email = "test@example.com" + company = "Test Company" + blog = "https://example.com" + email = "test@example.com" + twitter_username = "Test" + location = "Test Location" + name = "Test Name" + description = "Test Description" + has_organization_projects = true + has_repository_projects = true + default_repository_permission = "read" + members_can_create_repositories = true + members_can_create_public_repositories = true + members_can_create_private_repositories = true + members_can_create_internal_repositories = true + members_can_create_pages = true + members_can_create_public_pages = true + members_can_create_private_pages = true + members_can_fork_private_repositories = true + web_commit_signoff_required = true + advanced_security_enabled_for_new_repositories = false + dependabot_alerts_enabled_for_new_repositories= false + dependabot_security_updates_enabled_for_new_repositories = false + dependency_graph_enabled_for_new_repositories = false + secret_scanning_enabled_for_new_repositories = false + secret_scanning_push_protection_enabled_for_new_repositories = false +} +``` + +## Argument Reference + +The following arguments are supported: + +* `billing_email` - (Required) The billing email address for the organization. +* `company` - (Optional) The company name for the organization. +* `blog` - (Optional) The blog URL for the organization. +* `email` - (Optional) The email address for the organization. +* `twitter_username` - (Optional) The Twitter username for the organization. +* `location` - (Optional) The location for the organization. +* `name` - (Optional) The name for the organization. +* `description` - (Optional) The description for the organization. +* `has_organization_projects` - (Optional) Whether or not organization projects are enabled for the organization. +* `has_repository_projects` - (Optional) Whether or not repository projects are enabled for the organization. +* `default_repository_permission` - (Optional) The default permission for organization members to create new repositories. Can be one of `read`, `write`, `admin`, or `none`. Defaults to `read`. +* `members_can_create_repositories` - (Optional) Whether or not organization members can create new repositories. Defaults to `true`. +* `members_can_create_public_repositories` - (Optional) Whether or not organization members can create new public repositories. Defaults to `true`. +* `members_can_create_private_repositories` - (Optional) Whether or not organization members can create new private repositories. Defaults to `true`. +* `members_can_create_internal_repositories` - (Optional) Whether or not organization members can create new internal repositories. For Enterprise Organizations only. +* `members_can_create_pages` - (Optional) Whether or not organization members can create new pages. Defaults to `true`. +* `members_can_create_public_pages` - (Optional) Whether or not organization members can create new public pages. Defaults to `true`. +* `members_can_create_private_pages` - (Optional) Whether or not organization members can create new private pages. Defaults to `true`. +* `members_can_fork_private_repositories` - (Optional) Whether or not organization members can fork private repositories. Defaults to `false`. +* `web_commit_signoff_required` - (Optional) Whether or not commit signatures are required for commits to the organization. Defaults to `false`. +* `advanced_security_enabled_for_new_repositories` - (Optional) Whether or not advanced security is enabled for new repositories. Defaults to `false`. +* `dependabot_alerts_enabled_for_new_repositories` - (Optional) Whether or not dependabot alerts are enabled for new repositories. Defaults to `false`. +* `dependabot_security_updates_enabled_for_new_repositories` - (Optional) Whether or not dependabot security updates are enabled for new repositories. Defaults to `false`. +* `dependency_graph_enabled_for_new_repositories` - (Optional) Whether or not dependency graph is enabled for new repositories. Defaults to `false`. +* `secret_scanning_enabled_for_new_repositories` - (Optional) Whether or not secret scanning is enabled for new repositories. Defaults to `false`. +* `secret_scanning_push_protection_enabled_for_new_repositories` - (Optional) Whether or not secret scanning push protection is enabled for new repositories. Defaults to `false`. + + +## Attributes Reference + +The following additional attributes are exported: + +* `id` - The ID of the organization settings. + + +## Import + +Organization settings can be imported using the `id` of the organization. +The `id` of the organization can be found using the [get an organization](https://docs.github.com/en/rest/orgs/orgs#get-an-organization) API. + +``` +$ terraform import github_organization_settings.test 123456789 +``` diff --git a/website/docs/r/repository_tag_protection.html.markdown b/website/docs/r/repository_tag_protection.html.markdown index 0199defed0..cf04504bd6 100644 --- a/website/docs/r/repository_tag_protection.html.markdown +++ b/website/docs/r/repository_tag_protection.html.markdown @@ -35,7 +35,7 @@ The following additional attributes are exported: Repository tag protections can be imported using the `name` of the repository, combined with the `id` of the tag protection, separated by a `/` character. The `id` of the tag protection can be found using the [GitHub API](https://docs.github.com/en/rest/repos/tags#list-tag-protection-states-for-a-repository). -Importing uses the name of the repository, as well as the ID of the webhook, e.g. +Importing uses the name of the repository, as well as the ID of the tag protection, e.g. ``` $ terraform import github_repository_tag_protection.terraform my-repo/31077 diff --git a/website/github.erb b/website/github.erb index d2b7b3dba7..3cd6e44a5f 100644 --- a/website/github.erb +++ b/website/github.erb @@ -139,6 +139,9 @@
  • github_organization_project
  • +
  • + github_organization_settings +
  • github_organization_webhook