Skip to content

Commit eefc26c

Browse files
authored
Hide build logs older than 30 days (#4436)
1 parent dd5173b commit eefc26c

File tree

12 files changed

+113
-66
lines changed

12 files changed

+113
-66
lines changed

coderd/database/databasefake/databasefake.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -821,14 +821,17 @@ func (q *fakeQuerier) GetLatestWorkspaceBuildsByWorkspaceIDs(_ context.Context,
821821
return returnBuilds, nil
822822
}
823823

824-
func (q *fakeQuerier) GetWorkspaceBuildByWorkspaceID(_ context.Context,
825-
params database.GetWorkspaceBuildByWorkspaceIDParams,
824+
func (q *fakeQuerier) GetWorkspaceBuildsByWorkspaceID(_ context.Context,
825+
params database.GetWorkspaceBuildsByWorkspaceIDParams,
826826
) ([]database.WorkspaceBuild, error) {
827827
q.mutex.RLock()
828828
defer q.mutex.RUnlock()
829829

830830
history := make([]database.WorkspaceBuild, 0)
831831
for _, workspaceBuild := range q.workspaceBuilds {
832+
if workspaceBuild.CreatedAt.Before(params.Since) {
833+
continue
834+
}
832835
if workspaceBuild.WorkspaceID.String() == params.WorkspaceID.String() {
833836
history = append(history, workspaceBuild)
834837
}

coderd/database/querier.go

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/queries.sql.go

Lines changed: 46 additions & 43 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/queries/workspacebuilds.sql

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,14 @@ WHERE
3030
workspace_id = $1
3131
AND build_number = $2;
3232

33-
-- name: GetWorkspaceBuildByWorkspaceID :many
33+
-- name: GetWorkspaceBuildsByWorkspaceID :many
3434
SELECT
3535
*
3636
FROM
3737
workspace_builds
3838
WHERE
3939
workspace_builds.workspace_id = $1
40+
AND workspace_builds.created_at > @since
4041
AND CASE
4142
-- This allows using the last element on a page as effectively a cursor.
4243
-- This is an important option for scripts that need to paginate without

coderd/workspaceapps_test.go

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -299,10 +299,9 @@ func TestWorkspaceApplicationAuth(t *testing.T) {
299299
require.Equal(t, u.String(), gotLocation.Query().Get("redirect_uri"))
300300

301301
// Load the application auth-redirect endpoint.
302-
qp := codersdk.WithQueryParams(map[string]string{
303-
"redirect_uri": u.String(),
304-
})
305-
resp, err = client.Request(ctx, http.MethodGet, "/api/v2/applications/auth-redirect", nil, qp)
302+
resp, err = client.Request(ctx, http.MethodGet, "/api/v2/applications/auth-redirect", nil, codersdk.WithQueryParam(
303+
"redirect_uri", u.String(),
304+
))
306305
require.NoError(t, err)
307306
defer resp.Body.Close()
308307

@@ -434,15 +433,13 @@ func TestWorkspaceApplicationAuth(t *testing.T) {
434433
c := c
435434
t.Run(c.name, func(t *testing.T) {
436435
t.Parallel()
437-
qp := map[string]string{}
438-
if c.redirectURI != "" {
439-
qp["redirect_uri"] = c.redirectURI
440-
}
441436

442437
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
443438
defer cancel()
444439

445-
resp, err := client.Request(ctx, http.MethodGet, "/api/v2/applications/auth-redirect", nil, codersdk.WithQueryParams(qp))
440+
resp, err := client.Request(ctx, http.MethodGet, "/api/v2/applications/auth-redirect", nil,
441+
codersdk.WithQueryParam("redirect_uri", c.redirectURI),
442+
)
446443
require.NoError(t, err)
447444
defer resp.Body.Close()
448445
require.Equal(t, http.StatusBadRequest, resp.StatusCode)

coderd/workspacebuilds.go

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"fmt"
99
"net/http"
1010
"strconv"
11+
"time"
1112

1213
"github.com/go-chi/chi/v5"
1314
"github.com/google/uuid"
@@ -75,6 +76,21 @@ func (api *API) workspaceBuilds(rw http.ResponseWriter, r *http.Request) {
7576
return
7677
}
7778

79+
var since time.Time
80+
81+
sinceParam := r.URL.Query().Get("since")
82+
if sinceParam != "" {
83+
var err error
84+
since, err = time.Parse(time.RFC3339, sinceParam)
85+
if err != nil {
86+
httpapi.Write(r.Context(), rw, http.StatusBadRequest, codersdk.Response{
87+
Message: "bad `since` format, must be RFC3339",
88+
Detail: err.Error(),
89+
})
90+
return
91+
}
92+
}
93+
7894
var workspaceBuilds []database.WorkspaceBuild
7995
// Ensure all db calls happen in the same tx
8096
err := api.Database.InTx(func(store database.Store) error {
@@ -97,13 +113,14 @@ func (api *API) workspaceBuilds(rw http.ResponseWriter, r *http.Request) {
97113
}
98114
}
99115

100-
req := database.GetWorkspaceBuildByWorkspaceIDParams{
116+
req := database.GetWorkspaceBuildsByWorkspaceIDParams{
101117
WorkspaceID: workspace.ID,
102118
AfterID: paginationParams.AfterID,
103119
OffsetOpt: int32(paginationParams.Offset),
104120
LimitOpt: int32(paginationParams.Limit),
121+
Since: database.Time(since),
105122
}
106-
workspaceBuilds, err = store.GetWorkspaceBuildByWorkspaceID(ctx, req)
123+
workspaceBuilds, err = store.GetWorkspaceBuildsByWorkspaceID(ctx, req)
107124
if xerrors.Is(err, sql.ErrNoRows) {
108125
err = nil
109126
}

coderd/workspacebuilds_test.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,19 @@ func TestWorkspaceBuilds(t *testing.T) {
163163
require.Equal(t, int32(1), builds[0].BuildNumber)
164164
require.Equal(t, user.Username, builds[0].InitiatorUsername)
165165
require.NoError(t, err)
166+
167+
// Test since
168+
builds, err = client.WorkspaceBuilds(ctx,
169+
codersdk.WorkspaceBuildsRequest{WorkspaceID: workspace.ID, Since: database.Now().Add(time.Minute)},
170+
)
171+
require.NoError(t, err)
172+
require.Len(t, builds, 0)
173+
174+
builds, err = client.WorkspaceBuilds(ctx,
175+
codersdk.WorkspaceBuildsRequest{WorkspaceID: workspace.ID, Since: database.Now().Add(-time.Hour)},
176+
)
177+
require.NoError(t, err)
178+
require.Len(t, builds, 1)
166179
})
167180

168181
t.Run("PaginateNonExistentRow", func(t *testing.T) {

codersdk/client.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,13 @@ type Client struct {
4444

4545
type RequestOption func(*http.Request)
4646

47-
func WithQueryParams(params map[string]string) RequestOption {
47+
func WithQueryParam(key, value string) RequestOption {
4848
return func(r *http.Request) {
49-
q := r.URL.Query()
50-
for k, v := range params {
51-
q.Add(k, v)
49+
if value == "" {
50+
return
5251
}
52+
q := r.URL.Query()
53+
q.Add(key, value)
5354
r.URL.RawQuery = q.Encode()
5455
}
5556
}

codersdk/workspaces.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,11 +90,15 @@ func (c *Client) getWorkspace(ctx context.Context, id uuid.UUID, opts ...Request
9090
type WorkspaceBuildsRequest struct {
9191
WorkspaceID uuid.UUID
9292
Pagination
93+
Since time.Time
9394
}
9495

9596
func (c *Client) WorkspaceBuilds(ctx context.Context, req WorkspaceBuildsRequest) ([]WorkspaceBuild, error) {
96-
res, err := c.Request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/workspaces/%s/builds", req.WorkspaceID),
97-
nil, req.Pagination.asRequestOption())
97+
res, err := c.Request(
98+
ctx, http.MethodGet,
99+
fmt.Sprintf("/api/v2/workspaces/%s/builds", req.WorkspaceID),
100+
nil, req.Pagination.asRequestOption(), WithQueryParam("since", req.Since.Format(time.RFC3339)),
101+
)
98102
if err != nil {
99103
return nil, err
100104
}

site/src/api/api.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -406,9 +406,10 @@ export const regenerateUserSSHKey = async (userId = "me"): Promise<TypesGen.GitS
406406

407407
export const getWorkspaceBuilds = async (
408408
workspaceId: string,
409+
since: Date,
409410
): Promise<TypesGen.WorkspaceBuild[]> => {
410411
const response = await axios.get<TypesGen.WorkspaceBuild[]>(
411-
`/api/v2/workspaces/${workspaceId}/builds`,
412+
`/api/v2/workspaces/${workspaceId}/builds?since=${since.toISOString()}`,
412413
)
413414
return response.data
414415
}

site/src/api/typesGenerated.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -645,6 +645,7 @@ export interface WorkspaceBuild {
645645
// From codersdk/workspaces.go
646646
export interface WorkspaceBuildsRequest extends Pagination {
647647
readonly WorkspaceID: string
648+
readonly Since: string
648649
}
649650

650651
// From codersdk/workspaces.go

site/src/xServices/workspace/workspaceXService.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { getErrorMessage } from "api/errors"
2+
import dayjs from "dayjs"
23
import { workspaceScheduleBannerMachine } from "xServices/workspaceSchedule/workspaceScheduleBannerXService"
34
import { assign, createMachine, send } from "xstate"
45
import * as API from "../../api/api"
@@ -670,7 +671,12 @@ export const workspaceMachine = createMachine(
670671
},
671672
getBuilds: async (context) => {
672673
if (context.workspace) {
673-
return await API.getWorkspaceBuilds(context.workspace.id)
674+
// For now, we only retrieve the last month of builds to minimize
675+
// page bloat. We should add pagination in the future.
676+
return await API.getWorkspaceBuilds(
677+
context.workspace.id,
678+
dayjs().add(-30, "day").toDate(),
679+
)
674680
} else {
675681
throw Error("Cannot get builds without id")
676682
}

0 commit comments

Comments
 (0)