fix: pin chart to exact latest version at provision time, fix health check URL
Some checks failed
Build & Release / build (push) Has been cancelled

This commit is contained in:
Ryan Moon
2026-04-03 21:13:52 -05:00
parent 1910a18699
commit d0f520ee02
3 changed files with 25 additions and 7 deletions

View File

@@ -140,7 +140,7 @@ export async function customerRoutes(app: FastifyInstance) {
await createCustomerDnsRecord(slug);
await setStep("dns", "done");
addCustomerChart(slug, body.appVersion);
await addCustomerChart(slug, body.appVersion);
await setStep("chart", "done");
await db`UPDATE customers SET status = 'provisioned', updated_at = NOW() WHERE slug = ${slug}`;
@@ -299,7 +299,7 @@ export async function customerRoutes(app: FastifyInstance) {
const dbUrl = new URL(secrets["database-url"]);
await addCustomerToPool(slug, dbUrl.password);
addCustomerChart(slug, "*");
await addCustomerChart(slug, "*");
await db`UPDATE customers SET status = 'provisioned', updated_at = NOW() WHERE slug = ${slug}`;
app.log.info({ slug }, "customer reactivated");
return reply.code(200).send({ slug, status: "provisioned" });

View File

@@ -44,7 +44,7 @@ export async function getCustomerDnsRecord(slug: string): Promise<{ exists: bool
export async function checkCustomerHealth(slug: string): Promise<{ reachable: boolean; status: number | null }> {
try {
const res = await fetch(`https://${slug}.lunarfront.tech/health`, {
const res = await fetch(`https://${slug}.lunarfront.tech/api/health`, {
signal: AbortSignal.timeout(5000),
});
return { reachable: res.ok, status: res.status };

View File

@@ -4,6 +4,23 @@ import { tmpdir } from "os";
import { join } from "path";
import { config } from "../lib/config";
async function getLatestChartVersion(): Promise<string> {
const res = await fetch("https://api.digitalocean.com/v2/registry/lunarfront/repositories/lunarfront/tags?page=1&per_page=100", {
headers: { Authorization: `Bearer ${config.doToken}` },
});
const data = await res.json() as { tags: { tag: string }[] };
const versions = (data.tags ?? [])
.map(t => t.tag)
.filter(t => /^\d+\.\d+\.\d+$/.test(t))
.sort((a, b) => {
const [aMaj, aMin, aPat] = a.split(".").map(Number);
const [bMaj, bMin, bPat] = b.split(".").map(Number);
return bMaj - aMaj || bMin - aMin || bPat - aPat;
});
if (!versions.length) throw new Error("No chart versions found in DOCR");
return versions[0];
}
function withRepo<T>(fn: (dir: string, env: NodeJS.ProcessEnv) => T): T {
const keyPath = join(tmpdir(), `manager-ssh-key-${Date.now()}`);
const dir = join(tmpdir(), `lunarfront-charts-${Date.now()}`);
@@ -30,9 +47,10 @@ function withRepo<T>(fn: (dir: string, env: NodeJS.ProcessEnv) => T): T {
}
}
export function addCustomerChart(slug: string, appVersion: string) {
export async function addCustomerChart(slug: string, appVersion: string) {
const version = (appVersion === "*" || appVersion === "latest") ? await getLatestChartVersion() : appVersion;
withRepo((dir, env) => {
const manifest = buildArgoCDApp(slug, appVersion);
const manifest = buildArgoCDApp(slug, version);
writeFileSync(join(dir, "customers", `${slug}.yaml`), manifest);
execSync(`git -C ${dir} add customers/${slug}.yaml`, { env });
execSync(`git -C ${dir} commit -m "feat: provision customer ${slug}"`, { env });
@@ -50,8 +68,8 @@ export function removeCustomerChart(slug: string) {
});
}
function buildArgoCDApp(slug: string, appVersion: string): string {
const revision = appVersion === "*" || appVersion === "latest" ? ">=0.0.1" : appVersion;
function buildArgoCDApp(slug: string, version: string): string {
const revision = version;
return `apiVersion: argoproj.io/v1alpha1
kind: Application
metadata: