Skip to content

Commit 3aadf0b

Browse files
bdehamerCopilotCopilot
authored
Add Helm chart for deployment-tracker (#62)
* add helm chart Signed-off-by: Brian DeHamer <bdehamer@github.com> * set default version to 0.0.0 Signed-off-by: Brian DeHamer <bdehamer@github.com> * Update deploy/charts/deployment-tracker/templates/clusterrole.yaml Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Add Helm template validation for mutually exclusive namespace flags (#65) * Initial plan * Add template-time validation for mutually exclusive namespace flags Co-authored-by: bdehamer <398027+bdehamer@users.noreply.github.com> Agent-Logs-Url: https://github.com/github/deployment-tracker/sessions/ab6214f1-4681-454f-b5de-7d0caa1a9cc9 --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: bdehamer <398027+bdehamer@users.noreply.github.com> * Update deploy/charts/deployment-tracker/templates/_helpers.tpl Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * remove required value warning in notes Signed-off-by: Brian DeHamer <bdehamer@github.com> --------- Signed-off-by: Brian DeHamer <bdehamer@github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com> Co-authored-by: bdehamer <398027+bdehamer@users.noreply.github.com>
1 parent 2d6cac1 commit 3aadf0b

File tree

13 files changed

+642
-1
lines changed

13 files changed

+642
-1
lines changed

.github/workflows/build.yml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,3 +46,20 @@ jobs:
4646
- name: Test
4747
run: |
4848
make integration-test
49+
50+
helm-lint:
51+
name: Helm Lint
52+
runs-on: ubuntu-latest
53+
permissions:
54+
contents: read
55+
steps:
56+
- name: Checkout repository
57+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
58+
with:
59+
persist-credentials: false
60+
- name: Set up Helm
61+
uses: azure/setup-helm@b9e51907a09c216f16ebe8536097933489208112 # v4.3.0
62+
- name: Lint chart
63+
run: helm lint deploy/charts/deployment-tracker --set config.org=test --set config.logicalEnvironment=test --set config.cluster=test
64+
- name: Validate chart rendering
65+
run: helm template test deploy/charts/deployment-tracker --set config.org=test --set config.logicalEnvironment=test --set config.cluster=test > /dev/null

.github/workflows/release.yaml

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ on:
88
permissions:
99
contents: read
1010

11+
env:
12+
REGISTRY: ghcr.io
13+
IMAGE_NAME: ${{ github.repository }}
14+
1115
jobs:
1216
release:
1317
name: Build and Release OCI Image
@@ -53,6 +57,28 @@ jobs:
5357
- name: Attest build provenance
5458
uses: actions/attest-build-provenance@a2bbfa25375fe432b6a289bc6b6cd05ecd0c4c32 # v4.1.0
5559
with:
56-
subject-name: ghcr.io/github/artifact-attestations-opa-provider
60+
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
5761
subject-digest: ${{ steps.push.outputs.digest }}
5862
push-to-registry: true
63+
64+
- name: Set up Helm
65+
uses: azure/setup-helm@b9e51907a09c216f16ebe8536097933489208112 # v4.3.0
66+
67+
- name: Update chart version
68+
run: |
69+
VERSION=${GITHUB_REF#refs/tags/v}
70+
sed -i "s/^version:.*/version: ${VERSION}/" deploy/charts/deployment-tracker/Chart.yaml
71+
sed -i "s/^appVersion:.*/appVersion: \"${VERSION}\"/" deploy/charts/deployment-tracker/Chart.yaml
72+
73+
- name: Package Helm chart
74+
run: helm package deploy/charts/deployment-tracker
75+
76+
- name: Log in to GHCR for Helm
77+
run: |
78+
echo "${{ secrets.GITHUB_TOKEN }}" | \
79+
helm registry login ghcr.io -u ${{ github.actor }} --password-stdin
80+
81+
- name: Push Helm chart to GHCR
82+
run: |
83+
helm push deployment-tracker-*.tgz \
84+
oci://ghcr.io/${{ github.repository_owner }}/charts
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Patterns to ignore when building packages.
2+
.DS_Store
3+
*.swp
4+
*.bak
5+
*.tmp
6+
*.orig
7+
*~
8+
.git
9+
.gitignore
10+
.project
11+
.idea
12+
*.tmproj
13+
.vscode
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
apiVersion: v2
2+
name: deployment-tracker
3+
description: A Kubernetes controller that monitors pod lifecycles and uploads deployment records to GitHub's artifact metadata API
4+
type: application
5+
version: 0.0.0
6+
appVersion: "0.0.0"
7+
kubeVersion: ">= 1.19.0-0"
8+
keywords:
9+
- kubernetes
10+
- deployment-tracker
11+
- github
12+
- artifact-attestations
13+
- supply-chain-security
14+
home: https://github.com/github/deployment-tracker
15+
maintainers:
16+
- name: GitHub Package Security
17+
url: https://github.com/github
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
# deployment-tracker Helm Chart
2+
3+
A Helm chart for deploying the deployment-tracker Kubernetes controller, which
4+
monitors pod lifecycles and uploads deployment records to GitHub's artifact
5+
metadata API.
6+
7+
## Prerequisites
8+
9+
- Kubernetes 1.19+
10+
- Helm 3.8+
11+
- A GitHub organization with
12+
[Artifact Attestations](https://docs.github.com/en/actions/concepts/security/artifact-attestations)
13+
enabled
14+
- An API token or GitHub App for authentication
15+
16+
## Installation
17+
18+
### Install from OCI registry
19+
20+
```bash
21+
helm install deployment-tracker \
22+
oci://ghcr.io/github/charts/deployment-tracker \
23+
--namespace deployment-tracker \
24+
--create-namespace \
25+
--set config.org=my-org \
26+
--set config.logicalEnvironment=production \
27+
--set config.cluster=my-cluster \
28+
--set auth.apiTokenSecret=my-api-token-secret
29+
```
30+
31+
### Install from local source
32+
33+
```bash
34+
helm install deployment-tracker ./deploy/charts/deployment-tracker \
35+
--namespace deployment-tracker \
36+
--create-namespace \
37+
-f my-values.yaml
38+
```
39+
40+
## Required Values
41+
42+
The following values **must** be set for the controller to function:
43+
44+
| Value | Description |
45+
|-------|-------------|
46+
| `config.org` | GitHub organization name |
47+
| `config.logicalEnvironment` | Logical environment name (e.g., `production`, `staging`) |
48+
| `config.cluster` | Kubernetes cluster name |
49+
50+
At least one authentication method must be configured (see
51+
[Authentication](#authentication)).
52+
53+
## Configuration
54+
55+
### Controller Configuration
56+
57+
| Parameter | Description | Default |
58+
|-----------|-------------|---------|
59+
| `config.org` | GitHub organization name | `""` (required) |
60+
| `config.logicalEnvironment` | Logical environment name | `""` (required) |
61+
| `config.cluster` | Cluster name | `""` (required) |
62+
| `config.physicalEnvironment` | Physical environment name | `""` |
63+
| `config.baseUrl` | API base URL | `api.github.com` |
64+
| `config.dnTemplate` | Deployment name template | `{{namespace}}/{{deploymentName}}/{{containerName}}` |
65+
| `config.namespace` | Namespace to monitor (empty for all) | `""` |
66+
| `config.excludeNamespaces` | Namespaces to exclude (comma-separated) | `""` |
67+
| `config.workers` | Number of worker goroutines | `2` |
68+
| `config.metricsPort` | Port for Prometheus metrics | `9090` |
69+
70+
### Image Configuration
71+
72+
| Parameter | Description | Default |
73+
|-----------|-------------|---------|
74+
| `image.repository` | Container image repository | `ghcr.io/github/deployment-tracker` |
75+
| `image.tag` | Container image tag | Chart `appVersion` |
76+
| `image.pullPolicy` | Image pull policy | `IfNotPresent` |
77+
| `imagePullSecrets` | Image pull secrets | `[]` |
78+
79+
### Authentication
80+
81+
The controller supports two authentication methods: API token and GitHub App.
82+
83+
#### API Token
84+
85+
```yaml
86+
# Option 1: Inline token (not recommended for production)
87+
auth:
88+
apiToken: "ghp_xxxxxxxxxxxx"
89+
90+
# Option 2: Reference to an existing Secret (recommended)
91+
auth:
92+
apiTokenSecret: "my-api-token-secret"
93+
```
94+
95+
When using `apiTokenSecret`, the Secret must have a key named `token`:
96+
97+
```yaml
98+
apiVersion: v1
99+
kind: Secret
100+
metadata:
101+
name: my-api-token-secret
102+
type: Opaque
103+
stringData:
104+
token: "ghp_xxxxxxxxxxxx"
105+
```
106+
107+
#### GitHub App
108+
109+
```yaml
110+
# Option 1: Inline private key
111+
auth:
112+
githubApp:
113+
appId: "12345"
114+
installId: "67890"
115+
privateKey: "<base64-encoded-private-key>"
116+
117+
# Option 2: Reference to an existing Secret (recommended)
118+
auth:
119+
githubApp:
120+
appId: "12345"
121+
installId: "67890"
122+
privateKeySecret: "my-github-app-secret"
123+
```
124+
125+
When using `privateKeySecret`, the Secret must have a key named `private-key`:
126+
127+
```yaml
128+
apiVersion: v1
129+
kind: Secret
130+
metadata:
131+
name: my-github-app-secret
132+
type: Opaque
133+
stringData:
134+
private-key: "<base64-encoded-private-key>"
135+
```
136+
137+
### Resources and Security
138+
139+
| Parameter | Description | Default |
140+
|-----------|-------------|---------|
141+
| `replicaCount` | Number of controller replicas | `1` |
142+
| `resources.requests.cpu` | CPU request | `100m` |
143+
| `resources.requests.memory` | Memory request | `1024Mi` |
144+
| `resources.limits.cpu` | CPU limit | `200m` |
145+
| `resources.limits.memory` | Memory limit | `2048Mi` |
146+
| `securityContext` | Container security context | Hardened (see values.yaml) |
147+
| `readinessProbe` | Readiness probe configuration | HTTP GET /metrics:9090 |
148+
| `lifecycle` | Lifecycle hooks | preStop sleep 5s |
149+
150+
### Service and Networking
151+
152+
| Parameter | Description | Default |
153+
|-----------|-------------|---------|
154+
| `service.enabled` | Create a Service for metrics | `true` |
155+
| `service.type` | Service type | `ClusterIP` |
156+
| `service.port` | Service port | `9090` |
157+
| `nodeSelector` | Node selector | `{}` |
158+
| `tolerations` | Tolerations | `[]` |
159+
| `affinity` | Affinity rules | `{}` |
160+
161+
### Service Account
162+
163+
| Parameter | Description | Default |
164+
|-----------|-------------|---------|
165+
| `serviceAccount.create` | Create a ServiceAccount | `true` |
166+
| `serviceAccount.name` | ServiceAccount name | Generated from fullname |
167+
| `serviceAccount.annotations` | ServiceAccount annotations | `{}` |
168+
169+
## Uninstalling
170+
171+
```bash
172+
helm uninstall deployment-tracker -n deployment-tracker
173+
```
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
deployment-tracker has been installed.
2+
3+
1. Check the deployment status:
4+
5+
kubectl get deployment {{ include "deployment-tracker.fullname" . }} -n {{ .Release.Namespace }}
6+
7+
2. Check the controller pods:
8+
9+
kubectl get pods -n {{ .Release.Namespace }} -l "{{ include "deployment-tracker.selectorLabels" . | replace "\n" "," }}"
10+
11+
3. View controller logs:
12+
13+
kubectl logs -n {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "deployment-tracker.name" . }}" -f
14+
15+
{{- if .Values.service.enabled }}
16+
17+
4. Access Prometheus metrics:
18+
19+
kubectl port-forward -n {{ .Release.Namespace }} svc/{{ include "deployment-tracker.fullname" . }} {{ .Values.service.port }}:{{ .Values.service.port }}
20+
curl http://localhost:{{ .Values.service.port }}/metrics
21+
{{- end }}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
{{/*
2+
Expand the name of the chart.
3+
*/}}
4+
{{- define "deployment-tracker.name" -}}
5+
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
6+
{{- end }}
7+
8+
{{/*
9+
Create a default fully qualified app name.
10+
*/}}
11+
{{- define "deployment-tracker.fullname" -}}
12+
{{- if .Values.fullnameOverride }}
13+
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
14+
{{- else }}
15+
{{- $name := default .Chart.Name .Values.nameOverride }}
16+
{{- if contains $name .Release.Name }}
17+
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
18+
{{- else }}
19+
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
20+
{{- end }}
21+
{{- end }}
22+
{{- end }}
23+
24+
{{/*
25+
Create chart name and version as used by the chart label.
26+
*/}}
27+
{{- define "deployment-tracker.chart" -}}
28+
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
29+
{{- end }}
30+
31+
{{/*
32+
Common labels.
33+
*/}}
34+
{{- define "deployment-tracker.labels" -}}
35+
helm.sh/chart: {{ include "deployment-tracker.chart" . }}
36+
{{ include "deployment-tracker.selectorLabels" . }}
37+
{{- if .Chart.AppVersion }}
38+
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
39+
{{- end }}
40+
app.kubernetes.io/managed-by: {{ .Release.Service }}
41+
{{- end }}
42+
43+
{{/*
44+
Selector labels.
45+
*/}}
46+
{{- define "deployment-tracker.selectorLabels" -}}
47+
app.kubernetes.io/name: {{ include "deployment-tracker.name" . }}
48+
app.kubernetes.io/instance: {{ .Release.Name }}
49+
{{- end }}
50+
51+
{{/*
52+
Create the name of the service account to use.
53+
*/}}
54+
{{- define "deployment-tracker.serviceAccountName" -}}
55+
{{- if .Values.serviceAccount.create }}
56+
{{- default (include "deployment-tracker.fullname" .) .Values.serviceAccount.name }}
57+
{{- else }}
58+
{{- required "serviceAccount.name must be set when serviceAccount.create is false" .Values.serviceAccount.name }}
59+
{{- end }}
60+
{{- end }}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
apiVersion: rbac.authorization.k8s.io/v1
2+
kind: ClusterRole
3+
metadata:
4+
name: {{ include "deployment-tracker.fullname" . }}
5+
labels:
6+
{{- include "deployment-tracker.labels" . | nindent 4 }}
7+
rules:
8+
- apiGroups:
9+
- ""
10+
resources:
11+
- pods
12+
verbs:
13+
- get
14+
- list
15+
- watch
16+
- apiGroups:
17+
- apps
18+
resources:
19+
- deployments
20+
verbs:
21+
- get
22+
- apiGroups:
23+
- apps
24+
resources:
25+
- replicasets
26+
verbs:
27+
- get
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
apiVersion: rbac.authorization.k8s.io/v1
2+
kind: ClusterRoleBinding
3+
metadata:
4+
name: {{ include "deployment-tracker.fullname" . }}
5+
labels:
6+
{{- include "deployment-tracker.labels" . | nindent 4 }}
7+
roleRef:
8+
apiGroup: rbac.authorization.k8s.io
9+
kind: ClusterRole
10+
name: {{ include "deployment-tracker.fullname" . }}
11+
subjects:
12+
- kind: ServiceAccount
13+
name: {{ include "deployment-tracker.serviceAccountName" . }}
14+
namespace: {{ .Release.Namespace }}

0 commit comments

Comments
 (0)