rman 2.1.0 → 2.2.0
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/commands/version.command.d.ts +16 -3
- package/constants.js +1 -1
- package/package.json +1 -1
- package/services/version.service.js +28 -2
|
@@ -148,7 +148,9 @@ export interface VersionExtraKeys {
|
|
|
148
148
|
/** Files whose hard-coded version is rewritten to the version being written, in the same commit
|
|
149
149
|
* as the bump - paths relative to the package's own directory (e.g. `["src/constants.ts"]`).
|
|
150
150
|
* Per-package cascaded; a listed file a package doesn't have is a silent no-op, so one `"[*]"`
|
|
151
|
-
* declaration covers a repo where only some packages carry one.
|
|
151
|
+
* declaration covers a repo where only some packages carry one. A file that *exists* and holds
|
|
152
|
+
* nothing rewritable is an error instead - unless the entry is `{ file, optional: true }`, which
|
|
153
|
+
* is how a shared preset says "stamp it where there is one".
|
|
152
154
|
*
|
|
153
155
|
* Stamping the source, not the build output: a build-time rewrite leaves the checked-in file
|
|
154
156
|
* claiming a placeholder, so anything running from source reports that placeholder, git never
|
|
@@ -168,11 +170,22 @@ export interface VersionExtraKeys {
|
|
|
168
170
|
/** Same, after it (`postversion` in a Node repository). */
|
|
169
171
|
after?: RunStepValue | RunStepValue[];
|
|
170
172
|
}
|
|
171
|
-
/**
|
|
172
|
-
*
|
|
173
|
+
/**
|
|
174
|
+
* One `version.stamp` entry: a path, or a path plus the identifier to rewrite when it is not spelled
|
|
175
|
+
* `version` and whether the entry is `optional`.
|
|
176
|
+
*
|
|
177
|
+
* **`optional` marks an entry whose author cannot know whether the file holds a version.** A file
|
|
178
|
+
* that exists and has nothing to rewrite is otherwise an error - that is what catches a typo'd path
|
|
179
|
+
* or a renamed identifier before it silently ships a stale constant on every release. The case it
|
|
180
|
+
* is wrong for is a *shared preset* naming one path for every package of a technology, which is
|
|
181
|
+
* saying "stamp it where there is one" and cannot know which repositories keep a constant there.
|
|
182
|
+
* A bare string still throws; the asker chooses, the way `file.exists()` and `file.resolve()`
|
|
183
|
+
* already split the same question.
|
|
184
|
+
*/
|
|
173
185
|
export type VersionStampEntry = string | {
|
|
174
186
|
file: string;
|
|
175
187
|
constant?: string;
|
|
188
|
+
optional?: boolean;
|
|
176
189
|
};
|
|
177
190
|
type Args = RmanConfig.ArgsOf<typeof config, typeof COMMAND>;
|
|
178
191
|
declare const versionCommand: (app: import("../index.js").RmanApplication) => {
|
package/constants.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const version = '2.
|
|
1
|
+
export const version = '2.2.0';
|
package/package.json
CHANGED
|
@@ -291,6 +291,10 @@ export class VersionService extends Service {
|
|
|
291
291
|
const before = fs.readFileSync(file, 'utf-8');
|
|
292
292
|
const next = Manifest.stampVersion(pkg, file, before, version, { constant: entry.constant });
|
|
293
293
|
if (next === undefined) {
|
|
294
|
+
/** Unreachable in a normal run - `assertStampable` already refused, before any write. Kept
|
|
295
|
+
* because this function is exported and a caller may reach it directly. */
|
|
296
|
+
if (entry.optional)
|
|
297
|
+
continue;
|
|
294
298
|
const relative = path.relative(pkg.dirname, file);
|
|
295
299
|
throw new Error(`"version.stamp" lists "${relative}" for "${pkg.name}", but nothing in it could be ` +
|
|
296
300
|
`rewritten to ${version}.\n` +
|
|
@@ -320,12 +324,26 @@ export class VersionService extends Service {
|
|
|
320
324
|
const VERSION_LIFECYCLE = 'version';
|
|
321
325
|
/**
|
|
322
326
|
* `.rmanrc "version.stamp"`, normalized: a bare string is the file, an object may also name the
|
|
323
|
-
* identifier that holds the version (`{ file: 'src/version.go', constant: 'Version' }`)
|
|
327
|
+
* identifier that holds the version (`{ file: 'src/version.go', constant: 'Version' }`) and may
|
|
328
|
+
* mark the entry `optional`.
|
|
324
329
|
*
|
|
325
330
|
* The object form exists because the identifier was unnameable: `stampVersionConstant` took a
|
|
326
331
|
* `name` and nothing ever passed it, so only the exact lowercase word `version` was ever matched -
|
|
327
332
|
* `VERSION`, `Version` and `appVersion` were all silently skipped.
|
|
328
333
|
*/
|
|
334
|
+
/* **`optional` exists because the entry and the expectation can have different authors.** A file
|
|
335
|
+
* that exists and holds nothing rewritable is an error precisely because it means somebody asked
|
|
336
|
+
* for something and did not get it - but "somebody" is not always the repository. A *shared preset*
|
|
337
|
+
* naming `src/constants.ts` for every package of a technology is saying "stamp it where there is
|
|
338
|
+
* one", and it cannot know which of forty repositories actually keeps a version constant there.
|
|
339
|
+
* Measured on `panates/postgrejs`, which extends `@panates/rman-preset`: the file exists, has never
|
|
340
|
+
* held a version constant, and `rman version` therefore refused the release for a line no one in
|
|
341
|
+
* that repository wrote.
|
|
342
|
+
*
|
|
343
|
+
* So the *asker* says which it meant, and the two spellings keep their own failure modes: a bare
|
|
344
|
+
* string still throws, which is what catches a typo'd path or a renamed identifier before it
|
|
345
|
+
* silently ships a stale constant on every release from then on. It is the `file.exists()` /
|
|
346
|
+
* `file.resolve()` split again - the optional form and the throwing form, chosen by the caller. */
|
|
329
347
|
function readStampEntries(pkg) {
|
|
330
348
|
const configured = pkg.config?.version?.stamp;
|
|
331
349
|
const list = Array.isArray(configured) ? configured : configured ? [configured] : [];
|
|
@@ -334,7 +352,11 @@ function readStampEntries(pkg) {
|
|
|
334
352
|
if (typeof item === 'string')
|
|
335
353
|
entries.push({ file: item });
|
|
336
354
|
else if (item && typeof item === 'object' && typeof item.file === 'string') {
|
|
337
|
-
entries.push({
|
|
355
|
+
entries.push({
|
|
356
|
+
file: item.file,
|
|
357
|
+
constant: item.constant,
|
|
358
|
+
optional: item.optional === true,
|
|
359
|
+
});
|
|
338
360
|
}
|
|
339
361
|
}
|
|
340
362
|
return entries;
|
|
@@ -355,6 +377,10 @@ function assertStampable(pkg, version) {
|
|
|
355
377
|
});
|
|
356
378
|
if (next !== undefined)
|
|
357
379
|
continue;
|
|
380
|
+
/** The entry said "stamp it if there is one", so there being none is the answer rather than a
|
|
381
|
+
* mistake - see `readStampEntries`. */
|
|
382
|
+
if (entry.optional)
|
|
383
|
+
continue;
|
|
358
384
|
const relative = path.relative(pkg.dirname, file);
|
|
359
385
|
throw new Error(`"version.stamp" lists "${relative}" for "${pkg.name}", but nothing in it could be ` +
|
|
360
386
|
`rewritten to ${version}.\n` +
|