feat(hwlab): bootstrap v02 OpenFGA prerequisites

This commit is contained in:
Codex
2026-06-05 01:19:50 +00:00
parent 3875a8f08e
commit 56bf2dfa69
2 changed files with 407 additions and 12 deletions
+12
View File
@@ -48,6 +48,18 @@ assertCondition(
"v0.2 PR monitor help must expose the auto CI/CD lane, status query, latest-only CD, and dedupe comment state",
hwlabG14Help(),
);
assertCondition(
hwlabHelpUsage.some((line) => line.includes("secret status --lane v02 --name hwlab-v02-openfga"))
&& hwlabHelpUsage.some((line) => line.includes("secret ensure --lane v02 --name hwlab-v02-openfga --confirm")),
"v0.2 secret help must expose the controlled OpenFGA SecretRef bootstrap path",
hwlabHelpUsage,
);
assertCondition(
hwlabHelpUsage.some((line) => line.includes("upstream-image status --name openfga --tag v1.17.0"))
&& hwlabHelpUsage.some((line) => line.includes("upstream-image ensure --name openfga --tag v1.17.0 --confirm")),
"v0.2 help must expose the controlled OpenFGA upstream image mirroring path",
hwlabHelpUsage,
);
const v02CommentBody = v02PrAutomationCommentBody({
pr: {
+395 -12
View File
@@ -32,6 +32,12 @@ const V02_RUNTIME_PATH = "deploy/gitops/g14/runtime-v02";
const V02_RUNTIME_NAMESPACE = "hwlab-v02";
const V02_DEVICE_POD_API_KEY_SECRET = "hwlab-v02-device-pod-api-key";
const V02_DEVICE_POD_API_KEY_SECRET_KEY = "api-key";
const V02_OPENFGA_SECRET = "hwlab-v02-openfga";
const V02_OPENFGA_AUTHN_SECRET_KEY = "authn-preshared-key";
const V02_OPENFGA_DATASTORE_URI_SECRET_KEY = "datastore-uri";
const V02_OPENFGA_POSTGRES_PASSWORD_SECRET_KEY = "postgres-password";
const V02_OPENFGA_DB_NAME = "hwlab_openfga";
const V02_OPENFGA_DB_USER = "hwlab_openfga";
const V02_REGISTRY_PREFIX = "127.0.0.1:5000/hwlab";
const V02_BASE_IMAGE = "127.0.0.1:5000/hwlab/hwlab-node20-base:20-bookworm-slim";
const GIT_MIRROR_NAMESPACE = "devops-infra";
@@ -131,6 +137,15 @@ interface G14ToolsImageOptions {
timeoutSeconds: number;
}
interface G14UpstreamImageOptions {
action: "status" | "ensure";
name: "openfga";
tag: string;
dryRun: boolean;
confirm: boolean;
timeoutSeconds: number;
}
interface G14GitMirrorOptions {
action: "status" | "apply" | "sync" | "flush";
dryRun: boolean;
@@ -153,8 +168,9 @@ interface G14SecretOptions {
lane: "v02";
dryRun: boolean;
confirm: boolean;
name: typeof V02_DEVICE_POD_API_KEY_SECRET;
key: typeof V02_DEVICE_POD_API_KEY_SECRET_KEY;
name: typeof V02_DEVICE_POD_API_KEY_SECRET | typeof V02_OPENFGA_SECRET;
key?: typeof V02_DEVICE_POD_API_KEY_SECRET_KEY | typeof V02_OPENFGA_AUTHN_SECRET_KEY | typeof V02_OPENFGA_DATASTORE_URI_SECRET_KEY | typeof V02_OPENFGA_POSTGRES_PASSWORD_SECRET_KEY;
preset: "device-pod-api-key" | "openfga";
timeoutSeconds: number;
}
@@ -370,6 +386,28 @@ function parseToolsImageOptions(args: string[]): G14ToolsImageOptions {
};
}
function parseUpstreamImageOptions(args: string[]): G14UpstreamImageOptions {
const [actionRaw] = args;
if (actionRaw !== "status" && actionRaw !== "ensure") {
throw new Error("upstream-image usage: status|ensure --name openfga --tag v1.17.0 [--dry-run|--confirm]");
}
const name = optionValue(args, "--name") ?? "openfga";
if (name !== "openfga") throw new Error("upstream-image currently supports --name openfga");
const tag = optionValue(args, "--tag") ?? "v1.17.0";
if (tag !== "v1.17.0") throw new Error("upstream-image currently supports OpenFGA tag v1.17.0");
const confirm = args.includes("--confirm");
const explicitDryRun = args.includes("--dry-run");
if (confirm && explicitDryRun) throw new Error("upstream-image accepts only one of --confirm or --dry-run");
return {
action: actionRaw,
name,
tag,
confirm,
dryRun: actionRaw === "status" ? true : explicitDryRun || !confirm,
timeoutSeconds: positiveIntegerOption(args, "--timeout-seconds", 600, 1800),
};
}
function parseGitMirrorOptions(args: string[]): G14GitMirrorOptions {
const [actionRaw] = args;
if (actionRaw !== "status" && actionRaw !== "apply" && actionRaw !== "sync" && actionRaw !== "flush") {
@@ -411,14 +449,22 @@ function parseObservabilityOptions(args: string[]): G14ObservabilityOptions {
function parseSecretOptions(args: string[]): G14SecretOptions {
const [actionRaw] = args;
if (actionRaw !== "status" && actionRaw !== "ensure") {
throw new Error("secret usage: status|ensure --lane v02 --name hwlab-v02-device-pod-api-key --key api-key [--dry-run|--confirm]");
throw new Error("secret usage: status|ensure --lane v02 --name hwlab-v02-device-pod-api-key --key api-key | --name hwlab-v02-openfga [--dry-run|--confirm]");
}
const lane = optionValue(args, "--lane") ?? "v02";
if (lane !== "v02") throw new Error("secret currently supports --lane v02");
const name = optionValue(args, "--name") ?? V02_DEVICE_POD_API_KEY_SECRET;
if (name !== V02_DEVICE_POD_API_KEY_SECRET) throw new Error(`secret currently supports --name ${V02_DEVICE_POD_API_KEY_SECRET}`);
const key = optionValue(args, "--key") ?? V02_DEVICE_POD_API_KEY_SECRET_KEY;
if (key !== V02_DEVICE_POD_API_KEY_SECRET_KEY) throw new Error(`secret currently supports --key ${V02_DEVICE_POD_API_KEY_SECRET_KEY}`);
if (name !== V02_DEVICE_POD_API_KEY_SECRET && name !== V02_OPENFGA_SECRET) {
throw new Error(`secret currently supports --name ${V02_DEVICE_POD_API_KEY_SECRET} or ${V02_OPENFGA_SECRET}`);
}
const key = optionValue(args, "--key");
const preset = name === V02_OPENFGA_SECRET ? "openfga" : "device-pod-api-key";
if (preset === "device-pod-api-key") {
const effectiveKey = key ?? V02_DEVICE_POD_API_KEY_SECRET_KEY;
if (effectiveKey !== V02_DEVICE_POD_API_KEY_SECRET_KEY) throw new Error(`secret ${V02_DEVICE_POD_API_KEY_SECRET} supports --key ${V02_DEVICE_POD_API_KEY_SECRET_KEY}`);
} else if (key !== undefined && key !== V02_OPENFGA_AUTHN_SECRET_KEY && key !== V02_OPENFGA_DATASTORE_URI_SECRET_KEY && key !== V02_OPENFGA_POSTGRES_PASSWORD_SECRET_KEY) {
throw new Error(`secret ${V02_OPENFGA_SECRET} supports keys ${V02_OPENFGA_AUTHN_SECRET_KEY}, ${V02_OPENFGA_DATASTORE_URI_SECRET_KEY}, and ${V02_OPENFGA_POSTGRES_PASSWORD_SECRET_KEY}`);
}
const confirm = args.includes("--confirm");
const explicitDryRun = args.includes("--dry-run");
if (confirm && explicitDryRun) throw new Error("secret accepts only one of --confirm or --dry-run");
@@ -428,7 +474,8 @@ function parseSecretOptions(args: string[]): G14SecretOptions {
confirm,
dryRun: actionRaw === "status" ? true : explicitDryRun || !confirm,
name,
key,
key: preset === "device-pod-api-key" ? V02_DEVICE_POD_API_KEY_SECRET_KEY : key,
preset,
timeoutSeconds: positiveIntegerOption(args, "--timeout-seconds", 120, 600),
};
}
@@ -3193,6 +3240,8 @@ function runV02ControlPlane(options: G14ControlPlaneOptions): Record<string, unk
}
function v02SecretScript(options: G14SecretOptions): string {
if (options.preset === "openfga") return v02OpenFgaSecretScript(options);
const key = options.key ?? V02_DEVICE_POD_API_KEY_SECRET_KEY;
const emitAfterStatus = [
"after_exists=$(secret_exists_flag)",
"after_b64=$(secret_b64)",
@@ -3216,7 +3265,8 @@ function v02SecretScript(options: G14SecretOptions): string {
"set +e",
`namespace=${shellQuote(V02_RUNTIME_NAMESPACE)}`,
`name=${shellQuote(options.name)}`,
`key=${shellQuote(options.key)}`,
`key=${shellQuote(key)}`,
"preset=device-pod-api-key",
`action_request=${shellQuote(options.action)}`,
`dry_run=${shellQuote(options.dryRun ? "true" : "false")}`,
`field_manager=${shellQuote(V02_SECRET_FIELD_MANAGER)}`,
@@ -3253,8 +3303,219 @@ function v02SecretScript(options: G14SecretOptions): string {
].join("\n");
}
function v02OpenFgaSecretScript(options: G14SecretOptions): string {
const selectedKey = options.key ?? "";
return [
"set +e",
`namespace=${shellQuote(V02_RUNTIME_NAMESPACE)}`,
`name=${shellQuote(V02_OPENFGA_SECRET)}`,
`selected_key=${shellQuote(selectedKey)}`,
`authn_key=${shellQuote(V02_OPENFGA_AUTHN_SECRET_KEY)}`,
`datastore_uri_key=${shellQuote(V02_OPENFGA_DATASTORE_URI_SECRET_KEY)}`,
`postgres_password_key=${shellQuote(V02_OPENFGA_POSTGRES_PASSWORD_SECRET_KEY)}`,
`db_name=${shellQuote(V02_OPENFGA_DB_NAME)}`,
`db_user=${shellQuote(V02_OPENFGA_DB_USER)}`,
"db_host=hwlab-v02-postgres.hwlab-v02.svc.cluster.local",
`action_request=${shellQuote(options.action)}`,
`dry_run=${shellQuote(options.dryRun ? "true" : "false")}`,
`field_manager=${shellQuote(V02_SECRET_FIELD_MANAGER)}`,
"preset=openfga",
"secret_exists_flag() { kubectl -n \"$namespace\" get secret \"$name\" >/dev/null 2>&1 && printf yes || printf no; }",
"secret_b64_key() { kubectl -n \"$namespace\" get secret \"$name\" -o \"go-template={{ index .data \\\"$1\\\" }}\" 2>/dev/null || true; }",
"decoded_value() { if [ -n \"$1\" ]; then printf '%s' \"$1\" | base64 -d 2>/dev/null || true; fi; }",
"decoded_length() { if [ -n \"$1\" ]; then printf '%s' \"$1\" | base64 -d 2>/dev/null | wc -c | tr -d ' '; else printf '0'; fi; }",
"psql_scalar() { kubectl -n \"$namespace\" exec statefulset/hwlab-v02-postgres -c postgres -- env PGPASSWORD=\"$postgres_admin_password\" psql -U hwlab_v02 -d postgres -tAc \"$1\" 2>/dev/null | tr -d '[:space:]'; }",
"probe_db() {",
" role_result=unknown",
" database_result=unknown",
" probe_exit=missing-postgres-admin-secret",
" if [ -n \"$postgres_admin_password\" ]; then",
` role_result=$(psql_scalar "select exists(select 1 from pg_roles where rolname='${V02_OPENFGA_DB_USER}');")`,
" role_exit=$?",
` database_result=$(psql_scalar "select exists(select 1 from pg_database where datname='${V02_OPENFGA_DB_NAME}');")`,
" database_exit=$?",
" if [ \"$role_exit\" -eq 0 ] && [ \"$database_exit\" -eq 0 ]; then probe_exit=0; else probe_exit=$role_exit/$database_exit; fi",
" fi",
"}",
"before_exists=$(secret_exists_flag)",
"before_authn_b64=$(secret_b64_key \"$authn_key\")",
"before_uri_b64=$(secret_b64_key \"$datastore_uri_key\")",
"before_pg_password_b64=$(secret_b64_key \"$postgres_password_key\")",
"before_authn_present=$([ -n \"$before_authn_b64\" ] && printf yes || printf no)",
"before_uri_present=$([ -n \"$before_uri_b64\" ] && printf yes || printf no)",
"before_pg_password_present=$([ -n \"$before_pg_password_b64\" ] && printf yes || printf no)",
"before_authn_bytes=$(decoded_length \"$before_authn_b64\")",
"before_uri_bytes=$(decoded_length \"$before_uri_b64\")",
"before_pg_password_bytes=$(decoded_length \"$before_pg_password_b64\")",
"authn_value=$(decoded_value \"$before_authn_b64\")",
"datastore_uri=$(decoded_value \"$before_uri_b64\")",
"pg_password=$(decoded_value \"$before_pg_password_b64\")",
"postgres_admin_b64=$(kubectl -n \"$namespace\" get secret hwlab-v02-postgres -o 'go-template={{ index .data \"POSTGRES_PASSWORD\" }}' 2>/dev/null || true)",
"postgres_admin_present=$([ -n \"$postgres_admin_b64\" ] && printf yes || printf no)",
"postgres_admin_password=$(decoded_value \"$postgres_admin_b64\")",
"probe_db",
"db_role_exists_before=$role_result",
"db_database_exists_before=$database_result",
"db_probe_exit_before=$probe_exit",
"action=observed",
"mutation=false",
"apply_exit=",
"db_ensure_exit=",
"if [ \"$action_request\" = ensure ]; then",
" missing_secret=false",
" [ \"$before_authn_present\" = yes ] && [ \"$before_authn_bytes\" -gt 0 ] || missing_secret=true",
" [ \"$before_uri_present\" = yes ] && [ \"$before_uri_bytes\" -gt 0 ] || missing_secret=true",
" [ \"$before_pg_password_present\" = yes ] && [ \"$before_pg_password_bytes\" -gt 0 ] || missing_secret=true",
" missing_db=false",
" [ \"$db_role_exists_before\" = t ] || missing_db=true",
" [ \"$db_database_exists_before\" = t ] || missing_db=true",
" if [ \"$dry_run\" = true ]; then",
" if [ \"$missing_secret\" = true ] || [ \"$missing_db\" = true ]; then action=would-ensure; else action=kept; fi",
" elif ! command -v openssl >/dev/null 2>&1; then",
" action=openssl-missing",
" apply_exit=127",
" elif [ -z \"$postgres_admin_password\" ]; then",
" action=postgres-admin-secret-missing",
" apply_exit=44",
" else",
" [ -n \"$authn_value\" ] || authn_value=$(openssl rand -base64 48)",
" [ -n \"$pg_password\" ] || pg_password=$(openssl rand -hex 24)",
" [ -n \"$datastore_uri\" ] || datastore_uri=\"postgres://$db_user:$pg_password@$db_host:5432/$db_name?sslmode=disable\"",
" kubectl -n \"$namespace\" create secret generic \"$name\" --from-literal=\"$authn_key=$authn_value\" --from-literal=\"$datastore_uri_key=$datastore_uri\" --from-literal=\"$postgres_password_key=$pg_password\" --dry-run=client -o yaml | kubectl apply --server-side --force-conflicts --field-manager=\"$field_manager\" -f -",
" apply_exit=$?",
" if [ \"$apply_exit\" -eq 0 ]; then",
" kubectl -n \"$namespace\" exec -i statefulset/hwlab-v02-postgres -c postgres -- env PGPASSWORD=\"$postgres_admin_password\" psql -v ON_ERROR_STOP=1 -U hwlab_v02 -d postgres -v db_name=\"$db_name\" -v db_user=\"$db_user\" -v db_pass=\"$pg_password\" >/tmp/hwlab-openfga-psql.out 2>/tmp/hwlab-openfga-psql.err <<'SQL'",
"SELECT format('CREATE ROLE %I LOGIN PASSWORD %L', :'db_user', :'db_pass')",
"WHERE NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = :'db_user')",
"\\gexec",
"ALTER ROLE :\"db_user\" LOGIN PASSWORD :'db_pass';",
"SELECT format('CREATE DATABASE %I OWNER %I', :'db_name', :'db_user')",
"WHERE NOT EXISTS (SELECT 1 FROM pg_database WHERE datname = :'db_name')",
"\\gexec",
"ALTER DATABASE :\"db_name\" OWNER TO :\"db_user\";",
"SQL",
" db_ensure_exit=$?",
" if [ \"$db_ensure_exit\" -eq 0 ]; then action=ensured; mutation=true; else action=db-ensure-failed; fi",
" else",
" action=apply-failed",
" fi",
" fi",
"fi",
"after_exists=$(secret_exists_flag)",
"after_authn_b64=$(secret_b64_key \"$authn_key\")",
"after_uri_b64=$(secret_b64_key \"$datastore_uri_key\")",
"after_pg_password_b64=$(secret_b64_key \"$postgres_password_key\")",
"after_authn_present=$([ -n \"$after_authn_b64\" ] && printf yes || printf no)",
"after_uri_present=$([ -n \"$after_uri_b64\" ] && printf yes || printf no)",
"after_pg_password_present=$([ -n \"$after_pg_password_b64\" ] && printf yes || printf no)",
"after_authn_bytes=$(decoded_length \"$after_authn_b64\")",
"after_uri_bytes=$(decoded_length \"$after_uri_b64\")",
"after_pg_password_bytes=$(decoded_length \"$after_pg_password_b64\")",
"probe_db",
"db_role_exists_after=$role_result",
"db_database_exists_after=$database_result",
"db_probe_exit_after=$probe_exit",
"printf 'namespace\\t%s\\n' \"$namespace\"",
"printf 'secret\\t%s\\n' \"$name\"",
"printf 'key\\t%s\\n' \"$selected_key\"",
"printf 'preset\\t%s\\n' \"$preset\"",
"printf 'action\\t%s\\n' \"$action\"",
"printf 'dryRun\\t%s\\n' \"$dry_run\"",
"printf 'mutation\\t%s\\n' \"$mutation\"",
"printf 'beforeExists\\t%s\\n' \"$before_exists\"",
"printf 'beforeAuthnPresent\\t%s\\n' \"$before_authn_present\"",
"printf 'beforeAuthnBytes\\t%s\\n' \"$before_authn_bytes\"",
"printf 'beforeDatastoreUriPresent\\t%s\\n' \"$before_uri_present\"",
"printf 'beforeDatastoreUriBytes\\t%s\\n' \"$before_uri_bytes\"",
"printf 'beforePostgresPasswordPresent\\t%s\\n' \"$before_pg_password_present\"",
"printf 'beforePostgresPasswordBytes\\t%s\\n' \"$before_pg_password_bytes\"",
"printf 'afterExists\\t%s\\n' \"$after_exists\"",
"printf 'afterAuthnPresent\\t%s\\n' \"$after_authn_present\"",
"printf 'afterAuthnBytes\\t%s\\n' \"$after_authn_bytes\"",
"printf 'afterDatastoreUriPresent\\t%s\\n' \"$after_uri_present\"",
"printf 'afterDatastoreUriBytes\\t%s\\n' \"$after_uri_bytes\"",
"printf 'afterPostgresPasswordPresent\\t%s\\n' \"$after_pg_password_present\"",
"printf 'afterPostgresPasswordBytes\\t%s\\n' \"$after_pg_password_bytes\"",
"printf 'postgresAdminSecretPresent\\t%s\\n' \"$postgres_admin_present\"",
"printf 'dbName\\t%s\\n' \"$db_name\"",
"printf 'dbUser\\t%s\\n' \"$db_user\"",
"printf 'dbRoleExistsBefore\\t%s\\n' \"$db_role_exists_before\"",
"printf 'dbDatabaseExistsBefore\\t%s\\n' \"$db_database_exists_before\"",
"printf 'dbProbeExitCodeBefore\\t%s\\n' \"$db_probe_exit_before\"",
"printf 'dbRoleExistsAfter\\t%s\\n' \"$db_role_exists_after\"",
"printf 'dbDatabaseExistsAfter\\t%s\\n' \"$db_database_exists_after\"",
"printf 'dbProbeExitCodeAfter\\t%s\\n' \"$db_probe_exit_after\"",
"printf 'applyExitCode\\t%s\\n' \"$apply_exit\"",
"printf 'dbEnsureExitCode\\t%s\\n' \"$db_ensure_exit\"",
"authn_value=",
"datastore_uri=",
"pg_password=",
"postgres_admin_password=",
"if [ -n \"$apply_exit\" ] && [ \"$apply_exit\" != 0 ]; then exit \"$apply_exit\"; fi",
"if [ -n \"$db_ensure_exit\" ] && [ \"$db_ensure_exit\" != 0 ]; then exit \"$db_ensure_exit\"; fi",
].join("\n");
}
function v02SecretStatusFromText(text: string, commandOk: boolean, exitCode: number | null, stderr: string): Record<string, unknown> {
const fields = keyValueLinesFromText(text);
if (fields.preset === "openfga") {
const afterAuthnBytes = numericField(fields.afterAuthnBytes);
const afterUriBytes = numericField(fields.afterDatastoreUriBytes);
const afterPasswordBytes = numericField(fields.afterPostgresPasswordBytes);
const keysHealthy =
fields.afterExists === "yes" &&
fields.afterAuthnPresent === "yes" &&
fields.afterDatastoreUriPresent === "yes" &&
fields.afterPostgresPasswordPresent === "yes" &&
typeof afterAuthnBytes === "number" && afterAuthnBytes > 0 &&
typeof afterUriBytes === "number" && afterUriBytes > 0 &&
typeof afterPasswordBytes === "number" && afterPasswordBytes > 0;
const databaseHealthy = fields.dbRoleExistsAfter === "t" && fields.dbDatabaseExistsAfter === "t";
const healthy = keysHealthy && databaseHealthy;
return {
ok: commandOk && healthy,
namespace: fields.namespace || V02_RUNTIME_NAMESPACE,
secret: fields.secret || V02_OPENFGA_SECRET,
key: fields.key || null,
preset: "openfga",
action: fields.action || null,
dryRun: fields.dryRun === "true",
mutation: fields.mutation === "true",
before: {
exists: fields.beforeExists === "yes",
authnPresharedKey: { keyPresent: fields.beforeAuthnPresent === "yes", valueBytes: numericField(fields.beforeAuthnBytes) },
datastoreUri: { keyPresent: fields.beforeDatastoreUriPresent === "yes", valueBytes: numericField(fields.beforeDatastoreUriBytes) },
postgresPassword: { keyPresent: fields.beforePostgresPasswordPresent === "yes", valueBytes: numericField(fields.beforePostgresPasswordBytes) },
database: {
roleExists: fields.dbRoleExistsBefore || "unknown",
databaseExists: fields.dbDatabaseExistsBefore || "unknown",
probeExitCode: fields.dbProbeExitCodeBefore || null,
},
},
after: {
exists: fields.afterExists === "yes",
authnPresharedKey: { keyPresent: fields.afterAuthnPresent === "yes", valueBytes: afterAuthnBytes },
datastoreUri: { keyPresent: fields.afterDatastoreUriPresent === "yes", valueBytes: afterUriBytes },
postgresPassword: { keyPresent: fields.afterPostgresPasswordPresent === "yes", valueBytes: afterPasswordBytes },
database: {
roleExists: fields.dbRoleExistsAfter || "unknown",
databaseExists: fields.dbDatabaseExistsAfter || "unknown",
probeExitCode: fields.dbProbeExitCodeAfter || null,
},
},
postgresAdminSecretPresent: fields.postgresAdminSecretPresent === "yes",
dbName: fields.dbName || V02_OPENFGA_DB_NAME,
dbUser: fields.dbUser || V02_OPENFGA_DB_USER,
applyExitCode: numericField(fields.applyExitCode),
dbEnsureExitCode: numericField(fields.dbEnsureExitCode),
exitCode,
stderr: commandOk ? "" : stderr.trim().slice(0, 2000),
valuesRedacted: true,
summary: healthy
? `${fields.secret || V02_OPENFGA_SECRET} keys and Postgres database exist`
: `${fields.secret || V02_OPENFGA_SECRET} keys or Postgres database missing`,
};
}
const afterExists = fields.afterExists === "yes";
const afterKeyPresent = fields.afterKeyPresent === "yes";
const afterValueBytes = numericField(fields.afterValueBytes);
@@ -3299,7 +3560,8 @@ function runG14Secret(options: G14SecretOptions): Record<string, unknown> {
lane: options.lane,
namespace: V02_RUNTIME_NAMESPACE,
secret: options.name,
key: options.key,
key: options.key ?? null,
preset: options.preset,
mode: options.action === "status" ? "status" : options.dryRun ? "dry-run" : "confirmed-ensure",
status,
mutation: status.mutation === true,
@@ -3307,7 +3569,7 @@ function runG14Secret(options: G14SecretOptions): Record<string, unknown> {
valuesRedacted: true,
next: ok && options.action === "status"
? undefined
: { ensure: `bun scripts/cli.ts hwlab g14 secret ensure --lane v02 --name ${options.name} --key ${options.key} --confirm` },
: { ensure: `bun scripts/cli.ts hwlab g14 secret ensure --lane v02 --name ${options.name}${options.key ? ` --key ${options.key}` : ""} --confirm` },
};
}
@@ -4837,6 +5099,117 @@ function runG14ToolsImage(options: G14ToolsImageOptions): Record<string, unknown
return runG14ToolsImageBuild(options);
}
function g14UpstreamImageTarget(options: G14UpstreamImageOptions): string {
return `${V02_REGISTRY_PREFIX}/${options.name}:${options.tag}`;
}
function g14UpstreamImageSource(options: G14UpstreamImageOptions): string {
if (options.name === "openfga") return `docker.io/openfga/openfga:${options.tag}`;
return `${options.name}:${options.tag}`;
}
function runG14UpstreamImageStatus(options: G14UpstreamImageOptions): Record<string, unknown> {
const sourceImage = g14UpstreamImageSource(options);
const targetImage = g14UpstreamImageTarget(options);
const script = [
"set +e",
`source_image=${shellQuote(sourceImage)}`,
`target_image=${shellQuote(targetImage)}`,
`repo_path=${shellQuote(`hwlab/${options.name}`)}`,
`tag=${shellQuote(options.tag)}`,
"local_id=$(docker image inspect \"$target_image\" --format '{{.Id}}' 2>/dev/null || true)",
"local_created=$(docker image inspect \"$target_image\" --format '{{.Created}}' 2>/dev/null || true)",
"registry_tags=$(curl -fsS --max-time 10 \"http://127.0.0.1:5000/v2/$repo_path/tags/list\" 2>/dev/null || true)",
"registry_has_tag=false",
"if printf '%s' \"$registry_tags\" | grep -F '\"'$tag'\"' >/dev/null 2>&1; then registry_has_tag=true; fi",
"export source_image target_image local_id local_created registry_tags registry_has_tag",
"node <<'NODE'",
"const env = process.env;",
"console.log(JSON.stringify({",
" sourceImage: env.source_image,",
" targetImage: env.target_image,",
" localExists: Boolean(env.local_id),",
" localImageId: env.local_id || null,",
" localCreated: env.local_created || null,",
" registryHasTag: env.registry_has_tag === 'true',",
" registryTagsRaw: env.registry_tags || null",
"}, null, 2));",
"NODE",
].join("\n");
const result = g14HostScript(script, 120_000);
let parsedStatus: unknown = null;
const text = statusText(result);
if (text.length > 0) {
try {
parsedStatus = JSON.parse(text) as unknown;
} catch {
parsedStatus = null;
}
}
return {
ok: isCommandSuccess(result) && record(parsedStatus).registryHasTag === true,
command: "hwlab g14 upstream-image status --name openfga",
name: options.name,
tag: options.tag,
sourceImage,
targetImage,
status: parsedStatus ?? text,
result,
};
}
function runG14UpstreamImageEnsure(options: G14UpstreamImageOptions): Record<string, unknown> {
const sourceImage = g14UpstreamImageSource(options);
const targetImage = g14UpstreamImageTarget(options);
if (options.dryRun) {
return {
ok: true,
command: "hwlab g14 upstream-image ensure --name openfga",
mode: "dry-run",
name: options.name,
tag: options.tag,
sourceImage,
targetImage,
mutation: false,
next: { confirm: `bun scripts/cli.ts hwlab g14 upstream-image ensure --name ${options.name} --tag ${options.tag} --confirm` },
};
}
const script = [
"set -eu",
`source_image=${shellQuote(sourceImage)}`,
`target_image=${shellQuote(targetImage)}`,
"export HTTP_PROXY=http://127.0.0.1:10808 HTTPS_PROXY=http://127.0.0.1:10808 http_proxy=http://127.0.0.1:10808 https_proxy=http://127.0.0.1:10808",
"export NO_PROXY=localhost,127.0.0.1,::1,host.docker.internal,74.48.78.17,192.168.0.0/16,10.0.0.0/8,172.16.0.0/12,10.42.0.0/16,10.43.0.0/16,.svc,.svc.cluster.local,.cluster.local,kubernetes,kubernetes.default,kubernetes.default.svc,127.0.0.1:5000,localhost:5000",
"export no_proxy=$NO_PROXY",
"echo \"{\\\"phase\\\":\\\"pull\\\",\\\"sourceImage\\\":\\\"$source_image\\\"}\"",
"docker pull \"$source_image\"",
"docker tag \"$source_image\" \"$target_image\"",
"echo \"{\\\"phase\\\":\\\"push\\\",\\\"targetImage\\\":\\\"$target_image\\\"}\"",
"docker push \"$target_image\"",
"digest=$(docker image inspect \"$target_image\" --format '{{index .RepoDigests 0}}' 2>/dev/null || true)",
"echo \"{\\\"phase\\\":\\\"published\\\",\\\"targetImage\\\":\\\"$target_image\\\",\\\"digest\\\":\\\"$digest\\\"}\"",
].join("\n");
const result = g14HostScript(script, options.timeoutSeconds * 1000);
const status = runG14UpstreamImageStatus(options);
return {
ok: isCommandSuccess(result) && status.ok === true,
command: "hwlab g14 upstream-image ensure --name openfga",
mode: "confirmed-ensure",
name: options.name,
tag: options.tag,
sourceImage,
targetImage,
mutation: true,
result,
status,
};
}
function runG14UpstreamImage(options: G14UpstreamImageOptions): Record<string, unknown> {
if (options.action === "status") return runG14UpstreamImageStatus(options);
return runG14UpstreamImageEnsure(options);
}
function listOpenG14PullRequests(): CommandJsonResult {
return cliJson(["gh", "pr", "list", "--repo", HWLAB_REPO, "--state", "open", "--limit", "30", "--json", "number,title,state,url,head,base,draft,headRefName,baseRefName"], 60_000);
}
@@ -6167,6 +6540,9 @@ export function hwlabG14Help(): Record<string, unknown> {
"bun scripts/cli.ts hwlab g14 secret status --lane v02 --name hwlab-v02-device-pod-api-key --key api-key",
"bun scripts/cli.ts hwlab g14 secret ensure --lane v02 --name hwlab-v02-device-pod-api-key --key api-key --dry-run",
"bun scripts/cli.ts hwlab g14 secret ensure --lane v02 --name hwlab-v02-device-pod-api-key --key api-key --confirm",
"bun scripts/cli.ts hwlab g14 secret status --lane v02 --name hwlab-v02-openfga",
"bun scripts/cli.ts hwlab g14 secret ensure --lane v02 --name hwlab-v02-openfga --dry-run",
"bun scripts/cli.ts hwlab g14 secret ensure --lane v02 --name hwlab-v02-openfga --confirm",
"bun scripts/cli.ts hwlab g14 git-mirror status",
"bun scripts/cli.ts hwlab g14 git-mirror apply --confirm",
"bun scripts/cli.ts hwlab g14 git-mirror sync --confirm",
@@ -6179,9 +6555,12 @@ export function hwlabG14Help(): Record<string, unknown> {
"bun scripts/cli.ts hwlab g14 observability query --promql 'up{namespace=\"hwlab-v02\"}'",
"bun scripts/cli.ts hwlab g14 tools-image status --name ci-node-tools --tag node22-alpine-bun-v1",
"bun scripts/cli.ts hwlab g14 tools-image build --name ci-node-tools --tag node22-alpine-bun-v1 --confirm",
"bun scripts/cli.ts hwlab g14 upstream-image status --name openfga --tag v1.17.0",
"bun scripts/cli.ts hwlab g14 upstream-image ensure --name openfga --tag v1.17.0 --dry-run",
"bun scripts/cli.ts hwlab g14 upstream-image ensure --name openfga --tag v1.17.0 --confirm",
"bun scripts/cli.ts job status <jobId> --tail-bytes 30000",
],
description: "G14 HWLAB PR monitor, DEV rollout command, bounded v0.2 control-plane bootstrap/cleanup/runtime-migration helper, v0.2 runtime SecretRef bootstrap, devops-infra git mirror and observability maintenance, and controlled CI tools image build/status entry. The public monitor starts a fire-and-forget job. Default monitor lane is base=G14; --lane v02 monitors base=v0.2 PRs, waits for GitHub preflight/CI readiness, automatically merges ready PRs without waiting for other active v0.2 PipelineRuns, triggers v0.2 CD with latest-only GitOps writeback, flushes the git mirror when needed, and posts deduplicated PR comments for pending, blocked/conflict, success, superseded, failure, or timeout states. confirmed control-plane trigger-current and git-mirror sync/flush also return async jobs by default, with --wait reserved for explicit synchronous debugging. control-plane status/closeout/apply/cleanup-runs/cleanup-released-pvs/runtime-migration uses UniDesk G14:k3s routes for v0.2 Tekton/Argo control resources, runtime migration, historical PipelineRun/source-commit closeout verdicts, GitOps mirror flush state, and completed CI workspace retention only. secret status/ensure is the standard v0.2 runtime SecretRef bootstrap path; it never reads or prints secret values. git-mirror status/apply/sync/flush is the manual devops-infra mirror/relay control path and does not install a CronJob. observability status/apply/query owns the shared Prometheus Operator and Prometheus instance in devops-infra, while HWLAB lane manifests own only ServiceMonitor and PrometheusRule objects.",
description: "G14 HWLAB PR monitor, DEV rollout command, bounded v0.2 control-plane bootstrap/cleanup/runtime-migration helper, v0.2 runtime SecretRef bootstrap, devops-infra git mirror and observability maintenance, controlled CI tools image build/status entry, and allowlisted upstream image mirroring. The public monitor starts a fire-and-forget job. Default monitor lane is base=G14; --lane v02 monitors base=v0.2 PRs, waits for GitHub preflight/CI readiness, automatically merges ready PRs without waiting for other active v0.2 PipelineRuns, triggers v0.2 CD with latest-only GitOps writeback, flushes the git mirror when needed, and posts deduplicated PR comments for pending, blocked/conflict, success, superseded, failure, or timeout states. confirmed control-plane trigger-current and git-mirror sync/flush also return async jobs by default, with --wait reserved for explicit synchronous debugging. control-plane status/closeout/apply/cleanup-runs/cleanup-released-pvs/runtime-migration uses UniDesk G14:k3s routes for v0.2 Tekton/Argo control resources, runtime migration, historical PipelineRun/source-commit closeout verdicts, GitOps mirror flush state, and completed CI workspace retention only. secret status/ensure is the standard v0.2 runtime SecretRef bootstrap path; it never reads or prints secret values. upstream-image status/ensure only mirrors allowlisted upstream runtime images into the G14 local registry. git-mirror status/apply/sync/flush is the manual devops-infra mirror/relay control path and does not install a CronJob. observability status/apply/query owns the shared Prometheus Operator and Prometheus instance in devops-infra, while HWLAB lane manifests own only ServiceMonitor and PrometheusRule objects.",
defaults: {
repo: HWLAB_REPO,
base: G14_SOURCE_BRANCH,
@@ -6295,6 +6674,10 @@ export async function runHwlabG14Command(_config: Config, args: string[]): Promi
const options = parseToolsImageOptions(args.slice(1));
return runG14ToolsImage(options);
}
if (action === "upstream-image") {
const options = parseUpstreamImageOptions(args.slice(1));
return runG14UpstreamImage(options);
}
if (action === "git-mirror") {
const options = parseGitMirrorOptions(args.slice(1));
if ((options.action === "sync" || options.action === "flush") && options.confirm && !options.dryRun && !options.wait) {
@@ -6307,7 +6690,7 @@ export async function runHwlabG14Command(_config: Config, args: string[]): Promi
return runG14Observability(options);
}
if (action !== "monitor-prs") {
return { ok: false, command: `hwlab g14 ${action ?? ""}`.trim(), degradedReason: "unsupported-command", message: "supported commands: hwlab g14 monitor-prs, hwlab g14 record-rollout, hwlab g14 control-plane, hwlab g14 secret, hwlab g14 git-mirror, hwlab g14 observability, hwlab g14 tools-image" };
return { ok: false, command: `hwlab g14 ${action ?? ""}`.trim(), degradedReason: "unsupported-command", message: "supported commands: hwlab g14 monitor-prs, hwlab g14 record-rollout, hwlab g14 control-plane, hwlab g14 secret, hwlab g14 git-mirror, hwlab g14 observability, hwlab g14 tools-image, hwlab g14 upstream-image" };
}
const options = parseOptions(args.slice(1));
if (options.worker) return runMonitorWorker(options);