@@ -10,19 +10,20 @@ import (
1010 "strings"
1111
1212 "github.com/google/go-github/v67/github"
13+ "github.com/hashicorp/terraform-plugin-sdk/v2/diag"
1314 "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff"
1415 "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
1516 "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
1617)
1718
1819func resourceGithubRepository () * schema.Resource {
1920 return & schema.Resource {
20- Create : resourceGithubRepositoryCreate ,
21- Read : resourceGithubRepositoryRead ,
22- Update : resourceGithubRepositoryUpdate ,
23- Delete : resourceGithubRepositoryDelete ,
21+ CreateContext : resourceGithubRepositoryCreate ,
22+ ReadContext : resourceGithubRepositoryRead ,
23+ UpdateContext : resourceGithubRepositoryUpdate ,
24+ DeleteContext : resourceGithubRepositoryDelete ,
2425 Importer : & schema.ResourceImporter {
25- State : func (d * schema.ResourceData , meta any ) ([]* schema.ResourceData , error ) {
26+ StateContext : func (ctx context. Context , d * schema.ResourceData , meta any ) ([]* schema.ResourceData , error ) {
2627 if err := d .Set ("auto_init" , false ); err != nil {
2728 return nil , err
2829 }
@@ -390,7 +391,7 @@ func resourceGithubRepository() *schema.Resource {
390391 Type : schema .TypeBool ,
391392 Optional : true ,
392393 Computed : true ,
393- Description : "Set to 'true' to enable security alerts for vulnerable dependencies. Enabling requires alerts to be enabled on the owner level. (Note for importing: GitHub enables the alerts on public repos but disables them on private repos by default). Note that vulnerability alerts have not been successfully tested on any GitHub Enterprise instance and may be unavailable in those settings." ,
394+ Description : "Set to 'true' to enable security alerts for vulnerable dependencies. Enabling requires alerts to be enabled on the owner level. (Note for importing: GitHub enables the alerts on all repos by default). Note that vulnerability alerts have not been successfully tested on any GitHub Enterprise instance and may be unavailable in those settings." ,
394395 },
395396 "ignore_vulnerability_alerts_during_read" : {
396397 Type : schema .TypeBool ,
@@ -620,18 +621,17 @@ func resourceGithubRepositoryObject(d *schema.ResourceData) *github.Repository {
620621 return repository
621622}
622623
623- func resourceGithubRepositoryCreate (d * schema.ResourceData , meta any ) error {
624+ func resourceGithubRepositoryCreate (ctx context. Context , d * schema.ResourceData , meta any ) diag. Diagnostics {
624625 client := meta .(* Owner ).v3client
625626
626627 if branchName , hasDefaultBranch := d .GetOk ("default_branch" ); hasDefaultBranch && (branchName != "main" ) {
627- return fmt .Errorf ("cannot set the default branch on a new repository to something other than 'main'" )
628+ return diag .Errorf ("cannot set the default branch on a new repository to something other than 'main'" )
628629 }
629630
630631 repoReq := resourceGithubRepositoryObject (d )
631632 owner := meta .(* Owner ).name
632633
633634 repoName := repoReq .GetName ()
634- ctx := context .Background ()
635635
636636 // determine if repository should be private. assume public to start
637637 isPrivate := false
@@ -657,7 +657,7 @@ func resourceGithubRepositoryCreate(d *schema.ResourceData, meta any) error {
657657 for _ , templateConfigBlock := range templateConfigBlocks {
658658 templateConfigMap , ok := templateConfigBlock .(map [string ]any )
659659 if ! ok {
660- return errors .New ("failed to unpack template configuration block" )
660+ return diag . FromErr ( errors .New ("failed to unpack template configuration block" ) )
661661 }
662662
663663 templateRepo := templateConfigMap ["repository" ].(string )
@@ -678,7 +678,7 @@ func resourceGithubRepositoryCreate(d *schema.ResourceData, meta any) error {
678678 & templateRepoReq ,
679679 )
680680 if err != nil {
681- return err
681+ return diag . FromErr ( err )
682682 }
683683
684684 d .SetId (* repo .Name )
@@ -691,7 +691,7 @@ func resourceGithubRepositoryCreate(d *schema.ResourceData, meta any) error {
691691 log .Printf ("[INFO] Creating fork of %s/%s in %s" , sourceOwner , sourceRepo , owner )
692692
693693 if sourceOwner == "" || sourceRepo == "" {
694- return fmt .Errorf ("source_owner and source_repo must be provided when forking a repository" )
694+ return diag .Errorf ("source_owner and source_repo must be provided when forking a repository" )
695695 }
696696
697697 // Create the fork using the GitHub client library
@@ -712,18 +712,18 @@ func resourceGithubRepositoryCreate(d *schema.ResourceData, meta any) error {
712712 log .Printf ("[INFO] Fork is being created asynchronously" )
713713 // Despite the 202 status, the API should still return preliminary fork information
714714 if fork == nil {
715- return fmt .Errorf ("fork information not available after accepted status" )
715+ return diag .Errorf ("fork information not available after accepted status" )
716716 }
717717 log .Printf ("[DEBUG] Fork name: %s" , fork .GetName ())
718718 } else {
719- return fmt .Errorf ("failed to create fork: %w " , err )
719+ return diag .Errorf ("failed to create fork: %s " , err . Error () )
720720 }
721721 } else if resp != nil {
722722 log .Printf ("[DEBUG] Fork response status: %d" , resp .StatusCode )
723723 }
724724
725725 if fork == nil {
726- return fmt .Errorf ("fork creation failed - no repository returned" )
726+ return diag .Errorf ("fork creation failed - no repository returned" )
727727 }
728728
729729 log .Printf ("[INFO] Fork created with name: %s" , fork .GetName ())
@@ -747,7 +747,7 @@ func resourceGithubRepositoryCreate(d *schema.ResourceData, meta any) error {
747747 repo , _ , err = client .Repositories .Create (ctx , "" , repoReq )
748748 }
749749 if err != nil {
750- return err
750+ return diag . FromErr ( err )
751751 }
752752 d .SetId (repo .GetName ())
753753 }
@@ -756,27 +756,27 @@ func resourceGithubRepositoryCreate(d *schema.ResourceData, meta any) error {
756756 if len (topics ) > 0 {
757757 _ , _ , err := client .Repositories .ReplaceAllTopics (ctx , owner , repoName , topics )
758758 if err != nil {
759- return err
759+ return diag . FromErr ( err )
760760 }
761761 }
762762
763763 pages := expandPages (d .Get ("pages" ).([]any ))
764764 if pages != nil {
765765 _ , _ , err := client .Repositories .EnablePages (ctx , owner , repoName , pages )
766766 if err != nil {
767- return err
767+ return diag . FromErr ( err )
768768 }
769769 }
770770
771771 err := updateVulnerabilityAlerts (d , client , ctx , owner , repoName )
772772 if err != nil {
773- return err
773+ return diag . FromErr ( err )
774774 }
775775
776- return resourceGithubRepositoryUpdate (d , meta )
776+ return resourceGithubRepositoryUpdate (ctx , d , meta )
777777}
778778
779- func resourceGithubRepositoryRead (d * schema.ResourceData , meta any ) error {
779+ func resourceGithubRepositoryRead (ctx context. Context , d * schema.ResourceData , meta any ) diag. Diagnostics {
780780 client := meta .(* Owner ).v3client
781781
782782 owner := meta .(* Owner ).name
@@ -788,7 +788,7 @@ func resourceGithubRepositoryRead(d *schema.ResourceData, meta any) error {
788788 owner = explicitOwner
789789 }
790790
791- ctx : = context .WithValue (context . Background () , ctxId , d .Id ())
791+ ctx = context .WithValue (ctx , ctxId , d .Id ())
792792 if ! d .IsNewResource () {
793793 ctx = context .WithValue (ctx , ctxEtag , d .Get ("etag" ).(string ))
794794 }
@@ -807,7 +807,7 @@ func resourceGithubRepositoryRead(d *schema.ResourceData, meta any) error {
807807 return nil
808808 }
809809 }
810- return err
810+ return diag . FromErr ( err )
811811 }
812812
813813 _ = d .Set ("etag" , resp .Header .Get ("ETag" ))
@@ -853,10 +853,10 @@ func resourceGithubRepositoryRead(d *schema.ResourceData, meta any) error {
853853 if repo .GetHasPages () {
854854 pages , _ , err := client .Repositories .GetPagesInfo (ctx , owner , repoName )
855855 if err != nil {
856- return err
856+ return diag . FromErr ( err )
857857 }
858858 if err := d .Set ("pages" , flattenPages (pages )); err != nil {
859- return fmt .Errorf ("error setting pages: %w " , err )
859+ return diag .Errorf ("error setting pages: %s " , err . Error () )
860860 }
861861 }
862862
@@ -882,32 +882,32 @@ func resourceGithubRepositoryRead(d *schema.ResourceData, meta any) error {
882882 "repository" : repo .TemplateRepository .Name ,
883883 },
884884 }); err != nil {
885- return err
885+ return diag . FromErr ( err )
886886 }
887887 } else {
888888 if err = d .Set ("template" , []any {}); err != nil {
889- return err
889+ return diag . FromErr ( err )
890890 }
891891 }
892892
893893 if ! d .Get ("ignore_vulnerability_alerts_during_read" ).(bool ) {
894894 vulnerabilityAlerts , _ , err := client .Repositories .GetVulnerabilityAlerts (ctx , owner , repoName )
895895 if err != nil {
896- return fmt .Errorf ("error reading repository vulnerability alerts: %w " , err )
896+ return diag .Errorf ("error reading repository vulnerability alerts: %s " , err . Error () )
897897 }
898898 if err = d .Set ("vulnerability_alerts" , vulnerabilityAlerts ); err != nil {
899- return err
899+ return diag . FromErr ( err )
900900 }
901901 }
902902
903903 if err = d .Set ("security_and_analysis" , flattenSecurityAndAnalysis (repo .GetSecurityAndAnalysis ())); err != nil {
904- return err
904+ return diag . FromErr ( err )
905905 }
906906
907907 return nil
908908}
909909
910- func resourceGithubRepositoryUpdate (d * schema.ResourceData , meta any ) error {
910+ func resourceGithubRepositoryUpdate (ctx context. Context , d * schema.ResourceData , meta any ) diag. Diagnostics {
911911 // Can only update a repository if it is not archived or the update is to
912912 // archive the repository (unarchiving is not supported by the GitHub API)
913913 if d .Get ("archived" ).(bool ) && ! d .HasChange ("archived" ) {
@@ -937,7 +937,7 @@ func resourceGithubRepositoryUpdate(d *schema.ResourceData, meta any) error {
937937
938938 repoName := d .Id ()
939939 owner := meta .(* Owner ).name
940- ctx : = context .WithValue (context . Background () , ctxId , d .Id ())
940+ ctx = context .WithValue (ctx , ctxId , d .Id ())
941941
942942 // When the organization has "Require sign off on web-based commits" enabled,
943943 // the API doesn't allow you to send `web_commit_signoff_required` in order to
@@ -955,7 +955,7 @@ func resourceGithubRepositoryUpdate(d *schema.ResourceData, meta any) error {
955955
956956 repo , _ , err := client .Repositories .Edit (ctx , owner , repoName , repoReq )
957957 if err != nil {
958- return err
958+ return diag . FromErr ( err )
959959 }
960960 d .SetId (* repo .Name )
961961
@@ -964,7 +964,7 @@ func resourceGithubRepositoryUpdate(d *schema.ResourceData, meta any) error {
964964 if opts != nil {
965965 pages , res , err := client .Repositories .GetPagesInfo (ctx , owner , repoName )
966966 if res .StatusCode != http .StatusNotFound && err != nil {
967- return err
967+ return diag . FromErr ( err )
968968 }
969969
970970 if pages == nil {
@@ -973,12 +973,12 @@ func resourceGithubRepositoryUpdate(d *schema.ResourceData, meta any) error {
973973 _ , err = client .Repositories .UpdatePages (ctx , owner , repoName , opts )
974974 }
975975 if err != nil {
976- return err
976+ return diag . FromErr ( err )
977977 }
978978 } else {
979979 _ , err := client .Repositories .DisablePages (ctx , owner , repoName )
980980 if err != nil {
981- return err
981+ return diag . FromErr ( err )
982982 }
983983 }
984984 }
@@ -987,23 +987,23 @@ func resourceGithubRepositoryUpdate(d *schema.ResourceData, meta any) error {
987987 topics := repoReq .Topics
988988 _ , _ , err = client .Repositories .ReplaceAllTopics (ctx , owner , * repo .Name , topics )
989989 if err != nil {
990- return err
990+ return diag . FromErr ( err )
991991 }
992992 d .SetId (* repo .Name )
993993
994994 if d .HasChange ("topics" ) {
995995 topics := repoReq .Topics
996996 _ , _ , err = client .Repositories .ReplaceAllTopics (ctx , owner , * repo .Name , topics )
997997 if err != nil {
998- return err
998+ return diag . FromErr ( err )
999999 }
10001000 }
10011001 }
10021002
10031003 if d .HasChange ("vulnerability_alerts" ) {
10041004 err = updateVulnerabilityAlerts (d , client , ctx , owner , repoName )
10051005 if err != nil {
1006- return err
1006+ return diag . FromErr ( err )
10071007 }
10081008 }
10091009
@@ -1014,7 +1014,7 @@ func resourceGithubRepositoryUpdate(d *schema.ResourceData, meta any) error {
10141014 _ , resp , err := client .Repositories .Edit (ctx , owner , repoName , repoReq )
10151015 if err != nil {
10161016 if resp .StatusCode != 422 || ! strings .Contains (err .Error (), fmt .Sprintf ("Visibility is already %s" , n .(string ))) {
1017- return err
1017+ return diag . FromErr ( err )
10181018 }
10191019 }
10201020 } else {
@@ -1028,21 +1028,21 @@ func resourceGithubRepositoryUpdate(d *schema.ResourceData, meta any) error {
10281028 _ , _ , err = client .Repositories .Edit (ctx , owner , repoName , repoReq )
10291029 if err != nil {
10301030 if ! strings .Contains (err .Error (), "422 Privacy is already set" ) {
1031- return err
1031+ return diag . FromErr ( err )
10321032 }
10331033 }
10341034 } else {
10351035 log .Printf ("[DEBUG] No privacy update required. private: %v" , d .Get ("private" ))
10361036 }
10371037
1038- return resourceGithubRepositoryRead (d , meta )
1038+ return resourceGithubRepositoryRead (ctx , d , meta )
10391039}
10401040
1041- func resourceGithubRepositoryDelete (d * schema.ResourceData , meta any ) error {
1041+ func resourceGithubRepositoryDelete (ctx context. Context , d * schema.ResourceData , meta any ) diag. Diagnostics {
10421042 client := meta .(* Owner ).v3client
10431043 repoName := d .Id ()
10441044 owner := meta .(* Owner ).name
1045- ctx : = context .WithValue (context . Background () , ctxId , d .Id ())
1045+ ctx = context .WithValue (ctx , ctxId , d .Id ())
10461046
10471047 archiveOnDestroy := d .Get ("archive_on_destroy" ).(bool )
10481048 if archiveOnDestroy {
@@ -1051,20 +1051,20 @@ func resourceGithubRepositoryDelete(d *schema.ResourceData, meta any) error {
10511051 return nil
10521052 } else {
10531053 if err := d .Set ("archived" , true ); err != nil {
1054- return err
1054+ return diag . FromErr ( err )
10551055 }
10561056 repoReq := resourceGithubRepositoryObject (d )
10571057 // Always remove `web_commit_signoff_required` when archiving, to avoid 422 error
10581058 repoReq .WebCommitSignoffRequired = nil
10591059 log .Printf ("[DEBUG] Archiving repository on delete: %s/%s" , owner , repoName )
10601060 _ , _ , err := client .Repositories .Edit (ctx , owner , repoName , repoReq )
1061- return err
1061+ return diag . FromErr ( err )
10621062 }
10631063 }
10641064
10651065 log .Printf ("[DEBUG] Deleting repository: %s/%s" , owner , repoName )
10661066 _ , err := client .Repositories .Delete (ctx , owner , repoName )
1067- return err
1067+ return diag . FromErr ( err )
10681068}
10691069
10701070func expandPages (input []any ) * github.Pages {
@@ -1243,11 +1243,22 @@ func resourceGithubParseFullName(resourceDataLike interface {
12431243}
12441244
12451245func updateVulnerabilityAlerts (d * schema.ResourceData , client * github.Client , ctx context.Context , owner , repoName string ) error {
1246- updateVulnerabilityAlerts := client .Repositories .DisableVulnerabilityAlerts
1247- if vulnerabilityAlerts , ok := d .GetOk ("vulnerability_alerts" ); ok && vulnerabilityAlerts .(bool ) {
1248- updateVulnerabilityAlerts = client .Repositories .EnableVulnerabilityAlerts
1246+ updateVulnerabilityAlertsSDK := client .Repositories .DisableVulnerabilityAlerts
1247+ vulnerabilityAlerts , ok := d .GetOk ("vulnerability_alerts" )
1248+
1249+ // Only if the vulnerability alerts are specifically set to true, enable them.
1250+ // Otherwise, disable them as GitHub defaults to enabled and we have not wanted to introduce a breaking change for this yet.
1251+ if ok && vulnerabilityAlerts .(bool ) {
1252+ updateVulnerabilityAlertsSDK = client .Repositories .EnableVulnerabilityAlerts
12491253 }
12501254
1251- _ , err := updateVulnerabilityAlerts (ctx , owner , repoName )
1255+ resp , err := updateVulnerabilityAlertsSDK (ctx , owner , repoName )
1256+ if err != nil {
1257+ // Check if the error is because an Organization or Enterprise policy is preventing the change
1258+ // This is a temporary workaround while we extract Vulnerability Alerts into a separate resource.
1259+ if resp .StatusCode == http .StatusUnprocessableEntity && strings .Contains (err .Error (), "An enforced security configuration prevented modifying" ) && ! ok {
1260+ return nil
1261+ }
1262+ }
12521263 return err
12531264}
0 commit comments