fix(admin): filter non-container releases from deployments
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/push/woodpecker Pipeline was successful
This commit is contained in:
@@ -929,15 +929,25 @@ export class AppsService {
|
|||||||
? parseReleaseImageTags(release.imageTags).images
|
? parseReleaseImageTags(release.imageTags).images
|
||||||
: { [quickBuild!.component.name]: quickBuild!.image! };
|
: { [quickBuild!.component.name]: quickBuild!.image! };
|
||||||
const images = Object.fromEntries(
|
const images = Object.fromEntries(
|
||||||
Object.entries(releaseImages).filter(([componentName]) => (
|
Object.entries(releaseImages).filter(([componentName]) => {
|
||||||
app.components.find((component) => component.name === componentName)?.type !== 'DATABASE'
|
const componentType = app.components.find((component) => component.name === componentName)?.type;
|
||||||
)),
|
return componentType === 'CONTAINER' || componentType === 'STATIC_WEB';
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
const hasKubernetesWorkload = Object.keys(images).length > 0;
|
||||||
|
const isLauncherArtifactRelease = Boolean(
|
||||||
|
release
|
||||||
|
&& !hasKubernetesWorkload
|
||||||
|
&& body.updateLauncherAppVersion !== false
|
||||||
|
&& app.components.some((component) => component.type === 'ELECTRON')
|
||||||
|
&& hasReleaseArtifact(release.artifact, release.imageTags),
|
||||||
);
|
);
|
||||||
const deploymentLabel = release
|
const deploymentLabel = release
|
||||||
? `${app.name} ${release.version}`
|
? `${app.name} ${release.version}`
|
||||||
: `${app.name} ${quickBuild!.component.name} ${quickBuild!.commitSha?.slice(0, 7) ?? 'quick'}`;
|
: `${app.name} ${quickBuild!.component.name} ${quickBuild!.commitSha?.slice(0, 7) ?? 'quick'}`;
|
||||||
const requestedResources = body.resources;
|
const requestedResources = body.resources;
|
||||||
const runtimeProfile = await this.prisma.runtimeEnvProfile.findFirst({
|
const runtimeProfile = hasKubernetesWorkload
|
||||||
|
? await this.prisma.runtimeEnvProfile.findFirst({
|
||||||
where: {
|
where: {
|
||||||
appId: app.id,
|
appId: app.id,
|
||||||
environment,
|
environment,
|
||||||
@@ -949,17 +959,23 @@ export class AppsService {
|
|||||||
orderBy: { host: 'asc' },
|
orderBy: { host: 'asc' },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
if (Object.keys(images).length === 0) {
|
: null;
|
||||||
throw new BadRequestException('릴리즈에 배포 가능한 이미지가 없습니다.');
|
if (!hasKubernetesWorkload && !isLauncherArtifactRelease) {
|
||||||
|
if (release && hasReleaseArtifact(release.artifact, release.imageTags)) {
|
||||||
|
throw new BadRequestException('AppImage 릴리즈는 런처 앱 버전 업데이트를 선택해야 합니다.');
|
||||||
|
}
|
||||||
|
throw new BadRequestException('릴리즈에 배포 가능한 이미지 또는 AppImage 산출물이 없습니다.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (hasKubernetesWorkload) {
|
||||||
const namespaceExists = await this.namespaceExists(namespace);
|
const namespaceExists = await this.namespaceExists(namespace);
|
||||||
if (!namespaceExists) {
|
if (!namespaceExists) {
|
||||||
throw new BadRequestException(
|
throw new BadRequestException(
|
||||||
`${namespace} namespace가 없습니다. 런타임 구성에서 Namespace 생성/확인을 먼저 실행하세요.`,
|
`${namespace} namespace가 없습니다. 런타임 구성에서 Namespace 생성/확인을 먼저 실행하세요.`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const deploymentJob = await this.prisma.deploymentJob.create({
|
const deploymentJob = await this.prisma.deploymentJob.create({
|
||||||
data: {
|
data: {
|
||||||
@@ -975,6 +991,7 @@ export class AppsService {
|
|||||||
`[running] deployment started: ${deploymentLabel}`,
|
`[running] deployment started: ${deploymentLabel}`,
|
||||||
...(quickBuild ? [`[source] quick build ${quickBuild.id} ${quickBuild.image}`] : []),
|
...(quickBuild ? [`[source] quick build ${quickBuild.id} ${quickBuild.image}`] : []),
|
||||||
`[target] environment=${environment} namespace=${namespace}`,
|
`[target] environment=${environment} namespace=${namespace}`,
|
||||||
|
...(isLauncherArtifactRelease ? ['[launcher] AppImage release; Kubernetes rollout skipped'] : []),
|
||||||
].join('\n'),
|
].join('\n'),
|
||||||
},
|
},
|
||||||
include: {
|
include: {
|
||||||
@@ -3385,6 +3402,16 @@ function parseReleaseImageTags(value: Prisma.JsonValue | null) {
|
|||||||
return { images };
|
return { images };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function hasReleaseArtifact(artifact: string | null, imageTags: Prisma.JsonValue | null) {
|
||||||
|
if (artifact?.trim()) return true;
|
||||||
|
if (!imageTags || typeof imageTags !== 'object' || Array.isArray(imageTags)) return false;
|
||||||
|
|
||||||
|
const artifacts = (imageTags as Record<string, unknown>).artifacts;
|
||||||
|
if (!artifacts || typeof artifacts !== 'object' || Array.isArray(artifacts)) return false;
|
||||||
|
|
||||||
|
return Object.values(artifacts).some((value) => typeof value === 'string' && value.trim());
|
||||||
|
}
|
||||||
|
|
||||||
function getUsedReleaseBuildIds(releases: Array<{ imageTags: Prisma.JsonValue | null }>) {
|
function getUsedReleaseBuildIds(releases: Array<{ imageTags: Prisma.JsonValue | null }>) {
|
||||||
const ids = new Set<string>();
|
const ids = new Set<string>();
|
||||||
for (const release of releases) {
|
for (const release of releases) {
|
||||||
|
|||||||
Reference in New Issue
Block a user