@produck/agent-toolkit 0.1.0 → 0.1.3
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 +34 -3
- package/bin/release.mjs +271 -0
- package/package.json +5 -4
package/README.md
CHANGED
|
@@ -40,12 +40,43 @@ npm --prefix tools/agent-toolkit run pack:check
|
|
|
40
40
|
|
|
41
41
|
## Manual publish
|
|
42
42
|
|
|
43
|
-
|
|
43
|
+
Lerna-like release flow (recommended):
|
|
44
44
|
|
|
45
|
-
|
|
45
|
+
0) Interactive mode (TTY):
|
|
46
|
+
|
|
47
|
+
npm --prefix tools/agent-toolkit run release
|
|
48
|
+
|
|
49
|
+
Interactive prompts let you choose:
|
|
50
|
+
|
|
51
|
+
- version level: patch/minor/major
|
|
52
|
+
- action: dry-run or publish
|
|
53
|
+
- vcs mode: commit+tag / commit only / no commit+no tag
|
|
54
|
+
|
|
55
|
+
Default choices:
|
|
56
|
+
|
|
57
|
+
- patch
|
|
58
|
+
- dry-run
|
|
59
|
+
- commit + tag
|
|
60
|
+
|
|
61
|
+
Interactive mode handles both:
|
|
46
62
|
|
|
47
|
-
|
|
63
|
+
- version bump level (patch/minor/major)
|
|
64
|
+
- action mode (dry-run or publish)
|
|
65
|
+
- auto commit and tag after dry-run
|
|
48
66
|
|
|
67
|
+
Non-interactive flags:
|
|
68
|
+
|
|
69
|
+
- `npm --prefix tools/agent-toolkit run release -- patch --publish`
|
|
70
|
+
- `npm --prefix tools/agent-toolkit run release -- patch --no-tag`
|
|
71
|
+
- `npm --prefix tools/agent-toolkit run release -- patch --no-commit --no-tag`
|
|
72
|
+
|
|
73
|
+
Note:
|
|
74
|
+
|
|
75
|
+
- Release requires a clean working tree in `tools/agent-toolkit` before start.
|
|
76
|
+
|
|
77
|
+
Low-level commands (optional):
|
|
78
|
+
|
|
79
|
+
npm --prefix tools/agent-toolkit run publish:dry-run
|
|
49
80
|
npm --prefix tools/agent-toolkit run publish:latest
|
|
50
81
|
|
|
51
82
|
## GitHub workflow
|
package/bin/release.mjs
ADDED
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { spawnSync } from 'node:child_process';
|
|
5
|
+
import readline from 'node:readline/promises';
|
|
6
|
+
|
|
7
|
+
const LEVELS = new Set(['patch', 'minor', 'major']);
|
|
8
|
+
|
|
9
|
+
function usage() {
|
|
10
|
+
console.log([
|
|
11
|
+
'Usage:',
|
|
12
|
+
' node ./bin/release.mjs',
|
|
13
|
+
' node ./bin/release.mjs <patch|minor|major> [--publish] [--no-commit] [--no-tag]',
|
|
14
|
+
' node ./bin/release.mjs --interactive',
|
|
15
|
+
'',
|
|
16
|
+
'Behavior:',
|
|
17
|
+
' 1) bump version (no git tag)',
|
|
18
|
+
' 2) run verify',
|
|
19
|
+
' 3) run publish:dry-run',
|
|
20
|
+
' 4) auto commit version change (default)',
|
|
21
|
+
' 5) auto create git tag (default)',
|
|
22
|
+
' 6) optionally publish latest when --publish is set',
|
|
23
|
+
'',
|
|
24
|
+
'Interactive mode defaults:',
|
|
25
|
+
' - release level: patch',
|
|
26
|
+
' - publish mode: dry-run',
|
|
27
|
+
' - auto commit: enabled',
|
|
28
|
+
' - auto tag: enabled',
|
|
29
|
+
].join('\n'));
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function runNpm(args) {
|
|
33
|
+
const result = spawnSync('npm', args, {
|
|
34
|
+
stdio: 'inherit',
|
|
35
|
+
cwd: process.cwd(),
|
|
36
|
+
shell: true,
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
if (result.error) {
|
|
40
|
+
console.error(`[release] failed to run npm ${args.join(' ')}:`);
|
|
41
|
+
console.error(result.error.message);
|
|
42
|
+
process.exit(1);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (result.status !== 0) {
|
|
46
|
+
process.exit(result.status ?? 1);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function runGit(args) {
|
|
51
|
+
const result = spawnSync('git', args, {
|
|
52
|
+
stdio: 'inherit',
|
|
53
|
+
cwd: process.cwd(),
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
if (result.error) {
|
|
57
|
+
console.error(`[release] failed to run git ${args.join(' ')}:`);
|
|
58
|
+
console.error(result.error.message);
|
|
59
|
+
process.exit(1);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (result.status !== 0) {
|
|
63
|
+
process.exit(result.status ?? 1);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function getDirtyFiles() {
|
|
68
|
+
const result = spawnSync('git', ['status', '--porcelain'], {
|
|
69
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
70
|
+
cwd: process.cwd(),
|
|
71
|
+
encoding: 'utf8',
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
if (result.error || result.status !== 0) {
|
|
75
|
+
console.error('[release] unable to check git status');
|
|
76
|
+
process.exit(1);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return result.stdout
|
|
80
|
+
.split(/\r?\n/)
|
|
81
|
+
.map((line) => line.trim())
|
|
82
|
+
.filter((line) => line.length > 0);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function ensureReleaseWorkspaceClean() {
|
|
86
|
+
const dirty = getDirtyFiles();
|
|
87
|
+
if (dirty.length === 0) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
console.error('[release] working tree is not clean before release:');
|
|
92
|
+
for (const line of dirty) {
|
|
93
|
+
console.error(` ${line}`);
|
|
94
|
+
}
|
|
95
|
+
console.error('[release] commit/stash changes and retry');
|
|
96
|
+
process.exit(2);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function commitAndTag(version, shouldCommit, shouldTag) {
|
|
100
|
+
if (shouldCommit) {
|
|
101
|
+
const message = `[UPGRADE] <infra>: release @produck/agent-toolkit ${version}`;
|
|
102
|
+
console.log(`[release] commit version bump: ${message}`);
|
|
103
|
+
runGit(['add', 'package.json']);
|
|
104
|
+
runGit(['commit', '-m', message]);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (shouldTag) {
|
|
108
|
+
const tag = `agent-toolkit-v${version}`;
|
|
109
|
+
console.log(`[release] create tag: ${tag}`);
|
|
110
|
+
runGit(['tag', '-a', tag, '-m', `[UPGRADE] <infra>: tag ${tag}`]);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function bumpPreview(version, level) {
|
|
115
|
+
const parts = version.split('.').map((v) => Number(v));
|
|
116
|
+
if (parts.length !== 3 || parts.some((v) => Number.isNaN(v))) {
|
|
117
|
+
return `unknown (${version})`;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const [major, minor, patch] = parts;
|
|
121
|
+
if (level === 'patch') {
|
|
122
|
+
return `${major}.${minor}.${patch + 1}`;
|
|
123
|
+
}
|
|
124
|
+
if (level === 'minor') {
|
|
125
|
+
return `${major}.${minor + 1}.0`;
|
|
126
|
+
}
|
|
127
|
+
return `${major + 1}.0.0`;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
async function askInteractive(currentVersion) {
|
|
131
|
+
const rl = readline.createInterface({
|
|
132
|
+
input: process.stdin,
|
|
133
|
+
output: process.stdout,
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
try {
|
|
137
|
+
console.log(`[release] current version: ${currentVersion}`);
|
|
138
|
+
console.log('[release] select release level:');
|
|
139
|
+
console.log(` 1) patch (default) -> ${bumpPreview(currentVersion, 'patch')}`);
|
|
140
|
+
console.log(` 2) minor -> ${bumpPreview(currentVersion, 'minor')}`);
|
|
141
|
+
console.log(` 3) major -> ${bumpPreview(currentVersion, 'major')}`);
|
|
142
|
+
|
|
143
|
+
const levelAnswer = (
|
|
144
|
+
await rl.question('Choose level [1/2/3] (default: 1): ')
|
|
145
|
+
).trim();
|
|
146
|
+
|
|
147
|
+
let level = 'patch';
|
|
148
|
+
if (levelAnswer === '2') {
|
|
149
|
+
level = 'minor';
|
|
150
|
+
} else if (levelAnswer === '3') {
|
|
151
|
+
level = 'major';
|
|
152
|
+
} else if (levelAnswer && levelAnswer !== '1') {
|
|
153
|
+
console.error(`Invalid level choice: ${levelAnswer}`);
|
|
154
|
+
process.exit(2);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
console.log('[release] select publish mode:');
|
|
158
|
+
console.log(' 1) dry-run only (default)');
|
|
159
|
+
console.log(' 2) publish latest after dry-run');
|
|
160
|
+
|
|
161
|
+
const publishAnswer = (
|
|
162
|
+
await rl.question('Choose mode [1/2] (default: 1): ')
|
|
163
|
+
).trim();
|
|
164
|
+
|
|
165
|
+
let shouldPublish = false;
|
|
166
|
+
if (publishAnswer === '2') {
|
|
167
|
+
shouldPublish = true;
|
|
168
|
+
} else if (publishAnswer && publishAnswer !== '1') {
|
|
169
|
+
console.error(`Invalid publish choice: ${publishAnswer}`);
|
|
170
|
+
process.exit(2);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
console.log('[release] auto commit and tag settings:');
|
|
174
|
+
console.log(' 1) commit + tag (default)');
|
|
175
|
+
console.log(' 2) commit only');
|
|
176
|
+
console.log(' 3) no commit, no tag');
|
|
177
|
+
|
|
178
|
+
const vcsAnswer = (
|
|
179
|
+
await rl.question('Choose vcs mode [1/2/3] (default: 1): ')
|
|
180
|
+
).trim();
|
|
181
|
+
|
|
182
|
+
let shouldCommit = true;
|
|
183
|
+
let shouldTag = true;
|
|
184
|
+
if (vcsAnswer === '2') {
|
|
185
|
+
shouldCommit = true;
|
|
186
|
+
shouldTag = false;
|
|
187
|
+
} else if (vcsAnswer === '3') {
|
|
188
|
+
shouldCommit = false;
|
|
189
|
+
shouldTag = false;
|
|
190
|
+
} else if (vcsAnswer && vcsAnswer !== '1') {
|
|
191
|
+
console.error(`Invalid vcs choice: ${vcsAnswer}`);
|
|
192
|
+
process.exit(2);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
return { level, shouldPublish, shouldCommit, shouldTag };
|
|
196
|
+
} finally {
|
|
197
|
+
rl.close();
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
function runRelease(level, shouldPublish, shouldCommit, shouldTag) {
|
|
202
|
+
if (!LEVELS.has(level)) {
|
|
203
|
+
console.error(`Invalid release level: ${level}`);
|
|
204
|
+
usage();
|
|
205
|
+
process.exit(2);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
ensureReleaseWorkspaceClean();
|
|
209
|
+
|
|
210
|
+
const pkgFile = path.resolve('package.json');
|
|
211
|
+
const before = JSON.parse(fs.readFileSync(pkgFile, 'utf8')).version;
|
|
212
|
+
|
|
213
|
+
console.log(`[release] bump version: ${level}`);
|
|
214
|
+
runNpm(['version', level, '--no-git-tag-version']);
|
|
215
|
+
|
|
216
|
+
const after = JSON.parse(fs.readFileSync(pkgFile, 'utf8')).version;
|
|
217
|
+
console.log(`[release] version ${before} -> ${after}`);
|
|
218
|
+
|
|
219
|
+
console.log('[release] verify toolkit');
|
|
220
|
+
runNpm(['run', 'verify']);
|
|
221
|
+
|
|
222
|
+
console.log('[release] publish dry-run');
|
|
223
|
+
runNpm(['run', 'publish:dry-run']);
|
|
224
|
+
|
|
225
|
+
commitAndTag(after, shouldCommit, shouldTag);
|
|
226
|
+
|
|
227
|
+
if (shouldPublish) {
|
|
228
|
+
console.log('[release] publish latest');
|
|
229
|
+
runNpm(['run', 'publish:latest']);
|
|
230
|
+
} else {
|
|
231
|
+
console.log('[release] publish skipped (interactive default: dry-run)');
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
const args = process.argv.slice(2);
|
|
236
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
237
|
+
usage();
|
|
238
|
+
process.exit(0);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
const interactiveRequested = args.length === 0 || args.includes('--interactive');
|
|
242
|
+
if (interactiveRequested) {
|
|
243
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
244
|
+
console.error('Interactive mode requires a TTY.');
|
|
245
|
+
usage();
|
|
246
|
+
process.exit(2);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
const pkgFile = path.resolve('package.json');
|
|
250
|
+
const currentVersion = JSON.parse(fs.readFileSync(pkgFile, 'utf8')).version;
|
|
251
|
+
const interactive = await askInteractive(currentVersion);
|
|
252
|
+
runRelease(
|
|
253
|
+
interactive.level,
|
|
254
|
+
interactive.shouldPublish,
|
|
255
|
+
interactive.shouldCommit,
|
|
256
|
+
interactive.shouldTag
|
|
257
|
+
);
|
|
258
|
+
process.exit(0);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
const level = args[0];
|
|
262
|
+
const shouldPublish = args.includes('--publish');
|
|
263
|
+
const shouldCommit = !args.includes('--no-commit');
|
|
264
|
+
const shouldTag = !args.includes('--no-tag');
|
|
265
|
+
|
|
266
|
+
if (shouldTag && !shouldCommit) {
|
|
267
|
+
console.error('[release] --no-commit cannot be combined with tag enabled');
|
|
268
|
+
process.exit(2);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
runRelease(level, shouldPublish, shouldCommit, shouldTag);
|
package/package.json
CHANGED
|
@@ -1,21 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@produck/agent-toolkit",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "Central CLI toolkit for organization AI execution workflows",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
8
|
-
"url": "https://github.com/produck/.github.git",
|
|
8
|
+
"url": "git+https://github.com/produck/.github.git",
|
|
9
9
|
"directory": "tools/agent-toolkit"
|
|
10
10
|
},
|
|
11
11
|
"bin": {
|
|
12
|
-
"agent-toolkit": "
|
|
12
|
+
"agent-toolkit": "bin/agent-toolkit.mjs"
|
|
13
13
|
},
|
|
14
14
|
"scripts": {
|
|
15
15
|
"verify": "node ./bin/agent-toolkit.mjs --help && node ./bin/agent-toolkit.mjs preflight --cwd . --require package.json",
|
|
16
16
|
"pack:check": "npm pack --dry-run",
|
|
17
17
|
"publish:dry-run": "npm publish --dry-run --access public",
|
|
18
|
-
"publish:latest": "npm publish --access public"
|
|
18
|
+
"publish:latest": "npm publish --access public",
|
|
19
|
+
"release": "node ./bin/release.mjs"
|
|
19
20
|
},
|
|
20
21
|
"files": [
|
|
21
22
|
"bin"
|