diff --git a/src/app/(routegroups)/(projectroutes)/projects/[projectSlug]/[environmentSlug]/deployments/(deployments-page)/loading.tsx b/src/app/(routegroups)/(projectroutes)/projects/[projectSlug]/[environmentSlug]/deployments/(deployments-page)/loading.tsx index 1a5e005b..b09bef2c 100644 --- a/src/app/(routegroups)/(projectroutes)/projects/[projectSlug]/[environmentSlug]/deployments/(deployments-page)/loading.tsx +++ b/src/app/(routegroups)/(projectroutes)/projects/[projectSlug]/[environmentSlug]/deployments/(deployments-page)/loading.tsx @@ -3,11 +3,58 @@ import { usePathname } from 'next/navigation'; import SectionWrapper from '@/components/SectionWrapper/SectionWrapper'; -import DeployLatest from '@/components/pages/deployments/_components/DeployLatest'; import getDeploymentTableColumns from '@/components/pages/deployments/_components/TableColumns'; import { deploymentResultOptions, statusOptions } from '@/components/pages/deployments/_components/filterValues'; -import { DataTable, DateRangePicker, SelectWithOptions } from '@uselagoon/ui-library'; +import {Button, DataTable, DateRangePicker, SelectWithOptions} from '@uselagoon/ui-library'; import { useQueryStates } from 'nuqs'; +import {GitBranch, Zap} from "lucide-react"; + +const deploymentOptions = [ + { + type: 'full' as const, + icon: , + title: 'Full Deployment', + description: 'Builds new images and applies all pending changes including variables, routes, and services.', + }, + { + type: 'variables' as const, + icon: , + title: 'Variables Only Deployment', + description: 'Faster deployment that updates runtime variables and restarts pods. Does not rebuild images.', + }, +]; + +const DeployLatestSkeleton = () => ( +
+
+

Deployment Type

+

Choose how you want to deploy these changes

+
+ +
+ {deploymentOptions.map(option => ( + + ))} +
+
+ +
+
+); export default function Loading() { const [{ results }, setQuery] = useQueryStates({ @@ -25,7 +72,7 @@ export default function Loading() { View previous deployments or trigger a new one - + ( -
-
- Start a new deployment of -
- -
-); +type DeploymentType = 'full' | 'variables'; + + +const deploymentOptions = [ + { + type: 'full' as const, + icon: , + title: 'Full Deployment', + description: 'Builds new images and applies all pending changes including variables, routes, and services.', + }, + { + type: 'variables' as const, + icon: , + title: 'Variables Only Deployment', + description: 'Faster deployment that updates runtime variables and restarts pods. Does not rebuild images.', + }, +]; const DeployLatestData: React.FC = ({ environment }) => { const { id, deployType, deployBaseRef, deployHeadRef, deployTitle } = environment; + const [selectedType, setSelectedType] = useState('full'); - const [deployEnvironmentLatestMutation, { loading, error }] = useMutation(deployEnvironmentLatest, { + const [deployEnvironmentLatestMutation, { loading }] = useMutation(deployEnvironmentLatest, { onError: err => { console.error(err); toast.error('Deployment error', { @@ -44,9 +55,11 @@ const DeployLatestData: React.FC = ({ environment }) => { }, variables: { environmentId: id, + envVarOnly: selectedType === 'variables' ? "true" : "false", }, onCompleted: () => { - toast.success('Deployment triggered'); + const message = selectedType === 'variables' ? 'Variable-only deployment triggered' : 'Deployment triggered'; + toast.success(message); }, refetchQueries: ['getEnvironment'], }); @@ -65,38 +78,70 @@ const DeployLatestData: React.FC = ({ environment }) => { deploymentsEnabled = false; } + if (!deploymentsEnabled) { + return ( +
+
+ Manual deployments are not available for this environment. +
+ +
+ ); + } + return ( -
- {!deploymentsEnabled ? ( - <> -
- Manual deployments are not available for this environment. -
- - - ) : ( - <> -
- {deployType === 'branch' && `Start a new deployment of branch ${deployBaseRef}.`} - {deployType === 'pullrequest' && `Start a new deployment of pull request ${deployTitle}.`} - {deployType === 'promote' && - `Start a new deployment from environment ${environment.project.name}-${deployBaseRef}.`} + ))} +
+ + {selectedType === 'variables' && ( +
+ +
+

Partial Deployment Warning

+

+ Some changes will not fully apply with a variables only deployment. Runtime variables will update now. Build scoped behaviour and other changes will only take effect after a full deployment. +

- - +
)} + +
+ +
); }; const DeployLatest = (props: Props | PropsWithSkeleton) => { - if ('skeleton' in props && props.skeleton) { - return ; - } return ; }; diff --git a/src/lib/mutation/deployEnvironmentLatest.ts b/src/lib/mutation/deployEnvironmentLatest.ts index b854fe6d..deb0d6df 100644 --- a/src/lib/mutation/deployEnvironmentLatest.ts +++ b/src/lib/mutation/deployEnvironmentLatest.ts @@ -1,7 +1,14 @@ import { gql } from '@apollo/client'; export default gql` - mutation deployEnvironmentLatest($environmentId: Int!) { - deployEnvironmentLatest(input: { environment: { id: $environmentId } }) + mutation deployEnvironmentLatest($environmentId: Int!, $envVarOnly: String = "false") { + deployEnvironmentLatest(input: { environment: { id: $environmentId }, + buildVariables: [ + { + name: "LAGOON_VARIABLES_ONLY", + value: $envVarOnly + } + ] + }) } `;