mirror of
https://git.meshkee.com/Meshkee/backend.git
synced 2026-08-11 22:30:59 +04:30
Track real website deploy success/failure and support master branch.
Deploy agent waits for build completion, writes status, and checks out origin/HEAD (main or master) so empty-main repos like mashinify can deploy. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
co-authored by
Cursor
parent
acc8f35682
commit
f7cee26975
@@ -417,7 +417,7 @@ export class DomainAdminService {
|
||||
throw new BadRequestException('This domain has no storefront deploy configured');
|
||||
}
|
||||
|
||||
const markDeploy = async (status: 'started' | 'failed') => {
|
||||
const markDeploy = async (status: 'started' | 'success' | 'failed') => {
|
||||
const updated = await this.prisma.domain.update({
|
||||
where: { id: domainId },
|
||||
data: {
|
||||
@@ -428,28 +428,37 @@ export class DomainAdminService {
|
||||
return updated;
|
||||
};
|
||||
|
||||
await markDeploy('started');
|
||||
|
||||
try {
|
||||
await this.websiteDeployAgent.deploy(slug);
|
||||
const result = await this.websiteDeployAgent.deploy(slug, { wait: true });
|
||||
const updated = await markDeploy(
|
||||
result.status === 'success' || result.status === 'accepted'
|
||||
? 'success'
|
||||
: 'failed',
|
||||
);
|
||||
|
||||
return {
|
||||
status: 'ok' as const,
|
||||
slug,
|
||||
host: domain.host,
|
||||
message:
|
||||
result.detail?.trim() ||
|
||||
(updated.lastDeployStatus === 'success'
|
||||
? 'Deploy succeeded on websites server'
|
||||
: 'Deploy finished with unknown status'),
|
||||
lastDeployedAt: updated.lastDeployedAt?.toISOString() ?? null,
|
||||
lastDeployStatus: updated.lastDeployStatus,
|
||||
};
|
||||
} catch (err) {
|
||||
await markDeploy('failed');
|
||||
if (err instanceof ServiceUnavailableException) {
|
||||
throw err;
|
||||
}
|
||||
throw new ServiceUnavailableException(
|
||||
err instanceof Error ? err.message : 'Deploy failed to start',
|
||||
err instanceof Error ? err.message : 'Deploy failed',
|
||||
);
|
||||
}
|
||||
|
||||
const updated = await markDeploy('started');
|
||||
|
||||
return {
|
||||
status: 'accepted' as const,
|
||||
slug,
|
||||
host: domain.host,
|
||||
message: 'Deploy started on websites server',
|
||||
lastDeployedAt: updated.lastDeployedAt?.toISOString() ?? null,
|
||||
lastDeployStatus: updated.lastDeployStatus,
|
||||
};
|
||||
}
|
||||
|
||||
async update(domainIdRaw: string, dto: UpdateDomainAdminDto, actor: AuthUser) {
|
||||
|
||||
@@ -47,8 +47,9 @@ export class WebsiteDeployAgentService {
|
||||
return response.json().catch(() => ({ status: 'accepted' }));
|
||||
}
|
||||
|
||||
async deploy(slug: string) {
|
||||
async deploy(slug: string, options?: { wait?: boolean }) {
|
||||
const { deployUrl, token } = this.credentials();
|
||||
const wait = options?.wait !== false;
|
||||
|
||||
let response: Response;
|
||||
try {
|
||||
@@ -58,20 +59,43 @@ export class WebsiteDeployAgentService {
|
||||
'Content-Type': 'application/json',
|
||||
'X-Deploy-Token': token,
|
||||
},
|
||||
body: JSON.stringify({ slug }),
|
||||
body: JSON.stringify({ slug, wait }),
|
||||
signal: AbortSignal.timeout(15 * 60 * 1000),
|
||||
});
|
||||
} catch {
|
||||
} catch (err) {
|
||||
if (err instanceof Error && err.name === 'TimeoutError') {
|
||||
throw new ServiceUnavailableException(
|
||||
'Deploy timed out waiting for websites server (15m)',
|
||||
);
|
||||
}
|
||||
throw new ServiceUnavailableException('Could not reach website deploy agent');
|
||||
}
|
||||
|
||||
const text = await response.text().catch(() => '');
|
||||
let payload: {
|
||||
status?: string;
|
||||
slug?: string;
|
||||
detail?: string;
|
||||
error?: string;
|
||||
} = {};
|
||||
try {
|
||||
payload = text ? (JSON.parse(text) as typeof payload) : {};
|
||||
} catch {
|
||||
/* keep raw */
|
||||
}
|
||||
|
||||
if (!response.ok) {
|
||||
const text = await response.text().catch(() => '');
|
||||
const detail = payload.detail || payload.error || text;
|
||||
throw new ServiceUnavailableException(
|
||||
`Deploy agent rejected request (${response.status})${text ? `: ${text}` : ''}`,
|
||||
`Deploy failed (${response.status})${detail ? `: ${detail}` : ''}`,
|
||||
);
|
||||
}
|
||||
|
||||
return response.json().catch(() => ({ status: 'accepted', slug }));
|
||||
return {
|
||||
status: (payload.status as string) || (wait ? 'success' : 'accepted'),
|
||||
slug: payload.slug || slug,
|
||||
detail: payload.detail ?? null,
|
||||
};
|
||||
}
|
||||
|
||||
/** Issue / renew Let's Encrypt cert for a storefront host on the websites VM. */
|
||||
|
||||
Reference in New Issue
Block a user