@Summary Get workspace builds by workspace ID @ID get-workspace-builds-by-workspace-id @Security CoderSessionToken @Produce json @Tags Builds @Param workspace path string true "Workspace ID" format(uuid) @Param after_id query string false "After ID" format(uuid) @Param limit query int false "Page li
(rw http.ResponseWriter, r *http.Request)
| 115 | // @Success 200 {array} codersdk.WorkspaceBuild |
| 116 | // @Router /api/v2/workspaces/{workspace}/builds [get] |
| 117 | func (api *API) workspaceBuilds(rw http.ResponseWriter, r *http.Request) { |
| 118 | ctx := r.Context() |
| 119 | workspace := httpmw.WorkspaceParam(r) |
| 120 | |
| 121 | paginationParams, ok := ParsePagination(rw, r) |
| 122 | if !ok { |
| 123 | return |
| 124 | } |
| 125 | |
| 126 | var since time.Time |
| 127 | |
| 128 | sinceParam := r.URL.Query().Get("since") |
| 129 | if sinceParam != "" { |
| 130 | var err error |
| 131 | since, err = time.Parse(time.RFC3339, sinceParam) |
| 132 | if err != nil { |
| 133 | httpapi.Write(r.Context(), rw, http.StatusBadRequest, codersdk.Response{ |
| 134 | Message: "bad `since` format, must be RFC3339", |
| 135 | Detail: err.Error(), |
| 136 | }) |
| 137 | return |
| 138 | } |
| 139 | } |
| 140 | |
| 141 | var workspaceBuilds []database.WorkspaceBuild |
| 142 | // Ensure all db calls happen in the same tx |
| 143 | err := api.Database.InTx(func(store database.Store) error { |
| 144 | var err error |
| 145 | if paginationParams.AfterID != uuid.Nil { |
| 146 | // See if the record exists first. If the record does not exist, the pagination |
| 147 | // query will not work. |
| 148 | _, err := store.GetWorkspaceBuildByID(ctx, paginationParams.AfterID) |
| 149 | if err != nil && xerrors.Is(err, sql.ErrNoRows) { |
| 150 | httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{ |
| 151 | Message: fmt.Sprintf("Record at \"after_id\" (%q) does not exist.", paginationParams.AfterID.String()), |
| 152 | }) |
| 153 | return err |
| 154 | } else if err != nil { |
| 155 | httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{ |
| 156 | Message: "Internal error fetching workspace build at \"after_id\".", |
| 157 | Detail: err.Error(), |
| 158 | }) |
| 159 | return err |
| 160 | } |
| 161 | } |
| 162 | |
| 163 | req := database.GetWorkspaceBuildsByWorkspaceIDParams{ |
| 164 | WorkspaceID: workspace.ID, |
| 165 | AfterID: paginationParams.AfterID, |
| 166 | // #nosec G115 - Pagination offsets are small and fit in int32 |
| 167 | OffsetOpt: int32(paginationParams.Offset), |
| 168 | // #nosec G115 - Pagination limits are small and fit in int32 |
| 169 | LimitOpt: int32(paginationParams.Limit), |
| 170 | Since: dbtime.Time(since), |
| 171 | } |
| 172 | workspaceBuilds, err = store.GetWorkspaceBuildsByWorkspaceID(ctx, req) |
| 173 | if xerrors.Is(err, sql.ErrNoRows) { |
| 174 | err = nil |
nothing calls this directly
no test coverage detected