diff --git a/coderd/apidoc/docs.go b/coderd/apidoc/docs.go index f04565d1506a1..424ebfbab8b40 100644 --- a/coderd/apidoc/docs.go +++ b/coderd/apidoc/docs.go @@ -9040,6 +9040,15 @@ const docTemplate = `{ "updated_at": { "type": "string", "format": "date-time" + }, + "warnings": { + "type": "array", + "items": { + "enum": [ + "DEPRECATED_PARAMETERS" + ], + "$ref": "#/definitions/codersdk.TemplateVersionWarning" + } } } }, @@ -9178,6 +9187,15 @@ const docTemplate = `{ } } }, + "codersdk.TemplateVersionWarning": { + "type": "string", + "enum": [ + "DEPRECATED_PARAMETERS" + ], + "x-enum-varnames": [ + "TemplateVersionWarningDeprecatedParameters" + ] + }, "codersdk.TokenConfig": { "type": "object", "properties": { diff --git a/coderd/apidoc/swagger.json b/coderd/apidoc/swagger.json index cd13980208286..89d3226f68eeb 100644 --- a/coderd/apidoc/swagger.json +++ b/coderd/apidoc/swagger.json @@ -8122,6 +8122,13 @@ "updated_at": { "type": "string", "format": "date-time" + }, + "warnings": { + "type": "array", + "items": { + "enum": ["DEPRECATED_PARAMETERS"], + "$ref": "#/definitions/codersdk.TemplateVersionWarning" + } } } }, @@ -8248,6 +8255,11 @@ } } }, + "codersdk.TemplateVersionWarning": { + "type": "string", + "enum": ["DEPRECATED_PARAMETERS"], + "x-enum-varnames": ["TemplateVersionWarningDeprecatedParameters"] + }, "codersdk.TokenConfig": { "type": "object", "properties": { diff --git a/coderd/templateversions.go b/coderd/templateversions.go index 8b31c6ad177f1..15b037bd62988 100644 --- a/coderd/templateversions.go +++ b/coderd/templateversions.go @@ -62,7 +62,19 @@ func (api *API) templateVersion(rw http.ResponseWriter, r *http.Request) { return } - httpapi.Write(ctx, rw, http.StatusOK, convertTemplateVersion(templateVersion, convertProvisionerJob(job), user)) + schemas, err := api.Database.GetParameterSchemasByJobID(ctx, job.ID) + if errors.Is(err, sql.ErrNoRows) { + err = nil + } + if err != nil { + httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{ + Message: "Internal error listing parameter schemas.", + Detail: err.Error(), + }) + return + } + + httpapi.Write(ctx, rw, http.StatusOK, convertTemplateVersion(templateVersion, convertProvisionerJob(job), user, schemas)) } // @Summary Patch template version by ID @@ -156,7 +168,19 @@ func (api *API) patchTemplateVersion(rw http.ResponseWriter, r *http.Request) { return } - httpapi.Write(ctx, rw, http.StatusOK, convertTemplateVersion(updatedTemplateVersion, convertProvisionerJob(job), user)) + schemas, err := api.Database.GetParameterSchemasByJobID(ctx, job.ID) + if errors.Is(err, sql.ErrNoRows) { + err = nil + } + if err != nil { + httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{ + Message: "Internal error listing parameter schemas.", + Detail: err.Error(), + }) + return + } + + httpapi.Write(ctx, rw, http.StatusOK, convertTemplateVersion(updatedTemplateVersion, convertProvisionerJob(job), user, schemas)) } // @Summary Cancel template version by ID @@ -887,7 +911,18 @@ func (api *API) templateVersionsByTemplate(rw http.ResponseWriter, r *http.Reque }) return err } - apiVersions = append(apiVersions, convertTemplateVersion(version, convertProvisionerJob(job), user)) + schemas, err := api.Database.GetParameterSchemasByJobID(ctx, job.ID) + if errors.Is(err, sql.ErrNoRows) { + err = nil + } + if err != nil { + httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{ + Message: "Internal error listing parameter schemas.", + Detail: err.Error(), + }) + return err + } + apiVersions = append(apiVersions, convertTemplateVersion(version, convertProvisionerJob(job), user, schemas)) } return nil @@ -951,7 +986,19 @@ func (api *API) templateVersionByName(rw http.ResponseWriter, r *http.Request) { return } - httpapi.Write(ctx, rw, http.StatusOK, convertTemplateVersion(templateVersion, convertProvisionerJob(job), user)) + schemas, err := api.Database.GetParameterSchemasByJobID(ctx, job.ID) + if errors.Is(err, sql.ErrNoRows) { + err = nil + } + if err != nil { + httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{ + Message: "Internal error listing parameter schemas.", + Detail: err.Error(), + }) + return + } + + httpapi.Write(ctx, rw, http.StatusOK, convertTemplateVersion(templateVersion, convertProvisionerJob(job), user, schemas)) } // @Summary Get template version by organization, template, and name @@ -1025,7 +1072,19 @@ func (api *API) templateVersionByOrganizationTemplateAndName(rw http.ResponseWri return } - httpapi.Write(ctx, rw, http.StatusOK, convertTemplateVersion(templateVersion, convertProvisionerJob(job), user)) + schemas, err := api.Database.GetParameterSchemasByJobID(ctx, job.ID) + if errors.Is(err, sql.ErrNoRows) { + err = nil + } + if err != nil { + httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{ + Message: "Internal error listing parameter schemas.", + Detail: err.Error(), + }) + return + } + + httpapi.Write(ctx, rw, http.StatusOK, convertTemplateVersion(templateVersion, convertProvisionerJob(job), user, schemas)) } // @Summary Get previous template version by organization, template, and name @@ -1120,7 +1179,19 @@ func (api *API) previousTemplateVersionByOrganizationTemplateAndName(rw http.Res return } - httpapi.Write(ctx, rw, http.StatusOK, convertTemplateVersion(previousTemplateVersion, convertProvisionerJob(job), user)) + schemas, err := api.Database.GetParameterSchemasByJobID(ctx, job.ID) + if errors.Is(err, sql.ErrNoRows) { + err = nil + } + if err != nil { + httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{ + Message: "Internal error listing parameter schemas.", + Detail: err.Error(), + }) + return + } + + httpapi.Write(ctx, rw, http.StatusOK, convertTemplateVersion(previousTemplateVersion, convertProvisionerJob(job), user, schemas)) } // @Summary Update active template version by template ID @@ -1494,7 +1565,19 @@ func (api *API) postTemplateVersionsByOrganization(rw http.ResponseWriter, r *ht return } - httpapi.Write(ctx, rw, http.StatusCreated, convertTemplateVersion(templateVersion, convertProvisionerJob(provisionerJob), user)) + schemas, err := api.Database.GetParameterSchemasByJobID(ctx, provisionerJob.ID) + if errors.Is(err, sql.ErrNoRows) { + err = nil + } + if err != nil { + httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{ + Message: "Internal error listing parameter schemas.", + Detail: err.Error(), + }) + return + } + + httpapi.Write(ctx, rw, http.StatusCreated, convertTemplateVersion(templateVersion, convertProvisionerJob(provisionerJob), user, schemas)) } // templateVersionResources returns the workspace agent resources associated @@ -1561,7 +1644,7 @@ func (api *API) templateVersionLogs(rw http.ResponseWriter, r *http.Request) { api.provisionerJobLogs(rw, r, job) } -func convertTemplateVersion(version database.TemplateVersion, job codersdk.ProvisionerJob, user database.User) codersdk.TemplateVersion { +func convertTemplateVersion(version database.TemplateVersion, job codersdk.ProvisionerJob, user database.User, schemas []database.ParameterSchema) codersdk.TemplateVersion { createdBy := codersdk.User{ ID: user.ID, Username: user.Username, @@ -1572,6 +1655,11 @@ func convertTemplateVersion(version database.TemplateVersion, job codersdk.Provi AvatarURL: user.AvatarURL.String, } + var warnings []codersdk.TemplateVersionWarning + if len(schemas) > 0 { + warnings = append(warnings, codersdk.TemplateVersionWarningDeprecatedParameters) + } + return codersdk.TemplateVersion{ ID: version.ID, TemplateID: &version.TemplateID.UUID, @@ -1582,6 +1670,7 @@ func convertTemplateVersion(version database.TemplateVersion, job codersdk.Provi Job: job, Readme: version.Readme, CreatedBy: createdBy, + Warnings: warnings, } } diff --git a/coderd/templateversions_test.go b/coderd/templateversions_test.go index 12880449d57f2..4b192673a5de2 100644 --- a/coderd/templateversions_test.go +++ b/coderd/templateversions_test.go @@ -138,6 +138,7 @@ func TestPostTemplateVersionsByOrganization(t *testing.T) { require.Len(t, auditor.AuditLogs(), 2) assert.Equal(t, database.AuditActionCreate, auditor.AuditLogs()[1].Action) }) + t.Run("Example", func(t *testing.T) { t.Parallel() client := coderdtest.New(t, nil) @@ -1453,3 +1454,45 @@ func TestTemplateVersionPatch(t *testing.T) { require.Error(t, err) }) } + +func TestTemplateVersionWarnings(t *testing.T) { + t.Parallel() + + client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) + user := coderdtest.CreateFirstUser(t, client) + + ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong) + defer cancel() + + templateVersion := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ + Parse: []*proto.Parse_Response{{ + Type: &proto.Parse_Response_Complete{ + Complete: &proto.Parse_Complete{ + ParameterSchemas: []*proto.ParameterSchema{ + { + AllowOverrideSource: true, + Name: "example", + Description: "description 1", + DefaultSource: &proto.ParameterSource{ + Scheme: proto.ParameterSource_DATA, + Value: "tomato", + }, + DefaultDestination: &proto.ParameterDestination{ + Scheme: proto.ParameterDestination_PROVISIONER_VARIABLE, + }, + }, + }, + }, + }, + }}, + ProvisionApply: echo.ProvisionComplete, + ProvisionPlan: echo.ProvisionComplete, + }) + coderdtest.AwaitTemplateVersionJob(t, client, templateVersion.ID) + template := coderdtest.CreateTemplate(t, client, user.OrganizationID, templateVersion.ID) + + templateVersion, err := client.TemplateVersion(ctx, template.ActiveVersionID) + require.NoError(t, err) + + require.Contains(t, templateVersion.Warnings, codersdk.TemplateVersionWarningDeprecatedParameters) +} diff --git a/codersdk/templateversions.go b/codersdk/templateversions.go index b1608643084ec..cfc9af54443ae 100644 --- a/codersdk/templateversions.go +++ b/codersdk/templateversions.go @@ -11,6 +11,12 @@ import ( "github.com/google/uuid" ) +type TemplateVersionWarning string + +const ( + TemplateVersionWarningDeprecatedParameters TemplateVersionWarning = "DEPRECATED_PARAMETERS" +) + // TemplateVersion represents a single version of a template. type TemplateVersion struct { ID uuid.UUID `json:"id" format:"uuid"` @@ -22,6 +28,8 @@ type TemplateVersion struct { Job ProvisionerJob `json:"job"` Readme string `json:"readme"` CreatedBy User `json:"created_by"` + + Warnings []TemplateVersionWarning `json:"warnings,omitempty" enums:"DEPRECATED_PARAMETERS"` } type TemplateVersionGitAuth struct { diff --git a/docs/api/schemas.md b/docs/api/schemas.md index 6f191d774f3b3..cb66df84adcb5 100644 --- a/docs/api/schemas.md +++ b/docs/api/schemas.md @@ -4106,23 +4106,25 @@ Parameter represents a set value for the scope. "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6", "readme": "string", "template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc", - "updated_at": "2019-08-24T14:15:22Z" + "updated_at": "2019-08-24T14:15:22Z", + "warnings": ["DEPRECATED_PARAMETERS"] } ``` ### Properties -| Name | Type | Required | Restrictions | Description | -| ----------------- | -------------------------------------------------- | -------- | ------------ | ----------- | -| `created_at` | string | false | | | -| `created_by` | [codersdk.User](#codersdkuser) | false | | | -| `id` | string | false | | | -| `job` | [codersdk.ProvisionerJob](#codersdkprovisionerjob) | false | | | -| `name` | string | false | | | -| `organization_id` | string | false | | | -| `readme` | string | false | | | -| `template_id` | string | false | | | -| `updated_at` | string | false | | | +| Name | Type | Required | Restrictions | Description | +| ----------------- | --------------------------------------------------------------------------- | -------- | ------------ | ----------- | +| `created_at` | string | false | | | +| `created_by` | [codersdk.User](#codersdkuser) | false | | | +| `id` | string | false | | | +| `job` | [codersdk.ProvisionerJob](#codersdkprovisionerjob) | false | | | +| `name` | string | false | | | +| `organization_id` | string | false | | | +| `readme` | string | false | | | +| `template_id` | string | false | | | +| `updated_at` | string | false | | | +| `warnings` | array of [codersdk.TemplateVersionWarning](#codersdktemplateversionwarning) | false | | | ## codersdk.TemplateVersionGitAuth @@ -4260,6 +4262,20 @@ Parameter represents a set value for the scope. | `type` | `number` | | `type` | `bool` | +## codersdk.TemplateVersionWarning + +```json +"DEPRECATED_PARAMETERS" +``` + +### Properties + +#### Enumerated Values + +| Value | +| ----------------------- | +| `DEPRECATED_PARAMETERS` | + ## codersdk.TokenConfig ```json diff --git a/docs/api/templates.md b/docs/api/templates.md index 7df57183b54e3..6364e4b8e0279 100644 --- a/docs/api/templates.md +++ b/docs/api/templates.md @@ -394,7 +394,8 @@ curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/templat "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6", "readme": "string", "template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc", - "updated_at": "2019-08-24T14:15:22Z" + "updated_at": "2019-08-24T14:15:22Z", + "warnings": ["DEPRECATED_PARAMETERS"] } ``` @@ -471,7 +472,8 @@ curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/templat "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6", "readme": "string", "template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc", - "updated_at": "2019-08-24T14:15:22Z" + "updated_at": "2019-08-24T14:15:22Z", + "warnings": ["DEPRECATED_PARAMETERS"] } ``` @@ -580,7 +582,8 @@ curl -X POST http://coder-server:8080/api/v2/organizations/{organization}/templa "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6", "readme": "string", "template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc", - "updated_at": "2019-08-24T14:15:22Z" + "updated_at": "2019-08-24T14:15:22Z", + "warnings": ["DEPRECATED_PARAMETERS"] } ``` @@ -877,7 +880,8 @@ curl -X GET http://coder-server:8080/api/v2/templates/{template}/versions \ "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6", "readme": "string", "template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc", - "updated_at": "2019-08-24T14:15:22Z" + "updated_at": "2019-08-24T14:15:22Z", + "warnings": ["DEPRECATED_PARAMETERS"] } ] ``` @@ -927,6 +931,7 @@ Status Code **200** | `» readme` | string | false | | | | `» template_id` | string(uuid) | false | | | | `» updated_at` | string(date-time) | false | | | +| `» warnings` | array | false | | | #### Enumerated Values @@ -1064,7 +1069,8 @@ curl -X GET http://coder-server:8080/api/v2/templates/{template}/versions/{templ "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6", "readme": "string", "template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc", - "updated_at": "2019-08-24T14:15:22Z" + "updated_at": "2019-08-24T14:15:22Z", + "warnings": ["DEPRECATED_PARAMETERS"] } ] ``` @@ -1114,6 +1120,7 @@ Status Code **200** | `» readme` | string | false | | | | `» template_id` | string(uuid) | false | | | | `» updated_at` | string(date-time) | false | | | +| `» warnings` | array | false | | | #### Enumerated Values @@ -1195,7 +1202,8 @@ curl -X GET http://coder-server:8080/api/v2/templateversions/{templateversion} \ "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6", "readme": "string", "template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc", - "updated_at": "2019-08-24T14:15:22Z" + "updated_at": "2019-08-24T14:15:22Z", + "warnings": ["DEPRECATED_PARAMETERS"] } ``` @@ -1280,7 +1288,8 @@ curl -X PATCH http://coder-server:8080/api/v2/templateversions/{templateversion} "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6", "readme": "string", "template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc", - "updated_at": "2019-08-24T14:15:22Z" + "updated_at": "2019-08-24T14:15:22Z", + "warnings": ["DEPRECATED_PARAMETERS"] } ``` diff --git a/site/src/api/typesGenerated.ts b/site/src/api/typesGenerated.ts index 9e368ee93dbd6..d8ef384a4c406 100644 --- a/site/src/api/typesGenerated.ts +++ b/site/src/api/typesGenerated.ts @@ -899,6 +899,7 @@ export interface TemplateVersion { readonly job: ProvisionerJob readonly readme: string readonly created_by: User + readonly warnings?: TemplateVersionWarning[] } // From codersdk/templateversions.go @@ -1591,6 +1592,12 @@ export const ServerSentEventTypes: ServerSentEventType[] = [ export type TemplateRole = "" | "admin" | "use" export const TemplateRoles: TemplateRole[] = ["", "admin", "use"] +// From codersdk/templateversions.go +export type TemplateVersionWarning = "DEPRECATED_PARAMETERS" +export const TemplateVersionWarnings: TemplateVersionWarning[] = [ + "DEPRECATED_PARAMETERS", +] + // From codersdk/users.go export type UserStatus = "active" | "suspended" export const UserStatuses: UserStatus[] = ["active", "suspended"] diff --git a/site/src/components/TemplateVersionWarnings/TemplateVersionWarnings.stories.tsx b/site/src/components/TemplateVersionWarnings/TemplateVersionWarnings.stories.tsx new file mode 100644 index 0000000000000..7c3e0ebb4da46 --- /dev/null +++ b/site/src/components/TemplateVersionWarnings/TemplateVersionWarnings.stories.tsx @@ -0,0 +1,19 @@ +import { Story } from "@storybook/react" +import { + TemplateVersionWarnings, + TemplateVersionWarningsProps, +} from "./TemplateVersionWarnings" + +export default { + title: "components/TemplateVersionWarnings", + component: TemplateVersionWarnings, +} + +const Template: Story = (args) => ( + +) + +export const DeprecatedParameters = Template.bind({}) +DeprecatedParameters.args = { + warnings: ["DEPRECATED_PARAMETERS"], +} diff --git a/site/src/components/TemplateVersionWarnings/TemplateVersionWarnings.tsx b/site/src/components/TemplateVersionWarnings/TemplateVersionWarnings.tsx new file mode 100644 index 0000000000000..6f25efb925470 --- /dev/null +++ b/site/src/components/TemplateVersionWarnings/TemplateVersionWarnings.tsx @@ -0,0 +1,34 @@ +import { FC } from "react" +import * as TypesGen from "api/typesGenerated" +import { AlertBanner } from "components/AlertBanner/AlertBanner" +import { Maybe } from "components/Conditionals/Maybe" +import Link from "@mui/material/Link" + +export interface TemplateVersionWarningsProps { + warnings?: TypesGen.TemplateVersionWarning[] +} + +export const TemplateVersionWarnings: FC< + React.PropsWithChildren +> = ({ warnings }) => { + if (!warnings) { + return <> + } + + return ( + +
+ +
+ This template uses legacy parameters which will be deprecated in the + next Coder release. Learn how to migrate in{" "} + + our documentation + + . +
+
+
+
+ ) +} diff --git a/site/src/components/Workspace/Workspace.stories.tsx b/site/src/components/Workspace/Workspace.stories.tsx index 7b2b586915f44..fd36e6997e4da 100644 --- a/site/src/components/Workspace/Workspace.stories.tsx +++ b/site/src/components/Workspace/Workspace.stories.tsx @@ -660,3 +660,9 @@ function makeFailedBuildLogs(): ProvisionerJobLog[] { }, ] } + +export const WithDeprecatedParameters = Template.bind({}) +WithDeprecatedParameters.args = { + ...Running.args, + templateWarnings: ["DEPRECATED_PARAMETERS"], +} diff --git a/site/src/components/Workspace/Workspace.tsx b/site/src/components/Workspace/Workspace.tsx index 54201b6792a9f..0debdf2bdf07a 100644 --- a/site/src/components/Workspace/Workspace.tsx +++ b/site/src/components/Workspace/Workspace.tsx @@ -26,6 +26,7 @@ import { PageHeaderTitle, PageHeaderSubtitle, } from "components/PageHeader/FullWidthPageHeader" +import { TemplateVersionWarnings } from "components/TemplateVersionWarnings/TemplateVersionWarnings" export enum WorkspaceErrors { GET_BUILDS_ERROR = "getBuildsError", @@ -52,6 +53,7 @@ export interface WorkspaceProps { workspace: TypesGen.Workspace resources?: TypesGen.WorkspaceResource[] builds?: TypesGen.WorkspaceBuild[] + templateWarnings?: TypesGen.TemplateVersionWarning[] canUpdateWorkspace: boolean canUpdateTemplate: boolean canChangeVersions: boolean @@ -96,6 +98,7 @@ export const Workspace: FC> = ({ quota_budget, failedBuildLogs, handleBuildRetry, + templateWarnings, }) => { const styles = useStyles() const navigate = useNavigate() @@ -186,6 +189,8 @@ export const Workspace: FC> = ({ handleClick={() => navigate(`/templates`)} /> + + {failedBuildLogs && ( diff --git a/site/src/pages/TemplatePage/TemplateSummaryPage/TemplateSummaryPageView.stories.tsx b/site/src/pages/TemplatePage/TemplateSummaryPage/TemplateSummaryPageView.stories.tsx index a6869b189672c..58f47a8c5a1de 100644 --- a/site/src/pages/TemplatePage/TemplateSummaryPage/TemplateSummaryPageView.stories.tsx +++ b/site/src/pages/TemplatePage/TemplateSummaryPage/TemplateSummaryPageView.stories.tsx @@ -3,6 +3,7 @@ import { MockTemplate, MockTemplateDAUResponse, MockTemplateVersion, + MockTemplateVersion3, MockWorkspaceResource, MockWorkspaceResource2, } from "testHelpers/entities" @@ -65,3 +66,13 @@ SmallViewport.args = { SmallViewport.parameters = { chromatic: { viewports: [600] }, } + +export const WithDeprecatedParameters = Template.bind({}) +WithDeprecatedParameters.args = { + template: MockTemplate, + activeVersion: MockTemplateVersion3, + data: { + resources: [MockWorkspaceResource, MockWorkspaceResource2], + daus: MockTemplateDAUResponse, + }, +} diff --git a/site/src/pages/TemplatePage/TemplateSummaryPage/TemplateSummaryPageView.tsx b/site/src/pages/TemplatePage/TemplateSummaryPage/TemplateSummaryPageView.tsx index 4c46a84369cb1..462b9db37e69a 100644 --- a/site/src/pages/TemplatePage/TemplateSummaryPage/TemplateSummaryPageView.tsx +++ b/site/src/pages/TemplatePage/TemplateSummaryPage/TemplateSummaryPageView.tsx @@ -11,6 +11,7 @@ import { FC, useEffect } from "react" import { DAUChart } from "../../../components/DAUChart/DAUChart" import { TemplateSummaryData } from "./data" import { useLocation, useNavigate } from "react-router-dom" +import { TemplateVersionWarnings } from "components/TemplateVersionWarnings/TemplateVersionWarnings" export interface TemplateSummaryPageViewProps { data?: TemplateSummaryData @@ -48,6 +49,7 @@ export const TemplateSummaryPageView: FC = ({ return ( + {daus && } diff --git a/site/src/pages/WorkspacePage/WorkspacePage.test.tsx b/site/src/pages/WorkspacePage/WorkspacePage.test.tsx index 4ca8a3910749b..aad09d1c17a90 100644 --- a/site/src/pages/WorkspacePage/WorkspacePage.test.tsx +++ b/site/src/pages/WorkspacePage/WorkspacePage.test.tsx @@ -19,6 +19,7 @@ import { MockDeletingWorkspace, MockDeletedWorkspace, MockBuilds, + MockTemplateVersion3, } from "testHelpers/entities" import * as api from "../../api/api" import { Workspace } from "../../api/typesGenerated" @@ -351,4 +352,18 @@ describe("WorkspacePage", () => { expect(rows).toHaveLength(MockBuilds.length + 1) }) }) + + it("shows the template warnings", async () => { + server.use( + rest.get( + "/api/v2/templateversions/:templateVersionId", + async (req, res, ctx) => { + return res(ctx.status(200), ctx.json(MockTemplateVersion3)) + }, + ), + ) + + await renderWorkspacePage() + await screen.findByTestId("warning-deprecated-parameters") + }) }) diff --git a/site/src/pages/WorkspacePage/WorkspaceReadyPage.tsx b/site/src/pages/WorkspacePage/WorkspaceReadyPage.tsx index f25ca22927a4b..de80d7314e925 100644 --- a/site/src/pages/WorkspacePage/WorkspaceReadyPage.tsx +++ b/site/src/pages/WorkspacePage/WorkspaceReadyPage.tsx @@ -54,6 +54,7 @@ export const WorkspaceReadyPage = ({ const { workspace, template, + templateVersion, builds, getBuildsError, buildError, @@ -157,6 +158,7 @@ export const WorkspaceReadyPage = ({ sshPrefix={sshPrefix} template={template} quota_budget={quotaState.context.quota?.budget} + templateWarnings={templateVersion?.warnings} /> event.data, }), + assignTemplateVersion: assign({ + templateVersion: (_, event) => event.data, + }), assignPermissions: assign({ // Setting event.data as Permissions to be more stricted. So we know // what permissions we asked for. @@ -689,6 +718,15 @@ export const workspaceMachine = createMachine( throw Error("Cannot get template without workspace") } }, + getTemplateVersion: async (context) => { + if (context.template) { + return await API.getTemplateVersion( + context.template.active_version_id, + ) + } else { + throw Error("Cannot get template version without template") + } + }, updateWorkspace: ({ workspace }, { buildParameters }) => async (send) => {