@crewhaus/helm-chart 0.5.0 → 0.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/embedded.d.ts +6 -0
- package/dist/embedded.js +54 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +21 -11
- package/helm/crewhaus/Chart.yaml +16 -0
- package/helm/crewhaus/templates/_helpers.tpl +21 -0
- package/helm/crewhaus/templates/deployment.yaml +119 -0
- package/helm/crewhaus/templates/ingress.yaml +41 -0
- package/helm/crewhaus/templates/otel-collector.yaml +32 -0
- package/helm/crewhaus/templates/service.yaml +18 -0
- package/helm/crewhaus/templates/servicemonitor.yaml +20 -0
- package/helm/crewhaus/values.yaml +136 -0
- package/package.json +4 -4
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Template filename → body. Insertion order is the sorted order
|
|
3
|
+
* `readdirSync().sort()` used to produce, so `templateFiles()` keeps returning
|
|
4
|
+
* the same sequence and rendered output stays byte-stable across this change.
|
|
5
|
+
*/
|
|
6
|
+
export declare const TEMPLATE_BODIES: Readonly<Record<string, string>>;
|
package/dist/embedded.js
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compile-time-embedded bodies of the chart's `helm/crewhaus/templates/*`
|
|
3
|
+
* files.
|
|
4
|
+
*
|
|
5
|
+
* The `with { type: "text" }` import attribute makes Bun inline each file's
|
|
6
|
+
* text: on the interpreter path (`bun`/`bunx`) it reads the file from disk at
|
|
7
|
+
* module load, and under `bun build --compile` it bakes the text into the
|
|
8
|
+
* standalone binary's `/$bunfs` image. Either way, no `readdirSync`/
|
|
9
|
+
* `readFileSync` of a package-relative path runs at render time.
|
|
10
|
+
*
|
|
11
|
+
* That runtime read is exactly what broke `crewhaus cloud deploy` on every
|
|
12
|
+
* PUBLISHED channel, in two different ways at once:
|
|
13
|
+
*
|
|
14
|
+
* - the compiled binary derived `TEMPLATES_DIR` from `import.meta.url`,
|
|
15
|
+
* which resolves under `/$bunfs` where the chart was never present, so
|
|
16
|
+
* rendering threw `templates directory missing at
|
|
17
|
+
* /$bunfs/helm/crewhaus/templates`;
|
|
18
|
+
* - the npm tarball omitted the directory outright, because this package's
|
|
19
|
+
* `files` array listed only `src`, so the same read failed against a real
|
|
20
|
+
* but absent `node_modules/@crewhaus/helm-chart/helm/`.
|
|
21
|
+
*
|
|
22
|
+
* Neither reproduced in CI, which runs from a source checkout where
|
|
23
|
+
* `packages/helm-chart/helm/` is on disk — the same blind spot that let the
|
|
24
|
+
* `default-skills` ENOENT ship in 0.3.0.
|
|
25
|
+
*
|
|
26
|
+
* The checked-in chart files stay the single source of truth; this module only
|
|
27
|
+
* re-exports their text keyed by filename, so there is no second copy to
|
|
28
|
+
* drift. `helm/` is now also in `files`, so a published consumer can still
|
|
29
|
+
* `helm install` the real chart from `chartRoot()` — that path is for humans
|
|
30
|
+
* and tooling, and is no longer what rendering depends on.
|
|
31
|
+
*/
|
|
32
|
+
import helpersTpl from "../helm/crewhaus/templates/_helpers.tpl" with { type: "text" };
|
|
33
|
+
import deploymentYaml from "../helm/crewhaus/templates/deployment.yaml" with { type: "text" };
|
|
34
|
+
import ingressYaml from "../helm/crewhaus/templates/ingress.yaml" with { type: "text" };
|
|
35
|
+
import otelCollectorYaml from "../helm/crewhaus/templates/otel-collector.yaml" with {
|
|
36
|
+
type: "text"
|
|
37
|
+
};
|
|
38
|
+
import serviceYaml from "../helm/crewhaus/templates/service.yaml" with { type: "text" };
|
|
39
|
+
import serviceMonitorYaml from "../helm/crewhaus/templates/servicemonitor.yaml" with {
|
|
40
|
+
type: "text"
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* Template filename → body. Insertion order is the sorted order
|
|
44
|
+
* `readdirSync().sort()` used to produce, so `templateFiles()` keeps returning
|
|
45
|
+
* the same sequence and rendered output stays byte-stable across this change.
|
|
46
|
+
*/
|
|
47
|
+
export const TEMPLATE_BODIES = {
|
|
48
|
+
"_helpers.tpl": helpersTpl,
|
|
49
|
+
"deployment.yaml": deploymentYaml,
|
|
50
|
+
"ingress.yaml": ingressYaml,
|
|
51
|
+
"otel-collector.yaml": otelCollectorYaml,
|
|
52
|
+
"service.yaml": serviceYaml,
|
|
53
|
+
"servicemonitor.yaml": serviceMonitorYaml,
|
|
54
|
+
};
|
package/dist/index.d.ts
CHANGED
|
@@ -24,7 +24,23 @@ export declare class HelmChartError extends CrewhausError {
|
|
|
24
24
|
readonly name = "HelmChartError";
|
|
25
25
|
constructor(message: string, cause?: unknown);
|
|
26
26
|
}
|
|
27
|
+
/**
|
|
28
|
+
* On-disk location of the chart, for humans and for tooling that wants to run
|
|
29
|
+
* `helm install … <chartRoot()>` directly. Present in a source checkout and in
|
|
30
|
+
* a published npm install (`helm/` is in this package's `files`), but NOT in
|
|
31
|
+
* the compiled binary, where the chart exists only as embedded text. Rendering
|
|
32
|
+
* never reads it — use {@link renderChart}.
|
|
33
|
+
*/
|
|
27
34
|
export declare function chartRoot(): string;
|
|
35
|
+
/**
|
|
36
|
+
* The chart's template filenames, in the same sorted order the old
|
|
37
|
+
* `readdirSync().sort()` produced.
|
|
38
|
+
*
|
|
39
|
+
* Served from {@link TEMPLATE_BODIES} rather than the filesystem: the previous
|
|
40
|
+
* package-relative read failed on BOTH published channels — under `/$bunfs` in
|
|
41
|
+
* the compiled binary, and against an absent `helm/` in the npm tarball. See
|
|
42
|
+
* `embedded.ts`.
|
|
43
|
+
*/
|
|
28
44
|
export declare function templateFiles(): readonly string[];
|
|
29
45
|
export declare function readTemplate(name: string): string;
|
|
30
46
|
export type ChartValues = {
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { existsSync, readFileSync, readdirSync } from "node:fs";
|
|
2
1
|
import { dirname, join, resolve } from "node:path";
|
|
3
2
|
import { fileURLToPath } from "node:url";
|
|
4
3
|
import { TARGET_SHAPES, isTargetShape } from "@crewhaus/docker-images";
|
|
@@ -23,6 +22,7 @@ import { TARGET_SHAPES, isTargetShape } from "@crewhaus/docker-images";
|
|
|
23
22
|
* helm/crewhaus -f values.yaml`.
|
|
24
23
|
*/
|
|
25
24
|
import { CrewhausError } from "@crewhaus/errors";
|
|
25
|
+
import { TEMPLATE_BODIES } from "./embedded";
|
|
26
26
|
export class HelmChartError extends CrewhausError {
|
|
27
27
|
name = "HelmChartError";
|
|
28
28
|
constructor(message, cause) {
|
|
@@ -31,27 +31,37 @@ export class HelmChartError extends CrewhausError {
|
|
|
31
31
|
}
|
|
32
32
|
const PACKAGE_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
|
33
33
|
const CHART_ROOT = join(PACKAGE_ROOT, "helm", "crewhaus");
|
|
34
|
-
|
|
34
|
+
/**
|
|
35
|
+
* On-disk location of the chart, for humans and for tooling that wants to run
|
|
36
|
+
* `helm install … <chartRoot()>` directly. Present in a source checkout and in
|
|
37
|
+
* a published npm install (`helm/` is in this package's `files`), but NOT in
|
|
38
|
+
* the compiled binary, where the chart exists only as embedded text. Rendering
|
|
39
|
+
* never reads it — use {@link renderChart}.
|
|
40
|
+
*/
|
|
35
41
|
export function chartRoot() {
|
|
36
42
|
return CHART_ROOT;
|
|
37
43
|
}
|
|
44
|
+
/**
|
|
45
|
+
* The chart's template filenames, in the same sorted order the old
|
|
46
|
+
* `readdirSync().sort()` produced.
|
|
47
|
+
*
|
|
48
|
+
* Served from {@link TEMPLATE_BODIES} rather than the filesystem: the previous
|
|
49
|
+
* package-relative read failed on BOTH published channels — under `/$bunfs` in
|
|
50
|
+
* the compiled binary, and against an absent `helm/` in the npm tarball. See
|
|
51
|
+
* `embedded.ts`.
|
|
52
|
+
*/
|
|
38
53
|
export function templateFiles() {
|
|
39
|
-
|
|
40
|
-
throw new HelmChartError(`templates directory missing at ${TEMPLATES_DIR}`);
|
|
41
|
-
}
|
|
42
|
-
return readdirSync(TEMPLATES_DIR)
|
|
43
|
-
.filter((f) => /\.(ya?ml|tpl)$/.test(f))
|
|
44
|
-
.sort();
|
|
54
|
+
return Object.keys(TEMPLATE_BODIES);
|
|
45
55
|
}
|
|
46
56
|
export function readTemplate(name) {
|
|
47
57
|
if (name.includes("/") || name.includes("..")) {
|
|
48
58
|
throw new HelmChartError(`invalid template name: ${name}`);
|
|
49
59
|
}
|
|
50
|
-
const
|
|
51
|
-
if (
|
|
60
|
+
const body = TEMPLATE_BODIES[name];
|
|
61
|
+
if (body === undefined) {
|
|
52
62
|
throw new HelmChartError(`template not found: ${name}`);
|
|
53
63
|
}
|
|
54
|
-
return
|
|
64
|
+
return body;
|
|
55
65
|
}
|
|
56
66
|
export function defaultValues() {
|
|
57
67
|
return {
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
apiVersion: v2
|
|
2
|
+
name: crewhaus
|
|
3
|
+
description: CrewHaus Factory — modular meta-harness for compiling agent specs into deployable runtimes
|
|
4
|
+
type: application
|
|
5
|
+
version: 0.1.0
|
|
6
|
+
appVersion: "1.0.0"
|
|
7
|
+
home: https://github.com/crewhaus/factory
|
|
8
|
+
sources:
|
|
9
|
+
- https://github.com/crewhaus/factory
|
|
10
|
+
maintainers:
|
|
11
|
+
- name: CrewHaus
|
|
12
|
+
email: maintainers@crewhaus.ai
|
|
13
|
+
keywords:
|
|
14
|
+
- llm
|
|
15
|
+
- agents
|
|
16
|
+
- meta-harness
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{{/*
|
|
2
|
+
Helpers for the crewhaus chart. Kept deliberately simple so both
|
|
3
|
+
real Helm and the in-process renderChart() (used by tests in
|
|
4
|
+
@crewhaus/helm-chart) produce equivalent output.
|
|
5
|
+
*/}}
|
|
6
|
+
|
|
7
|
+
{{- define "crewhaus.name" -}}
|
|
8
|
+
crewhaus
|
|
9
|
+
{{- end -}}
|
|
10
|
+
|
|
11
|
+
{{- define "crewhaus.fullname" -}}
|
|
12
|
+
{{ .Release.Name }}-crewhaus
|
|
13
|
+
{{- end -}}
|
|
14
|
+
|
|
15
|
+
{{- define "crewhaus.labels" -}}
|
|
16
|
+
app.kubernetes.io/name: {{ include "crewhaus.name" . }}
|
|
17
|
+
app.kubernetes.io/instance: {{ .Release.Name }}
|
|
18
|
+
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
|
|
19
|
+
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
|
20
|
+
crewhaus.ai/target: {{ .Values.target | quote }}
|
|
21
|
+
{{- end -}}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
apiVersion: apps/v1
|
|
2
|
+
kind: Deployment
|
|
3
|
+
metadata:
|
|
4
|
+
name: {{ include "crewhaus.fullname" . }}
|
|
5
|
+
labels:
|
|
6
|
+
{{- include "crewhaus.labels" . | nindent 4 }}
|
|
7
|
+
spec:
|
|
8
|
+
replicas: {{ .Values.replicas }}
|
|
9
|
+
selector:
|
|
10
|
+
matchLabels:
|
|
11
|
+
app.kubernetes.io/name: {{ include "crewhaus.name" . }}
|
|
12
|
+
app.kubernetes.io/instance: {{ .Release.Name }}
|
|
13
|
+
template:
|
|
14
|
+
metadata:
|
|
15
|
+
labels:
|
|
16
|
+
{{- include "crewhaus.labels" . | nindent 8 }}
|
|
17
|
+
spec:
|
|
18
|
+
{{- with .Values.image.pullSecrets }}
|
|
19
|
+
imagePullSecrets:
|
|
20
|
+
{{- toYaml . | nindent 8 }}
|
|
21
|
+
{{- end }}
|
|
22
|
+
securityContext:
|
|
23
|
+
{{- toYaml .Values.podSecurityContext | nindent 8 }}
|
|
24
|
+
containers:
|
|
25
|
+
- name: crewhaus
|
|
26
|
+
# image.registry (default ghcr.io/crewhaus — where releases publish)
|
|
27
|
+
# prefixes the target-derived image name; image.digest pins by
|
|
28
|
+
# registry manifest digest, otherwise tag is used.
|
|
29
|
+
image: "{{ .Values.image.registry }}/{{ .Values.target }}{{ if .Values.image.digest }}@{{ .Values.image.digest }}{{ else }}:{{ .Values.image.tag }}{{ end }}"
|
|
30
|
+
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
|
31
|
+
securityContext:
|
|
32
|
+
{{- toYaml .Values.securityContext | nindent 12 }}
|
|
33
|
+
env:
|
|
34
|
+
- name: CREWHAUS_TARGET
|
|
35
|
+
value: {{ .Values.target | quote }}
|
|
36
|
+
{{- if .Values.secrets.anthropic }}
|
|
37
|
+
- name: ANTHROPIC_AUTH_TOKEN
|
|
38
|
+
valueFrom:
|
|
39
|
+
secretKeyRef:
|
|
40
|
+
name: {{ .Values.secrets.anthropic.secretName }}
|
|
41
|
+
key: {{ .Values.secrets.anthropic.key }}
|
|
42
|
+
{{- end }}
|
|
43
|
+
{{- if eq .Values.target "channel" }}
|
|
44
|
+
- name: SLACK_SIGNING_SECRET
|
|
45
|
+
valueFrom:
|
|
46
|
+
secretKeyRef:
|
|
47
|
+
name: {{ .Values.secrets.slack.signing.secretName }}
|
|
48
|
+
key: {{ .Values.secrets.slack.signing.key }}
|
|
49
|
+
- name: SLACK_BOT_TOKEN
|
|
50
|
+
valueFrom:
|
|
51
|
+
secretKeyRef:
|
|
52
|
+
name: {{ .Values.secrets.slack.bot.secretName }}
|
|
53
|
+
key: {{ .Values.secrets.slack.bot.key }}
|
|
54
|
+
{{- end }}
|
|
55
|
+
{{- range .Values.secrets.provider }}
|
|
56
|
+
- name: {{ .name }}
|
|
57
|
+
valueFrom:
|
|
58
|
+
secretKeyRef:
|
|
59
|
+
name: {{ .secretName }}
|
|
60
|
+
key: {{ .key }}
|
|
61
|
+
{{- end }}
|
|
62
|
+
{{- range .Values.extraEnv }}
|
|
63
|
+
- name: {{ .name }}
|
|
64
|
+
value: {{ .value | quote }}
|
|
65
|
+
{{- end }}
|
|
66
|
+
{{- if .Values.otel.enabled }}
|
|
67
|
+
- name: OTEL_EXPORTER_OTLP_ENDPOINT
|
|
68
|
+
value: {{ .Values.otel.endpoint | quote }}
|
|
69
|
+
{{- if .Values.otel.headers }}
|
|
70
|
+
- name: OTEL_EXPORTER_OTLP_HEADERS
|
|
71
|
+
value: {{ .Values.otel.headers | quote }}
|
|
72
|
+
{{- end }}
|
|
73
|
+
{{- end }}
|
|
74
|
+
{{- if has .Values.target (list "channel" "managed" "crew" "voice" "browser") }}
|
|
75
|
+
ports:
|
|
76
|
+
- name: http
|
|
77
|
+
containerPort: {{ .Values.service.targetPort }}
|
|
78
|
+
protocol: TCP
|
|
79
|
+
livenessProbe:
|
|
80
|
+
httpGet:
|
|
81
|
+
path: /healthz
|
|
82
|
+
port: http
|
|
83
|
+
initialDelaySeconds: 5
|
|
84
|
+
periodSeconds: 15
|
|
85
|
+
readinessProbe:
|
|
86
|
+
httpGet:
|
|
87
|
+
path: /healthz
|
|
88
|
+
port: http
|
|
89
|
+
initialDelaySeconds: 2
|
|
90
|
+
periodSeconds: 5
|
|
91
|
+
{{- else }}
|
|
92
|
+
# Process-liveness only: `doctor --liveness` exits 0 without
|
|
93
|
+
# credential/spec checks. Plain `doctor` always failed here —
|
|
94
|
+
# /app/crewhaus.yaml never exists in the image.
|
|
95
|
+
livenessProbe:
|
|
96
|
+
exec:
|
|
97
|
+
command: ["bun", "/app/crewhaus.js", "doctor", "--liveness"]
|
|
98
|
+
initialDelaySeconds: 5
|
|
99
|
+
periodSeconds: 30
|
|
100
|
+
readinessProbe:
|
|
101
|
+
exec:
|
|
102
|
+
command: ["bun", "/app/crewhaus.js", "doctor", "--liveness"]
|
|
103
|
+
initialDelaySeconds: 2
|
|
104
|
+
periodSeconds: 10
|
|
105
|
+
{{- end }}
|
|
106
|
+
resources:
|
|
107
|
+
{{- toYaml .Values.resources | nindent 12 }}
|
|
108
|
+
volumeMounts:
|
|
109
|
+
- name: spec
|
|
110
|
+
mountPath: /spec
|
|
111
|
+
readOnly: true
|
|
112
|
+
- name: tmp
|
|
113
|
+
mountPath: /tmp
|
|
114
|
+
volumes:
|
|
115
|
+
- name: spec
|
|
116
|
+
configMap:
|
|
117
|
+
name: {{ .Values.spec.configMap }}
|
|
118
|
+
- name: tmp
|
|
119
|
+
emptyDir: {}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{{- if and .Values.ingress.enabled (has .Values.target (list "channel" "managed" "crew" "voice" "browser")) -}}
|
|
2
|
+
apiVersion: networking.k8s.io/v1
|
|
3
|
+
kind: Ingress
|
|
4
|
+
metadata:
|
|
5
|
+
name: {{ include "crewhaus.fullname" . }}
|
|
6
|
+
labels:
|
|
7
|
+
{{- include "crewhaus.labels" . | nindent 4 }}
|
|
8
|
+
{{- with .Values.ingress.annotations }}
|
|
9
|
+
annotations:
|
|
10
|
+
{{- toYaml . | nindent 4 }}
|
|
11
|
+
{{- end }}
|
|
12
|
+
spec:
|
|
13
|
+
{{- if .Values.ingress.className }}
|
|
14
|
+
ingressClassName: {{ .Values.ingress.className }}
|
|
15
|
+
{{- end }}
|
|
16
|
+
{{- if .Values.ingress.tls }}
|
|
17
|
+
tls:
|
|
18
|
+
{{- range .Values.ingress.tls }}
|
|
19
|
+
- hosts:
|
|
20
|
+
{{- range .hosts }}
|
|
21
|
+
- {{ . | quote }}
|
|
22
|
+
{{- end }}
|
|
23
|
+
secretName: {{ .secretName }}
|
|
24
|
+
{{- end }}
|
|
25
|
+
{{- end }}
|
|
26
|
+
rules:
|
|
27
|
+
{{- range .Values.ingress.hosts }}
|
|
28
|
+
- host: {{ .host | quote }}
|
|
29
|
+
http:
|
|
30
|
+
paths:
|
|
31
|
+
{{- range .paths }}
|
|
32
|
+
- path: {{ .path }}
|
|
33
|
+
pathType: {{ .pathType }}
|
|
34
|
+
backend:
|
|
35
|
+
service:
|
|
36
|
+
name: {{ include "crewhaus.fullname" $ }}
|
|
37
|
+
port:
|
|
38
|
+
number: {{ $.Values.service.port }}
|
|
39
|
+
{{- end }}
|
|
40
|
+
{{- end }}
|
|
41
|
+
{{- end }}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{{- if .Values.otel.enabled -}}
|
|
2
|
+
apiVersion: v1
|
|
3
|
+
kind: ConfigMap
|
|
4
|
+
metadata:
|
|
5
|
+
name: {{ include "crewhaus.fullname" . }}-otel
|
|
6
|
+
labels:
|
|
7
|
+
{{- include "crewhaus.labels" . | nindent 4 }}
|
|
8
|
+
data:
|
|
9
|
+
collector.yaml: |
|
|
10
|
+
receivers:
|
|
11
|
+
otlp:
|
|
12
|
+
protocols:
|
|
13
|
+
http:
|
|
14
|
+
endpoint: 0.0.0.0:4318
|
|
15
|
+
processors:
|
|
16
|
+
batch:
|
|
17
|
+
timeout: 5s
|
|
18
|
+
send_batch_size: 1000
|
|
19
|
+
exporters:
|
|
20
|
+
logging:
|
|
21
|
+
loglevel: info
|
|
22
|
+
service:
|
|
23
|
+
pipelines:
|
|
24
|
+
traces:
|
|
25
|
+
receivers: [otlp]
|
|
26
|
+
processors: [batch]
|
|
27
|
+
exporters: [logging]
|
|
28
|
+
metrics:
|
|
29
|
+
receivers: [otlp]
|
|
30
|
+
processors: [batch]
|
|
31
|
+
exporters: [logging]
|
|
32
|
+
{{- end }}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{{- if has .Values.target (list "channel" "managed" "crew" "voice" "browser") -}}
|
|
2
|
+
apiVersion: v1
|
|
3
|
+
kind: Service
|
|
4
|
+
metadata:
|
|
5
|
+
name: {{ include "crewhaus.fullname" . }}
|
|
6
|
+
labels:
|
|
7
|
+
{{- include "crewhaus.labels" . | nindent 4 }}
|
|
8
|
+
spec:
|
|
9
|
+
type: {{ .Values.service.type }}
|
|
10
|
+
ports:
|
|
11
|
+
- port: {{ .Values.service.port }}
|
|
12
|
+
targetPort: http
|
|
13
|
+
protocol: TCP
|
|
14
|
+
name: http
|
|
15
|
+
selector:
|
|
16
|
+
app.kubernetes.io/name: {{ include "crewhaus.name" . }}
|
|
17
|
+
app.kubernetes.io/instance: {{ .Release.Name }}
|
|
18
|
+
{{- end }}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{{- if .Values.serviceMonitor.enabled -}}
|
|
2
|
+
apiVersion: monitoring.coreos.com/v1
|
|
3
|
+
kind: ServiceMonitor
|
|
4
|
+
metadata:
|
|
5
|
+
name: {{ include "crewhaus.fullname" . }}
|
|
6
|
+
labels:
|
|
7
|
+
{{- include "crewhaus.labels" . | nindent 4 }}
|
|
8
|
+
{{- with .Values.serviceMonitor.labels }}
|
|
9
|
+
{{- toYaml . | nindent 4 }}
|
|
10
|
+
{{- end }}
|
|
11
|
+
spec:
|
|
12
|
+
selector:
|
|
13
|
+
matchLabels:
|
|
14
|
+
app.kubernetes.io/name: {{ include "crewhaus.name" . }}
|
|
15
|
+
app.kubernetes.io/instance: {{ .Release.Name }}
|
|
16
|
+
endpoints:
|
|
17
|
+
- port: http
|
|
18
|
+
path: /metrics
|
|
19
|
+
interval: {{ .Values.serviceMonitor.interval }}
|
|
20
|
+
{{- end }}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
## Default values for the crewhaus chart.
|
|
2
|
+
|
|
3
|
+
# One of: cli, workflow, channel, graph, managed, pipeline, crew, research,
|
|
4
|
+
# batch, voice, browser, eval. Determines which Deployment template renders
|
|
5
|
+
# and which Dockerfile-bundled image is used.
|
|
6
|
+
target: channel
|
|
7
|
+
|
|
8
|
+
image:
|
|
9
|
+
# Registry + namespace prefix for the per-shape images. The image NAME is
|
|
10
|
+
# always derived from `target` (<registry>/<target>), so this is the only
|
|
11
|
+
# knob needed to point at a mirror or private registry. The default matches
|
|
12
|
+
# where the release workflow actually publishes — nothing publishes to
|
|
13
|
+
# docker.io.
|
|
14
|
+
registry: ghcr.io/crewhaus
|
|
15
|
+
tag: latest
|
|
16
|
+
# Optional content-digest pin. When set to "sha256:<64 hex>" (a REGISTRY
|
|
17
|
+
# MANIFEST digest, as recorded in packages/docker-images/docker/digests.json
|
|
18
|
+
# by `crewhaus build-image --push` and the release workflow's docker-digests
|
|
19
|
+
# job — local --load builds record nothing pullable), the Deployment
|
|
20
|
+
# references <registry>/<target>@sha256:... and `tag` is ignored —
|
|
21
|
+
# reproducible, tamper-evident deploys.
|
|
22
|
+
# digest: "sha256:<digest>"
|
|
23
|
+
pullPolicy: IfNotPresent
|
|
24
|
+
pullSecrets: []
|
|
25
|
+
|
|
26
|
+
replicas: 1
|
|
27
|
+
|
|
28
|
+
# Spec ConfigMap source. The chart mounts this ConfigMap at /spec/crewhaus.yaml
|
|
29
|
+
# inside every pod. Paths inside spec must use $VAR_NAME refs (Section 12) —
|
|
30
|
+
# the chart wires them into env vars from `secrets` below.
|
|
31
|
+
spec:
|
|
32
|
+
configMap: crewhaus-spec
|
|
33
|
+
fileName: crewhaus.yaml
|
|
34
|
+
|
|
35
|
+
# Secret references. Each maps a CrewHaus env var to a Kubernetes Secret name +
|
|
36
|
+
# key. Wires §27 secrets-manager to k8s Secret resources.
|
|
37
|
+
secrets:
|
|
38
|
+
anthropic:
|
|
39
|
+
secretName: crewhaus-creds
|
|
40
|
+
key: ANTHROPIC_AUTH_TOKEN
|
|
41
|
+
slack:
|
|
42
|
+
signing:
|
|
43
|
+
secretName: crewhaus-creds
|
|
44
|
+
key: SLACK_SIGNING_SECRET
|
|
45
|
+
bot:
|
|
46
|
+
secretName: crewhaus-creds
|
|
47
|
+
key: SLACK_BOT_TOKEN
|
|
48
|
+
# Generic provider secret list — one entry per env var the spec's model
|
|
49
|
+
# provider needs, each sourced from a Kubernetes Secret. Use this for
|
|
50
|
+
# non-Anthropic models (the model-router grammar: openai/*, gemini/*,
|
|
51
|
+
# bedrock/*, local/<m>@<url>). Presets:
|
|
52
|
+
#
|
|
53
|
+
# openai: - name: OPENAI_API_KEY # or OPENAI_BASE_URL for an
|
|
54
|
+
# # OpenAI-compatible endpoint
|
|
55
|
+
# gemini: - name: GEMINI_API_KEY # or GOOGLE_API_KEY; Vertex
|
|
56
|
+
# # users set GOOGLE_CLOUD_PROJECT
|
|
57
|
+
# # + GOOGLE_GENAI_USE_VERTEXAI
|
|
58
|
+
# # via extraEnv below
|
|
59
|
+
# bedrock: - name: AWS_BEARER_TOKEN_BEDROCK # or AWS_ACCESS_KEY_ID +
|
|
60
|
+
# - name: AWS_SECRET_ACCESS_KEY # AWS_SECRET_ACCESS_KEY; the
|
|
61
|
+
# # SDK default chain (IRSA,
|
|
62
|
+
# # instance profile) needs none
|
|
63
|
+
# local: (no credentials)
|
|
64
|
+
#
|
|
65
|
+
# Example:
|
|
66
|
+
# provider:
|
|
67
|
+
# - name: OPENAI_API_KEY
|
|
68
|
+
# secretName: crewhaus-creds
|
|
69
|
+
# key: OPENAI_API_KEY
|
|
70
|
+
provider: []
|
|
71
|
+
|
|
72
|
+
# Plain (non-secret) env vars appended to the container, e.g. provider
|
|
73
|
+
# region/endpoint selectors:
|
|
74
|
+
# - name: AWS_REGION
|
|
75
|
+
# value: us-east-1
|
|
76
|
+
# - name: OPENAI_BASE_URL
|
|
77
|
+
# value: http://vllm.internal:8000/v1
|
|
78
|
+
# - name: GOOGLE_CLOUD_PROJECT
|
|
79
|
+
# value: my-project
|
|
80
|
+
extraEnv: []
|
|
81
|
+
|
|
82
|
+
# Service & Ingress (only rendered for daemon shapes: channel, managed, crew,
|
|
83
|
+
# voice, browser).
|
|
84
|
+
service:
|
|
85
|
+
type: ClusterIP
|
|
86
|
+
port: 80
|
|
87
|
+
targetPort: 3000
|
|
88
|
+
|
|
89
|
+
ingress:
|
|
90
|
+
enabled: false
|
|
91
|
+
className: ""
|
|
92
|
+
annotations: {}
|
|
93
|
+
hosts:
|
|
94
|
+
- host: crewhaus.example.com
|
|
95
|
+
paths:
|
|
96
|
+
- path: /
|
|
97
|
+
pathType: Prefix
|
|
98
|
+
tls: []
|
|
99
|
+
|
|
100
|
+
# §20 gateway-server JWT issuance.
|
|
101
|
+
gateway:
|
|
102
|
+
tls:
|
|
103
|
+
cert: ""
|
|
104
|
+
key: ""
|
|
105
|
+
|
|
106
|
+
resources:
|
|
107
|
+
requests:
|
|
108
|
+
cpu: 100m
|
|
109
|
+
memory: 256Mi
|
|
110
|
+
limits:
|
|
111
|
+
cpu: 1000m
|
|
112
|
+
memory: 1Gi
|
|
113
|
+
|
|
114
|
+
# §15 OTel collector sidecar — emits trace events to a configured backend.
|
|
115
|
+
otel:
|
|
116
|
+
enabled: true
|
|
117
|
+
endpoint: ""
|
|
118
|
+
headers: ""
|
|
119
|
+
|
|
120
|
+
# Prometheus operator ServiceMonitor for §15 metrics-collector httpServer mode.
|
|
121
|
+
serviceMonitor:
|
|
122
|
+
enabled: true
|
|
123
|
+
interval: 30s
|
|
124
|
+
labels: {}
|
|
125
|
+
|
|
126
|
+
# Pod security context (mirrors the Dockerfile USER + read-only root).
|
|
127
|
+
podSecurityContext:
|
|
128
|
+
runAsNonRoot: true
|
|
129
|
+
runAsUser: 10001
|
|
130
|
+
fsGroup: 10001
|
|
131
|
+
|
|
132
|
+
securityContext:
|
|
133
|
+
readOnlyRootFilesystem: true
|
|
134
|
+
allowPrivilegeEscalation: false
|
|
135
|
+
capabilities:
|
|
136
|
+
drop: [ALL]
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@crewhaus/helm-chart",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Kubernetes Helm chart (templates + values schema + ServiceMonitor + OTel collector sidecar) plus an in-process renderChart() for tests (Section 32)",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -15,8 +15,8 @@
|
|
|
15
15
|
"test": "bun test src"
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"@crewhaus/docker-images": "0.5.
|
|
19
|
-
"@crewhaus/errors": "0.5.
|
|
18
|
+
"@crewhaus/docker-images": "0.5.2",
|
|
19
|
+
"@crewhaus/errors": "0.5.2"
|
|
20
20
|
},
|
|
21
21
|
"license": "Apache-2.0",
|
|
22
22
|
"author": {
|
|
@@ -36,5 +36,5 @@
|
|
|
36
36
|
"publishConfig": {
|
|
37
37
|
"access": "public"
|
|
38
38
|
},
|
|
39
|
-
"files": ["dist", "README.md", "LICENSE", "NOTICE"]
|
|
39
|
+
"files": ["dist", "helm", "README.md", "LICENSE", "NOTICE"]
|
|
40
40
|
}
|