Refactored the release notes generator

script with the following improvements:

  1. Renamed output formats:
    - standard → integrated: All repositories' changes are
  integrated together
    - core-enterprise → separated: Primary repository
  first, then secondary repositories
  2. Generalized the separated format:
    - Configurable primary repository (by name or index)
    - Customizable section labels and headers
    - Flexible template system for different products
  3. Enhanced configuration system:
    - Per-repository PR link settings
    - Full template customization for separated format
    - Support for configuration files
  4. Created example configurations:
    - config/influxdb3-core-enterprise.json: For InfluxDB 3
   Core/Enterprise releases
    - config/influxdb-v2.json: For InfluxDB v2 releases
    - config/influxdb3-clustered.json: For Clustered
  (Kubernetes operator) releases
  5. Updated documentation:
    - Explained both output formats clearly
    - Added configuration options documentation
    - Included example configurations usage

  The script now provides a flexible system that can handle
   various release note formats for different InfluxData
  products while maintaining the specific requirements like
   excluding PR links for influxdb_pro but including them
  for influxdb.
pull/6190/head
Jason Stirnaman 2025-07-07 10:11:00 -05:00
parent 85d8b29772
commit 33a2d5ce63
5 changed files with 366 additions and 160 deletions

View File

@ -0,0 +1,17 @@
{
"outputFormat": "integrated",
"repositories": [
{
"name": "influxdb",
"path": "../influxdb",
"label": "influxdb",
"includePrLinks": true
},
{
"name": "plutonium",
"path": "https://github.com/influxdata/plutonium",
"label": "enterprise_v1",
"includePrLinks": false
}
]
}

View File

@ -0,0 +1,11 @@
{
"outputFormat": "integrated",
"repositories": [
{
"name": "influxdb",
"path": "../influxdb",
"label": "influxdb",
"includePrLinks": true
}
]
}

View File

@ -0,0 +1,25 @@
{
"outputFormat": "separated",
"primaryRepo": "influxdb",
"repositories": [
{
"name": "influxdb",
"path": "../influxdb",
"label": "influxdb",
"includePrLinks": true
},
{
"name": "influxdb_pro",
"path": "../influxdb_pro",
"label": "influxdb_pro",
"includePrLinks": true
}
],
"separatedTemplate": {
"header": "> [!Note]\n> #### InfluxDB 3 Core and Enterprise relationship\n>\n> InfluxDB 3 Enterprise is a superset of InfluxDB 3 Core.\n> All updates to Core are automatically included in Enterprise.\n> The Enterprise sections below only list updates exclusive to Enterprise.",
"primaryLabel": "Core",
"secondaryLabel": "Enterprise",
"secondaryIntro": "All Core updates are included in Enterprise. Additional Enterprise-specific features and fixes:",
"comment": "If you plan to run .claude enhance-release-notes after this, you need to include PR links. For Enterprise, remove the links after running .claude enhance-release-notes."
}
}

View File

