read launcher build version from package json
This commit is contained in:
+4
-2
@@ -88,11 +88,13 @@ export class CreateLauncherBuildJobDto {
|
||||
@IsString()
|
||||
commitSha?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
version!: string;
|
||||
version?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
artifact!: string;
|
||||
artifact?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
|
||||
@@ -3,7 +3,8 @@ import { ConfigService } from '@nestjs/config';
|
||||
import { exec } from 'node:child_process';
|
||||
import { createHash } from 'node:crypto';
|
||||
import { createReadStream } from 'node:fs';
|
||||
import { copyFile, mkdir, rm, stat } from 'node:fs/promises';
|
||||
import { copyFile, mkdir, readFile, rm, stat } from 'node:fs/promises';
|
||||
import { basename } from 'node:path';
|
||||
import { promisify } from 'node:util';
|
||||
import { PutObjectCommand, S3Client } from '@aws-sdk/client-s3';
|
||||
|
||||
@@ -764,11 +765,12 @@ export class LauncherService {
|
||||
}
|
||||
|
||||
async createBuildJob(body: CreateLauncherBuildJobDto) {
|
||||
if (!body.version?.trim()) throw new BadRequestException('버전을 입력하세요.');
|
||||
if (!body.artifact?.trim()) throw new BadRequestException('산출물 파일명을 입력하세요.');
|
||||
const source = await this.getSourceSettings();
|
||||
const target = body.target?.trim() || 'launcher-client';
|
||||
const isBackend = target === 'launcher-backend';
|
||||
if (isBackend && !body.artifact?.trim()) throw new BadRequestException('이미지 이름을 입력하세요.');
|
||||
const requestedVersion = body.version?.trim() || 'package-json';
|
||||
const requestedArtifact = body.artifact?.trim() || 'autonomy-studio-launcher.deb';
|
||||
const repository = body.repository
|
||||
? normalizeRepository(body.repository)
|
||||
: isBackend
|
||||
@@ -777,20 +779,21 @@ export class LauncherService {
|
||||
const branch = body.branch?.trim() || (isBackend ? source.backend.branch : source.branch) || 'release';
|
||||
const commitSha = body.commitSha?.trim() || (isBackend ? source.backend.commitSha : source.commitSha) || null;
|
||||
const plan = isBackend
|
||||
? this.createLauncherBackendImagePlan(body.version.trim(), body.artifact.trim(), body.uploadPath?.trim(), body.downloadUrl?.trim())
|
||||
: this.createLauncherArtifactPlan(body.version.trim(), branch, commitSha, body.artifact.trim(), body.uploadPath?.trim(), body.downloadUrl?.trim());
|
||||
? this.createLauncherBackendImagePlan(requestedVersion, requestedArtifact, body.uploadPath?.trim(), body.downloadUrl?.trim())
|
||||
: this.createLauncherArtifactPlan(requestedVersion, branch, commitSha, requestedArtifact, body.uploadPath?.trim(), body.downloadUrl?.trim());
|
||||
if (!repository) throw new BadRequestException('소스 저장소가 연결되지 않았습니다.');
|
||||
if (!plan.uploadPath) throw new BadRequestException(isBackend ? 'Dockerfile 경로를 입력하세요.' : '업로드 경로를 입력하세요.');
|
||||
if (!plan.downloadUrl) throw new BadRequestException(isBackend ? '이미지 태그를 입력하세요.' : '다운로드 URL을 입력하세요.');
|
||||
|
||||
const logs = [
|
||||
`[queued] launcher build created: ${body.artifact.trim()}`,
|
||||
`[queued] launcher build created: ${requestedArtifact}`,
|
||||
`[target] ${target}`,
|
||||
repository ? `[plan] clone ${this.toCloneUrl(repository)}` : '[plan] source repository is not linked',
|
||||
`[plan] checkout branch ${branch}`,
|
||||
commitSha ? `[plan] checkout commit ${commitSha}` : '[plan] use branch latest commit',
|
||||
isBackend ? `[plan] build and push image ${plan.downloadUrl}` : `[plan] build deb package`,
|
||||
isBackend ? `[plan] dockerfile ${plan.uploadPath}` : `[plan] upload ${body.artifact.trim()} to ${plan.uploadPath}`,
|
||||
isBackend ? `[plan] dockerfile ${plan.uploadPath}` : `[plan] upload ${requestedArtifact} to ${plan.uploadPath}`,
|
||||
'[plan] final version will be read from package.json after clone',
|
||||
isBackend ? `[plan] image tag ${plan.downloadUrl}` : `[plan] publish download url ${plan.downloadUrl}`,
|
||||
'[pending] waiting for launcher build runner',
|
||||
].join('\n');
|
||||
@@ -801,8 +804,8 @@ export class LauncherService {
|
||||
repository,
|
||||
branch,
|
||||
commitSha,
|
||||
version: body.version.trim(),
|
||||
artifact: body.artifact.trim(),
|
||||
version: requestedVersion,
|
||||
artifact: requestedArtifact,
|
||||
uploadPath: plan.uploadPath,
|
||||
downloadUrl: plan.downloadUrl,
|
||||
logs,
|
||||
@@ -871,10 +874,17 @@ export class LauncherService {
|
||||
}
|
||||
|
||||
if (job.target === 'launcher-backend') {
|
||||
const packageVersion = (await this.readPackageVersion(workDir)) || job.version;
|
||||
const dockerfile = job.uploadPath || 'Dockerfile';
|
||||
const imageTag = job.downloadUrl || job.artifact;
|
||||
const imagePlan = this.createLauncherBackendImagePlan(packageVersion, job.artifact, dockerfile);
|
||||
const imageTag = imagePlan.downloadUrl;
|
||||
await append(`[backend] package version ${packageVersion}`);
|
||||
await append(`[backend] dockerfile ${dockerfile}`);
|
||||
await append(`[backend] image ${imageTag}`);
|
||||
await this.prisma.launcherBuildJob.update({
|
||||
where: { id: jobId },
|
||||
data: { version: packageVersion, uploadPath: dockerfile, downloadUrl: imageTag },
|
||||
});
|
||||
await runCommand(
|
||||
`docker build -t ${quote(imageTag)} -f ${quote(dockerfile)} .`,
|
||||
workDir,
|
||||
@@ -888,6 +898,9 @@ export class LauncherService {
|
||||
data: {
|
||||
status: 'SUCCEEDED',
|
||||
finishedAt: new Date(),
|
||||
version: packageVersion,
|
||||
uploadPath: dockerfile,
|
||||
downloadUrl: imageTag,
|
||||
logs,
|
||||
},
|
||||
});
|
||||
@@ -901,10 +914,35 @@ export class LauncherService {
|
||||
const debPath = stdout.trim().split('\n').filter(Boolean)[0];
|
||||
if (!debPath) throw new Error('.deb 산출물을 찾지 못했습니다.');
|
||||
|
||||
const uploadedUrl = await this.uploadLauncherArtifactIfConfigured(job, debPath, append);
|
||||
const packageVersion = (await this.readPackageVersion(workDir)) || job.version;
|
||||
const artifactName = basename(debPath);
|
||||
const artifactPlan = this.createLauncherArtifactPlan(packageVersion, job.branch, job.commitSha, artifactName, job.uploadPath, job.downloadUrl);
|
||||
const finalJob = {
|
||||
version: packageVersion,
|
||||
branch: job.branch,
|
||||
commitSha: job.commitSha,
|
||||
artifact: artifactName,
|
||||
uploadPath: artifactPlan.uploadPath,
|
||||
};
|
||||
await append(
|
||||
`[artifact] package version ${packageVersion}`,
|
||||
`[artifact] found ${artifactName}`,
|
||||
`[artifact] upload key ${artifactPlan.uploadPath}`,
|
||||
);
|
||||
await this.prisma.launcherBuildJob.update({
|
||||
where: { id: jobId },
|
||||
data: {
|
||||
version: packageVersion,
|
||||
artifact: artifactName,
|
||||
uploadPath: artifactPlan.uploadPath,
|
||||
downloadUrl: artifactPlan.downloadUrl,
|
||||
},
|
||||
});
|
||||
|
||||
const uploadedUrl = await this.uploadLauncherArtifactIfConfigured(finalJob, debPath, append);
|
||||
if (!uploadedUrl) {
|
||||
await mkdir(job.uploadPath, { recursive: true });
|
||||
const destination = `${job.uploadPath.replace(/\/$/, '')}/${job.artifact}`;
|
||||
await mkdir(artifactPlan.uploadPath, { recursive: true });
|
||||
const destination = `${artifactPlan.uploadPath.replace(/\/$/, '')}/${artifactName}`;
|
||||
await copyFile(debPath, destination);
|
||||
await append(`[upload] ${destination}`);
|
||||
}
|
||||
@@ -915,8 +953,11 @@ export class LauncherService {
|
||||
data: {
|
||||
status: 'SUCCEEDED',
|
||||
finishedAt: new Date(),
|
||||
version: packageVersion,
|
||||
artifact: artifactName,
|
||||
uploadPath: artifactPlan.uploadPath,
|
||||
downloadUrl: uploadedUrl || artifactPlan.downloadUrl,
|
||||
logs,
|
||||
...(uploadedUrl ? { downloadUrl: uploadedUrl } : {}),
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
@@ -1092,6 +1133,18 @@ export class LauncherService {
|
||||
return this.r2Client;
|
||||
}
|
||||
|
||||
private async readPackageVersion(workDir: string) {
|
||||
try {
|
||||
const packageJson = await readFile(`${workDir}/package.json`, 'utf8');
|
||||
const parsed = JSON.parse(packageJson) as { version?: unknown };
|
||||
return typeof parsed.version === 'string' && parsed.version.trim()
|
||||
? parsed.version.trim()
|
||||
: null;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private createLauncherArtifactObjectKey(version: string, branch: string, commitSha: string | null, artifact: string) {
|
||||
const prefix = this.configService.get<string>('R2_ARTIFACT_PREFIX', 'studio-artifacts');
|
||||
const revision = commitSha?.slice(0, 7) || 'latest';
|
||||
|
||||
Reference in New Issue
Block a user