Skip to content

Commit 8d92de2

Browse files
committed
feat: add fixed basepath /helm-dashboard
1 parent 3ffdbba commit 8d92de2

File tree

12 files changed

+1075
-1698
lines changed

12 files changed

+1075
-1698
lines changed

.github/workflows/release.yaml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,17 @@ jobs:
9898
build-args: VER=${{ needs.pre_release.outputs.release_tag }}
9999
platforms: linux/amd64,linux/arm64
100100

101+
- name: Build and push with base path
102+
uses: docker/build-push-action@v4
103+
if: github.event_name != 'pull_request'
104+
with:
105+
context: .
106+
push: ${{ github.event_name != 'pull_request' }}
107+
tags: komodorio/helm-dashboard:${{ needs.pre_release.outputs.release_tag }}-basepath,komodorio/helm-dashboard:latest-basepath
108+
labels: ${{ steps.meta.outputs.labels }}
109+
build-args: VER=${{ needs.pre_release.outputs.release_tag }},VITE_BASE_PATH=/helm-dashboard
110+
platforms: linux/amd64,linux/arm64
111+
101112
publish_chart:
102113
runs-on: ubuntu-latest
103114
needs: [ image, pre_release ]

Dockerfile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ FROM node:latest as frontend
44
WORKDIR /build
55

66
COPY frontend ./
7+
ARG VITE_BASE_PATH
78

89
RUN npm i && npm run build
910

@@ -49,4 +50,4 @@ COPY --from=builder /build/src/bin/dashboard /bin/helm-dashboard
4950

5051
ENTRYPOINT ["/bin/helm-dashboard", "--no-browser", "--bind=0.0.0.0", "--port=8080"]
5152

52-
# docker build . -t komodorio/helm-dashboard:0.0.0 && kind load docker-image komodorio/helm-dashboard:0.0.0
53+
# docker build . -t komodorio/helm-dashboard:0.0.0 && kind load docker-image komodorio/helm-dashboard:0.0.0

Makefile

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,18 @@ pull: ; $(info $(M) Pulling source...) @
1414
@git pull
1515

1616
.PHONY: build_go
17-
build_go: $(BIN) ; $(info $(M) Building GO...) @ ## Build program binary
17+
build_go: $(BIN) ; $(info $(M) Building GO...) @ ## Build program binary
1818
go build \
1919
-ldflags '-X main.version=$(VERSION) -X main.buildDate=$(DATE)' \
20-
-o bin/dashboard .
20+
-o bin/dashboard . ;
2121

2222
.PHONY: build_ui
2323
build_ui: $(BIN) ; $(info $(M) Building UI...) @ ## Build program binary
24-
cd frontend && npm i && npm run build && cd ..
24+
cd frontend && npm i && npm run build && cd .. ;
2525

2626
.PHONY: build
2727
build: build_ui build_go ; $(info $(M) Building executable...) @ ## Build program binary
2828

2929
.PHONY: debug
3030
debug: ; $(info $(M) Running dashboard in debug mode...) @
31-
@DEBUG=1 ./bin/dashboard
31+
@DEBUG=1 ./bin/dashboard

charts/helm-dashboard/templates/_helpers.tpl

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ Return the proper image name
6464
{{- define "helm-dashboard.image" -}}
6565
{{- $image := .Values.image -}}
6666
{{- $tag := default .Chart.AppVersion $image.tag -}}
67+
{{- if .Values.image.basePath }}
68+
{{- $tag = printf "%s%s" $tag "-basepath" -}}
69+
{{- end -}}
6770
{{- $_ := set $image "tag" $tag -}}
6871
{{ include "common.images.image" (dict "imageRoot" $_ "global" .Values.global) }}
6972
{{- end -}}
@@ -73,4 +76,4 @@ Return the proper image name
7376
*/}}
7477
{{- define "test.image" -}}
7578
{{ include "common.images.image" (dict "imageRoot" .Values.testImage "global" .Values.global) }}
76-
{{- end -}}
79+
{{- end -}}

charts/helm-dashboard/templates/deployment.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@ spec:
4646
value: /opt/dashboard/helm/data
4747
- name: DEBUG
4848
value: {{- ternary " '1'" "" .Values.debug }}
49+
{{- if .Values.image.basePath }}
50+
- name: HD_BASE_PATH
51+
value: /helm-dashboard
52+
{{end}}
4953
{{- if .Values.dashboard.namespace }}
5054
- name: HELM_NAMESPACE
5155
value: {{ .Values.dashboard.namespace }}

