Skip to content

Support publishing additional container ports in thv run#3892

Open
Sanskarzz wants to merge 4 commits intostacklok:mainfrom
Sanskarzz:addports
Open

Support publishing additional container ports in thv run#3892
Sanskarzz wants to merge 4 commits intostacklok:mainfrom
Sanskarzz:addports

Conversation

@Sanskarzz
Copy link
Contributor

Fix: #3812

Summary

This PR adds support for the --publish / -p flag to the thv run command, enabling users to expose arbitrary container ports to the host, similar to docker run -p. It also fixes a bug in the Docker runtime client where explicitly requested host ports were being overwritten by random ports.

Key Changes

  • Added --publish flag to thv run.
  • Implemented networking.ParsePortSpec for robust port specification parsing.
  • Updated runtime.Setup to handle multiple port bindings efficiently.
  • Fixed pkg/container/docker/client.go to respect existing HostPort assignments in generatePortBindings.
  • Added unit tests for port parsing logic.

Signed-off-by: Sanskarzz <sanskar.gur@gmail.com>
@github-actions github-actions bot added the size/S Small PR: 100-299 lines changed label Feb 19, 2026
Signed-off-by: Sanskarzz <sanskar.gur@gmail.com>
@github-actions github-actions bot added size/S Small PR: 100-299 lines changed and removed size/S Small PR: 100-299 lines changed labels Feb 19, 2026
@codecov
Copy link

codecov bot commented Feb 19, 2026

Codecov Report

❌ Patch coverage is 44.44444% with 30 lines in your changes missing coverage. Please review.
✅ Project coverage is 66.76%. Comparing base (821b7c6) to head (45115fd).
⚠️ Report is 58 commits behind head on main.

Files with missing lines Patch % Lines
pkg/runtime/setup.go 0.00% 15 Missing ⚠️
pkg/networking/port.go 71.42% 3 Missing and 3 partials ⚠️
pkg/container/docker/client.go 61.53% 2 Missing and 3 partials ⚠️
pkg/runner/config_builder.go 0.00% 4 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3892      +/-   ##
==========================================
- Coverage   66.80%   66.76%   -0.04%     
==========================================
  Files         444      444              
  Lines       44503    44550      +47     
==========================================
+ Hits        29730    29744      +14     
- Misses      12445    12474      +29     
- Partials     2328     2332       +4     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@github-actions github-actions bot added size/S Small PR: 100-299 lines changed and removed size/S Small PR: 100-299 lines changed labels Feb 19, 2026
Signed-off-by: Sanskarzz <sanskar.gur@gmail.com>
@github-actions github-actions bot added size/S Small PR: 100-299 lines changed and removed size/S Small PR: 100-299 lines changed labels Feb 19, 2026
Copy link
Contributor

@jerm-dro jerm-dro left a comment

Choose a reason for hiding this comment

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

Mostly LGTM to me. Can you manually verify this fixes the user's reported issue by running this locally? A series of screenshots or video will do.

Comment on lines +131 to +153
if tt.wantError {
if err == nil {
t.Errorf("ParsePortSpec(%s) expected error but got nil", tt.portSpec)
}
return
}

if err != nil {
t.Errorf("ParsePortSpec(%s) unexpected error: %v", tt.portSpec, err)
return
}

if tt.expectedHostPort != "" && hostPort != tt.expectedHostPort {
t.Errorf("ParsePortSpec(%s) hostPort = %s, want %s", tt.portSpec, hostPort, tt.expectedHostPort)
}

if tt.expectedHostPort == "" && hostPort == "" {
t.Errorf("ParsePortSpec(%s) hostPort is empty, want random port", tt.portSpec)
}

if containerPort != tt.expectedContainer {
t.Errorf("ParsePortSpec(%s) containerPort = %d, want %d", tt.portSpec, containerPort, tt.expectedContainer)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: can you rewrite these assertions to use the require package (e.g.require.Equal or require.True)?

This will make the tests less nested and easier to read.

Comment on lines +1640 to +1654
hostPortStr := bindings[0].HostPort
if hostPortStr == "" || hostPortStr == "0" {
hostPort = networking.FindAvailable()
if hostPort == 0 {
return nil, 0, fmt.Errorf("could not find an available port")
}
bindings[0].HostPort = fmt.Sprintf("%d", hostPort)
portBindings[key] = bindings
} else {
var err error
hostPort, err = strconv.Atoi(hostPortStr)
if err != nil {
return nil, 0, fmt.Errorf("failed to convert host port %s to int: %w", hostPortStr, err)
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this the fix for:

It also fixes a bug in the Docker runtime client where explicitly requested host ports were being overwritten by random ports.

?

If so, can you find a way to add a regression test and some unit tests here? The generatePortBindings function seems like it should be amenable to unit testing without any refactoring.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/S Small PR: 100-299 lines changed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support publishing additional container ports in thv run

2 participants