fix: render pac history times from yaml timezone
This commit is contained in:
@@ -14,6 +14,9 @@ defaults:
|
||||
targetId: JD01
|
||||
consumerId: agentrun-jd01-v02
|
||||
|
||||
display:
|
||||
timeZone: Asia/Shanghai
|
||||
|
||||
release:
|
||||
version: v0.48.0
|
||||
manifestUrl: https://github.com/tektoncd/pipelines-as-code/releases/download/v0.48.0/release.k8s.yaml
|
||||
|
||||
@@ -265,6 +265,17 @@ const cp = require('node:child_process');
|
||||
const limit = Math.max(1, Math.min(50, Number.parseInt(process.env.UNIDESK_PAC_HISTORY_LIMIT || '5', 10) || 5));
|
||||
const detailId = process.env.UNIDESK_PAC_HISTORY_ID || '';
|
||||
const consumers = JSON.parse(Buffer.from(process.env.UNIDESK_PAC_HISTORY_CONSUMERS_B64 || 'W10=', 'base64').toString('utf8'));
|
||||
const displayTimeZone = process.env.UNIDESK_PAC_DISPLAY_TIME_ZONE || 'UTC';
|
||||
const displayTimeFormatter = new Intl.DateTimeFormat('sv-SE', {
|
||||
timeZone: displayTimeZone,
|
||||
year: 'numeric',
|
||||
month: '2-digit',
|
||||
day: '2-digit',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
second: '2-digit',
|
||||
hour12: false,
|
||||
});
|
||||
|
||||
function kubectlJson(args, fallback) {
|
||||
try {
|
||||
@@ -293,6 +304,13 @@ function durationSeconds(start, done) {
|
||||
return Math.max(0, Math.round((doneMs - startMs) / 1000));
|
||||
}
|
||||
|
||||
function formatDisplayTime(value) {
|
||||
if (!value) return null;
|
||||
const date = new Date(value);
|
||||
if (!Number.isFinite(date.getTime())) return null;
|
||||
return displayTimeFormatter.format(date);
|
||||
}
|
||||
|
||||
function mapParams(params) {
|
||||
const out = {};
|
||||
for (const item of params || []) {
|
||||
@@ -435,6 +453,10 @@ function rowFor(consumer, item, taskRuns) {
|
||||
triggeredAt: item.metadata?.creationTimestamp || item.status?.startTime || null,
|
||||
startTime: item.status?.startTime || null,
|
||||
completionTime: item.status?.completionTime || null,
|
||||
displayTime: formatDisplayTime(item.metadata?.creationTimestamp || item.status?.startTime || null),
|
||||
displayStartTime: formatDisplayTime(item.status?.startTime || null),
|
||||
displayCompletionTime: formatDisplayTime(item.status?.completionTime || null),
|
||||
displayTimeZone,
|
||||
durationSeconds: durationSeconds(item.status?.startTime || item.metadata?.creationTimestamp, item.status?.completionTime),
|
||||
status: c.status || null,
|
||||
reason: c.reason || null,
|
||||
@@ -650,7 +672,7 @@ history_action() {
|
||||
history=$(history_rows)
|
||||
rows=$(printf '%s' "$history" | node -e 'const fs=require("fs"); const h=JSON.parse(fs.readFileSync(0,"utf8")||"{}"); process.stdout.write(JSON.stringify(h.rows||[]));')
|
||||
consumers=$(printf '%s' "$history" | node -e 'const fs=require("fs"); const h=JSON.parse(fs.readFileSync(0,"utf8")||"{}"); process.stdout.write(JSON.stringify(h.consumers||[]));')
|
||||
printf '{"ok":%s,"crdPresent":%s,"controllerReady":"%s","repositoryCondition":"%s","repository":{"name":"%s","repo":"%s/%s","url":"%s"},"consumer":"%s","consumerRows":%s,"rows":%s,"webhooks":%s,"source":"gitea-pac-tekton-live","historyStore":"none","valuesPrinted":false}\n' \
|
||||
printf '{"ok":%s,"crdPresent":%s,"controllerReady":"%s","repositoryCondition":"%s","repository":{"name":"%s","repo":"%s/%s","url":"%s"},"consumer":"%s","display":{"timeZone":"%s"},"consumerRows":%s,"rows":%s,"webhooks":%s,"source":"gitea-pac-tekton-live","historyStore":"none","valuesPrinted":false}\n' \
|
||||
"$( [ -n "$crd" ] && [ "$controller_ready" != "0/0" ] && echo true || echo false )" \
|
||||
"$( [ -n "$crd" ] && echo true || echo false )" \
|
||||
"$(json_string "$controller_ready")" \
|
||||
@@ -660,6 +682,7 @@ history_action() {
|
||||
"$(json_string "$UNIDESK_PAC_GITEA_REPO")" \
|
||||
"$(json_string "$UNIDESK_PAC_REPOSITORY_URL")" \
|
||||
"$(json_string "$UNIDESK_PAC_CONSUMER_ID")" \
|
||||
"$(json_string "$UNIDESK_PAC_DISPLAY_TIME_ZONE")" \
|
||||
"$consumers" "$rows" "$hooks"
|
||||
}
|
||||
|
||||
|
||||
@@ -50,6 +50,9 @@ interface PacConfig {
|
||||
targetId: string;
|
||||
consumerId: string;
|
||||
};
|
||||
display: {
|
||||
timeZone: string;
|
||||
};
|
||||
release: {
|
||||
version: string;
|
||||
manifestUrl: string;
|
||||
@@ -192,6 +195,7 @@ function readPacConfig(): PacConfig {
|
||||
const root = readYamlRecord<Record<string, unknown>>(configFile, "platform-infra-pipelines-as-code");
|
||||
const release = y.objectField(root, "release", "");
|
||||
const gitea = y.objectField(root, "gitea", "");
|
||||
const display = y.objectField(root, "display", "");
|
||||
const admin = y.objectField(gitea, "admin", "gitea");
|
||||
const webhook = y.objectField(gitea, "webhook", "gitea");
|
||||
const repositories = root.repositories === undefined
|
||||
@@ -214,6 +218,9 @@ function readPacConfig(): PacConfig {
|
||||
targetId: y.stringField(defaults, "targetId", "defaults"),
|
||||
consumerId: typeof defaults.consumerId === "string" && defaults.consumerId.length > 0 ? defaults.consumerId : consumers[0]?.id ?? "default",
|
||||
},
|
||||
display: {
|
||||
timeZone: y.stringField(display, "timeZone", "display"),
|
||||
},
|
||||
release: {
|
||||
version: y.stringField(release, "version", "release"),
|
||||
manifestUrl: urlField(release, "manifestUrl", "release"),
|
||||
@@ -313,6 +320,7 @@ function validateConfig(config: PacConfig): void {
|
||||
if (repository.namespace !== consumer.namespace) throw new Error(`${configLabel}.consumers.${consumer.id}.namespace must match repository namespace`);
|
||||
}
|
||||
if (!config.gitea.webhook.events.includes("push")) throw new Error(`${configLabel}.gitea.webhook.events must include push`);
|
||||
validateTimeZone(config.display.timeZone, `${configLabel}.display.timeZone`);
|
||||
}
|
||||
|
||||
function resolveTarget(config: PacConfig, targetId: string | null): PacTarget {
|
||||
@@ -426,6 +434,7 @@ async function history(config: UniDeskConfig, options: HistoryOptions): Promise<
|
||||
path: configLabel,
|
||||
source: "Gitea Repository CR + Tekton PipelineRun/TaskRun live objects; no UniDesk-owned history store is written.",
|
||||
limitPerConsumer: options.limit,
|
||||
displayTimeZone: pac.display.timeZone,
|
||||
valuesPrinted: false,
|
||||
},
|
||||
consumers: selectedConsumers.map((consumer) => consumer.id),
|
||||
@@ -497,6 +506,7 @@ function remoteScript(action: "apply" | "status" | "history" | "webhook-test", p
|
||||
UNIDESK_PAC_HISTORY_LIMIT: "limit" in options ? String(options.limit) : "5",
|
||||
UNIDESK_PAC_HISTORY_ID: "detailId" in options && options.detailId !== null ? options.detailId : "",
|
||||
UNIDESK_PAC_HISTORY_CONSUMERS_B64: Buffer.from(JSON.stringify(historyConsumers.map((item) => historyConsumerConfig(pac, item))), "utf8").toString("base64"),
|
||||
UNIDESK_PAC_DISPLAY_TIME_ZONE: pac.display.timeZone,
|
||||
UNIDESK_PAC_ARGO_NAMESPACE: consumer.argoNamespace,
|
||||
UNIDESK_PAC_ARGO_APPLICATION: consumer.argoApplication,
|
||||
UNIDESK_PAC_PART_OF: pacPartOf(consumer.id),
|
||||
@@ -642,6 +652,7 @@ function configSummary(pac: PacConfig, consumer: PacConsumer, repository: PacRep
|
||||
metadata: pac.metadata,
|
||||
release: pac.release,
|
||||
gitea: { configRef: pac.gitea.configRef, internalBaseUrl: pac.gitea.internalBaseUrl, webhookBranch: pac.gitea.webhook.branch },
|
||||
display: pac.display,
|
||||
repositories: pac.repositories.map(repositorySummary),
|
||||
consumers: pac.consumers,
|
||||
repository: repositorySummary(repository),
|
||||
@@ -657,6 +668,7 @@ function compactConfigSummary(pac: PacConfig, consumer: PacConsumer, repository:
|
||||
repository: repository.name,
|
||||
providerType: repository.providerType,
|
||||
sourceUrl: repository.cloneUrl,
|
||||
displayTimeZone: pac.display.timeZone,
|
||||
consumer: `${consumer.node}/${consumer.lane}`,
|
||||
consumerId: consumer.id,
|
||||
pipeline: consumer.pipeline,
|
||||
@@ -775,14 +787,15 @@ function renderHistory(result: Record<string, unknown>): RenderedCliResult {
|
||||
const rows = arrayRecords(result.rows);
|
||||
const config = record(result.config);
|
||||
const detailId = stringValue(result.detailId);
|
||||
const timeHeader = `TIME(${stringValue(config.displayTimeZone)})`;
|
||||
const lines = [
|
||||
"PLATFORM-INFRA PIPELINES-AS-CODE HISTORY",
|
||||
`DATA: ${stringValue(config.source)}`,
|
||||
`ROWS: ${stringValue(rows.length)} LIMIT_PER_CONSUMER: ${stringValue(config.limitPerConsumer)}`,
|
||||
"",
|
||||
"TRIGGERS",
|
||||
...(rows.length === 0 ? ["-"] : table(["TIME", "CONSUMER", "REPO", "STATUS", "DUR_S", "COMMIT", "ENV_REUSE", "ID"], rows.map((row) => [
|
||||
isoShort(stringValue(row.triggeredAt)),
|
||||
...(rows.length === 0 ? ["-"] : table([timeHeader, "CONSUMER", "REPO", "STATUS", "DUR_S", "COMMIT", "ENV_REUSE", "ID"], rows.map((row) => [
|
||||
stringValue(row.displayTime) === "-" ? isoShort(stringValue(row.triggeredAt)) : stringValue(row.displayTime),
|
||||
stringValue(row.consumer),
|
||||
stringValue(row.repo),
|
||||
statusText(row),
|
||||
@@ -920,6 +933,14 @@ function urlField(obj: Record<string, unknown>, key: string, path: string): stri
|
||||
return value.replace(/\/+$/u, "");
|
||||
}
|
||||
|
||||
function validateTimeZone(value: string, path: string): void {
|
||||
try {
|
||||
new Intl.DateTimeFormat("en-US", { timeZone: value }).format(new Date(0));
|
||||
} catch (error) {
|
||||
throw new Error(`${path} must be a valid IANA time zone: ${(error as Error).message}`);
|
||||
}
|
||||
}
|
||||
|
||||
function stringRecord(obj: Record<string, unknown>, path: string): Record<string, string> {
|
||||
const out: Record<string, string> = {};
|
||||
for (const [key, value] of Object.entries(obj)) {
|
||||
@@ -1001,8 +1022,8 @@ function renderHistoryDetail(row: Record<string, unknown>): string[] {
|
||||
["pipeline", stringValue(row.pipeline)],
|
||||
["branch", stringValue(row.branch)],
|
||||
["commit", stringValue(row.commit)],
|
||||
["started", stringValue(row.startTime)],
|
||||
["completed", stringValue(row.completionTime)],
|
||||
["started", stringValue(row.displayStartTime) === "-" ? stringValue(row.startTime) : stringValue(row.displayStartTime)],
|
||||
["completed", stringValue(row.displayCompletionTime) === "-" ? stringValue(row.completionTime) : stringValue(row.displayCompletionTime)],
|
||||
["taskRuns", stringValue(taskRuns.count)],
|
||||
["longestTask", stringValue(longest.name)],
|
||||
["longestTaskDurationS", stringValue(longest.durationSeconds)],
|
||||
|
||||
Reference in New Issue
Block a user