versionary 0.24.0 → 0.25.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/README.md CHANGED
@@ -144,6 +144,17 @@ For a quick trial, use:
144
144
  Python source file (e.g. `src/<pkg>/__init__.py`) to update a `__version__`
145
145
  assignment instead. Refreshes `poetry.lock`/`uv.lock`/`pdm.lock` at the
146
146
  package root if present
147
+ - `release-type` can also be an array of strategy names to compose them across
148
+ manifests, e.g. `["python", "rust"]` for a PyO3/maturin project: the first
149
+ entry is the *primary* (drives `readVersion`, `readPackageName`, and consumes
150
+ any `version-file` override); each *secondary* writes its default manifest
151
+ with the same target version. Common combinations:
152
+ - `["python", "rust"]` — PyO3/maturin (`pyproject.toml` + `Cargo.toml` +
153
+ `Cargo.lock`)
154
+ - `["node", "rust"]` — napi-rs (`package.json` + `Cargo.toml` + `Cargo.lock`)
155
+ - `["r", "rust"]` — R packages with embedded Rust crates (note: nested
156
+ `src/rust/Cargo.toml` layouts are not supported by the array form yet —
157
+ use a single strategy until per-strategy `version-file` overrides land)
147
158
  - simple/default strategy keeps `version.txt` as source of truth and does not
148
159
  update `package.json`
149
160
  - stable release branch (`release-branch`, default: `versionary/release`) so
@@ -30,9 +30,9 @@ export declare const configSchema: z.ZodObject<{
30
30
  "bump-minor-pre-major": z.ZodOptional<z.ZodBoolean>;
31
31
  "allow-stable-major": z.ZodOptional<z.ZodBoolean>;
32
32
  "include-commit-authors": z.ZodOptional<z.ZodBoolean>;
33
- "release-type": z.ZodOptional<z.ZodString>;
33
+ "release-type": z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
34
34
  packages: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
35
- "release-type": z.ZodOptional<z.ZodString>;
35
+ "release-type": z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
36
36
  "package-name": z.ZodOptional<z.ZodString>;
37
37
  "changelog-file": z.ZodOptional<z.ZodString>;
38
38
  "changelog-format": z.ZodOptional<z.ZodEnum<{
@@ -54,7 +54,9 @@ const artifactRuleSchema = zod_1.z
54
54
  });
55
55
  const packageSchema = zod_1.z
56
56
  .object({
57
- "release-type": zod_1.z.string().optional(),
57
+ "release-type": zod_1.z
58
+ .union([zod_1.z.string().min(1), zod_1.z.array(zod_1.z.string().min(1)).min(1)])
59
+ .optional(),
58
60
  "package-name": zod_1.z.string().optional(),
59
61
  "changelog-file": zod_1.z.string().optional(),
60
62
  "changelog-format": zod_1.z.enum(["markdown-changelog", "r-news"]).optional(),
@@ -83,7 +85,9 @@ exports.configSchema = zod_1.z
83
85
  "bump-minor-pre-major": zod_1.z.boolean().optional(),
84
86
  "allow-stable-major": zod_1.z.boolean().optional(),
85
87
  "include-commit-authors": zod_1.z.boolean().optional(),
86
- "release-type": zod_1.z.string().optional(),
88
+ "release-type": zod_1.z
89
+ .union([zod_1.z.string().min(1), zod_1.z.array(zod_1.z.string().min(1)).min(1)])
90
+ .optional(),
87
91
  packages: zod_1.z.record(zod_1.z.string().min(1), packageSchema).optional(),
88
92
  })
89
93
  .strict()
