@afoures/auto-release 0.2.12 → 0.3.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.
@@ -7,17 +7,17 @@ import { relative } from "node:path";
7
7
 
8
8
  //#region src/lib/commands/tag-release-commit.ts
9
9
  /**
10
- * Get the version of an app at a specific git revision
10
+ * Get the version of a project at a specific git revision
11
11
  */
12
- async function get_app_version_at_revision(app, root, revision) {
12
+ async function get_project_version_at_revision(project, root, revision) {
13
13
  try {
14
- const version = await compute_current_version(app, { get_file_content: (file_path) => {
14
+ const version = await compute_current_version(project, { get_file_content: (file_path) => {
15
15
  const relative_path = relative(root, file_path);
16
16
  return read_file_at_revision(root, revision, relative_path);
17
- } }) ?? app.versioning.initial_version;
18
- if (!app.versioning.validate({ version })) return {
17
+ } }) ?? project.versioning.initial_version;
18
+ if (!project.versioning.validate({ version })) return {
19
19
  ok: false,
20
- error: `Invalid version format for ${app.name} at revision ${revision}: ${version}`
20
+ error: `Invalid version format for ${project.name} at revision ${revision}: ${version}`
21
21
  };
22
22
  return {
23
23
  ok: true,
@@ -26,7 +26,7 @@ async function get_app_version_at_revision(app, root, revision) {
26
26
  } catch (error) {
27
27
  return {
28
28
  ok: false,
29
- error: `Failed to get version for ${app.name} at revision ${revision}: ${error.message}`
29
+ error: `Failed to get version for ${project.name} at revision ${revision}: ${error.message}`
30
30
  };
31
31
  }
32
32
  }
@@ -60,34 +60,37 @@ const tag_release_commit = create_command({
60
60
  status: "success",
61
61
  message: "HEAD has no parent commit - nothing to tag"
62
62
  };
63
- const changed_apps = [];
64
- for (const app of config.managed_applications) {
65
- const head_result = await get_app_version_at_revision(app, root, head_sha);
63
+ const changed_projects = [];
64
+ for (const project of config.managed_projects) {
65
+ const head_result = await get_project_version_at_revision(project, root, head_sha);
66
66
  if (!head_result.ok) return {
67
67
  status: "error",
68
- error: `Failed to get HEAD version for ${app.name}: ${head_result.error}`
68
+ error: `Failed to get HEAD version for ${project.name}: ${head_result.error}`
69
69
  };
70
- const base_result = await get_app_version_at_revision(app, root, base_sha);
70
+ const base_result = await get_project_version_at_revision(project, root, base_sha);
71
71
  if (!base_result.ok) return {
72
72
  status: "error",
73
- error: `Failed to get base version for ${app.name}: ${base_result.error}`
73
+ error: `Failed to get base version for ${project.name}: ${base_result.error}`
74
74
  };
75
- if (head_result.version !== base_result.version) changed_apps.push({
76
- app,
75
+ if (head_result.version !== base_result.version) changed_projects.push({
76
+ project,
77
77
  head_version: head_result.version,
78
78
  base_version: base_result.version
79
79
  });
80
80
  }
81
- if (changed_apps.length === 0) return {
81
+ if (changed_projects.length === 0) return {
82
82
  status: "success",
83
83
  message: "No version changes detected"
84
84
  };
85
- logger.info(`Detected version changes in ${changed_apps.length} app(s):`);
86
- for (const { app, head_version, base_version } of changed_apps) logger.info(` ${app.name}: ${base_version} → ${head_version}`);
85
+ logger.info(`Detected version changes in ${changed_projects.length} project(s):`);
86
+ for (const { project, head_version, base_version } of changed_projects) logger.info(` ${project.name}: ${base_version} → ${head_version}`);
87
87
  if (dry_run) {
88
88
  logger.info("\nDry run - would create tags and releases:");
89
- for (const { app, head_version } of changed_apps) {
90
- const tag = `${app.name}@${head_version}`;
89
+ for (const { project, head_version } of changed_projects) {
90
+ const tag = config.git.tag_generator({
91
+ project: { name: project.name },
92
+ version: head_version
93
+ });
91
94
  logger.info(` - Tag: ${tag}`);
92
95
  logger.info(` - Release: ${tag}`);
93
96
  }
@@ -96,15 +99,18 @@ const tag_release_commit = create_command({
96
99
  message: "Dry run completed - no changes were made"
97
100
  };
98
101
  }
99
- const tagged_apps = [];
102
+ const tagged_projects = [];
100
103
  const errors = [];
101
- for (const { app, head_version } of changed_apps) {
102
- const tag = `${app.name}@${head_version}`;
104
+ for (const { project, head_version } of changed_projects) {
105
+ const tag = config.git.tag_generator({
106
+ project: { name: project.name },
107
+ version: head_version
108
+ });
103
109
  try {
104
110
  const existing_tag = await config.git.platform.get_tag({ tag });
105
111
  if (existing_tag !== null) if (existing_tag.commit_sha === head_sha) {
106
112
  logger.info(`Tag ${tag} already exists on commit ${head_sha} - skipping`);
107
- tagged_apps.push(tag);
113
+ tagged_projects.push(tag);
108
114
  continue;
109
115
  } else {
110
116
  errors.push(`Tag ${tag} already exists but points to different commit (${existing_tag.commit_sha} vs ${head_sha})`);
@@ -119,16 +125,16 @@ const tag_release_commit = create_command({
119
125
  tag,
120
126
  release: {
121
127
  name: tag,
122
- body: app.versioning.formatter.generate_release_notes({
123
- app: {
124
- name: app.name,
125
- changelog: app.changelog
128
+ body: project.versioning.formatter.generate_release_notes({
129
+ project: {
130
+ name: project.name,
131
+ changelog: project.changelog
126
132
  },
127
133
  version: head_version
128
134
  })
129
135
  }
130
136
  });
131
- tagged_apps.push(tag);
137
+ tagged_projects.push(tag);
132
138
  logger.success(`Tagged and released ${tag}`);
133
139
  } catch (error) {
134
140
  errors.push(`Failed to tag/release ${tag}: ${error.message}`);
@@ -140,7 +146,7 @@ const tag_release_commit = create_command({
140
146
  };
141
147
  return {
142
148
  status: "success",
143
- message: tagged_apps.length === 1 ? `Tagged 1 app: ${tagged_apps[0]}` : `Tagged ${tagged_apps.length} apps: ${tagged_apps.join(", ")}`
149
+ message: tagged_projects.length === 1 ? `Tagged 1 project: ${tagged_projects[0]}` : `Tagged ${tagged_projects.length} projects: ${tagged_projects.join(", ")}`
144
150
  };
145
151
  }
146
152
  });
@@ -1,5 +1,5 @@
1
1
  import { GitPlatformClient } from "./platforms/types.mjs";
2
- import { AutoReleaseConfig, ManagedApplication } from "./types.mjs";
2
+ import { AutoReleaseConfig, ManagedProject } from "./types.mjs";
3
3
 
4
4
  //#region src/lib/config.d.ts
5
5
  declare function define_config<const config extends AutoReleaseConfig>(config: config): InternalConfig;
@@ -14,8 +14,14 @@ declare class InternalConfig {
14
14
  platform: GitPlatformClient;
15
15
  target_branch: string;
16
16
  default_release_branch_prefix: string;
17
+ tag_generator: (args: {
18
+ project: {
19
+ name: string;
20
+ };
21
+ version: string;
22
+ }) => string;
17
23
  };
18
- get managed_applications(): Array<ManagedApplication>;
24
+ get managed_projects(): Array<ManagedProject>;
19
25
  }
20
26
  //#endregion
21
27
  export { define_config };
@@ -33,11 +33,12 @@ var InternalConfig = class {
33
33
  return {
34
34
  platform: this.#config.git.platform,
35
35
  target_branch: this.#config.git.target_branch || "main",
36
- default_release_branch_prefix: this.#config.git.default_release_branch_prefix || "release"
36
+ default_release_branch_prefix: this.#config.git.default_release_branch_prefix || "release",
37
+ tag_generator: this.#config.git.tag_generator || (({ project, version }) => `${project.name}@${version}`)
37
38
  };
38
39
  }
39
- get managed_applications() {
40
- return Object.entries(this.#config.apps).map(([name, definition]) => {
40
+ get managed_projects() {
41
+ return Object.entries(this.#config.projects).map(([name, definition]) => {
41
42
  const components = definition.components.map((component) => component(this.folder));
42
43
  return {
43
44
  name,
@@ -130,16 +131,15 @@ async function find_nearest_config(options) {
130
131
  */
131
132
  function validate_config(config) {
132
133
  if (!config.git) throw new Error("Auto-release config must have a \"git\" platform. Use github() or gitlab() from \"auto-release/providers\"");
133
- if (!config.apps || typeof config.apps !== "object" || Array.isArray(config.apps)) throw new Error("Auto-release config must have an \"apps\" record (object keyed by app name)");
134
- const app_entries = Object.entries(config.apps);
135
- if (app_entries.length === 0) throw new Error("Auto-release config must have at least one app");
136
- for (const [name, app] of app_entries) {
137
- if (!app.components || !Array.isArray(app.components)) throw new Error(`App "${name}" must have a "components" array`);
138
- if (app.components.length === 0) throw new Error(`App "${name}" must have at least one component`);
139
- if (!app.versioning) throw new Error(`App "${name}" must have a "versioning" config`);
140
- if (typeof app.versioning.bump !== "function") throw new Error(`App "${name}" versioning must have a "bump" function. Did you forget to call the strategy function?`);
141
- if (!app.versioning.allowed_changes || !Array.isArray(app.versioning.allowed_changes)) throw new Error(`App "${name}" versioning must have an "allowed_changes" array`);
142
- if (!app.changelog || typeof app.changelog !== "string") throw new Error(`App "${name}" must have a changelog path (string)`);
134
+ if (!config.projects || typeof config.projects !== "object" || Array.isArray(config.projects)) throw new Error("Auto-release config must have a \"projects\" record (object keyed by project name)");
135
+ const project_entries = Object.entries(config.projects);
136
+ for (const [name, project] of project_entries) {
137
+ if (!project.components || !Array.isArray(project.components)) throw new Error(`Project "${name}" must have a "components" array`);
138
+ if (project.components.length === 0) throw new Error(`Project "${name}" must have at least one component`);
139
+ if (!project.versioning) throw new Error(`Project "${name}" must have a "versioning" config`);
140
+ if (typeof project.versioning.bump !== "function") throw new Error(`Project "${name}" versioning must have a "bump" function. Did you forget to call the strategy function?`);
141
+ if (!project.versioning.allowed_changes || !Array.isArray(project.versioning.allowed_changes)) throw new Error(`Project "${name}" versioning must have an "allowed_changes" array`);
142
+ if (!project.changelog || typeof project.changelog !== "string") throw new Error(`Project "${name}" must have a changelog path (string)`);
143
143
  }
144
144
  }
145
145
 
@@ -88,12 +88,10 @@ function default_formatter({ allowed_changes, display_map }) {
88
88
  },
89
89
  format_changelog(changelog, context) {
90
90
  const lines = [];
91
- if (changelog.root.title) lines.push(changelog.root.title);
92
- else lines.push(`# \`${context.app.name}\` changelog`);
93
- if (changelog.root.description.length > 0) {
94
- console.log(changelog.root.description);
95
- lines.push(changelog.root.description.join("\n"));
96
- } else lines.push(`This is the changelog for \`${context.app.name}\`.`);
91
+ if (changelog.root.title) lines.push(changelog.root.title, "");
92
+ else lines.push(`# \`${context.project.name}\` changelog`, "");
93
+ if (changelog.root.description.length > 0) lines.push(changelog.root.description.join("\n"), "");
94
+ else lines.push(`This is the changelog for \`${context.project.name}\`.`, "");
97
95
  for (const release of changelog.releases) {
98
96
  const release_lines = [`## ${release.version}`, ""];
99
97
  for (const change_kind of allowed_changes) {
@@ -107,17 +105,20 @@ function default_formatter({ allowed_changes, display_map }) {
107
105
  if (release.changes.length === 0) release_lines.push("No changes in this release.", "");
108
106
  lines.push(release_lines.join("\n"));
109
107
  }
110
- return lines.join("\n\n");
108
+ return lines.join("\n");
111
109
  },
112
- generate_release_notes({ app, version }) {
110
+ generate_release_notes({ project, version }) {
113
111
  const hash = version.replaceAll(".", "");
114
- const file = `${app.changelog}#${hash}`;
115
- return `[See the changelog for ${app.name}@${version} release notes](${file})`;
112
+ const file = `${project.changelog}#${hash}`;
113
+ return `[See the changelog for ${project.name}@${version} release notes](${file})`;
116
114
  },
117
- generate_pr_body({ app, current_version, next_version, changes }) {
115
+ generate_pr_body({ project, current_version, next_version, changes }) {
118
116
  const lines = [];
119
- lines.push(`# Release ${app.name} ${next_version}`);
120
- lines.push(`Version: ${current_version} ${next_version}`);
117
+ lines.push("This PR is managed by `[auto-release](https://github.com/afoures/auto-release)`. Do not edit it manually.");
118
+ lines.push(`## Automated release for \`${project.name}\``);
119
+ lines.push(`Version: \`${current_version}\` → \`${next_version}\``);
120
+ lines.push("");
121
+ lines.push("## Changelog");
121
122
  const grouped = /* @__PURE__ */ new Map();
122
123
  for (const change of changes) {
123
124
  const group = grouped.get(change.kind) ?? [];
@@ -130,7 +131,7 @@ function default_formatter({ allowed_changes, display_map }) {
130
131
  const labels = resolved_display_map[kind];
131
132
  const heading = labels?.plural ?? labels?.singular ?? kind;
132
133
  lines.push("");
133
- lines.push(`## ${heading}`);
134
+ lines.push(`### ${heading}`);
134
135
  for (const change of items) {
135
136
  lines.push(change.summary);
136
137
  lines.push("");
@@ -13,22 +13,28 @@ interface AutoReleaseConfig {
13
13
  platform: GitPlatformClient;
14
14
  target_branch?: string;
15
15
  default_release_branch_prefix?: string;
16
+ tag_generator?: (args: {
17
+ project: {
18
+ name: string;
19
+ };
20
+ version: string;
21
+ }) => string;
16
22
  };
17
- apps: Record<string, AppDefinition>;
23
+ projects: Record<string, ProjectDefinition>;
18
24
  }
19
25
  /**
20
- * App definition
26
+ * Project definition
21
27
  */
22
- interface AppDefinition {
28
+ interface ProjectDefinition {
23
29
  components: Array<Component>;
24
30
  versioning: VersionManager;
25
31
  changelog: string;
26
32
  }
27
- type ManagedApplication = {
33
+ type ManagedProject = {
28
34
  name: string;
29
35
  components: Array<ResolvedComponent>;
30
36
  versioning: VersionManager;
31
37
  changelog: string;
32
38
  };
33
39
  //#endregion
34
- export { AutoReleaseConfig, ManagedApplication };
40
+ export { AutoReleaseConfig, ManagedProject };
@@ -1,6 +1,3 @@
1
- import "./git.mjs";
2
- import { cancel, confirm, isCancel, log } from "@clack/prompts";
3
-
4
1
  //#region src/lib/utils/branch-protection.ts
5
2
  /**
6
3
  * Detect if we're running in a CI environment
@@ -1,14 +1,14 @@
1
1
  //#region src/lib/utils/version.ts
2
- async function compute_current_version(app, { get_file_content }) {
2
+ async function compute_current_version(project, { get_file_content }) {
3
3
  const versions = /* @__PURE__ */ new Set();
4
- for (const component of app.components) for (const part of component.parts) {
4
+ for (const component of project.components) for (const part of component.parts) {
5
5
  const file_content = await get_file_content(part.file);
6
6
  if (file_content === null) continue;
7
7
  const version = part.get_current_version(file_content);
8
8
  versions.add(version);
9
9
  }
10
10
  if (versions.size === 0) return null;
11
- return Array.from(versions).sort((a, b) => app.versioning.compare(a, b)).at(-1) ?? null;
11
+ return Array.from(versions).sort((a, b) => project.versioning.compare(a, b)).at(-1) ?? null;
12
12
  }
13
13
 
14
14
  //#endregion
@@ -25,7 +25,7 @@ type Formatter<change_kinds extends string = string, parsed_changelog extends {
25
25
  * @returns Markdown string that will be written to the changelog file
26
26
  */
27
27
  format_changelog(changelog: NoInfer<parsed_changelog>, context: {
28
- app: {
28
+ project: {
29
29
  name: string;
30
30
  };
31
31
  }): string;
@@ -35,7 +35,7 @@ type Formatter<change_kinds extends string = string, parsed_changelog extends {
35
35
  * @returns Markdown string for PR body
36
36
  */
37
37
  generate_pr_body(options: {
38
- app: {
38
+ project: {
39
39
  name: string;
40
40
  };
41
41
  current_version: string;
@@ -43,12 +43,12 @@ type Formatter<change_kinds extends string = string, parsed_changelog extends {
43
43
  changes: ChangeFile<change_kinds>[];
44
44
  }): string;
45
45
  /**
46
- * Generate release notes for a given app to use in GitHub/GitLab release bodies.
46
+ * Generate release notes for a given project to use in GitHub/GitLab release bodies.
47
47
  * @param options - The options for generating release notes
48
48
  * @returns Markdown string for release body
49
49
  */
50
50
  generate_release_notes(options: {
51
- app: {
51
+ project: {
52
52
  name: string;
53
53
  changelog: string;
54
54
  };
@@ -0,0 +1,31 @@
1
+ # Change Files
2
+
3
+ Change files are stored in `.changes/<project-name>/` with format:
4
+
5
+ ```
6
+ <type>.<slug>.md
7
+ ```
8
+
9
+ Examples:
10
+
11
+ - `.changes/my-app/major.add-authentication.md`
12
+ - `.changes/my-app/patch.fix-login-bug.md`
13
+
14
+ The change files folder can be customized.
15
+
16
+ ## Format
17
+
18
+ **Simple** (title only):
19
+
20
+ ```markdown
21
+ Fix authentication bug in login flow
22
+ ```
23
+
24
+ **Detailed** (with description):
25
+
26
+ ```markdown
27
+ This adds a comprehensive user profile page with:
28
+ - Avatar upload
29
+ - Bio and social links
30
+ - Privacy settings
31
+ ```
@@ -0,0 +1,80 @@
1
+ # Commands
2
+
3
+ ## `init`
4
+
5
+ Set up auto-release in your repository:
6
+
7
+ ```bash
8
+ auto-release init
9
+ ```
10
+
11
+ Interactively configures projects, versioning strategies, and git platform.
12
+
13
+ ## `check`
14
+
15
+ Validate configuration and change files:
16
+
17
+ ```bash
18
+ auto-release check
19
+ ```
20
+
21
+ Use in CI to ensure everything is valid before merging.
22
+
23
+ ## `record-change`
24
+
25
+ Create a new change file:
26
+
27
+ ```bash
28
+ # Interactive
29
+ auto-release record-change
30
+
31
+ # Non-interactive
32
+ auto-release record-change --project my-app --type minor
33
+ ```
34
+
35
+ ## `list`
36
+
37
+ List all projects managed by `auto-release` with their current versions:
38
+
39
+ ```bash
40
+ auto-release list
41
+ ```
42
+
43
+ ## `generate-release-pr`
44
+
45
+ Create or update release PRs:
46
+
47
+ ```bash
48
+ # Preview changes
49
+ auto-release generate-release-pr --dry-run
50
+
51
+ # Create/update PRs
52
+ auto-release generate-release-pr
53
+
54
+ # Specific projects only
55
+ auto-release generate-release-pr --filter my-app --filter another-app
56
+ ```
57
+
58
+ ## `tag-release-commit`
59
+
60
+ Create git tags and releases for version changes:
61
+
62
+ ```bash
63
+ # Preview what would be tagged
64
+ auto-release tag-release-commit --dry-run
65
+
66
+ # Create tags and releases
67
+ auto-release tag-release-commit
68
+ ```
69
+
70
+ Compares HEAD with HEAD^1 to detect version changes. Creates tags in format `project-name@version`.
71
+
72
+ ## `manual-release`
73
+
74
+ Create a manual release using existing change files:
75
+
76
+ ```bash
77
+ auto-release manual-release
78
+ ```
79
+
80
+ Useful for local testing or emergency releases.
@@ -0,0 +1,116 @@
1
+ # Configuration
2
+
3
+ ## Projects
4
+
5
+ The `projects` object defines each releasable unit:
6
+
7
+ ```typescript
8
+ projects: {
9
+ 'my-app': {
10
+ // Components: where versions are read/written
11
+ components: [
12
+ node('packages/my-app'),
13
+ node('packages/shared'),
14
+ ],
15
+
16
+ // Versioning strategy
17
+ versioning: semver(),
18
+
19
+ // Changelog file path
20
+ changelog: 'apps/my-app/CHANGELOG.md',
21
+ },
22
+ }
23
+ ```
24
+
25
+ ## Versioning Strategies
26
+
27
+ ```typescript
28
+ import { semver, calver, markver } from 'auto-release/versioning'
29
+
30
+ // Semantic versioning: 1.2.3
31
+ versioning: semver() // Change types: major, minor, patch
32
+
33
+ // Calendar versioning: 2025.1.2
34
+ versioning: calver() // Change types: feature, fix
35
+
36
+ // Marketing versioning: 1.0.0
37
+ versioning: markver() // Change types: marketing, feature, fix
38
+ ```
39
+
40
+ ## Git Platforms
41
+
42
+ ### GitHub
43
+
44
+ ```typescript
45
+ import { github } from 'auto-release/providers'
46
+
47
+ git: {
48
+ platform: github({
49
+ token: process.env.GITHUB_TOKEN!,
50
+ owner: 'your-org',
51
+ repo: 'your-repo',
52
+ }),
53
+ target_branch: 'main',
54
+ tag_generator: ({ project, version }) => `${project.name}-${version}`,
55
+ }
56
+ ```
57
+
58
+ ### GitLab
59
+
60
+ ```typescript
61
+ import { gitlab } from 'auto-release/providers'
62
+
63
+ git: {
64
+ platform: gitlab({
65
+ token: process.env.GITLAB_TOKEN!,
66
+ project_id: 'your-project-id',
67
+ }),
68
+ target_branch: 'main',
69
+ }
70
+ ```
71
+
72
+ ## Tag Generator
73
+
74
+ Customize the format of git tags created during release:
75
+
76
+ ```typescript
77
+ git: {
78
+ // ... other options
79
+ tag_generator: ({ project, version }) => `${project.name}-${version}`,
80
+ }
81
+ ```
82
+
83
+ **Default**: `project-name@version` (e.g., `my-app@1.2.3`)
84
+
85
+ **Custom examples**:
86
+
87
+ ```typescript
88
+ // Version only: 1.2.3
89
+ tag_generator: ({ version }) => `${version}`
90
+
91
+ // Prefixed: v1.2.3
92
+ tag_generator: ({ version }) => `v${version}`
93
+
94
+ // With prefix: release/my-app-1.2.3
95
+ tag_generator: ({ project, version }) => `release/${project.name}-${version}`
96
+ ```
97
+
98
+ ## Components
99
+
100
+ Components define version sources:
101
+
102
+ - **`node(path)`**: any node project with package.json
103
+ - **`bun(path)`**: any bun project with package.json
104
+ - **`expo(path)`**: any Expo project with package.json and app.json
105
+ - **`php(path)`**: any PHP project with composer.json
106
+
107
+ ```typescript
108
+ import { node, expo, php } from 'auto-release/components'
109
+
110
+ components: [
111
+ node('packages/web'),
112
+ bun('packages/bff'),
113
+ expo('apps/mobile'),
114
+ php('packages/api'),
115
+ ]
116
+ ```
@@ -0,0 +1,23 @@
1
+ # `auto-release` Lexicon
2
+
3
+ This is a list of words and phrases used in `auto-release` to help contributors and users have a shared understanding of various concepts in the project.
4
+
5
+ - **change file** - A markdown file documenting a single change to a project. Change files are stored in the changes directory with the format `<kind>.<slug>.md` (e.g., `major.add-authentication.md`). Change files are stackable, running `generate-release-pr` will apply any number of change files correctly to calculate the next version and generate changelog entries.
6
+ - **changes directory** - The `.changes/` folder where change files are stored. This directory contains subdirectories for each project (e.g., `.changes/my-app/`), and each subdirectory contains the change files for that project.
7
+ - **change kind** - The type of change represented by a change file (e.g., `major`, `minor`, `patch`, `feature`, `fix`). The valid kinds for a project are defined by its versioning strategy's `allowed_changes`. This determines how the version will be bumped.
8
+ - **slug** - A unique identifier for a change file, used in the filename between the kind and the `.md` extension. Generated automatically or provided by the user (e.g., `add-authentication` in `major.add-authentication.md`).
9
+ - **project** - A releasable unit in your repository or monorepo. Each project has its own independent versioning strategy, one or more components, its own changelog, and a dedicated subdirectory in the changes directory. Projects are defined in the configuration file.
10
+ - **component** - A source of version information within a project. Components define where versions are read from and written to. Built-in component types include `node()/bun()` for package.json files, `expo()` for app.json files, and `php()` for composer.json files. All components within a project must have the same version.
11
+ - **versioning strategy** - Defines how versions are calculated and formatted for a project. Each strategy specifies valid change kinds and a `bump()` function to compute the next version from the current version and collected change kinds.
12
+ - **bump**
13
+ - (1) The command/process to apply all current change files, calculate new versions, update all component files, update changelogs, and remove processed change files.
14
+ - (2) The act of updating a project's version to a new version based on change files.
15
+ - **changelog** - A markdown file where release entries are appended for a project. Each project specifies its changelog path in the configuration. Changelog entries are generated from change file summaries using the formatter.
16
+ - **formatter** - Controls how changelogs and release notes are generated from change files. The formatter can parse markdown from change files and format changelog sections. The default formatter groups changes by kind and outputs markdown lists.
17
+ - **target branch** - The main branch where releases are merged to (typically `main` or `master`). This is the branch that release PRs target and where version tags are created.
18
+ - **release branch** - A branch created by the `generate-release-pr` command containing updated versions in all component files, new changelog entries, and removed change files. Format: `<prefix>/<project-name>` (e.g., `release/my-app`).
19
+ - **release PR** - A pull request from a release branch to the target branch, containing all version updates and changelog changes for a release. Created or updated by the `generate-release-pr` command.
20
+ - **git platform** - The hosting service for your git repository (GitHub or GitLab). The git platform integration is used to create and update release PRs, manage release notes, and interact with the repository API. Configured in the configuration file with authentication tokens.
21
+ - **tag** - A git tag created when a version change is detected on the target branch after a release PR is merged. Format: `<project-name>@<version>` (e.g., `my-app@1.2.3`). Created by the `tag-release-commit` command, typically run in CI.
22
+ - **release** - The combination of versioning, updating changelogs, creating a git tag, and publishing release notes on the git platform. This happens when a release PR is merged and the `tag-release-commit` command detects the version change.
23
+ - **config file** - The `auto-release.config.ts` TypeScript configuration file at the root of your repository. Defines projects, their components, versioning strategies, changelog paths, and git platform settings.