diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..88eb1a71 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,16 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +## [0.9.34] - 2024-07-01 + +This is the initial changelog entry. Future releases will automatically update this file with release notes from GitHub. + +### Added +- Auto-generation of release notes for GitHub releases +- Auto-updating of CHANGELOG.md files for both main and CLI packages +- Display of release notes on npmjs.com through the CHANGELOG.md files + +### Changed +- Modified deployment scripts to ensure GitHub releases are created with auto-generated notes +- Updated package.json files to include CHANGELOG.md in published packages diff --git a/cli-package/CHANGELOG.md b/cli-package/CHANGELOG.md new file mode 100644 index 00000000..88eb1a71 --- /dev/null +++ b/cli-package/CHANGELOG.md @@ -0,0 +1,16 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +## [0.9.34] - 2024-07-01 + +This is the initial changelog entry. Future releases will automatically update this file with release notes from GitHub. + +### Added +- Auto-generation of release notes for GitHub releases +- Auto-updating of CHANGELOG.md files for both main and CLI packages +- Display of release notes on npmjs.com through the CHANGELOG.md files + +### Changed +- Modified deployment scripts to ensure GitHub releases are created with auto-generated notes +- Updated package.json files to include CHANGELOG.md in published packages diff --git a/cli-package/package.json b/cli-package/package.json index 7a480daa..c8af8f0e 100644 --- a/cli-package/package.json +++ b/cli-package/package.json @@ -9,6 +9,7 @@ "files": [ "cli-wrapper.js", "README.md", + "CHANGELOG.md", "dist/cli.js", "dist/cli.js.map" ], diff --git a/package.json b/package.json index 450b7420..36887686 100644 --- a/package.json +++ b/package.json @@ -44,8 +44,8 @@ "check-format": "prettier --check \"src/**/*.{ts,js}\"", "check-style": "node scripts/check-code-style.js", "prepare": "npm run build", - "deploy": "npm run build && npm publish", - "deploy:cli": "node scripts/generate-version.js && cd cli-package && npm run build && npm publish", + "deploy": "npm run build && npm publish && node scripts/create-github-release.js", + "deploy:cli": "node scripts/generate-version.js && cd cli-package && npm run build && npm publish && node ../scripts/create-github-release.js", "deploy:both": "node scripts/publish-cli.js", "deploy:cloud:aws": "cd cloud-wrapper && npm run build && npm run deploy:aws", "deploy:cloud:gcp": "cd cloud-wrapper && npm run build && npm run deploy:gcp", @@ -93,6 +93,7 @@ "dist/utils/", "LICENSE", "README.md", + "CHANGELOG.md", "brainy.png" ], "devDependencies": { diff --git a/scripts/create-github-release.js b/scripts/create-github-release.js new file mode 100644 index 00000000..bb6ebb27 --- /dev/null +++ b/scripts/create-github-release.js @@ -0,0 +1,77 @@ +#!/usr/bin/env node + +/** + * Create GitHub Release Script + * + * This script creates a GitHub release with auto-generated release notes + * for the current version of the package. + * + * It uses the GitHub CLI (gh) to create the release, so the gh CLI must be installed + * and authenticated with appropriate permissions. + * + * The script: + * 1. Gets the current version from package.json + * 2. Creates a GitHub release for that version + * 3. Auto-generates release notes based on commits since the last release + * + * This ensures that each npm release has a corresponding GitHub release with notes. + */ + +import { execSync } from 'child_process' +import fs from 'fs' +import path from 'path' +import { fileURLToPath } from 'url' + +// Get the directory of the current module +const __filename = fileURLToPath(import.meta.url) +const __dirname = path.dirname(__filename) + +// Path to the root directory +const rootDir = path.join(__dirname, '..') + +// Path to package.json +const packageJsonPath = path.join(rootDir, 'package.json') + +// Read package.json +const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8')) +const version = packageJson.version + +// Check if GitHub CLI is installed +try { + execSync('gh --version', { stdio: 'ignore' }) +} catch (error) { + console.error('Error: GitHub CLI (gh) is not installed or not in PATH') + console.error('Please install it from https://cli.github.com/ and authenticate with `gh auth login`') + process.exit(1) +} + +// Create the GitHub release +try { + console.log(`Creating GitHub release for v${version}...`) + + // Create a release with auto-generated notes + // The --generate-notes flag automatically generates release notes based on PRs and commits + execSync( + `gh release create v${version} --title "v${version}" --generate-notes`, + { stdio: 'inherit', cwd: rootDir } + ) + + console.log(`GitHub release v${version} created successfully!`) + + // Update CHANGELOG.md with the release notes + console.log('Updating CHANGELOG.md with release notes...') + execSync('node scripts/update-changelog.js', { stdio: 'inherit', cwd: rootDir }) +} catch (error) { + // If the release already exists, this is not a fatal error + if (error.message.includes('already exists')) { + console.log(`GitHub release v${version} already exists, skipping creation.`) + + // Still update CHANGELOG.md with the release notes + console.log('Updating CHANGELOG.md with release notes...') + execSync('node scripts/update-changelog.js', { stdio: 'inherit', cwd: rootDir }) + } else { + console.error('Error creating GitHub release:', error.message) + // Don't exit with error to allow the npm publish to continue + // process.exit(1) + } +} diff --git a/scripts/publish-cli.js b/scripts/publish-cli.js index 1c0d2e40..a9a0b045 100755 --- a/scripts/publish-cli.js +++ b/scripts/publish-cli.js @@ -63,6 +63,12 @@ try { execSync('npm publish', { stdio: 'inherit', cwd: cliPackageDir }) console.log('Both packages published successfully!') + + // Step 8: Create GitHub release + console.log('Creating GitHub release...') + execSync('node scripts/create-github-release.js', { stdio: 'inherit', cwd: rootDir }) + + console.log('Deployment complete!') } catch (error) { console.error('Error:', error.message) process.exit(1) diff --git a/scripts/update-changelog.js b/scripts/update-changelog.js new file mode 100755 index 00000000..d818edae --- /dev/null +++ b/scripts/update-changelog.js @@ -0,0 +1,138 @@ +#!/usr/bin/env node + +/** + * Update Changelog Script + * + * This script updates the CHANGELOG.md file with the latest release notes + * from GitHub. It's designed to be called after creating a GitHub release. + * + * The script: + * 1. Gets the current version from package.json + * 2. Fetches the release notes from GitHub for that version + * 3. Updates the CHANGELOG.md file with the new release notes + * + * This ensures that the CHANGELOG.md file is always up-to-date with the + * latest release notes, which will be displayed on npmjs.com. + */ + +import { execSync } from 'child_process' +import fs from 'fs' +import path from 'path' +import { fileURLToPath } from 'url' + +// Get the directory of the current module +const __filename = fileURLToPath(import.meta.url) +const __dirname = path.dirname(__filename) + +// Path to the root directory +const rootDir = path.join(__dirname, '..') + +// Path to package.json +const packageJsonPath = path.join(rootDir, 'package.json') + +// Path to CHANGELOG.md +const changelogPath = path.join(rootDir, 'CHANGELOG.md') + +// Read package.json +const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8')) +const version = packageJson.version + +// Check if GitHub CLI is installed +try { + execSync('gh --version', { stdio: 'ignore' }) +} catch (error) { + console.error('Error: GitHub CLI (gh) is not installed or not in PATH') + console.error('Please install it from https://cli.github.com/ and authenticate with `gh auth login`') + process.exit(1) +} + +// Fetch release notes from GitHub +try { + console.log(`Fetching release notes for v${version} from GitHub...`) + + // Get the release notes using GitHub CLI + const releaseNotes = execSync( + `gh release view v${version} --json body --jq .body`, + { encoding: 'utf8', cwd: rootDir } + ).trim() + + // Create or update the CHANGELOG.md file + let changelog = '' + + // If CHANGELOG.md exists, read its content + if (fs.existsSync(changelogPath)) { + changelog = fs.readFileSync(changelogPath, 'utf8') + } else { + // Create a new CHANGELOG.md file with a header + changelog = '# Changelog\n\nAll notable changes to this project will be documented in this file.\n\n' + } + + // Format the new entry + const date = new Date().toISOString().split('T')[0] + const newEntry = `## [${version}] - ${date}\n\n${releaseNotes}\n\n` + + // Check if this version is already in the changelog + if (changelog.includes(`## [${version}]`)) { + // Replace the existing entry + const versionRegex = new RegExp(`## \\[${version}\\].*?(?=## \\[|$)`, 's') + changelog = changelog.replace(versionRegex, newEntry) + } else { + // Add the new entry after the header (before the first version entry) + const firstVersionIndex = changelog.search(/## \[\d+\.\d+\.\d+\]/) + + if (firstVersionIndex !== -1) { + // Insert before the first version entry + changelog = changelog.slice(0, firstVersionIndex) + newEntry + changelog.slice(firstVersionIndex) + } else { + // No existing version entries, append to the end + changelog += newEntry + } + } + + // Write the updated changelog + fs.writeFileSync(changelogPath, changelog) + + console.log(`CHANGELOG.md updated with release notes for v${version}`) + + // Also update the CLI package's CHANGELOG.md + const cliChangelogPath = path.join(rootDir, 'cli-package', 'CHANGELOG.md') + + // Create or update the CLI CHANGELOG.md file + let cliChangelog = '' + + // If CLI CHANGELOG.md exists, read its content + if (fs.existsSync(cliChangelogPath)) { + cliChangelog = fs.readFileSync(cliChangelogPath, 'utf8') + } else { + // Create a new CHANGELOG.md file with a header + cliChangelog = '# Changelog\n\nAll notable changes to this project will be documented in this file.\n\n' + } + + // Check if this version is already in the changelog + if (cliChangelog.includes(`## [${version}]`)) { + // Replace the existing entry + const versionRegex = new RegExp(`## \\[${version}\\].*?(?=## \\[|$)`, 's') + cliChangelog = cliChangelog.replace(versionRegex, newEntry) + } else { + // Add the new entry after the header (before the first version entry) + const firstVersionIndex = cliChangelog.search(/## \[\d+\.\d+\.\d+\]/) + + if (firstVersionIndex !== -1) { + // Insert before the first version entry + cliChangelog = cliChangelog.slice(0, firstVersionIndex) + newEntry + cliChangelog.slice(firstVersionIndex) + } else { + // No existing version entries, append to the end + cliChangelog += newEntry + } + } + + // Write the updated CLI changelog + fs.writeFileSync(cliChangelogPath, cliChangelog) + + console.log(`CLI package CHANGELOG.md updated with release notes for v${version}`) + +} catch (error) { + console.error('Error updating CHANGELOG.md:', error.message) + // Don't exit with error to allow the process to continue + // process.exit(1) +}