relizy 1.8.0 → 1.10.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
@@ -58,6 +58,7 @@ Imagine you have multiple packages in your project (like a box with several toys
58
58
  - ⚙️ Multiple configuration files support for different release workflows
59
59
  - 🔧 Support for npm, yarn, pnpm, and bun (auto-detected)
60
60
  - 📱 Social media integration (Twitter & Slack) for release announcements
61
+ - 🧹 Built-in commit linting with your Relizy config, a commitlint replacement (`relizy commitlint`)
61
62
 
62
63
  ## 📚 Documentation
63
64
 
@@ -136,6 +137,15 @@ Automatically post release announcements to Twitter and Slack when you ship new
136
137
  relizy release --minor # Automatically posts to configured social channels
137
138
  ```
138
139
 
140
+ ### Commit Linting
141
+
142
+ Lint your commit messages with your Relizy config: the same parser, types and packages as your releases, and commit bodies checked as they will appear in your changelogs. No commitlint config to keep in sync.
143
+
144
+ ```bash
145
+ relizy commitlint --install # Writes the commit-msg hook
146
+ relizy commitlint # Lints the commits of the pull request in CI
147
+ ```
148
+
139
149
  ## 📖 Learn More
140
150
 
141
151
  This README covers the basics to get you started quickly. For detailed documentation, configuration options, and advanced features, visit our full documentation:
@@ -148,6 +158,7 @@ Topics covered in the documentation:
148
158
  - Monorepo versioning strategies (unified, selective, independent)
149
159
  - CI/CD integration (GitHub Actions, GitLab CI)
150
160
  - Social media integration (Twitter & Slack)
161
+ - [Commit linting](https://relizy.dev/commitlint/)
151
162
  - Custom registries and private packages
152
163
  - Multiple configuration files
153
164
  - And much more...
package/dist/cli.mjs CHANGED
@@ -4,30 +4,35 @@ import { dirname, join } from 'node:path';
4
4
  import process from 'node:process';
5
5
  import { fileURLToPath } from 'node:url';
6
6
  import { printBanner, logger } from '@maz-ui/node';
7
- import { Command } from 'commander';
8
- import { aD as isInCI, W as getCIName, h as bump, j as changelog, aV as publish, aT as providerRelease, bc as social, aS as prComment, b2 as release } from './shared/relizy.BljqIKug.mjs';
7
+ import { Command, Option } from 'commander';
8
+ import { b6 as isInCI, ad as getCIName, o as bump, q as changelog, bs as publish, bq as providerRelease, bS as social, u as commitlint, bp as prComment, bC as release } from './shared/relizy.BY0-QHlV.mjs';
9
9
  import 'node:child_process';
10
+ import 'node:module';
11
+ import 'mdast-util-from-markdown';
12
+ import 'mdast-util-gfm';
13
+ import 'micromark-extension-gfm';
14
+ import 'fast-glob';
15
+ import 'changelogen';
10
16
  import '@maz-ui/utils/helpers/formatJson';
11
17
  import 'c12';
12
- import 'changelogen';
13
18
  import 'defu';
14
19
  import '@inquirer/prompts';
15
20
  import 'micromatch';
16
21
  import 'semver';
17
22
  import '@maz-ui/utils/helpers/getErrorMessage';
18
- import 'fast-glob';
19
23
  import '@maz-ui/utils/helpers/upperFirst';
20
24
  import 'convert-gitmoji';
21
25
  import 'node-fetch-native';
22
26
 
23
27
  const hasSilentFlag = process.argv.includes("--log-level") && process.argv.includes("silent");
28
+ const isCommitlint = process.argv[2] === "commitlint";
24
29
  const __filename$1 = fileURLToPath(import.meta.url);
25
30
  const __dirname$1 = dirname(__filename$1);
26
31
  const packageJson = JSON.parse(
27
32
  readFileSync(join(__dirname$1, "../package.json"), "utf-8")
28
33
  );
29
34
  const version = packageJson.version;
30
- if (!hasSilentFlag) {
35
+ if (!hasSilentFlag && !isCommitlint) {
31
36
  printBanner({
32
37
  name: "Relizy",
33
38
  version: `v${version}`,
@@ -41,7 +46,7 @@ if (!hasSilentFlag) {
41
46
  }
42
47
  });
43
48
  }
44
- if (isInCI()) {
49
+ if (isInCI() && !isCommitlint) {
45
50
  logger.log(`Running in CI: ${getCIName()}`);
46
51
  } else {
47
52
  logger.debug("Running locally");
@@ -68,6 +73,9 @@ function getReleaseType(options) {
68
73
  type = "prepatch";
69
74
  return type;
70
75
  }
76
+ function slackFormatOption() {
77
+ return new Option("--slack-format <format>", "Slack changelog format, overrides social.slack.changelogFormat").choices(["summary", "full"]);
78
+ }
71
79
  program.name("relizy").description("Release management tool for monorepos and standalone packages").version(version).option("--config <name>", "Config file name (without .config.ts - e.g. changelog-test)").option("--no-safety-check", "Skip safety check").option("--log-level <level>", "Set log level (silent, error, warning, normal, default, debug, trace, verbose)", "default").option("--dry-run", "Preview changes without writing files, creating tags, commits or publishing").option("--pr-number <number>", "Override PR/MR number for PR comment features", Number);
72
80
  program.command("bump").description("Bump package versions").option("--major", "Bump major version").option("--minor", "Bump minor version").option("--patch", "Bump patch version").option("--prerelease", "Bump prerelease version").option("--premajor", "Bump premajor version").option("--preminor", "Bump preminor version").option("--prepatch", "Bump prepatch version").option("--preid <id>", "Prerelease identifier (alpha, beta, rc, etc.)").option("--suffix <suffix>", "Custom suffix for prerelease versions - replace the last .X with .suffix (e.g. 1.0.0-beta.0 -> 1.0.0-beta.suffix)").option("--no-clean", "Skip check if the working directory is clean").option("--force", "Bump even if there are no commits").option("--yes", "Skip confirmation prompt about bumping packages").option("--canary", "Publish a canary release from the current commit").option("--include-private", "Include private packages in the bump").action(async (options) => {
73
81
  try {
@@ -146,7 +154,7 @@ program.command("provider-release").description("Publish release to git provider
146
154
  process.exit(1);
147
155
  }
148
156
  });
149
- program.command("social").description("Post release announcements to social media platforms").option("--from <ref>", "Start commit reference").option("--to <ref>", "End commit reference").option("--ai", "Force-enable AI for social posts").option("--no-ai", "Force-disable AI for social posts").action(async (options) => {
157
+ program.command("social").description("Post release announcements to social media platforms").option("--from <ref>", "Start commit reference").option("--to <ref>", "End commit reference").option("--ai", "Force-enable AI for social posts").option("--no-ai", "Force-disable AI for social posts").addOption(slackFormatOption()).action(async (options) => {
150
158
  try {
151
159
  await social({
152
160
  from: options.from,
@@ -155,12 +163,43 @@ program.command("social").description("Post release announcements to social medi
155
163
  logLevel: program.opts().logLevel,
156
164
  configName: program.opts().config,
157
165
  safetyCheck: hasCliFlag("--no-safety-check") ? false : void 0,
158
- ai: hasCliFlag("--ai") ? true : hasCliFlag("--no-ai") ? false : void 0
166
+ ai: hasCliFlag("--ai") ? true : hasCliFlag("--no-ai") ? false : void 0,
167
+ slackFormat: options.slackFormat
159
168
  });
160
169
  } catch {
161
170
  process.exit(1);
162
171
  }
163
172
  });
173
+ program.command("commitlint").description("Lint commit messages with the relizy config (types, scopes, changelog rendering)").option("--edit [file]", "Lint the message of the commit being created (the file given to the commit-msg hook, .git/COMMIT_EDITMSG by default)").option("--message <message>", "Lint this message").option("--from <ref>", "Lint the commits after this ref (default: merge-base of the pull/merge request in CI, otherwise the last tag)").option("--to <ref>", "Last commit of the range (default: HEAD)").option("--title", "Also lint the title of the pull/merge request in CI (default: commitlint.title)").option("--no-title", "Do not lint the title of the pull/merge request in CI").option("--preview", "Print the changelog entry of each commit").option("--quiet", "Only print the commits with problems, and the summary").addOption(new Option("--format <format>", "Output format: text for people, json for programs and AI agents").choices(["text", "json"]).default("text")).option("--install", "Write the commit-msg hook running relizy commitlint (in .husky/ when husky is set up)").option("--force", "Replace an existing commit-msg hook with --install").action(async (options) => {
174
+ try {
175
+ const { errorCount } = await commitlint({
176
+ edit: options.edit,
177
+ message: options.message,
178
+ from: options.from,
179
+ to: options.to,
180
+ title: options.title,
181
+ preview: options.preview,
182
+ format: options.format,
183
+ quiet: options.quiet,
184
+ install: options.install,
185
+ force: options.force,
186
+ configName: program.opts().config,
187
+ logLevel: program.opts().logLevel
188
+ });
189
+ if (errorCount > 0) {
190
+ process.exit(1);
191
+ }
192
+ } catch (error) {
193
+ const message = error instanceof Error ? error.message : String(error);
194
+ if (options.format === "json") {
195
+ process.stdout.write(`${JSON.stringify({ valid: false, error: message }, null, 2)}
196
+ `);
197
+ } else {
198
+ logger.error("Failed to lint the commits -", message);
199
+ }
200
+ process.exit(1);
201
+ }
202
+ });
164
203
  program.command("pr-comment").description("Post or re-post a PR comment with release information").action(async () => {
165
204
  try {
166
205
  await prComment({
@@ -174,7 +213,7 @@ program.command("pr-comment").description("Post or re-post a PR comment with rel
174
213
  process.exit(1);
175
214
  }
176
215
  });
177
- program.command("release").description("Complete release workflow (bump + changelog + commit + tag + push to remote + publish release)").option("--major", "Bump major version").option("--minor", "Bump minor version").option("--patch", "Bump patch version").option("--prerelease", "Bump prerelease version").option("--premajor", "Bump premajor version").option("--preminor", "Bump preminor version").option("--prepatch", "Bump prepatch version").option("--preid <id>", "Prerelease identifier (alpha, beta, rc, etc.)").option("--suffix <suffix>", "Custom suffix for prerelease versions - replace the last .X with .suffix (e.g. 1.0.0-beta.0 -> 1.0.0-beta.suffix)").option("--from <ref>", "Start commit reference").option("--to <ref>", "End commit reference").option("--no-push", "Skip push changes and tags to remote").option("--no-provider-release", "Skip release creation (GitHub/GitLab)").option("--no-publish", "Skip npm publish").option("--registry <url>", "Custom npm registry URL").option("--tag <tag>", "Publish with specific tag (default: latest for stable, next for prerelease)").option("--access <type>", "Package access level (public or restricted)").option("--otp <code>", "One-time password for 2FA").option("--no-verify", "Skip git hooks during commit").option("--format-cmd <cmd>", 'Command to format CHANGELOG files after generation (e.g. "pnpm lint")').option("--build-cmd <cmd>", 'Command to build packages before publish (e.g. "pnpm build")').option("--no-root-changelog", "Skip generation of root changelog file").option("--token <token>", "Git token (github or gitlab)").option("--force", "Bump even if there are no commits").option("--no-clean", "Skip check if the working directory is clean").option("--no-commit", "Skip commit and tag").option("--no-git-tag", "Skip tag creation").option("--no-changelog", "Skip changelog generation files").option("--provider <provider>", "Git provider (github or gitlab)").option("--no-social", "Skip social media posting").option("--no-pr-comment", "Skip PR comment posting").option("--yes", "Skip confirmation prompt about bumping packages").option("--publish-token <token>", 'NPM token (e.g. "123456") - only supported for pnpm and npm').option("--skip-existing-versions", "Skip packages whose version already exists on the registry instead of failing").option("--canary", "Publish a canary release from the current commit").option("--include-private", "Include private packages in bump and changelog phases").option("--ai", "Force-enable AI for release notes and social posts").option("--no-ai", "Force-disable AI for release notes and social posts").action(async (options) => {
216
+ program.command("release").description("Complete release workflow (bump + changelog + commit + tag + push to remote + publish release)").option("--major", "Bump major version").option("--minor", "Bump minor version").option("--patch", "Bump patch version").option("--prerelease", "Bump prerelease version").option("--premajor", "Bump premajor version").option("--preminor", "Bump preminor version").option("--prepatch", "Bump prepatch version").option("--preid <id>", "Prerelease identifier (alpha, beta, rc, etc.)").option("--suffix <suffix>", "Custom suffix for prerelease versions - replace the last .X with .suffix (e.g. 1.0.0-beta.0 -> 1.0.0-beta.suffix)").option("--from <ref>", "Start commit reference").option("--to <ref>", "End commit reference").option("--no-push", "Skip push changes and tags to remote").option("--no-provider-release", "Skip release creation (GitHub/GitLab)").option("--no-publish", "Skip npm publish").option("--registry <url>", "Custom npm registry URL").option("--tag <tag>", "Publish with specific tag (default: latest for stable, next for prerelease)").option("--access <type>", "Package access level (public or restricted)").option("--otp <code>", "One-time password for 2FA").option("--no-verify", "Skip git hooks during commit").option("--format-cmd <cmd>", 'Command to format CHANGELOG files after generation (e.g. "pnpm lint")').option("--build-cmd <cmd>", 'Command to build packages before publish (e.g. "pnpm build")').option("--no-root-changelog", "Skip generation of root changelog file").option("--token <token>", "Git token (github or gitlab)").option("--force", "Bump even if there are no commits").option("--no-clean", "Skip check if the working directory is clean").option("--no-commit", "Skip commit and tag").option("--no-git-tag", "Skip tag creation").option("--no-changelog", "Skip changelog generation files").option("--provider <provider>", "Git provider (github or gitlab)").option("--no-social", "Skip social media posting").option("--no-pr-comment", "Skip PR comment posting").option("--yes", "Skip confirmation prompt about bumping packages").option("--publish-token <token>", 'NPM token (e.g. "123456") - only supported for pnpm and npm').option("--skip-existing-versions", "Skip packages whose version already exists on the registry instead of failing").option("--canary", "Publish a canary release from the current commit").option("--include-private", "Include private packages in bump and changelog phases").option("--ai", "Force-enable AI for release notes and social posts").option("--no-ai", "Force-disable AI for release notes and social posts").addOption(slackFormatOption()).action(async (options) => {
178
217
  try {
179
218
  await release({
180
219
  type: getReleaseType(options),
@@ -211,7 +250,8 @@ program.command("release").description("Complete release workflow (bump + change
211
250
  social: hasCliFlag("--no-social") ? false : void 0,
212
251
  prComment: hasCliFlag("--no-pr-comment") ? false : void 0,
213
252
  prNumber: program.opts().prNumber,
214
- ai: hasCliFlag("--ai") ? true : hasCliFlag("--no-ai") ? false : void 0
253
+ ai: hasCliFlag("--ai") ? true : hasCliFlag("--no-ai") ? false : void 0,
254
+ slackFormat: options.slackFormat
215
255
  });
216
256
  } catch (error) {
217
257
  logger.error("Failed to release -", error);