@ankhorage/devtools 1.6.1 → 1.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -4
- package/dist/cli/index.d.ts +2 -2
- package/dist/internal/readmeDocs.js +8 -0
- package/dist/owner/synchronizeRenovateOwnerAsync.d.ts +6 -0
- package/dist/owner/synchronizeRenovateOwnerAsync.js +153 -0
- package/dist/policy/applyBunRuntimePolicy.d.ts +4 -0
- package/dist/policy/applyBunRuntimePolicy.js +15 -0
- package/dist/policy/bunRuntimePolicy.d.ts +0 -6
- package/dist/policy/bunRuntimePolicy.js +4 -3
- package/dist/tools/package/index.js +10 -15
- package/dist/tools/workflows/files/ci.yml +4 -3
- package/dist/tools/workflows/files/renovate.yml +21 -0
- package/dist/tools/workflows/index.d.ts +1 -1
- package/dist/tools/workflows/index.js +6 -9
- package/dist/tools/workflows/renderWorkflowAsync.d.ts +4 -0
- package/dist/tools/workflows/renderWorkflowAsync.js +9 -0
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -101,7 +101,7 @@ The synchronized package scripts are:
|
|
|
101
101
|
"lint:fix": "ankhorage-eslint . --fix --max-warnings=0",
|
|
102
102
|
"format": "ankhorage-prettier --write .",
|
|
103
103
|
"format:check": "ankhorage-prettier --check .",
|
|
104
|
-
"knip": "ankhorage-knip"
|
|
104
|
+
"knip:check": "ankhorage-knip"
|
|
105
105
|
}
|
|
106
106
|
}
|
|
107
107
|
```
|
|
@@ -258,13 +258,17 @@ export default createKnipConfig();
|
|
|
258
258
|
|
|
259
259
|
The canonical Bun policy is defined once in devtools and consumed by both package and workflow synchronization. The current policy is:
|
|
260
260
|
|
|
261
|
+
<!-- devtools-bun-policy:start -->
|
|
262
|
+
|
|
261
263
|
```text
|
|
262
264
|
Bun runtime 1.3.14
|
|
263
265
|
packageManager bun@1.3.14
|
|
264
266
|
@types/bun ^1.3.14
|
|
265
267
|
```
|
|
266
268
|
|
|
267
|
-
|
|
269
|
+
<!-- devtools-bun-policy:end -->
|
|
270
|
+
|
|
271
|
+
Renovate owns the single `BUN_VERSION` literal in `src/policy/bunRuntimePolicy.ts`. Its trusted base-branch workflow invokes `bun scripts/sync-renovate-owner.ts sync repository` to regenerate `packageManager`, `@types/bun`, the Bun workflow setup versions, this documentation block, and `bun.lock`, then runs `bun scripts/sync-renovate-owner.ts status repository` to reject stale generated artifacts. Do not synchronize those values manually in a Renovate branch.
|
|
268
272
|
|
|
269
273
|
## Managed package contract
|
|
270
274
|
|
|
@@ -279,7 +283,7 @@ It owns:
|
|
|
279
283
|
- `lint:fix`
|
|
280
284
|
- `format`
|
|
281
285
|
- `format:check`
|
|
282
|
-
- `knip`
|
|
286
|
+
- `knip:check`
|
|
283
287
|
|
|
284
288
|
For normal consumers, `@ankhorage/devtools` is a devDependency. `@ankhorage/ankh` keeps devtools as a runtime dependency because it loads the provider. Devtools itself participates in the Bun runtime policy without attempting to install itself as a consumer dependency.
|
|
285
289
|
|
|
@@ -291,10 +295,13 @@ When this managed package contract changes, synchronization runs `bun install`.
|
|
|
291
295
|
|
|
292
296
|
```text
|
|
293
297
|
.github/workflows/ci.yml
|
|
298
|
+
.github/workflows/renovate.yml
|
|
294
299
|
.github/workflows/release.yml
|
|
295
300
|
```
|
|
296
301
|
|
|
297
|
-
|
|
302
|
+
CI and Release render their `bun-version` from the same managed Bun runtime policy used for `package.json`. The CI workflow installs that Bun version with the frozen lockfile, builds before repository-provider validation, runs `bunx @ankhorage/ankh doctor validate .`, and conditionally runs lint, formatting, Knip, tests, typecheck, and Changesets checks.
|
|
303
|
+
|
|
304
|
+
The Renovate workflow accepts only same-repository branches created by `renovate[bot]`. It calls the SHA-pinned `ankhorage/renovate` workflow to add a release Changeset for runtime Ankhorage dependency updates or an empty Changeset for dev-only updates, then dispatches CI for that bot-authored commit. It never checks out or executes pull-request code in the privileged `pull_request_target` context.
|
|
298
305
|
|
|
299
306
|
## Managed VS Code configuration
|
|
300
307
|
|
package/dist/cli/index.d.ts
CHANGED
|
@@ -4,12 +4,12 @@ declare const provider: {
|
|
|
4
4
|
version: string;
|
|
5
5
|
capabilities: ("devtools.format" | "devtools.knip" | "devtools.lint" | "devtools.status" | "devtools.sync" | "devtools.eslint.status" | "devtools.eslint.sync" | "devtools.knip.status" | "devtools.knip.sync" | "devtools.package.status" | "devtools.package.sync" | "devtools.prettier.status" | "devtools.prettier.sync" | "devtools.vscode.status" | "devtools.vscode.sync" | "devtools.workflows.status" | "devtools.workflows.sync")[];
|
|
6
6
|
commands: {
|
|
7
|
-
path:
|
|
7
|
+
path: string[];
|
|
8
8
|
capability: "devtools.format" | "devtools.knip" | "devtools.lint" | "devtools.status" | "devtools.sync" | "devtools.eslint.status" | "devtools.eslint.sync" | "devtools.knip.status" | "devtools.knip.sync" | "devtools.package.status" | "devtools.package.sync" | "devtools.prettier.status" | "devtools.prettier.sync" | "devtools.vscode.status" | "devtools.vscode.sync" | "devtools.workflows.status" | "devtools.workflows.sync";
|
|
9
9
|
summary: string;
|
|
10
10
|
}[];
|
|
11
11
|
handlers: {
|
|
12
|
-
path:
|
|
12
|
+
path: string[];
|
|
13
13
|
handler: (request: import("@ankhorage/ankh").AnkhCommandExecutionRequest) => Promise<{
|
|
14
14
|
readonly exitCode: number;
|
|
15
15
|
}>;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { bunRuntimePolicy } from '../policy/bunRuntimePolicy.js';
|
|
1
2
|
const REQUIRED_README_SNIPPETS = [
|
|
2
3
|
'ankh devtools lint',
|
|
3
4
|
'ankh devtools format',
|
|
@@ -19,6 +20,13 @@ const REQUIRED_README_SNIPPETS = [
|
|
|
19
20
|
'--dry-run',
|
|
20
21
|
"profile: 'auto'",
|
|
21
22
|
'@ankhorage/utility/project',
|
|
23
|
+
'<!-- devtools-bun-policy:start -->',
|
|
24
|
+
'<!-- devtools-bun-policy:end -->',
|
|
25
|
+
'bun scripts/sync-renovate-owner.ts sync repository',
|
|
26
|
+
'bun scripts/sync-renovate-owner.ts status',
|
|
27
|
+
bunRuntimePolicy.version,
|
|
28
|
+
bunRuntimePolicy.packageManager,
|
|
29
|
+
bunRuntimePolicy.typesRange,
|
|
22
30
|
];
|
|
23
31
|
export function getReadmeDocumentationErrors(readmeContents) {
|
|
24
32
|
return REQUIRED_README_SNIPPETS.flatMap((snippet) => readmeContents.includes(snippet)
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare function synchronizeRenovateOwnerAsync(operation: OwnerSyncOperation, targetDirectory: string, options?: OwnerSyncOptions): Promise<void>;
|
|
2
|
+
type OwnerSyncOperation = 'status' | 'sync';
|
|
3
|
+
interface OwnerSyncOptions {
|
|
4
|
+
readonly runLockfileAsync?: (operation: OwnerSyncOperation, targetDirectory: string) => Promise<void>;
|
|
5
|
+
}
|
|
6
|
+
export {};
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import { mkdir, readFile, writeFile } from 'node:fs/promises';
|
|
3
|
+
import { dirname, resolve } from 'node:path';
|
|
4
|
+
import { applyBunRuntimePolicy } from '../policy/applyBunRuntimePolicy.js';
|
|
5
|
+
import { nodeRuntimePolicy } from '../policy/bunRuntimePolicy.js';
|
|
6
|
+
import { renderWorkflowAsync } from '../tools/workflows/renderWorkflowAsync.js';
|
|
7
|
+
export async function synchronizeRenovateOwnerAsync(operation, targetDirectory, options = {}) {
|
|
8
|
+
const target = resolve(targetDirectory);
|
|
9
|
+
const policy = await readTargetBunPolicyAsync(target);
|
|
10
|
+
const definitions = await createManagedDefinitionsAsync(target, policy);
|
|
11
|
+
await assertDevtoolsTargetAsync(target);
|
|
12
|
+
if (operation === 'sync') {
|
|
13
|
+
await syncDefinitionsAsync(target, definitions);
|
|
14
|
+
await (options.runLockfileAsync ?? runBunLockfileAsync)(operation, target);
|
|
15
|
+
}
|
|
16
|
+
const outdatedPaths = await getOutdatedPathsAsync(target, definitions);
|
|
17
|
+
if (outdatedPaths.length > 0) {
|
|
18
|
+
throw new Error(`Stale Devtools owner policy artifacts: ${outdatedPaths.join(', ')}`);
|
|
19
|
+
}
|
|
20
|
+
if (operation === 'status') {
|
|
21
|
+
await (options.runLockfileAsync ?? runBunLockfileAsync)(operation, target);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
async function assertDevtoolsTargetAsync(targetDirectory) {
|
|
25
|
+
const manifest = JSON.parse(await readFile(resolve(targetDirectory, 'package.json'), 'utf8'));
|
|
26
|
+
if (!isRecord(manifest) || manifest.name !== '@ankhorage/devtools') {
|
|
27
|
+
throw new Error('The Renovate owner sync target must be @ankhorage/devtools.');
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
async function createManagedDefinitionsAsync(targetDirectory, policy) {
|
|
31
|
+
const manifest = JSON.parse(await readFile(resolve(targetDirectory, 'package.json'), 'utf8'));
|
|
32
|
+
if (!isRecord(manifest)) {
|
|
33
|
+
throw new Error('Devtools package.json must contain a JSON object.');
|
|
34
|
+
}
|
|
35
|
+
const readme = await readFile(resolve(targetDirectory, 'README.md'), 'utf8');
|
|
36
|
+
const workflowPolicy = {
|
|
37
|
+
bunVersion: policy.version,
|
|
38
|
+
nodeVersion: nodeRuntimePolicy.setupVersion,
|
|
39
|
+
};
|
|
40
|
+
return [
|
|
41
|
+
{
|
|
42
|
+
relativePath: 'package.json',
|
|
43
|
+
contents: serializePackageManifest(applyBunRuntimePolicy(manifest, policy)),
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
relativePath: '.github/workflows/ci.yml',
|
|
47
|
+
contents: await renderWorkflowAsync(new URL('../tools/workflows/files/ci.yml', import.meta.url), workflowPolicy),
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
relativePath: '.github/workflows/release.yml',
|
|
51
|
+
contents: await renderWorkflowAsync(new URL('../tools/workflows/files/release.yml', import.meta.url), workflowPolicy),
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
relativePath: '.github/workflows/renovate.yml',
|
|
55
|
+
contents: await renderWorkflowAsync(new URL('../tools/workflows/files/renovate.yml', import.meta.url), workflowPolicy),
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
relativePath: 'README.md',
|
|
59
|
+
contents: replaceReadmePolicy(readme, policy),
|
|
60
|
+
},
|
|
61
|
+
];
|
|
62
|
+
}
|
|
63
|
+
async function getOutdatedPathsAsync(targetDirectory, definitions) {
|
|
64
|
+
const results = await Promise.all(definitions.map(async ({ contents, relativePath }) => {
|
|
65
|
+
const current = await readFile(resolve(targetDirectory, relativePath), 'utf8').catch((error) => {
|
|
66
|
+
if (isNodeError(error) && error.code === 'ENOENT')
|
|
67
|
+
return null;
|
|
68
|
+
throw error;
|
|
69
|
+
});
|
|
70
|
+
return current === contents ? null : relativePath;
|
|
71
|
+
}));
|
|
72
|
+
return results.filter((relativePath) => relativePath !== null);
|
|
73
|
+
}
|
|
74
|
+
function isNodeError(error) {
|
|
75
|
+
return error instanceof Error && 'code' in error;
|
|
76
|
+
}
|
|
77
|
+
function isRecord(value) {
|
|
78
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
79
|
+
}
|
|
80
|
+
async function readTargetBunPolicyAsync(targetDirectory) {
|
|
81
|
+
const contents = await readFile(resolve(targetDirectory, 'src/policy/bunRuntimePolicy.ts'), 'utf8');
|
|
82
|
+
const matches = [...contents.matchAll(BUN_VERSION_PATTERN)];
|
|
83
|
+
const version = matches.length === 1 ? matches[0]?.[1] : undefined;
|
|
84
|
+
if (version === undefined) {
|
|
85
|
+
throw new Error('Expected exactly one canonical BUN_VERSION literal in the target policy.');
|
|
86
|
+
}
|
|
87
|
+
return {
|
|
88
|
+
packageManager: `bun@${version}`,
|
|
89
|
+
typesRange: `^${version}`,
|
|
90
|
+
version,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
function replaceReadmePolicy(readme, policy) {
|
|
94
|
+
const startIndex = readme.indexOf(README_POLICY_START);
|
|
95
|
+
const endIndex = readme.indexOf(README_POLICY_END);
|
|
96
|
+
if (startIndex === -1 || endIndex === -1 || endIndex < startIndex) {
|
|
97
|
+
throw new Error('README.md must contain one ordered Devtools Bun policy marker pair.');
|
|
98
|
+
}
|
|
99
|
+
if (readme.includes(README_POLICY_START, startIndex + README_POLICY_START.length) ||
|
|
100
|
+
readme.includes(README_POLICY_END, endIndex + README_POLICY_END.length)) {
|
|
101
|
+
throw new Error('README.md must contain exactly one Devtools Bun policy marker pair.');
|
|
102
|
+
}
|
|
103
|
+
const replacement = `${README_POLICY_START}\n\n${renderReadmePolicy(policy)}\n\n${README_POLICY_END}`;
|
|
104
|
+
return `${readme.slice(0, startIndex)}${replacement}${readme.slice(endIndex + README_POLICY_END.length)}`;
|
|
105
|
+
}
|
|
106
|
+
function renderReadmePolicy(policy) {
|
|
107
|
+
return `\`\`\`text
|
|
108
|
+
Bun runtime ${policy.version}
|
|
109
|
+
packageManager ${policy.packageManager}
|
|
110
|
+
@types/bun ${policy.typesRange}
|
|
111
|
+
\`\`\``;
|
|
112
|
+
}
|
|
113
|
+
async function runBunLockfileAsync(operation, targetDirectory) {
|
|
114
|
+
const args = [
|
|
115
|
+
'install',
|
|
116
|
+
'--cwd',
|
|
117
|
+
targetDirectory,
|
|
118
|
+
'--ignore-scripts',
|
|
119
|
+
'--lockfile-only',
|
|
120
|
+
'--registry=https://registry.npmjs.org',
|
|
121
|
+
];
|
|
122
|
+
if (operation === 'status')
|
|
123
|
+
args.push('--frozen-lockfile');
|
|
124
|
+
await new Promise((resolvePromise, rejectPromise) => {
|
|
125
|
+
const child = spawn('bun', args, { stdio: 'inherit' });
|
|
126
|
+
child.once('error', rejectPromise);
|
|
127
|
+
child.once('exit', (code) => {
|
|
128
|
+
if (code === 0)
|
|
129
|
+
return resolvePromise();
|
|
130
|
+
rejectPromise(new Error(`Bun lockfile ${operation} exited with code ${code ?? 'unknown'}.`));
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
function serializePackageManifest(manifest) {
|
|
135
|
+
return `${JSON.stringify(manifest, null, 2)}\n`;
|
|
136
|
+
}
|
|
137
|
+
async function syncDefinitionsAsync(targetDirectory, definitions) {
|
|
138
|
+
for (const { contents, relativePath } of definitions) {
|
|
139
|
+
const targetPath = resolve(targetDirectory, relativePath);
|
|
140
|
+
const current = await readFile(targetPath, 'utf8').catch((error) => {
|
|
141
|
+
if (isNodeError(error) && error.code === 'ENOENT')
|
|
142
|
+
return null;
|
|
143
|
+
throw error;
|
|
144
|
+
});
|
|
145
|
+
if (current === contents)
|
|
146
|
+
continue;
|
|
147
|
+
await mkdir(dirname(targetPath), { recursive: true });
|
|
148
|
+
await writeFile(targetPath, contents, 'utf8');
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
const BUN_VERSION_PATTERN = /const BUN_VERSION = '(\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?)';/gu;
|
|
152
|
+
const README_POLICY_END = '<!-- devtools-bun-policy:end -->';
|
|
153
|
+
const README_POLICY_START = '<!-- devtools-bun-policy:start -->';
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export function applyBunRuntimePolicy(manifest, policy) {
|
|
2
|
+
const devDependencies = toRecord(manifest.devDependencies);
|
|
3
|
+
devDependencies['@types/bun'] = policy.typesRange;
|
|
4
|
+
return {
|
|
5
|
+
...manifest,
|
|
6
|
+
packageManager: policy.packageManager,
|
|
7
|
+
devDependencies,
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
function isRecord(value) {
|
|
11
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
12
|
+
}
|
|
13
|
+
function toRecord(value) {
|
|
14
|
+
return isRecord(value) ? { ...value } : {};
|
|
15
|
+
}
|
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Canonical runtime/tooling policies for Ankhorage repositories.
|
|
3
|
-
*
|
|
4
|
-
* Import these from `@ankhorage/devtools/policy` when another package needs to inspect
|
|
5
|
-
* the managed Bun or Node baseline without defining an independent version authority.
|
|
6
|
-
*/
|
|
7
1
|
export declare const bunRuntimePolicy: {
|
|
8
2
|
readonly packageManager: "bun@1.3.14";
|
|
9
3
|
readonly typesRange: "^1.3.14";
|
|
@@ -4,10 +4,11 @@
|
|
|
4
4
|
* Import these from `@ankhorage/devtools/policy` when another package needs to inspect
|
|
5
5
|
* the managed Bun or Node baseline without defining an independent version authority.
|
|
6
6
|
*/
|
|
7
|
+
const BUN_VERSION = '1.3.14';
|
|
7
8
|
export const bunRuntimePolicy = {
|
|
8
|
-
packageManager:
|
|
9
|
-
typesRange:
|
|
10
|
-
version:
|
|
9
|
+
packageManager: `bun@${BUN_VERSION}`,
|
|
10
|
+
typesRange: `^${BUN_VERSION}`,
|
|
11
|
+
version: BUN_VERSION,
|
|
11
12
|
};
|
|
12
13
|
/**
|
|
13
14
|
* Canonical Node LTS baseline for Node-based Ankhorage tooling and CI execution.
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* as a development dependency for normal consumers, while `@ankhorage/ankh` keeps devtools as a
|
|
6
6
|
* runtime dependency because the CLI loads it as a bundled core provider. Individually installed
|
|
7
7
|
* toolchain packages that devtools now owns are removed, and the canonical `lint`, `lint:fix`,
|
|
8
|
-
* `format`, `format:check`, and `knip` scripts are written.
|
|
8
|
+
* `format`, `format:check`, and `knip:check` scripts are written.
|
|
9
9
|
* Unrelated manifest fields, scripts, dependencies, and metadata are preserved.
|
|
10
10
|
*
|
|
11
11
|
* The Bun runtime policy is shared by every repository, including devtools itself. Devtools skips
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
import { readFileSync } from 'node:fs';
|
|
21
21
|
import { readFile, writeFile } from 'node:fs/promises';
|
|
22
22
|
import { resolve } from 'node:path';
|
|
23
|
+
import { applyBunRuntimePolicy } from '../../policy/applyBunRuntimePolicy.js';
|
|
23
24
|
import { bunRuntimePolicy } from '../../policy/bunRuntimePolicy.js';
|
|
24
25
|
const PACKAGE_PATH = 'package.json';
|
|
25
26
|
const DEVTOOLS_PACKAGE_NAME = '@ankhorage/devtools';
|
|
@@ -30,7 +31,7 @@ const STANDARD_SCRIPTS = {
|
|
|
30
31
|
'lint:fix': 'ankhorage-eslint . --fix --max-warnings=0',
|
|
31
32
|
format: 'ankhorage-prettier --write .',
|
|
32
33
|
'format:check': 'ankhorage-prettier --check .',
|
|
33
|
-
knip: 'ankhorage-knip',
|
|
34
|
+
'knip:check': 'ankhorage-knip',
|
|
34
35
|
};
|
|
35
36
|
const DEVTOOLS_OWNED_DEV_DEPENDENCIES = [
|
|
36
37
|
'@eslint/js',
|
|
@@ -80,9 +81,11 @@ export async function syncPackageManifest(targetDirectory, devtoolsVersion, opti
|
|
|
80
81
|
}
|
|
81
82
|
export function applyManagedPackageContract(manifest, devtoolsVersion) {
|
|
82
83
|
if (manifest.name === DEVTOOLS_PACKAGE_NAME) {
|
|
83
|
-
return applyBunRuntimePolicy(manifest);
|
|
84
|
+
return applyBunRuntimePolicy(manifest, bunRuntimePolicy);
|
|
84
85
|
}
|
|
85
|
-
const scripts = { ...toRecord(manifest.scripts)
|
|
86
|
+
const scripts = { ...toRecord(manifest.scripts) };
|
|
87
|
+
delete scripts.knip;
|
|
88
|
+
Object.assign(scripts, STANDARD_SCRIPTS);
|
|
86
89
|
const devDependencies = removeOwnedDependencies(toRecord(manifest.devDependencies));
|
|
87
90
|
const dependencies = toRecord(manifest.dependencies);
|
|
88
91
|
applyDevtoolsDependencyPlacement(manifest, dependencies, devDependencies, devtoolsVersion);
|
|
@@ -91,7 +94,7 @@ export function applyManagedPackageContract(manifest, devtoolsVersion) {
|
|
|
91
94
|
...normalizedDependencies(manifest, dependencies),
|
|
92
95
|
scripts,
|
|
93
96
|
devDependencies,
|
|
94
|
-
});
|
|
97
|
+
}, bunRuntimePolicy);
|
|
95
98
|
}
|
|
96
99
|
export function isManagedPackageContractCurrent(manifest, devtoolsVersion) {
|
|
97
100
|
if (!hasCurrentBunRuntimePolicy(manifest)) {
|
|
@@ -130,15 +133,6 @@ async function readPackageManifest(targetDirectory) {
|
|
|
130
133
|
throw error;
|
|
131
134
|
}
|
|
132
135
|
}
|
|
133
|
-
function applyBunRuntimePolicy(manifest) {
|
|
134
|
-
const devDependencies = toRecord(manifest.devDependencies);
|
|
135
|
-
devDependencies[BUN_TYPES_PACKAGE_NAME] = bunRuntimePolicy.typesRange;
|
|
136
|
-
return {
|
|
137
|
-
...manifest,
|
|
138
|
-
packageManager: bunRuntimePolicy.packageManager,
|
|
139
|
-
devDependencies,
|
|
140
|
-
};
|
|
141
|
-
}
|
|
142
136
|
function hasCurrentBunRuntimePolicy(manifest) {
|
|
143
137
|
const devDependencies = toRecord(manifest.devDependencies);
|
|
144
138
|
return (manifest.packageManager === bunRuntimePolicy.packageManager &&
|
|
@@ -175,7 +169,8 @@ function normalizedDependencies(manifest, dependencies) {
|
|
|
175
169
|
: { dependencies };
|
|
176
170
|
}
|
|
177
171
|
function hasStandardScripts(scripts) {
|
|
178
|
-
return
|
|
172
|
+
return (scripts.knip === undefined &&
|
|
173
|
+
Object.entries(STANDARD_SCRIPTS).every(([name, command]) => scripts[name] === command));
|
|
179
174
|
}
|
|
180
175
|
function serializePackageManifest(manifest) {
|
|
181
176
|
return `${JSON.stringify(manifest, null, 2)}\n`;
|
|
@@ -5,6 +5,7 @@ on:
|
|
|
5
5
|
push:
|
|
6
6
|
branches:
|
|
7
7
|
- main
|
|
8
|
+
workflow_dispatch:
|
|
8
9
|
|
|
9
10
|
permissions:
|
|
10
11
|
contents: read
|
|
@@ -61,10 +62,10 @@ jobs:
|
|
|
61
62
|
|
|
62
63
|
- name: Run Knip
|
|
63
64
|
run: |
|
|
64
|
-
if node -e "const p=require('./package.json'); process.exit(p.scripts?.knip ? 0 : 1)"; then
|
|
65
|
-
bun run knip
|
|
65
|
+
if node -e "const p=require('./package.json'); process.exit(p.scripts?.['knip:check'] ? 0 : 1)"; then
|
|
66
|
+
bun run knip:check
|
|
66
67
|
else
|
|
67
|
-
echo "No knip script found; skipping."
|
|
68
|
+
echo "No knip:check script found; skipping."
|
|
68
69
|
fi
|
|
69
70
|
|
|
70
71
|
- name: Run tests
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
name: Renovate
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request_target:
|
|
5
|
+
types:
|
|
6
|
+
- opened
|
|
7
|
+
- reopened
|
|
8
|
+
- synchronize
|
|
9
|
+
|
|
10
|
+
permissions:
|
|
11
|
+
actions: write
|
|
12
|
+
contents: write
|
|
13
|
+
pull-requests: read
|
|
14
|
+
|
|
15
|
+
jobs:
|
|
16
|
+
changeset:
|
|
17
|
+
if: >-
|
|
18
|
+
github.actor == 'renovate[bot]' &&
|
|
19
|
+
github.event.pull_request.head.repo.full_name == github.repository &&
|
|
20
|
+
startsWith(github.event.pull_request.head.ref, 'renovate/')
|
|
21
|
+
uses: ankhorage/renovate/.github/workflows/changeset.yml@7d4a5104b94e763ca5be34919f4fcfbb12efd526
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { ManagedFileDefinition } from '../shared/managedFiles.js';
|
|
2
|
-
export declare const workflowManagedFiles: readonly [ManagedFileDefinition, ManagedFileDefinition];
|
|
2
|
+
export declare const workflowManagedFiles: readonly [ManagedFileDefinition, ManagedFileDefinition, ManagedFileDefinition];
|
|
@@ -1,20 +1,17 @@
|
|
|
1
|
-
import { readFile } from 'node:fs/promises';
|
|
2
1
|
import { bunRuntimePolicy, nodeRuntimePolicy } from '../../policy/bunRuntimePolicy.js';
|
|
3
|
-
|
|
4
|
-
const NODE_VERSION_TOKEN = '__ANKH_NODE_VERSION__';
|
|
2
|
+
import { renderWorkflowAsync } from './renderWorkflowAsync.js';
|
|
5
3
|
export const workflowManagedFiles = [
|
|
6
4
|
createWorkflowDefinition('.github/workflows/ci.yml', './files/ci.yml'),
|
|
7
5
|
createWorkflowDefinition('.github/workflows/release.yml', './files/release.yml'),
|
|
6
|
+
createWorkflowDefinition('.github/workflows/renovate.yml', './files/renovate.yml'),
|
|
8
7
|
];
|
|
9
8
|
function createWorkflowDefinition(relativePath, sourcePath) {
|
|
10
9
|
const sourceUrl = new URL(sourcePath, import.meta.url);
|
|
11
10
|
return {
|
|
12
11
|
relativePath,
|
|
13
|
-
render: async () => {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
.replaceAll(NODE_VERSION_TOKEN, nodeRuntimePolicy.setupVersion);
|
|
18
|
-
},
|
|
12
|
+
render: async () => await renderWorkflowAsync(sourceUrl, {
|
|
13
|
+
bunVersion: bunRuntimePolicy.version,
|
|
14
|
+
nodeVersion: nodeRuntimePolicy.setupVersion,
|
|
15
|
+
}),
|
|
19
16
|
};
|
|
20
17
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises';
|
|
2
|
+
export async function renderWorkflowAsync(sourceUrl, policy) {
|
|
3
|
+
const template = await readFile(sourceUrl, 'utf8');
|
|
4
|
+
return template
|
|
5
|
+
.replaceAll(BUN_VERSION_TOKEN, policy.bunVersion)
|
|
6
|
+
.replaceAll(NODE_VERSION_TOKEN, policy.nodeVersion);
|
|
7
|
+
}
|
|
8
|
+
const BUN_VERSION_TOKEN = '__ANKH_BUN_VERSION__';
|
|
9
|
+
const NODE_VERSION_TOKEN = '__ANKH_NODE_VERSION__';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ankhorage/devtools",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.1",
|
|
4
4
|
"description": "Shared development tools and repository standards for Ankhorage",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://github.com/ankhorage/devtools#readme",
|
|
@@ -86,7 +86,7 @@
|
|
|
86
86
|
"build": "rm -rf dist tsconfig.tsbuildinfo && tsc && mkdir -p dist/tools/prettier dist/tools/workflows dist/tools/vscode && cp src/tools/prettier/index.cjs dist/tools/prettier/index.cjs && cp -R src/tools/workflows/files dist/tools/workflows/files && cp -R src/tools/vscode/files dist/tools/vscode/files",
|
|
87
87
|
"typecheck": "bun x tsc --noEmit -p tsconfig.test.json",
|
|
88
88
|
"doctor": "ankhorage-doctor validate .",
|
|
89
|
-
"knip": "knip",
|
|
89
|
+
"knip:check": "knip",
|
|
90
90
|
"lint": "eslint .",
|
|
91
91
|
"lint:fix": "eslint . --fix --max-warnings=0",
|
|
92
92
|
"format": "prettier --write .",
|
|
@@ -99,7 +99,7 @@
|
|
|
99
99
|
"version-packages": "changeset version"
|
|
100
100
|
},
|
|
101
101
|
"dependencies": {
|
|
102
|
-
"@ankhorage/utility": "^0.
|
|
102
|
+
"@ankhorage/utility": "^0.2.0",
|
|
103
103
|
"@eslint/compat": "^2.1.0",
|
|
104
104
|
"@eslint/js": "^10.0.1",
|
|
105
105
|
"eslint": "^10.7.0",
|
|
@@ -117,8 +117,8 @@
|
|
|
117
117
|
"typescript-eslint": "^8.24.0"
|
|
118
118
|
},
|
|
119
119
|
"devDependencies": {
|
|
120
|
-
"@ankhorage/ankh": "^0.
|
|
121
|
-
"@ankhorage/doctor": "0.
|
|
120
|
+
"@ankhorage/ankh": "^0.8.2",
|
|
121
|
+
"@ankhorage/doctor": "0.10.1",
|
|
122
122
|
"@changesets/cli": "^2.30.0",
|
|
123
123
|
"@types/bun": "^1.3.14",
|
|
124
124
|
"@types/node": "^25.2.3",
|