| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351 |
- /* eslint-env node */
- const fs = require("fs")
- const path = require("path")
- const { execSync } = require("child_process")
- const readline = require("readline")
- const PACKAGE_NAME = "@roo-code/types"
- const BRANCH_NAME = "roo-code-types-v"
- const rootDir = path.join(__dirname, "..")
- const npmDir = path.join(rootDir, "npm")
- const monorepoPackagePath = path.join(rootDir, "package.json")
- const npmMetadataPath = path.join(npmDir, "package.metadata.json")
- const npmPackagePath = path.join(npmDir, "package.json")
- const args = process.argv.slice(2)
- const publishOnly = args.includes("--publish-only")
- async function confirmPublish() {
- const rl = readline.createInterface({
- input: process.stdin,
- output: process.stdout,
- })
- return new Promise((resolve) => {
- rl.question("\n⚠️ Are you sure you want to publish to npm? (y/n): ", (answer) => {
- rl.close()
- resolve(answer.toLowerCase() === "y")
- })
- })
- }
- function updatePackageVersion(filePath, version) {
- try {
- const packageContent = JSON.parse(fs.readFileSync(filePath, "utf8"))
- const oldVersion = packageContent.version
- packageContent.version = version
- fs.writeFileSync(filePath, JSON.stringify(packageContent, null, 2) + "\n")
- try {
- execSync(`npx prettier --write "${filePath}"`, { stdio: "pipe" })
- console.log(`✨ Formatted ${path.basename(filePath)} with prettier`)
- } catch (prettierError) {
- console.warn(`⚠️ Could not format with prettier:`, prettierError.message)
- }
- const fileName = path.basename(filePath)
- console.log(`✅ Updated ${fileName} version: ${oldVersion} → ${version}`)
- return oldVersion
- } catch (error) {
- throw new Error(`Failed to update version in ${path.basename(filePath)}: ${error.message}`)
- }
- }
- function syncVersionToMetadata(version) {
- console.log(" 📝 Syncing version to package.metadata.json...")
- updatePackageVersion(npmMetadataPath, version)
- }
- function commitVersionChanges(version) {
- try {
- console.log(" 📝 Committing version changes to git...")
- try {
- const status = execSync("git status --porcelain", { encoding: "utf8" })
- const relevantChanges = status.split("\n").filter((line) => line.includes("packages/types/npm/package"))
- if (relevantChanges.length === 0) {
- console.log(" ⚠️ No version changes to commit")
- return
- }
- } catch (error) {
- console.warn(" ⚠️ Could not check git status:", error.message)
- }
- execSync("git add .", { stdio: "pipe" })
- const commitMessage = `chore: bump version to v${version}`
- execSync(`git commit -m "${commitMessage}"`, { stdio: "pipe" })
- console.log(` ✅ Committed: ${commitMessage}`)
- } catch (error) {
- console.warn(" ⚠️ Could not commit version changes:", error.message)
- console.log(" You may need to commit these changes manually.")
- }
- }
- function checkGitHubCLI() {
- try {
- execSync("gh --version", { stdio: "pipe" })
- execSync("gh auth status", { stdio: "pipe" })
- return true
- } catch (_error) {
- return false
- }
- }
- function createPullRequest(branchName, baseBranch, version) {
- try {
- console.log(` 🔄 Creating pull request...`)
- if (!checkGitHubCLI()) {
- console.warn(" ⚠️ GitHub CLI not found or not authenticated")
- console.log(" Install gh CLI and run: gh auth login")
- console.log(" Then manually create PR with: gh pr create")
- return
- }
- const title = `Release: v${version}`
- const body = `## 🚀 Release v${version}
- This PR contains the version bump for the SDK release v${version}.
- ### Changes
- - Bumped version from previous to v${version}
- - Published to npm as ${PACKAGE_NAME}@${version}
- ### Checklist
- - [x] Version bumped
- - [x] Package published to npm
- - [ ] Changelog updated (if applicable)
- - [ ] Documentation updated (if applicable)
- ---
- *This PR was automatically created by the npm publish script.*`
- try {
- // Create the pull request
- const prUrl = execSync(
- `gh pr create --base "${baseBranch}" --head "${branchName}" --title "${title}" --body "${body}"`,
- { encoding: "utf8", stdio: "pipe" },
- ).trim()
- console.log(` ✅ Pull request created: ${prUrl}`)
- } catch (error) {
- if (error.message.includes("already exists")) {
- console.log(" ℹ️ Pull request already exists for this branch")
- } else {
- throw error
- }
- }
- } catch (error) {
- console.error(" ❌ Failed to create pull request:", error.message)
- console.log(" You can manually create a PR with:")
- console.log(` gh pr create --base "${baseBranch}" --head "${branchName}"`)
- }
- }
- function createVersionBranchAndCommit(version) {
- try {
- const branchName = `${BRANCH_NAME}${version}`
- console.log(` 🌿 Creating version branch: ${branchName}...`)
- let currentBranch
- try {
- currentBranch = execSync("git rev-parse --abbrev-ref HEAD", {
- encoding: "utf8",
- }).trim()
- } catch (_error) {
- console.warn(" ⚠️ Could not determine current branch")
- currentBranch = "main"
- }
- execSync(`git checkout -b ${branchName}`, { stdio: "pipe" })
- console.log(` ✅ Created branch: ${branchName}`)
- commitVersionChanges(version)
- execSync(`git push --set-upstream origin ${branchName}`, { stdio: "pipe" })
- console.log(` ✅ Pushed branch to origin with upstream tracking`)
- createPullRequest(branchName, currentBranch, version)
- if (currentBranch) {
- execSync(`git checkout ${currentBranch}`, { stdio: "pipe" })
- console.log(` ✅ Returned to branch: ${currentBranch}`)
- }
- console.log(` 🎯 Version branch created with commits: ${branchName}`)
- } catch (error) {
- console.error(" ❌ Failed to create version branch:", error.message)
- console.log(" You may need to create the branch manually.")
- }
- }
- function generateNpmPackage() {
- try {
- console.log(" 📖 Reading monorepo package.json...")
- const monorepoPackageContent = fs.readFileSync(monorepoPackagePath, "utf8")
- const monorepoPackage = JSON.parse(monorepoPackageContent)
- console.log(" 📖 Reading npm package metadata...")
- const npmMetadataContent = fs.readFileSync(npmMetadataPath, "utf8")
- const npmMetadata = JSON.parse(npmMetadataContent)
- console.log(" 🔨 Generating npm package.json...")
- const npmPackage = {
- ...npmMetadata,
- dependencies: monorepoPackage.dependencies || {},
- main: "./dist/index.cjs",
- module: "./dist/index.js",
- types: "./dist/index.d.ts",
- exports: {
- ".": {
- types: "./dist/index.d.ts",
- import: "./dist/index.js",
- require: {
- types: "./dist/index.d.cts",
- default: "./dist/index.cjs",
- },
- },
- },
- files: ["dist"],
- }
- const outputContent = JSON.stringify(npmPackage, null, 2) + "\n"
- fs.writeFileSync(npmPackagePath, outputContent)
- console.log(" ✅ npm/package.json generated successfully")
- console.log(` 📦 Package name: ${npmPackage.name}`)
- console.log(` 📌 Version: ${npmPackage.version}`)
- console.log(` 📚 Dependencies: ${Object.keys(npmPackage.dependencies).length}`)
- } catch (error) {
- throw new Error(`Failed to generate npm package.json: ${error.message}`)
- }
- }
- async function publish() {
- try {
- console.log("\n🚀 NPM PUBLISH WORKFLOW")
- if (publishOnly) {
- console.log("📌 Mode: Publish only (no git operations)")
- }
- console.log("=".repeat(60))
- console.log("\n📦 Step 1: Generating npm package.json...")
- generateNpmPackage()
- const npmPackage = JSON.parse(fs.readFileSync(npmPackagePath, "utf8"))
- const originalVersion = npmPackage.version // Save original version
- console.log(`\n📌 Current version: ${npmPackage.version}`)
- console.log(`📦 Package name: ${npmPackage.name}`)
- console.log("\n📈 Step 2: Bumping version (minor)...")
- try {
- execSync("npm version minor --no-git-tag-version", {
- cwd: npmDir,
- stdio: "inherit",
- })
- } catch (error) {
- console.error("❌ Failed to bump version:", error.message)
- throw error
- }
- const updatedPackage = JSON.parse(fs.readFileSync(npmPackagePath, "utf8"))
- console.log(`✅ New version: ${updatedPackage.version}`)
- console.log("\n🔨 Step 3: Building production bundle...")
- console.log(" This may take a moment...")
- try {
- execSync("NODE_ENV=production pnpm tsup --outDir npm/dist", {
- cwd: rootDir,
- stdio: "inherit",
- })
- console.log("✅ Production build complete")
- } catch (error) {
- console.error("❌ Build failed:", error.message)
- throw error
- }
- console.log("\n" + "=".repeat(60))
- console.log("📋 PUBLISH SUMMARY:")
- console.log(` Package: ${updatedPackage.name}`)
- console.log(` Version: ${updatedPackage.version}`)
- console.log(` Registry: ${updatedPackage.publishConfig?.registry || "https://registry.npmjs.org/"}`)
- console.log(` Access: ${updatedPackage.publishConfig?.access || "public"}`)
- console.log("=".repeat(60))
- const confirmed = await confirmPublish()
- if (!confirmed) {
- console.log("\n❌ Publishing cancelled by user")
- console.log("🔙 Reverting version change...")
- try {
- updatePackageVersion(npmPackagePath, originalVersion)
- } catch (revertError) {
- console.error("⚠️ Could not revert version:", revertError.message)
- console.log(` You may need to manually change version back to ${originalVersion}`)
- }
- process.exit(0)
- }
- console.log("\n💾 Step 4: Syncing version to metadata...")
- syncVersionToMetadata(updatedPackage.version)
- console.log("\n🚀 Step 5: Publishing to npm...")
- try {
- execSync("npm publish", {
- cwd: npmDir,
- stdio: "inherit",
- })
- } catch (error) {
- console.error("❌ Publish failed:", error.message)
- console.error("💡 The package was built but not published.")
- console.error(" You can try publishing manually from the npm directory.")
- throw error
- }
- if (!publishOnly) {
- console.log("\n🌿 Step 6: Creating version branch, committing, and opening PR...")
- createVersionBranchAndCommit(updatedPackage.version)
- } else {
- console.log("\n📝 Step 6: Skipping version branch creation (--publish-only mode)")
- }
- console.log("\n" + "=".repeat(60))
- console.log("✅ Successfully published to npm!")
- console.log(`🎉 ${updatedPackage.name}@${updatedPackage.version} is now live`)
- console.log(`📦 View at: https://www.npmjs.com/package/${updatedPackage.name}`)
- if (!publishOnly) {
- console.log(`🌿 Version branch: ${BRANCH_NAME}${updatedPackage.version}`)
- }
- console.log("=".repeat(60) + "\n")
- } catch (error) {
- console.error("\n❌ Error during publish process:", error.message)
- console.error("\n💡 Troubleshooting tips:")
- console.error(" 1. Ensure you are logged in to npm: npm whoami")
- console.error(" 2. Check your npm permissions for this package")
- console.error(" 3. Verify the package name is not already taken")
- console.error(" 4. Make sure all dependencies are installed: pnpm install")
- process.exit(1)
- }
- }
- async function main() {
- await publish()
- }
- main().catch((error) => {
- console.error("Unexpected error:", error)
- process.exit(1)
- })
|