Skip to content

fix(tunnels): extract tunnel domain from base url#755

Merged
sid-rl merged 2 commits intomainfrom
siddarth/tunnel-url
Mar 25, 2026
Merged

fix(tunnels): extract tunnel domain from base url#755
sid-rl merged 2 commits intomainfrom
siddarth/tunnel-url

Conversation

@sid-rl
Copy link
Copy Markdown
Contributor

@sid-rl sid-rl commented Mar 24, 2026

User description

⚠️ PR Title Must Follow Conventional Commits

Format: feat[optional scope]: <description>

Examples: feat: add new SDK method · feat(storage): support file uploads · feat!: breaking API change


Description

Motivation

Changes

Testing

  • Unit tests added
  • Integration tests added
  • Smoke Tests added/updated
  • Tested locally

Breaking Changes

Checklist

  • PR title follows Conventional Commits format (feat: or feat(scope):)
  • Documentation updated (if needed)
  • Breaking changes documented (if applicable)

CodeAnt-AI Description

Use the API base domain when building tunnel links

What Changed

  • Tunnel URLs now use the same base domain as the connected API host, instead of always ending in runloop.ai
  • This keeps tunnel links working for other environments, such as runloop.pro
  • Tests now cover both the default domain and a different base domain

Impact

✅ Tunnel links work across API environments
✅ Fewer broken devbox tunnel URLs
✅ Clearer local access in non-default deployments

💡 Usage Guide

Checking Your Pull Request

Every time you make a pull request, our system automatically looks through it. We check for security issues, mistakes in how you're setting up your infrastructure, and common code problems. We do this to make sure your changes are solid and won't cause any trouble later.

Talking to CodeAnt AI

Got a question or need a hand with something in your pull request? You can easily get in touch with CodeAnt AI right here. Just type the following in a comment on your pull request, and replace "Your question here" with whatever you want to ask:

@codeant-ai ask: Your question here

This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.

Example

@codeant-ai ask: Can you suggest a safer alternative to storing this secret?

Preserve Org Learnings with CodeAnt

You can record team preferences so CodeAnt AI applies them in future reviews. Reply directly to the specific CodeAnt AI suggestion (in the same thread) and replace "Your feedback here" with your input:

@codeant-ai: Your feedback here

This helps CodeAnt AI learn and adapt to your team's coding style and standards.

Example

@codeant-ai: Do not flag unused imports.

Retrigger review

Ask CodeAnt AI to review the PR again, by typing:

@codeant-ai: review

Check Your Repository Health

To analyze the health of your code repository, visit our dashboard at https://app.codeant.ai. This tool helps you identify potential issues and areas for improvement in your codebase, ensuring your repository maintains high standards of code health.

@codeant-ai
Copy link
Copy Markdown
Contributor

codeant-ai bot commented Mar 24, 2026

CodeAnt AI is reviewing your PR.


Thanks for using CodeAnt! 🎉

We're free for open-source projects. if you're enjoying it, help us grow by sharing.

Share on X ·
Reddit ·
LinkedIn

@sid-rl sid-rl requested review from alb-rl, dines-rl and james-rl March 24, 2026 22:22
@codeant-ai codeant-ai bot added the size:S This PR changes 10-29 lines, ignoring generated files label Mar 24, 2026
@codeant-ai
Copy link
Copy Markdown
Contributor

codeant-ai bot commented Mar 24, 2026

Sequence Diagram

This PR updates tunnel URL generation to derive the tunnel domain from the SDK client base URL instead of using a fixed domain. This allows the same method to return correct tunnel hosts across different environments.

sequenceDiagram
    participant User
    participant DevboxSDK
    participant DevboxAPI

    User->>DevboxSDK: Request tunnel URL for port
    DevboxSDK->>DevboxAPI: Retrieve devbox tunnel details
    DevboxAPI-->>DevboxSDK: Return tunnel key
    DevboxSDK->>DevboxSDK: Derive base domain from client base URL and build tunnel host
    DevboxSDK-->>User: Return tunnel URL for requested port
Loading

Generated by CodeAnt AI

@codeant-ai
Copy link
Copy Markdown
Contributor

codeant-ai bot commented Mar 24, 2026

Nitpicks 🔍

