Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 71 additions & 0 deletions .github/workflows/_helm.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
name: Package helm charts

on:
workflow_call:

env:
HELM_VERSION_TO_INSTALL: 3.14.3

jobs:
package-helm-charts:
name: Package and Push Helm Chart
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Install helm
uses: Azure/setup-helm@v3
with:
version: ${{ env.HELM_VERSION_TO_INSTALL }}

# Check that alpha/beta versions have the form X.Y.Z-alpha.A requried by Helm.
# An early check saves waiting for the entire build before finding a problem.
- name: Check helm version tag
if: ${{ github.ref_type == 'tag' }}
env:
VERSION: "${{ github.ref_name }}"
run: |
if [[ "${VERSION}" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-alpha|-beta|-rc).*?$ ]]; then
echo "Valid version format: ${VERSION}"
else
echo "Invalid version: ${VERSION}. Expected: X.Y.Z or X.Y.Z-beta.1 or X.Y.Z-alpha.1"
exit 1
fi

- name: Package helm charts
env:
VERSION: "${{ github.ref_type == 'tag' && github.ref_name || '0.0.0' }}"
run: |
set -xe

mkdir -p charts
for i in $(find Charts -type d -maxdepth 1 -mindepth 1); do
if [[ ${i} =~ ^.*-ioc$ ]]; then
echo "Skipping IOC schema chart: ${i}"
continue
fi
echo "Packaging chart: ${i}"
helm package -u --app-version ${VERSION} --version ${VERSION} ${i}
mv $(basename ${i})-*.tgz charts/
done

