dsh-plugin-toolkit 0.8.4 → 0.8.5

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/CHANGELOG.md CHANGED
@@ -1,3 +1,12 @@
1
+ ## 0.8.5
2
+
3
+ - `release --market <dir>`: write the index entry into a checkout of the
4
+ repository that owns the index, and open the pull request there. Before this,
5
+ `release` only touched a `market/index.json` inside the plugin's own repo, so
6
+ anyone listed in a central market had to patch the entry by hand — which is
7
+ where the timestamp goes wrong.
8
+ - `--index` still names the file inside that repository.
9
+
1
10
  ## 0.8.4
2
11
 
3
12
  - README: `## When the panel does not appear` — the five checks that explain a
package/README.md CHANGED
@@ -320,6 +320,19 @@ merged
320
320
 
321
321
  Without `--pr` it prints the `git add` / `gh pr create` commands instead of running them; `--dry-run` prints the whole sequence before anything happens. A re-run after a failure is safe: the same version with the same publish time is a no-op.
322
322
 
323
+ ### When the index lives in someone else's repository
324
+
325
+ Most plugins are listed in a central market repository, not their own. Point
326
+ `--market` at a checkout of that repository and the entry — and the pull
327
+ request — land there:
328
+
329
+ ```sh
330
+ $ dsh-plugin release . --market ../market-repo --pr --merge
331
+ tagged plugin-v0.4.0, npm served my-plugin@0.4.0 after 92s
332
+ updated /Users/me/market-repo/market/index.json on market/0.4.0
333
+ merged
334
+ ```
335
+
323
336
  ## Exit codes
324
337
 
325
338
  | Code | Meaning |
