Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
feat: support LiquidJS templates in strategy properties
Property values are now rendered through the template engine with the
same context available to version and tag templates. This allows
properties like:

  properties:
    previousVersion: "{{ commitInfo.previousSemVerReleaseVersion }}"
    baseVersion: "{{ commitInfo.previousSemVerReleaseVersion | semver_inc: 'minor' }}"

Static string values continue to work as before.

Closes #64
  • Loading branch information
maff committed Mar 15, 2026
commit 653f66dd4a80e8aafb183810078595fd81eb83b3
24 changes: 12 additions & 12 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,12 +87,12 @@ output:

Settings defined here are inherited by all strategies via deep merge (except `branchPrefixes`, which is only used at the top level).

| Key | Type | Default | Description |
| ---------------- | ------------------------ | ------- | -------------------------------------------------------- |
| `branchPrefixes` | `string[]` | `[]` | Prefixes stripped from branch names before slugification |
| `snapshot` | `SnapshotConfig` | `{}` | Snapshot version generation settings |
| `tags` | `TagsConfig` | `{}` | Tag generation settings |
| `properties` | `Record<string, string>` | `{}` | Custom key-value pairs included in output |
| Key | Type | Default | Description |
| ---------------- | ------------------------ | ------- | --------------------------------------------------------------------------------------- |
| `branchPrefixes` | `string[]` | `[]` | Prefixes stripped from branch names before slugification |
| `snapshot` | `SnapshotConfig` | `{}` | Snapshot version generation settings |
| `tags` | `TagsConfig` | `{}` | Tag generation settings |
| `properties` | `Record<string, string>` | `{}` | Custom key-value pairs included in output (supports [LiquidJS templates](templates.md)) |

### SnapshotConfig

Expand Down Expand Up @@ -125,12 +125,12 @@ Each entry is a LiquidJS template. Empty results are filtered out, and duplicate

Each strategy is an independent configuration that produces its own version string and tags. Strategies inherit from `defaults` via deep merge.

| Key | Type | Default | Description |
| ------------ | ------------------------ | ------- | ---------------------------------------------- |
| `enabled` | `boolean` | `true` | Whether this strategy is active |
| `snapshot` | `SnapshotConfig` | `{}` | Snapshot settings (merged with defaults) |
| `tags` | `TagsConfig` | `{}` | Tag generation settings (merged with defaults) |
| `properties` | `Record<string, string>` | `{}` | Custom key-value pairs included in output |
| Key | Type | Default | Description |
| ------------ | ------------------------ | ------- | --------------------------------------------------------------------------------------- |
| `enabled` | `boolean` | `true` | Whether this strategy is active |
| `snapshot` | `SnapshotConfig` | `{}` | Snapshot settings (merged with defaults) |
| `tags` | `TagsConfig` | `{}` | Tag generation settings (merged with defaults) |
| `properties` | `Record<string, string>` | `{}` | Custom key-value pairs included in output (supports [LiquidJS templates](templates.md)) |

### OutputConfig

