Skip to content

Commit

Permalink
feat(job): deploy other version for jobs and advanced settings (#435)
Browse files Browse the repository at this point in the history
  • Loading branch information
bdebon committed Jan 2, 2023
1 parent facc3bf commit 72e6a10
Show file tree
Hide file tree
Showing 41 changed files with 623 additions and 305 deletions.
48 changes: 43 additions & 5 deletions libs/domains/application/src/lib/slices/application.actions.ts
Expand Up @@ -7,7 +7,7 @@ import {
JobActionsApi,
JobMainCallsApi,
} from 'qovery-typescript-axios'
import { ServiceTypeEnum, isContainer, isJob } from '@qovery/shared/enums'
import { ServiceTypeEnum, isApplication, isContainer, isJob } from '@qovery/shared/enums'
import { ToastEnum, toast } from '@qovery/shared/toast'
import { fetchApplicationDeployments, fetchApplicationsStatus } from './applications.slice'

Expand Down Expand Up @@ -96,12 +96,20 @@ export const postApplicationActionsDeploy = createAsyncThunk<

export const postApplicationActionsDeployByCommitId = createAsyncThunk<
any,
{ environmentId: string; applicationId: string; git_commit_id: string }
{ environmentId: string; applicationId: string; git_commit_id: string; serviceType: ServiceTypeEnum }
>('applicationActions/deploy', async (data, { dispatch }) => {
try {
const response = await applicationActionApi.deployApplication(data.applicationId, {
git_commit_id: data.git_commit_id,
})
let response

if (isApplication(data.serviceType)) {
response = await applicationActionApi.deployApplication(data.applicationId, {
git_commit_id: data.git_commit_id,
})
} else {
response = await jobActionApi.deployJob(data.applicationId, false, {
git_commit_id: data.git_commit_id,
})
}

if (response.status === 202) {
// refetch status after update
Expand All @@ -116,6 +124,36 @@ export const postApplicationActionsDeployByCommitId = createAsyncThunk<
}
})

export const postApplicationActionsDeployByTag = createAsyncThunk<
any,
{ environmentId: string; applicationId: string; tag: string; serviceType: ServiceTypeEnum }
>('applicationActions/deploy', async (data, { dispatch }) => {
try {
let response

if (isContainer(data.serviceType)) {
response = await containerActionApi.deployContainer(data.applicationId, {
image_tag: data.tag,
})
} else {
response = await jobActionApi.deployJob(data.applicationId, false, {
image_tag: data.tag,
})
}

if (response.status === 202) {
// refetch status after update
await dispatch(fetchApplicationsStatus({ environmentId: data.environmentId }))
toast(ToastEnum.SUCCESS, `Your ${isJob(data.serviceType) ? 'job' : 'application'} is deploying`)
}

return response
} catch (err) {
// error message
return toast(ToastEnum.ERROR, 'Deploying error', (err as Error).message)
}
})

export const postApplicationActionsStop = createAsyncThunk<
any,
{ environmentId: string; applicationId: string; serviceType?: ServiceTypeEnum; withDeployments?: boolean }
Expand Down
94 changes: 60 additions & 34 deletions libs/domains/application/src/lib/slices/applications.slice.ts
Expand Up @@ -7,7 +7,6 @@ import {
createSlice,
} from '@reduxjs/toolkit'
import {
Application,
ApplicationAdvancedSettings,
ApplicationConfigurationApi,
ApplicationDeploymentHistoryApi,
Expand All @@ -23,20 +22,21 @@ import {
ContainerMainCallsApi,
ContainerMetricsApi,
ContainerRequest,
ContainerResponse,
ContainersApi,
DeploymentHistoryApplication,
Instance,
JobAdvancedSettings,
JobConfigurationApi,
JobDeploymentHistoryApi,
JobMainCallsApi,
JobRequest,
JobResponse,
JobsApi,
Link,
Status,
} from 'qovery-typescript-axios'
import { ServiceTypeEnum, isApplication, isContainer, isJob } from '@qovery/shared/enums'
import {
AdvancedSettings,
ApplicationEntity,
ApplicationsState,
ContainerApplicationEntity,
Expand Down Expand Up @@ -75,9 +75,10 @@ const containerConfigurationApi = new ContainerConfigurationApi()
const jobsApi = new JobsApi()
const jobMainCallsApi = new JobMainCallsApi()
const jobDeploymentsApi = new JobDeploymentHistoryApi()
const jobConfigurationApi = new JobConfigurationApi()

export const fetchApplications = createAsyncThunk<
Application[] | ContainerResponse[],
ApplicationEntity[],
{ environmentId: string; withoutStatus?: boolean }
>('applications/fetch', async (data, thunkApi) => {
const result = await Promise.all([
Expand Down Expand Up @@ -140,14 +141,17 @@ export const editApplication = createAsyncThunk(
const cloneJob = Object.assign({}, refactoJobPayload(payload.data as Partial<JobApplicationEntity>))
response = await jobMainCallsApi.editJob(payload.applicationId, cloneJob as JobRequest)
} else {
const cloneApplication = Object.assign({}, refactoGitApplicationPayload(payload.data))
const cloneApplication = Object.assign(
{},
refactoGitApplicationPayload(payload.data as Partial<GitApplicationEntity>)
)
response = await applicationMainCallsApi.editApplication(
payload.applicationId,
cloneApplication as ApplicationEditRequest
)
}

return response.data as Application
return response.data as ApplicationEntity
}
)

Expand All @@ -167,7 +171,7 @@ export const createApplication = createAsyncThunk(
response = await jobsApi.createJob(payload.environmentId, payload.data as JobRequest)
}

return response.data as Application | ContainerResponse | JobResponse
return response.data as ApplicationEntity
}
)

Expand Down Expand Up @@ -199,13 +203,19 @@ export const fetchApplicationInstances = createAsyncThunk<
return response.data.results as Instance[]
})

export const fetchApplicationCommits = createAsyncThunk<Commit[], { applicationId: string }>(
'application/commits',
async (data) => {
const response = await applicationMainCallsApi.listApplicationCommit(data.applicationId)
return response.data.results as Commit[]
export const fetchApplicationCommits = createAsyncThunk<
Commit[],
{ applicationId: string; serviceType: ServiceTypeEnum }
>('application/commits', async (data) => {
let response
if (isApplication(data.serviceType)) {
response = await applicationMainCallsApi.listApplicationCommit(data.applicationId)
} else {
response = await jobMainCallsApi.listJobCommit(data.applicationId)
}
)

return response.data.results as Commit[]
})

export const fetchApplicationDeployments = createAsyncThunk<
DeploymentHistoryApplication[],
Expand Down Expand Up @@ -245,17 +255,19 @@ export const fetchApplicationAdvancedSettings = createAsyncThunk<
let response
if (isContainer(data.serviceType)) {
response = await containerConfigurationApi.getContainerAdvancedSettings(data.applicationId)
} else if (isJob(data.serviceType)) {
response = await jobConfigurationApi.getJobAdvancedSettings(data.applicationId)
} else {
response = await applicationConfigurationApi.getAdvancedSettings(data.applicationId)
}
return response.data as ApplicationAdvancedSettings
})

export const editApplicationAdvancedSettings = createAsyncThunk<
ApplicationAdvancedSettings,
ApplicationAdvancedSettings | JobAdvancedSettings,
{
applicationId: string
settings: ApplicationAdvancedSettings | ContainerAdvancedSettings
settings: ApplicationAdvancedSettings | ContainerAdvancedSettings | JobAdvancedSettings
serviceType: ServiceTypeEnum
toasterCallback: () => void
}
Expand All @@ -266,6 +278,11 @@ export const editApplicationAdvancedSettings = createAsyncThunk<
data.applicationId,
data.settings as ContainerAdvancedSettings[]
)
} else if (isJob(data.serviceType)) {
response = await jobConfigurationApi.editJobAdvancedSettings(
data.applicationId,
data.settings as JobAdvancedSettings
)
} else {
response = await applicationConfigurationApi.editAdvancedSettings(
data.applicationId,
Expand All @@ -275,13 +292,23 @@ export const editApplicationAdvancedSettings = createAsyncThunk<
return response.data as ApplicationAdvancedSettings
})

