Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
185955d
Add resource for repository pages and deprecate it from repository R
deiga Feb 8, 2026
9573c9a
Add data source for repository pages and deprecate it from repository DS
deiga Feb 8, 2026
3fa91c9
Update formatting of docs page
deiga Feb 8, 2026
201bd36
Change `github_repository` to only Read pages info if pages is in the…
deiga Feb 8, 2026
375abaf
Fix faulty test
deiga Feb 8, 2026
67ce894
Update Import test
deiga Feb 13, 2026
fe1b608
Add `repository_id` diff logic and unify naming
deiga Feb 16, 2026
e0c486c
Use `ConfigStateChecks` in DS tests
deiga Feb 17, 2026
a26cc55
Refactor to use `ConfigStateChecks` in Resource
deiga Feb 17, 2026
1464785
Comment out `owner` field for now
deiga Feb 17, 2026
60ab3f0
Comment out `owner` field for DS as well
deiga Feb 19, 2026
f58d1be
Simplify import ID
deiga Feb 19, 2026
9d0c41c
Add support for `public` field in pages
deiga Feb 19, 2026
e3f1c9c
Update docs
deiga Feb 19, 2026
0b3605a
Improve field descriptions
deiga Feb 19, 2026
fb8a929
Only modify `CNAME` in state if it has a value upstream
deiga Feb 19, 2026
5eb4333
Add `https_enforced` field
deiga Feb 21, 2026
4612467
Update `go-github` version
deiga Feb 21, 2026
a7429b7
Replace `switch` with `if`
deiga Feb 23, 2026
425f356
Re-order `d.Set` calls
deiga Feb 23, 2026
bfb9319
Restructure `UpdatePages` section
deiga Feb 23, 2026
c37b496
Refactor tests to use `testAccConf.testRepositoryVisibility`
deiga Feb 24, 2026
4c56ad0
Fix linter
deiga Mar 30, 2026
cd3a680
Add tests to ensure that `source` validation works properly
deiga Apr 16, 2026
9235e4c
Add more debug logging and fix validation
deiga Apr 16, 2026
5170b65
Fixed validation tests to notify when they are not working
deiga Apr 16, 2026
eb4caae
Add comments to make it clearer why we need to use this partial value…
deiga Apr 18, 2026
64db034
Remove unnecessary `hasChanges` checks and explain the ones that are …
deiga Apr 18, 2026
e7d9740
Address review comments
deiga Apr 22, 2026
1babab0
Reduce test time by parallelising
deiga Apr 22, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions github/data_source_github_repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -241,8 +241,9 @@ func dataSourceGithubRepository() *schema.Resource {
},
},
"pages": {
Type: schema.TypeList,
Computed: true,
Type: schema.TypeList,
Computed: true,
Deprecated: "Use the github_repository_pages data source instead. This field will be removed in a future version.",
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"source": {
Expand Down
156 changes: 156 additions & 0 deletions github/data_source_github_repository_pages.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
package github

import (
"context"
"net/http"
"strconv"

"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

func dataSourceGithubRepositoryPages() *schema.Resource {
return &schema.Resource{
Description: "Use this data source to retrieve GitHub Pages configuration for a repository.",
ReadContext: dataSourceGithubRepositoryPagesRead,

Schema: map[string]*schema.Schema{
"repository": {
Type: schema.TypeString,
Required: true,
Description: "The repository name to get GitHub Pages information for.",
},
// TODO: Uncomment this when we are ready to support owner fields properly. https://github.com/integrations/terraform-provider-github/pull/3166#discussion_r2816053082
// "owner": {
// Type: schema.TypeString,
// Required: true,
// Description: "The owner of the repository.",
// },
"source": {
Type: schema.TypeList,
Computed: true,
Description: "The source branch and directory for the rendered Pages site.",
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"branch": {
Type: schema.TypeString,
Computed: true,
Description: "The repository branch used to publish the site's source files.",
},
"path": {
Type: schema.TypeString,
Computed: true,
Description: "The repository directory from which the site publishes.",
},
},
},
},
"build_type": {
Type: schema.TypeString,
Computed: true,
Description: "The type of GitHub Pages site. Can be 'legacy' or 'workflow'.",
},
"cname": {
Type: schema.TypeString,
Computed: true,
Description: "The custom domain for the repository.",
},
"custom_404": {
Type: schema.TypeBool,
Computed: true,
Description: "Whether the rendered GitHub Pages site has a custom 404 page.",
},
"html_url": {
Type: schema.TypeString,
Computed: true,
Description: "The absolute URL (with scheme) to the rendered GitHub Pages site.",
},
"build_status": {
Type: schema.TypeString,
Computed: true,
Description: "The GitHub Pages site's build status e.g. 'building' or 'built'.",
},
"api_url": {
Type: schema.TypeString,
Computed: true,
Description: "The API URL of the GitHub Pages resource.",
},
"public": {
Type: schema.TypeBool,
Computed: true,
Description: "Whether the GitHub Pages site is publicly visible. If set to `true`, the site is accessible to anyone on the internet. If set to `false`, the site will only be accessible to users who have at least `read` access to the repository that published the site.",
},
"https_enforced": {
Type: schema.TypeBool,
Computed: true,
Description: "Whether the rendered GitHub Pages site will only be served over HTTPS.",
},
},
}
}

func dataSourceGithubRepositoryPagesRead(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics {
meta := m.(*Owner)
client := meta.v3client

owner := meta.name // TODO: Add owner support // d.Get("owner").(string)
repoName := d.Get("repository").(string)

pages, resp, err := client.Repositories.GetPagesInfo(ctx, owner, repoName)
if err != nil {
if resp != nil && resp.StatusCode == http.StatusNotFound {
return diag.Errorf("GitHub Pages not found for repository %s/%s", owner, repoName)
}
return diag.Errorf("error reading repository pages: %s", err.Error())
}

repo, _, err := client.Repositories.Get(ctx, owner, repoName)
if err != nil {
return diag.FromErr(err)
}

d.SetId(strconv.Itoa(int(repo.GetID())))

if err := d.Set("build_type", pages.GetBuildType()); err != nil {
return diag.FromErr(err)
}
if err := d.Set("cname", pages.GetCNAME()); err != nil {
return diag.FromErr(err)
}
if err := d.Set("custom_404", pages.GetCustom404()); err != nil {
return diag.FromErr(err)
}
if err := d.Set("html_url", pages.GetHTMLURL()); err != nil {
return diag.FromErr(err)
}
if err := d.Set("build_status", pages.GetStatus()); err != nil {
return diag.FromErr(err)
}
if err := d.Set("api_url", pages.GetURL()); err != nil {
return diag.FromErr(err)
}
if err := d.Set("public", pages.GetPublic()); err != nil {
return diag.FromErr(err)
}
if err := d.Set("https_enforced", pages.GetHTTPSEnforced()); err != nil {
return diag.FromErr(err)
}
// Set source only for legacy build type
if pages.GetBuildType() == "legacy" && pages.GetSource() != nil {
source := []map[string]any{
{
"branch": pages.GetSource().GetBranch(),
"path": pages.GetSource().GetPath(),
},
}
if err := d.Set("source", source); err != nil {
return diag.FromErr(err)
}
} else {
if err := d.Set("source", []map[string]any{}); err != nil {
return diag.FromErr(err)
}
}

return nil
}
117 changes: 117 additions & 0 deletions github/data_source_github_repository_pages_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
package github

import (
"fmt"
"testing"

"github.com/hashicorp/terraform-plugin-testing/compare"
"github.com/hashicorp/terraform-plugin-testing/helper/acctest"
"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 TestAccGithubRepositoryPagesDataSource(t *testing.T) {
t.Run("reads_pages_configuration", func(t *testing.T) {
randomID := acctest.RandString(5)
repoName := fmt.Sprintf("%spages-ds-%s", testResourcePrefix, randomID)

config := fmt.Sprintf(`
resource "github_repository" "test" {
name = "%s"
visibility = "%s"
auto_init = true
}

resource "github_repository_pages" "test" {
repository = github_repository.test.name
build_type = "legacy"
source {
branch = "main"
path = "/"
}
}

data "github_repository_pages" "test" {
repository = github_repository.test.name

depends_on = [github_repository_pages.test]
}
`, repoName, testAccConf.testRepositoryVisibility)

resource.Test(t, resource.TestCase{
PreCheck: func() {
skipUnauthenticated(t)
},
ProviderFactories: providerFactories,
Steps: []resource.TestStep{
{
Config: config,
ConfigStateChecks: []statecheck.StateCheck{
statecheck.CompareValuePairs("data.github_repository_pages.test", tfjsonpath.New("build_type"), "github_repository_pages.test", tfjsonpath.New("build_type"), compare.ValuesSame()),
statecheck.CompareValuePairs("data.github_repository_pages.test", tfjsonpath.New("source").AtSliceIndex(0).AtMapKey("branch"), "github_repository_pages.test", tfjsonpath.New("source").AtSliceIndex(0).AtMapKey("branch"), compare.ValuesSame()),
statecheck.CompareValuePairs("data.github_repository_pages.test", tfjsonpath.New("source").AtSliceIndex(0).AtMapKey("path"), "github_repository_pages.test", tfjsonpath.New("source").AtSliceIndex(0).AtMapKey("path"), compare.ValuesSame()),
statecheck.CompareValuePairs("data.github_repository_pages.test", tfjsonpath.New("cname"), "github_repository_pages.test", tfjsonpath.New("cname"), compare.ValuesSame()),
statecheck.CompareValuePairs("data.github_repository_pages.test", tfjsonpath.New("custom_404"), "github_repository_pages.test", tfjsonpath.New("custom_404"), compare.ValuesSame()),
statecheck.CompareValuePairs("data.github_repository_pages.test", tfjsonpath.New("html_url"), "github_repository_pages.test", tfjsonpath.New("html_url"), compare.ValuesSame()),
statecheck.ExpectKnownValue("data.github_repository_pages.test", tfjsonpath.New("build_status"), knownvalue.NotNull()),
statecheck.CompareValuePairs("data.github_repository_pages.test", tfjsonpath.New("api_url"), "github_repository_pages.test", tfjsonpath.New("api_url"), compare.ValuesSame()),
statecheck.ExpectKnownValue("data.github_repository_pages.test", tfjsonpath.New("public"), knownvalue.Bool(testAccConf.authMode != enterprise)),
statecheck.CompareValuePairs("data.github_repository_pages.test", tfjsonpath.New("https_enforced"), "github_repository_pages.test", tfjsonpath.New("https_enforced"), compare.ValuesSame()),
},
},
},
})
})
t.Run("reads_pages_enterprise_configuration", func(t *testing.T) {
randomID := acctest.RandString(5)
repoName := fmt.Sprintf("%spages-ds-%s", testResourcePrefix, randomID)

config := fmt.Sprintf(`
resource "github_repository" "test" {
name = "%s"
visibility = "%s"
auto_init = true
}

resource "github_repository_pages" "test" {
repository = github_repository.test.name
build_type = "legacy"
source {
branch = "main"
path = "/"
}
public = false
}

data "github_repository_pages" "test" {
repository = github_repository.test.name

depends_on = [github_repository_pages.test]
}
`, repoName, testAccConf.testRepositoryVisibility)

resource.Test(t, resource.TestCase{
PreCheck: func() { skipUnlessEnterprise(t) },
ProviderFactories: providerFactories,
Steps: []resource.TestStep{
{
Config: config,
ConfigStateChecks: []statecheck.StateCheck{
statecheck.CompareValuePairs("data.github_repository_pages.test", tfjsonpath.New("build_type"), "github_repository_pages.test", tfjsonpath.New("build_type"), compare.ValuesSame()),
statecheck.CompareValuePairs("data.github_repository_pages.test", tfjsonpath.New("source").AtSliceIndex(0).AtMapKey("branch"), "github_repository_pages.test", tfjsonpath.New("source").AtSliceIndex(0).AtMapKey("branch"), compare.ValuesSame()),
statecheck.CompareValuePairs("data.github_repository_pages.test", tfjsonpath.New("source").AtSliceIndex(0).AtMapKey("path"), "github_repository_pages.test", tfjsonpath.New("source").AtSliceIndex(0).AtMapKey("path"), compare.ValuesSame()),
statecheck.CompareValuePairs("data.github_repository_pages.test", tfjsonpath.New("cname"), "github_repository_pages.test", tfjsonpath.New("cname"), compare.ValuesSame()),
statecheck.CompareValuePairs("data.github_repository_pages.test", tfjsonpath.New("custom_404"), "github_repository_pages.test", tfjsonpath.New("custom_404"), compare.ValuesSame()),
statecheck.CompareValuePairs("data.github_repository_pages.test", tfjsonpath.New("html_url"), "github_repository_pages.test", tfjsonpath.New("html_url"), compare.ValuesSame()),
statecheck.ExpectKnownValue("data.github_repository_pages.test", tfjsonpath.New("build_status"), knownvalue.NotNull()),
statecheck.CompareValuePairs("data.github_repository_pages.test", tfjsonpath.New("api_url"), "github_repository_pages.test", tfjsonpath.New("api_url"), compare.ValuesSame()),
statecheck.CompareValuePairs("data.github_repository_pages.test", tfjsonpath.New("public"), "github_repository_pages.test", tfjsonpath.New("public"), compare.ValuesSame()),
statecheck.CompareValuePairs("data.github_repository_pages.test", tfjsonpath.New("https_enforced"), "github_repository_pages.test", tfjsonpath.New("https_enforced"), compare.ValuesSame()),
},
},
},
})
})
}
2 changes: 2 additions & 0 deletions github/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@ func Provider() *schema.Provider {
"github_repository_environment_deployment_policy": resourceGithubRepositoryEnvironmentDeploymentPolicy(),
"github_repository_file": resourceGithubRepositoryFile(),
"github_repository_milestone": resourceGithubRepositoryMilestone(),
"github_repository_pages": resourceGithubRepositoryPages(),
"github_repository_project": resourceGithubRepositoryProject(),
"github_repository_pull_request": resourceGithubRepositoryPullRequest(),
"github_repository_ruleset": resourceGithubRepositoryRuleset(),
Expand Down Expand Up @@ -284,6 +285,7 @@ func Provider() *schema.Provider {
"github_repository_deployment_branch_policies": dataSourceGithubRepositoryDeploymentBranchPolicies(),
"github_repository_file": dataSourceGithubRepositoryFile(),
"github_repository_milestone": dataSourceGithubRepositoryMilestone(),
"github_repository_pages": dataSourceGithubRepositoryPages(),
"github_repository_pull_request": dataSourceGithubRepositoryPullRequest(),
"github_repository_pull_requests": dataSourceGithubRepositoryPullRequests(),
"github_repository_teams": dataSourceGithubRepositoryTeams(),
Expand Down
4 changes: 3 additions & 1 deletion github/resource_github_repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,7 @@ func resourceGithubRepository() *schema.Resource {
MaxItems: 1,
Optional: true,
Description: "The repository's GitHub Pages configuration",
Deprecated: "Use the github_repository_pages resource instead. This field will be removed in a future version.",
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"source": {
Expand Down Expand Up @@ -860,7 +861,8 @@ func resourceGithubRepositoryRead(ctx context.Context, d *schema.ResourceData, m
_ = d.Set("squash_merge_commit_title", repo.GetSquashMergeCommitTitle())
}

if repo.GetHasPages() {
_, isPagesConfigured := d.GetOk("pages")
if repo.GetHasPages() && isPagesConfigured {
pages, _, err := client.Repositories.GetPagesInfo(ctx, owner, repoName)
if err != nil {
return diag.FromErr(err)
Expand Down
Loading