🔒 No security issues identified
⚡ Recommended areas for review

  • Domain Parsing
    Deriving the tunnel domain by taking the last two hostname labels can produce incorrect hosts for multi-part public suffixes and non-standard domains, such as api.example.co.uk or localhost. This should be validated against the supported deployment hostnames to avoid generating unusable tunnel URLs.

}
return `https://${port}-${tunnel.tunnel_key}.tunnel.runloop.ai`;
const apiHost = new URL(this.client.baseURL).hostname;
const baseDomain = apiHost.split('.').slice(-2).join('.');
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: Domain extraction is incorrect for non-DNS hosts like IP-based baseURL values (for example http://127.0.0.1:4010): splitting and taking the last two labels turns 127.0.0.1 into 0.1, producing a broken tunnel URL. Derive the tunnel domain by removing only a leading api. prefix when present, and otherwise keep the full hostname. [logic error]

Severity Level: Major ⚠️
- ⚠️ `getTunnelUrl` breaks with IP-based client baseURL.
- ⚠️ Custom/local deployments get unusable tunnel links.
Suggested change
const baseDomain = apiHost.split('.').slice(-2).join('.');
const baseDomain = apiHost.startsWith('api.') ? apiHost.slice(4) : apiHost;
Steps of Reproduction ✅
1. Configure a client with non-DNS/IP host support, which is allowed by `Runloop`
constructor in `src/index.ts:331-346` (`baseURL` is accepted directly with no hostname
restriction).

2. Create or obtain a `Devbox` instance, then call `Devbox.getTunnelUrl()` (method at
`src/sdk/devbox.ts:842`) as shown in real usage at `examples/devbox-tunnel.ts:70`.

3. Execution path is `getTunnelUrl()``getTunnel()` (`src/sdk/devbox.ts:811`) →
`getInfo()` (`src/sdk/devbox.ts:793`) and then URL construction at
`src/sdk/devbox.ts:847-849`.

4. In `getTunnelUrl()`, current code derives domain using
`apiHost.split('.').slice(-2).join('.')` (`src/sdk/devbox.ts:848`); for `127.0.0.1` this
deterministically becomes `0.1` (same last-two-label behavior demonstrated via shell
extraction).

5. Returned URL becomes `https://<port>-<tunnel_key>.tunnel.0.1`, which is not the
intended tunnel host format, so consumers get a broken/unresolvable tunnel URL when using
IP-based `baseURL`.
Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** src/sdk/devbox.ts
**Line:** 848:848
**Comment:**
	*Logic Error: Domain extraction is incorrect for non-DNS hosts like IP-based `baseURL` values (for example `http://127.0.0.1:4010`): splitting and taking the last two labels turns `127.0.0.1` into `0.1`, producing a broken tunnel URL. Derive the tunnel domain by removing only a leading `api.` prefix when present, and otherwise keep the full hostname.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
👍 | 👎

@codeant-ai
Copy link
Copy Markdown
Contributor

codeant-ai bot commented Mar 24, 2026

CodeAnt AI finished reviewing your PR.

@github-actions
Copy link
Copy Markdown

github-actions bot commented Mar 24, 2026

❌ Object Smoke Tests Failed

Test Results

❌ Some smoke tests failed

Failed Tests:

  • smoketest: object-oriented devbox › devbox creation from blueprint and snapshot › create devbox from blueprint ID
  • smoketest: object-oriented devbox › devbox creation from blueprint and snapshot › create devbox from blueprint name
  • smoketest: object-oriented axons › axon lifecycle › subscribe to SSE stream and receive events
  • smoketest: object-oriented blueprint › blueprint lifecycle › create blueprint
  • smoketest: object-oriented blueprint › blueprint lifecycle › get blueprint info
  • smoketest: object-oriented blueprint › blueprint lifecycle › get blueprint logs
  • smoketest: object-oriented blueprint › blueprint lifecycle › create devbox from blueprint (SDK method)
  • smoketest: object-oriented blueprint › blueprint lifecycle › create devbox from blueprint (instance method)
  • smoketest: object-oriented blueprint › blueprint lifecycle › delete blueprint
  • smoketest: object-oriented blueprint › blueprint build context with object storage and .dockerignore › creates blueprint with COPY using object-based build context honoring .dockerignore

Please fix the failing tests before checking coverage.

📋 View full test logs

Copy link
Copy Markdown
Contributor

@james-rl james-rl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should change this so that it's more obvious what the tunnel url is or just skip this entire test in dev.

Right now this is not really a great example.

That said, I'm eager to fix the smoke test, so I'm approving this

@sid-rl sid-rl force-pushed the siddarth/tunnel-url branch from 1d591bb to 5af7c81 Compare March 24, 2026 23:42
@sid-rl sid-rl force-pushed the siddarth/tunnel-url branch from 5af7c81 to 775c494 Compare March 25, 2026 03:00
@sid-rl sid-rl merged commit 03b7479 into main Mar 25, 2026
8 of 9 checks passed
@sid-rl sid-rl deleted the siddarth/tunnel-url branch March 25, 2026 03:10
@stainless-app stainless-app bot mentioned this pull request Mar 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:S This PR changes 10-29 lines, ignoring generated files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants