Skip to content

Commit 4caa528

Browse files
authored
chore!: remove api.ts unnecessary calls (#22168)
> [!WARNING] > The change of the status code from `404` to `204` could break peoples code downstream. Adding this as a breaking change incase. Theres a whole ton of noise around failed requests, these are all unrelated to the actual thing that is broken at hand (and are confusing). * Change `/api/v2/organizations/.../templates/.../versions/.../previous` to return `204` instead of `404` (actually makes more sense because the content doesn't exist, but the route is found. * Remove unnecessary calls to `/api/v2/users/me/appearance` when the user isn't logged in. * Remove unnecessary calls to `/api/v2/deployment/stats` when the deployment stats aren't allowed to be seen. * Various changes to `workspace-sharing` so we don't make unnecessary calls. Whats left: * `/api/v2/users/me` still `401`s on the login page. This persists as when the user is logged in but tries to reach the sign-in page they should be redirected to the app, not sign in again. * `monaco-editor` is still upset... we theoretically could inject an environment that can serve workers... but eh. #### Old ```sh % pnpm playwright:test -g "create workspace with default and required parameters" > coder-v2@ playwright:test /home/coder/coder/site > playwright test --config=e2e/playwright.config.ts -g 'create workspace with default and required parameters' ... Running 2 tests using 1 worker ✓ 1 …e/setup/addUsersAndLicense.spec.ts:7:5 › setup deployment (8.2s) 2 ….ts:79:5 › create workspace with default and required parameters [console][error] Failed to load resource: the server responded with a status of 401 (Unauthorized) [console][error] Failed to load resource: the server responded with a status of 401 (Unauthorized) [response] url=http://localhost:3111/api/v2/users/me/appearance status=401 body={"message":"You are signed out or your session has expired. Please sign in again to continue.","detail":"Cookie \"coder_session_token\" or query parameter must be provided."} [response] url=http://localhost:3111/api/v2/users/me status=401 body={"message":"You are signed out or your session has expired. Please sign in again to continue.","detail":"Cookie \"coder_session_token\" or query parameter must be provided."} [console][error] Failed to load resource: the server responded with a status of 403 (Forbidden) [response] url=http://localhost:3111/api/v2/deployment/stats status=403 body={"message":"Forbidden.","detail":"You don't have permission to view this content. If you believe this is a mistake, please contact your administrator or try signing in with different credentials."} [console][error] Failed to load resource: the server responded with a status of 403 (Forbidden) [response] url=http://localhost:3111/api/v2/deployment/stats status=403 body={"message":"Forbidden.","detail":"You don't have permission to view this content. If you believe this is a mistake, please contact your administrator or try signing in with different credentials."} [console][error] Failed to load resource: the server responded with a status of 404 (Not Found) [response] url=http://localhost:3111/api/v2/organizations//provisionerdaemons status=404 body={"message":"Resource not found or you do not have access to this resource"} [console][error] Failed to load resource: the server responded with a status of 404 (Not Found) [response] url=http://localhost:3111/api/v2/organizations/default/templates/a4e8096d/versions/agreeable_glenn33/previous status=404 body={"message":"No previous template version found for \"agreeable_glenn33\"."} [console][warning] Could not create web worker(s). Falling back to loading web worker code in main thread, which might cause UI freezes. Please see https://github.com/microsoft/monaco-editor#faq [console][warning] You must define a function MonacoEnvironment.getWorkerUrl or MonacoEnvironment.getWorker [console][error] Failed to load resource: the server responded with a status of 401 (Unauthorized) [console][error] Failed to load resource: the server responded with a status of 401 (Unauthorized) [response] url=http://localhost:3111/api/v2/users/me/appearance status=401 body={"message":"You are signed out or your session has expired. Please sign in again to continue.","detail":"Cookie \"coder_session_token\" or query parameter must be provided."} [response] url=http://localhost:3111/api/v2/users/me status=401 body={"message":"You are signed out or your session has expired. Please sign in again to continue.","detail":"Cookie \"coder_session_token\" or query parameter must be provided."} [console][error] Failed to load resource: the server responded with a status of 403 (Forbidden) [response] url=http://localhost:3111/api/v2/deployment/stats status=403 body={"message":"Forbidden.","detail":"You don't have permission to view this content. If you believe this is a mistake, please contact your administrator or try signing in with different credentials."} ✓ 2 …5 › create workspace with default and required parameters (7.0s)atus of 403 (Forbidden) [response] url=http://localhost:3111/api/v2/deployment/stats status=403 body={"message":"Forbidden.","detail":"You don't have permission to view this content. If you believe this is a mistake, please contact your administrator or try signing in with different credentials."} [console][error] Failed to load resource: the server responded with a status of 403 (Forbidden) [response] url=http://localhost:3111/api/v2/deployment/stats status=403 body={"message":"Forbidden.","detail":"You don't have permission to view this content. If you believe this is a mistake, please contact your administrator or try signing in with different credentials."} 2 passed (56.1s) ``` `23 LOL` (Lines of logs) #### New ```sh % pnpm playwright:test -g "create workspace with default and required parameters" > coder-v2@ playwright:test /home/coder/coder/site > playwright test --config=e2e/playwright.config.ts -g 'create workspace with default and required parameters' ... Running 2 tests using 1 worker ✓ 1 …e/setup/addUsersAndLicense.spec.ts:7:5 › setup deployment (8.7s) 2 ….ts:79:5 › create workspace with default and required parameters [console][error] Failed to load resource: the server responded with a status of 401 (Unauthorized) [console][error] Failed to load resource: the server responded with a status of 401 (Unauthorized) [response] url=http://localhost:3111/api/v2/users/me/appearance status=401 body={"message":"You are signed out or your session has expired. Please sign in again to continue.","detail":"Cookie \"coder_session_token\" or query parameter must be provided."} [response] url=http://localhost:3111/api/v2/users/me status=401 body={"message":"You are signed out or your session has expired. Please sign in again to continue.","detail":"Cookie \"coder_session_token\" or query parameter must be provided."} [console][warning] Could not create web worker(s). Falling back to loading web worker code in main thread, which might cause UI freezes. Please see https://github.com/microsoft/monaco-editor#faq [console][warning] You must define a function MonacoEnvironment.getWorkerUrl or MonacoEnvironment.getWorker ✓ 2 …5 › create workspace with default and required parameters (7.1s)atus of 401 (Unauthorized) [console][error] Failed to load resource: the server responded with a status of 401 (Unauthorized) [response] url=http://localhost:3111/api/v2/users/me/appearance status=401 body={"message":"You are signed out or your session has expired. Please sign in again to continue.","detail":"Cookie \"coder_session_token\" or query parameter must be provided."} [response] url=http://localhost:3111/api/v2/users/me status=401 body={"message":"You are signed out or your session has expired. Please sign in again to continue.","detail":"Cookie \"coder_session_token\" or query parameter must be provided."} 2 passed (32.0s) ``` `9 LOL` (Lines of logs)
1 parent 7d044fa commit 4caa528

12 files changed

Lines changed: 40 additions & 33 deletions

File tree

coderd/apidoc/docs.go

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

coderd/apidoc/swagger.json

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

coderd/templateversions.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1074,6 +1074,7 @@ func (api *API) templateVersionByOrganizationTemplateAndName(rw http.ResponseWri
10741074
// @Param templatename path string true "Template name"
10751075
// @Param templateversionname path string true "Template version name"
10761076
// @Success 200 {object} codersdk.TemplateVersion
1077+
// @Success 204
10771078
// @Router /organizations/{organization}/templates/{templatename}/versions/{templateversionname}/previous [get]
10781079
func (api *API) previousTemplateVersionByOrganizationTemplateAndName(rw http.ResponseWriter, r *http.Request) {
10791080
ctx := r.Context()
@@ -1126,9 +1127,7 @@ func (api *API) previousTemplateVersionByOrganizationTemplateAndName(rw http.Res
11261127
})
11271128
if err != nil {
11281129
if httpapi.Is404Error(err) {
1129-
httpapi.Write(ctx, rw, http.StatusNotFound, codersdk.Response{
1130-
Message: fmt.Sprintf("No previous template version found for %q.", templateVersionName),
1131-
})
1130+
rw.WriteHeader(http.StatusNoContent)
11321131
return
11331132
}
11341133

coderd/templateversions_test.go

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1980,8 +1980,8 @@ func TestPreviousTemplateVersion(t *testing.T) {
19801980
templateAVersion1 := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
19811981
coderdtest.CreateTemplate(t, client, user.OrganizationID, templateAVersion1.ID)
19821982
coderdtest.AwaitTemplateVersionJobCompleted(t, client, templateAVersion1.ID)
1983-
// Create two versions for the template B to be sure if we try to get the
1984-
// previous version of the first version it will returns a 404
1983+
// Create two versions for template B so we can verify that requesting
1984+
// the previous version of the first version returns nil.
19851985
templateBVersion1 := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
19861986
templateB := coderdtest.CreateTemplate(t, client, user.OrganizationID, templateBVersion1.ID)
19871987
coderdtest.AwaitTemplateVersionJobCompleted(t, client, templateBVersion1.ID)
@@ -1992,9 +1992,7 @@ func TestPreviousTemplateVersion(t *testing.T) {
19921992
defer cancel()
19931993

19941994
_, err := client.PreviousTemplateVersion(ctx, user.OrganizationID, templateB.Name, templateBVersion1.Name)
1995-
var apiErr *codersdk.Error
1996-
require.ErrorAs(t, err, &apiErr)
1997-
require.Equal(t, http.StatusNotFound, apiErr.StatusCode())
1995+
require.ErrorIs(t, err, codersdk.ErrNoPreviousVersion)
19981996
})
19991997

20001998
t.Run("Previous version found", func(t *testing.T) {

codersdk/templateversions.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"time"
1010

1111
"github.com/google/uuid"
12+
"golang.org/x/xerrors"
1213
)
1314

1415
type TemplateVersionWarning string
@@ -280,12 +281,19 @@ func (c *Client) CancelTemplateVersionDryRun(ctx context.Context, version, job u
280281
return nil
281282
}
282283

284+
// ErrNoPreviousVersion is returned when no previous template version
285+
// exists (the server responds with 204 No Content).
286+
var ErrNoPreviousVersion = xerrors.New("no previous template version")
287+
283288
func (c *Client) PreviousTemplateVersion(ctx context.Context, organization uuid.UUID, templateName, versionName string) (TemplateVersion, error) {
284289
res, err := c.Request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/organizations/%s/templates/%s/versions/%s/previous", organization, templateName, versionName), nil)
285290
if err != nil {
286291
return TemplateVersion{}, err
287292
}
288293
defer res.Body.Close()
294+
if res.StatusCode == http.StatusNoContent {
295+
return TemplateVersion{}, ErrNoPreviousVersion
296+
}
289297
if res.StatusCode != http.StatusOK {
290298
return TemplateVersion{}, ReadBodyAsError(res)
291299
}

docs/reference/api/templates.md

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

site/src/api/api.ts

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1097,25 +1097,17 @@ class ApiMethods {
10971097
templateName: string,
10981098
versionName: string,
10991099
) => {
1100-
try {
1101-
const response = await this.axios.get<TypesGen.TemplateVersion>(
1102-
`/api/v2/organizations/${organization}/templates/${templateName}/versions/${versionName}/previous`,
1103-
);
1104-
1105-
return response.data;
1106-
} catch (error) {
1107-
// When there is no previous version, like the first version of a
1108-
// template, the API returns 404 so in this case we can safely return
1109-
// undefined
1110-
const is404 =
1111-
isAxiosError(error) && error.response && error.response.status === 404;
1112-
1113-
if (is404) {
1114-
return undefined;
1115-
}
1100+
const response = await this.axios.get<TypesGen.TemplateVersion>(
1101+
`/api/v2/organizations/${organization}/templates/${templateName}/versions/${versionName}/previous`,
1102+
);
11161103

1117-
throw error;
1104+
// The API returns 204 No Content when there is no previous version
1105+
// (e.g. the first version of a template).
1106+
if (response.status === 204) {
1107+
return undefined;
11181108
}
1109+
1110+
return response.data;
11191111
};
11201112

11211113
/**

site/src/modules/dashboard/DeploymentBanner/DeploymentBanner.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,10 @@ const HIDE_DEPLOYMENT_BANNER_PATHS = [
1818

1919
export const DeploymentBanner: FC = () => {
2020
const { permissions } = useAuthenticated();
21-
const deploymentStatsQuery = useQuery(deploymentStats());
21+
const deploymentStatsQuery = useQuery({
22+
...deploymentStats(),
23+
enabled: permissions.viewDeploymentStats,
24+
});
2225
const healthQuery = useQuery({
2326
...health(),
2427
enabled: permissions.viewDeploymentConfig,

site/src/pages/CreateTemplatePage/CreateTemplateForm.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ export const CreateTemplateForm: FC<CreateTemplateFormProps> = (props) => {
259259

260260
const { data: provisioners } = useQuery({
261261
...provisionerDaemons(selectedOrg?.id ?? ""),
262-
enabled: showOrganizationPicker && Boolean(selectedOrg),
262+
enabled: Boolean(showOrganizationPicker) && Boolean(selectedOrg),
263263
});
264264

265265
// TODO: Ideally, we would have a backend endpoint that could notify the

site/src/pages/OrganizationSettingsPage/OrganizationProvisionerKeysPage/OrganizationProvisionerKeysPage.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ const OrganizationProvisionerKeysPage: FC = () => {
1717
const { entitlements } = useDashboard();
1818
const provisionerKeyDaemonsQuery = useQuery({
1919
...provisionerDaemonGroups(organizationName),
20+
enabled: !!organization,
2021
select: (data) =>
2122
[...data].sort((a, b) => b.daemons.length - a.daemons.length),
2223
});

0 commit comments

Comments
 (0)