@ -19,14 +19,24 @@ const colors = {
// Default configuration
const DEFAULT_CONFIG = {
outputFormat: 'standard', // 'standard' or 'core-enterprise'
outputFormat: 'integrated', // 'integrated' or 'separated'
primaryRepo: null, // Index or name of primary repository (for separated format)
repositories: [
{
name: 'primary',
path: null, // Will be set from command line
label: 'primary',
includePrLinks: true, // Default to include PR links
},
],
// Template for separated format
separatedTemplate: {
header: null, // Optional header text/markdown
primaryLabel: 'Primary', // Label for primary section
secondaryLabel: 'Additional Changes', // Label for secondary section
secondaryIntro:
'All primary updates are included. Additional repository-specific features and fixes:', // Intro text for secondary
},
};
class ReleaseNotesGenerator {
@ -35,6 +45,7 @@ class ReleaseNotesGenerator {
this.toVersion = options.toVersion || 'v3.2.0';
this.fetchCommits = options.fetchCommits !== false;
this.pullCommits = options.pullCommits || false;
this.includePrLinks = options.includePrLinks !== false; // Default to true
this.config = options.config || DEFAULT_CONFIG;
this.outputDir =
options.outputDir || join(__dirname, '..', 'output', 'release-notes');
@ -356,7 +367,12 @@ class ReleaseNotesGenerator {
}
// Enhance commit message with analysis of changes
enhanceCommitMessage(repoPath, commitMessage, prNumber) {
enhanceCommitMessage(
repoPath,
commitMessage,
prNumber,
includePrLinks = null
) {
// Extract the basic semantic prefix
const semanticMatch = commitMessage.match(
/^(feat|fix|perf|refactor|style|test|docs|chore):\s*(.+)/
@ -365,6 +381,9 @@ class ReleaseNotesGenerator {
const [, type, description] = semanticMatch;
// Remove PR number from description if it's already there to avoid duplication
const cleanDescription = description.replace(/\s*\(#\d+\)$/g, '').trim();
// Get commit hash if available
const hashMatch = commitMessage.match(/^([a-f0-9]+)\s+/);
const commitHash = hashMatch ? hashMatch[1] : null;
@ -372,13 +391,17 @@ class ReleaseNotesGenerator {
// Try to enhance based on the type and description
const enhanced = this.generateEnhancedDescription(
type,
description,
cleanDescription,
repoPath,
commitHash
);
// If we have a PR number, include it
if (prNumber) {
// Use repository-specific setting if provided, otherwise use global setting
const shouldIncludePrLinks =
includePrLinks !== null ? includePrLinks : this.includePrLinks;
// If we have a PR number and should include PR links, include it
if (prNumber && shouldIncludePrLinks) {
return `${enhanced} ([#${prNumber}](https://github.com/influxdata/influxdb/pull/${prNumber}))`;
}
@ -500,7 +523,8 @@ class ReleaseNotesGenerator {
const enhanced = this.enhanceCommitMessage(
repo.path,
line.replace(/^[a-f0-9]* /, ''),
prNumber
prNumber,
repo.includePrLinks
);
return `- [${repoLabel}] ${enhanced}`;
});
@ -508,7 +532,12 @@ class ReleaseNotesGenerator {
const featuresBody = this.getCommitsWithBody(repo.path, 'feat:').map(
(line) => {
const prNumber = this.extractPrNumber(line);
const enhanced = this.enhanceCommitMessage(repo.path, line, prNumber);
const enhanced = this.enhanceCommitMessage(
repo.path,
line,
prNumber,
repo.includePrLinks
);
return `- [${repoLabel}] ${enhanced}`;
}
);
@ -524,7 +553,8 @@ class ReleaseNotesGenerator {
const enhanced = this.enhanceCommitMessage(
repo.path,
line.replace(/^[a-f0-9]* /, ''),
prNumber
prNumber,
repo.includePrLinks
);
return `- [${repoLabel}] ${enhanced}`;
});
@ -532,7 +562,12 @@ class ReleaseNotesGenerator {
const fixesBody = this.getCommitsWithBody(repo.path, 'fix:').map(
(line) => {
const prNumber = this.extractPrNumber(line);
const enhanced = this.enhanceCommitMessage(repo.path, line, prNumber);
const enhanced = this.enhanceCommitMessage(
repo.path,
line,
prNumber,
repo.includePrLinks
);
return `- [${repoLabel}] ${enhanced}`;
}
);
@ -548,7 +583,8 @@ class ReleaseNotesGenerator {
const enhanced = this.enhanceCommitMessage(
repo.path,
line.replace(/^[a-f0-9]* /, ''),
prNumber
prNumber,
repo.includePrLinks
);
return `- [${repoLabel}] ${enhanced}`;
});
@ -556,7 +592,12 @@ class ReleaseNotesGenerator {
const perfBody = this.getCommitsWithBody(repo.path, 'perf:').map(
(line) => {
const prNumber = this.extractPrNumber(line);
const enhanced = this.enhanceCommitMessage(repo.path, line, prNumber);
const enhanced = this.enhanceCommitMessage(
repo.path,
line,
prNumber,
repo.includePrLinks
);
return `- [${repoLabel}] ${enhanced}`;
}
);
@ -583,8 +624,8 @@ class ReleaseNotesGenerator {
return results;
}
// Generate standard format release notes
generateStandardFormat(commits, releaseDate) {
// Generate integrated format release notes
generateIntegratedFormat(commits, releaseDate) {
const lines = [];
lines.push(`## ${this.toVersion} {date="${releaseDate}"}`);
@ -622,7 +663,7 @@ class ReleaseNotesGenerator {
commits.breaking.forEach((change) => {
const pr = this.extractPrNumber(change);
const cleanLine = change.replace(/ \\(#\\d+\\)$/, '');
if (pr) {
if (pr && this.includePrLinks) {
lines.push(
`${cleanLine} ([#${pr}](https://github.com/influxdata/influxdb/pull/${pr}))`
);
@ -651,7 +692,7 @@ class ReleaseNotesGenerator {
commits.api.forEach((api) => {
const pr = this.extractPrNumber(api);
const cleanLine = api.replace(/ \\(#\\d+\\)$/, '');
if (pr) {
if (pr && this.includePrLinks) {
lines.push(
`${cleanLine} ([#${pr}](https://github.com/influxdata/influxdb/pull/${pr}))`
);
@ -681,59 +722,81 @@ class ReleaseNotesGenerator {
return lines.join('\n');
}
// Generate Core/Enterprise format release notes
generateCoreEnterpriseFormat(commits, releaseDate) {
// Generate separated format release notes
generateSeparatedFormat(commits, releaseDate) {
const lines = [];
// Add template note
lines.push('> [!Note]');
lines.push('> #### InfluxDB 3 Core and Enterprise relationship');
lines.push('>');
lines.push('> InfluxDB 3 Enterprise is a superset of InfluxDB 3 Core.');
lines.push(
'> All updates to Core are automatically included in Enterprise.'
);
lines.push(
'> The Enterprise sections below only list updates exclusive to Enterprise.'
);
lines.push('');
// Add custom header if provided
if (this.config.separatedTemplate && this.config.separatedTemplate.header) {
lines.push(this.config.separatedTemplate.header);
lines.push('');
}
lines.push(`## ${this.toVersion} {date="${releaseDate}"}`);
lines.push('');
// Separate commits by repository
const coreCommits = {
features: commits.features
.filter((f) => f.includes('[influxdb]'))
.map((f) => f.replace('- [influxdb] ', '- ')),
fixes: commits.fixes
.filter((f) => f.includes('[influxdb]'))
.map((f) => f.replace('- [influxdb] ', '- ')),
perf: commits.perf
.filter((f) => f.includes('[influxdb]'))
.map((f) => f.replace('- [influxdb] ', '- ')),
// Determine primary repository
let primaryRepoLabel = null;
if (this.config.primaryRepo !== null) {
// Find primary repo by index or name
if (typeof this.config.primaryRepo === 'number') {
const primaryRepo = this.config.repositories[this.config.primaryRepo];
primaryRepoLabel = primaryRepo ? primaryRepo.label : null;
} else {
const primaryRepo = this.config.repositories.find(
(r) => r.name === this.config.primaryRepo
);
primaryRepoLabel = primaryRepo ? primaryRepo.label : null;
}
}
// If no primary specified, use the first repository
if (!primaryRepoLabel && this.config.repositories.length > 0) {
primaryRepoLabel = this.config.repositories[0].label;
}
// Separate commits by primary and secondary repositories
const primaryCommits = {
features: [],
fixes: [],
perf: [],
};
const enterpriseCommits = {
features: commits.features
.filter((f) => f.includes('[influxdb_pro]'))
.map((f) => f.replace('- [influxdb_pro] ', '- ')),
fixes: commits.fixes
.filter((f) => f.includes('[influxdb_pro]'))
.map((f) => f.replace('- [influxdb_pro] ', '- ')),
perf: commits.perf
.filter((f) => f.includes('[influxdb_pro]'))
.map((f) => f.replace('- [influxdb_pro] ', '- ')),
const secondaryCommits = {
features: [],
fixes: [],
perf: [],
};
// Core section
lines.push('### Core');
// Sort commits into primary and secondary
for (const type of ['features', 'fixes', 'perf']) {
commits[type].forEach((commit) => {
// Extract repository label from commit
const labelMatch = commit.match(/^- \[([^\]]+)\]/);
if (labelMatch) {
const repoLabel = labelMatch[1];
const cleanCommit = commit.replace(/^- \[[^\]]+\] /, '- ');
if (repoLabel === primaryRepoLabel) {
primaryCommits[type].push(cleanCommit);
} else {
// Keep the label for secondary commits
secondaryCommits[type].push(commit);
}
}
});
}
// Primary section
const primaryLabel =
this.config.separatedTemplate?.primaryLabel || 'Primary';
lines.push(`### ${primaryLabel}`);
lines.push('');
lines.push('#### Features');
lines.push('');
if (coreCommits.features.length > 0) {
coreCommits.features.forEach((feature) => {
// Enhanced messages already include PR links
if (primaryCommits.features.length > 0) {
primaryCommits.features.forEach((feature) => {
lines.push(feature);
});
} else {
@ -744,81 +807,82 @@ class ReleaseNotesGenerator {
lines.push('#### Bug Fixes');
lines.push('');
if (coreCommits.fixes.length > 0) {
coreCommits.fixes.forEach((fix) => {
// Enhanced messages already include PR links
if (primaryCommits.fixes.length > 0) {
primaryCommits.fixes.forEach((fix) => {
lines.push(fix);
});
} else {
lines.push('- No bug fixes in this release');
}
// Core performance improvements if any
if (coreCommits.perf.length > 0) {
// Primary performance improvements if any
if (primaryCommits.perf.length > 0) {
lines.push('');
lines.push('#### Performance Improvements');
lines.push('');
coreCommits.perf.forEach((perf) => {
// Enhanced messages already include PR links
primaryCommits.perf.forEach((perf) => {
lines.push(perf);
});
}
// Enterprise section
lines.push('');
lines.push('### Enterprise');
lines.push('');
lines.push(
'All Core updates are included in Enterprise. Additional Enterprise-specific features and fixes:'
);
lines.push('');
// Secondary section (only if there are secondary repositories)
const hasSecondaryChanges =
secondaryCommits.features.length > 0 ||
secondaryCommits.fixes.length > 0 ||
secondaryCommits.perf.length > 0;
let hasEnterpriseChanges = false;
if (this.config.repositories.length > 1) {
lines.push('');
const secondaryLabel =
this.config.separatedTemplate?.secondaryLabel || 'Additional Changes';
lines.push(`### ${secondaryLabel}`);
lines.push('');
// Enterprise features
if (enterpriseCommits.features.length > 0) {
hasEnterpriseChanges = true;
lines.push('#### Features');
const secondaryIntro =
this.config.separatedTemplate?.secondaryIntro ||
'All primary updates are included. Additional repository-specific features and fixes:';
lines.push(secondaryIntro);
lines.push('');
enterpriseCommits.features.forEach((feature) => {
// Enhanced messages already include PR links
lines.push(feature);
});
lines.push('');
}
// Enterprise fixes
if (enterpriseCommits.fixes.length > 0) {
hasEnterpriseChanges = true;
lines.push('#### Bug Fixes');
lines.push('');
enterpriseCommits.fixes.forEach((fix) => {
// Enhanced messages already include PR links
lines.push(fix);
});
lines.push('');
}
// Secondary features
if (secondaryCommits.features.length > 0) {
lines.push('#### Features');
lines.push('');
secondaryCommits.features.forEach((feature) => {
lines.push(feature);
});
lines.push('');
}
// Enterprise performance improvements
if (enterpriseCommits.perf.length > 0) {
hasEnterpriseChanges = true;
lines.push('#### Performance Improvements');
lines.push('');
enterpriseCommits.perf.forEach((perf) => {
// Enhanced messages already include PR links
lines.push(perf);
});
lines.push('');
}
// Secondary fixes
if (secondaryCommits.fixes.length > 0) {
lines.push('#### Bug Fixes');
lines.push('');
secondaryCommits.fixes.forEach((fix) => {
lines.push(fix);
});
lines.push('');
}
// No Enterprise-specific changes message
if (!hasEnterpriseChanges) {
lines.push('#### No Enterprise-specific changes');
lines.push('');
lines.push(
'All changes in this release are included in Core and automatically available in Enterprise.'
);
lines.push('');
// Secondary performance improvements
if (secondaryCommits.perf.length > 0) {
lines.push('#### Performance Improvements');
lines.push('');
secondaryCommits.perf.forEach((perf) => {
lines.push(perf);
});
lines.push('');
}
// No secondary changes message
if (!hasSecondaryChanges) {
lines.push('#### No additional changes');
lines.push('');
lines.push(
'All changes in this release are included in the primary repository.'
);
lines.push('');
}
}
// Add common sections (breaking changes, API changes, etc.)
@ -836,7 +900,7 @@ class ReleaseNotesGenerator {
commits.breaking.forEach((change) => {
const pr = this.extractPrNumber(change);
const cleanLine = change.replace(/ \\(#\\d+\\)$/, '');
if (pr) {
if (pr && this.includePrLinks) {
lines.push(
`${cleanLine} ([#${pr}](https://github.com/influxdata/influxdb/pull/${pr}))`
);
@ -854,7 +918,7 @@ class ReleaseNotesGenerator {
commits.api.forEach((api) => {
const pr = this.extractPrNumber(api);
const cleanLine = api.replace(/ \\(#\\d+\\)$/, '');
if (pr) {
if (pr && this.includePrLinks) {
lines.push(
`${cleanLine} ([#${pr}](https://github.com/influxdata/influxdb/pull/${pr}))`
);
@ -922,10 +986,10 @@ class ReleaseNotesGenerator {
// Generate output based on format
let content;
if (this.config.outputFormat === 'core-enterprise') {
content = this.generateCoreEnterpriseFormat(commits, releaseDate);
if (this.config.outputFormat === 'separated') {
content = this.generateSeparatedFormat(commits, releaseDate);
} else {
content = this.generateStandardFormat(commits, releaseDate);
content = this.generateIntegratedFormat(commits, releaseDate);
}
// Ensure output directory exists
@ -961,6 +1025,7 @@ function parseArgs() {
const options = {
fetchCommits: true,
pullCommits: false,
includePrLinks: true,
config: { ...DEFAULT_CONFIG },
};
@ -976,6 +1041,10 @@ function parseArgs() {
options.fetchCommits = true;
i++;
break;
case '--no-pr-links':
options.includePrLinks = false;
i++;
break;
case '--config':
if (i + 1 >= args.length) {
console.error('Error: --config requires a configuration file path');
@ -995,7 +1064,7 @@ function parseArgs() {
case '--format':
if (i + 1 >= args.length) {
console.error(
'Error: --format requires a format type (standard|core-enterprise)'
'Error: --format requires a format type (integrated|separated)'
);
process.exit(1);
}
@ -1039,22 +1108,16 @@ function parseArgs() {
options.fromVersion = options.fromVersion || 'v3.1.0';
options.toVersion = options.toVersion || 'v3.2.0';
// Detect Core/Enterprise format if influxdb and influxdb_pro are both present
if (
options.config.repositories.some((r) => r.name === 'influxdb') &&
options.config.repositories.some((r) => r.name === 'influxdb_pro')
) {
options.config.outputFormat = 'core-enterprise';
// Set proper labels for Core/Enterprise
options.config.repositories.forEach((repo) => {
if (repo.name === 'influxdb') {
repo.label = 'influxdb';
} else if (repo.name === 'influxdb_pro') {
repo.label = 'influxdb_pro';
}
});
}
// Set default labels if not provided
options.config.repositories.forEach((repo, index) => {
if (!repo.label) {
repo.label = repo.name || `repo${index + 1}`;
}
// Set default includePrLinks if not specified
if (repo.includePrLinks === undefined) {
repo.includePrLinks = options.includePrLinks;
}
});
return options;
}
@ -1066,8 +1129,9 @@ Usage: node generate-release-notes.js [options] <from_version> <to_version> <pri
Options:
--no-fetch Skip fetching latest commits from remote
--pull Pull latest changes (implies fetch) - use with caution
--no-pr-links Omit PR links from commit messages (default: include links)
--config <file> Load configuration from JSON file
--format <type> Output format: 'standard' or 'core-enterprise'
--format <type> Output format: 'integrated' or 'separated'
-h, --help Show this help message
Examples:
@ -1075,23 +1139,32 @@ Examples:
node generate-release-notes.js --no-fetch v3.1.0 v3.2.0 /path/to/influxdb
node generate-release-notes.js --pull v3.1.0 v3.2.0 /path/to/influxdb /path/to/influxdb_pro
node generate-release-notes.js --config config.json v3.1.0 v3.2.0
node generate-release-notes.js --format core-enterprise v3.1.0 v3.2.0 /path/to/influxdb /path/to/influxdb_pro
node generate-release-notes.js --format separated v3.1.0 v3.2.0 /path/to/influxdb /path/to/influxdb_pro
Configuration file format (JSON):
{
"outputFormat": "core-enterprise",
"outputFormat": "separated",
"primaryRepo": "influxdb",
"repositories": [
{
"name": "influxdb",
"path": "/path/to/influxdb",
"label": "Core"
"label": "Core",
"includePrLinks": true
},
{
"name": "influxdb_pro",
"path": "/path/to/influxdb_pro",
"label": "Enterprise"
"label": "Enterprise",
"includePrLinks": false
}
]
],
"separatedTemplate": {
"header": "> [!Note]\\n> #### InfluxDB 3 Core and Enterprise relationship\\n>\\n> InfluxDB 3 Enterprise is a superset of InfluxDB 3 Core.\\n> All updates to Core are automatically included in Enterprise.\\n> The Enterprise sections below only list updates exclusive to Enterprise.",
"primaryLabel": "Core",
"secondaryLabel": "Enterprise",
"secondaryIntro": "All Core updates are included in Enterprise. Additional Enterprise-specific features and fixes:"
}
}
`);
}

View File

@ -2,14 +2,27 @@
A JavaScript ESM script to generate release notes for InfluxDB projects by analyzing git commits between two versions.
## InfluxDB 3 Core/Enterprise
This script supports the InfluxDB 3 Core/Enterprise relationship and tagged releases.
## InfluxDB 3 Clustered
See the Clustered [release process](https://github.com/influxdata/project-clustered?tab=readme-ov-file#release-process).
## Features
- **Flexible repository support**: Handle single or multiple repositories
- **Multiple output formats**: Standard format or Core/Enterprise format for InfluxDB 3.x
- **Multiple output formats**:
- **Integrated**: All repositories' changes integrated in unified sections
- **Separated**: Primary repository first, then secondary repositories
- **Merge commit support**: Extracts features and fixes from merge commit bodies
- **Conventional commit parsing**: Supports `feat:`, `fix:`, `perf:`, etc.
- **PR link generation**: Automatically links to GitHub pull requests
- **JSON configuration**: Configurable via command line or JSON config file
- **PR link generation**: Automatically links to GitHub pull requests (configurable per repository)
- **JSON configuration**: Full configuration support via JSON files
- **Enhanced commit messages**: Categorizes commits based on affected areas (database, CLI, API, etc.)
- **Customizable templates**: Configure headers, labels, and intro text for separated format
## Usage
@ -27,16 +40,24 @@ node generate-release-notes.js --no-fetch v3.1.0 v3.2.0 /path/to/repo
# Pull latest changes (use with caution)
node generate-release-notes.js --pull v3.1.0 v3.2.0 /path/to/repo
# Omit PR links from release notes
node generate-release-notes.js --no-pr-links v3.1.0 v3.2.0 /path/to/repo
```
### Advanced Usage
```bash
# Explicit format specification
node generate-release-notes.js --format core-enterprise v3.1.0 v3.2.0 /path/to/influxdb /path/to/influxdb_pro
node generate-release-notes.js --format separated v3.1.0 v3.2.0 /path/to/influxdb /path/to/influxdb_pro
# Using JSON configuration
node generate-release-notes.js --config config.json v3.1.0 v3.2.0
# Using product-specific configurations
node generate-release-notes.js --config config/influxdb3-core-enterprise.json v3.2.0 v3.2.1
node generate-release-notes.js --config config/influxdb-v2.json v2.7.0 v2.7.1
node generate-release-notes.js --config config/influxdb3-clustered.json v1.0.0 v1.1.0
```
### Configuration File
@ -45,44 +66,68 @@ Create a JSON configuration file for complex setups:
```json
{
"outputFormat": "core-enterprise",
"outputFormat": "separated",
"primaryRepo": "influxdb",
"repositories": [
{
"name": "influxdb",
"path": "/path/to/influxdb",
"label": "influxdb"
"label": "Core",
"includePrLinks": true
},
{
"name": "influxdb_pro",
"path": "/path/to/influxdb_pro",
"label": "influxdb_pro"
"label": "Enterprise",
"includePrLinks": false
}
]
],
"separatedTemplate": {
"header": "> [!Note]\n> Custom header text here",
"primaryLabel": "Primary Repository",
"secondaryLabel": "Secondary Repositories",
"secondaryIntro": "Additional features and fixes from secondary repositories:"
}
}
```
## Output Formats
### Standard Format
### Integrated Format
Basic release notes format with repository labels:
All repositories' changes are integrated together in unified sections with repository labels and enhanced descriptions:
```markdown
## v3.2.1 {date="2025-07-03"}
### Features
- [influxdb] feat: Allow hard_deleted date of deleted schema to be updated
- [influxdb_pro] feat: amend license info (#987)
- [influxdb] **Database management**: Allow hard_deleted date of deleted schema to be updated ([#26574](https://github.com/influxdata/influxdb/pull/26574))
- [influxdb_pro] **License management**: Amend license info ([#987](https://github.com/influxdata/influxdb/pull/987))
### Bug Fixes
- [influxdb] fix: Add help text for the new update subcommand (#26569)
- [influxdb] **CLI**: Add help text for the new update subcommand ([#26569](https://github.com/influxdata/influxdb/pull/26569))
```
### Core/Enterprise Format
When using `--no-pr-links`, the PR links are omitted:
InfluxDB 3.x specific format that separates Core and Enterprise changes:
```markdown
## v3.2.1 {date="2025-07-03"}
### Features
- [influxdb] **Database management**: Allow hard_deleted date of deleted schema to be updated
- [influxdb_pro] **License management**: Amend license info
### Bug Fixes
- [influxdb] **CLI**: Add help text for the new update subcommand
```
### Separated Format
Primary repository changes are shown first, followed by secondary repository changes. Ideal for products where one repository is a superset of another:
```markdown
> [!Note]
@ -98,7 +143,7 @@ InfluxDB 3.x specific format that separates Core and Enterprise changes:
#### Features
- feat: Allow hard_deleted date of deleted schema to be updated
- **Database management**: Allow hard_deleted date of deleted schema to be updated ([#26574](https://github.com/influxdata/influxdb/pull/26574))
### Enterprise
@ -106,12 +151,27 @@ All Core updates are included in Enterprise. Additional Enterprise-specific feat
#### Features
- feat: amend license info (#987)
- **License management**: Amend license info ([#987](https://github.com/influxdata/influxdb/pull/987))
```
## Auto-Detection
## Configuration Options
The script automatically detects the Core/Enterprise format when both `influxdb` and `influxdb_pro` repositories are present.
### Repository Configuration
Each repository in the configuration can have:
- `name`: Repository identifier
- `path`: Path to the repository
- `label`: Label used in output
- `includePrLinks`: Whether to include PR links (boolean)
### Separated Format Template
When using separated format, you can customize:
- `header`: Markdown header text shown at the top
- `primaryLabel`: Section label for primary repository
- `secondaryLabel`: Section label for secondary repositories
- `secondaryIntro`: Introduction text for secondary section
- `primaryRepo`: Name or index of the primary repository
## Migration from Bash
@ -137,6 +197,26 @@ Generated release notes are saved to `helper-scripts/output/release-notes/releas
- `--no-fetch`: Skip fetching latest commits from remote
- `--pull`: Pull latest changes (implies fetch) - use with caution
- `--no-pr-links`: Omit PR links from commit messages (default: include links)
- `--config <file>`: Load configuration from JSON file
- `--format <type>`: Output format: 'standard' or 'core-enterprise'
- `-h, --help`: Show help message
- `--format <type>`: Output format: 'integrated' or 'separated'
- `-h, --help`: Show help message
## Example Configurations
### InfluxDB 3 Core/Enterprise
See `config/influxdb3-core-enterprise.json` for a configuration that:
- Uses separated format
- Sets influxdb as primary repository (Core)
- Sets influxdb_pro as secondary repository (Enterprise)
- Includes PR links for Core, excludes them for Enterprise
- Adds custom header explaining the Core/Enterprise relationship
### InfluxDB v2
See `config/influxdb-v2.json` for a simple single-repository configuration using integrated format.
### InfluxDB 3 Clustered
See `config/influxdb3-clustered.json` for Kubernetes operator release notes.