charts/helm-dashboard/values.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ image:
2020
# Specifies the exact image digest to pull.
2121
digest: ""
2222
imagePullSecrets: []
23+
# Flag for using an image with fixed base path /helm-dashboard
24+
basePath: false
2325

2426
nameOverride: ""
2527
fullnameOverride: ""

frontend/src/API/apiService.ts

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,18 @@ interface ClustersResponse {
1616
}
1717
class ApiService {
1818
currentCluster = "";
19-
constructor(protected readonly isMockMode: boolean = false) {}
19+
private readonly basePath: string;
20+
constructor(protected readonly isMockMode: boolean = false) {
21+
const fromEnv = (import.meta as any).env?.VITE_BASE_PATH as string | undefined;
22+
// In production, Vite injects import.meta.env.BASE_URL. Prefer explicit VITE_BASE_PATH if provided.
23+
const viteBase = (import.meta as any).env?.BASE_URL as string | undefined;
24+
const computed = (fromEnv ?? viteBase ?? "/").trim();
25+
// Normalize to leading slash, no trailing slash (except root)
26+
let normalized = computed;
27+
if (!normalized.startsWith("/")) normalized = "/" + normalized;
28+
if (normalized !== "/") normalized = normalized.replace(/\/+$/g, "");
29+
this.basePath = normalized;
30+
}
2031

2132
setCluster = (cluster: string) => {
2233
this.currentCluster = cluster;
@@ -28,14 +39,20 @@ class ApiService {
2839
): Promise<T> {
2940
let response;
3041

42+
const isAbsolute = /^https?:\/\//.test(url);
43+
const fullUrl = isAbsolute
44+
? url
45+
: this.basePath === "/"
46+
? url
47+
: `${this.basePath}${url.startsWith("/") ? url : `/${url}`}`;
3148
if (this.currentCluster) {
3249
const headers = new Headers(options?.headers);
3350
if (!headers.has("X-Kubecontext")) {
3451
headers.set("X-Kubecontext", this.currentCluster);
3552
}
36-
response = await fetch(url, { ...options, headers });
53+
response = await fetch(fullUrl, { ...options, headers });
3754
} else {
38-
response = await fetch(url, options);
55+
response = await fetch(fullUrl, options);
3956
}
4057

4158
if (!response.ok) {
@@ -55,7 +72,7 @@ class ApiService {
5572
}
5673

5774
getToolVersion = async () => {
58-
const response = await fetch("/status");
75+
const response = await this.fetchWithDefaults("/status");
5976
const data = await response.json();
6077
return data;
6178
};
@@ -73,8 +90,9 @@ class ApiService {
7390
};
7491

7592
getClusters = async () => {
76-
const response = await fetch("/api/k8s/contexts");
77-
const data = (await response.json()) as ClustersResponse[];
93+
const data = await this.fetchWithDefaults<ClustersResponse[]>(
94+
"/api/k8s/contexts"
95+
);
7896
return data;
7997
};
8098

frontend/vite.config.ts

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ export default defineConfig(({ mode }) => {
66
const env = loadEnv(mode, process.cwd(), "");
77
const port = env.VITE_SERVER_PORT || 8080;
88
return {
9+
base: env.VITE_BASE_PATH || "/",
910
plugins: [
1011
react(),
1112
viteStaticCopy({
@@ -31,12 +32,25 @@ export default defineConfig(({ mode }) => {
3132
emptyOutDir: true,
3233
},
3334
server: {
34-
proxy: {
35-
"^/api/.*": `http://127.0.0.1:${port}`,
36-
"^/status*": `http://127.0.0.1:${port}`,
37-
"^/diff*": `http://127.0.0.1:${port}`,
38-
"^/static*": `http://127.0.0.1:${port}`,
39-
},
35+
proxy: (() => {
36+
const base = (env.VITE_BASE_PATH || "/").replace(/\/$/, "");
37+
const target = `http://127.0.0.1:${port}`;
38+
// Support both with and without base for local dev convenience
39+
return {
40+
"^/api/.*": target,
41+
"^/status*": target,
42+
"^/diff*": target,
43+
"^/static*": target,
44+
...(base
45+
? {
46+
[`^${base}/api/.*`]: target,
47+
[`^${base}/status*`]: target,
48+
[`^${base}/diff*`]: target,
49+
[`^${base}/static*`]: target,
50+
}
51+
: {}),
52+
} as Record<string, string>;
53+
})(),
4054
},
4155
};
4256
});

0 commit comments

Comments
 (0)