From 33c5a23b4ce1f44c0c78fe4749b8daddda77eb7b Mon Sep 17 00:00:00 2001 From: Lasse Gaardsholt Date: Wed, 13 May 2026 15:40:19 +0200 Subject: [PATCH 01/15] feat: add github_organization_private_registry resource and data source This introduces the `github_organization_private_registry` resource and data source, allowing users to configure and manage centralized private registries at the organization level for Dependabot. Includes full CRUD acceptance tests, examples, and documentation. Signed-off-by: Lasse Gaardsholt --- .../organization_private_registry.md | 46 ++ .../organization_private_registry.md | 55 +++ .../data-source.tf | 3 + .../resource.tf | 8 + ...ce_github_organization_private_registry.go | 188 +++++++ ...thub_organization_private_registry_test.go | 44 ++ github/provider.go | 2 + ...ce_github_organization_private_registry.go | 457 ++++++++++++++++++ ...thub_organization_private_registry_test.go | 45 ++ .../organization_private_registry.md.tmpl | 42 ++ .../organization_private_registry.md.tmpl | 46 ++ 11 files changed, 936 insertions(+) create mode 100644 docs/data-sources/organization_private_registry.md create mode 100644 docs/resources/organization_private_registry.md create mode 100644 examples/data-sources/github_organization_private_registry/data-source.tf create mode 100644 examples/resources/github_organization_private_registry/resource.tf create mode 100644 github/data_source_github_organization_private_registry.go create mode 100644 github/data_source_github_organization_private_registry_test.go create mode 100644 github/resource_github_organization_private_registry.go create mode 100644 github/resource_github_organization_private_registry_test.go create mode 100644 templates/data-sources/organization_private_registry.md.tmpl create mode 100644 templates/resources/organization_private_registry.md.tmpl diff --git a/docs/data-sources/organization_private_registry.md b/docs/data-sources/organization_private_registry.md new file mode 100644 index 0000000000..c688ef5055 --- /dev/null +++ b/docs/data-sources/organization_private_registry.md @@ -0,0 +1,46 @@ +--- +page_title: "github_organization_private_registry (Data Source) - GitHub" +description: |- + Retrieves information about a specific organization private registry. +--- + +# github_organization_private_registry (Data Source) + +Use this data source to retrieve information about a specific organization private registry. + +## Example Usage + +```terraform +data "github_organization_private_registry" "my_registry" { + name = "NPM_REGISTRY_SECRET_1" +} +``` + +## Argument Reference + +The following arguments are supported: + +- `name` - (Required) The name of the private registry. + +## Attributes Reference + +- `id` - The ID of the private registry. +- `registry_type` - The registry type. Can be `maven_repository`, `nuget_feed`, `goproxy_server`, `npm_registry`, `rubygems_server`, `cargo_registry`, `composer_repository`, `docker_registry`, `git_source`, `helm_registry`, `pub_repository`, `python_index`, or `terraform_registry`. +- `visibility` - Configures the access that repositories have to the organization private registry. Must be one of `all`, `private`, or `selected`. +- `auth_type` - The authentication type for the private registry. Can be `token`, `username_password`, `oidc_azure`, `oidc_aws`, or `oidc_jfrog`. +- `url` - The URL of the private registry. +- `username` - The username to use when authenticating with the private registry. +- `replaces_base` - Whether this registry replaces a base registry. +- `selected_repository_ids` - An array of repository IDs that can access the organization private registry. +- `created_at` - Timestamp of when the private registry was created. +- `updated_at` - Timestamp of when the private registry was last updated. +- `oidc_audience` - The OIDC audience. +- `oidc_azure_tenant_id` - The Azure tenant ID. +- `oidc_azure_client_id` - The Azure client ID. +- `oidc_aws_account_id` - The AWS account ID. +- `oidc_aws_region` - The AWS region. +- `oidc_aws_role_name` - The AWS role name. +- `oidc_aws_domain` - The AWS domain. +- `oidc_aws_domain_owner` - The AWS domain owner. +- `oidc_jfrog_provider_name` - The JFrog provider name. +- `oidc_jfrog_identity_mapping_name` - The JFrog identity mapping name. diff --git a/docs/resources/organization_private_registry.md b/docs/resources/organization_private_registry.md new file mode 100644 index 0000000000..e6e80f13a7 --- /dev/null +++ b/docs/resources/organization_private_registry.md @@ -0,0 +1,55 @@ +--- +page_title: "github_organization_private_registry (Resource) - GitHub" +description: |- + Creates and manages an organization private registry. +--- + +# github_organization_private_registry (Resource) + +This resource allows you to create and manage an organization's private registry. Centralized private registry configuration for Dependabot allows you to configure rules and credentials for registries at the organization level, replacing the need for repository-level configurations. + +## Example Usage + +```terraform +resource "github_organization_private_registry" "my_registry" { + registry_type = "npm_registry" + url = "https://npm.pkg.github.com" + auth_type = "username_password" + username = "github-actions" + secret = "super_secret_token_123" + visibility = "private" +} +``` + +## Argument Reference + +The following arguments are supported: + +- `name` - (Required) The name of the private registry. + +- `registry_type` - (Required) The registry type. Can be `maven_repository`, `nuget_feed`, `goproxy_server`, `npm_registry`, `rubygems_server`, `cargo_registry`, `composer_repository`, `docker_registry`, `git_source`, `helm_registry`, `pub_repository`, `python_index`, or `terraform_registry`. +- `visibility` - (Required) Configures the access that repositories have to the organization private registry. Must be one of `all`, `private`, or `selected`. +- `url` - (Required) The URL of the private registry. +- `auth_type` - (Optional) The authentication type for the private registry. Can be `token`, `username_password`, `oidc_azure`, `oidc_aws`, or `oidc_jfrog`. Defaults to `token`. +- `username` - (Optional) The username to use when authenticating with the private registry. +- `secret` - (Optional) The secret/password to use when authenticating with the private registry. This will be encrypted locally before sending to GitHub. +- `key_id` - (Optional) ID of the public key used to encrypt the secret. Required if `encrypted_value` is set directly. +- `encrypted_value` - (Optional) The encrypted value of the secret using the GitHub public key in Base64 format. +- `replaces_base` - (Optional) Whether this registry should replace a base registry configuration. +- `selected_repository_ids` - (Optional) An array of repository IDs that can access the organization private registry. Required when `visibility` is set to `selected`. +- `oidc_audience` - (Optional) The OIDC audience. +- `oidc_azure_tenant_id` - (Optional) The Azure tenant ID. Required when `auth_type` is `oidc_azure`. +- `oidc_azure_client_id` - (Optional) The Azure client ID. Required when `auth_type` is `oidc_azure`. +- `oidc_aws_account_id` - (Optional) The AWS account ID. Required when `auth_type` is `oidc_aws`. +- `oidc_aws_region` - (Optional) The AWS region. Required when `auth_type` is `oidc_aws`. +- `oidc_aws_role_name` - (Optional) The AWS role name. Required when `auth_type` is `oidc_aws`. +- `oidc_aws_domain` - (Optional) The AWS domain. Required when `auth_type` is `oidc_aws`. +- `oidc_aws_domain_owner` - (Optional) The AWS domain owner. Required when `auth_type` is `oidc_aws`. +- `oidc_jfrog_provider_name` - (Optional) The JFrog provider name. Required when `auth_type` is `oidc_jfrog`. +- `oidc_jfrog_identity_mapping_name` - (Optional) The JFrog identity mapping name. Required when `auth_type` is `oidc_jfrog`. + +## Attributes Reference + +- `id` - The ID of the private registry. +- `created_at` - Timestamp of when the private registry was created. +- `updated_at` - Timestamp of when the private registry was last updated. diff --git a/examples/data-sources/github_organization_private_registry/data-source.tf b/examples/data-sources/github_organization_private_registry/data-source.tf new file mode 100644 index 0000000000..3f1e7d7943 --- /dev/null +++ b/examples/data-sources/github_organization_private_registry/data-source.tf @@ -0,0 +1,3 @@ +data "github_organization_private_registry" "my_registry" { + name = "NPM_REGISTRY_SECRET_1" +} diff --git a/examples/resources/github_organization_private_registry/resource.tf b/examples/resources/github_organization_private_registry/resource.tf new file mode 100644 index 0000000000..5c685c96ec --- /dev/null +++ b/examples/resources/github_organization_private_registry/resource.tf @@ -0,0 +1,8 @@ +resource "github_organization_private_registry" "my_registry" { + registry_type = "npm_registry" + url = "https://npm.pkg.github.com" + auth_type = "username_password" + username = "github-actions" + secret = "super_secret_token_123" + visibility = "private" +} diff --git a/github/data_source_github_organization_private_registry.go b/github/data_source_github_organization_private_registry.go new file mode 100644 index 0000000000..400e26acdb --- /dev/null +++ b/github/data_source_github_organization_private_registry.go @@ -0,0 +1,188 @@ +package github + +import ( + "context" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +func dataSourceGithubOrganizationPrivateRegistry() *schema.Resource { + return &schema.Resource{ + ReadContext: dataSourceGithubOrganizationPrivateRegistryRead, + Schema: map[string]*schema.Schema{ + "name": { + Description: "The name of the private registry.", + Type: schema.TypeString, + Required: true, + }, + "registry_type": { + Description: "The registry type. Can be `maven_repository`, `nuget_feed`, `goproxy_server`, `npm_registry`, `rubygems_server`, `cargo_registry`, `composer_repository`, `docker_registry`, `git_source`, `helm_registry`, `pub_repository`, `python_index`, or `terraform_registry`.", + Type: schema.TypeString, + Computed: true, + }, + "url": { + Type: schema.TypeString, + Computed: true, + }, + "username": { + Type: schema.TypeString, + Computed: true, + }, + "replaces_base": { + Type: schema.TypeBool, + Computed: true, + }, + "visibility": { + Description: "Configures the access that repositories have to the organization private registry. Must be one of `all`, `private`, or `selected`.", + Type: schema.TypeString, + Computed: true, + }, + "auth_type": { + Description: "The authentication type for the private registry. Can be `token`, `username_password`, `oidc_azure`, `oidc_aws`, or `oidc_jfrog`.", + Type: schema.TypeString, + Computed: true, + }, + "oidc_azure_tenant_id": { + Type: schema.TypeString, + Computed: true, + }, + "oidc_azure_client_id": { + Type: schema.TypeString, + Computed: true, + }, + "oidc_aws_region": { + Type: schema.TypeString, + Computed: true, + }, + "oidc_aws_account_id": { + Type: schema.TypeString, + Computed: true, + }, + "oidc_aws_role_name": { + Type: schema.TypeString, + Computed: true, + }, + "oidc_aws_domain": { + Type: schema.TypeString, + Computed: true, + }, + "oidc_aws_domain_owner": { + Type: schema.TypeString, + Computed: true, + }, + "oidc_jfrog_provider_name": { + Type: schema.TypeString, + Computed: true, + }, + "oidc_audience": { + Type: schema.TypeString, + Computed: true, + }, + "oidc_jfrog_identity_mapping_name": { + Type: schema.TypeString, + Computed: true, + }, + "selected_repository_ids": { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeInt, + }, + }, + "created_at": { + Type: schema.TypeString, + Computed: true, + }, + "updated_at": { + Type: schema.TypeString, + Computed: true, + }, + }, + } +} + +func dataSourceGithubOrganizationPrivateRegistryRead(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { + client := meta.(*Owner).v3client + org := meta.(*Owner).name + registryName := d.Get("name").(string) + + registry, _, err := client.PrivateRegistries.GetOrganizationPrivateRegistry(ctx, org, registryName) + if err != nil { + return diag.FromErr(err) + } + + d.SetId(registry.GetName()) + + if registry.RegistryType != nil { + if err := d.Set("registry_type", string(*registry.RegistryType)); err != nil { + return diag.FromErr(err) + } + } + if err := d.Set("url", registry.GetURL()); err != nil { + return diag.FromErr(err) + } + if err := d.Set("username", registry.GetUsername()); err != nil { + return diag.FromErr(err) + } + if err := d.Set("replaces_base", registry.GetReplacesBase()); err != nil { + return diag.FromErr(err) + } + if registry.Visibility != nil { + if err := d.Set("visibility", string(*registry.Visibility)); err != nil { + return diag.FromErr(err) + } + } + + if registry.AuthType != nil { + if err := d.Set("auth_type", string(*registry.AuthType)); err != nil { + return diag.FromErr(err) + } + } + if err := d.Set("oidc_azure_tenant_id", registry.GetTenantID()); err != nil { + return diag.FromErr(err) + } + if err := d.Set("oidc_azure_client_id", registry.GetClientID()); err != nil { + return diag.FromErr(err) + } + if err := d.Set("oidc_aws_region", registry.GetAWSRegion()); err != nil { + return diag.FromErr(err) + } + if err := d.Set("oidc_aws_account_id", registry.GetAccountID()); err != nil { + return diag.FromErr(err) + } + if err := d.Set("oidc_aws_role_name", registry.GetRoleName()); err != nil { + return diag.FromErr(err) + } + if err := d.Set("oidc_aws_domain", registry.GetDomain()); err != nil { + return diag.FromErr(err) + } + if err := d.Set("oidc_aws_domain_owner", registry.GetDomainOwner()); err != nil { + return diag.FromErr(err) + } + if err := d.Set("oidc_jfrog_provider_name", registry.GetJFrogOIDCProviderName()); err != nil { + return diag.FromErr(err) + } + if err := d.Set("oidc_audience", registry.GetAudience()); err != nil { + return diag.FromErr(err) + } + if err := d.Set("oidc_jfrog_identity_mapping_name", registry.GetIdentityMappingName()); err != nil { + return diag.FromErr(err) + } + + var repoIDs []any + for _, id := range registry.SelectedRepositoryIDs { + repoIDs = append(repoIDs, int(id)) + } + if err := d.Set("selected_repository_ids", schema.NewSet(schema.HashInt, repoIDs)); err != nil { + return diag.FromErr(err) + } + if err := d.Set("created_at", registry.GetCreatedAt().String()); err != nil { + return diag.FromErr(err) + } + if err := d.Set("updated_at", registry.GetUpdatedAt().String()); err != nil { + return diag.FromErr(err) + } + + return nil +} diff --git a/github/data_source_github_organization_private_registry_test.go b/github/data_source_github_organization_private_registry_test.go new file mode 100644 index 0000000000..2743e71147 --- /dev/null +++ b/github/data_source_github_organization_private_registry_test.go @@ -0,0 +1,44 @@ +package github + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" +) + +func TestAccDataSourceGithubOrganizationPrivateRegistry(t *testing.T) { + skipUnlessMode(t, organization) + + config := ` + resource "github_organization_private_registry" "test" { + registry_type = "npm_registry" + url = "https://npm.pkg.github.com" + username = "github-actions" + secret = "super_secret_token_123" + visibility = "private" + } + + data "github_organization_private_registry" "test" { + name = github_organization_private_registry.test.name + } + ` + + check := resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("data.github_organization_private_registry.test", "id"), + resource.TestCheckResourceAttr("data.github_organization_private_registry.test", "registry_type", "npm_registry"), + resource.TestCheckResourceAttr("data.github_organization_private_registry.test", "url", "https://npm.pkg.github.com"), + resource.TestCheckResourceAttr("data.github_organization_private_registry.test", "username", "github-actions"), + resource.TestCheckResourceAttr("data.github_organization_private_registry.test", "visibility", "private"), + ) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { skipUnlessHasOrgs(t) }, + ProviderFactories: providerFactories, + Steps: []resource.TestStep{ + { + Config: config, + Check: check, + }, + }, + }) +} diff --git a/github/provider.go b/github/provider.go index cf044eee66..9853431da3 100644 --- a/github/provider.go +++ b/github/provider.go @@ -174,6 +174,7 @@ func Provider() *schema.Provider { "github_organization_custom_role": resourceGithubOrganizationCustomRole(), "github_organization_custom_properties": resourceGithubOrganizationCustomProperties(), "github_organization_project": resourceGithubOrganizationProject(), + "github_organization_private_registry": resourceGithubOrganizationPrivateRegistry(), "github_organization_repository_role": resourceGithubOrganizationRepositoryRole(), "github_organization_role": resourceGithubOrganizationRole(), "github_organization_role_team": resourceGithubOrganizationRoleTeam(), @@ -263,6 +264,7 @@ func Provider() *schema.Provider { "github_organization_ip_allow_list": dataSourceGithubOrganizationIpAllowList(), "github_organization_repository_role": dataSourceGithubOrganizationRepositoryRole(), "github_organization_repository_roles": dataSourceGithubOrganizationRepositoryRoles(), + "github_organization_private_registry": dataSourceGithubOrganizationPrivateRegistry(), "github_organization_role": dataSourceGithubOrganizationRole(), "github_organization_role_teams": dataSourceGithubOrganizationRoleTeams(), "github_organization_role_users": dataSourceGithubOrganizationRoleUsers(), diff --git a/github/resource_github_organization_private_registry.go b/github/resource_github_organization_private_registry.go new file mode 100644 index 0000000000..b13d73abed --- /dev/null +++ b/github/resource_github_organization_private_registry.go @@ -0,0 +1,457 @@ +package github + +import ( + "context" + "encoding/base64" + "errors" + + "github.com/google/go-github/v86/github" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" +) + +func resourceGithubOrganizationPrivateRegistry() *schema.Resource { + return &schema.Resource{ + CreateContext: resourceGithubOrganizationPrivateRegistryCreate, + ReadContext: resourceGithubOrganizationPrivateRegistryRead, + UpdateContext: resourceGithubOrganizationPrivateRegistryUpdate, + DeleteContext: resourceGithubOrganizationPrivateRegistryDelete, + Importer: &schema.ResourceImporter{ + StateContext: schema.ImportStatePassthroughContext, + }, + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Computed: true, + Description: "The name of the private registry.", + }, + "registry_type": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateDiagFunc: validation.ToDiagFunc(validation.StringInSlice([]string{"maven_repository", "nuget_feed", "goproxy_server", "npm_registry", "rubygems_server", "cargo_registry", "composer_repository", "docker_registry", "git_source", "helm_registry", "pub_repository", "python_index", "terraform_registry"}, false)), + Description: "The registry type. Can be `maven_repository`, `nuget_feed`, `goproxy_server`, `npm_registry`, `rubygems_server`, `cargo_registry`, `composer_repository`, `docker_registry`, `git_source`, `helm_registry`, `pub_repository`, `python_index`, or `terraform_registry`.", + }, + "url": { + Type: schema.TypeString, + Required: true, + Description: "The URL of the private registry.", + }, + "username": { + Type: schema.TypeString, + Optional: true, + Description: "The username to use when authenticating with the private registry.", + }, + "replaces_base": { + Type: schema.TypeBool, + Optional: true, + Default: false, + Description: "Indicates whether this private registry should replace the base registry.", + }, + "secret": { + Type: schema.TypeString, + Optional: true, + Sensitive: true, + ExactlyOneOf: []string{"secret", "encrypted_value"}, + Description: "The plaintext secret to be encrypted and sent to GitHub. This is used for a token when auth_type is token, and for a password when auth_type is username_password. Required when auth_type is token or username_password.", + }, + "encrypted_value": { + Type: schema.TypeString, + Optional: true, + Sensitive: true, + ExactlyOneOf: []string{"secret", "encrypted_value"}, + Description: "The encrypted value of the secret using the GitHub public key in Base64 format.", + }, + "key_id": { + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: "ID of the public key used to encrypt the secret. Required if encrypted_value is set.", + }, + "visibility": { + Type: schema.TypeString, + Required: true, + ValidateDiagFunc: validation.ToDiagFunc(validation.StringInSlice([]string{"all", "private", "selected"}, false)), + Description: "Configures the access that repositories have to the organization private registry. Must be one of `all`, `private`, or `selected`.", + }, + "selected_repository_ids": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeInt, + }, + Description: "An array of repository IDs that can access the organization private registry.", + }, + "auth_type": { + Type: schema.TypeString, + Optional: true, + Default: "token", + ValidateDiagFunc: validation.ToDiagFunc(validation.StringInSlice([]string{"token", "username_password", "oidc_azure", "oidc_aws", "oidc_jfrog"}, false)), + Description: "The authentication type for the private registry. Can be `token`, `username_password`, `oidc_azure`, `oidc_aws`, or `oidc_jfrog`. Defaults to `token`.", + }, + "oidc_azure_tenant_id": { + Type: schema.TypeString, + Optional: true, + Description: "The tenant ID of the Azure AD application. Required when auth_type is oidc_azure.", + }, + "oidc_azure_client_id": { + Type: schema.TypeString, + Optional: true, + Description: "The client ID of the Azure AD application. Required when auth_type is oidc_azure.", + }, + "oidc_aws_region": { + Type: schema.TypeString, + Optional: true, + Description: "The AWS region. Required when auth_type is oidc_aws.", + }, + "oidc_aws_account_id": { + Type: schema.TypeString, + Optional: true, + Description: "The AWS account ID. Required when auth_type is oidc_aws.", + }, + "oidc_aws_role_name": { + Type: schema.TypeString, + Optional: true, + Description: "The AWS IAM role name. Required when auth_type is oidc_aws.", + }, + "oidc_aws_domain": { + Type: schema.TypeString, + Optional: true, + Description: "The CodeArtifact domain. Required when auth_type is oidc_aws.", + }, + "oidc_aws_domain_owner": { + Type: schema.TypeString, + Optional: true, + Description: "The CodeArtifact domain owner. Required when auth_type is oidc_aws.", + }, + "oidc_jfrog_provider_name": { + Type: schema.TypeString, + Optional: true, + Description: "The JFrog OIDC provider name. Required when auth_type is oidc_jfrog.", + }, + "oidc_audience": { + Type: schema.TypeString, + Optional: true, + Description: "The OIDC audience.", + }, + "oidc_jfrog_identity_mapping_name": { + Type: schema.TypeString, + Optional: true, + Description: "The JFrog identity mapping name.", + }, + "created_at": { + Type: schema.TypeString, + Computed: true, + Description: "The timestamp when the private registry was created.", + }, + "updated_at": { + Type: schema.TypeString, + Computed: true, + Description: "The timestamp when the private registry was last updated.", + }, + }, + } +} + +func resourceGithubOrganizationPrivateRegistryCreate(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { + client := meta.(*Owner).v3client + org := meta.(*Owner).name + + encryptedValue := d.Get("encrypted_value").(string) + keyID := d.Get("key_id").(string) + + authType := d.Get("auth_type").(string) + if authType == "token" || authType == "username_password" { + if keyID == "" || len(encryptedValue) == 0 { + ki, pk, err := getOrganizationRegistryPublicKeyDetails(ctx, client, org) + if err != nil { + return diag.FromErr(err) + } + keyID = ki + + if len(encryptedValue) == 0 { + plaintextValue := d.Get("secret").(string) + encryptedBytes, err := encryptPlaintext(plaintextValue, pk) + if err != nil { + return diag.FromErr(err) + } + encryptedValue = base64.StdEncoding.EncodeToString(encryptedBytes) + } + } + } + + payload := github.CreateOrganizationPrivateRegistry{ + RegistryType: github.PrivateRegistryType(d.Get("registry_type").(string)), + URL: d.Get("url").(string), + Visibility: github.PrivateRegistryVisibility(d.Get("visibility").(string)), + } + + if v, ok := d.GetOk("username"); ok { + payload.Username = new(v.(string)) + } + if v, ok := d.GetOk("replaces_base"); ok { + payload.ReplacesBase = new(v.(bool)) + } + if v, ok := d.GetOk("auth_type"); ok { + payload.AuthType = new(v.(string)) + } + + if encryptedValue != "" { + payload.EncryptedValue = new(encryptedValue) + payload.KeyID = new(keyID) + } + + if v, ok := d.GetOk("oidc_azure_tenant_id"); ok { + payload.TenantID = new(v.(string)) + } + if v, ok := d.GetOk("oidc_azure_client_id"); ok { + payload.ClientID = new(v.(string)) + } + if v, ok := d.GetOk("oidc_aws_region"); ok { + payload.AWSRegion = new(v.(string)) + } + if v, ok := d.GetOk("oidc_aws_account_id"); ok { + payload.AccountID = new(v.(string)) + } + if v, ok := d.GetOk("oidc_aws_role_name"); ok { + payload.RoleName = new(v.(string)) + } + if v, ok := d.GetOk("oidc_aws_domain"); ok { + payload.Domain = new(v.(string)) + } + if v, ok := d.GetOk("oidc_aws_domain_owner"); ok { + payload.DomainOwner = new(v.(string)) + } + if v, ok := d.GetOk("oidc_jfrog_provider_name"); ok { + payload.JFrogOIDCProviderName = new(v.(string)) + } + if v, ok := d.GetOk("oidc_audience"); ok { + payload.Audience = new(v.(string)) + } + if v, ok := d.GetOk("oidc_jfrog_identity_mapping_name"); ok { + payload.IdentityMappingName = new(v.(string)) + } + + if v, ok := d.GetOk("selected_repository_ids"); ok { + ids := v.(*schema.Set).List() + for _, id := range ids { + payload.SelectedRepositoryIDs = append(payload.SelectedRepositoryIDs, int64(id.(int))) + } + } + + registry, _, err := client.PrivateRegistries.CreateOrganizationPrivateRegistry(ctx, org, payload) + if err != nil { + return diag.FromErr(err) + } + + d.SetId(registry.GetName()) + + return resourceGithubOrganizationPrivateRegistryRead(ctx, d, meta) +} + +func resourceGithubOrganizationPrivateRegistryRead(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { + client := meta.(*Owner).v3client + org := meta.(*Owner).name + + registry, _, err := client.PrivateRegistries.GetOrganizationPrivateRegistry(ctx, org, d.Id()) + if err != nil { + var ghErr *github.ErrorResponse + if errors.As(err, &ghErr) && ghErr.Response.StatusCode == 404 { + d.SetId("") + return nil + } + return diag.FromErr(err) + } + if err := d.Set("name", registry.GetName()); err != nil { + return diag.FromErr(err) + } + if registry.RegistryType != nil { + if err := d.Set("registry_type", string(*registry.RegistryType)); err != nil { + return diag.FromErr(err) + } + } + if err := d.Set("url", registry.GetURL()); err != nil { + return diag.FromErr(err) + } + if err := d.Set("username", registry.GetUsername()); err != nil { + return diag.FromErr(err) + } + if err := d.Set("replaces_base", registry.GetReplacesBase()); err != nil { + return diag.FromErr(err) + } + if registry.Visibility != nil { + if err := d.Set("visibility", string(*registry.Visibility)); err != nil { + return diag.FromErr(err) + } + } + + if registry.AuthType != nil { + if err := d.Set("auth_type", string(*registry.AuthType)); err != nil { + return diag.FromErr(err) + } + } + if err := d.Set("oidc_azure_tenant_id", registry.GetTenantID()); err != nil { + return diag.FromErr(err) + } + if err := d.Set("oidc_azure_client_id", registry.GetClientID()); err != nil { + return diag.FromErr(err) + } + if err := d.Set("oidc_aws_region", registry.GetAWSRegion()); err != nil { + return diag.FromErr(err) + } + if err := d.Set("oidc_aws_account_id", registry.GetAccountID()); err != nil { + return diag.FromErr(err) + } + if err := d.Set("oidc_aws_role_name", registry.GetRoleName()); err != nil { + return diag.FromErr(err) + } + if err := d.Set("oidc_aws_domain", registry.GetDomain()); err != nil { + return diag.FromErr(err) + } + if err := d.Set("oidc_aws_domain_owner", registry.GetDomainOwner()); err != nil { + return diag.FromErr(err) + } + if err := d.Set("oidc_jfrog_provider_name", registry.GetJFrogOIDCProviderName()); err != nil { + return diag.FromErr(err) + } + if err := d.Set("oidc_audience", registry.GetAudience()); err != nil { + return diag.FromErr(err) + } + if err := d.Set("oidc_jfrog_identity_mapping_name", registry.GetIdentityMappingName()); err != nil { + return diag.FromErr(err) + } + + var repoIDs []any + for _, id := range registry.SelectedRepositoryIDs { + repoIDs = append(repoIDs, int(id)) + } + if err := d.Set("selected_repository_ids", schema.NewSet(schema.HashInt, repoIDs)); err != nil { + return diag.FromErr(err) + } + if err := d.Set("created_at", registry.GetCreatedAt().String()); err != nil { + return diag.FromErr(err) + } + if err := d.Set("updated_at", registry.GetUpdatedAt().String()); err != nil { + return diag.FromErr(err) + } + + return nil +} + +func resourceGithubOrganizationPrivateRegistryUpdate(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { + client := meta.(*Owner).v3client + org := meta.(*Owner).name + + encryptedValue := d.Get("encrypted_value").(string) + keyID := d.Get("key_id").(string) + + authType := d.Get("auth_type").(string) + if (d.HasChange("secret") || d.HasChange("encrypted_value")) && (authType == "token" || authType == "username_password") { + ki, pk, err := getOrganizationRegistryPublicKeyDetails(ctx, client, org) + if err != nil { + return diag.FromErr(err) + } + keyID = ki + + if len(encryptedValue) == 0 { + plaintextValue := d.Get("secret").(string) + encryptedBytes, err := encryptPlaintext(plaintextValue, pk) + if err != nil { + return diag.FromErr(err) + } + encryptedValue = base64.StdEncoding.EncodeToString(encryptedBytes) + } + } + + payload := github.UpdateOrganizationPrivateRegistry{ + RegistryType: (*github.PrivateRegistryType)(new(d.Get("registry_type").(string))), + } + + if d.HasChange("url") { + payload.URL = new(d.Get("url").(string)) + } + if d.HasChange("username") { + payload.Username = new(d.Get("username").(string)) + } + if d.HasChange("replaces_base") { + payload.ReplacesBase = new(d.Get("replaces_base").(bool)) + } + if d.HasChange("visibility") { + payload.Visibility = (*github.PrivateRegistryVisibility)(new(d.Get("visibility").(string))) + } + if d.HasChange("auth_type") { + payload.AuthType = new(d.Get("auth_type").(string)) + } + + if encryptedValue != "" { + payload.EncryptedValue = new(encryptedValue) + payload.KeyID = new(keyID) + } + + if d.HasChange("oidc_azure_tenant_id") { + payload.TenantID = new(d.Get("oidc_azure_tenant_id").(string)) + } + if d.HasChange("oidc_azure_client_id") { + payload.ClientID = new(d.Get("oidc_azure_client_id").(string)) + } + if d.HasChange("oidc_aws_region") { + payload.AWSRegion = new(d.Get("oidc_aws_region").(string)) + } + if d.HasChange("oidc_aws_account_id") { + payload.AccountID = new(d.Get("oidc_aws_account_id").(string)) + } + if d.HasChange("oidc_aws_role_name") { + payload.RoleName = new(d.Get("oidc_aws_role_name").(string)) + } + if d.HasChange("oidc_aws_domain") { + payload.Domain = new(d.Get("oidc_aws_domain").(string)) + } + if d.HasChange("oidc_aws_domain_owner") { + payload.DomainOwner = new(d.Get("oidc_aws_domain_owner").(string)) + } + if d.HasChange("oidc_jfrog_provider_name") { + payload.JFrogOIDCProviderName = new(d.Get("oidc_jfrog_provider_name").(string)) + } + if d.HasChange("oidc_audience") { + payload.Audience = new(d.Get("oidc_audience").(string)) + } + if d.HasChange("oidc_jfrog_identity_mapping_name") { + payload.IdentityMappingName = new(d.Get("oidc_jfrog_identity_mapping_name").(string)) + } + if d.HasChange("selected_repository_ids") { + v := d.Get("selected_repository_ids").(*schema.Set).List() + var ids []int64 + for _, id := range v { + ids = append(ids, int64(id.(int))) + } + payload.SelectedRepositoryIDs = ids + } + + _, err := client.PrivateRegistries.UpdateOrganizationPrivateRegistry(ctx, org, d.Id(), payload) + if err != nil { + return diag.FromErr(err) + } + + return resourceGithubOrganizationPrivateRegistryRead(ctx, d, meta) +} + +func resourceGithubOrganizationPrivateRegistryDelete(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { + client := meta.(*Owner).v3client + org := meta.(*Owner).name + + _, err := client.PrivateRegistries.DeleteOrganizationPrivateRegistry(ctx, org, d.Id()) + if err != nil { + return diag.FromErr(err) + } + + return nil +} + +func getOrganizationRegistryPublicKeyDetails(ctx context.Context, client *github.Client, org string) (string, string, error) { + publicKey, _, err := client.PrivateRegistries.GetOrganizationPrivateRegistriesPublicKey(ctx, org) + if err != nil { + return "", "", err + } + return publicKey.GetKeyID(), publicKey.GetKey(), nil +} diff --git a/github/resource_github_organization_private_registry_test.go b/github/resource_github_organization_private_registry_test.go new file mode 100644 index 0000000000..38813c2a2d --- /dev/null +++ b/github/resource_github_organization_private_registry_test.go @@ -0,0 +1,45 @@ +package github + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" +) + +func TestAccGithubOrganizationPrivateRegistry_basic(t *testing.T) { + skipUnlessMode(t, organization) + + config := ` + resource "github_organization_private_registry" "test" { + registry_type = "npm_registry" + url = "https://npm.pkg.github.com" + username = "github-actions" + secret = "super_secret_token_123" + visibility = "private" + } + + data "github_organization_private_registry" "test" { + name = github_organization_private_registry.test.name + } + ` + + check := resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("github_organization_private_registry.test", "name"), + resource.TestCheckResourceAttr("github_organization_private_registry.test", "registry_type", "npm_registry"), + resource.TestCheckResourceAttr("github_organization_private_registry.test", "url", "https://npm.pkg.github.com"), + resource.TestCheckResourceAttr("github_organization_private_registry.test", "username", "github-actions"), + resource.TestCheckResourceAttr("github_organization_private_registry.test", "visibility", "private"), + resource.TestCheckResourceAttr("data.github_organization_private_registry.test", "registry_type", "npm_registry"), + ) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { skipUnlessHasOrgs(t) }, + ProviderFactories: providerFactories, + Steps: []resource.TestStep{ + { + Config: config, + Check: check, + }, + }, + }) +} diff --git a/templates/data-sources/organization_private_registry.md.tmpl b/templates/data-sources/organization_private_registry.md.tmpl new file mode 100644 index 0000000000..d431cdfb8c --- /dev/null +++ b/templates/data-sources/organization_private_registry.md.tmpl @@ -0,0 +1,42 @@ +--- +page_title: "github_organization_private_registry (Data Source) - GitHub" +description: |- + Retrieves information about a specific organization private registry. +--- + +# github_organization_private_registry (Data Source) + +Use this data source to retrieve information about a specific organization private registry. + +## Example Usage + +{{ tffile "examples/data-sources/github_organization_private_registry/data-source.tf" }} + +## Argument Reference + +The following arguments are supported: + +- `name` - (Required) The name of the private registry. + +## Attributes Reference + +- `id` - The ID of the private registry. +- `registry_type` - The registry type. Can be `maven_repository`, `nuget_feed`, `goproxy_server`, `npm_registry`, `rubygems_server`, `cargo_registry`, `composer_repository`, `docker_registry`, `git_source`, `helm_registry`, `pub_repository`, `python_index`, or `terraform_registry`. +- `visibility` - Configures the access that repositories have to the organization private registry. Must be one of `all`, `private`, or `selected`. +- `auth_type` - The authentication type for the private registry. Can be `token`, `username_password`, `oidc_azure`, `oidc_aws`, or `oidc_jfrog`. +- `url` - The URL of the private registry. +- `username` - The username to use when authenticating with the private registry. +- `replaces_base` - Whether this registry replaces a base registry. +- `selected_repository_ids` - An array of repository IDs that can access the organization private registry. +- `created_at` - Timestamp of when the private registry was created. +- `updated_at` - Timestamp of when the private registry was last updated. +- `oidc_audience` - The OIDC audience. +- `oidc_azure_tenant_id` - The Azure tenant ID. +- `oidc_azure_client_id` - The Azure client ID. +- `oidc_aws_account_id` - The AWS account ID. +- `oidc_aws_region` - The AWS region. +- `oidc_aws_role_name` - The AWS role name. +- `oidc_aws_domain` - The AWS domain. +- `oidc_aws_domain_owner` - The AWS domain owner. +- `oidc_jfrog_provider_name` - The JFrog provider name. +- `oidc_jfrog_identity_mapping_name` - The JFrog identity mapping name. diff --git a/templates/resources/organization_private_registry.md.tmpl b/templates/resources/organization_private_registry.md.tmpl new file mode 100644 index 0000000000..98aec9c026 --- /dev/null +++ b/templates/resources/organization_private_registry.md.tmpl @@ -0,0 +1,46 @@ +--- +page_title: "github_organization_private_registry (Resource) - GitHub" +description: |- + Creates and manages an organization private registry. +--- + +# github_organization_private_registry (Resource) + +This resource allows you to create and manage an organization's private registry. Centralized private registry configuration for Dependabot allows you to configure rules and credentials for registries at the organization level, replacing the need for repository-level configurations. + +## Example Usage + +{{ tffile "examples/resources/github_organization_private_registry/resource.tf" }} + +## Argument Reference + +The following arguments are supported: + +- `name` - (Required) The name of the private registry. + +- `registry_type` - (Required) The registry type. Can be `maven_repository`, `nuget_feed`, `goproxy_server`, `npm_registry`, `rubygems_server`, `cargo_registry`, `composer_repository`, `docker_registry`, `git_source`, `helm_registry`, `pub_repository`, `python_index`, or `terraform_registry`. +- `visibility` - (Required) Configures the access that repositories have to the organization private registry. Must be one of `all`, `private`, or `selected`. +- `url` - (Required) The URL of the private registry. +- `auth_type` - (Optional) The authentication type for the private registry. Can be `token`, `username_password`, `oidc_azure`, `oidc_aws`, or `oidc_jfrog`. Defaults to `token`. +- `username` - (Optional) The username to use when authenticating with the private registry. +- `secret` - (Optional) The secret/password to use when authenticating with the private registry. This will be encrypted locally before sending to GitHub. +- `key_id` - (Optional) ID of the public key used to encrypt the secret. Required if `encrypted_value` is set directly. +- `encrypted_value` - (Optional) The encrypted value of the secret using the GitHub public key in Base64 format. +- `replaces_base` - (Optional) Whether this registry should replace a base registry configuration. +- `selected_repository_ids` - (Optional) An array of repository IDs that can access the organization private registry. Required when `visibility` is set to `selected`. +- `oidc_audience` - (Optional) The OIDC audience. +- `oidc_azure_tenant_id` - (Optional) The Azure tenant ID. Required when `auth_type` is `oidc_azure`. +- `oidc_azure_client_id` - (Optional) The Azure client ID. Required when `auth_type` is `oidc_azure`. +- `oidc_aws_account_id` - (Optional) The AWS account ID. Required when `auth_type` is `oidc_aws`. +- `oidc_aws_region` - (Optional) The AWS region. Required when `auth_type` is `oidc_aws`. +- `oidc_aws_role_name` - (Optional) The AWS role name. Required when `auth_type` is `oidc_aws`. +- `oidc_aws_domain` - (Optional) The AWS domain. Required when `auth_type` is `oidc_aws`. +- `oidc_aws_domain_owner` - (Optional) The AWS domain owner. Required when `auth_type` is `oidc_aws`. +- `oidc_jfrog_provider_name` - (Optional) The JFrog provider name. Required when `auth_type` is `oidc_jfrog`. +- `oidc_jfrog_identity_mapping_name` - (Optional) The JFrog identity mapping name. Required when `auth_type` is `oidc_jfrog`. + +## Attributes Reference + +- `id` - The ID of the private registry. +- `created_at` - Timestamp of when the private registry was created. +- `updated_at` - Timestamp of when the private registry was last updated. From 8a803040fb9feecf6ed713d44842587d496c0a70 Mon Sep 17 00:00:00 2001 From: Lasse Gaardsholt Date: Tue, 26 May 2026 09:18:43 +0200 Subject: [PATCH 02/15] Re-added the new resources to provider.go Signed-off-by: Lasse Gaardsholt --- github/provider.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/github/provider.go b/github/provider.go index b70c58c9f0..b68a46a0d4 100644 --- a/github/provider.go +++ b/github/provider.go @@ -169,6 +169,7 @@ func NewProvider() func() *schema.Provider { "github_organization_block": resourceOrganizationBlock(), "github_organization_custom_role": resourceGithubOrganizationCustomRole(), "github_organization_custom_properties": resourceGithubOrganizationCustomProperties(), + "github_organization_private_registry": resourceGithubOrganizationPrivateRegistry(), "github_organization_project": resourceGithubOrganizationProject(), "github_organization_repository_role": resourceGithubOrganizationRepositoryRole(), "github_organization_role": resourceGithubOrganizationRole(), @@ -257,6 +258,7 @@ func NewProvider() func() *schema.Provider { "github_organization_custom_properties": dataSourceGithubOrganizationCustomProperties(), "github_organization_external_identities": dataSourceGithubOrganizationExternalIdentities(), "github_organization_ip_allow_list": dataSourceGithubOrganizationIpAllowList(), + "github_organization_private_registry": dataSourceGithubOrganizationPrivateRegistry(), "github_organization_repository_role": dataSourceGithubOrganizationRepositoryRole(), "github_organization_repository_roles": dataSourceGithubOrganizationRepositoryRoles(), "github_organization_role": dataSourceGithubOrganizationRole(), From f8737edc4c5542de50b81ff39751526387c75700 Mon Sep 17 00:00:00 2001 From: Lasse Gaardsholt Date: Wed, 27 May 2026 10:04:18 +0200 Subject: [PATCH 03/15] Removed unnecessary docs templates Signed-off-by: Lasse Gaardsholt --- .../organization_private_registry.md.tmpl | 42 ----------------- .../organization_private_registry.md.tmpl | 46 ------------------- 2 files changed, 88 deletions(-) delete mode 100644 templates/data-sources/organization_private_registry.md.tmpl delete mode 100644 templates/resources/organization_private_registry.md.tmpl diff --git a/templates/data-sources/organization_private_registry.md.tmpl b/templates/data-sources/organization_private_registry.md.tmpl deleted file mode 100644 index d431cdfb8c..0000000000 --- a/templates/data-sources/organization_private_registry.md.tmpl +++ /dev/null @@ -1,42 +0,0 @@ ---- -page_title: "github_organization_private_registry (Data Source) - GitHub" -description: |- - Retrieves information about a specific organization private registry. ---- - -# github_organization_private_registry (Data Source) - -Use this data source to retrieve information about a specific organization private registry. - -## Example Usage - -{{ tffile "examples/data-sources/github_organization_private_registry/data-source.tf" }} - -## Argument Reference - -The following arguments are supported: - -- `name` - (Required) The name of the private registry. - -## Attributes Reference - -- `id` - The ID of the private registry. -- `registry_type` - The registry type. Can be `maven_repository`, `nuget_feed`, `goproxy_server`, `npm_registry`, `rubygems_server`, `cargo_registry`, `composer_repository`, `docker_registry`, `git_source`, `helm_registry`, `pub_repository`, `python_index`, or `terraform_registry`. -- `visibility` - Configures the access that repositories have to the organization private registry. Must be one of `all`, `private`, or `selected`. -- `auth_type` - The authentication type for the private registry. Can be `token`, `username_password`, `oidc_azure`, `oidc_aws`, or `oidc_jfrog`. -- `url` - The URL of the private registry. -- `username` - The username to use when authenticating with the private registry. -- `replaces_base` - Whether this registry replaces a base registry. -- `selected_repository_ids` - An array of repository IDs that can access the organization private registry. -- `created_at` - Timestamp of when the private registry was created. -- `updated_at` - Timestamp of when the private registry was last updated. -- `oidc_audience` - The OIDC audience. -- `oidc_azure_tenant_id` - The Azure tenant ID. -- `oidc_azure_client_id` - The Azure client ID. -- `oidc_aws_account_id` - The AWS account ID. -- `oidc_aws_region` - The AWS region. -- `oidc_aws_role_name` - The AWS role name. -- `oidc_aws_domain` - The AWS domain. -- `oidc_aws_domain_owner` - The AWS domain owner. -- `oidc_jfrog_provider_name` - The JFrog provider name. -- `oidc_jfrog_identity_mapping_name` - The JFrog identity mapping name. diff --git a/templates/resources/organization_private_registry.md.tmpl b/templates/resources/organization_private_registry.md.tmpl deleted file mode 100644 index 98aec9c026..0000000000 --- a/templates/resources/organization_private_registry.md.tmpl +++ /dev/null @@ -1,46 +0,0 @@ ---- -page_title: "github_organization_private_registry (Resource) - GitHub" -description: |- - Creates and manages an organization private registry. ---- - -# github_organization_private_registry (Resource) - -This resource allows you to create and manage an organization's private registry. Centralized private registry configuration for Dependabot allows you to configure rules and credentials for registries at the organization level, replacing the need for repository-level configurations. - -## Example Usage - -{{ tffile "examples/resources/github_organization_private_registry/resource.tf" }} - -## Argument Reference - -The following arguments are supported: - -- `name` - (Required) The name of the private registry. - -- `registry_type` - (Required) The registry type. Can be `maven_repository`, `nuget_feed`, `goproxy_server`, `npm_registry`, `rubygems_server`, `cargo_registry`, `composer_repository`, `docker_registry`, `git_source`, `helm_registry`, `pub_repository`, `python_index`, or `terraform_registry`. -- `visibility` - (Required) Configures the access that repositories have to the organization private registry. Must be one of `all`, `private`, or `selected`. -- `url` - (Required) The URL of the private registry. -- `auth_type` - (Optional) The authentication type for the private registry. Can be `token`, `username_password`, `oidc_azure`, `oidc_aws`, or `oidc_jfrog`. Defaults to `token`. -- `username` - (Optional) The username to use when authenticating with the private registry. -- `secret` - (Optional) The secret/password to use when authenticating with the private registry. This will be encrypted locally before sending to GitHub. -- `key_id` - (Optional) ID of the public key used to encrypt the secret. Required if `encrypted_value` is set directly. -- `encrypted_value` - (Optional) The encrypted value of the secret using the GitHub public key in Base64 format. -- `replaces_base` - (Optional) Whether this registry should replace a base registry configuration. -- `selected_repository_ids` - (Optional) An array of repository IDs that can access the organization private registry. Required when `visibility` is set to `selected`. -- `oidc_audience` - (Optional) The OIDC audience. -- `oidc_azure_tenant_id` - (Optional) The Azure tenant ID. Required when `auth_type` is `oidc_azure`. -- `oidc_azure_client_id` - (Optional) The Azure client ID. Required when `auth_type` is `oidc_azure`. -- `oidc_aws_account_id` - (Optional) The AWS account ID. Required when `auth_type` is `oidc_aws`. -- `oidc_aws_region` - (Optional) The AWS region. Required when `auth_type` is `oidc_aws`. -- `oidc_aws_role_name` - (Optional) The AWS role name. Required when `auth_type` is `oidc_aws`. -- `oidc_aws_domain` - (Optional) The AWS domain. Required when `auth_type` is `oidc_aws`. -- `oidc_aws_domain_owner` - (Optional) The AWS domain owner. Required when `auth_type` is `oidc_aws`. -- `oidc_jfrog_provider_name` - (Optional) The JFrog provider name. Required when `auth_type` is `oidc_jfrog`. -- `oidc_jfrog_identity_mapping_name` - (Optional) The JFrog identity mapping name. Required when `auth_type` is `oidc_jfrog`. - -## Attributes Reference - -- `id` - The ID of the private registry. -- `created_at` - Timestamp of when the private registry was created. -- `updated_at` - Timestamp of when the private registry was last updated. From 64b32a5487618395d6e2649d0872cc546c0a4e34 Mon Sep 17 00:00:00 2001 From: Lasse Gaardsholt Date: Thu, 4 Jun 2026 22:49:44 +0200 Subject: [PATCH 04/15] update go-github to v88 to align with the rest of the provider Signed-off-by: Lasse Gaardsholt --- github/resource_github_organization_private_registry.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/github/resource_github_organization_private_registry.go b/github/resource_github_organization_private_registry.go index b13d73abed..a7fa20cddc 100644 --- a/github/resource_github_organization_private_registry.go +++ b/github/resource_github_organization_private_registry.go @@ -5,7 +5,7 @@ import ( "encoding/base64" "errors" - "github.com/google/go-github/v86/github" + "github.com/google/go-github/v88/github" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" From 2f8443bf070cbb294874c3eb647048455abf3a96 Mon Sep 17 00:00:00 2001 From: Lasse Gaardsholt Date: Mon, 8 Jun 2026 12:55:06 +0200 Subject: [PATCH 05/15] Changed description of the `name` field Signed-off-by: Lasse Gaardsholt --- github/data_source_github_organization_private_registry.go | 3 ++- github/resource_github_organization_private_registry.go | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/github/data_source_github_organization_private_registry.go b/github/data_source_github_organization_private_registry.go index 400e26acdb..c168891bc1 100644 --- a/github/data_source_github_organization_private_registry.go +++ b/github/data_source_github_organization_private_registry.go @@ -10,9 +10,10 @@ import ( func dataSourceGithubOrganizationPrivateRegistry() *schema.Resource { return &schema.Resource{ ReadContext: dataSourceGithubOrganizationPrivateRegistryRead, + Description: "Use this data source to retrieve information about a specific organization private registry.", Schema: map[string]*schema.Schema{ "name": { - Description: "The name of the private registry.", + Description: "The auto-generated name of the private registry (computed by GitHub).", Type: schema.TypeString, Required: true, }, diff --git a/github/resource_github_organization_private_registry.go b/github/resource_github_organization_private_registry.go index a7fa20cddc..7f4c5c1f4b 100644 --- a/github/resource_github_organization_private_registry.go +++ b/github/resource_github_organization_private_registry.go @@ -24,7 +24,7 @@ func resourceGithubOrganizationPrivateRegistry() *schema.Resource { "name": { Type: schema.TypeString, Computed: true, - Description: "The name of the private registry.", + Description: "The auto-generated name of the private registry (computed by GitHub).", }, "registry_type": { Type: schema.TypeString, From 3694567b0c13f5166dfdccb62661ae6ba04ee961 Mon Sep 17 00:00:00 2001 From: Lasse Gaardsholt Date: Mon, 8 Jun 2026 12:55:19 +0200 Subject: [PATCH 06/15] ran `make generatedocs` Signed-off-by: Lasse Gaardsholt --- .../organization_private_registry.md | 60 ++++++++-------- .../organization_private_registry.md | 72 ++++++++++--------- 2 files changed, 69 insertions(+), 63 deletions(-) diff --git a/docs/data-sources/organization_private_registry.md b/docs/data-sources/organization_private_registry.md index c688ef5055..dc280f6809 100644 --- a/docs/data-sources/organization_private_registry.md +++ b/docs/data-sources/organization_private_registry.md @@ -1,7 +1,8 @@ --- page_title: "github_organization_private_registry (Data Source) - GitHub" +subcategory: "" description: |- - Retrieves information about a specific organization private registry. + Use this data source to retrieve information about a specific organization private registry. --- # github_organization_private_registry (Data Source) @@ -16,31 +17,32 @@ data "github_organization_private_registry" "my_registry" { } ``` -## Argument Reference - -The following arguments are supported: - -- `name` - (Required) The name of the private registry. - -## Attributes Reference - -- `id` - The ID of the private registry. -- `registry_type` - The registry type. Can be `maven_repository`, `nuget_feed`, `goproxy_server`, `npm_registry`, `rubygems_server`, `cargo_registry`, `composer_repository`, `docker_registry`, `git_source`, `helm_registry`, `pub_repository`, `python_index`, or `terraform_registry`. -- `visibility` - Configures the access that repositories have to the organization private registry. Must be one of `all`, `private`, or `selected`. -- `auth_type` - The authentication type for the private registry. Can be `token`, `username_password`, `oidc_azure`, `oidc_aws`, or `oidc_jfrog`. -- `url` - The URL of the private registry. -- `username` - The username to use when authenticating with the private registry. -- `replaces_base` - Whether this registry replaces a base registry. -- `selected_repository_ids` - An array of repository IDs that can access the organization private registry. -- `created_at` - Timestamp of when the private registry was created. -- `updated_at` - Timestamp of when the private registry was last updated. -- `oidc_audience` - The OIDC audience. -- `oidc_azure_tenant_id` - The Azure tenant ID. -- `oidc_azure_client_id` - The Azure client ID. -- `oidc_aws_account_id` - The AWS account ID. -- `oidc_aws_region` - The AWS region. -- `oidc_aws_role_name` - The AWS role name. -- `oidc_aws_domain` - The AWS domain. -- `oidc_aws_domain_owner` - The AWS domain owner. -- `oidc_jfrog_provider_name` - The JFrog provider name. -- `oidc_jfrog_identity_mapping_name` - The JFrog identity mapping name. + +## Schema + +### Required + +- `name` (String) The auto-generated name of the private registry (computed by GitHub). + +### Read-Only + +- `auth_type` (String) The authentication type for the private registry. Can be `token`, `username_password`, `oidc_azure`, `oidc_aws`, or `oidc_jfrog`. +- `created_at` (String) +- `id` (String) The ID of this resource. +- `oidc_audience` (String) +- `oidc_aws_account_id` (String) +- `oidc_aws_domain` (String) +- `oidc_aws_domain_owner` (String) +- `oidc_aws_region` (String) +- `oidc_aws_role_name` (String) +- `oidc_azure_client_id` (String) +- `oidc_azure_tenant_id` (String) +- `oidc_jfrog_identity_mapping_name` (String) +- `oidc_jfrog_provider_name` (String) +- `registry_type` (String) The registry type. Can be `maven_repository`, `nuget_feed`, `goproxy_server`, `npm_registry`, `rubygems_server`, `cargo_registry`, `composer_repository`, `docker_registry`, `git_source`, `helm_registry`, `pub_repository`, `python_index`, or `terraform_registry`. +- `replaces_base` (Boolean) +- `selected_repository_ids` (Set of Number) +- `updated_at` (String) +- `url` (String) +- `username` (String) +- `visibility` (String) Configures the access that repositories have to the organization private registry. Must be one of `all`, `private`, or `selected`. diff --git a/docs/resources/organization_private_registry.md b/docs/resources/organization_private_registry.md index e6e80f13a7..4bd89bb147 100644 --- a/docs/resources/organization_private_registry.md +++ b/docs/resources/organization_private_registry.md @@ -1,12 +1,13 @@ --- page_title: "github_organization_private_registry (Resource) - GitHub" +subcategory: "" description: |- - Creates and manages an organization private registry. + --- # github_organization_private_registry (Resource) -This resource allows you to create and manage an organization's private registry. Centralized private registry configuration for Dependabot allows you to configure rules and credentials for registries at the organization level, replacing the need for repository-level configurations. + ## Example Usage @@ -21,35 +22,38 @@ resource "github_organization_private_registry" "my_registry" { } ``` -## Argument Reference - -The following arguments are supported: - -- `name` - (Required) The name of the private registry. - -- `registry_type` - (Required) The registry type. Can be `maven_repository`, `nuget_feed`, `goproxy_server`, `npm_registry`, `rubygems_server`, `cargo_registry`, `composer_repository`, `docker_registry`, `git_source`, `helm_registry`, `pub_repository`, `python_index`, or `terraform_registry`. -- `visibility` - (Required) Configures the access that repositories have to the organization private registry. Must be one of `all`, `private`, or `selected`. -- `url` - (Required) The URL of the private registry. -- `auth_type` - (Optional) The authentication type for the private registry. Can be `token`, `username_password`, `oidc_azure`, `oidc_aws`, or `oidc_jfrog`. Defaults to `token`. -- `username` - (Optional) The username to use when authenticating with the private registry. -- `secret` - (Optional) The secret/password to use when authenticating with the private registry. This will be encrypted locally before sending to GitHub. -- `key_id` - (Optional) ID of the public key used to encrypt the secret. Required if `encrypted_value` is set directly. -- `encrypted_value` - (Optional) The encrypted value of the secret using the GitHub public key in Base64 format. -- `replaces_base` - (Optional) Whether this registry should replace a base registry configuration. -- `selected_repository_ids` - (Optional) An array of repository IDs that can access the organization private registry. Required when `visibility` is set to `selected`. -- `oidc_audience` - (Optional) The OIDC audience. -- `oidc_azure_tenant_id` - (Optional) The Azure tenant ID. Required when `auth_type` is `oidc_azure`. -- `oidc_azure_client_id` - (Optional) The Azure client ID. Required when `auth_type` is `oidc_azure`. -- `oidc_aws_account_id` - (Optional) The AWS account ID. Required when `auth_type` is `oidc_aws`. -- `oidc_aws_region` - (Optional) The AWS region. Required when `auth_type` is `oidc_aws`. -- `oidc_aws_role_name` - (Optional) The AWS role name. Required when `auth_type` is `oidc_aws`. -- `oidc_aws_domain` - (Optional) The AWS domain. Required when `auth_type` is `oidc_aws`. -- `oidc_aws_domain_owner` - (Optional) The AWS domain owner. Required when `auth_type` is `oidc_aws`. -- `oidc_jfrog_provider_name` - (Optional) The JFrog provider name. Required when `auth_type` is `oidc_jfrog`. -- `oidc_jfrog_identity_mapping_name` - (Optional) The JFrog identity mapping name. Required when `auth_type` is `oidc_jfrog`. - -## Attributes Reference - -- `id` - The ID of the private registry. -- `created_at` - Timestamp of when the private registry was created. -- `updated_at` - Timestamp of when the private registry was last updated. + +## Schema + +### Required + +- `registry_type` (String) The registry type. Can be `maven_repository`, `nuget_feed`, `goproxy_server`, `npm_registry`, `rubygems_server`, `cargo_registry`, `composer_repository`, `docker_registry`, `git_source`, `helm_registry`, `pub_repository`, `python_index`, or `terraform_registry`. +- `url` (String) The URL of the private registry. +- `visibility` (String) Configures the access that repositories have to the organization private registry. Must be one of `all`, `private`, or `selected`. + +### Optional + +- `auth_type` (String) The authentication type for the private registry. Can be `token`, `username_password`, `oidc_azure`, `oidc_aws`, or `oidc_jfrog`. Defaults to `token`. +- `encrypted_value` (String, Sensitive) The encrypted value of the secret using the GitHub public key in Base64 format. +- `key_id` (String) ID of the public key used to encrypt the secret. Required if encrypted_value is set. +- `oidc_audience` (String) The OIDC audience. +- `oidc_aws_account_id` (String) The AWS account ID. Required when auth_type is oidc_aws. +- `oidc_aws_domain` (String) The CodeArtifact domain. Required when auth_type is oidc_aws. +- `oidc_aws_domain_owner` (String) The CodeArtifact domain owner. Required when auth_type is oidc_aws. +- `oidc_aws_region` (String) The AWS region. Required when auth_type is oidc_aws. +- `oidc_aws_role_name` (String) The AWS IAM role name. Required when auth_type is oidc_aws. +- `oidc_azure_client_id` (String) The client ID of the Azure AD application. Required when auth_type is oidc_azure. +- `oidc_azure_tenant_id` (String) The tenant ID of the Azure AD application. Required when auth_type is oidc_azure. +- `oidc_jfrog_identity_mapping_name` (String) The JFrog identity mapping name. +- `oidc_jfrog_provider_name` (String) The JFrog OIDC provider name. Required when auth_type is oidc_jfrog. +- `replaces_base` (Boolean) Indicates whether this private registry should replace the base registry. +- `secret` (String, Sensitive) The plaintext secret to be encrypted and sent to GitHub. This is used for a token when auth_type is token, and for a password when auth_type is username_password. Required when auth_type is token or username_password. +- `selected_repository_ids` (Set of Number) An array of repository IDs that can access the organization private registry. +- `username` (String) The username to use when authenticating with the private registry. + +### Read-Only + +- `created_at` (String) The timestamp when the private registry was created. +- `id` (String) The ID of this resource. +- `name` (String) The auto-generated name of the private registry (computed by GitHub). +- `updated_at` (String) The timestamp when the private registry was last updated. From 070c5dbf87baba0ce2a4f06b68b9593d283b8e75 Mon Sep 17 00:00:00 2001 From: Lasse Gaardsholt Date: Mon, 8 Jun 2026 13:02:35 +0200 Subject: [PATCH 07/15] Handle 404 error when deleting organization private registry Signed-off-by: Lasse Gaardsholt --- github/resource_github_organization_private_registry.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/github/resource_github_organization_private_registry.go b/github/resource_github_organization_private_registry.go index 7f4c5c1f4b..2c5e0aea04 100644 --- a/github/resource_github_organization_private_registry.go +++ b/github/resource_github_organization_private_registry.go @@ -442,6 +442,11 @@ func resourceGithubOrganizationPrivateRegistryDelete(ctx context.Context, d *sch _, err := client.PrivateRegistries.DeleteOrganizationPrivateRegistry(ctx, org, d.Id()) if err != nil { + var ghErr *github.ErrorResponse + if errors.As(err, &ghErr) && ghErr.Response.StatusCode == 404 { + return nil + } + return diag.FromErr(err) } From 31e426a4654cd765f568f9555ceac36421a8691c Mon Sep 17 00:00:00 2001 From: Lasse Gaardsholt Date: Mon, 8 Jun 2026 13:47:38 +0200 Subject: [PATCH 08/15] Swapped `ExactlyOneOf` with `ConflictsWith` + added CustomizeDiff to make sure `secret` or `encrypted_value` is set when `auth_type` is `token` or `username_password` Signed-off-by: Lasse Gaardsholt --- ...ce_github_organization_private_registry.go | 39 ++++++++++++++----- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/github/resource_github_organization_private_registry.go b/github/resource_github_organization_private_registry.go index 2c5e0aea04..8746a6d93f 100644 --- a/github/resource_github_organization_private_registry.go +++ b/github/resource_github_organization_private_registry.go @@ -4,9 +4,11 @@ import ( "context" "encoding/base64" "errors" + "fmt" "github.com/google/go-github/v88/github" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" ) @@ -17,6 +19,7 @@ func resourceGithubOrganizationPrivateRegistry() *schema.Resource { ReadContext: resourceGithubOrganizationPrivateRegistryRead, UpdateContext: resourceGithubOrganizationPrivateRegistryUpdate, DeleteContext: resourceGithubOrganizationPrivateRegistryDelete, + CustomizeDiff: customdiff.All(resourceGithubOrganizationPrivateRegistryDiff), Importer: &schema.ResourceImporter{ StateContext: schema.ImportStatePassthroughContext, }, @@ -50,18 +53,18 @@ func resourceGithubOrganizationPrivateRegistry() *schema.Resource { Description: "Indicates whether this private registry should replace the base registry.", }, "secret": { - Type: schema.TypeString, - Optional: true, - Sensitive: true, - ExactlyOneOf: []string{"secret", "encrypted_value"}, - Description: "The plaintext secret to be encrypted and sent to GitHub. This is used for a token when auth_type is token, and for a password when auth_type is username_password. Required when auth_type is token or username_password.", + Type: schema.TypeString, + Optional: true, + Sensitive: true, + ConflictsWith: []string{"encrypted_value"}, + Description: "The plaintext secret to be encrypted and sent to GitHub. This is used for a token when auth_type is token, and for a password when auth_type is username_password. Required when auth_type is token or username_password.", }, "encrypted_value": { - Type: schema.TypeString, - Optional: true, - Sensitive: true, - ExactlyOneOf: []string{"secret", "encrypted_value"}, - Description: "The encrypted value of the secret using the GitHub public key in Base64 format.", + Type: schema.TypeString, + Optional: true, + Sensitive: true, + ConflictsWith: []string{"secret"}, + Description: "The encrypted value of the secret using the GitHub public key in Base64 format.", }, "key_id": { Type: schema.TypeString, @@ -154,6 +157,22 @@ func resourceGithubOrganizationPrivateRegistry() *schema.Resource { } } +func resourceGithubOrganizationPrivateRegistryDiff(_ context.Context, d *schema.ResourceDiff, _ any) error { + authType := d.Get("auth_type").(string) + if authType != "token" && authType != "username_password" { + return nil + } + + if _, ok := d.GetOk("secret"); ok { + return nil + } + if _, ok := d.GetOk("encrypted_value"); ok { + return nil + } + + return fmt.Errorf("one of `secret,encrypted_value` must be specified when auth_type is %q", authType) +} + func resourceGithubOrganizationPrivateRegistryCreate(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { client := meta.(*Owner).v3client org := meta.(*Owner).name From 09bd2d940d9be27b25a69e91e37fe47f91182ddb Mon Sep 17 00:00:00 2001 From: Lasse Gaardsholt Date: Mon, 8 Jun 2026 14:43:32 +0200 Subject: [PATCH 09/15] Added test for import Signed-off-by: Lasse Gaardsholt --- ...thub_organization_private_registry_test.go | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/github/resource_github_organization_private_registry_test.go b/github/resource_github_organization_private_registry_test.go index 38813c2a2d..7171044fa8 100644 --- a/github/resource_github_organization_private_registry_test.go +++ b/github/resource_github_organization_private_registry_test.go @@ -23,6 +23,20 @@ func TestAccGithubOrganizationPrivateRegistry_basic(t *testing.T) { } ` + updatedConfig := ` + resource "github_organization_private_registry" "test" { + registry_type = "npm_registry" + url = "https://npm-registry.example.com" + username = "github-actions" + secret = "super_secret_token_123" + visibility = "all" + } + + data "github_organization_private_registry" "test" { + name = github_organization_private_registry.test.name + } + ` + check := resource.ComposeTestCheckFunc( resource.TestCheckResourceAttrSet("github_organization_private_registry.test", "name"), resource.TestCheckResourceAttr("github_organization_private_registry.test", "registry_type", "npm_registry"), @@ -31,6 +45,14 @@ func TestAccGithubOrganizationPrivateRegistry_basic(t *testing.T) { resource.TestCheckResourceAttr("github_organization_private_registry.test", "visibility", "private"), resource.TestCheckResourceAttr("data.github_organization_private_registry.test", "registry_type", "npm_registry"), ) + updatedCheck := resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("github_organization_private_registry.test", "name"), + resource.TestCheckResourceAttr("github_organization_private_registry.test", "registry_type", "npm_registry"), + resource.TestCheckResourceAttr("github_organization_private_registry.test", "url", "https://npm-registry.example.com"), + resource.TestCheckResourceAttr("github_organization_private_registry.test", "username", "github-actions"), + resource.TestCheckResourceAttr("github_organization_private_registry.test", "visibility", "all"), + resource.TestCheckResourceAttr("data.github_organization_private_registry.test", "registry_type", "npm_registry"), + ) resource.Test(t, resource.TestCase{ PreCheck: func() { skipUnlessHasOrgs(t) }, @@ -40,6 +62,16 @@ func TestAccGithubOrganizationPrivateRegistry_basic(t *testing.T) { Config: config, Check: check, }, + { + ResourceName: "github_organization_private_registry.test", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"secret"}, + }, + { + Config: updatedConfig, + Check: updatedCheck, + }, }, }) } From 543f4d476df3bc955c11413f9cced0a7d8affb36 Mon Sep 17 00:00:00 2001 From: Lasse Gaardsholt Date: Thu, 2 Jul 2026 23:26:52 +0200 Subject: [PATCH 10/15] using ConfigStateChecks instead Signed-off-by: Lasse Gaardsholt --- ..._github_organization_private_registry_test.go | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/github/data_source_github_organization_private_registry_test.go b/github/data_source_github_organization_private_registry_test.go index 2743e71147..9677e332cd 100644 --- a/github/data_source_github_organization_private_registry_test.go +++ b/github/data_source_github_organization_private_registry_test.go @@ -23,21 +23,19 @@ func TestAccDataSourceGithubOrganizationPrivateRegistry(t *testing.T) { } ` - check := resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttrSet("data.github_organization_private_registry.test", "id"), - resource.TestCheckResourceAttr("data.github_organization_private_registry.test", "registry_type", "npm_registry"), - resource.TestCheckResourceAttr("data.github_organization_private_registry.test", "url", "https://npm.pkg.github.com"), - resource.TestCheckResourceAttr("data.github_organization_private_registry.test", "username", "github-actions"), - resource.TestCheckResourceAttr("data.github_organization_private_registry.test", "visibility", "private"), - ) - resource.Test(t, resource.TestCase{ PreCheck: func() { skipUnlessHasOrgs(t) }, ProviderFactories: providerFactories, Steps: []resource.TestStep{ { Config: config, - Check: check, + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue("data.github_organization_private_registry.test", tfjsonpath.New("id"), knownvalue.NotNull()), + statecheck.ExpectKnownValue("data.github_organization_private_registry.test", tfjsonpath.New("registry_type"), knownvalue.StringExact("npm_registry")), + statecheck.ExpectKnownValue("data.github_organization_private_registry.test", tfjsonpath.New("url"), knownvalue.StringExact("https://npm.pkg.github.com")), + statecheck.ExpectKnownValue("data.github_organization_private_registry.test", tfjsonpath.New("username"), knownvalue.StringExact("github-actions")), + statecheck.ExpectKnownValue("data.github_organization_private_registry.test", tfjsonpath.New("visibility"), knownvalue.StringExact("private")), + }, }, }, }) From c490f6c85850741f16c120f703bda1f550ca1af9 Mon Sep 17 00:00:00 2001 From: Lasse Gaardsholt Date: Fri, 3 Jul 2026 00:29:34 +0200 Subject: [PATCH 11/15] adressing pr comments Signed-off-by: Lasse Gaardsholt --- .../organization_private_registry.md | 38 ++++---- .../organization_private_registry.md | 10 +-- .../resource.tf | 2 +- ...ce_github_organization_private_registry.go | 86 +++++++++++-------- ...thub_organization_private_registry_test.go | 14 +-- ...ce_github_organization_private_registry.go | 35 ++++---- ...thub_organization_private_registry_test.go | 76 +++++++--------- 7 files changed, 136 insertions(+), 125 deletions(-) diff --git a/docs/data-sources/organization_private_registry.md b/docs/data-sources/organization_private_registry.md index dc280f6809..50ca688e10 100644 --- a/docs/data-sources/organization_private_registry.md +++ b/docs/data-sources/organization_private_registry.md @@ -26,23 +26,23 @@ data "github_organization_private_registry" "my_registry" { ### Read-Only -- `auth_type` (String) The authentication type for the private registry. Can be `token`, `username_password`, `oidc_azure`, `oidc_aws`, or `oidc_jfrog`. -- `created_at` (String) +- `auth_type` (String) The authentication type for the private registry. +- `created_at` (String) The time the registry was created. - `id` (String) The ID of this resource. -- `oidc_audience` (String) -- `oidc_aws_account_id` (String) -- `oidc_aws_domain` (String) -- `oidc_aws_domain_owner` (String) -- `oidc_aws_region` (String) -- `oidc_aws_role_name` (String) -- `oidc_azure_client_id` (String) -- `oidc_azure_tenant_id` (String) -- `oidc_jfrog_identity_mapping_name` (String) -- `oidc_jfrog_provider_name` (String) -- `registry_type` (String) The registry type. Can be `maven_repository`, `nuget_feed`, `goproxy_server`, `npm_registry`, `rubygems_server`, `cargo_registry`, `composer_repository`, `docker_registry`, `git_source`, `helm_registry`, `pub_repository`, `python_index`, or `terraform_registry`. -- `replaces_base` (Boolean) -- `selected_repository_ids` (Set of Number) -- `updated_at` (String) -- `url` (String) -- `username` (String) -- `visibility` (String) Configures the access that repositories have to the organization private registry. Must be one of `all`, `private`, or `selected`. +- `oidc_audience` (String) The JWT audience. +- `oidc_aws_account_id` (String) The AWS account ID. +- `oidc_aws_domain` (String) The AWS domain. +- `oidc_aws_domain_owner` (String) The AWS domain owner. +- `oidc_aws_region` (String) The AWS region. +- `oidc_aws_role_name` (String) The AWS role name. +- `oidc_azure_client_id` (String) The Azure client ID. +- `oidc_azure_tenant_id` (String) The Azure tenant ID. +- `oidc_jfrog_identity_mapping_name` (String) The JFrog identity mapping name. +- `oidc_jfrog_provider_name` (String) The JFrog provider name. +- `registry_type` (String) The registry type. +- `replaces_base` (Boolean) Whether the private registry should replace the public base registry. +- `selected_repository_ids` (Set of Number) An array of repository IDs that can access the organization private registry. +- `updated_at` (String) The time the registry was updated. +- `url` (String) The registry URL. +- `username` (String) The registry username. +- `visibility` (String) Configures the access that repositories have to the organization private registry. diff --git a/docs/resources/organization_private_registry.md b/docs/resources/organization_private_registry.md index 4bd89bb147..3143d14d54 100644 --- a/docs/resources/organization_private_registry.md +++ b/docs/resources/organization_private_registry.md @@ -2,12 +2,12 @@ page_title: "github_organization_private_registry (Resource) - GitHub" subcategory: "" description: |- - + This resource allows you to create and manage an organization private registry. --- # github_organization_private_registry (Resource) - +This resource allows you to create and manage an organization private registry. ## Example Usage @@ -17,7 +17,7 @@ resource "github_organization_private_registry" "my_registry" { url = "https://npm.pkg.github.com" auth_type = "username_password" username = "github-actions" - secret = "super_secret_token_123" + value = "super_secret_token_123" visibility = "private" } ``` @@ -34,7 +34,6 @@ resource "github_organization_private_registry" "my_registry" { ### Optional - `auth_type` (String) The authentication type for the private registry. Can be `token`, `username_password`, `oidc_azure`, `oidc_aws`, or `oidc_jfrog`. Defaults to `token`. -- `encrypted_value` (String, Sensitive) The encrypted value of the secret using the GitHub public key in Base64 format. - `key_id` (String) ID of the public key used to encrypt the secret. Required if encrypted_value is set. - `oidc_audience` (String) The OIDC audience. - `oidc_aws_account_id` (String) The AWS account ID. Required when auth_type is oidc_aws. @@ -47,9 +46,10 @@ resource "github_organization_private_registry" "my_registry" { - `oidc_jfrog_identity_mapping_name` (String) The JFrog identity mapping name. - `oidc_jfrog_provider_name` (String) The JFrog OIDC provider name. Required when auth_type is oidc_jfrog. - `replaces_base` (Boolean) Indicates whether this private registry should replace the base registry. -- `secret` (String, Sensitive) The plaintext secret to be encrypted and sent to GitHub. This is used for a token when auth_type is token, and for a password when auth_type is username_password. Required when auth_type is token or username_password. - `selected_repository_ids` (Set of Number) An array of repository IDs that can access the organization private registry. - `username` (String) The username to use when authenticating with the private registry. +- `value` (String, Sensitive) The plaintext secret to be encrypted and sent to GitHub. This is used for a token when auth_type is token, and for a password when auth_type is username_password. Required when auth_type is token or username_password. +- `value_encrypted` (String, Sensitive) The encrypted value of the secret using the GitHub public key in Base64 format. ### Read-Only diff --git a/examples/resources/github_organization_private_registry/resource.tf b/examples/resources/github_organization_private_registry/resource.tf index 5c685c96ec..d91dc936f5 100644 --- a/examples/resources/github_organization_private_registry/resource.tf +++ b/examples/resources/github_organization_private_registry/resource.tf @@ -3,6 +3,6 @@ resource "github_organization_private_registry" "my_registry" { url = "https://npm.pkg.github.com" auth_type = "username_password" username = "github-actions" - secret = "super_secret_token_123" + value = "super_secret_token_123" visibility = "private" } diff --git a/github/data_source_github_organization_private_registry.go b/github/data_source_github_organization_private_registry.go index c168891bc1..c623d4fd9d 100644 --- a/github/data_source_github_organization_private_registry.go +++ b/github/data_source_github_organization_private_registry.go @@ -18,86 +18,102 @@ func dataSourceGithubOrganizationPrivateRegistry() *schema.Resource { Required: true, }, "registry_type": { - Description: "The registry type. Can be `maven_repository`, `nuget_feed`, `goproxy_server`, `npm_registry`, `rubygems_server`, `cargo_registry`, `composer_repository`, `docker_registry`, `git_source`, `helm_registry`, `pub_repository`, `python_index`, or `terraform_registry`.", + Description: "The registry type.", Type: schema.TypeString, Computed: true, }, "url": { - Type: schema.TypeString, - Computed: true, + Description: "The registry URL.", + Type: schema.TypeString, + Computed: true, }, "username": { - Type: schema.TypeString, - Computed: true, + Description: "The registry username.", + Type: schema.TypeString, + Computed: true, }, "replaces_base": { - Type: schema.TypeBool, - Computed: true, + Description: "Whether the private registry should replace the public base registry.", + Type: schema.TypeBool, + Computed: true, }, "visibility": { - Description: "Configures the access that repositories have to the organization private registry. Must be one of `all`, `private`, or `selected`.", + Description: "Configures the access that repositories have to the organization private registry.", Type: schema.TypeString, Computed: true, }, "auth_type": { - Description: "The authentication type for the private registry. Can be `token`, `username_password`, `oidc_azure`, `oidc_aws`, or `oidc_jfrog`.", + Description: "The authentication type for the private registry.", Type: schema.TypeString, Computed: true, }, "oidc_azure_tenant_id": { - Type: schema.TypeString, - Computed: true, + Description: "The Azure tenant ID.", + Type: schema.TypeString, + Computed: true, }, "oidc_azure_client_id": { - Type: schema.TypeString, - Computed: true, + Description: "The Azure client ID.", + Type: schema.TypeString, + Computed: true, }, "oidc_aws_region": { - Type: schema.TypeString, - Computed: true, + Description: "The AWS region.", + Type: schema.TypeString, + Computed: true, }, "oidc_aws_account_id": { - Type: schema.TypeString, - Computed: true, + Description: "The AWS account ID.", + Type: schema.TypeString, + Computed: true, }, "oidc_aws_role_name": { - Type: schema.TypeString, - Computed: true, + Description: "The AWS role name.", + Type: schema.TypeString, + Computed: true, }, "oidc_aws_domain": { - Type: schema.TypeString, - Computed: true, + Description: "The AWS domain.", + Type: schema.TypeString, + Computed: true, }, "oidc_aws_domain_owner": { - Type: schema.TypeString, - Computed: true, + Description: "The AWS domain owner.", + Type: schema.TypeString, + Computed: true, }, "oidc_jfrog_provider_name": { - Type: schema.TypeString, - Computed: true, + Description: "The JFrog provider name.", + Type: schema.TypeString, + Computed: true, }, "oidc_audience": { - Type: schema.TypeString, - Computed: true, + Description: "The JWT audience.", + Type: schema.TypeString, + Computed: true, }, "oidc_jfrog_identity_mapping_name": { - Type: schema.TypeString, - Computed: true, + Description: "The JFrog identity mapping name.", + Type: schema.TypeString, + Computed: true, }, "selected_repository_ids": { - Type: schema.TypeSet, - Computed: true, + Description: "An array of repository IDs that can access the organization private registry.", + Type: schema.TypeSet, + Computed: true, Elem: &schema.Schema{ Type: schema.TypeInt, }, }, "created_at": { - Type: schema.TypeString, - Computed: true, + Description: "The time the registry was created.", + Type: schema.TypeString, + Computed: true, }, "updated_at": { - Type: schema.TypeString, - Computed: true, + Description: "The time the registry was updated.", + Type: schema.TypeString, + Computed: true, }, }, } diff --git a/github/data_source_github_organization_private_registry_test.go b/github/data_source_github_organization_private_registry_test.go index 9677e332cd..619b4e5769 100644 --- a/github/data_source_github_organization_private_registry_test.go +++ b/github/data_source_github_organization_private_registry_test.go @@ -4,17 +4,18 @@ import ( "testing" "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/knownvalue" + "github.com/hashicorp/terraform-plugin-testing/statecheck" + "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" ) -func TestAccDataSourceGithubOrganizationPrivateRegistry(t *testing.T) { - skipUnlessMode(t, organization) - +func TestAccGithubDataSourceOrganizationPrivateRegistry(t *testing.T) { config := ` resource "github_organization_private_registry" "test" { registry_type = "npm_registry" url = "https://npm.pkg.github.com" username = "github-actions" - secret = "super_secret_token_123" + value = "super_secret_token_123" visibility = "private" } @@ -24,7 +25,10 @@ func TestAccDataSourceGithubOrganizationPrivateRegistry(t *testing.T) { ` resource.Test(t, resource.TestCase{ - PreCheck: func() { skipUnlessHasOrgs(t) }, + PreCheck: func() { + skipUnlessMode(t, organization) + skipUnlessHasOrgs(t) + }, ProviderFactories: providerFactories, Steps: []resource.TestStep{ { diff --git a/github/resource_github_organization_private_registry.go b/github/resource_github_organization_private_registry.go index 8746a6d93f..3f80b24484 100644 --- a/github/resource_github_organization_private_registry.go +++ b/github/resource_github_organization_private_registry.go @@ -15,11 +15,12 @@ import ( func resourceGithubOrganizationPrivateRegistry() *schema.Resource { return &schema.Resource{ + Description: "This resource allows you to create and manage an organization private registry.", CreateContext: resourceGithubOrganizationPrivateRegistryCreate, ReadContext: resourceGithubOrganizationPrivateRegistryRead, UpdateContext: resourceGithubOrganizationPrivateRegistryUpdate, DeleteContext: resourceGithubOrganizationPrivateRegistryDelete, - CustomizeDiff: customdiff.All(resourceGithubOrganizationPrivateRegistryDiff), + CustomizeDiff: customdiff.All(resourceGithubOrganizationPrivateRegistryDiff, diffSecret, diffSecretVariableVisibility), Importer: &schema.ResourceImporter{ StateContext: schema.ImportStatePassthroughContext, }, @@ -52,25 +53,27 @@ func resourceGithubOrganizationPrivateRegistry() *schema.Resource { Default: false, Description: "Indicates whether this private registry should replace the base registry.", }, - "secret": { + "value": { Type: schema.TypeString, Optional: true, Sensitive: true, - ConflictsWith: []string{"encrypted_value"}, + ConflictsWith: []string{"value_encrypted"}, Description: "The plaintext secret to be encrypted and sent to GitHub. This is used for a token when auth_type is token, and for a password when auth_type is username_password. Required when auth_type is token or username_password.", }, - "encrypted_value": { + "value_encrypted": { Type: schema.TypeString, Optional: true, Sensitive: true, - ConflictsWith: []string{"secret"}, + ConflictsWith: []string{"value"}, Description: "The encrypted value of the secret using the GitHub public key in Base64 format.", }, "key_id": { - Type: schema.TypeString, - Optional: true, - Computed: true, - Description: "ID of the public key used to encrypt the secret. Required if encrypted_value is set.", + Type: schema.TypeString, + Optional: true, + Computed: true, + RequiredWith: []string{"value_encrypted"}, + ConflictsWith: []string{"value"}, + Description: "ID of the public key used to encrypt the secret. Required if encrypted_value is set.", }, "visibility": { Type: schema.TypeString, @@ -163,10 +166,10 @@ func resourceGithubOrganizationPrivateRegistryDiff(_ context.Context, d *schema. return nil } - if _, ok := d.GetOk("secret"); ok { + if _, ok := d.GetOk("value"); ok { return nil } - if _, ok := d.GetOk("encrypted_value"); ok { + if _, ok := d.GetOk("value_encrypted"); ok { return nil } @@ -177,7 +180,7 @@ func resourceGithubOrganizationPrivateRegistryCreate(ctx context.Context, d *sch client := meta.(*Owner).v3client org := meta.(*Owner).name - encryptedValue := d.Get("encrypted_value").(string) + encryptedValue := d.Get("value_encrypted").(string) keyID := d.Get("key_id").(string) authType := d.Get("auth_type").(string) @@ -190,7 +193,7 @@ func resourceGithubOrganizationPrivateRegistryCreate(ctx context.Context, d *sch keyID = ki if len(encryptedValue) == 0 { - plaintextValue := d.Get("secret").(string) + plaintextValue := d.Get("value").(string) encryptedBytes, err := encryptPlaintext(plaintextValue, pk) if err != nil { return diag.FromErr(err) @@ -362,11 +365,11 @@ func resourceGithubOrganizationPrivateRegistryUpdate(ctx context.Context, d *sch client := meta.(*Owner).v3client org := meta.(*Owner).name - encryptedValue := d.Get("encrypted_value").(string) + encryptedValue := d.Get("value_encrypted").(string) keyID := d.Get("key_id").(string) authType := d.Get("auth_type").(string) - if (d.HasChange("secret") || d.HasChange("encrypted_value")) && (authType == "token" || authType == "username_password") { + if (d.HasChange("value") || d.HasChange("value_encrypted")) && (authType == "token" || authType == "username_password") { ki, pk, err := getOrganizationRegistryPublicKeyDetails(ctx, client, org) if err != nil { return diag.FromErr(err) @@ -374,7 +377,7 @@ func resourceGithubOrganizationPrivateRegistryUpdate(ctx context.Context, d *sch keyID = ki if len(encryptedValue) == 0 { - plaintextValue := d.Get("secret").(string) + plaintextValue := d.Get("value").(string) encryptedBytes, err := encryptPlaintext(plaintextValue, pk) if err != nil { return diag.FromErr(err) diff --git a/github/resource_github_organization_private_registry_test.go b/github/resource_github_organization_private_registry_test.go index 7171044fa8..5e50e10a38 100644 --- a/github/resource_github_organization_private_registry_test.go +++ b/github/resource_github_organization_private_registry_test.go @@ -1,21 +1,23 @@ package github import ( + "fmt" "testing" "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/knownvalue" + "github.com/hashicorp/terraform-plugin-testing/statecheck" + "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" ) -func TestAccGithubOrganizationPrivateRegistry_basic(t *testing.T) { - skipUnlessMode(t, organization) - - config := ` +func TestAccGithubOrganizationPrivateRegistry(t *testing.T) { + configTmpl := ` resource "github_organization_private_registry" "test" { registry_type = "npm_registry" - url = "https://npm.pkg.github.com" + url = "%s" username = "github-actions" - secret = "super_secret_token_123" - visibility = "private" + value = "super_secret_token_123" + visibility = "%s" } data "github_organization_private_registry" "test" { @@ -23,54 +25,40 @@ func TestAccGithubOrganizationPrivateRegistry_basic(t *testing.T) { } ` - updatedConfig := ` - resource "github_organization_private_registry" "test" { - registry_type = "npm_registry" - url = "https://npm-registry.example.com" - username = "github-actions" - secret = "super_secret_token_123" - visibility = "all" - } - - data "github_organization_private_registry" "test" { - name = github_organization_private_registry.test.name - } - ` - - check := resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttrSet("github_organization_private_registry.test", "name"), - resource.TestCheckResourceAttr("github_organization_private_registry.test", "registry_type", "npm_registry"), - resource.TestCheckResourceAttr("github_organization_private_registry.test", "url", "https://npm.pkg.github.com"), - resource.TestCheckResourceAttr("github_organization_private_registry.test", "username", "github-actions"), - resource.TestCheckResourceAttr("github_organization_private_registry.test", "visibility", "private"), - resource.TestCheckResourceAttr("data.github_organization_private_registry.test", "registry_type", "npm_registry"), - ) - updatedCheck := resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttrSet("github_organization_private_registry.test", "name"), - resource.TestCheckResourceAttr("github_organization_private_registry.test", "registry_type", "npm_registry"), - resource.TestCheckResourceAttr("github_organization_private_registry.test", "url", "https://npm-registry.example.com"), - resource.TestCheckResourceAttr("github_organization_private_registry.test", "username", "github-actions"), - resource.TestCheckResourceAttr("github_organization_private_registry.test", "visibility", "all"), - resource.TestCheckResourceAttr("data.github_organization_private_registry.test", "registry_type", "npm_registry"), - ) - resource.Test(t, resource.TestCase{ - PreCheck: func() { skipUnlessHasOrgs(t) }, + PreCheck: func() { + skipUnlessMode(t, organization) + skipUnlessHasOrgs(t) + }, ProviderFactories: providerFactories, Steps: []resource.TestStep{ { - Config: config, - Check: check, + Config: fmt.Sprintf(configTmpl, "https://npm.pkg.github.com", "private"), + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue("github_organization_private_registry.test", tfjsonpath.New("name"), knownvalue.NotNull()), + statecheck.ExpectKnownValue("github_organization_private_registry.test", tfjsonpath.New("registry_type"), knownvalue.StringExact("npm_registry")), + statecheck.ExpectKnownValue("github_organization_private_registry.test", tfjsonpath.New("url"), knownvalue.StringExact("https://npm.pkg.github.com")), + statecheck.ExpectKnownValue("github_organization_private_registry.test", tfjsonpath.New("username"), knownvalue.StringExact("github-actions")), + statecheck.ExpectKnownValue("github_organization_private_registry.test", tfjsonpath.New("visibility"), knownvalue.StringExact("private")), + statecheck.ExpectKnownValue("data.github_organization_private_registry.test", tfjsonpath.New("registry_type"), knownvalue.StringExact("npm_registry")), + }, }, { ResourceName: "github_organization_private_registry.test", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"secret"}, + ImportStateVerifyIgnore: []string{"value"}, }, { - Config: updatedConfig, - Check: updatedCheck, + Config: fmt.Sprintf(configTmpl, "https://npm-registry.example.com", "all"), + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue("github_organization_private_registry.test", tfjsonpath.New("name"), knownvalue.NotNull()), + statecheck.ExpectKnownValue("github_organization_private_registry.test", tfjsonpath.New("registry_type"), knownvalue.StringExact("npm_registry")), + statecheck.ExpectKnownValue("github_organization_private_registry.test", tfjsonpath.New("url"), knownvalue.StringExact("https://npm-registry.example.com")), + statecheck.ExpectKnownValue("github_organization_private_registry.test", tfjsonpath.New("username"), knownvalue.StringExact("github-actions")), + statecheck.ExpectKnownValue("github_organization_private_registry.test", tfjsonpath.New("visibility"), knownvalue.StringExact("all")), + statecheck.ExpectKnownValue("data.github_organization_private_registry.test", tfjsonpath.New("registry_type"), knownvalue.StringExact("npm_registry")), + }, }, }, }) From 7a9f5da889f60e96380ace0dca5e3671d178e0a2 Mon Sep 17 00:00:00 2001 From: Lasse Gaardsholt Date: Fri, 3 Jul 2026 23:49:51 +0200 Subject: [PATCH 12/15] Fixed description for `registry_type` --- github/resource_github_organization_private_registry.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/github/resource_github_organization_private_registry.go b/github/resource_github_organization_private_registry.go index 3f80b24484..4e8d07083e 100644 --- a/github/resource_github_organization_private_registry.go +++ b/github/resource_github_organization_private_registry.go @@ -35,7 +35,7 @@ func resourceGithubOrganizationPrivateRegistry() *schema.Resource { Required: true, ForceNew: true, ValidateDiagFunc: validation.ToDiagFunc(validation.StringInSlice([]string{"maven_repository", "nuget_feed", "goproxy_server", "npm_registry", "rubygems_server", "cargo_registry", "composer_repository", "docker_registry", "git_source", "helm_registry", "pub_repository", "python_index", "terraform_registry"}, false)), - Description: "The registry type. Can be `maven_repository`, `nuget_feed`, `goproxy_server`, `npm_registry`, `rubygems_server`, `cargo_registry`, `composer_repository`, `docker_registry`, `git_source`, `helm_registry`, `pub_repository`, `python_index`, or `terraform_registry`.", + Description: "The registry type.", }, "url": { Type: schema.TypeString, From b21f84b51e4d1577aa94ac8436b52fadbb39e004 Mon Sep 17 00:00:00 2001 From: Lasse Gaardsholt Date: Fri, 3 Jul 2026 23:55:34 +0200 Subject: [PATCH 13/15] renamed old `encrypted_value` to `value_encrypted` --- github/resource_github_organization_private_registry.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/github/resource_github_organization_private_registry.go b/github/resource_github_organization_private_registry.go index 4e8d07083e..3c79a34d60 100644 --- a/github/resource_github_organization_private_registry.go +++ b/github/resource_github_organization_private_registry.go @@ -73,7 +73,7 @@ func resourceGithubOrganizationPrivateRegistry() *schema.Resource { Computed: true, RequiredWith: []string{"value_encrypted"}, ConflictsWith: []string{"value"}, - Description: "ID of the public key used to encrypt the secret. Required if encrypted_value is set.", + Description: "ID of the public key used to encrypt the secret. Required if value_encrypted is set.", }, "visibility": { Type: schema.TypeString, @@ -173,7 +173,7 @@ func resourceGithubOrganizationPrivateRegistryDiff(_ context.Context, d *schema. return nil } - return fmt.Errorf("one of `secret,encrypted_value` must be specified when auth_type is %q", authType) + return fmt.Errorf("one of `value,value_encrypted` must be specified when auth_type is %q", authType) } func resourceGithubOrganizationPrivateRegistryCreate(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { From 59dbff21cf4021c8e9027faef37137567f9357ab Mon Sep 17 00:00:00 2001 From: Lasse Gaardsholt Date: Sat, 4 Jul 2026 00:00:21 +0200 Subject: [PATCH 14/15] Added base64 validation to `value_encrypted` --- github/resource_github_organization_private_registry.go | 1 + 1 file changed, 1 insertion(+) diff --git a/github/resource_github_organization_private_registry.go b/github/resource_github_organization_private_registry.go index 3c79a34d60..2cc2dd99cf 100644 --- a/github/resource_github_organization_private_registry.go +++ b/github/resource_github_organization_private_registry.go @@ -65,6 +65,7 @@ func resourceGithubOrganizationPrivateRegistry() *schema.Resource { Optional: true, Sensitive: true, ConflictsWith: []string{"value"}, + ValidateDiagFunc: validation.ToDiagFunc(validation.StringIsBase64), Description: "The encrypted value of the secret using the GitHub public key in Base64 format.", }, "key_id": { From 0f1e2c259cd604d952054f72cbe439ff33c3bd17 Mon Sep 17 00:00:00 2001 From: Lasse Gaardsholt Date: Mon, 17 Aug 2026 09:00:14 +0200 Subject: [PATCH 15/15] fix: update go-github dependency to v89 Signed-off-by: Lasse Gaardsholt --- .../resource_github_organization_private_registry.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/github/resource_github_organization_private_registry.go b/github/resource_github_organization_private_registry.go index 2cc2dd99cf..4efa293ece 100644 --- a/github/resource_github_organization_private_registry.go +++ b/github/resource_github_organization_private_registry.go @@ -6,7 +6,7 @@ import ( "errors" "fmt" - "github.com/google/go-github/v88/github" + "github.com/google/go-github/v89/github" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" @@ -61,12 +61,12 @@ func resourceGithubOrganizationPrivateRegistry() *schema.Resource { Description: "The plaintext secret to be encrypted and sent to GitHub. This is used for a token when auth_type is token, and for a password when auth_type is username_password. Required when auth_type is token or username_password.", }, "value_encrypted": { - Type: schema.TypeString, - Optional: true, - Sensitive: true, - ConflictsWith: []string{"value"}, + Type: schema.TypeString, + Optional: true, + Sensitive: true, + ConflictsWith: []string{"value"}, ValidateDiagFunc: validation.ToDiagFunc(validation.StringIsBase64), - Description: "The encrypted value of the secret using the GitHub public key in Base64 format.", + Description: "The encrypted value of the secret using the GitHub public key in Base64 format.", }, "key_id": { Type: schema.TypeString,