Package for Render Deployment - #11
Open
SiddharthMadhavan wants to merge 20 commits into
Open
Conversation
Updated package versions in requirements.txt to latest.
Updated package versions in requirements.txt to latest.
…chestrate and WatsonX
There was a problem hiding this comment.
Pull request overview
Packages the project for Render deployment: switches the VS Code extension to point at a hosted Render backend by default, removes the in-extension setup wizard, teaches the extension/back end to analyze a remote repo_url (cloned server-side) when the backend isn't local, and adds deployment artifacts (Dockerfile, Procfile, render.yaml, runtime.txt, release notes, LICENSE, vsce packaging).
Changes:
- Drop the WatsonX/Orchestrate setup wizard from the webview and
SidebarProvider; add_resolveAnalysisPath, git-remote auto-detection, and a newreposense.remoteRepoUrlsetting so remote backends can clone the user's repo. - Backend now accepts
repo_urlinAnalyzeRequest, clones to a temp dir withgit clone --depth 1, adds/config/test-orchestrateand/config/test-watsonxdiagnostic endpoints, and reloads settings in place after/config/setup. - Add Render/Docker/Procfile/runtime/release-notes/LICENSE packaging files; bump extension version to 1.0.0 and add
vscepackaging.
Reviewed changes
Copilot reviewed 21 out of 28 changed files in this pull request and generated 13 comments.
Show a summary per file
| File | Description |
|---|---|
| vscode-extension/webview/main.js | Remove setup-wizard handlers; consolidate hideAllStates. |
| vscode-extension/webview/main.html | Delete setup-wizard markup. |
| vscode-extension/src/SidebarProvider.ts | Add path resolution, git-remote detection, repo_url request body, richer error messages; drop config-check/save flow. |
| vscode-extension/src/config.ts | Default backend to Render URL; add remoteRepoUrl setting. |
| vscode-extension/package.json / package-lock.json | Bump to 1.0.0, add vsce devDep and packaging script, add (placeholder) repository URL. |
| vscode-extension/out/* | Recompiled JS / source maps mirroring the TS changes. |
| vscode-extension/RELEASE_NOTES.md | New 1.0.0 release notes (still references the removed setup screen). |
| vscode-extension/LICENSE | New MIT license file. |
| backend/src/main.py | Accept repo_url, clone to temp dir, add diagnostic endpoints, call reload_settings. |
| backend/src/models.py | AnalyzeRequest now allows local_path or repo_url via model_validator. |
| backend/src/config.py | Optional .env loading; add reload_settings; change default WatsonX model. |
| backend/src/orchestrate_client.py | Guard against empty API key; recreate client when settings change. |
| backend/Dockerfile / Procfile / render.yaml / runtime.txt / requirements.txt | New Render deployment artifacts (includes invalid asyncio==4.0.0, .env* COPY, conflicting Procfiles). |
| Procfile / render.yaml / runtime.txt / requirements.txt (root) | Duplicate/competing deployment descriptors at the repo root. |
| .vscode/settings.json, .vscode/launch.json | Workspace settings + extension launch config. |
Files not reviewed (1)
- vscode-extension/package-lock.json: Language not supported
Comments suppressed due to low confidence (1)
vscode-extension/package.json:105
vscewas renamed to@vscode/vsceand thevscepackage is deprecated (the install output even emits a deprecation warning, visible in this lockfile under "deprecated"). For a fresh 1.0.0 packaging script, please depend on@vscode/vsceinstead and update thepackagescript tovsce packagefrom the new bin.
,
"vsce": "^2.0.0"
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| @@ -0,0 +1 @@ | |||
| python-3.11.9 | |||
| @@ -0,0 +1 @@ | |||
| web: pip install -r backend/requirements.txt && cd backend && gunicorn -k uvicorn.workers.UvicornWorker src.main:app --bind 0.0.0.0:$PORT --workers 1 | |||
| @@ -0,0 +1 @@ | |||
| web: cd backend && gunicorn -k uvicorn.workers.UvicornWorker src.main:app --bind 0.0.0.0:$PORT --workers 1 | |||
|
|
||
| # Copy the source | ||
| COPY src ./src | ||
| COPY .env* ./ |
| "version": "1.0.0", | ||
| "repository": { | ||
| "type": "git", | ||
| "url": "https://github.com/yourusername/bits-and-bobs-deployment.git" |
Comment on lines
+375
to
+403
| private _tryGetWorkspaceGitRemote(analysisPath: string): string | null { | ||
| try { | ||
| const output = cp.execFileSync('git', ['-C', analysisPath, 'remote', 'get-url', 'origin'], { | ||
| encoding: 'utf8', | ||
| timeout: 5000, | ||
| stdio: ['ignore', 'pipe', 'ignore'] | ||
| }).trim(); | ||
|
|
||
| if (!output) { | ||
| return null; | ||
| } | ||
|
|
||
| return this._normalizeGitRemoteUrl(output); | ||
| } catch { | ||
| return null; | ||
| } | ||
| } | ||
|
|
||
| private _normalizeGitRemoteUrl(remoteUrl: string): string { | ||
| const trimmed = remoteUrl.trim(); | ||
| const sshMatch = /^git@([^:]+):(.+)$/.exec(trimmed); | ||
| if (sshMatch) { | ||
| const host = sshMatch[1]; | ||
| const repoPath = sshMatch[2]; | ||
| return `https://${host}/${repoPath}`; | ||
| } | ||
|
|
||
| return trimmed; | ||
| } |
Comment on lines
103
to
+104
| "typescript": "^4.9.3" | ||
| , |
Comment on lines
231
to
264
| @@ -192,9 +257,10 @@ async def analyze_codebase( | |||
|
|
|||
| # Start background analysis with validated path | |||
| background_tasks.add_task( | |||
| orchestrate_analysis, | |||
| run_analysis_with_optional_cleanup, | |||
| job_id=job_id, | |||
| local_path=validated_path | |||
| local_path=validated_path, | |||
| temp_root=temp_clone_root, | |||
| ) | |||
Comment on lines
+116
to
+157
| def validate_repo_url(repo_url: str) -> str: | ||
| """Validate repository URL format for server-side clone analysis.""" | ||
| normalized = (repo_url or "").strip() | ||
| if not normalized: | ||
| raise HTTPException(status_code=400, detail="repo_url cannot be empty") | ||
|
|
||
| valid_prefixes = ("https://", "http://", "git@") | ||
| if not normalized.startswith(valid_prefixes): | ||
| raise HTTPException( | ||
| status_code=400, | ||
| detail="repo_url must start with https://, http://, or git@" | ||
| ) | ||
|
|
||
| return normalized | ||
|
|
||
|
|
||
| def clone_repo_to_temp(repo_url: str) -> tuple[str, str]: | ||
| """Clone repository to a temporary directory and return (repo_path, temp_root).""" | ||
| temp_root = tempfile.mkdtemp(prefix="reposense-") | ||
| repo_path = str(Path(temp_root) / "repo") | ||
|
|
||
| try: | ||
| subprocess.run( | ||
| ["git", "clone", "--depth", "1", repo_url, repo_path], | ||
| check=True, | ||
| capture_output=True, | ||
| text=True, | ||
| timeout=180, | ||
| ) | ||
| except FileNotFoundError as e: | ||
| shutil.rmtree(temp_root, ignore_errors=True) | ||
| raise HTTPException(status_code=500, detail="git is not available on the backend server") from e | ||
| except subprocess.TimeoutExpired as e: | ||
| shutil.rmtree(temp_root, ignore_errors=True) | ||
| raise HTTPException(status_code=408, detail="Timed out while cloning repository") from e | ||
| except subprocess.CalledProcessError as e: | ||
| shutil.rmtree(temp_root, ignore_errors=True) | ||
| stderr = (e.stderr or "").strip() | ||
| message = stderr[:300] if stderr else "Unknown git clone error" | ||
| raise HTTPException(status_code=400, detail=f"Failed to clone repository: {message}") from e | ||
|
|
||
| return repo_path, temp_root |
Comment on lines
+361
to
+389
| @app.get("/config/test-orchestrate") | ||
| async def config_test_orchestrate(): | ||
| """Perform an IAM token exchange using the configured ORCHESTRATE_API_KEY. | ||
|
|
||
| Returns the first bytes of the token on success, or a 400 with the error message. | ||
| """ | ||
| try: | ||
| from .orchestrate_client import get_orchestrate_client | ||
| client = get_orchestrate_client() | ||
| token = await client._get_iam_token() | ||
| return {"ok": True, "message": "IAM token obtained", "token_excerpt": (token[:16] + "...") if token else None} | ||
| except Exception as e: | ||
| return JSONResponse(status_code=400, content={"ok": False, "error": str(e)}) | ||
|
|
||
|
|
||
| @app.get("/config/test-watsonx") | ||
| async def config_test_watsonx(): | ||
| """Perform a minimal WatsonX call to validate WatsonX credentials and project. | ||
|
|
||
| Returns an excerpt of the response on success, or a 400 with the error message. | ||
| """ | ||
| try: | ||
| from .watsonx import _call_watsonx | ||
| # Use a short prompt that should always succeed if credentials and project are valid | ||
| resp = await _call_watsonx("Say hello in one short sentence.") | ||
| excerpt = resp[:200] if isinstance(resp, str) else str(resp) | ||
| return {"ok": True, "message": "WatsonX responded", "response_excerpt": excerpt} | ||
| except Exception as e: | ||
| return JSONResponse(status_code=400, content={"ok": False, "error": str(e)}) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.