Skip to content

Commit 166b487

Browse files
authored
feat: Split ProxyRunner Capability into Separate Binary for ToolHive on Kubernetes (#1057)
Signed-off-by: ChrisJBurns <[email protected]>
1 parent d88e8fc commit 166b487

File tree

8 files changed

+456
-3
lines changed

8 files changed

+456
-3
lines changed

.github/ko-ci.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,15 @@ builds:
1010

1111
- id: thv-operator
1212
dir: ./cmd/thv-operator
13+
ldflags:
14+
- -s -w
15+
- -X github.com/stacklok/toolhive/pkg/versions.Version={{.Env.VERSION}}
16+
- -X github.com/stacklok/toolhive/pkg/versions.Commit={{.Env.COMMIT}}
17+
- -X github.com/stacklok/toolhive/pkg/versions.BuildDate={{.Env.BUILD_DATE}}
18+
- -X github.com/stacklok/toolhive/pkg/versions.BuildType=release
19+
20+
- id: thv-proxyrunner
21+
dir: ./cmd/thv-proxyrunner
1322
ldflags:
1423
- -s -w
1524
- -X github.com/stacklok/toolhive/pkg/versions.Version={{.Env.VERSION}}

.github/workflows/image-build-and-publish.yml

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,3 +243,82 @@ jobs:
243243
if [[ "${{ github.ref }}" == refs/tags/* ]]; then
244244
cosign sign -y $BASE_REPO:latest
245245
fi
246+
247+
proxyrunner-image-build-and-publish:
248+
runs-on: ubuntu-latest
249+
permissions:
250+
contents: write
251+
packages: write
252+
id-token: write
253+
254+
env:
255+
BASE_REPO: "ghcr.io/stacklok/toolhive/proxyrunner"
256+
257+
steps:
258+
- name: Checkout repository
259+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
260+
261+
- name: Set up Go
262+
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5
263+
with:
264+
go-version-file: go.mod
265+
266+
- name: Compute version number
267+
id: version-string
268+
run: |
269+
if [[ "${{ github.ref }}" == "refs/heads/main" ]]; then
270+
# For main branch, use semver with -dev suffix
271+
echo "tag=0.0.1-dev.$GITHUB_RUN_NUMBER+$(git rev-parse --short HEAD)" >> "$GITHUB_OUTPUT"
272+
elif [[ "${{ github.ref }}" == refs/tags/* ]]; then
273+
# For tags, use the tag as is (assuming it's semver)
274+
TAG="${{ github.ref_name }}"
275+
echo "tag=$TAG" >> "$GITHUB_OUTPUT"
276+
else
277+
# For other branches, use branch name and run number
278+
BRANCH="${{ github.ref_name }}"
279+
echo "tag=0.0.1-$BRANCH.$GITHUB_RUN_NUMBER+$(git rev-parse --short HEAD)" >> "$GITHUB_OUTPUT"
280+
fi
281+
282+
- name: Login to GitHub Container Registry
283+
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0
284+
with:
285+
registry: ghcr.io
286+
username: ${{ github.actor }}
287+
password: ${{ secrets.GITHUB_TOKEN }}
288+
289+
- name: Setup ko
290+
uses: ko-build/setup-ko@d006021bd0c28d1ce33a07e7943d48b079944c8d # v0.9
291+
292+
- name: Install Cosign
293+
uses: sigstore/cosign-installer@398d4b0eeef1380460a10c8013a76f728fb906ac # v3.9.1
294+
295+
- name: Build and Push Image to GHCR
296+
env:
297+
VERSION: ${{ steps.version-string.outputs.tag }}
298+
COMMIT: ${{ github.sha }}
299+
BUILD_DATE: ${{ github.event.head_commit.timestamp }}
300+
KO_CONFIG_PATH: ${{ github.workspace }}/.github/ko-ci.yml
301+
run: |
302+
TAG=$(echo "${{ steps.version-string.outputs.tag }}" | sed 's/+/_/g')
303+
TAGS="-t $TAG"
304+
305+
# Add latest tag only if building from a tag
306+
if [[ "${{ github.ref }}" == refs/tags/* ]]; then
307+
TAGS="$TAGS -t latest"
308+
fi
309+
310+
KO_DOCKER_REPO=$BASE_REPO ko build --platform=linux/amd64,linux/arm64 --bare $TAGS ./cmd/thv-proxyrunner \
311+
--image-label=org.opencontainers.image.source=https://github.com/stacklok/toolhive,org.opencontainers.image.title="toolhive-proxyrunner",org.opencontainers.image.vendor=Stacklok
312+
313+
- name: Sign Image with Cosign
314+
# This step uses the identity token to provision an ephemeral certificate
315+
# against the sigstore community Fulcio instance.
316+
run: |
317+
TAG=$(echo "${{ steps.version-string.outputs.tag }}" | sed 's/+/_/g')
318+
# Sign the ko image
319+
cosign sign -y $BASE_REPO:$TAG
320+
321+
# Sign the latest tag if building from a tag
322+
if [[ "${{ github.ref }}" == refs/tags/* ]]; then
323+
cosign sign -y $BASE_REPO:latest
324+
fi

Taskfile.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ tasks:
7373
- mkdir -p bin
7474
- go build -ldflags "-s -w -X github.com/stacklok/toolhive/pkg/versions.Version={{.VERSION}} -X github.com/stacklok/toolhive/pkg/versions.Commit={{.COMMIT}} -X github.com/stacklok/toolhive/pkg/versions.BuildDate={{.BUILD_DATE}}" -o bin/thv ./cmd/thv
7575

76+
7677
install:
7778
desc: Install the thv binary to GOPATH/bin
7879
vars:

cmd/thv-operator/Taskfile.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ tasks:
9999
OPERATOR_IMAGE:
100100
sh: KO_DOCKER_REPO=kind.local ko build --local -B ./cmd/thv-operator | tail -n 1
101101
TOOLHIVE_IMAGE:
102-
sh: KO_DOCKER_REPO=kind.local ko build --local -B ./cmd/thv | tail -n 1
102+
sh: KO_DOCKER_REPO=kind.local ko build --local -B ./cmd/thv-proxyrunner | tail -n 1
103103
cmds:
104104
- echo "Loading toolhive operator image {{.OPERATOR_IMAGE}} into kind..."
105105
- kind load docker-image --name toolhive {{.OPERATOR_IMAGE}}

cmd/thv-proxyrunner/app/commands.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// Package app provides the entry point for the toolhive command-line application.
2+
package app
3+
4+
import (
5+
"github.com/spf13/cobra"
6+
"github.com/spf13/viper"
7+
8+
"github.com/stacklok/toolhive/pkg/logger"
9+
)
10+
11+
var rootCmd = &cobra.Command{
12+
Use: "thv-proxyrunner",
13+
DisableAutoGenTag: true,
14+
Short: "ToolHive (thv) is a lightweight, secure, and fast manager for MCP servers",
15+
Long: `ToolHive (thv) is a lightweight, secure, and fast manager for MCP (Model Context Protocol) servers.
16+
It is written in Go and has extensive test coverage—including input validation—to ensure reliability and security.`,
17+
Run: func(cmd *cobra.Command, _ []string) {
18+
// If no subcommand is provided, print help
19+
if err := cmd.Help(); err != nil {
20+
logger.Errorf("Error displaying help: %v", err)
21+
}
22+
},
23+
PersistentPreRun: func(_ *cobra.Command, _ []string) {
24+
logger.Initialize()
25+
},
26+
}
27+
28+
// NewRootCmd creates a new root command for the ToolHive CLI.
29+
func NewRootCmd() *cobra.Command {
30+
// Add persistent flags
31+
rootCmd.PersistentFlags().Bool("debug", false, "Enable debug mode")
32+
err := viper.BindPFlag("debug", rootCmd.PersistentFlags().Lookup("debug"))
33+
if err != nil {
34+
logger.Errorf("Error binding debug flag: %v", err)
35+
}
36+
37+
// Add subcommands
38+
rootCmd.AddCommand(runCmd)
39+
40+
return rootCmd
41+
}

0 commit comments

Comments
 (0)