@@ -0,0 +1,2 @@
1
+ import type { VersionStrategy } from "./types.js";
2
+ export declare function compositeVersionStrategy(strategies: readonly VersionStrategy[]): VersionStrategy;
@@ -0,0 +1,100 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.compositeVersionStrategy = compositeVersionStrategy;
4
+ function configForSecondary(config) {
5
+ if (config["version-file"] === undefined) {
6
+ return config;
7
+ }
8
+ const { "version-file": _omit, ...rest } = config;
9
+ return rest;
10
+ }
11
+ function dedupedSorted(values) {
12
+ return [...new Set(values)].sort((a, b) => a.localeCompare(b));
13
+ }
14
+ function compositeVersionStrategy(strategies) {
15
+ if (strategies.length === 0) {
16
+ throw new Error("compositeVersionStrategy requires at least one strategy.");
17
+ }
18
+ if (strategies.length === 1) {
19
+ const only = strategies[0];
20
+ if (!only) {
21
+ throw new Error("compositeVersionStrategy requires at least one strategy.");
22
+ }
23
+ return only;
24
+ }
25
+ const primary = strategies[0];
26
+ const secondaries = strategies.slice(1);
27
+ if (!primary) {
28
+ throw new Error("compositeVersionStrategy requires at least one strategy.");
29
+ }
30
+ const composite = {
31
+ name: strategies.map((strategy) => strategy.name).join("+"),
32
+ getVersionFile(config) {
33
+ return primary.getVersionFile(config);
34
+ },
35
+ readVersion(cwd, config) {
36
+ return primary.readVersion(cwd, config);
37
+ },
38
+ writeVersion(cwd, config, version) {
39
+ const updated = [];
40
+ updated.push(...primary.writeVersion(cwd, config, version));
41
+ const secondaryConfig = configForSecondary(config);
42
+ for (const secondary of secondaries) {
43
+ updated.push(...secondary.writeVersion(cwd, secondaryConfig, version));
44
+ }
45
+ return dedupedSorted(updated);
46
+ },
47
+ };
48
+ if (primary.getDefaultChangelogFormat ||
49
+ secondaries.some((strategy) => strategy.getDefaultChangelogFormat)) {
50
+ composite.getDefaultChangelogFormat = () => {
51
+ return primary.getDefaultChangelogFormat?.() ?? "markdown-changelog";
52
+ };
53
+ }
54
+ if (primary.validateProject ||
55
+ secondaries.some((strategy) => strategy.validateProject)) {
56
+ composite.validateProject = (cwd, config) => {
57
+ const messages = [];
58
+ const primaryError = primary.validateProject?.(cwd, config) ?? null;
59
+ if (primaryError) {
60
+ messages.push(primaryError);
61
+ }
62
+ const secondaryConfig = configForSecondary(config);
63
+ for (const secondary of secondaries) {
64
+ const error = secondary.validateProject?.(cwd, secondaryConfig) ?? null;
65
+ if (error) {
66
+ messages.push(error);
67
+ }
68
+ }
69
+ return messages.length === 0 ? null : messages.join("\n");
70
+ };
71
+ }
72
+ if (primary.readPackageName) {
73
+ composite.readPackageName = (cwd, config) => {
74
+ return primary.readPackageName?.(cwd, config) ?? null;
75
+ };
76
+ }
77
+ if (primary.propagateDependentPatchImpacts ||
78
+ secondaries.some((strategy) => strategy.propagateDependentPatchImpacts)) {
79
+ composite.propagateDependentPatchImpacts = (cwd, packages) => {
80
+ const impacted = [];
81
+ impacted.push(...(primary.propagateDependentPatchImpacts?.(cwd, packages) ?? []));
82
+ for (const secondary of secondaries) {
83
+ impacted.push(...(secondary.propagateDependentPatchImpacts?.(cwd, packages) ?? []));
84
+ }
85
+ return dedupedSorted(impacted);
86
+ };
87
+ }
88
+ if (primary.finalizeVersionWrites ||
89
+ secondaries.some((strategy) => strategy.finalizeVersionWrites)) {
90
+ composite.finalizeVersionWrites = (cwd, writes, context) => {
91
+ const updated = [];
92
+ updated.push(...(primary.finalizeVersionWrites?.(cwd, writes, context) ?? []));
93
+ for (const secondary of secondaries) {
94
+ updated.push(...(secondary.finalizeVersionWrites?.(cwd, writes, context) ?? []));
95
+ }
96
+ return dedupedSorted(updated);
97
+ };
98
+ }
99
+ return composite;
100
+ }
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.listKnownReleaseTypes = listKnownReleaseTypes;
4
4
  exports.resolveVersionStrategy = resolveVersionStrategy;