Expand Down
1 change: 1 addition & 0 deletions docs/templates.md
Original file line number Diff line number Diff line change
Expand Up @@ -191,4 +191,5 @@ strategies:
- "{% if versionInfo.isHighestSemVerReleaseVersion %}stable{% endif %}"
properties:
chartName: my-app
previousVersion: "{{ commitInfo.previousSemVerReleaseVersion }}"
```
54 changes: 54 additions & 0 deletions src/version/versionStrategy.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,25 @@ describe("VersionStrategy", () => {
);
expect(result.customProp).toBe("value");
});

it("should render template expressions in properties", () => {
const config = createStrategyConfig({
properties: {
commitSha: "{{ commitInfo.sha }}",
tagName: "{{ version }}",
static: "plain-value",
},
});
const strategy = new VersionStrategy("test", config);
const result = strategy.taggedVersionResult(
createContext({ isTaggedVersion: true }),
createCommitInfo({ sha: "abc123def456", tag: "build-123" }),
"build-123",
);
expect(result.commitSha).toBe("abc123def456");
expect(result.tagName).toBe("build-123");
expect(result.static).toBe("plain-value");
});
});

describe("semVerVersionResult", () => {
Expand All @@ -164,6 +183,24 @@ describe("VersionStrategy", () => {
expect(result.version).toBe("1.2.3");
});

it("should render template expressions in properties with semVer context", () => {
const config = createStrategyConfig({
properties: {
majorVersion: "{{ semVer.major }}",
previousRelease: "{{ commitInfo.previousSemVerReleaseVersion }}",
},
});
const strategy = new VersionStrategy("test", config);
const version = semver.parse("2.3.0")!;
const result = strategy.semVerVersionResult(
createContext({ isSemVerVersion: true }),
createCommitInfo({ tag: "v2.3.0" }),
version,
);
expect(result.majorVersion).toBe("2");
expect(result.previousRelease).toBe("1.0.0");
});

it("should make semVer context available in tag templates", () => {
const strategy = new VersionStrategy("test", createStrategyConfig());
const version = semver.parse("2.3.0")!;
Expand Down Expand Up @@ -290,5 +327,22 @@ describe("VersionStrategy", () => {
);
expect(result.version).toEndWith("-SNAPSHOT");
});

it("should render template expressions in properties with snapshot context", () => {
const config = createStrategyConfig({
properties: {
baseVersion:
"{{ commitInfo.previousSemVerReleaseVersion | semver_inc: 'minor' }}",
snapshotVersion: "{{ version }}",
},
});
const strategy = new VersionStrategy("test", config);
const result = strategy.snapshotVersionResult(
createContext({ isSnapshotVersion: true }),
createCommitInfo(),
);
expect(result.baseVersion).toBe("1.1.0");
expect(result.snapshotVersion).toBe("1.0.0-20240101120000.abc123def456");
});
});
});
55 changes: 35 additions & 20 deletions src/version/versionStrategy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,15 @@ export class VersionStrategy {
commitInfo: CommitInfo,
tag: string,
): StrategyVersion {
const tplContext = {
...this.templateContext(context, commitInfo),
version: tag,
};

return {
version: tag,
tags: this.uniqueTags(this.config.tags.tagged, {
...this.templateContext(context, commitInfo),
version: tag,
}),
...this.config.properties,
tags: this.uniqueTags(this.config.tags.tagged, tplContext),
...this.renderProperties(tplContext),
};
Comment on lines 35 to 39
}

Expand All @@ -44,14 +46,16 @@ export class VersionStrategy {
): StrategyVersion {
const stringVersion = semVerVersionString(version);

const tplContext = {
...this.templateContext(context, commitInfo),
version: stringVersion,
semVer: version,
};

return {
version: stringVersion,
tags: this.uniqueTags(this.config.tags.semVer, {
...this.templateContext(context, commitInfo),
version: stringVersion,
semVer: version,
}),
...this.config.properties,
tags: this.uniqueTags(this.config.tags.semVer, tplContext),
...this.renderProperties(tplContext),
};
Comment on lines 55 to 59
}

Expand Down Expand Up @@ -99,17 +103,19 @@ export class VersionStrategy {
},
);

const snapshotTplContext = {
...templateContext,
version,
prefix,
suffix,
branchIdentifier,
commitIdentifier,
};

return {
version: version,
tags: this.uniqueTags(this.config.tags.snapshot, {
...templateContext,
version,
prefix,
suffix,
branchIdentifier,
commitIdentifier,
}),
...this.config.properties,
tags: this.uniqueTags(this.config.tags.snapshot, snapshotTplContext),
...this.renderProperties(snapshotTplContext),
};
Comment on lines 115 to 119
}

Expand All @@ -125,6 +131,15 @@ export class VersionStrategy {
};
}

private renderProperties(context: any): Record<string, string> {
return Object.fromEntries(
Object.entries(this.config.properties).map(([key, value]) => [
key,
templateEngine.parseAndRenderSync(value, context),
]),
);
}

private uniqueTags(templates: string[], context: any) {
if (!this.config.tags.enabled) {
return [];
Expand Down
Loading