Skip to content

Commit fa7d381

Browse files
Merge branch 'main' into develop
2 parents 6145388 + e3a3c6c commit fa7d381

8 files changed

+187
-57
lines changed

github/data_source_github_repository.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,9 @@ func dataSourceGithubRepository() *schema.Resource {
6161
Computed: true,
6262
},
6363
"has_downloads": {
64-
Type: schema.TypeBool,
65-
Computed: true,
64+
Type: schema.TypeBool,
65+
Computed: true,
66+
Deprecated: "This attribute is no longer in use, but it hasn't been removed yet. It will be removed in a future version. See https://github.com/orgs/community/discussions/102145#discussioncomment-8351756",
6667
},
6768
"has_wiki": {
6869
Type: schema.TypeBool,

github/resource_github_actions_organization_secret_test.go

Lines changed: 100 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,11 @@ import (
66
"strings"
77
"testing"
88

9+
"github.com/google/go-github/v81/github"
10+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
911
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
1012
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
13+
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
1114
)
1215

1316
func TestAccGithubActionsOrganizationSecret(t *testing.T) {
@@ -17,16 +20,16 @@ func TestAccGithubActionsOrganizationSecret(t *testing.T) {
1720

1821
config := fmt.Sprintf(`
1922
resource "github_actions_organization_secret" "plaintext_secret" {
20-
secret_name = "test_plaintext_secret"
21-
plaintext_value = "%s"
22-
visibility = "private"
23+
secret_name = "test_plaintext_secret"
24+
plaintext_value = "%s"
25+
visibility = "private"
2326
}
2427
2528
resource "github_actions_organization_secret" "encrypted_secret" {
26-
secret_name = "test_encrypted_secret"
27-
encrypted_value = "%s"
28-
visibility = "private"
29-
destroy_on_drift = false
29+
secret_name = "test_encrypted_secret"
30+
encrypted_value = "%s"
31+
visibility = "private"
32+
destroy_on_drift = false
3033
}
3134
`, secretValue, secretValue)
3235

@@ -143,8 +146,79 @@ func TestAccGithubActionsOrganizationSecret(t *testing.T) {
143146
},
144147
})
145148
})
149+
}
150+
151+
func TestAccGithubActionsOrganizationSecret_DestroyOnDrift(t *testing.T) {
152+
t.Run("destroyOnDrift false", func(t *testing.T) {
153+
destroyOnDrift := false
154+
t.Run("should ignore drift when ignore_changes lifecycle is configured", func(t *testing.T) {
155+
// Verify https://github.com/integrations/terraform-provider-github/issues/2614
156+
randomID := acctest.RandStringFromCharSet(5, acctest.CharSetAlphaNum)
157+
config := fmt.Sprintf(`
158+
resource "github_actions_organization_secret" "test_secret" {
159+
secret_name = "test_secret_%s"
160+
plaintext_value = "test_value"
161+
visibility = "private"
162+
163+
destroy_on_drift = %t
164+
lifecycle {
165+
ignore_changes = [plaintext_value]
166+
}
167+
}
168+
`, randomID, destroyOnDrift)
169+
170+
resource.Test(t, resource.TestCase{
171+
PreCheck: func() { skipUnlessHasOrgs(t) },
172+
Providers: testAccProviders,
173+
Steps: []resource.TestStep{
174+
{
175+
Config: config,
176+
},
177+
{
178+
Config: config,
179+
Check: resource.ComposeTestCheckFunc(
180+
func(s *terraform.State) error {
181+
rs, ok := s.RootModule().Resources["github_actions_organization_secret.test_secret"]
182+
if !ok {
183+
t.Errorf("not found: github_actions_organization_secret.test_secret")
184+
}
185+
// Now that the secret is created, update it to trigger a drift.
186+
client := testAccProvider.Meta().(*Owner).v3client
187+
owner := testAccProvider.Meta().(*Owner).name
188+
ctx := t.Context()
189+
190+
keyId, publicKey, err := getOrganizationPublicKeyDetails(owner, testAccProvider.Meta().(*Owner))
191+
if err != nil {
192+
t.Errorf("Failed to get organization public key details: %v", err)
193+
}
146194

147-
// Unit tests for drift detection behavior
195+
encryptedSecret, err := createEncryptedSecret(rs.Primary, "foo", keyId, publicKey)
196+
if err != nil {
197+
t.Errorf("Failed to create encrypted secret: %v", err)
198+
}
199+
_, err = client.Actions.CreateOrUpdateOrgSecret(ctx, owner, encryptedSecret)
200+
if err != nil {
201+
t.Errorf("Failed to create or update organization secret: %v", err)
202+
}
203+
return err
204+
},
205+
),
206+
},
207+
{
208+
Config: config,
209+
PlanOnly: true,
210+
ExpectNonEmptyPlan: false,
211+
},
212+
},
213+
})
214+
})
215+
})
216+
// t.Run("destroyOnDrift true", func(t *testing.T) {
217+
// destroyOnDrift := true
218+
// })
219+
}
220+
221+
func TestGithubActionsOrganizationSecret_DestroyOnDrift(t *testing.T) {
148222
t.Run("destroyOnDrift false clears sensitive values instead of recreating", func(t *testing.T) {
149223
originalTimestamp := "2023-01-01T00:00:00Z"
150224
newTimestamp := "2023-01-02T00:00:00Z"
@@ -248,3 +322,21 @@ func TestAccGithubActionsOrganizationSecret(t *testing.T) {
248322
}
249323
})
250324
}
325+
326+
func createEncryptedSecret(is *terraform.InstanceState, plaintextValue, keyId, publicKey string) (*github.EncryptedSecret, error) {
327+
secretName := is.Attributes["secret_name"]
328+
visibility := is.Attributes["visibility"]
329+
330+
encryptedBytes, err := encryptPlaintext(plaintextValue, publicKey)
331+
if err != nil {
332+
return nil, err
333+
}
334+
encryptedValue := base64.StdEncoding.EncodeToString(encryptedBytes)
335+
336+
return &github.EncryptedSecret{
337+
Name: secretName,
338+
KeyID: keyId,
339+
Visibility: visibility,
340+
EncryptedValue: encryptedValue,
341+
}, nil
342+
}