5
+ const composite_js_1 = require("./composite.js");
5
6
  const latex_js_1 = require("./latex.js");
6
7
  const node_js_1 = require("./node.js");
7
8
  const python_js_1 = require("./python.js");
@@ -19,12 +20,30 @@ const strategyRegistry = {
19
20
  function listKnownReleaseTypes() {
20
21
  return Object.keys(strategyRegistry).sort((a, b) => a.localeCompare(b));
21
22
  }
22
- function resolveVersionStrategy(config) {
23
- const releaseType = config["release-type"] ?? "simple";
24
- const strategy = strategyRegistry[releaseType];
23
+ function resolveSingle(name) {
24
+ const strategy = strategyRegistry[name];
25
25
  if (!strategy) {
26
26
  const known = listKnownReleaseTypes().join(", ");
27
- throw new Error(`Unsupported release-type "${releaseType}". Supported release types: ${known}.`);
27
+ throw new Error(`Unsupported release-type "${name}". Supported release types: ${known}.`);
28
28
  }
29
29
  return strategy;
30
30
  }
31
+ function resolveVersionStrategy(config) {
32
+ const releaseType = config["release-type"] ?? "simple";
33
+ if (Array.isArray(releaseType)) {
34
+ if (releaseType.length === 0) {
35
+ throw new Error("release-type array must contain at least one strategy name.");
36
+ }
37
+ const seen = new Set();
38
+ const strategies = [];
39
+ for (const name of releaseType) {
40
+ if (seen.has(name)) {
41
+ throw new Error(`release-type array contains duplicate entry "${name}".`);
42
+ }
43
+ seen.add(name);
44
+ strategies.push(resolveSingle(name));
45
+ }
46
+ return (0, composite_js_1.compositeVersionStrategy)(strategies);
47
+ }
48
+ return resolveSingle(releaseType);
49
+ }
@@ -763,6 +763,10 @@ exports.rustVersionStrategy = {
763
763
  finalizeVersionWrites(cwd, writes, _context) {
764
764
  const manifestToVersion = {};
765
765
  for (const write of writes) {
766
+ if (node_path_1.default.posix.basename(normalizeSlashPath(write.versionFile)) !==
767
+ "Cargo.toml") {
768
+ continue;
769
+ }
766
770
  manifestToVersion[write.versionFile] = write.version;
767
771
  }
768
772
  return [
@@ -9,7 +9,7 @@ export interface VersionaryArtifactRule {
9
9
  pattern?: string;
10
10
  }
11
11
  export interface VersionaryPackage {
12
- "release-type"?: string;
12
+ "release-type"?: string | string[];
13
13
  "package-name"?: string;
14
14
  "changelog-file"?: string;
15
15
  "changelog-format"?: VersionaryChangelogFormat;
@@ -33,7 +33,7 @@ export interface VersionaryConfig {
33
33
  "bump-minor-pre-major"?: boolean;
34
34
  "allow-stable-major"?: boolean;
35
35
  "include-commit-authors"?: boolean;
36
- "release-type"?: string;
36
+ "release-type"?: string | string[];
37
37
  packages?: Record<string, VersionaryPackage>;
38
38
  }
39
39
  export interface LoadedConfig {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "versionary",
3
- "version": "0.24.0",
3
+ "version": "0.25.0",
4
4
  "description": "Automatic release framework based on conventional commits and semantic versioning",
5
5
  "keywords": [
6
6
  "releasing",