From 5d0967947602cf5892ce3187f5e043b75501039a Mon Sep 17 00:00:00 2001 From: Fabio Gartenmann <137318798+artiphishle@users.noreply.github.com> Date: Tue, 22 Sep 2026 06:02:21 +0200 Subject: [PATCH 1/5] fix(ci): preserve self-hosted owner workflows --- src/owner/synchronizeRenovateOwnerAsync.ts | 27 +++++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/src/owner/synchronizeRenovateOwnerAsync.ts b/src/owner/synchronizeRenovateOwnerAsync.ts index 371f6f2a..87b79f6c 100644 --- a/src/owner/synchronizeRenovateOwnerAsync.ts +++ b/src/owner/synchronizeRenovateOwnerAsync.ts @@ -2,12 +2,17 @@ import { spawn } from 'node:child_process'; import { mkdir, readFile, writeFile } from 'node:fs/promises'; import { dirname, resolve } from 'node:path'; +import { resolveApmReleaseCommandAsync } from '../features/apm-release-validation/adapters/outbound/resolveApmReleaseCommandAsync.js'; +import { resolveStructureReleaseCommandAsync } from '../features/structure-descriptor-generation/adapters/outbound/resolveStructureReleaseCommandAsync.js'; import { applyBunRuntimePolicy } from '../policy/applyBunRuntimePolicy.js'; import { nodeRuntimePolicy } from '../policy/bunRuntimePolicy.js'; import { renderBunPolicyDocumentation } from '../policy/renderBunPolicyDocumentation.js'; import { readCurrentDoctorVersion } from '../tools/workflows/readCurrentDoctorVersion.js'; import { renderRenovateWorkflowAsync } from '../tools/workflows/renderRenovateWorkflowAsync.js'; -import { renderWorkflowAsync } from '../tools/workflows/renderWorkflowAsync.js'; +import { + renderWorkflowAsync, + type WorkflowPolicy, +} from '../tools/workflows/renderWorkflowAsync.js'; import type { BunPolicy } from '../types/bunPolicy.js'; /*** Synchronize or validate Renovate-owned Devtools policy artifacts. */ @@ -73,11 +78,7 @@ async function createManagedDefinitionsAsync( } const readme = await readFile(resolve(targetDirectory, 'README.md'), 'utf8'); - const workflowPolicy = { - bunVersion: policy.version, - doctorVersion: readCurrentDoctorVersion(), - nodeVersion: nodeRuntimePolicy.setupVersion, - }; + const workflowPolicy = await createWorkflowPolicyAsync(targetDirectory, policy); return [ { @@ -113,6 +114,20 @@ async function createManagedDefinitionsAsync( ]; } +/*** Build the self-hosted workflow policy used by Devtools owner synchronization. */ +async function createWorkflowPolicyAsync( + targetDirectory: string, + policy: BunPolicy, +): Promise { + return { + apmReleaseCommand: await resolveApmReleaseCommandAsync(targetDirectory), + structureReleaseCommand: await resolveStructureReleaseCommandAsync(targetDirectory), + bunVersion: policy.version, + doctorVersion: readCurrentDoctorVersion(), + nodeVersion: nodeRuntimePolicy.setupVersion, + }; +} + /*** Return owner-managed artifact paths whose current bytes differ from policy output. */ async function getOutdatedPathsAsync( targetDirectory: string, From 4550b2dae3a9af530a63ee5a9a8efc0d57a33cd8 Mon Sep 17 00:00:00 2001 From: Fabio Gartenmann <137318798+artiphishle@users.noreply.github.com> Date: Tue, 22 Sep 2026 06:02:24 +0200 Subject: [PATCH 2/5] test(ci): cover self-hosted owner workflows --- src/owner/synchronizeRenovateOwnerAsync.test.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/owner/synchronizeRenovateOwnerAsync.test.ts b/src/owner/synchronizeRenovateOwnerAsync.test.ts index f4470e47..6ab3e29f 100644 --- a/src/owner/synchronizeRenovateOwnerAsync.test.ts +++ b/src/owner/synchronizeRenovateOwnerAsync.test.ts @@ -38,7 +38,10 @@ describe('Devtools Renovate owner synchronization', () => { expect(first.readme).toContain('Bun runtime 1.4.2'); expect(first.readme).toContain('@types/bun ^1.4.1'); expect(first.ci).toContain("bun-version: '1.4.2'"); + expect(first.ci).toContain('node ./dist/cli/bin/apm-release.js validate . --allow-owner-code'); expect(first.release).toContain("bun-version: '1.4.2'"); + expect(first.release).toContain('node ./dist/cli/bin/apm-release.js sync .'); + expect(first.release).toContain('node ./dist/cli/bin/structure.js build .'); expect(first.renovate).toMatch(/changeset\.yml@[0-9a-f]{40}/u); expect(await readFile(unrelatedPath, 'utf8')).toBe('leave me alone\n'); From 63e989df3e0095ea660b15884028e55a38fe2bee Mon Sep 17 00:00:00 2001 From: Fabio Gartenmann <137318798+artiphishle@users.noreply.github.com> Date: Tue, 22 Sep 2026 06:02:35 +0200 Subject: [PATCH 3/5] fix(workflows): normalize rendered file endings --- src/tools/workflows/renderWorkflowAsync.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/tools/workflows/renderWorkflowAsync.ts b/src/tools/workflows/renderWorkflowAsync.ts index dcf3f890..0775c6cc 100644 --- a/src/tools/workflows/renderWorkflowAsync.ts +++ b/src/tools/workflows/renderWorkflowAsync.ts @@ -18,7 +18,7 @@ export interface WorkflowPolicy { /*** Renders one workflow template with the canonical runtime, Doctor, and Changesets policy. */ export async function renderWorkflowAsync(sourceUrl: URL, policy: WorkflowPolicy): Promise { const template = await readFile(sourceUrl, 'utf8'); - return template + const rendered = template .replaceAll(BUN_VERSION_TOKEN, policy.bunVersion) .replaceAll(PKGVIZ_AUDIT_STEPS_TOKEN, renderPkgvizAuditSteps(policy)) .replaceAll(CHANGESETS_PUBLISH_COMMAND_TOKEN, changesetsPolicy.workflowCommands.publish) @@ -34,6 +34,7 @@ export async function renderWorkflowAsync(sourceUrl: URL, policy: WorkflowPolicy policy.structureReleaseCommand ?? './node_modules/.bin/ankhorage-structure', ) .replaceAll(NODE_VERSION_TOKEN, policy.nodeVersion); + return `${rendered.trimEnd()}\n`; } const BUN_VERSION_TOKEN = '__ANKH_BUN_VERSION__'; From 21ca89e7b7487f13771f2129591269242831eaab Mon Sep 17 00:00:00 2001 From: Fabio Gartenmann <137318798+artiphishle@users.noreply.github.com> Date: Tue, 22 Sep 2026 06:02:50 +0200 Subject: [PATCH 4/5] test(workflows): require stable terminal newline --- src/tools/workflows/index.test.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/tools/workflows/index.test.ts b/src/tools/workflows/index.test.ts index 715604b7..60672b58 100644 --- a/src/tools/workflows/index.test.ts +++ b/src/tools/workflows/index.test.ts @@ -170,6 +170,8 @@ describe('managed PKGViz audit', () => { expect(ci).not.toContain('Enforce PKGViz cyclic-dependencies rule'); expect(ci).not.toContain('pkgviz-audit.json'); + expect(ci?.endsWith('\n')).toBe(true); + expect(ci?.endsWith('\n\n')).toBe(false); }); }); From 6b9b4e5790a3abd15bdbec238b7230502f0fef1d Mon Sep 17 00:00:00 2001 From: Fabio Gartenmann <137318798+artiphishle@users.noreply.github.com> Date: Tue, 22 Sep 2026 06:02:57 +0200 Subject: [PATCH 5/5] chore(changeset): document owner workflow fix --- .changeset/owner-workflow-generation.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/owner-workflow-generation.md diff --git a/.changeset/owner-workflow-generation.md b/.changeset/owner-workflow-generation.md new file mode 100644 index 00000000..e271ad83 --- /dev/null +++ b/.changeset/owner-workflow-generation.md @@ -0,0 +1,5 @@ +--- +'@ankhorage/devtools': patch +--- + +Keep Devtools owner-generated workflows self-hosted and normalize rendered workflow files to one terminal newline.