- name: Upload helm chart values schemas
uses: actions/upload-artifact@v4
with:
name: helm-chart-schemas
path: schemas/*

- name: Push tagged helm chart to registry
# TODO - switch to using https://github.com/helm/chart-releaser-action of maybe the docker action?
if: ${{ github.ref_type == 'tag' }}
run: |
set -x

echo "${{ secrets.GITHUB_TOKEN }}" | helm registry login ghcr.io/${{ github.repository_owner }} --username ${{ github.repository_owner }} --password-stdin
REGISTRY=oci://ghcr.io/${{github.repository_owner }}/charts
for i in charts/*.tgz; do
helm push "${i}" ${REGISTRY,,}
done
3 changes: 3 additions & 0 deletions .github/workflows/_tox.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,8 @@ jobs:
- name: Install python packages
uses: ./.github/actions/install_requirements

- name: Install helm plugins
run: helm plugin install https://github.com/losisin/helm-values-schema-json.git

- name: Run tox
run: tox -e ${{ inputs.tox }}
10 changes: 8 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,16 +44,22 @@ jobs:
if: needs.check.outputs.branch-pr == ''
uses: ./.github/workflows/_dist.yml

helm:
uses: ./.github/workflows/_helm.yml
permissions:
contents: read
packages: write

pypi:
if: github.ref_type == 'tag'
needs: dist
needs: [helm, dist]
uses: ./.github/workflows/_pypi.yml
permissions:
id-token: write

release:
if: github.ref_type == 'tag'
needs: [dist, docs]
needs: [dist, docs, helm]
uses: ./.github/workflows/_release.yml
permissions:
contents: write
11 changes: 10 additions & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
rev: v5.0.0
hooks:
- id: check-added-large-files
- id: check-yaml
exclude: ^Charts/
- id: check-merge-conflict
- id: end-of-file-fixer

Expand All @@ -22,3 +23,11 @@ repos:
entry: ruff format --force-exclude
types: [python]
require_serial: true

- repo: https://github.com/losisin/helm-values-schema-json
rev: v2.2.1
hooks:
- id: helm-schema
args:
- --config
- Charts/fastcs/.schema.config.yaml
70 changes: 70 additions & 0 deletions Charts/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Charts

This directory contains Helm charts for deploying FastCS services.

## Github Actions

This folder works in tandem with [_helm.yml](../.github/workflows/_helm.yml) github actions workflow which:

- Validates the stricter form of SemVer tag that helm requires.
- Finds all subfolders in the `Charts` directory and packages them as Helm charts.
- Publishes the packaged charts to ghcr.io/${{github.repository_owner }}/charts/CHART_NAME
- Uploads the contents of /schemas to artifacts (meaning they will be published to the release)

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.

## Schema Generation

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.

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:

```bash
git add . ; pre-commit
# or
pre-commit run --all-files
```


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.

## `schemas` folder

The schemas folder allows us to declare the schemas we want to publish to the release.

It should contain:

- 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.
- 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)

The service schema files are hand coded as they are extremely simple and unlikely to change.

## Debuging/Development In-Cluster

The `fastcs` helm chart has two variables to enable debugging/development in-cluster:

- `editable`: When true:
- a PVC is created.
- The debug version of the container image is referenced.
- The contents of /workspaces and /venv are copied into the PVC.
- The venv from the debug image is an editable install of the project source code in /workspaces.
- The PVC folders are mounted over the corresponding folders in the container.
- `autostart`:
- When false, the container starts with PID 1 as sleep infinity.
- When true, the container starts with its normal entrypoint.

In combination these flags can be used to debug or develop in-cluster.

These features will be accessed via `ec`. See https://github.com/epics-containers/edge-containers-cli/issues/207

This script will:

- 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).
- Port forward the debugpy port (5678) from the pod to localhost.
- If editable is true, it will mount the PVC locally using pv-mounter and open VSCode to the /workspaces/xxx folder.
- If autostart is false, it will exec into the container and launch debugpy to run the main program.
- If autostart is true, it will exec into the container and attach debugpy to PID 1.

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.

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).
23 changes: 23 additions & 0 deletions Charts/fastcs/.helmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*.orig
*~
# Various IDEs
.project
.idea/
*.tmproj
.vscode/
26 changes: 26 additions & 0 deletions Charts/fastcs/.schema.config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# .schema.yaml

# Define input, output and source for $refs relative to repository root for pre-commit
values:
- Charts/fastcs/values.yaml
- Charts/fastcs/extra.values.yaml

output: Charts/fastcs/values.schema.json

# bundle up references (don't do this as K8S refs are 500kb+)
bundleRoot: Charts
bundle: false

# Include comments for the helm-docs plugin into the schema, to allow e.g. documentation in VSCode
useHelmDocs: false

# Allow additional properties for eg. initResources, different types of volumes/volumeMounts
noAdditionalProperties: false

schemaRoot:
title: FastCS Helm chart
description: Helm chart for deploying a FastCS application
# No additional properties in schema root for tighter protection:
additionalProperties: false

k8sSchemaVersion: v1.33.3
24 changes: 24 additions & 0 deletions Charts/fastcs/Chart.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
apiVersion: v2
name: fastcs
description: A Helm chart for FastCS Applications

# A chart can be either an 'application' or a 'library' chart.
#
# Application charts are a collection of templates that can be packaged into versioned archives
# to be deployed.
#
# Library charts provide useful utilities or functions for the chart developer. They're included as
# a dependency of application charts to inject those utilities and functions into the rendering
# pipeline. Library charts do not define any templates and therefore cannot be deployed.
type: application

# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 0.1.0

# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application. Versions are not expected to
# follow Semantic Versioning. They should reflect the version the application is using.
# It is recommended to use it with quotes.
appVersion: "1.16.0"
15 changes: 15 additions & 0 deletions Charts/fastcs/extra.values.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
################################################################################
# values for lists of custom objects from values.yaml for schema generation
################################################################################

# @schema description: Add arbitrary containers to the pod
extraContainers:
# @schema: description: A name for the additional container
- name: container_name
# @schema $ref: $k8s/container.json#/properties/image
image: image_uri
# @schema $ref: $k8s/container.json#/properties/command
command:
- command
- arg1
- arg2
51 changes: 51 additions & 0 deletions Charts/fastcs/templates/_helpers.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
{{/*
Expand the name of the chart.
*/}}
{{- define "fastcs.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}

{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
If release name contains chart name it will be used as a full name.
*/}}
{{- define "fastcs.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}

{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "fastcs.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}

{{/*
Common labels
*/}}
{{- define "fastcs.labels" -}}
helm.sh/chart: {{ include "fastcs.chart" . }}
{{ include "fastcs.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}

{{/*
Selector labels
*/}}
{{- define "fastcs.selectorLabels" -}}
app.kubernetes.io/name: {{ include "fastcs.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
Loading
Loading