From 6578c4d6b6dba203d8c981cf869fdd53805d4363 Mon Sep 17 00:00:00 2001 From: Yaroslav Grishajev Date: Fri, 29 Nov 2024 09:29:01 +0100 Subject: [PATCH] refactor(template): use env var for cicd template check refs #477 --- apps/deploy-web/env/.env | 4 +- .../deployments/DeploymentDetail.tsx | 6 +- .../new-deployment/NewDeploymentContainer.tsx | 59 +++++++++---------- .../update/RemoteDeployUpdate.tsx | 13 ++-- .../src/config/browser-env.config.ts | 3 +- .../src/config/env-config.schema.ts | 6 +- .../SdlBuilderProvider/SdlBuilderProvider.tsx | 2 +- .../lib/nextjs/getValidatedServerSIdeProps.ts | 24 ++++---- .../src/pages/deploy-linux/index.tsx | 3 + .../src/pages/deployments/[dseq]/index.tsx | 5 -- .../src/pages/new-deployment/index.tsx | 26 +++++++- apps/deploy-web/src/queries/queryKeys.ts | 1 + .../src/queries/useTemplateQuery.tsx | 7 +++ .../remote-deployment-controller.service.ts | 5 +- package-lock.json | 2 +- 15 files changed, 94 insertions(+), 72 deletions(-) diff --git a/apps/deploy-web/env/.env b/apps/deploy-web/env/.env index 9a707a612..c83a5625b 100644 --- a/apps/deploy-web/env/.env +++ b/apps/deploy-web/env/.env @@ -10,4 +10,6 @@ NEXT_PUBLIC_REDIRECT_URI='https://console.akash.network/new-deployment' NEXT_PUBLIC_GITHUB_APP_INSTALLATION_URL='https://github.com/apps/akash-console-build-and-deploy-app/installations/new' NEXT_PUBLIC_BITBUCKET_CLIENT_ID=tdH2xfRkTcdqVP6cwW NEXT_PUBLIC_GITHUB_CLIENT_ID=Iv23lidSwihrsSL7aGew -NEXT_PUBLIC_GITLAB_CLIENT_ID=beb5370aad2fdb6147edb44248d20d30c3e189ddfb40c26f651c77bbe949d5a8 \ No newline at end of file +NEXT_PUBLIC_GITLAB_CLIENT_ID=beb5370aad2fdb6147edb44248d20d30c3e189ddfb40c26f651c77bbe949d5a8 + +NEXT_PUBLIC_CI_CD_IMAGE_NAME=hoomanhq/automation \ No newline at end of file diff --git a/apps/deploy-web/src/components/deployments/DeploymentDetail.tsx b/apps/deploy-web/src/components/deployments/DeploymentDetail.tsx index 4ffe8e226..09f9ddacd 100644 --- a/apps/deploy-web/src/components/deployments/DeploymentDetail.tsx +++ b/apps/deploy-web/src/components/deployments/DeploymentDetail.tsx @@ -1,7 +1,6 @@ "use client"; import { createRef, FC, useEffect, useState } from "react"; -import type { TemplateOutput } from "@akashnetwork/http-sdk/src/template/template-http.service"; import { Alert, Button, buttonVariants, Spinner, Tabs, TabsList, TabsTrigger } from "@akashnetwork/ui/components"; import { cn } from "@akashnetwork/ui/utils"; import { ArrowLeft } from "iconoir-react"; @@ -32,10 +31,9 @@ import { ManifestUpdate } from "./ManifestUpdate"; export interface DeploymentDetailProps { dseq: string; - remoteDeployTemplate: TemplateOutput; } -export const DeploymentDetail: FC = ({ dseq, remoteDeployTemplate }) => { +export const DeploymentDetail: FC = ({ dseq }) => { const router = useRouter(); const [activeTab, setActiveTab] = useState("LEASES"); const [editedManifest, setEditedManifest] = useState(null); @@ -43,7 +41,7 @@ export const DeploymentDetail: FC = ({ dseq, remoteDeploy const { isSettingsInit } = useSettings(); const [leaseRefs, setLeaseRefs] = useState>([]); const [deploymentManifest, setDeploymentManifest] = useState(null); - const isRemoteDeploy: boolean = !!editedManifest && !!isImageInYaml(editedManifest, remoteDeployTemplate?.deploy); + const isRemoteDeploy: boolean = !!editedManifest && !!isImageInYaml(editedManifest); const repo: string | null = isRemoteDeploy ? extractRepositoryUrl(editedManifest) : null; const { diff --git a/apps/deploy-web/src/components/new-deployment/NewDeploymentContainer.tsx b/apps/deploy-web/src/components/new-deployment/NewDeploymentContainer.tsx index d772e4a07..b30b35601 100644 --- a/apps/deploy-web/src/components/new-deployment/NewDeploymentContainer.tsx +++ b/apps/deploy-web/src/components/new-deployment/NewDeploymentContainer.tsx @@ -1,5 +1,6 @@ "use client"; -import { FC, useEffect, useState } from "react"; +import { FC, useCallback, useEffect, useState } from "react"; +import { TemplateOutput } from "@akashnetwork/http-sdk/src/template/template-http.service"; import { useAtomValue } from "jotai"; import { useRouter, useSearchParams } from "next/navigation"; @@ -20,7 +21,12 @@ import { ManifestEdit } from "./ManifestEdit"; import { CustomizedSteppers } from "./Stepper"; import { TemplateList } from "./TemplateList"; -export const NewDeploymentContainer: FC = () => { +export interface NewDeploymentContainerProps { + template?: TemplateOutput; + templateId?: string; +} + +export const NewDeploymentContainer: FC = ({ template: requestedTemplate, templateId }) => { const [isGitProviderTemplate, setIsGitProviderTemplate] = useState(false); const { isLoading: isLoadingTemplates, templates } = useTemplates(); const [activeStep, setActiveStep] = useState(null); @@ -28,7 +34,6 @@ export const NewDeploymentContainer: FC = () => { const [editedManifest, setEditedManifest] = useState(null); const deploySdl = useAtomValue(sdlStore.deploySdl); const { getDeploymentData } = useLocalNotes(); - const { getTemplateById } = useTemplates(); const router = useRouter(); const searchParams = useSearchParams(); const dseq = searchParams?.get("dseq"); @@ -78,8 +83,7 @@ export const NewDeploymentContainer: FC = () => { toggleCmp("ssh"); } - const cicdTemplate = getTemplateById(CI_CD_TEMPLATE_ID); - const isRemoteYamlImage = isImageInYaml(template?.content as string, cicdTemplate?.deploy); + const isRemoteYamlImage = isImageInYaml(template?.content as string); const queryStep = searchParams?.get("step"); if (queryStep !== RouteStep.editDeployment) { if (isRemoteYamlImage) { @@ -113,34 +117,25 @@ export const NewDeploymentContainer: FC = () => { return template; }; - const getGalleryTemplate = (): Partial<{ - code: string; - name: string; - content: string; - valuesToChange: any[]; - config: { ssh?: boolean }; - }> | null => { - const queryTemplateId = searchParams?.get("templateId"); - if (queryTemplateId) { - const templateById = getTemplateById(queryTemplateId as string); - if (templateById) { - return { + const getGalleryTemplate = useCallback((): + | Partial<{ + code: string; + name: string; + content: string; + valuesToChange: any[]; + config: { ssh?: boolean }; + }> + | undefined => { + return requestedTemplate + ? { code: "empty", - name: templateById.name, - content: templateById.deploy, - valuesToChange: templateById.valuesToChange || [], - config: templateById.config - }; - } - - const hardCodedTemplate = hardcodedTemplates.find(t => t.code === queryTemplateId); - if (hardCodedTemplate) { - return hardCodedTemplate; - } - } - - return null; - }; + name: requestedTemplate.name, + content: requestedTemplate.deploy, + valuesToChange: [], + config: requestedTemplate.config + } + : hardcodedTemplates.find(t => t.code === templateId); + }, [requestedTemplate, templateId]); function getStepIndexByParam(step: (typeof RouteStep)[keyof typeof RouteStep] | null) { switch (step) { diff --git a/apps/deploy-web/src/components/remote-deploy/update/RemoteDeployUpdate.tsx b/apps/deploy-web/src/components/remote-deploy/update/RemoteDeployUpdate.tsx index f1d8c600c..ab242e426 100644 --- a/apps/deploy-web/src/components/remote-deploy/update/RemoteDeployUpdate.tsx +++ b/apps/deploy-web/src/components/remote-deploy/update/RemoteDeployUpdate.tsx @@ -6,9 +6,9 @@ import { useSnackbar } from "notistack"; import { EnvFormModal } from "@src/components/sdl/EnvFormModal"; import { EnvVarList } from "@src/components/sdl/EnvVarList"; -import { CI_CD_TEMPLATE_ID, CURRENT_SERVICE, protectedEnvironmentVariables } from "@src/config/remote-deploy.config"; +import { browserEnvConfig } from "@src/config/browser-env.config"; +import { CURRENT_SERVICE, protectedEnvironmentVariables } from "@src/config/remote-deploy.config"; import { SdlBuilderProvider } from "@src/context/SdlBuilderProvider"; -import { useTemplates } from "@src/context/TemplatesProvider"; import { EnvVarUpdater } from "@src/services/remote-deploy/remote-deployment-controller.service"; import { tokens } from "@src/store/remoteDeployStore"; import { SdlBuilderFormValuesType, ServiceType } from "@src/types"; @@ -26,8 +26,6 @@ const RemoteDeployUpdate = ({ sdlString, onManifestChange }: { sdlString: string const [isEditingEnv, setIsEditingEnv] = useState(false); const { control, watch, setValue } = useForm({ defaultValues: { services: [defaultService] } }); const { fields: services } = useFieldArray({ control, name: "services", keyName: "id" }); - const { getTemplateById } = useTemplates(); - const remoteDeployTemplate = getTemplateById(CI_CD_TEMPLATE_ID); const envVarUpdater = useMemo(() => new EnvVarUpdater(services), [services]); useEffect(() => { @@ -51,10 +49,7 @@ const RemoteDeployUpdate = ({ sdlString, onManifestChange }: { sdlString: string const createAndValidateSdl = (yamlStr: string) => { try { - if (!yamlStr) return []; - const services = importSimpleSdl(yamlStr); - - return services; + return yamlStr ? importSimpleSdl(yamlStr) : []; } catch (err) { if (err.name === "YAMLException" || err.name === "CustomValidationError") { enqueueSnackbar(, { variant: "error" }); @@ -65,7 +60,7 @@ const RemoteDeployUpdate = ({ sdlString, onManifestChange }: { sdlString: string } } }; - return remoteDeployTemplate?.deploy?.includes(services?.[0]?.image) && services?.[0]?.env && services?.[0]?.env?.length > 0 ? ( + return services?.[0]?.image.startsWith(browserEnvConfig.NEXT_PUBLIC_CI_CD_IMAGE_NAME) && services?.[0]?.env && services?.[0]?.env?.length > 0 ? (
diff --git a/apps/deploy-web/src/config/browser-env.config.ts b/apps/deploy-web/src/config/browser-env.config.ts index 27fa036af..5981e7dfd 100644 --- a/apps/deploy-web/src/config/browser-env.config.ts +++ b/apps/deploy-web/src/config/browser-env.config.ts @@ -22,5 +22,6 @@ export const browserEnvConfig = validateStaticEnvVars({ NEXT_PUBLIC_BITBUCKET_CLIENT_ID: process.env.NEXT_PUBLIC_BITBUCKET_CLIENT_ID, NEXT_PUBLIC_GITLAB_CLIENT_ID: process.env.NEXT_PUBLIC_GITLAB_CLIENT_ID, NEXT_PUBLIC_GITHUB_CLIENT_ID: process.env.NEXT_PUBLIC_GITHUB_CLIENT_ID, - NEXT_PUBLIC_GA_MEASUREMENT_ID: process.env.NEXT_PUBLIC_GA_MEASUREMENT_ID + NEXT_PUBLIC_GA_MEASUREMENT_ID: process.env.NEXT_PUBLIC_GA_MEASUREMENT_ID, + NEXT_PUBLIC_CI_CD_IMAGE_NAME: process.env.NEXT_PUBLIC_CI_CD_IMAGE_NAME }); diff --git a/apps/deploy-web/src/config/env-config.schema.ts b/apps/deploy-web/src/config/env-config.schema.ts index 2d3682f5b..6000539e2 100644 --- a/apps/deploy-web/src/config/env-config.schema.ts +++ b/apps/deploy-web/src/config/env-config.schema.ts @@ -25,7 +25,8 @@ export const browserEnvSchema = z.object({ NEXT_PUBLIC_GITHUB_APP_INSTALLATION_URL: z.string().url(), NEXT_PUBLIC_BITBUCKET_CLIENT_ID: z.string().optional(), NEXT_PUBLIC_GITLAB_CLIENT_ID: z.string().optional(), - NEXT_PUBLIC_GITHUB_CLIENT_ID: z.string().optional() + NEXT_PUBLIC_GITHUB_CLIENT_ID: z.string().optional(), + NEXT_PUBLIC_CI_CD_IMAGE_NAME: z.string() }); export const serverEnvSchema = browserEnvSchema.extend({ @@ -42,7 +43,8 @@ export const serverEnvSchema = browserEnvSchema.extend({ BASE_API_SANDBOX_URL: z.string().url(), GITHUB_CLIENT_SECRET: z.string(), BITBUCKET_CLIENT_SECRET: z.string(), - GITLAB_CLIENT_SECRET: z.string() + GITLAB_CLIENT_SECRET: z.string(), + NEXT_PUBLIC_CI_CD_IMAGE_NAME: z.string() }); export type BrowserEnvConfig = z.infer; diff --git a/apps/deploy-web/src/context/SdlBuilderProvider/SdlBuilderProvider.tsx b/apps/deploy-web/src/context/SdlBuilderProvider/SdlBuilderProvider.tsx index 3f168b53a..cd02100a4 100644 --- a/apps/deploy-web/src/context/SdlBuilderProvider/SdlBuilderProvider.tsx +++ b/apps/deploy-web/src/context/SdlBuilderProvider/SdlBuilderProvider.tsx @@ -68,7 +68,7 @@ export const useSdlBuilder = () => { }; export const withSdlBuilder = (options: SdlBuilderProviderProps = {}) => - function wrapWithSdlBuilder

(Component: React.ComponentType

): FC

| React.ComponentType

{ + function wrapWithSdlBuilder

>(Component: React.ComponentType

): FC

| React.ComponentType

{ return function WrappedComponent(props: P) { return ( diff --git a/apps/deploy-web/src/lib/nextjs/getValidatedServerSIdeProps.ts b/apps/deploy-web/src/lib/nextjs/getValidatedServerSIdeProps.ts index 537c74227..37204a3a7 100644 --- a/apps/deploy-web/src/lib/nextjs/getValidatedServerSIdeProps.ts +++ b/apps/deploy-web/src/lib/nextjs/getValidatedServerSIdeProps.ts @@ -1,20 +1,18 @@ -import { GetServerSidePropsContext, GetServerSidePropsResult, PreviewData } from "next/types"; +import { GetServerSidePropsContext, GetServerSidePropsResult } from "next/types"; import type { ParsedUrlQuery } from "querystring"; import { z } from "zod"; -export const getValidatedServerSideProps = < - Props extends { [key: string]: any } = { [key: string]: any }, - Params extends ParsedUrlQuery = ParsedUrlQuery, - Preview extends PreviewData = PreviewData, - Schema extends z.ZodObject = z.ZodObject<{ params: z.ZodObject }, any, any> ->( +type ContextParamsSchema = z.ZodObject | z.ZodOptional>>; + +type ContextSchema = z.ZodObject<{ params?: ContextParamsSchema; query?: ContextParamsSchema }>; + +export const getValidatedServerSideProps = ( schema: Schema, - handler: ( - context: Omit, "params"> & { params: z.infer["params"] } - ) => Promise> -): ((context: GetServerSidePropsContext) => Promise>) => { + handler: (context: Omit & z.infer) => Promise> +): ((context: GetServerSidePropsContext) => Promise>) => { return context => { - const { params } = schema.parse(context); - return handler({ ...context, params }); + const validated = schema.parse(context); + + return handler({ ...context, ...validated }); }; }; diff --git a/apps/deploy-web/src/pages/deploy-linux/index.tsx b/apps/deploy-web/src/pages/deploy-linux/index.tsx index f45a806ad..6e997c446 100644 --- a/apps/deploy-web/src/pages/deploy-linux/index.tsx +++ b/apps/deploy-web/src/pages/deploy-linux/index.tsx @@ -1,7 +1,10 @@ import { NewDeploymentContainer } from "@src/components/new-deployment/NewDeploymentContainer"; import { withSdlBuilder } from "@src/context/SdlBuilderProvider/SdlBuilderProvider"; +import { getServerSideProps } from "../new-deployment"; export default withSdlBuilder({ componentsSet: "ssh", imageSource: "ssh-vms" })(NewDeploymentContainer); + +export { getServerSideProps }; diff --git a/apps/deploy-web/src/pages/deployments/[dseq]/index.tsx b/apps/deploy-web/src/pages/deployments/[dseq]/index.tsx index f80655361..357cc27b3 100644 --- a/apps/deploy-web/src/pages/deployments/[dseq]/index.tsx +++ b/apps/deploy-web/src/pages/deployments/[dseq]/index.tsx @@ -1,9 +1,7 @@ import { z } from "zod"; import { DeploymentDetail } from "@src/components/deployments/DeploymentDetail"; -import { CI_CD_TEMPLATE_ID } from "@src/config/remote-deploy.config"; import { getValidatedServerSideProps } from "@src/lib/nextjs/getValidatedServerSIdeProps"; -import { services } from "@src/services/http/http-server.service"; export default DeploymentDetail; @@ -14,11 +12,8 @@ const contextSchema = z.object({ }); export const getServerSideProps = getValidatedServerSideProps(contextSchema, async ({ params }) => { - const remoteDeployTemplate = await services.template.findById(CI_CD_TEMPLATE_ID); - return { props: { - remoteDeployTemplate, dseq: params.dseq } }; diff --git a/apps/deploy-web/src/pages/new-deployment/index.tsx b/apps/deploy-web/src/pages/new-deployment/index.tsx index 9f9b50e8b..0feaddf2c 100644 --- a/apps/deploy-web/src/pages/new-deployment/index.tsx +++ b/apps/deploy-web/src/pages/new-deployment/index.tsx @@ -1,4 +1,28 @@ -import { NewDeploymentContainer } from "@src/components/new-deployment/NewDeploymentContainer"; +import { z } from "zod"; + +import { NewDeploymentContainer, NewDeploymentContainerProps } from "@src/components/new-deployment/NewDeploymentContainer"; import { withSdlBuilder } from "@src/context/SdlBuilderProvider/SdlBuilderProvider"; +import { getValidatedServerSideProps } from "@src/lib/nextjs/getValidatedServerSIdeProps"; +import { services } from "@src/services/http/http-server.service"; export default withSdlBuilder()(NewDeploymentContainer); + +const contextSchema = z.object({ + query: z.object({ + templateId: z.string().optional() + }) +}); + +export const getServerSideProps = getValidatedServerSideProps(contextSchema, async ({ query }) => { + if (!query.templateId) { + return { props: {} }; + } + + const template = await services.template.findById(query.templateId); + + if (template && query.templateId) { + return { props: { template, templateId: query.templateId } }; + } + + return { props: {} }; +}); diff --git a/apps/deploy-web/src/queries/queryKeys.ts b/apps/deploy-web/src/queries/queryKeys.ts index efc9b8a51..b45347522 100644 --- a/apps/deploy-web/src/queries/queryKeys.ts +++ b/apps/deploy-web/src/queries/queryKeys.ts @@ -42,6 +42,7 @@ export class QueryKeys { static getBlockKey = (id: string) => ["BLOCK", id]; static getBalancesKey = (address?: string) => (address ? ["BALANCES", address] : []); static getTemplatesKey = () => ["TEMPLATES"]; + static getTemplateKey = (id: string) => ["TEMPLATES", id]; static getProviderAttributesSchema = () => ["PROVIDER_ATTRIBUTES_SCHEMA"]; static getDepositParamsKey = () => ["DEPOSIT_PARAMS"]; static getGpuModelsKey = () => ["GPU_MODELS"]; diff --git a/apps/deploy-web/src/queries/useTemplateQuery.tsx b/apps/deploy-web/src/queries/useTemplateQuery.tsx index e8a24cd68..e4d493810 100644 --- a/apps/deploy-web/src/queries/useTemplateQuery.tsx +++ b/apps/deploy-web/src/queries/useTemplateQuery.tsx @@ -1,10 +1,13 @@ import { QueryKey, useMutation, useQuery, useQueryClient, UseQueryOptions } from "react-query"; +import { UseQueryResult } from "react-query/types/react/types"; +import { TemplateOutput } from "@akashnetwork/http-sdk/src/template/template-http.service"; import { Snackbar } from "@akashnetwork/ui/components"; import axios from "axios"; import { useRouter } from "next/navigation"; import { useSnackbar } from "notistack"; import { useCustomUser } from "@src/hooks/useCustomUser"; +import { services } from "@src/services/http/http-browser.service"; import { ITemplate } from "@src/types"; import { ApiUrlService } from "@src/utils/apiUtils"; import { UrlService } from "@src/utils/urlUtils"; @@ -130,3 +133,7 @@ export function useTemplates(options = {}) { refetchOnReconnect: false }); } + +export function useTemplateById(id: string, options: UseQueryOptions = {}): UseQueryResult { + return useQuery(QueryKeys.getTemplateKey(id), () => services.template.findById(id), options); +} diff --git a/apps/deploy-web/src/services/remote-deploy/remote-deployment-controller.service.ts b/apps/deploy-web/src/services/remote-deploy/remote-deployment-controller.service.ts index 2d341594a..11fbeb60a 100644 --- a/apps/deploy-web/src/services/remote-deploy/remote-deployment-controller.service.ts +++ b/apps/deploy-web/src/services/remote-deploy/remote-deployment-controller.service.ts @@ -1,5 +1,6 @@ import { nanoid } from "nanoid"; +import { browserEnvConfig } from "@src/config/browser-env.config"; import { SdlBuilderFormValuesType, ServiceType } from "@src/types"; export class EnvVarUpdater { @@ -35,8 +36,8 @@ export function formatUrlWithoutInitialPath(url?: string): string | undefined { return url?.split("/").slice(-2).join("/"); } -export function isImageInYaml(yml: string, cicdYml?: string): boolean | undefined { - return cicdYml?.includes(yml?.split("service-1:")?.[1]?.split("expose:")?.[0]?.split("image: ")?.[1]); +export function isImageInYaml(yml: string): boolean | undefined { + return yml.includes(browserEnvConfig.NEXT_PUBLIC_CI_CD_IMAGE_NAME); } export function extractRepositoryUrl(yml?: string | null): string | null { diff --git a/package-lock.json b/package-lock.json index 9c70de49d..4511a8ba4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -31,7 +31,7 @@ }, "apps/api": { "name": "@akashnetwork/console-api", - "version": "2.34.0", + "version": "2.35.1", "license": "Apache-2.0", "dependencies": { "@akashnetwork/akash-api": "^1.3.0",