Skip to content

Commit 7768a52

Browse files
committed
Add resource for repository pages and deprecate it from repository R
Signed-off-by: Timo Sand <timo.sand@f-secure.com>
1 parent 256cdd8 commit 7768a52

6 files changed

Lines changed: 672 additions & 19 deletions

github/provider.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,7 @@ func Provider() *schema.Provider {
198198
"github_repository_environment_deployment_policy": resourceGithubRepositoryEnvironmentDeploymentPolicy(),
199199
"github_repository_file": resourceGithubRepositoryFile(),
200200
"github_repository_milestone": resourceGithubRepositoryMilestone(),
201+
"github_repository_pages": resourceGithubRepositoryPages(),
201202
"github_repository_project": resourceGithubRepositoryProject(),
202203
"github_repository_pull_request": resourceGithubRepositoryPullRequest(),
203204
"github_repository_ruleset": resourceGithubRepositoryRuleset(),

github/resource_github_repository.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,7 @@ func resourceGithubRepository() *schema.Resource {
328328
MaxItems: 1,
329329
Optional: true,
330330
Description: "The repository's GitHub Pages configuration",
331+
Deprecated: "Use the github_repository_pages resource instead. This field will be removed in a future version.",
331332
Elem: &schema.Resource{
332333
Schema: map[string]*schema.Schema{
333334
"source": {
Lines changed: 337 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,337 @@
1+
package github
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"net/http"
7+
8+
"github.com/google/go-github/v82/github"
9+
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
10+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
11+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
12+
)
13+
14+
func resourceGithubRepositoryPages() *schema.Resource {
15+
return &schema.Resource{
16+
Description: "Manages GitHub Pages for a repository.",
17+
CreateContext: resourceGithubRepositoryPagesCreate,
18+
ReadContext: resourceGithubRepositoryPagesRead,
19+
UpdateContext: resourceGithubRepositoryPagesUpdate,
20+
DeleteContext: resourceGithubRepositoryPagesDelete,
21+
Importer: &schema.ResourceImporter{
22+
StateContext: resourceGithubRepositoryPagesImport,
23+
},
24+
25+
Schema: map[string]*schema.Schema{
26+
"repository_name": {
27+
Type: schema.TypeString,
28+
Required: true,
29+
ForceNew: true,
30+
Description: "The repository name to configure GitHub Pages for.",
31+
},
32+
"owner": {
33+
Type: schema.TypeString,
34+
Required: true,
35+
ForceNew: true,
36+
Description: "The owner of the repository to configure GitHub Pages for.",
37+
},
38+
"source": {
39+
Type: schema.TypeList,
40+
MaxItems: 1,
41+
Optional: true,
42+
Description: "The source branch and directory for the rendered Pages site.",
43+
Elem: &schema.Resource{
44+
Schema: map[string]*schema.Schema{
45+
"branch": {
46+
Type: schema.TypeString,
47+
Required: true,
48+
Description: "The repository branch used to publish the site's source files. (i.e. 'main' or 'gh-pages')",
49+
},
50+
"path": {
51+
Type: schema.TypeString,
52+
Optional: true,
53+
Default: "/",
54+
Description: "The repository directory from which the site publishes (Default: '/')",
55+
},
56+
},
57+
},
58+
},
59+
"build_type": {
60+
Type: schema.TypeString,
61+
Optional: true,
62+
Default: "legacy",
63+
Description: "The type of GitHub Pages site to build. Can be 'legacy' or 'workflow'.",
64+
ValidateDiagFunc: validation.ToDiagFunc(validation.StringInSlice([]string{"legacy", "workflow"}, false)),
65+
},
66+
"cname": {
67+
Type: schema.TypeString,
68+
Optional: true,
69+
Description: "The custom domain for the repository.",
70+
},
71+
"custom_404": {
72+
Type: schema.TypeBool,
73+
Computed: true,
74+
Description: "Whether the rendered GitHub Pages site has a custom 404 page.",
75+
},
76+
"html_url": {
77+
Type: schema.TypeString,
78+
Computed: true,
79+
Description: "The absolute URL (with scheme) to the rendered GitHub Pages site.",
80+
},
81+
"build_status": {
82+
Type: schema.TypeString,
83+
Computed: true,
84+
Description: "The GitHub Pages site's build status e.g. 'building' or 'built'.",
85+
},
86+
"api_url": {
87+
Type: schema.TypeString,
88+
Computed: true,
89+
Description: "The API URL of the GitHub Pages resource.",
90+
},
91+
},
92+
CustomizeDiff: resourceGithubRepositoryPagesDiff,
93+
}
94+
}
95+
96+
func resourceGithubRepositoryPagesCreate(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics {
97+
meta := m.(*Owner)
98+
client := meta.v3client
99+
100+
owner := d.Get("owner").(string)
101+
repoName := d.Get("repository_name").(string)
102+
103+
pages := expandPagesForCreate(d)
104+
pages, _, err := client.Repositories.EnablePages(ctx, owner, repoName, pages)
105+
if err != nil {
106+
return diag.FromErr(err)
107+
}
108+
109+
id, err := buildID(owner, repoName)
110+
if err != nil {
111+
return diag.FromErr(err)
112+
}
113+
d.SetId(id)
114+
115+
if err := d.Set("build_type", pages.GetBuildType()); err != nil {
116+
return diag.FromErr(err)
117+
}
118+
if err := d.Set("cname", pages.GetCNAME()); err != nil {
119+
return diag.FromErr(err)
120+
}
121+
if err := d.Set("custom_404", pages.GetCustom404()); err != nil {
122+
return diag.FromErr(err)
123+
}
124+
if err := d.Set("html_url", pages.GetHTMLURL()); err != nil {
125+
return diag.FromErr(err)
126+
}
127+
if err := d.Set("build_status", pages.GetStatus()); err != nil {
128+
return diag.FromErr(err)
129+
}
130+
if err := d.Set("api_url", pages.GetURL()); err != nil {
131+
return diag.FromErr(err)
132+
}
133+
134+
// Handle CNAME update after creation if specified
135+
if cname, ok := d.GetOk("cname"); ok && cname.(string) != "" {
136+
update := &github.PagesUpdate{
137+
CNAME: github.Ptr(cname.(string)),
138+
}
139+
_, err = client.Repositories.UpdatePages(ctx, owner, repoName, update)
140+
if err != nil {
141+
return diag.FromErr(err)
142+
}
143+
}
144+
145+
return nil
146+
}
147+
148+
func resourceGithubRepositoryPagesRead(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics {
149+
meta := m.(*Owner)
150+
client := meta.v3client
151+
152+
owner := d.Get("owner").(string)
153+
repoName := d.Get("repository_name").(string)
154+
155+
pages, resp, err := client.Repositories.GetPagesInfo(ctx, owner, repoName)
156+
if err != nil {
157+
if resp != nil && resp.StatusCode == http.StatusNotFound {
158+
d.SetId("")
159+
return nil
160+
}
161+
return diag.Errorf("error reading repository pages: %s", err.Error())
162+
}
163+
164+
if err := d.Set("build_type", pages.GetBuildType()); err != nil {
165+
return diag.FromErr(err)
166+
}
167+
if err := d.Set("cname", pages.GetCNAME()); err != nil {
168+
return diag.FromErr(err)
169+
}
170+
if err := d.Set("custom_404", pages.GetCustom404()); err != nil {
171+
return diag.FromErr(err)
172+
}
173+
if err := d.Set("html_url", pages.GetHTMLURL()); err != nil {
174+
return diag.FromErr(err)
175+
}
176+
if err := d.Set("build_status", pages.GetStatus()); err != nil {
177+
return diag.FromErr(err)
178+
}
179+
if err := d.Set("api_url", pages.GetURL()); err != nil {
180+
return diag.FromErr(err)
181+
}
182+
183+
// Set source only for legacy build type
184+
if pages.GetBuildType() == "legacy" && pages.GetSource() != nil {
185+
source := []map[string]any{
186+
{
187+
"branch": pages.GetSource().GetBranch(),
188+
"path": pages.GetSource().GetPath(),
189+
},
190+
}
191+
if err := d.Set("source", source); err != nil {
192+
return diag.FromErr(err)
193+
}
194+
} else {
195+
if err := d.Set("source", nil); err != nil {
196+
return diag.FromErr(err)
197+
}
198+
}
199+
200+
return nil
201+
}
202+
203+
func resourceGithubRepositoryPagesUpdate(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics {
204+
meta := m.(*Owner)
205+
client := meta.v3client
206+
207+
owner := d.Get("owner").(string)
208+
repoName := d.Get("repository_name").(string)
209+
210+
update := &github.PagesUpdate{}
211+
212+
if d.HasChange("cname") {
213+
cname := d.Get("cname").(string)
214+
if cname != "" {
215+
update.CNAME = github.Ptr(cname)
216+
}
217+
}
218+
219+
if d.HasChange("build_type") {
220+
buildType := d.Get("build_type").(string)
221+
update.BuildType = github.Ptr(buildType)
222+
}
223+
224+
if d.HasChange("source") || d.HasChange("build_type") {
225+
buildType := d.Get("build_type").(string)
226+
if buildType == "legacy" {
227+
if source, ok := d.GetOk("source"); ok {
228+
sourceList := source.([]any)
229+
if len(sourceList) > 0 {
230+
sourceMap := sourceList[0].(map[string]any)
231+
branch := sourceMap["branch"].(string)
232+
path := sourceMap["path"].(string)
233+
update.Source = &github.PagesSource{
234+
Branch: &branch,
235+
Path: &path,
236+
}
237+
}
238+
}
239+
}
240+
}
241+
242+
_, err := client.Repositories.UpdatePages(ctx, owner, repoName, update)
243+
if err != nil {
244+
return diag.FromErr(err)
245+
}
246+
247+
return nil
248+
}
249+
250+
func resourceGithubRepositoryPagesDelete(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics {
251+
meta := m.(*Owner)
252+
client := meta.v3client
253+
254+
owner := d.Get("owner").(string)
255+
repoName := d.Get("repository_name").(string)
256+
257+
_, err := client.Repositories.DisablePages(ctx, owner, repoName)
258+
if err != nil {
259+
return diag.FromErr(handleArchivedRepoDelete(err, "repository pages", d.Id(), owner, repoName))
260+
}
261+
262+
return nil
263+
}
264+
265+
func resourceGithubRepositoryPagesImport(ctx context.Context, d *schema.ResourceData, meta any) ([]*schema.ResourceData, error) {
266+
owner, repoName, err := parseID2(d.Id())
267+
if err != nil {
268+
return nil, fmt.Errorf("invalid ID specified: supplied ID must be written as <owner>/<repository>. Original error: %w", err)
269+
}
270+
if err := d.Set("owner", owner); err != nil {
271+
return nil, err
272+
}
273+
if err := d.Set("repository_name", repoName); err != nil {
274+
return nil, err
275+
}
276+
277+
id, err := buildID(owner, repoName)
278+
if err != nil {
279+
return nil, err
280+
}
281+
d.SetId(id)
282+
283+
return []*schema.ResourceData{d}, nil
284+
}
285+
286+
func resourceGithubRepositoryPagesDiff(ctx context.Context, d *schema.ResourceDiff, _ any) error {
287+
if d.Id() == "" {
288+
return nil
289+
}
290+
291+
buildType := d.Get("build_type").(string)
292+
switch buildType {
293+
case "workflow":
294+
if _, ok := d.GetOk("source"); ok {
295+
return fmt.Errorf("'source' is not supported for workflow build type")
296+
}
297+
return nil
298+
case "legacy":
299+
if _, ok := d.GetOk("source"); !ok {
300+
return fmt.Errorf("'source' is required for legacy build type")
301+
}
302+
}
303+
304+
return nil
305+
}
306+
307+
func expandPagesForCreate(d *schema.ResourceData) *github.Pages {
308+
pages := &github.Pages{}
309+
310+
buildType := d.Get("build_type").(string)
311+
pages.BuildType = github.Ptr(buildType)
312+
313+
if buildType == "legacy" {
314+
if source, ok := d.GetOk("source"); ok {
315+
sourceList := source.([]any)
316+
if len(sourceList) > 0 {
317+
sourceMap := sourceList[0].(map[string]any)
318+
branch := sourceMap["branch"].(string)
319+
pagesSource := &github.PagesSource{
320+
Branch: github.Ptr(branch),
321+
}
322+
if path, ok := sourceMap["path"].(string); ok && path != "" && path != "/" {
323+
pagesSource.Path = github.Ptr(path)
324+
}
325+
pages.Source = pagesSource
326+
}
327+
}
328+
// Default to main branch if no source specified
329+
if pages.Source == nil {
330+
pages.Source = &github.PagesSource{
331+
Branch: github.Ptr("main"),
332+
}
333+
}
334+
}
335+
336+
return pages
337+
}

0 commit comments

Comments
 (0)