const unknownValue = "unknown"; export function normalizeIsoTimestamp(value) { const source = String(value ?? "").trim(); if (!source) return null; if (/^\d+$/u.test(source)) { const seconds = Number.parseInt(source, 10); if (Number.isSafeInteger(seconds)) { const date = new Date(seconds * 1000); if (Number.isFinite(date.getTime())) return date.toISOString(); } } const date = new Date(source); return Number.isFinite(date.getTime()) ? date.toISOString() : null; } export function imageTagFromReference(imageReference) { const source = String(imageReference ?? "").trim(); const slashIndex = source.lastIndexOf("/"); const colonIndex = source.lastIndexOf(":"); if (colonIndex <= slashIndex) return null; return source.slice(colonIndex + 1) || null; } export function shortRevision(value) { const source = String(value ?? "").trim(); return source.length >= 7 ? source.slice(0, 7) : source || unknownValue; } export function buildMetadataFromEnv(env = process.env, { serviceId = "hwlab-unknown", fallbackImageRepository = null } = {}) { const commitId = firstNonEmpty(env.HWLAB_COMMIT_ID, env.HWLAB_GIT_SHA, env.GIT_COMMIT) ?? unknownValue; const revision = firstNonEmpty(env.HWLAB_REVISION, commitId) ?? unknownValue; const fallbackRepository = fallbackImageRepository ?? `ghcr.io/pikastech/${serviceId}`; const imageReference = firstNonEmpty(env.HWLAB_IMAGE, `${fallbackRepository}:${shortRevision(commitId)}`) ?? unknownValue; const imageTag = firstNonEmpty(env.HWLAB_IMAGE_TAG, imageTagFromReference(imageReference), shortRevision(commitId)) ?? unknownValue; const buildCreatedAt = normalizeIsoTimestamp( firstNonEmpty(env.HWLAB_BUILD_CREATED_AT, env.HWLAB_IMAGE_CREATED_AT, env.SOURCE_DATE_EPOCH, env.BUILD_DATE) ); const buildSource = firstNonEmpty(env.HWLAB_BUILD_SOURCE, "runtime-env") ?? "runtime-env"; return { revision, commit: { id: commitId, source: buildSource }, image: { reference: imageReference, tag: imageTag, digest: firstNonEmpty(env.HWLAB_IMAGE_DIGEST, unknownValue) ?? unknownValue }, build: { createdAt: buildCreatedAt, source: buildSource, provenance: firstNonEmpty(env.HWLAB_BUILD_PROVENANCE, null), metadataSource: buildCreatedAt ? "runtime-env:HWLAB_BUILD_CREATED_AT" : "unavailable", unavailableReason: buildCreatedAt ? null : "HWLAB_BUILD_CREATED_AT missing from runtime environment" }, runtime: runtimeIdentityFromEnv(env) }; } export function runtimeIdentityFromEnv(env = process.env) { const runtimeMode = firstNonEmpty(env.HWLAB_RUNTIME_MODE, null); const bootRepo = firstNonEmpty(env.HWLAB_BOOT_REPO, null); const bootCommit = firstNonEmpty(env.HWLAB_BOOT_COMMIT, null); const bootSh = firstNonEmpty(env.HWLAB_BOOT_SH, null); const environmentImage = firstNonEmpty(env.HWLAB_ENVIRONMENT_IMAGE, null); const environmentDigest = firstNonEmpty(env.HWLAB_ENVIRONMENT_DIGEST, env.HWLAB_IMAGE_DIGEST, null); const environmentInputHash = firstNonEmpty(env.HWLAB_ENVIRONMENT_INPUT_HASH, null); const codeInputHash = firstNonEmpty(env.HWLAB_CODE_INPUT_HASH, null); const pod = runtimePodIdentityFromEnv(env); if (!runtimeMode && !bootRepo && !bootCommit && !bootSh && !environmentDigest && !pod) return null; return pruneUndefined({ mode: runtimeMode, environmentImage, environmentDigest, environmentInputHash, codeInputHash, pod, boot: pruneUndefined({ repo: bootRepo, commit: bootCommit, sh: bootSh }) }); } function runtimePodIdentityFromEnv(env = process.env) { const name = firstNonEmpty(env.HWLAB_RUNTIME_POD_NAME, env.POD_NAME, env.HOSTNAME, null); const namespace = firstNonEmpty(env.HWLAB_RUNTIME_NAMESPACE, env.POD_NAMESPACE, env.KUBERNETES_NAMESPACE, env.HWLAB_NAMESPACE, null); const container = firstNonEmpty(env.HWLAB_RUNTIME_CONTAINER, env.HWLAB_CONTAINER_NAME, null); const nodeName = firstNonEmpty(env.HWLAB_RUNTIME_NODE_NAME, env.NODE_NAME, null); if (!name && !namespace && !container && !nodeName) return null; return pruneUndefined({ name, namespace, container, nodeName }); } function firstNonEmpty(...values) { for (const value of values) { if (value === null || value === undefined) continue; const text = String(value).trim(); if (text) return text; } return null; } function pruneUndefined(value) { return Object.fromEntries(Object.entries(value).filter(([, item]) => item !== undefined && item !== null && item !== "")); }