+
diff --git a/apps/client/src/main.css b/apps/client/src/main.css
index f9098d4dee..58f1adca7f 100644
--- a/apps/client/src/main.css
+++ b/apps/client/src/main.css
@@ -42,6 +42,7 @@ body,
.fr-fieldset {
margin: 1rem 0 0;
align-items: flex-start;
+ min-width: 0;
}
.fr-checkbox-group {
@@ -72,6 +73,10 @@ body,
background-color: var(--background-alt-grey);
}
+.fr-alert pre {
+ white-space: normal;
+}
+
.log-panel, .log-btn {
background-color: var(--background-default-grey);
}
diff --git a/apps/client/src/utils/project-utils.ts b/apps/client/src/utils/project-utils.ts
index 7aa201b8ad..cc20822824 100644
--- a/apps/client/src/utils/project-utils.ts
+++ b/apps/client/src/utils/project-utils.ts
@@ -1,6 +1,8 @@
import type {
+ CreateDeploymentBody,
CreateEnvironmentBody,
CreateRepositoryBody,
+ Deployment,
Environment,
GetLogsQuery,
PermissionTarget,
@@ -13,6 +15,7 @@ import type {
Repo,
RepositoryParams,
Role,
+ UpdateDeploymentBody,
UpdateEnvironmentBody,
UpdateRepositoryBody,
User,
@@ -35,6 +38,7 @@ import { getRandomId } from './func.js'
export type ProjectOperations = 'create'
| 'delete'
+ | 'deploymentManagement'
| 'envManagement'
| 'repoManagement'
| 'teamManagement'
@@ -80,6 +84,7 @@ export class Project implements ProjectV2 {
myPerms: bigint
repositories: Ref
environments: Ref
+ deployments: Ref
services: ProjectService[] = []
lastSuccessProvisionningVersion: string | null
needReplay: Ref
@@ -112,6 +117,7 @@ export class Project implements ProjectV2 {
this.environments = ref([])
this.repositories = ref([])
this.needReplay = ref(false)
+ this.deployments = ref([])
}
private removeOperation(operationName: ProjectOperations) {
@@ -229,6 +235,40 @@ export class Project implements ProjectV2 {
},
}
+ Deployments = {
+ list: async () => {
+ this.deployments.value = await apiClient.Deployments.listDeployments({ query: { projectId: this.id } })
+ .then((response: any) => extractData(response, 200))
+ return this.deployments.value
+ },
+ create: async (deploymentData: Omit) => {
+ const callback = this.addOperation('deploymentManagement')
+ try {
+ await apiClient.Deployments.createDeployment({ body: { ...deploymentData, projectId: this.id } })
+ .then((response: any) => extractData(response, 201))
+ return this.Deployments.list()
+ } finally { callback() }
+ },
+ update: async (id: Deployment['id'], deployment: UpdateDeploymentBody) => {
+ const callback = this.addOperation('deploymentManagement')
+ try {
+ await apiClient.Deployments.updateDeployment({ body: deployment, params: { deploymentId: id } })
+ .then((response: any) => extractData(response, 200))
+ await this.Deployments.list()
+ return this.deployments
+ } finally { callback() }
+ },
+ delete: async (deploymentId: Deployment['id']) => {
+ const callback = this.addOperation('deploymentManagement')
+ try {
+ await apiClient.Deployments.deleteDeployment({ params: { deploymentId } })
+ .then((response: any) => extractData(response, 204))
+ await this.Deployments.list()
+ return this.deployments
+ } finally { callback() }
+ },
+ }
+
Environments = {
list: async () => {
this.environments.value = await apiClient.Environments.listEnvironments({ query: { projectId: this.id } })
diff --git a/packages/shared/src/api-client.ts b/packages/shared/src/api-client.ts
index 6c877a08de..96532b6a4d 100644
--- a/packages/shared/src/api-client.ts
+++ b/packages/shared/src/api-client.ts
@@ -11,6 +11,7 @@ export async function getContract() {
AdminRoles: (await import('./contracts/index.js')).adminRoleContract,
Clusters: (await import('./contracts/index.js')).clusterContract,
ServiceChains: (await import('./contracts/index.js')).serviceChainContract,
+ Deployments: (await import('./contracts/index.js')).deploymentContract,
Environments: (await import('./contracts/index.js')).environmentContract,
Logs: (await import('./contracts/index.js')).logContract,
PersonalAccessTokens: (await import('./contracts/index.js'))
diff --git a/packages/shared/src/contracts/deployment.ts b/packages/shared/src/contracts/deployment.ts
new file mode 100644
index 0000000000..556e96d899
--- /dev/null
+++ b/packages/shared/src/contracts/deployment.ts
@@ -0,0 +1,91 @@
+import type { ClientInferRequest } from '@ts-rest/core'
+import { z } from 'zod'
+import { apiPrefix, contractInstance } from '../api-client.js'
+import {
+ CreateDeploymentSchema,
+ DeploymentSchema,
+ UpdateDeploymentSchema,
+} from '../schemas/index.js'
+import { baseHeaders, ErrorSchema } from './_utils.js'
+
+export const deploymentContract = contractInstance.router({
+ createDeployment: {
+ method: 'POST',
+ path: '',
+ contentType: 'application/json',
+ summary: 'Create deployment',
+ description: 'Create new deployment.',
+ body: CreateDeploymentSchema,
+ responses: {
+ 201: DeploymentSchema,
+ 400: ErrorSchema,
+ 401: ErrorSchema,
+ 500: ErrorSchema,
+ },
+ },
+
+ listDeployments: {
+ method: 'GET',
+ path: '',
+ summary: 'Get deployments',
+ description: 'Retrieved project deployments.',
+ query: z.object({
+ projectId: z.string()
+ .uuid(),
+ }),
+ responses: {
+ 200: DeploymentSchema.array(),
+ 400: ErrorSchema,
+ 401: ErrorSchema,
+ 403: ErrorSchema,
+ 404: ErrorSchema,
+ 500: ErrorSchema,
+ },
+ },
+
+ updateDeployment: {
+ method: 'PUT',
+ path: `/:deploymentId`,
+ summary: 'Update deployment',
+ description: 'Update a deployment by its ID.',
+ pathParams: z.object({
+ deploymentId: z.string()
+ .uuid(),
+ }),
+ body: UpdateDeploymentSchema,
+ responses: {
+ 200: DeploymentSchema,
+ 400: ErrorSchema,
+ 401: ErrorSchema,
+ 403: ErrorSchema,
+ 404: ErrorSchema,
+ 500: ErrorSchema,
+ },
+ },
+
+ deleteDeployment: {
+ method: 'DELETE',
+ path: `/:deploymentId`,
+ summary: 'Delete deployment',
+ description: 'Delete a deployment by its ID.',
+ body: null,
+ pathParams: z.object({
+ deploymentId: z.string()
+ .uuid(),
+ }),
+ responses: {
+ 204: null,
+ 400: ErrorSchema,
+ 401: ErrorSchema,
+ 403: ErrorSchema,
+ 404: ErrorSchema,
+ 500: ErrorSchema,
+ },
+ },
+}, {
+ baseHeaders,
+ pathPrefix: `${apiPrefix}/deployments`,
+})
+
+export type CreateDeploymentBody = ClientInferRequest['body']
+export type UpdateDeploymentBody = ClientInferRequest['body']
diff --git a/packages/shared/src/contracts/index.ts b/packages/shared/src/contracts/index.ts
index 85488f73ac..c5c88fab16 100644
--- a/packages/shared/src/contracts/index.ts
+++ b/packages/shared/src/contracts/index.ts
@@ -1,6 +1,7 @@
export * from './admin-role.js'
export * from './admin-token.js'
export * from './cluster.js'
+export * from './deployment.js'
export * from './environment.js'
export * from './log.js'
export * from './personal-access-token.js'