From 827f5e77527530ff4d9e1e9ce1927af6e87372a6 Mon Sep 17 00:00:00 2001 From: MergeCheck Date: Fri, 3 Jul 2026 15:36:43 -0300 Subject: [PATCH 1/3] fix(github-mcp-server): align template standards --- charts/github-mcp-server/README.md | 3 ++ charts/github-mcp-server/templates/NOTES.txt | 45 ++++++++++++++----- .../github-mcp-server/templates/_helpers.tpl | 16 +++++++ .../templates/deployment.yaml | 2 +- .../github-mcp-server/templates/ingress.yaml | 4 +- .../templates/networkpolicy.yaml | 8 ++++ .../github-mcp-server/templates/validate.yaml | 9 +--- .../tests/networkpolicy_test.yaml | 20 +++++++++ .../tests/templates_test.yaml | 13 ++++++ .../tests/validation_test.yaml | 7 +++ charts/github-mcp-server/values.schema.json | 7 ++- charts/github-mcp-server/values.yaml | 2 + 12 files changed, 116 insertions(+), 20 deletions(-) diff --git a/charts/github-mcp-server/README.md b/charts/github-mcp-server/README.md index 57002f6f1..5f45203f6 100644 --- a/charts/github-mcp-server/README.md +++ b/charts/github-mcp-server/README.md @@ -15,6 +15,9 @@ The default deployment starts the server in HTTP mode on port `8082`, read-only The chart is stateless by default. If persistence is enabled and the Deployment is scaled above one replica, use `ReadWriteMany` storage or disable persistence to avoid sharing one `ReadWriteOnce` PVC across pods. +Ingress class rendering is optional. Set `ingress.ingressClassName: ""` to omit `spec.ingressClassName`. +When `networkPolicy.enabled=true`, use `networkPolicy.extraEgress` for DNS, proxy, or API-server egress allowances. + ## Token Configuration Use a Kubernetes Secret for production: diff --git a/charts/github-mcp-server/templates/NOTES.txt b/charts/github-mcp-server/templates/NOTES.txt index f7a1047e5..d84d1dad2 100644 --- a/charts/github-mcp-server/templates/NOTES.txt +++ b/charts/github-mcp-server/templates/NOTES.txt @@ -1,13 +1,16 @@ {{/* SPDX-License-Identifier: Apache-2.0 */}} -GitHub MCP Server has been deployed. +1. Release -Access: +GitHub MCP Server has been deployed as release {{ .Release.Name }} in namespace {{ .Release.Namespace }}. -- Service: http://{{ include "github-mcp-server.fullname" . }}.{{ .Release.Namespace }}.svc:{{ .Values.service.port }} -- Port-forward: kubectl port-forward svc/{{ include "github-mcp-server.fullname" . }} 8082:{{ .Values.service.port }} -n {{ .Release.Namespace }} +2. Access + +- Service DNS: http://{{ include "github-mcp-server.fullname" . }}.{{ .Release.Namespace }}.svc:{{ .Values.service.port }} +- Port-forward: + kubectl port-forward svc/{{ include "github-mcp-server.fullname" . }} 8082:{{ .Values.service.port }} -n {{ .Release.Namespace }} - Local MCP URL: http://127.0.0.1:8082 -GitHub runtime: +3. GitHub Runtime - Read-only mode: {{ .Values.github.readOnly }} - Toolsets: {{ .Values.github.toolsets }} @@ -23,18 +26,40 @@ GitHub runtime: - No GitHub token is configured; set github.existingSecret for production. {{- end }} -Security: +4. Security - Keep this service internal or protect Ingress/Gateway with external authentication. - Keep github.readOnly=true unless write tools are explicitly required. - Restrict token scopes to the enabled toolsets. +- Enable networkPolicy.enabled and set networkPolicy.ingressFrom for restricted clients. + +5. Scaling + +- Current replicas: {{ .Values.replicaCount }} +- If persistence.enabled=true and replicaCount > 1, persistence.accessModes must include ReadWriteMany. +- Prefer stateless replicas with persistence.enabled=false for horizontal scaling. + +6. Networking + +{{- if .Values.ingress.enabled }} +- Ingress is enabled. +{{- else }} +- Ingress is disabled. +{{- end }} +{{- if .Values.gateway.enabled }} +- Gateway API HTTPRoute is enabled. +{{- else }} +- Gateway API HTTPRoute is disabled. +{{- end }} -Troubleshooting: +7. Troubleshooting -- kubectl get pod -l app.kubernetes.io/instance={{ .Release.Name }} -n {{ .Release.Namespace }} -- kubectl logs deploy/{{ include "github-mcp-server.fullname" . }} -n {{ .Release.Namespace }} +- Pods: + kubectl get pod -l app.kubernetes.io/instance={{ .Release.Name }} -n {{ .Release.Namespace }} +- Logs: + kubectl logs deploy/{{ include "github-mcp-server.fullname" . }} -n {{ .Release.Namespace }} -Resources: +8. Resources - Chart documentation: https://helmforge.dev/docs/charts/github-mcp-server - Upstream: https://github.com/github/github-mcp-server diff --git a/charts/github-mcp-server/templates/_helpers.tpl b/charts/github-mcp-server/templates/_helpers.tpl index f5073c9ee..507bea129 100644 --- a/charts/github-mcp-server/templates/_helpers.tpl +++ b/charts/github-mcp-server/templates/_helpers.tpl @@ -26,3 +26,19 @@ app.kubernetes.io/part-of: helmforge {{- end -}} {{- end -}} {{- end -}} + +{{- define "github-mcp-server.validate" -}} +{{- if and .Values.github.requireToken (not (or .Values.github.personalAccessToken .Values.github.existingSecret)) -}} +{{- fail "github.requireToken=true requires github.personalAccessToken or github.existingSecret" -}} +{{- end -}} +{{- if and (gt (int .Values.replicaCount) 1) .Values.persistence.enabled (not (has "ReadWriteMany" .Values.persistence.accessModes)) -}} +{{- fail "replicaCount > 1 with persistence.enabled requires persistence.accessModes to include ReadWriteMany or persistence.enabled=false" -}} +{{- end -}} +{{- $podLabels := .Values.podLabels | default dict -}} +{{- if hasKey $podLabels "app.kubernetes.io/name" -}} +{{- fail "podLabels must not override the selector label app.kubernetes.io/name" -}} +{{- end -}} +{{- if hasKey $podLabels "app.kubernetes.io/instance" -}} +{{- fail "podLabels must not override the selector label app.kubernetes.io/instance" -}} +{{- end -}} +{{- end -}} diff --git a/charts/github-mcp-server/templates/deployment.yaml b/charts/github-mcp-server/templates/deployment.yaml index 4bc814cfd..a29cd372e 100644 --- a/charts/github-mcp-server/templates/deployment.yaml +++ b/charts/github-mcp-server/templates/deployment.yaml @@ -13,7 +13,7 @@ spec: template: metadata: labels: - {{- include "github-mcp-server.labels" . | nindent 8 }} + {{- include "github-mcp-server.selectorLabels" . | nindent 8 }} {{- with .Values.podLabels }} {{- toYaml . | nindent 8 }} {{- end }} diff --git a/charts/github-mcp-server/templates/ingress.yaml b/charts/github-mcp-server/templates/ingress.yaml index 9eaf45872..53aeaf4c5 100644 --- a/charts/github-mcp-server/templates/ingress.yaml +++ b/charts/github-mcp-server/templates/ingress.yaml @@ -11,7 +11,9 @@ metadata: {{- toYaml . | nindent 4 }} {{- end }} spec: - ingressClassName: {{ .Values.ingress.ingressClassName | quote }} + {{- with .Values.ingress.ingressClassName }} + ingressClassName: {{ . | quote }} + {{- end }} {{- with .Values.ingress.tls }} tls: {{- toYaml . | nindent 4 }} diff --git a/charts/github-mcp-server/templates/networkpolicy.yaml b/charts/github-mcp-server/templates/networkpolicy.yaml index 75799c2ea..0037b8469 100644 --- a/charts/github-mcp-server/templates/networkpolicy.yaml +++ b/charts/github-mcp-server/templates/networkpolicy.yaml @@ -1,5 +1,6 @@ {{/* SPDX-License-Identifier: Apache-2.0 */}} {{- if .Values.networkPolicy.enabled }} +{{- $egressRules := .Values.networkPolicy.extraEgress | default list }} apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: @@ -12,6 +13,9 @@ spec: {{- include "github-mcp-server.selectorLabels" . | nindent 6 }} policyTypes: - Ingress + {{- if $egressRules }} + - Egress + {{- end }} ingress: - from: {{- if .Values.networkPolicy.ingressFrom }} @@ -22,4 +26,8 @@ spec: ports: - protocol: TCP port: http + {{- with $egressRules }} + egress: + {{- toYaml . | nindent 4 }} + {{- end }} {{- end }} diff --git a/charts/github-mcp-server/templates/validate.yaml b/charts/github-mcp-server/templates/validate.yaml index e23c4c5b5..e4c99e46a 100644 --- a/charts/github-mcp-server/templates/validate.yaml +++ b/charts/github-mcp-server/templates/validate.yaml @@ -1,7 +1,2 @@ -{{/* SPDX-License-Identifier: Apache-2.0 */}} -{{- if and .Values.github.requireToken (not (or .Values.github.personalAccessToken .Values.github.existingSecret)) -}} -{{- fail "github.requireToken=true requires github.personalAccessToken or github.existingSecret" -}} -{{- end -}} -{{- if and (gt (int .Values.replicaCount) 1) .Values.persistence.enabled (not (has "ReadWriteMany" .Values.persistence.accessModes)) -}} -{{- fail "replicaCount > 1 with persistence.enabled requires persistence.accessModes to include ReadWriteMany or persistence.enabled=false" -}} -{{- end -}} +# SPDX-License-Identifier: Apache-2.0 +{{- include "github-mcp-server.validate" . -}} diff --git a/charts/github-mcp-server/tests/networkpolicy_test.yaml b/charts/github-mcp-server/tests/networkpolicy_test.yaml index 7ee096186..30b7f650c 100644 --- a/charts/github-mcp-server/tests/networkpolicy_test.yaml +++ b/charts/github-mcp-server/tests/networkpolicy_test.yaml @@ -14,3 +14,23 @@ tests: content: protocol: TCP port: http + + - it: appends extra egress rules + set: + networkPolicy: + enabled: true + extraEgress: + - to: + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: kube-system + ports: + - protocol: UDP + port: 53 + asserts: + - contains: + path: spec.policyTypes + content: Egress + - equal: + path: spec.egress[0].ports[0].port + value: 53 diff --git a/charts/github-mcp-server/tests/templates_test.yaml b/charts/github-mcp-server/tests/templates_test.yaml index a333a3c34..3a3cbecf5 100644 --- a/charts/github-mcp-server/tests/templates_test.yaml +++ b/charts/github-mcp-server/tests/templates_test.yaml @@ -41,6 +41,19 @@ tests: - equal: path: metadata.annotations["cert-manager.io/cluster-issuer"] value: letsencrypt + - it: omits ingressClassName when empty + template: templates/ingress.yaml + set: + ingress.enabled: true + ingress.ingressClassName: "" + ingress.hosts: + - host: github-mcp-server.example.com + paths: + - path: / + pathType: Prefix + asserts: + - notExists: + path: spec.ingressClassName - it: renders HTTPRoute hostnames template: templates/httproute.yaml set: diff --git a/charts/github-mcp-server/tests/validation_test.yaml b/charts/github-mcp-server/tests/validation_test.yaml index a107fed95..8d4cdb1d4 100644 --- a/charts/github-mcp-server/tests/validation_test.yaml +++ b/charts/github-mcp-server/tests/validation_test.yaml @@ -17,3 +17,10 @@ tests: asserts: - failedTemplate: errorMessage: "replicaCount > 1 with persistence.enabled requires persistence.accessModes to include ReadWriteMany or persistence.enabled=false" + - it: fails when podLabels override selector labels + set: + podLabels: + app.kubernetes.io/name: custom + asserts: + - failedTemplate: + errorMessage: "podLabels must not override the selector label app.kubernetes.io/name" diff --git a/charts/github-mcp-server/values.schema.json b/charts/github-mcp-server/values.schema.json index df74af3ca..38dcdb243 100644 --- a/charts/github-mcp-server/values.schema.json +++ b/charts/github-mcp-server/values.schema.json @@ -60,7 +60,12 @@ "type": "object", "properties": { "enabled": { "type": "boolean", "default": false }, - "ingressFrom": { "type": "array", "items": { "type": "object" } } + "ingressFrom": { "type": "array", "items": { "type": "object" } }, + "extraEgress": { + "type": "array", + "description": "Additional egress rules appended to the NetworkPolicy", + "items": { "type": "object" } + } } }, "probes": { "$ref": "#/definitions/probes" }, diff --git a/charts/github-mcp-server/values.yaml b/charts/github-mcp-server/values.yaml index 265831956..fd8124355 100644 --- a/charts/github-mcp-server/values.yaml +++ b/charts/github-mcp-server/values.yaml @@ -101,6 +101,8 @@ networkPolicy: enabled: false # -- Ingress peers allowed to reach the MCP server. Empty allows all namespaces when policy is enabled. ingressFrom: [] + # -- Additional egress rules appended to the NetworkPolicy. + extraEgress: [] probes: startup: { enabled: true, initialDelaySeconds: 5, periodSeconds: 10, timeoutSeconds: 3, failureThreshold: 60 } From 0212a0762540259f609f033e2a522bb9ccd51bf3 Mon Sep 17 00:00:00 2001 From: MergeCheck Date: Fri, 3 Jul 2026 15:53:45 -0300 Subject: [PATCH 2/3] fix(github-mcp-server): address review feedback --- charts/github-mcp-server/README.md | 3 ++- .../github-mcp-server/templates/_helpers.tpl | 2 +- .../templates/networkpolicy.yaml | 23 ++++++++++++++++--- .../tests/networkpolicy_test.yaml | 6 +++++ .../tests/validation_test.yaml | 8 +++++++ charts/github-mcp-server/values.schema.json | 2 +- charts/github-mcp-server/values.yaml | 2 +- 7 files changed, 39 insertions(+), 7 deletions(-) diff --git a/charts/github-mcp-server/README.md b/charts/github-mcp-server/README.md index 5f45203f6..eb786cb85 100644 --- a/charts/github-mcp-server/README.md +++ b/charts/github-mcp-server/README.md @@ -16,7 +16,8 @@ The chart is stateless by default. If persistence is enabled and the Deployment is scaled above one replica, use `ReadWriteMany` storage or disable persistence to avoid sharing one `ReadWriteOnce` PVC across pods. Ingress class rendering is optional. Set `ingress.ingressClassName: ""` to omit `spec.ingressClassName`. -When `networkPolicy.enabled=true`, use `networkPolicy.extraEgress` for DNS, proxy, or API-server egress allowances. +When `networkPolicy.enabled=true`, ingress is restricted to the configured peers. +Setting `networkPolicy.extraEgress` also enables egress isolation with built-in DNS and HTTPS allowances, then appends the supplied proxy or API-server rules. ## Token Configuration diff --git a/charts/github-mcp-server/templates/_helpers.tpl b/charts/github-mcp-server/templates/_helpers.tpl index 507bea129..1d50b271a 100644 --- a/charts/github-mcp-server/templates/_helpers.tpl +++ b/charts/github-mcp-server/templates/_helpers.tpl @@ -31,7 +31,7 @@ app.kubernetes.io/part-of: helmforge {{- if and .Values.github.requireToken (not (or .Values.github.personalAccessToken .Values.github.existingSecret)) -}} {{- fail "github.requireToken=true requires github.personalAccessToken or github.existingSecret" -}} {{- end -}} -{{- if and (gt (int .Values.replicaCount) 1) .Values.persistence.enabled (not (has "ReadWriteMany" .Values.persistence.accessModes)) -}} +{{- if and (gt (int .Values.replicaCount) 1) .Values.persistence.enabled (not .Values.persistence.existingClaim) (not (has "ReadWriteMany" .Values.persistence.accessModes)) -}} {{- fail "replicaCount > 1 with persistence.enabled requires persistence.accessModes to include ReadWriteMany or persistence.enabled=false" -}} {{- end -}} {{- $podLabels := .Values.podLabels | default dict -}} diff --git a/charts/github-mcp-server/templates/networkpolicy.yaml b/charts/github-mcp-server/templates/networkpolicy.yaml index 0037b8469..42ff7f07c 100644 --- a/charts/github-mcp-server/templates/networkpolicy.yaml +++ b/charts/github-mcp-server/templates/networkpolicy.yaml @@ -1,6 +1,6 @@ {{/* SPDX-License-Identifier: Apache-2.0 */}} {{- if .Values.networkPolicy.enabled }} -{{- $egressRules := .Values.networkPolicy.extraEgress | default list }} +{{- $extraEgress := .Values.networkPolicy.extraEgress | default list }} apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: @@ -13,7 +13,7 @@ spec: {{- include "github-mcp-server.selectorLabels" . | nindent 6 }} policyTypes: - Ingress - {{- if $egressRules }} + {{- if $extraEgress }} - Egress {{- end }} ingress: @@ -26,8 +26,25 @@ spec: ports: - protocol: TCP port: http - {{- with $egressRules }} + {{- if $extraEgress }} egress: + - to: + - namespaceSelector: {} + ports: + - protocol: UDP + port: 53 + - protocol: TCP + port: 53 + - to: + - ipBlock: + cidr: 0.0.0.0/0 + - ipBlock: + cidr: ::/0 + ports: + - protocol: TCP + port: 443 + {{- with $extraEgress }} {{- toYaml . | nindent 4 }} + {{- end }} {{- end }} {{- end }} diff --git a/charts/github-mcp-server/tests/networkpolicy_test.yaml b/charts/github-mcp-server/tests/networkpolicy_test.yaml index 30b7f650c..d4bd12938 100644 --- a/charts/github-mcp-server/tests/networkpolicy_test.yaml +++ b/charts/github-mcp-server/tests/networkpolicy_test.yaml @@ -34,3 +34,9 @@ tests: - equal: path: spec.egress[0].ports[0].port value: 53 + - equal: + path: spec.egress[1].ports[0].port + value: 443 + - equal: + path: spec.egress[2].ports[0].port + value: 53 diff --git a/charts/github-mcp-server/tests/validation_test.yaml b/charts/github-mcp-server/tests/validation_test.yaml index 8d4cdb1d4..a068d171f 100644 --- a/charts/github-mcp-server/tests/validation_test.yaml +++ b/charts/github-mcp-server/tests/validation_test.yaml @@ -17,6 +17,14 @@ tests: asserts: - failedTemplate: errorMessage: "replicaCount > 1 with persistence.enabled requires persistence.accessModes to include ReadWriteMany or persistence.enabled=false" + - it: allows scaling with an existing persistence claim + set: + replicaCount: 2 + persistence.enabled: true + persistence.existingClaim: github-mcp-data-rwx + persistence.accessModes[0]: ReadWriteOnce + asserts: + - notFailedTemplate: {} - it: fails when podLabels override selector labels set: podLabels: diff --git a/charts/github-mcp-server/values.schema.json b/charts/github-mcp-server/values.schema.json index 38dcdb243..7ba4c0d07 100644 --- a/charts/github-mcp-server/values.schema.json +++ b/charts/github-mcp-server/values.schema.json @@ -63,7 +63,7 @@ "ingressFrom": { "type": "array", "items": { "type": "object" } }, "extraEgress": { "type": "array", - "description": "Additional egress rules appended to the NetworkPolicy", + "description": "Additional egress rules appended after the built-in DNS and HTTPS allowances", "items": { "type": "object" } } } diff --git a/charts/github-mcp-server/values.yaml b/charts/github-mcp-server/values.yaml index fd8124355..da0eb9f6e 100644 --- a/charts/github-mcp-server/values.yaml +++ b/charts/github-mcp-server/values.yaml @@ -101,7 +101,7 @@ networkPolicy: enabled: false # -- Ingress peers allowed to reach the MCP server. Empty allows all namespaces when policy is enabled. ingressFrom: [] - # -- Additional egress rules appended to the NetworkPolicy. + # -- Additional egress rules appended after the built-in DNS and HTTPS allowances. extraEgress: [] probes: From 203e221555b074b27d57ad43538d9a0ccd52ff81 Mon Sep 17 00:00:00 2001 From: MergeCheck Date: Sun, 5 Jul 2026 17:00:59 -0300 Subject: [PATCH 3/3] test(github-mcp-server): cover selector instance validation --- charts/github-mcp-server/templates/NOTES.txt | 1 + charts/github-mcp-server/templates/_helpers.tpl | 7 +++---- charts/github-mcp-server/tests/validation_test.yaml | 7 +++++++ 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/charts/github-mcp-server/templates/NOTES.txt b/charts/github-mcp-server/templates/NOTES.txt index d84d1dad2..e5f37d3e1 100644 --- a/charts/github-mcp-server/templates/NOTES.txt +++ b/charts/github-mcp-server/templates/NOTES.txt @@ -31,6 +31,7 @@ GitHub MCP Server has been deployed as release {{ .Release.Name }} in namespace - Keep this service internal or protect Ingress/Gateway with external authentication. - Keep github.readOnly=true unless write tools are explicitly required. - Restrict token scopes to the enabled toolsets. +- When NetworkPolicy is enabled, use networkPolicy.extraEgress for required private proxies or GitHub Enterprise endpoints. - Enable networkPolicy.enabled and set networkPolicy.ingressFrom for restricted clients. 5. Scaling diff --git a/charts/github-mcp-server/templates/_helpers.tpl b/charts/github-mcp-server/templates/_helpers.tpl index 1d50b271a..9b4dfb8b5 100644 --- a/charts/github-mcp-server/templates/_helpers.tpl +++ b/charts/github-mcp-server/templates/_helpers.tpl @@ -35,10 +35,9 @@ app.kubernetes.io/part-of: helmforge {{- fail "replicaCount > 1 with persistence.enabled requires persistence.accessModes to include ReadWriteMany or persistence.enabled=false" -}} {{- end -}} {{- $podLabels := .Values.podLabels | default dict -}} -{{- if hasKey $podLabels "app.kubernetes.io/name" -}} -{{- fail "podLabels must not override the selector label app.kubernetes.io/name" -}} +{{- range $key := (list "app.kubernetes.io/name" "app.kubernetes.io/instance") -}} +{{- if hasKey $podLabels $key -}} +{{- fail (printf "podLabels must not override the selector label %s" $key) -}} {{- end -}} -{{- if hasKey $podLabels "app.kubernetes.io/instance" -}} -{{- fail "podLabels must not override the selector label app.kubernetes.io/instance" -}} {{- end -}} {{- end -}} diff --git a/charts/github-mcp-server/tests/validation_test.yaml b/charts/github-mcp-server/tests/validation_test.yaml index a068d171f..1a76e4d17 100644 --- a/charts/github-mcp-server/tests/validation_test.yaml +++ b/charts/github-mcp-server/tests/validation_test.yaml @@ -17,6 +17,13 @@ tests: asserts: - failedTemplate: errorMessage: "replicaCount > 1 with persistence.enabled requires persistence.accessModes to include ReadWriteMany or persistence.enabled=false" + - it: fails when podLabels override selector instance + set: + podLabels: + app.kubernetes.io/instance: custom + asserts: + - failedTemplate: + errorMessage: "podLabels must not override the selector label app.kubernetes.io/instance" - it: allows scaling with an existing persistence claim set: replicaCount: 2