Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for pages deployment auto pagination #1264

Merged
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
19 changes: 19 additions & 0 deletions .changelog/1264.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
```release-note:breaking-change
pages_deployment: add support for auto pagination
```

```release-note:enchancement
pages_deployment: add Force to DeletePagesDeploymentParams
```

```release-note:breaking-change
pages_deployment: change DeletePagesDeploymentParams to contain all parameters
```

```release-note:breaking-change
pages_project: rename PagesProject to GetPagesProject
```

```release-note:breaking-change
pages_project: change to use ResourceContainer for account ID
```
74 changes: 45 additions & 29 deletions pages_deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,22 +62,16 @@ type pagesDeploymentResponse struct {
Result PagesProjectDeployment `json:"result"`
}

type pagesDeploymentStageLogsResponse struct {
Response
Result PagesDeploymentStageLogs `json:"result"`
ResultInfo `json:"result_info"`
}

type pagesDeploymentLogsResponse struct {
Response
Result PagesDeploymentLogs `json:"result"`
ResultInfo `json:"result_info"`
}

type ListPagesDeploymentsParams struct {
ProjectName string
ProjectName string `url:"-"`

PaginationOptions
ResultInfo
}

type GetPagesDeploymentInfoParams struct {
Expand All @@ -101,12 +95,14 @@ type GetPagesDeploymentLogsParams struct {
}

type DeletePagesDeploymentParams struct {
ProjectName string
DeploymentID string
ProjectName string `url:"-"`
DeploymentID string `url:"-"`
Force bool `url:"force,omitempty"`
}

type CreatePagesDeploymentParams struct {
ProjectName string
ProjectName string `json:"-"`
Branch string `json:"branch,omitempty"`
}

type RetryPagesDeploymentParams struct {
Expand All @@ -122,33 +118,53 @@ type RollbackPagesDeploymentParams struct {
var (
ErrMissingProjectName = errors.New("required missing project name")
ErrMissingDeploymentID = errors.New("required missing deployment ID")
ErrMissingStageName = errors.New("required missing stage name")
)

// ListPagesDeployments returns all deployments for a Pages project.
//
// API reference: https://api.cloudflare.com/#pages-deployment-get-deployments
func (api *API) ListPagesDeployments(ctx context.Context, rc *ResourceContainer, params ListPagesDeploymentsParams) ([]PagesProjectDeployment, ResultInfo, error) {
func (api *API) ListPagesDeployments(ctx context.Context, rc *ResourceContainer, params ListPagesDeploymentsParams) ([]PagesProjectDeployment, *ResultInfo, error) {
if rc.Identifier == "" {
return []PagesProjectDeployment{}, ResultInfo{}, ErrMissingAccountID
return []PagesProjectDeployment{}, &ResultInfo{}, ErrMissingAccountID
}

if params.ProjectName == "" {
return []PagesProjectDeployment{}, ResultInfo{}, ErrMissingProjectName
return []PagesProjectDeployment{}, &ResultInfo{}, ErrMissingProjectName
}

uri := buildURI(fmt.Sprintf("/accounts/%s/pages/projects/%s/deployments", rc.Identifier, params.ProjectName), params.PaginationOptions)
autoPaginate := true
if params.PerPage >= 1 || params.Page >= 1 {
autoPaginate = false
}

res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil)
if err != nil {
return []PagesProjectDeployment{}, ResultInfo{}, err
if params.PerPage < 1 {
params.PerPage = 25
}
var r pagesDeploymentListResponse
err = json.Unmarshal(res, &r)
if err != nil {
return []PagesProjectDeployment{}, ResultInfo{}, fmt.Errorf("%s: %w", errUnmarshalError, err)

if params.Page < 1 {
params.Page = 1
}
return r.Result, r.ResultInfo, nil

var deployments []PagesProjectDeployment
var r pagesDeploymentListResponse

for {
uri := buildURI(fmt.Sprintf("/accounts/%s/pages/projects/%s/deployments", rc.Identifier, params.ProjectName), params)
res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil)
if err != nil {
return []PagesProjectDeployment{}, &ResultInfo{}, err
}
err = json.Unmarshal(res, &r)
if err != nil {
return []PagesProjectDeployment{}, &ResultInfo{}, fmt.Errorf("%s: %w", errUnmarshalError, err)
}
deployments = append(deployments, r.Result...)
params.ResultInfo = r.ResultInfo.Next()
if params.DoneCount() || !autoPaginate {
break
}
}
return deployments, &r.ResultInfo, nil
}

// GetPagesDeploymentInfo returns a deployment for a Pages project.
Expand Down Expand Up @@ -217,20 +233,20 @@ func (api *API) GetPagesDeploymentLogs(ctx context.Context, rc *ResourceContaine
// DeletePagesDeployment deletes a Pages deployment.
//
// API reference: https://api.cloudflare.com/#pages-deployment-delete-deployment
func (api *API) DeletePagesDeployment(ctx context.Context, rc *ResourceContainer, projectName, deploymentID string) error {
func (api *API) DeletePagesDeployment(ctx context.Context, rc *ResourceContainer, params DeletePagesDeploymentParams) error {
if rc.Identifier == "" {
return ErrMissingAccountID
}

if projectName == "" {
if params.ProjectName == "" {
return ErrMissingProjectName
}

if deploymentID == "" {
if params.DeploymentID == "" {
return ErrMissingDeploymentID
}

uri := fmt.Sprintf("/accounts/%s/pages/projects/%s/deployments/%s", rc.Identifier, projectName, deploymentID)
uri := buildURI(fmt.Sprintf("/accounts/%s/pages/projects/%s/deployments/%s", rc.Identifier, params.ProjectName, params.DeploymentID), params)

_, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil)
if err != nil {
Expand All @@ -253,7 +269,7 @@ func (api *API) CreatePagesDeployment(ctx context.Context, rc *ResourceContainer

uri := fmt.Sprintf("/accounts/%s/pages/projects/%s/deployments", rc.Identifier, params.ProjectName)

res, err := api.makeRequestContext(ctx, http.MethodPost, uri, nil)
res, err := api.makeRequestContext(ctx, http.MethodPost, uri, params)
if err != nil {
return PagesProjectDeployment{}, err
}
Expand Down
118 changes: 69 additions & 49 deletions pages_deployment_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
)

const (
testPagesDeplyomentResponse = `
testPagesDeploymentResponse = `
{
"id": "0012e50b-fa5d-44db-8cb5-1f372785dcbe",
"short_id": "0012e50b",
Expand Down Expand Up @@ -207,44 +207,6 @@ var (
Status: "success",
}

expectedPagesDeploymentStageLogEntries = []PagesDeploymentStageLogEntry{
{
ID: 0,
Timestamp: &pagesDeploymentDummyTime,
Message: "Installing dependencies",
},
{
ID: 1,
Timestamp: &pagesDeploymentDummyTime,
Message: "Verify run directory",
},
{
ID: 2,
Timestamp: &pagesDeploymentDummyTime,
Message: "Executing user command: bash test.sh",
},
{
ID: 3,
Timestamp: &pagesDeploymentDummyTime,
Message: "Finished",
},
{
ID: 4,
Timestamp: &pagesDeploymentDummyTime,
Message: "Building functions...",
},
{
ID: 5,
Timestamp: &pagesDeploymentDummyTime,
Message: "Validating asset output directory",
},
{
ID: 6,
Timestamp: &pagesDeploymentDummyTime,
Message: "Parsed 2 valid header rules.",
},
}

expectedPagesDeploymentLogs = &PagesDeploymentLogs{
Total: 6,
IncludesContainerLogs: true,
Expand Down Expand Up @@ -289,6 +251,8 @@ func TestListPagesDeployments(t *testing.T) {

handler := func(w http.ResponseWriter, r *http.Request) {
assert.Equal(t, http.MethodGet, r.Method, "Expected method 'GET', got %s", r.Method)
assert.Equal(t, "25", r.URL.Query().Get("per_page"))
assert.Equal(t, "1", r.URL.Query().Get("page"))

w.Header().Set("content-type", "application/json")
fmt.Fprintf(w, `{
Expand All @@ -304,7 +268,7 @@ func TestListPagesDeployments(t *testing.T) {
"count": 1,
"total_count": 1
}
}`, testPagesDeplyomentResponse)
}`, testPagesDeploymentResponse)
}

mux.HandleFunc("/accounts/"+testAccountID+"/pages/projects/test/deployments", handler)
Expand All @@ -319,12 +283,68 @@ func TestListPagesDeployments(t *testing.T) {
Total: 1,
}
actual, resultInfo, err := client.ListPagesDeployments(context.Background(), AccountIdentifier(testAccountID), ListPagesDeploymentsParams{
ProjectName: "test",
PaginationOptions: PaginationOptions{},
ProjectName: "test",
ResultInfo: ResultInfo{},
})
if assert.NoError(t, err) {
assert.Equal(t, expectedPagesDeployments, actual)
assert.Equal(t, expectedResultInfo, resultInfo)
assert.Equal(t, &expectedResultInfo, resultInfo)
}
}

func TestListPagesDeploymentsPagination(t *testing.T) {
setup()
defer teardown()
var page1Called, page2Called bool
handler := func(w http.ResponseWriter, r *http.Request) {
page := r.URL.Query().Get("page")
w.Header().Set("content-type", "application/json")
switch page {
case "1":
page1Called = true
fmt.Fprintf(w, `{
"success": true,
"errors": [],
"messages": [],
"result": [
%s
],
"result_info": {
"page": 1,
"per_page": 25,
"total_count": 26
}
}`, testPagesDeploymentResponse)
case "2":
page2Called = true
fmt.Fprintf(w, `{
"success": true,
"errors": [],
"messages": [],
"result": [
%s
],
"result_info": {
"page": 2,
"per_page": 25,
"total_count": 26
}
}`, testPagesDeploymentResponse)
default:
assert.Failf(t, "Unexpected page number", "Expected page 1 or 2, got %s", page)
return
}
}
mux.HandleFunc("/accounts/"+testAccountID+"/pages/projects/test/deployments", handler)
actual, resultInfo, err := client.ListPagesDeployments(context.Background(), AccountIdentifier(testAccountID), ListPagesDeploymentsParams{
ProjectName: "test",
ResultInfo: ResultInfo{},
})
if assert.NoError(t, err) {
assert.True(t, page1Called)
assert.True(t, page2Called)
assert.Equal(t, 2, len(actual))
assert.Equal(t, 26, resultInfo.Total)
}
}

Expand All @@ -341,7 +361,7 @@ func TestGetPagesDeploymentInfo(t *testing.T) {
"errors": [],
"messages": [],
"result": %s
}`, testPagesDeplyomentResponse)
}`, testPagesDeploymentResponse)
}

mux.HandleFunc("/accounts/"+testAccountID+"/pages/projects/test/deployments/0012e50b-fa5d-44db-8cb5-1f372785dcbe", handler)
Expand Down Expand Up @@ -386,7 +406,7 @@ func TestDeletePagesDeployment(t *testing.T) {

handler := func(w http.ResponseWriter, r *http.Request) {
assert.Equal(t, http.MethodDelete, r.Method, "Expected method 'DELETE', got %s", r.Method)

assert.Equal(t, "true", r.URL.Query().Get("force"))
w.Header().Set("content-type", "application/json")
fmt.Fprintf(w, `{
"success": true,
Expand All @@ -398,7 +418,7 @@ func TestDeletePagesDeployment(t *testing.T) {

mux.HandleFunc("/accounts/"+testAccountID+"/pages/projects/test/deployments/0012e50b-fa5d-44db-8cb5-1f372785dcbe", handler)

err := client.DeletePagesDeployment(context.Background(), AccountIdentifier(testAccountID), "test", "0012e50b-fa5d-44db-8cb5-1f372785dcbe")
err := client.DeletePagesDeployment(context.Background(), AccountIdentifier(testAccountID), DeletePagesDeploymentParams{ProjectName: "test", DeploymentID: "0012e50b-fa5d-44db-8cb5-1f372785dcbe", Force: true})
assert.NoError(t, err)
}

Expand All @@ -415,7 +435,7 @@ func TestCreatePagesDeployment(t *testing.T) {
"errors": [],
"messages": [],
"result": %s
}`, testPagesDeplyomentResponse)
}`, testPagesDeploymentResponse)
}

mux.HandleFunc("/accounts/"+testAccountID+"/pages/projects/test/deployments", handler)
Expand All @@ -442,7 +462,7 @@ func TestRetryPagesDeployment(t *testing.T) {
"errors": [],
"messages": [],
"result": %s
}`, testPagesDeplyomentResponse)
}`, testPagesDeploymentResponse)
}

mux.HandleFunc("/accounts/"+testAccountID+"/pages/projects/test/deployments/0012e50b-fa5d-44db-8cb5-1f372785dcbe/retry", handler)
Expand All @@ -466,7 +486,7 @@ func TestRollbackPagesDeployment(t *testing.T) {
"errors": [],
"messages": [],
"result": %s
}`, testPagesDeplyomentResponse)
}`, testPagesDeploymentResponse)
}

mux.HandleFunc("/accounts/"+testAccountID+"/pages/projects/test/deployments/0012e50b-fa5d-44db-8cb5-1f372785dcbe/rollback", handler)
Expand Down