Skip to content

Commit c9c889c

Browse files
authored
Add helm chart with debug capabilities and values schema
1 parent 1294694 commit c9c889c

19 files changed

+943
-3
lines changed

.github/workflows/_helm.yml

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
name: Package helm charts
2+
3+
on:
4+
workflow_call:
5+
6+
env:
7+
HELM_VERSION_TO_INSTALL: 3.14.3
8+
9+
jobs:
10+
package-helm-charts:
11+
name: Package and Push Helm Chart
12+
runs-on: ubuntu-latest
13+
steps:
14+
- name: Checkout
15+
uses: actions/checkout@v4
16+
with:
17+
fetch-depth: 0
18+
19+
- name: Install helm
20+
uses: Azure/setup-helm@v3
21+
with:
22+
version: ${{ env.HELM_VERSION_TO_INSTALL }}
23+
24+
# Check that alpha/beta versions have the form X.Y.Z-alpha.A requried by Helm.
25+
# An early check saves waiting for the entire build before finding a problem.
26+
- name: Check helm version tag
27+
if: ${{ github.ref_type == 'tag' }}
28+
env:
29+
VERSION: "${{ github.ref_name }}"
30+
run: |
31+
if [[ "${VERSION}" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-alpha|-beta|-rc).*?$ ]]; then
32+
echo "Valid version format: ${VERSION}"
33+
else
34+
echo "Invalid version: ${VERSION}. Expected: X.Y.Z or X.Y.Z-beta.1 or X.Y.Z-alpha.1"
35+
exit 1
36+
fi
37+
38+
- name: Package helm charts
39+
env:
40+
VERSION: "${{ github.ref_type == 'tag' && github.ref_name || '0.0.0' }}"
41+
run: |
42+
set -xe
43+
44+
mkdir -p charts
45+
for i in $(find Charts -type d -maxdepth 1 -mindepth 1); do
46+
if [[ ${i} =~ ^.*-ioc$ ]]; then
47+
echo "Skipping IOC schema chart: ${i}"
48+
continue
49+
fi
50+
echo "Packaging chart: ${i}"
51+
helm package -u --app-version ${VERSION} --version ${VERSION} ${i}
52+
mv $(basename ${i})-*.tgz charts/
53+
done
54+
55+
- name: Upload helm chart values schemas
56+
uses: actions/upload-artifact@v4
57+
with:
58+
name: helm-chart-schemas
59+
path: schemas/*
60+
61+
- name: Push tagged helm chart to registry
62+
# TODO - switch to using https://github.com/helm/chart-releaser-action of maybe the docker action?
63+
if: ${{ github.ref_type == 'tag' }}
64+
run: |
65+
set -x
66+
67+
echo "${{ secrets.GITHUB_TOKEN }}" | helm registry login ghcr.io/${{ github.repository_owner }} --username ${{ github.repository_owner }} --password-stdin
68+
REGISTRY=oci://ghcr.io/${{github.repository_owner }}/charts
69+
for i in charts/*.tgz; do
70+
helm push "${i}" ${REGISTRY,,}
71+
done

.github/workflows/_tox.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,8 @@ jobs:
1818
- name: Install python packages
1919
uses: ./.github/actions/install_requirements
2020

21+
- name: Install helm plugins
22+
run: helm plugin install https://github.com/losisin/helm-values-schema-json.git
23+
2124
- name: Run tox
2225
run: tox -e ${{ inputs.tox }}

.github/workflows/ci.yml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,16 +44,22 @@ jobs:
4444
if: needs.check.outputs.branch-pr == ''
4545
uses: ./.github/workflows/_dist.yml
4646

47+
helm:
48+
uses: ./.github/workflows/_helm.yml
49+
permissions:
50+
contents: read
51+
packages: write
52+
4753
pypi:
4854
if: github.ref_type == 'tag'
49-
needs: dist
55+
needs: [helm, dist]
5056
uses: ./.github/workflows/_pypi.yml
5157
permissions:
5258
id-token: write
5359

5460
release:
5561
if: github.ref_type == 'tag'
56-
needs: [dist, docs]
62+
needs: [dist, docs, helm]
5763
uses: ./.github/workflows/_release.yml
5864
permissions:
5965
contents: write

.pre-commit-config.yaml

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
repos:
22
- repo: https://github.com/pre-commit/pre-commit-hooks
3-
rev: v4.5.0
3+
rev: v5.0.0
44
hooks:
55
- id: check-added-large-files
66
- id: check-yaml
7+
exclude: ^Charts/
78
- id: check-merge-conflict
89
- id: end-of-file-fixer
910

@@ -22,3 +23,11 @@ repos:
2223
entry: ruff format --force-exclude
2324
types: [python]
2425
require_serial: true
26+
27+
- repo: https://github.com/losisin/helm-values-schema-json
28+
rev: v2.2.1
29+
hooks:
30+
- id: helm-schema
31+
args:
32+
- --config
33+
- Charts/fastcs/.schema.config.yaml

Charts/README.md

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# Charts
2+
3+
This directory contains Helm charts for deploying FastCS services.
4+
5+
## Github Actions
6+
7+
This folder works in tandem with [_helm.yml](../.github/workflows/_helm.yml) github actions workflow which:
8+
9+
- Validates the stricter form of SemVer tag that helm requires.
10+
- Finds all subfolders in the `Charts` directory and packages them as Helm charts.
11+
- Publishes the packaged charts to ghcr.io/${{github.repository_owner }}/charts/CHART_NAME
12+
- Uploads the contents of /schemas to artifacts (meaning they will be published to the release)
13+
14+
This standalone Helm related workflow is independent of the rest of the workflows except that the _pypi workflow has _helm added to its `needs` in `ci.yml`, making sure we only publish to pypi with valid SemVer tags.
15+
16+
## Schema Generation
17+
18+
Schema generation for charts' `values.yaml` is handled by [helm-values-schema-json](https://github.com/losisin/helm-values-schema-json). Which is in turn controlled by annotations in the default [values.yaml](fastcs/values.yaml) file.
19+
20+
The generated schema file will be called `values.schema.json` and will be placed in the same directory as the `values.yaml` file and commited to the repo. This is done automatically by a [pre-commit hook](https://github.com/DiamondLightSource/FastCS/blob/8232393b38cc8e0eee00680e95c2ce06e7983ba6/.pre-commit-config.yaml#L27-L33). Therefore, when developing charts you can update schemas with:
21+
22+
```bash
23+
git add . ; pre-commit
24+
# or
25+
pre-commit run --all-files
26+
```
27+
28+
29+
Note that this standard name for the schema file means that it is packaged up with the helm chart and available for schema checks in ArgoCD for example.
30+
31+
## `schemas` folder
32+
33+
The schemas folder allows us to declare the schemas we want to publish to the release.
34+
35+
It should contain:
36+
37+
- A symlink to each of the `values.schema.json` files in the subfolders of `Charts`. The symlink should have a unique name, e.g. `fastcs-values.schema.json`, thus allowing multiple schemas to be published per repo.
38+
- A service schema file which references the above and can be used to validate `values.yaml` in epics-containers services repos, where the these charts will be used as sub-charts. e.g. [fastcs-service.schema.json](../schemas/fastcs-service.schema.json)
39+
40+
The service schema files are hand coded as they are extremely simple and unlikely to change.
41+
42+
## Debuging/Development In-Cluster
43+
44+
The `fastcs` helm chart has two variables to enable debugging/development in-cluster:
45+
46+
- `editable`: When true:
47+
- a PVC is created.
48+
- The debug version of the container image is referenced.
49+
- The contents of /workspaces and /venv are copied into the PVC.
50+
- The venv from the debug image is an editable install of the project source code in /workspaces.
51+
- The PVC folders are mounted over the corresponding folders in the container.
52+
- `autostart`:
53+
- When false, the container starts with PID 1 as sleep infinity.
54+
- When true, the container starts with its normal entrypoint.
55+
56+
In combination these flags can be used to debug or develop in-cluster.
57+
58+
These features will be accessed via `ec`. See https://github.com/epics-containers/edge-containers-cli/issues/207
59+
60+
This script will:
61+
62+
- Inspect the values of `editable` and `autostart` in the `values.yaml` file of the specified IOC (TODO: at present it uses the p47-services source code to do so but this should be determined from the cluster in future).
63+
- Port forward the debugpy port (5678) from the pod to localhost.
64+
- If editable is true, it will mount the PVC locally using pv-mounter and open VSCode to the /workspaces/xxx folder.
65+
- If autostart is false, it will exec into the container and launch debugpy to run the main program.
66+
- If autostart is true, it will exec into the container and attach debugpy to PID 1.
67+
68+
This then allows you to attach VSCode to debugpy in the cluster container and if 'editable' is true, edit the source code in VSCode and have the changes reflected.
69+
70+
To attach to debugpy the following launch.json configuration is supplied in the [fastcs-example project](https://github.com/DiamondLightSource/fastcs-example/blob/77daed5f5a2bd01ab4c0e1d8c812e8754b254674/.vscode/launch.json#L7-L22). (this will also go in python-copier-template in future).

Charts/fastcs/.helmignore

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Patterns to ignore when building packages.
2+
# This supports shell glob matching, relative path matching, and
3+
# negation (prefixed with !). Only one pattern per line.
4+
.DS_Store
5+
# Common VCS dirs
6+
.git/
7+
.gitignore
8+
.bzr/
9+
.bzrignore
10+
.hg/
11+
.hgignore
12+
.svn/
13+
# Common backup files
14+
*.swp
15+
*.bak
16+
*.tmp
17+
*.orig
18+
*~
19+
# Various IDEs
20+
.project
21+
.idea/
22+
*.tmproj
23+
.vscode/

Charts/fastcs/.schema.config.yaml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# .schema.yaml
2+
3+
# Define input, output and source for $refs relative to repository root for pre-commit
4+
values:
5+
- Charts/fastcs/values.yaml
6+
- Charts/fastcs/extra.values.yaml
7+
8+
output: Charts/fastcs/values.schema.json
9+
10+
# bundle up references (don't do this as K8S refs are 500kb+)
11+
bundleRoot: Charts
12+
bundle: false
13+
14+
# Include comments for the helm-docs plugin into the schema, to allow e.g. documentation in VSCode
15+
useHelmDocs: false
16+
17+
# Allow additional properties for eg. initResources, different types of volumes/volumeMounts
18+
noAdditionalProperties: false
19+
20+
schemaRoot:
21+
title: FastCS Helm chart
22+
description: Helm chart for deploying a FastCS application
23+
# No additional properties in schema root for tighter protection:
24+
additionalProperties: false
25+
26+
k8sSchemaVersion: v1.33.3

Charts/fastcs/Chart.yaml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
apiVersion: v2
2+
name: fastcs
3+
description: A Helm chart for FastCS Applications
4+
5+
# A chart can be either an 'application' or a 'library' chart.
6+
#
7+
# Application charts are a collection of templates that can be packaged into versioned archives
8+
# to be deployed.
9+
#
10+
# Library charts provide useful utilities or functions for the chart developer. They're included as
11+
# a dependency of application charts to inject those utilities and functions into the rendering
12+
# pipeline. Library charts do not define any templates and therefore cannot be deployed.
13+
type: application
14+
15+
# This is the chart version. This version number should be incremented each time you make changes
16+
# to the chart and its templates, including the app version.
17+
# Versions are expected to follow Semantic Versioning (https://semver.org/)
18+
version: 0.1.0
19+
20+
# This is the version number of the application being deployed. This version number should be
21+
# incremented each time you make changes to the application. Versions are not expected to
22+
# follow Semantic Versioning. They should reflect the version the application is using.
23+
# It is recommended to use it with quotes.
24+
appVersion: "1.16.0"

Charts/fastcs/extra.values.yaml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
################################################################################
2+
# values for lists of custom objects from values.yaml for schema generation
3+
################################################################################
4+
5+
# @schema description: Add arbitrary containers to the pod
6+
extraContainers:
7+
# @schema: description: A name for the additional container
8+
- name: container_name
9+
# @schema $ref: $k8s/container.json#/properties/image
10+
image: image_uri
11+
# @schema $ref: $k8s/container.json#/properties/command
12+
command:
13+
- command
14+
- arg1
15+
- arg2
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
{{/*
2+
Expand the name of the chart.
3+
*/}}
4+
{{- define "fastcs.name" -}}
5+
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
6+
{{- end }}
7+
8+
{{/*
9+
Create a default fully qualified app name.
10+
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
11+
If release name contains chart name it will be used as a full name.
12+
*/}}
13+
{{- define "fastcs.fullname" -}}
14+
{{- if .Values.fullnameOverride }}
15+
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
16+
{{- else }}
17+
{{- $name := default .Chart.Name .Values.nameOverride }}
18+
{{- if contains $name .Release.Name }}
19+
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
20+
{{- else }}
21+
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
22+
{{- end }}
23+
{{- end }}
24+
{{- end }}
25+
26+
{{/*
27+
Create chart name and version as used by the chart label.
28+
*/}}
29+
{{- define "fastcs.chart" -}}
30+
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
31+
{{- end }}
32+
33+
{{/*
34+
Common labels
35+
*/}}
36+
{{- define "fastcs.labels" -}}
37+
helm.sh/chart: {{ include "fastcs.chart" . }}
38+
{{ include "fastcs.selectorLabels" . }}
39+
{{- if .Chart.AppVersion }}
40+
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
41+
{{- end }}
42+
app.kubernetes.io/managed-by: {{ .Release.Service }}
43+
{{- end }}
44+
45+
{{/*
46+
Selector labels
47+
*/}}
48+
{{- define "fastcs.selectorLabels" -}}
49+
app.kubernetes.io/name: {{ include "fastcs.name" . }}
50+
app.kubernetes.io/instance: {{ .Release.Name }}
51+
{{- end }}

0 commit comments

Comments
 (0)