github/resource_github_organization_ruleset_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import (
99
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
1010
)
1111

12-
func TestGithubOrganizationRulesets(t *testing.T) {
12+
func TestAccGithubOrganizationRuleset(t *testing.T) {
1313
t.Run("create_branch_ruleset", func(t *testing.T) {
1414
randomID := acctest.RandStringFromCharSet(5, acctest.CharSetAlphaNum)
1515

github/resource_github_repository.go

Lines changed: 25 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,7 @@ func resourceGithubRepository() *schema.Resource {
211211
Type: schema.TypeBool,
212212
Optional: true,
213213
Description: "Set to 'true' to enable the (deprecated) downloads features on the repository.",
214+
Deprecated: "This attribute is no longer in use, but it hasn't been removed yet. It will be removed in a future version. See https://github.com/orgs/community/discussions/102145#discussioncomment-8351756",
214215
},
215216
"has_wiki": {
216217
Type: schema.TypeBool,
@@ -249,7 +250,7 @@ func resourceGithubRepository() *schema.Resource {
249250
"allow_forking": {
250251
Type: schema.TypeBool,
251252
Optional: true,
252-
Default: false,
253+
Computed: true,
253254
Description: "Set to 'true' to allow private forking on the repository; this is only relevant if the repository is owned by an organization and is private or internal.",
254255
},
255256
"squash_merge_commit_title": {
@@ -580,11 +581,13 @@ func calculateSecurityAndAnalysis(d *schema.ResourceData) *github.SecurityAndAna
580581
}
581582

582583
func resourceGithubRepositoryObject(d *schema.ResourceData) *github.Repository {
584+
visibility := calculateVisibility(d)
585+
583586
repository := &github.Repository{
584587
Name: github.Ptr(d.Get("name").(string)),
585588
Description: github.Ptr(d.Get("description").(string)),
586589
Homepage: github.Ptr(d.Get("homepage_url").(string)),
587-
Visibility: github.Ptr(calculateVisibility(d)),
590+
Visibility: github.Ptr(visibility),
588591
HasDownloads: github.Ptr(d.Get("has_downloads").(bool)),
589592
HasIssues: github.Ptr(d.Get("has_issues").(bool)),
590593
HasDiscussions: github.Ptr(d.Get("has_discussions").(bool)),
@@ -595,7 +598,6 @@ func resourceGithubRepositoryObject(d *schema.ResourceData) *github.Repository {
595598
AllowSquashMerge: github.Ptr(d.Get("allow_squash_merge").(bool)),
596599
AllowRebaseMerge: github.Ptr(d.Get("allow_rebase_merge").(bool)),
597600
AllowAutoMerge: github.Ptr(d.Get("allow_auto_merge").(bool)),
598-
AllowForking: github.Ptr(d.Get("allow_forking").(bool)),
599601
DeleteBranchOnMerge: github.Ptr(d.Get("delete_branch_on_merge").(bool)),
600602
WebCommitSignoffRequired: github.Ptr(d.Get("web_commit_signoff_required").(bool)),
601603
AutoInit: github.Ptr(d.Get("auto_init").(bool)),
@@ -625,6 +627,12 @@ func resourceGithubRepositoryObject(d *schema.ResourceData) *github.Repository {
625627
}
626628
}
627629

630+
// only configure allow forking if repository is not public
631+
allowForking, ok := d.Get("allow_forking").(bool)
632+
if ok && visibility != "public" {
633+
repository.AllowForking = github.Ptr(allowForking)
634+
}
635+
628636
return repository
629637
}
630638

@@ -637,27 +645,10 @@ func resourceGithubRepositoryCreate(ctx context.Context, d *schema.ResourceData,
637645

638646
repoReq := resourceGithubRepositoryObject(d)
639647
owner := meta.(*Owner).name
640-
641648
repoName := repoReq.GetName()
642649

643-
// determine if repository should be private. assume public to start
644-
isPrivate := false
645-
646-
// prefer visibility to private flag since private flag is deprecated
647-
privateKeyword, ok := d.Get("private").(bool)
648-
if ok {
649-
isPrivate = privateKeyword
650-
}
651-
652-
visibility, ok := d.Get("visibility").(string)
653-
if ok {
654-
if visibility == "private" || visibility == "internal" {
655-
isPrivate = true
656-
}
657-
}
658-
650+
isPrivate := repoReq.GetVisibility() == "private"
659651
repoReq.Private = github.Ptr(isPrivate)
660-
661652
if template, ok := d.GetOk("template"); ok {
662653
templateConfigBlocks := template.([]any)
663654

@@ -928,8 +919,15 @@ func resourceGithubRepositoryUpdate(ctx context.Context, d *schema.ResourceData,
928919
repoReq := resourceGithubRepositoryObject(d)
929920

930921
// handle visibility updates separately from other fields
922+
visibility := repoReq.GetVisibility()
931923
repoReq.Visibility = nil
932924

925+
// This change needs to be made with the correct visibility
926+
allowForking := repoReq.AllowForking
927+
if d.HasChanges("visibility", "private") {
928+
repoReq.AllowForking = nil
929+
}
930+
933931
if !d.HasChange("security_and_analysis") {
934932
repoReq.SecurityAndAnalysis = nil
935933
log.Print("[DEBUG] No security_and_analysis update required. Removing this field from the payload.")
@@ -1015,32 +1013,17 @@ func resourceGithubRepositoryUpdate(ctx context.Context, d *schema.ResourceData,
10151013
}
10161014
}
10171015

1018-
if d.HasChange("visibility") {
1019-
o, n := d.GetChange("visibility")
1020-
repoReq.Visibility = github.Ptr(n.(string))
1021-
log.Printf("[DEBUG] Updating repository visibility from %s to %s", o, n)
1022-
_, resp, err := client.Repositories.Edit(ctx, owner, repoName, repoReq)
1023-
if err != nil {
1024-
if resp.StatusCode != 422 || !strings.Contains(err.Error(), fmt.Sprintf("Visibility is already %s", n.(string))) {
1025-
return diag.FromErr(err)
1026-
}
1027-
}
1028-
} else {
1029-
log.Printf("[DEBUG] No visibility update required. visibility: %s", d.Get("visibility"))
1030-
}
1016+
if d.HasChanges("visibility", "private") {
1017+
repoReq.Visibility = github.Ptr(visibility)
1018+
repoReq.AllowForking = allowForking
10311019

1032-
if d.HasChange("private") {
1033-
o, n := d.GetChange("private")
1034-
repoReq.Private = github.Ptr(n.(bool))
1035-
log.Printf("[DEBUG] Updating repository privacy from %v to %v", o, n)
1036-
_, _, err = client.Repositories.Edit(ctx, owner, repoName, repoReq)
1020+
log.Printf("[DEBUG] Updating repository visibility from %s to %s", repo.GetVisibility(), visibility)
1021+
_, resp, err := client.Repositories.Edit(ctx, owner, repoName, repoReq)
10371022
if err != nil {
1038-
if !strings.Contains(err.Error(), "422 Privacy is already set") {
1023+
if resp.StatusCode != 422 || !strings.Contains(err.Error(), fmt.Sprintf("Visibility is already %s", visibility)) {
10391024
return diag.FromErr(err)
10401025
}
10411026
}
1042-
} else {
1043-
log.Printf("[DEBUG] No privacy update required. private: %v", d.Get("private"))
10441027
}
10451028

10461029
return resourceGithubRepositoryRead(ctx, d, meta)

github/resource_github_repository_ruleset_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import (
1212
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
1313
)
1414

15-
func TestGithubRepositoryRulesets(t *testing.T) {
15+
func TestAccGithubRepositoryRuleset(t *testing.T) {
1616
t.Run("create_branch_ruleset", func(t *testing.T) {
1717
randomID := acctest.RandStringFromCharSet(5, acctest.CharSetAlphaNum)
1818

@@ -501,7 +501,7 @@ resource "github_repository_ruleset" "test" {
501501
})
502502
}
503503

504-
func TestGithubRepositoryRulesetArchived(t *testing.T) {
504+
func TestAccGithubRepositoryRulesetArchived(t *testing.T) {
505505
randomID := acctest.RandStringFromCharSet(5, acctest.CharSetAlphaNum)
506506

507507
t.Run("skips update and delete on archived repository", func(t *testing.T) {

github/resource_github_repository_test.go

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1061,6 +1061,60 @@ func TestAccGithubRepository(t *testing.T) {
10611061
})
10621062
})
10631063

1064+
t.Run("update_public_to_private_allow_forking", func(t *testing.T) {
1065+
randomID := acctest.RandStringFromCharSet(5, acctest.CharSetAlphaNum)
1066+
config := fmt.Sprintf(`
1067+
resource "github_repository" "test" {
1068+
name = "tf-acc-test-%s"
1069+
visibility = "public"
1070+
}
1071+
`, randomID)
1072+
1073+
configPrivate := fmt.Sprintf(`
1074+
resource "github_repository" "test" {
1075+
name = "tf-acc-test-%s"
1076+
visibility = "private"
1077+
allow_forking = false
1078+
}
1079+
`, randomID)
1080+
1081+
configPrivateForking := fmt.Sprintf(`
1082+
resource "github_repository" "test" {
1083+
name = "tf-acc-test-%s"
1084+
visibility = "private"
1085+
allow_forking = true
1086+
}
1087+
`, randomID)
1088+
1089+
resource.Test(t, resource.TestCase{
1090+
PreCheck: func() { skipUnauthenticated(t) },
1091+
ProviderFactories: providerFactories,
1092+
Steps: []resource.TestStep{
1093+
{
1094+
Config: config,
1095+
Check: resource.ComposeTestCheckFunc(
1096+
resource.TestCheckResourceAttr("github_repository.test", "visibility", "public"),
1097+
resource.TestCheckResourceAttr("github_repository.test", "allow_forking", "true"),
1098+
),
1099+
},
1100+
{
1101+
Config: configPrivate,
1102+
Check: resource.ComposeTestCheckFunc(
1103+
resource.TestCheckResourceAttr("github_repository.test", "visibility", "private"),
1104+
resource.TestCheckResourceAttr("github_repository.test", "allow_forking", "false"),
1105+
),
1106+
},
1107+
{
1108+
Config: configPrivateForking,
1109+
Check: resource.ComposeTestCheckFunc(
1110+
resource.TestCheckResourceAttr("github_repository.test", "visibility", "private"),
1111+
resource.TestCheckResourceAttr("github_repository.test", "allow_forking", "true"),
1112+
),
1113+
},
1114+
},
1115+
})
1116+
})
1117+
10641118
t.Run("updates repos to public visibility", func(t *testing.T) {
10651119
randomID := acctest.RandStringFromCharSet(5, acctest.CharSetAlphaNum)
10661120
config := fmt.Sprintf(`

website/docs/d/repository.html.markdown

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ The following arguments are supported:
6767

6868
* `merge_commit_message` - The default value for a merge commit message.
6969

70-
* `has_downloads` - Whether the repository has Downloads feature enabled.
70+
* `has_downloads` - (**DEPRECATED**) Whether the repository has Downloads feature enabled. This attribute is no longer in use, but it hasn't been removed yet. It will be removed in a future version. See [this discussion](https://github.com/orgs/community/discussions/102145#discussioncomment-8351756).
7171

7272
* `default_branch` - The name of the default branch of the repository.
7373

website/docs/r/repository.html.markdown

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ The following arguments are supported:
114114

115115
* `web_commit_signoff_required` - (Optional) Require contributors to sign off on web-based commits. See more [here](https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/managing-repository-settings/managing-the-commit-signoff-policy-for-your-repository). Defaults to `false`.
116116

117-
* `has_downloads` - (Optional) Set to `true` to enable the (deprecated) downloads features on the repository.
117+
* `has_downloads` - (**DEPRECATED**) (Optional) Set to `true` to enable the (deprecated) downloads features on the repository. This attribute is no longer in use, but it hasn't been removed yet. It will be removed in a future version. See [this discussion](https://github.com/orgs/community/discussions/102145#discussioncomment-8351756).
118118

119119
* `auto_init` - (Optional) Set to `true` to produce an initial commit in the repository.
120120

0 commit comments

Comments
 (0)