package/lib/cli.mjs CHANGED
@@ -37,6 +37,7 @@ export const HELP = `dsh-plugin — preflight and release DeepSeek Harness plugi
37
37
  Flags
38
38
  --dry-run show the steps without touching anything
39
39
  --index <path> index file, default market/index.json
40
+ --market <dir> with release: a checkout of the repository that holds the index
40
41
  --tag-prefix <prefix> default plugin-v
41
42
  --budget <seconds> how long to wait for npm, default 480
42
43
  --pr commit the index on a branch, push it, open the pull request
@@ -72,6 +73,7 @@ function flags(argv) {
72
73
  else if (token === '--pr') parsed.pr = true;
73
74
  else if (token === '--merge') parsed.merge = true;
74
75
  else if (token === '--base') parsed.base = argv[++index];
76
+ else if (token === '--market') parsed.market = argv[++index];
75
77
  else if (token.startsWith('--') === true) throw new Error(`unknown flag ${token}`);
76
78
  else parsed.positional.push(token);
77
79
  }
@@ -210,6 +212,7 @@ export async function run(argv, io = console) {
210
212
  const result = await release({
211
213
  dir,
212
214
  indexFile: options.index,
215
+ marketDir: options.market,
213
216
  tagPrefix: options.tagPrefix,
214
217
  budgetMs: options.budget === undefined ? undefined : options.budget * 1000,
215
218
  pr: options.pr === true,
package/lib/release.mjs CHANGED
@@ -51,7 +51,7 @@ export function dirtyPaths(dir, limit = 3, run) {
51
51
  * anything runs is what makes `--dry-run` useful: it shows the whole sequence
52
52
  * and the exact commands.
53
53
  */
54
- export function plan({ dir = process.cwd(), version, name, tagPrefix = 'plugin-v', indexFile = 'market/index.json' }) {
54
+ export function plan({ dir = process.cwd(), version, name, tagPrefix = 'plugin-v', indexFile = 'market/index.json', marketDir }) {
55
55
  const report = doctor(dir);
56
56
  const resolvedName = name ?? report.manifest.name ?? 'this-plugin';
57
57
  const resolvedVersion = version ?? report.manifest.version ?? '0.0.0';
@@ -61,7 +61,13 @@ export function plan({ dir = process.cwd(), version, name, tagPrefix = 'plugin-v
61
61
  { title: `Create the tag ${tag}`, command: `git tag ${tag}`, runs: true },
62
62
  { title: 'Push the tag, which starts the release workflow', command: `git push origin ${tag}`, runs: true },
63
63
  { title: `Wait until the registry serves ${resolvedName}@${resolvedVersion}`, command: `GET /${resolvedName}`, runs: true },
64
- { title: 'Write the version into the market index, with the publish time the registry reported', command: `patch ${indexFile}`, runs: true },
64
+ {
65
+ title: marketDir === undefined
66
+ ? 'Write the version into the market index, with the publish time the registry reported'
67
+ : `Write the version into the market index at ${marketDir}`,
68
+ command: `patch ${path.join(marketDir ?? '', indexFile)}`,
69
+ runs: true,
70
+ },
65
71
  { title: 'Open the index pull request', command: 'gh pr create', runs: false },
66
72
  { title: 'Re-read the live index and confirm the version is listed', command: 'GET market/index.json', runs: false },
67
73
  ];
@@ -74,6 +80,7 @@ export async function release(options) {
74
80
  registry,
75
81
  tagPrefix = 'plugin-v',
76
82
  indexFile = 'market/index.json',
83
+ marketDir,
77
84
  budgetMs,
78
85
  intervalMs,
79
86
  sleep,
@@ -155,7 +162,10 @@ export async function release(options) {
155
162
 
156
163
  const timestamp = publishedAt(waited.document, version);
157
164
  const entry = buildEntry({ version, publishTimestamp: timestamp, hostRange: report.notes.hostRange });
158
- const indexPath = path.join(dir, indexFile);
165
+ // Most plugins are listed in someone else's index: `--market` points at a
166
+ // checkout of that repository, and the entry plus the pull request land there.
167
+ const indexRoot = typeof marketDir === 'string' && marketDir.length > 0 ? path.resolve(marketDir) : dir;
168
+ const indexPath = path.join(indexRoot, indexFile);
159
169
  let indexUpdate = null;
160
170
  if (fs.existsSync(indexPath) === true) {
161
171
  try {
@@ -163,10 +173,10 @@ export async function release(options) {
163
173
  const after = addVersion(before, name, entry);
164
174
  if (after !== before) {
165
175
  writeIndex(indexPath, after);
166
- indexUpdate = { file: indexFile, version, entry };
176
+ indexUpdate = { file: indexPath, version, entry };
167
177
  if (typeof onChange === 'function') onChange(indexUpdate);
168
178
  } else {
169
- indexUpdate = { file: indexFile, version, entry, unchanged: true };
179
+ indexUpdate = { file: indexPath, version, entry, unchanged: true };
170
180
  }
171
181
  } catch (error) {
172
182
  return { ok: false, stage: 'index', failures: [{ check: 'index', message: error.message }] };
@@ -188,16 +198,17 @@ export async function release(options) {
188
198
  // The index change is one line, but it still needs a branch, a pull request,
189
199
  // a green CI and a merge; doing that by hand is where "forgot to open the PR"
190
200
  // happens.
191
- const ghRunner = options.gh ?? defaultGh(dir);
201
+ const ghRunner = options.gh ?? defaultGh(indexRoot);
202
+ const marketGit = options.marketGit ?? (indexRoot === dir ? options.git : ((args) => git(indexRoot, args)));
192
203
  const pull = await openIndexPr({
193
- dir,
204
+ dir: indexRoot,
205
+ git: marketGit,
194
206
  indexFile,
195
207
  version,
196
208
  base: options.base ?? 'main',
197
209
  branch: options.branch,
198
210
  title: options.prTitle,
199
211
  body: options.prBody,
200
- git: options.git,
201
212
  gh: ghRunner,
202
213
  onStep: options.onStep,
203
214
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-plugin-toolkit",
3
- "version": "0.8.4",
3
+ "version": "0.8.5",
4
4
  "description": "Preflight, release and test DeepSeek Harness plugins: checks what the host needs, waits for npm to actually serve the version, and keeps the market index honest.",
5
5
  "type": "module",
6
6
  "bin": {