Răsfoiți Sursa

Use a redirect instead of a fetch for cli auth (#10799)

Chris Estreich 5 zile în urmă
părinte
comite
98d35f7cfc
3 a modificat fișierele cu 61 adăugiri și 37 ștergeri
  1. 45 3
      .roo/commands/cli-release.md
  2. 1 4
      apps/cli/scripts/release.sh
  3. 15 30
      apps/cli/src/commands/auth/login.ts

+ 45 - 3
.roo/commands/cli-release.md

@@ -48,16 +48,58 @@ mode: code
     - Include links to relevant source files where helpful
     - Include links to relevant source files where helpful
     - Describe changes from the user's perspective
     - Describe changes from the user's perspective
 
 
-5. Commit the version bump and changelog update:
+5. Create a release branch and commit the changes:
 
 
     ```bash
     ```bash
+    # Ensure you're on main and up to date
+    git checkout main
+    git pull origin main
+
+    # Create a new branch for the release
+    git checkout -b cli-release-v<version>
+
+    # Commit the version bump and changelog update
     git add apps/cli/package.json apps/cli/CHANGELOG.md
     git add apps/cli/package.json apps/cli/CHANGELOG.md
     git commit -m "chore(cli): prepare release v<version>"
     git commit -m "chore(cli): prepare release v<version>"
+
+    # Push the branch to origin
+    git push -u origin cli-release-v<version>
     ```
     ```
 
 
-6. Run the release script from the monorepo root:
+6. Create a pull request for the release:
 
 
     ```bash
     ```bash
+    gh pr create --title "chore(cli): prepare release v<version>" \
+        --body "## CLI Release v<version>
+
+    This PR prepares the CLI release v<version>.
+
+    ### Changes
+    - Version bump in package.json
+    - Changelog update
+
+    ### Checklist
+    - [ ] Version number is correct
+    - [ ] Changelog entry is complete and accurate
+    - [ ] All CI checks pass" \
+        --base main
+    ```
+
+7. Wait for PR approval and merge:
+
+    - Request review if required by your workflow
+    - Ensure CI checks pass
+    - Merge the PR using: `gh pr merge --squash --delete-branch`
+    - Or merge via the GitHub UI
+
+8. Run the release script from the monorepo root:
+
+    ```bash
+    # Ensure you're on the updated main branch after the PR merge
+    git checkout main
+    git pull origin main
+
+    # Run the release script
     ./apps/cli/scripts/release.sh
     ./apps/cli/scripts/release.sh
     ```
     ```
 
 
@@ -69,7 +111,7 @@ mode: code
     - Extract changelog content and include it in the GitHub release notes
     - Extract changelog content and include it in the GitHub release notes
     - Create the GitHub release with the tarball attached
     - Create the GitHub release with the tarball attached
 
 
-7. After a successful release, verify:
+9. After a successful release, verify:
     - Check the release page: https://github.com/RooCodeInc/Roo-Code/releases
     - Check the release page: https://github.com/RooCodeInc/Roo-Code/releases
     - Verify the "What's New" section contains the changelog content
     - Verify the "What's New" section contains the changelog content
     - Test installation: `curl -fsSL https://raw.githubusercontent.com/RooCodeInc/Roo-Code/main/apps/cli/install.sh | sh`
     - Test installation: `curl -fsSL https://raw.githubusercontent.com/RooCodeInc/Roo-Code/main/apps/cli/install.sh | sh`

+ 1 - 4
apps/cli/scripts/release.sh

@@ -536,11 +536,8 @@ ROO_VERSION=$VERSION curl -fsSL https://raw.githubusercontent.com/RooCodeInc/Roo
 ## Usage
 ## Usage
 
 
 \`\`\`bash
 \`\`\`bash
-# Set your API key
-export OPENROUTER_API_KEY=sk-or-v1-...
-
 # Run a task
 # Run a task
-roo "What is this project?" ~/my-project
+roo "What is this project?"
 
 
 # See all options
 # See all options
 roo --help
 roo --help

+ 15 - 30
apps/cli/src/commands/auth/login.ts

@@ -32,58 +32,43 @@ export async function login({ timeout = 5 * 60 * 1000, verbose = false }: LoginO
 		console.log(`[Auth] Starting local callback server on port ${port}`)
 		console.log(`[Auth] Starting local callback server on port ${port}`)
 	}
 	}
 
 
-	const corsHeaders = {
-		"Access-Control-Allow-Origin": AUTH_BASE_URL,
-		"Access-Control-Allow-Methods": "POST, OPTIONS",
-		"Access-Control-Allow-Headers": "Content-Type",
-	}
-
 	// Create promise that will be resolved when we receive the callback.
 	// Create promise that will be resolved when we receive the callback.
 	const tokenPromise = new Promise<{ token: string; state: string }>((resolve, reject) => {
 	const tokenPromise = new Promise<{ token: string; state: string }>((resolve, reject) => {
 		const server = http.createServer((req, res) => {
 		const server = http.createServer((req, res) => {
 			const url = new URL(req.url!, host)
 			const url = new URL(req.url!, host)
 
 
-			// Handle CORS preflight request.
-			if (req.method === "OPTIONS") {
-				res.writeHead(204, corsHeaders)
-				res.end()
-				return
-			}
-
-			if (url.pathname === "/callback" && req.method === "POST") {
+			if (url.pathname === "/callback") {
 				const receivedState = url.searchParams.get("state")
 				const receivedState = url.searchParams.get("state")
 				const token = url.searchParams.get("token")
 				const token = url.searchParams.get("token")
 				const error = url.searchParams.get("error")
 				const error = url.searchParams.get("error")
 
 
-				const sendJsonResponse = (status: number, body: object) => {
-					res.writeHead(status, {
-						...corsHeaders,
-						"Content-Type": "application/json",
-					})
-					res.end(JSON.stringify(body))
-				}
-
 				if (error) {
 				if (error) {
-					sendJsonResponse(400, { success: false, error })
-					res.on("close", () => {
+					const errorUrl = new URL(`${AUTH_BASE_URL}/cli/sign-in?error=error-in-callback`)
+					errorUrl.searchParams.set("message", error)
+					res.writeHead(302, { Location: errorUrl.toString() })
+					res.end(() => {
 						server.close()
 						server.close()
 						reject(new Error(error))
 						reject(new Error(error))
 					})
 					})
 				} else if (!token) {
 				} else if (!token) {
-					sendJsonResponse(400, { success: false, error: "Missing token in callback" })
-					res.on("close", () => {
+					const errorUrl = new URL(`${AUTH_BASE_URL}/cli/sign-in?error=missing-token`)
+					errorUrl.searchParams.set("message", "Missing token in callback")
+					res.writeHead(302, { Location: errorUrl.toString() })
+					res.end(() => {
 						server.close()
 						server.close()
 						reject(new Error("Missing token in callback"))
 						reject(new Error("Missing token in callback"))
 					})
 					})
 				} else if (receivedState !== state) {
 				} else if (receivedState !== state) {
-					sendJsonResponse(400, { success: false, error: "Invalid state parameter" })
-					res.on("close", () => {
+					const errorUrl = new URL(`${AUTH_BASE_URL}/cli/sign-in?error=invalid-state-parameter`)
+					errorUrl.searchParams.set("message", "Invalid state parameter")
+					res.writeHead(302, { Location: errorUrl.toString() })
+					res.end(() => {
 						server.close()
 						server.close()
 						reject(new Error("Invalid state parameter"))
 						reject(new Error("Invalid state parameter"))
 					})
 					})
 				} else {
 				} else {
-					sendJsonResponse(200, { success: true })
-					res.on("close", () => {
+					res.writeHead(302, { Location: `${AUTH_BASE_URL}/cli/sign-in?success=true` })
+					res.end(() => {
 						server.close()
 						server.close()
 						resolve({ token, state: receivedState })
 						resolve({ token, state: receivedState })
 					})
 					})