Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
1 change: 1 addition & 0 deletions .releaserc.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"branches": ["release"],
"extends": "semantic-release-monorepo",
"plugins": [
"@semantic-release/commit-analyzer",
"@semantic-release/release-notes-generator",
Expand Down
1 change: 1 addition & 0 deletions docs/release-process.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Release Process with semantic-release-monorepo\n\n## Overview\n\nThis project uses `semantic-release-monorepo` to automate the versioning and release process across all packages in the monorepo. This ensures that each package is versioned independently based on its own changes, while maintaining a consistent release process.\n\n## How It Works\n\n1. When code is pushed to the `release` branch, the GitHub Actions workflow is triggered.\n2. The workflow builds and tests all packages.\n3. `semantic-release-monorepo` analyzes the commit history for each package to determine the next version.\n4. New versions are published to npm, and release notes are generated based on conventional commits.\n5. Git tags are created for each package release.\n\n## Commit Message Format\n\nThis project follows the [Conventional Commits](https://www.conventionalcommits.org/) specification. Your commit messages should be structured as follows:\n\n```\n<type>[optional scope]: <description>\n\n[optional body]\n\n[optional footer(s)]\n```\n\nExamples:\n\n```\nfeat(cli): add new command for project initialization\nfix(agent): resolve issue with async tool execution\ndocs: update installation instructions\n```\n\n### Types\n\n- `feat`: A new feature (triggers a minor version bump)\n- `fix`: A bug fix (triggers a patch version bump)\n- `docs`: Documentation changes\n- `style`: Changes that don't affect the code's meaning (formatting, etc.)\n- `refactor`: Code changes that neither fix a bug nor add a feature\n- `perf`: Performance improvements\n- `test`: Adding or correcting tests\n- `chore`: Changes to the build process, tooling, etc.\n\n### Breaking Changes\n\nIf your commit introduces a breaking change, add `BREAKING CHANGE:` in the footer followed by a description of the change. This will trigger a major version bump.\n\nExample:\n\n```\nfeat(agent): change API for tool execution\n\nBREAKING CHANGE: The tool execution API now requires an options object instead of individual parameters.\n```\n\n## Troubleshooting\n\nIf you encounter issues with the release process:\n\n1. Run `pnpm verify-release-config` to check if your semantic-release configuration is correct.\n2. Ensure your commit messages follow the conventional commits format.\n3. Check if the package has a `.releaserc.json` file that extends `semantic-release-monorepo`.\n4. Verify that each package has a `semantic-release` script in its `package.json`.\n\n## Manual Release\n\nIn rare cases, you might need to trigger a release manually. You can do this by:\n\n```bash\n# Release all packages\npnpm release\n\n# Release a specific package\ncd packages/cli\npnpm semantic-release\n```\n
1 change: 1 addition & 0 deletions lerna.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{\n \"version\": \"independent\",\n \"npmClient\": \"pnpm\",\n \"command\": {\n \"publish\": {\n \"conventionalCommits\": true,\n \"message\": \"chore(release): publish\"\n }\n },\n \"packages\": [\"packages/*\"]\n}
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
"cli": "cd packages/cli && node --no-deprecation bin/cli.js",
"prepare": "husky",
"semantic-release": "semantic-release",
"release": "semantic-release"
"verify-release-config": "node scripts/verify-release-config.js",
"release": "pnpm verify-release-config && npx lerna exec --concurrency 1 -- npx --no-install semantic-release -e semantic-release-monorepo"
},
"lint-staged": {
"*.{js,jsx,ts,tsx}": [
Expand Down Expand Up @@ -51,9 +52,11 @@
"eslint-plugin-promise": "^7.2.1",
"eslint-plugin-unused-imports": "^4.1.4",
"husky": "^9.1.7",
"lerna": "^8.2.1",
"lint-staged": "^15.4.3",
"prettier": "^3.5.1",
"semantic-release": "^24.2.3",
"semantic-release-monorepo": "^8.0.2",
"typescript-eslint": "^8.23.0"
},
"pnpm": {
Expand Down
18 changes: 18 additions & 0 deletions packages/agent/.releaserc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"extends": "semantic-release-monorepo",
"branches": ["release"],
"plugins": [
"@semantic-release/commit-analyzer",
"@semantic-release/release-notes-generator",
"@semantic-release/changelog",
"@semantic-release/npm",
[
"@semantic-release/git",
{
"assets": ["package.json", "CHANGELOG.md"],
"message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
}
],
"@semantic-release/github"
]
}
3 changes: 2 additions & 1 deletion packages/agent/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@
"typecheck": "tsc --noEmit",
"clean": "rimraf dist",
"clean:all": "rimraf node_modules dist",
"prepublishOnly": "pnpm run clean && pnpm run build && pnpm run test"
"prepublishOnly": "pnpm run clean && pnpm run build && pnpm run test",
"semantic-release": "semantic-release -e semantic-release-monorepo"
},
"keywords": [
"ai",
Expand Down
18 changes: 18 additions & 0 deletions packages/cli/.releaserc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"extends": "semantic-release-monorepo",
"branches": ["release"],
"plugins": [
"@semantic-release/commit-analyzer",
"@semantic-release/release-notes-generator",
"@semantic-release/changelog",
"@semantic-release/npm",
[
"@semantic-release/git",
{
"assets": ["package.json", "CHANGELOG.md"],
"message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
}
],
"@semantic-release/github"
]
}
3 changes: 2 additions & 1 deletion packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@
"test:ci": "vitest --run --coverage",
"changeset": "changeset",
"version": "changeset version",
"prepublishOnly": "pnpm run clean && pnpm run build && pnpm run test"
"prepublishOnly": "pnpm run clean && pnpm run build && pnpm run test",
"semantic-release": "semantic-release -e semantic-release-monorepo"
},
"keywords": [
"ai",
Expand Down
83 changes: 83 additions & 0 deletions scripts/verify-release-config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
#!/usr/bin/env node

/* eslint-disable no-console */
/* eslint-env node */

import fs from 'fs';
import path from 'path';

const ROOT_DIR = path.resolve('.');
const PACKAGES_DIR = path.join(ROOT_DIR, 'packages');

console.log('Starting verification script...');
console.log('Checking root package.json...');
// Check if required packages are installed
const rootPackageJson = JSON.parse(fs.readFileSync(path.join(ROOT_DIR, 'package.json'), 'utf8'));
const hasSemanticReleaseMonorepo = rootPackageJson.devDependencies && 'semantic-release-monorepo' in rootPackageJson.devDependencies;
const hasLerna = rootPackageJson.devDependencies && 'lerna' in rootPackageJson.devDependencies;

if (!hasSemanticReleaseMonorepo) {
console.error('❌ semantic-release-monorepo is not installed in root package.json');
process.exit(1);
}

if (!hasLerna) {
console.error('❌ lerna is not installed in root package.json');
process.exit(1);
}

console.log('Checking root .releaserc.json...');
// Check root .releaserc.json
const rootReleaseRc = JSON.parse(fs.readFileSync(path.join(ROOT_DIR, '.releaserc.json'), 'utf8'));
if (!rootReleaseRc.extends || rootReleaseRc.extends !== 'semantic-release-monorepo') {
console.error('❌ Root .releaserc.json does not extend semantic-release-monorepo');
process.exit(1);
}

console.log('Checking lerna.json...');
// Check lerna.json
if (!fs.existsSync(path.join(ROOT_DIR, 'lerna.json'))) {
console.error('❌ lerna.json is missing');
process.exit(1);
}

console.log('Checking packages...');
// Check packages
const packages = fs.readdirSync(PACKAGES_DIR)
.filter(dir => fs.statSync(path.join(PACKAGES_DIR, dir)).isDirectory());

console.log(`Found packages: ${packages.join(', ')}`);

for (const pkg of packages) {
const packageDir = path.join(PACKAGES_DIR, pkg);
const packageJsonPath = path.join(packageDir, 'package.json');
const releaseRcPath = path.join(packageDir, '.releaserc.json');

console.log(`Checking package ${pkg}...`);

// Check package.json
if (fs.existsSync(packageJsonPath)) {
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
if (!packageJson.scripts || !packageJson.scripts['semantic-release']) {
console.error(`❌ Package ${pkg} does not have a semantic-release script`);
process.exit(1);
}
} else {
console.error(`❌ Package ${pkg} does not have a package.json file`);
process.exit(1);
}

// Check .releaserc.json
if (fs.existsSync(releaseRcPath)) {
const releaseRc = JSON.parse(fs.readFileSync(releaseRcPath, 'utf8'));
if (!releaseRc.extends || releaseRc.extends !== 'semantic-release-monorepo') {
console.error(`❌ Package ${pkg} .releaserc.json does not extend semantic-release-monorepo`);
process.exit(1);
}
} else {
console.error(`❌ Package ${pkg} does not have a .releaserc.json file`);
process.exit(1);
}
}

console.log('✅ All semantic-release-monorepo configurations are correct!');
Loading