export const fetchDefaultApplicationAdvancedSettings = createAsyncThunk<ApplicationAdvancedSettings>(
'application/defaultAdvancedSettings',
async () => {
const response = await applicationsApi.getDefaultApplicationAdvancedSettings()
return response.data as ApplicationAdvancedSettings
export const fetchDefaultApplicationAdvancedSettings = createAsyncThunk<
AdvancedSettings,
{
serviceType: ServiceTypeEnum
}
)
>('application/defaultAdvancedSettings', async (data) => {
let response

if (isApplication(data.serviceType) || isContainer(data.serviceType)) {
response = await applicationsApi.getDefaultApplicationAdvancedSettings()
} else if (isJob(data.serviceType)) {
response = await jobsApi.getDefaultJobAdvancedSettings()
} else {
response = { data: {} }
}
return response.data
})

export const initialApplicationsState: ApplicationsState = applicationsAdapter.getInitialState({
loadingStatus: 'not loaded',
Expand Down Expand Up @@ -345,7 +372,7 @@ export const applicationsSlice = createSlice({
state.loadingStatus = 'loading'
})
// fetch applications
.addCase(fetchApplications.fulfilled, (state: ApplicationsState, action: PayloadAction<Application[]>) => {
.addCase(fetchApplications.fulfilled, (state: ApplicationsState, action: PayloadAction<ApplicationEntity[]>) => {
applicationsAdapter.upsertMany(state, action.payload)
action.payload.forEach((app) => {
state.joinEnvApplication = addOneToManyRelation(app.environment?.id, app.id, { ...state.joinEnvApplication })
Expand All @@ -361,7 +388,7 @@ export const applicationsSlice = createSlice({
state.loadingStatus = 'loading'
})
.addCase(editApplication.fulfilled, (state: ApplicationsState, action) => {
const update: Update<Application> = {
const update: Update<ApplicationEntity> = {
id: action.meta.arg.applicationId,
changes: {
...action.payload,
Expand Down Expand Up @@ -420,7 +447,7 @@ export const applicationsSlice = createSlice({
},
})
)
applicationsAdapter.updateMany(state, update as Update<Application>[])
applicationsAdapter.updateMany(state, update as Update<ApplicationEntity>[])
state.statusLoadingStatus = 'loaded'
})
.addCase(fetchApplicationsStatus.rejected, (state: ApplicationsState, action) => {
Expand Down Expand Up @@ -539,8 +566,7 @@ export const applicationsSlice = createSlice({
changes: {
advanced_settings: {
loadingStatus: 'loading',
current_settings: (state.entities[applicationId] as GitApplicationEntity)?.advanced_settings
?.current_settings,
current_settings: state.entities[applicationId]?.advanced_settings?.current_settings,
},
},
}
Expand Down Expand Up @@ -574,11 +600,11 @@ export const applicationsSlice = createSlice({
changes: {
advanced_settings: {
loadingStatus: 'error',
current_settings: (state.entities[applicationId] as GitApplicationEntity)?.advanced_settings
?.current_settings,
current_settings: state.entities[applicationId]?.advanced_settings?.current_settings,
},
},
}

toast(
ToastEnum.ERROR,
`Your advanced settings have not been updated. Something must be wrong with the values provided`
Expand Down Expand Up @@ -634,7 +660,7 @@ export const applicationsSlice = createSlice({
},
},
}
applicationsAdapter.updateOne(state, update as Update<Application>)
applicationsAdapter.updateOne(state, update as Update<ApplicationEntity>)
})
.addCase(fetchApplicationDeployments.fulfilled, (state: ApplicationsState, action) => {
const update = {
Expand All @@ -646,7 +672,7 @@ export const applicationsSlice = createSlice({
},
},
}
applicationsAdapter.updateOne(state, update as Update<Application>)
applicationsAdapter.updateOne(state, update as Update<ApplicationEntity>)
})
.addCase(fetchApplicationDeployments.rejected, (state: ApplicationsState, action) => {
const update = {
Expand All @@ -657,7 +683,7 @@ export const applicationsSlice = createSlice({
},
},
}
applicationsAdapter.updateOne(state, update as Update<Application>)
applicationsAdapter.updateOne(state, update as Update<ApplicationEntity>)
})
// get application status
.addCase(fetchApplicationStatus.pending, (state: ApplicationsState, action) => {
Expand All @@ -669,7 +695,7 @@ export const applicationsSlice = createSlice({
},
},
}
applicationsAdapter.updateOne(state, update as Update<Application>)
applicationsAdapter.updateOne(state, update as Update<ApplicationEntity>)
})
.addCase(fetchApplicationStatus.fulfilled, (state: ApplicationsState, action) => {
const update = {
Expand All @@ -678,7 +704,7 @@ export const applicationsSlice = createSlice({
status: action.payload,
},
}
applicationsAdapter.updateOne(state, update as Update<Application>)
applicationsAdapter.updateOne(state, update as Update<ApplicationEntity>)
state.statusLoadingStatus = 'loaded'
})
.addCase(fetchApplicationStatus.rejected, (state: ApplicationsState, action) => {
Expand Down Expand Up @@ -712,7 +738,7 @@ export const selectApplicationsEntities = createSelector(getApplicationsState, s

export const selectApplicationsEntitiesByEnvId = (state: RootState, environmentId: string): ApplicationEntity[] => {
const appState = getApplicationsState(state)
return getEntitiesByIds<Application>(appState.entities, appState?.joinEnvApplication[environmentId])
return getEntitiesByIds<ApplicationEntity>(appState.entities, appState?.joinEnvApplication[environmentId])
}

export const selectApplicationById = (state: RootState, applicationId: string): ApplicationEntity | undefined =>
Expand Down
Expand Up @@ -3,30 +3,28 @@ import { useSelector } from 'react-redux'
import { useParams } from 'react-router-dom'
import { getApplicationsState, getCountNewCommitsToDeploy } from '@qovery/domains/application'
import { isJob } from '@qovery/shared/enums'
import { GitApplicationEntity, JobApplicationEntity, LoadingStatus } from '@qovery/shared/interfaces'
import { ApplicationEntity, LoadingStatus } from '@qovery/shared/interfaces'
import { RootState } from '@qovery/store'
import LastCommit from '../../ui/last-commit/last-commit'

export function LastCommitFeature() {
const { applicationId = '' } = useParams()
const commitDeltaCount = useSelector(getCountNewCommitsToDeploy(applicationId))
const application = useSelector<RootState, GitApplicationEntity | undefined>(
const application = useSelector<RootState, ApplicationEntity | undefined>(
(state) => getApplicationsState(state).entities[applicationId]
)

const getCommitById = (commits?: Commit[]) => {
const deployedCommitId = isJob(application)
? (application as JobApplicationEntity).source?.docker?.git_repository?.deployed_commit_id
? application?.source?.docker?.git_repository?.deployed_commit_id
: application?.git_repository?.deployed_commit_id

const deployedCommit = commits?.find((commit) => commit.git_commit_id === deployedCommitId)

if (deployedCommit) {
return deployedCommit
} else {
return isJob(application)
? (application as JobApplicationEntity).source?.docker?.git_repository
: application?.git_repository
return isJob(application) ? application?.source?.docker?.git_repository : application?.git_repository
}
}

Expand Down
@@ -1,7 +1,8 @@
import { ApplicationAdvancedSettings } from 'qovery-typescript-axios'
import { applicationFactoryMock } from '@qovery/domains/application'
import { getServiceType } from '@qovery/shared/enums'
import { ApplicationEntity } from '@qovery/shared/interfaces'
import { initFormValues } from './utils'
import { initFormValues } from './init-form-values'

const mockApplication: ApplicationEntity = applicationFactoryMock(1)[0]
const mockAdvancedSettings: Partial<ApplicationAdvancedSettings> = {
Expand All @@ -19,7 +20,8 @@ describe('InitFormValues', () => {
expect(
initFormValues(
['build.timeout_max_sec', 'deployment.custom_domain_check_enabled', 'liveness_probe.http_get.path'],
mockApplication
mockApplication,
getServiceType(mockApplication)
)
).toStrictEqual({
'build.timeout_max_sec': '60',
Expand Down

0 comments on commit 72e6a10

Please sign in to comment.