From 28709415eb4b1daf232a648cfd7871147f601dc3 Mon Sep 17 00:00:00 2001 From: Jared Lewis Date: Sat, 21 Feb 2026 15:24:28 +1100 Subject: [PATCH 01/10] feat(helm): add API component and Gateway API HTTPRoute support Add ref-app API deployment to the Helm chart with service, ingress, and environment configuration. Add Gateway API HTTPRoute templates for both API and Flower as an alternative to traditional Ingress resources. Update docker-compose with ref-app service, restructure per-component ingress templates, and update documentation. --- README.md | 8 +- docker/docker-compose.yaml | 14 +++ helm/README.md | 130 +++++++++++++++++++---- helm/ci/gh-actions-values.yaml | 13 ++- helm/local-test-values.yaml | 18 +++- helm/templates/api/httproute.yaml | 33 ++++++ helm/templates/api/ingress.yaml | 35 ++++++ helm/templates/flower/httproute.yaml | 33 ++++++ helm/templates/{ => flower}/ingress.yaml | 17 +-- helm/values.yaml | 81 ++++++++++++-- 10 files changed, 338 insertions(+), 44 deletions(-) create mode 100644 helm/templates/api/httproute.yaml create mode 100644 helm/templates/api/ingress.yaml create mode 100644 helm/templates/flower/httproute.yaml rename helm/templates/{ => flower}/ingress.yaml (55%) diff --git a/README.md b/README.md index 61f9527..32f6a30 100644 --- a/README.md +++ b/README.md @@ -23,9 +23,11 @@ The AFT deployment brings together independently versioned packages: | `climate-ref-core` | [Climate-REF/climate-ref](https://github.com/Climate-REF/climate-ref) | Core library with base classes and interfaces | | `climate-ref` | [Climate-REF/climate-ref](https://github.com/Climate-REF/climate-ref) | Main application, CLI, database, solver | | `climate-ref-celery` | [Climate-REF/climate-ref](https://github.com/Climate-REF/climate-ref) | Celery executor for distributed execution | -| `climate-ref-esmvaltool` | [Climate-REF/climate-ref-esmvaltool](https://github.com/Climate-REF/climate-ref-esmvaltool) | ESMValTool diagnostic provider | -| `climate-ref-pmp` | [Climate-REF/climate-ref-pmp](https://github.com/Climate-REF/climate-ref-pmp) | PCMDI Metrics Package diagnostic provider | -| `climate-ref-ilamb` | [Climate-REF/climate-ref-ilamb](https://github.com/Climate-REF/climate-ref-ilamb) | ILAMB diagnostic provider | +| `climate-ref-esmvaltool` | [Climate-REF/climate-ref](https://github.com/Climate-REF/climate-ref) | ESMValTool diagnostic provider | +| `climate-ref-pmp` | [Climate-REF/climate-ref](https://github.com/Climate-REF/climate-ref) | PCMDI Metrics Package diagnostic provider | +| `climate-ref-ilamb` | [Climate-REF/climate-ref](https://github.com/Climate-REF/climate-ref) | ILAMB diagnostic provider | + +Note: we intend to split the providers out into their own repositories in the coming weeks. ## Versioning diff --git a/docker/docker-compose.yaml b/docker/docker-compose.yaml index 8b074ae..8de101f 100644 --- a/docker/docker-compose.yaml +++ b/docker/docker-compose.yaml @@ -26,6 +26,20 @@ services: ports: - "5432:5432" + ref-app: + image: ghcr.io/climate-ref/ref-app:latest + restart: always + depends_on: + - postgres + - redis + environment: + - REF_DATABASE_URL=postgresql://postgres:example@postgres:5432/postgres + - ENVIRONMENT=local + - SECRET_KEY=local-dev-secret + - REF_CONFIGURATION=/app/.ref + ports: + - "8000:8000" + flower: image: mher/flower:2.0.1 restart: always diff --git a/helm/README.md b/helm/README.md index 405e3d7..573af41 100644 --- a/helm/README.md +++ b/helm/README.md @@ -1,12 +1,17 @@ # Climate REF Helm Chart A Helm chart for deploying the Climate REF (Rapid Evaluation Framework) on Kubernetes. -This chart deploys a distributed task execution system using Celery workers for running climate diagnostics. +This chart deploys the full stack: + +- the ref-app API/website +- celery monitoring UI +- distributed Celery workers for running climate diagnostics. ## Overview The chart deploys: +- **ref-app (API)**: FastAPI application serving the REST API and static React frontend - **Dragonfly** (Redis-compatible): Message broker and result backend for Celery - **Flower**: Web UI for monitoring Celery tasks - **Provider Workers**: Celery workers for each diagnostic provider (orchestrator, esmvaltool, pmp, ilamb, example) @@ -16,6 +21,7 @@ The chart deploys: - Kubernetes 1.19+ - Helm 3.0+ - Access to container images: + - `ghcr.io/climate-ref/ref-app` - `ghcr.io/climate-ref/climate-ref` - `mher/flower` @@ -57,9 +63,12 @@ helm dependency update ```mermaid flowchart TB - ingress[Ingress
optional] + apiIngress[API Ingress
optional] + flowerIngress[Flower Ingress
optional] + api[ref-app
API + frontend] flower[Flower
monitoring] dragonfly[Dragonfly
Redis broker] + db[(PostgreSQL
external)] subgraph workers[Provider Workers] orchestrator[Orchestrator
Worker] @@ -70,7 +79,9 @@ flowchart TB pvcs[(PVCs
shared data storage)] - ingress --> flower + apiIngress --> api + flowerIngress --> flower + api --> db flower --> dragonfly dragonfly --> orchestrator dragonfly --> esmvaltool @@ -104,15 +115,55 @@ Each provider worker listens to a specific Celery queue: | `nameOverride` | Override chart name | `""` | | `fullnameOverride` | Override full release name | `""` | -### Ingress Configuration - -| Parameter | Description | Default | -| --------------------- | ------------------- | ------- | -| `ingress.enabled` | Enable ingress | `false` | -| `ingress.host` | Ingress hostname | `""` | -| `ingress.className` | Ingress class name | `""` | -| `ingress.annotations` | Ingress annotations | `{}` | -| `ingress.labels` | Ingress labels | `{}` | +### API Configuration + +The `api` section configures the ref-app (FastAPI + React frontend). + +| Parameter | Description | Default | +| --------------------------------- | --------------------------- | --------------------------------- | +| `api.enabled` | Enable the API deployment | `true` | +| `api.replicaCount` | Number of API replicas | `1` | +| `api.image.repository` | API image repository | `ghcr.io/climate-ref/ref-app` | +| `api.image.tag` | API image tag | `latest` | +| `api.image.pullPolicy` | Image pull policy | `IfNotPresent` | +| `api.service.type` | Service type | `ClusterIP` | +| `api.service.port` | Service port | `80` | +| `api.resources` | Resource requests/limits | `{}` | +| `api.nodeSelector` | Node selector | `{}` | +| `api.tolerations` | Tolerations | `[]` | +| `api.affinity` | Affinity rules | `{}` | + +#### API Environment Variables + +Set via `api.env`: + +| Variable | Description | Default | +| ------------------- | ------------------------------ | --------------------------------- | +| `ENVIRONMENT` | Runtime environment | `production` | +| `LOG_LEVEL` | Logging level | `INFO` | +| `SECRET_KEY` | Application secret key | `changethis` (override in prod!) | +| `REF_DATABASE_URL` | Database connection string | `""` (required) | +| `REF_CONFIGURATION` | Path to REF configuration | `/app/.ref` | + +#### API Ingress + +| Parameter | Description | Default | +| -------------------------- | ------------------- | ------- | +| `api.ingress.enabled` | Enable API ingress | `false` | +| `api.ingress.host` | Ingress hostname | `""` | +| `api.ingress.className` | Ingress class name | `""` | +| `api.ingress.annotations` | Ingress annotations | `{}` | +| `api.ingress.labels` | Ingress labels | `{}` | + +#### API HTTPRoute (Gateway API) + +| Parameter | Description | Default | +| ---------------------------- | ---------------------------- | ------- | +| `api.httpRoute.enabled` | Enable API HTTPRoute | `false` | +| `api.httpRoute.hostnames` | List of hostnames to match | `[]` | +| `api.httpRoute.parentRefs` | Gateway parent references | `[]` | +| `api.httpRoute.annotations` | HTTPRoute annotations | `{}` | +| `api.httpRoute.labels` | HTTPRoute labels | `{}` | ### Dragonfly (Redis) Configuration @@ -139,6 +190,26 @@ See [Dragonfly Helm chart](https://github.com/dragonflydb/dragonfly/tree/main/co | `flower.tolerations` | Tolerations | `[]` | | `flower.affinity` | Affinity rules | `{}` | +#### Flower Ingress + +| Parameter | Description | Default | +| ----------------------------- | ----------------------- | ------- | +| `flower.ingress.enabled` | Enable Flower ingress | `false` | +| `flower.ingress.host` | Ingress hostname | `""` | +| `flower.ingress.className` | Ingress class name | `""` | +| `flower.ingress.annotations` | Ingress annotations | `{}` | +| `flower.ingress.labels` | Ingress labels | `{}` | + +#### Flower HTTPRoute (Gateway API) + +| Parameter | Description | Default | +| ------------------------------- | ---------------------------- | ------- | +| `flower.httpRoute.enabled` | Enable Flower HTTPRoute | `false` | +| `flower.httpRoute.hostnames` | List of hostnames to match | `[]` | +| `flower.httpRoute.parentRefs` | Gateway parent references | `[]` | +| `flower.httpRoute.annotations` | HTTPRoute annotations | `{}` | +| `flower.httpRoute.labels` | HTTPRoute labels | `{}` | + ### Provider Defaults These defaults apply to all providers unless overridden per-provider. @@ -279,17 +350,32 @@ kubectl port-forward svc/ref-flower 5555:5555 Open in your browser. +### Accessing the API + +Access the ref-app API: + +```bash +kubectl port-forward svc/ref-api 8000:80 +``` + +Open in your browser, or check the health endpoint: + +```bash +curl http://localhost:8000/api/v1/utils/health-check/ +``` + ## Resources Created The chart creates the following Kubernetes resources: -| Resource | Count | Description | -| ----------------------- | --------------- | -------------------------------- | -| Deployment | 1 + N providers | Flower + one per provider | -| Service | 2 | Flower + Dragonfly | -| ServiceAccount | 1 + N providers | Flower + one per provider | -| Secret | 1 + N providers | Environment config per component | -| ServiceMonitor | 0-1 | Optional Prometheus integration | -| HorizontalPodAutoscaler | 0-N | Optional per-provider | -| PersistentVolumeClaim | N | As configured in createPVCs | -| Ingress | 0-1 | Optional | +| Resource | Count | Description | +| ----------------------- | --------------- | ---------------------------------- | +| Deployment | 2 + N providers | API + Flower + one per provider | +| Service | 3 | API + Flower + Dragonfly | +| ServiceAccount | 2 + N providers | API + Flower + one per provider | +| Secret | 2 + N providers | Environment config per component | +| ServiceMonitor | 0-1 | Optional Prometheus integration | +| HorizontalPodAutoscaler | 0-N | Optional per-provider | +| PersistentVolumeClaim | N | As configured in createPVCs | +| Ingress | 0-2 | Optional API and/or Flower ingress | +| HTTPRoute | 0-2 | Optional Gateway API routes | diff --git a/helm/ci/gh-actions-values.yaml b/helm/ci/gh-actions-values.yaml index c13a40a..d7318ea 100644 --- a/helm/ci/gh-actions-values.yaml +++ b/helm/ci/gh-actions-values.yaml @@ -1,5 +1,14 @@ -ingress: - host: Climate-ref.test +api: + env: + SECRET_KEY: ci-test-secret + REF_DATABASE_URL: sqlite:////tmp/ref.db + volumes: + - name: tmp + emptyDir: {} + volumeMounts: + - name: tmp + mountPath: /tmp + readOnly: false service: type: NodePort diff --git a/helm/local-test-values.yaml b/helm/local-test-values.yaml index 8809004..44ceebe 100644 --- a/helm/local-test-values.yaml +++ b/helm/local-test-values.yaml @@ -4,7 +4,7 @@ defaults: image: repository: ghcr.io/climate-ref/climate-ref pullPolicy: IfNotPresent - tag: pr-492 # Using current PR tag + tag: latest podSecurityContext: runAsUser: 1000 @@ -52,3 +52,19 @@ providers: pmp: {} ilamb: {} example: {} + +api: + image: + tag: latest + env: + ENVIRONMENT: local + SECRET_KEY: local-test-secret + REF_DATABASE_URL: sqlite:////tmp/ref.db + REF_CONFIGURATION: /app/.ref + volumes: + - name: tmp + emptyDir: {} + volumeMounts: + - name: tmp + mountPath: /tmp + readOnly: false diff --git a/helm/templates/api/httproute.yaml b/helm/templates/api/httproute.yaml new file mode 100644 index 0000000..6fec81e --- /dev/null +++ b/helm/templates/api/httproute.yaml @@ -0,0 +1,33 @@ +{{- if and .Values.api.enabled .Values.api.httpRoute.enabled -}} +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: {{ include "ref.fullname" . }}-api + labels: + app.kubernetes.io/component: api + {{- include "ref.labels" . | nindent 4 }} + {{- with .Values.api.httpRoute.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.api.httpRoute.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- with .Values.api.httpRoute.parentRefs }} + parentRefs: + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.api.httpRoute.hostnames }} + hostnames: + {{- toYaml . | nindent 4 }} + {{- end }} + rules: + - matches: + - path: + type: PathPrefix + value: / + backendRefs: + - name: {{ include "ref.fullname" . }}-api + port: {{ .Values.api.service.port }} +{{- end }} diff --git a/helm/templates/api/ingress.yaml b/helm/templates/api/ingress.yaml new file mode 100644 index 0000000..b3f1058 --- /dev/null +++ b/helm/templates/api/ingress.yaml @@ -0,0 +1,35 @@ +{{- if and .Values.api.enabled .Values.api.ingress.enabled -}} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ include "ref.fullname" . }}-api + labels: + app.kubernetes.io/component: api + {{- include "ref.labels" . | nindent 4 }} + {{- with .Values.api.ingress.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.api.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- with .Values.api.ingress.className }} + ingressClassName: {{ . }} + {{- end }} + tls: + - hosts: + - {{ .Values.api.ingress.host | quote }} + secretName: {{ include "ref.fullname" . }}-api-ingress-cert + rules: + - host: {{ .Values.api.ingress.host | quote }} + http: + paths: + - path: / + pathType: ImplementationSpecific + backend: + service: + name: {{ include "ref.fullname" . }}-api + port: + number: {{ .Values.api.service.port }} +{{- end }} diff --git a/helm/templates/flower/httproute.yaml b/helm/templates/flower/httproute.yaml new file mode 100644 index 0000000..6f194a0 --- /dev/null +++ b/helm/templates/flower/httproute.yaml @@ -0,0 +1,33 @@ +{{- if .Values.flower.httpRoute.enabled -}} +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: {{ include "ref.fullname" . }}-flower + labels: + app.kubernetes.io/component: flower + {{- include "ref.labels" . | nindent 4 }} + {{- with .Values.flower.httpRoute.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.flower.httpRoute.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- with .Values.flower.httpRoute.parentRefs }} + parentRefs: + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.flower.httpRoute.hostnames }} + hostnames: + {{- toYaml . | nindent 4 }} + {{- end }} + rules: + - matches: + - path: + type: PathPrefix + value: / + backendRefs: + - name: {{ include "ref.fullname" . }}-flower + port: {{ .Values.flower.service.port }} +{{- end }} diff --git a/helm/templates/ingress.yaml b/helm/templates/flower/ingress.yaml similarity index 55% rename from helm/templates/ingress.yaml rename to helm/templates/flower/ingress.yaml index 4e87201..fa83e3f 100644 --- a/helm/templates/ingress.yaml +++ b/helm/templates/flower/ingress.yaml @@ -1,27 +1,28 @@ -{{- if .Values.ingress.enabled -}} +{{- if .Values.flower.ingress.enabled -}} apiVersion: networking.k8s.io/v1 kind: Ingress metadata: - name: {{ include "ref.fullname" . }} + name: {{ include "ref.fullname" . }}-flower labels: + app.kubernetes.io/component: flower {{- include "ref.labels" . | nindent 4 }} - {{- with .Values.ingress.labels }} + {{- with .Values.flower.ingress.labels }} {{- toYaml . | nindent 4 }} {{- end }} - {{- with .Values.ingress.annotations }} + {{- with .Values.flower.ingress.annotations }} annotations: {{- toYaml . | nindent 4 }} {{- end }} spec: - {{- with .Values.ingress.className }} + {{- with .Values.flower.ingress.className }} ingressClassName: {{ . }} {{- end }} tls: - hosts: - - {{ .Values.ingress.host | quote }} - secretName: {{ include "ref.fullname" . }}-ingress-cert + - {{ .Values.flower.ingress.host | quote }} + secretName: {{ include "ref.fullname" . }}-flower-ingress-cert rules: - - host: {{ .Values.ingress.host | quote }} + - host: {{ .Values.flower.ingress.host | quote }} http: paths: - path: / diff --git a/helm/values.yaml b/helm/values.yaml index b084e9b..ca09a6f 100644 --- a/helm/values.yaml +++ b/helm/values.yaml @@ -2,14 +2,65 @@ imagePullSecrets: [] nameOverride: "" fullnameOverride: "" -ingress: - enabled: false - host: - className: "" - annotations: {} - # kubernetes.io/ingress.class: nginx - # kubernetes.io/tls-acme: "true" - labels: {} +api: + enabled: true + replicaCount: 1 + + image: + repository: ghcr.io/climate-ref/ref-app + pullPolicy: IfNotPresent + tag: latest + + env: + ENVIRONMENT: production + LOG_LEVEL: INFO + SECRET_KEY: changethis # Must override in production + REF_DATABASE_URL: "" # Required: e.g. postgresql://user:pass@host:5432/db + REF_CONFIGURATION: /app/.ref + + ingress: + enabled: false + host: + className: "" + annotations: {} + labels: {} + + httpRoute: + enabled: false + hostnames: [] + parentRefs: [] + annotations: {} + labels: {} + + serviceAccount: + create: true + automount: false + annotations: {} + name: "" + + podAnnotations: {} + podLabels: {} + + podSecurityContext: {} + + securityContext: + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true + runAsNonRoot: true + + service: + type: ClusterIP + port: 80 + + resources: {} + + volumes: [] + volumeMounts: [] + nodeSelector: {} + tolerations: [] + affinity: {} dragonfly: storage: @@ -20,6 +71,20 @@ flower: CELERY_BROKER_URL: redis://{{ include "dragonfly.fullname" .Subcharts.dragonfly }}:{{ .Values.dragonfly.service.port }} CELERY_RESULT_BACKEND: redis://{{ include "dragonfly.fullname" .Subcharts.dragonfly }}:{{ .Values.dragonfly.service.port }} + ingress: + enabled: false + host: + className: "" + annotations: {} + labels: {} + + httpRoute: + enabled: false + hostnames: [] + parentRefs: [] + annotations: {} + labels: {} + serviceMonitor: enabled: false From 3eebb0b03ecdfc10b81336d16237dc9ca9c80ad3 Mon Sep 17 00:00:00 2001 From: Jared Lewis Date: Sat, 21 Feb 2026 15:32:36 +1100 Subject: [PATCH 02/10] feat(helm): add API deployment, service, secret, and serviceaccount templates Add the core Kubernetes resource templates for the ref-app API component: deployment with health checks and env configuration, ClusterIP service, secret for environment variables, and serviceaccount with configurable automount. --- helm/templates/api/deployment.yaml | 80 ++++++++++++++++++++++++++ helm/templates/api/secret.yaml | 11 ++++ helm/templates/api/service.yaml | 19 ++++++ helm/templates/api/serviceaccount.yaml | 14 +++++ 4 files changed, 124 insertions(+) create mode 100644 helm/templates/api/deployment.yaml create mode 100644 helm/templates/api/secret.yaml create mode 100644 helm/templates/api/service.yaml create mode 100644 helm/templates/api/serviceaccount.yaml diff --git a/helm/templates/api/deployment.yaml b/helm/templates/api/deployment.yaml new file mode 100644 index 0000000..162c035 --- /dev/null +++ b/helm/templates/api/deployment.yaml @@ -0,0 +1,80 @@ +{{- if .Values.api.enabled -}} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "ref.fullname" . }}-api + labels: + app.kubernetes.io/component: api + {{- include "ref.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.api.replicaCount }} + selector: + matchLabels: + app.kubernetes.io/component: api + {{- include "ref.selectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + checksum/config: {{ include (print $.Template.BasePath "/api/secret.yaml") . | sha256sum }} + {{- with .Values.api.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + app.kubernetes.io/component: api + {{- include "ref.labels" . | nindent 8 }} + {{- with .Values.api.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "ref.fullname" . }}-api + {{- with .Values.api.podSecurityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: api + {{- with .Values.api.securityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + image: "{{ .Values.api.image.repository }}:{{ .Values.api.image.tag }}" + imagePullPolicy: {{ .Values.api.image.pullPolicy }} + envFrom: + - secretRef: + name: {{ include "ref.fullname" . }}-api + ports: + - name: http + containerPort: 8000 + readinessProbe: + httpGet: + path: /api/v1/utils/health-check/ + port: http + {{- with .Values.api.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.api.volumeMounts }} + volumeMounts: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.api.volumes }} + volumes: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.api.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.api.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.api.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} diff --git a/helm/templates/api/secret.yaml b/helm/templates/api/secret.yaml new file mode 100644 index 0000000..a3b831f --- /dev/null +++ b/helm/templates/api/secret.yaml @@ -0,0 +1,11 @@ +{{- if .Values.api.enabled -}} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "ref.fullname" . }}-api + labels: + app.kubernetes.io/component: api + {{- include "ref.labels" . | nindent 4 }} +stringData: + {{- tpl (toYaml .Values.api.env) . | nindent 2}} +{{- end }} diff --git a/helm/templates/api/service.yaml b/helm/templates/api/service.yaml new file mode 100644 index 0000000..0452521 --- /dev/null +++ b/helm/templates/api/service.yaml @@ -0,0 +1,19 @@ +{{- if .Values.api.enabled -}} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "ref.fullname" . }}-api + labels: + app.kubernetes.io/component: api + {{- include "ref.labels" . | nindent 4 }} +spec: + type: {{ .Values.api.service.type }} + ports: + - port: {{ .Values.api.service.port }} + targetPort: http + protocol: TCP + name: http + selector: + app.kubernetes.io/component: api + {{- include "ref.selectorLabels" . | nindent 4 }} +{{- end }} diff --git a/helm/templates/api/serviceaccount.yaml b/helm/templates/api/serviceaccount.yaml new file mode 100644 index 0000000..074d043 --- /dev/null +++ b/helm/templates/api/serviceaccount.yaml @@ -0,0 +1,14 @@ +{{- if and .Values.api.enabled .Values.api.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "ref.fullname" . }}-api + labels: + app.kubernetes.io/component: api + {{- include "ref.labels" . | nindent 4 }} + {{- with .Values.api.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +automountServiceAccountToken: {{ .Values.api.serviceAccount.automount }} +{{- end }} From b3ddbf5c8aa64a01e9c3d49194bce6f0a178a0ec Mon Sep 17 00:00:00 2001 From: Jared Lewis Date: Sat, 21 Feb 2026 15:34:45 +1100 Subject: [PATCH 03/10] chore: update API image to climate-ref-frontend and pin to main tag Rename ref-app image to climate-ref-frontend across docker-compose and Helm values. Add platform: linux/amd64 to docker-compose services for cross-platform compatibility. --- docker/docker-compose.yaml | 6 ++++-- helm/values.yaml | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/docker/docker-compose.yaml b/docker/docker-compose.yaml index 8de101f..e5ad9fe 100644 --- a/docker/docker-compose.yaml +++ b/docker/docker-compose.yaml @@ -27,7 +27,8 @@ services: - "5432:5432" ref-app: - image: ghcr.io/climate-ref/ref-app:latest + image: ghcr.io/climate-ref/climate-ref-frontend:main + platform: linux/amd64 restart: always depends_on: - postgres @@ -54,7 +55,8 @@ services: # Base worker to track the executions of async tasks climate-ref: - image: ghcr.io/climate-ref/climate-ref:latest + image: ghcr.io/climate-ref/climate-ref:main + platform: linux/amd64 restart: always depends_on: - postgres diff --git a/helm/values.yaml b/helm/values.yaml index ca09a6f..ee70d0f 100644 --- a/helm/values.yaml +++ b/helm/values.yaml @@ -7,9 +7,9 @@ api: replicaCount: 1 image: - repository: ghcr.io/climate-ref/ref-app + repository: ghcr.io/climate-ref/climate-ref-frontend pullPolicy: IfNotPresent - tag: latest + tag: main env: ENVIRONMENT: production From e891d959b483c4b085206143bce339e2f70d3fd9 Mon Sep 17 00:00:00 2001 From: Jared Lewis Date: Sat, 21 Feb 2026 15:41:48 +1100 Subject: [PATCH 04/10] docs: add changelog fragment for PR #3 --- changelog/3.feature.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog/3.feature.md diff --git a/changelog/3.feature.md b/changelog/3.feature.md new file mode 100644 index 0000000..0d9c409 --- /dev/null +++ b/changelog/3.feature.md @@ -0,0 +1 @@ +Add ref-app API component and Gateway API HTTPRoute support to the Helm chart. From 62610511e005dc5f7836e9986e00193f8104535d Mon Sep 17 00:00:00 2001 From: Jared Lewis Date: Sat, 21 Feb 2026 16:25:31 +1100 Subject: [PATCH 05/10] fix(ci): add provider setup step before integration tests The integration test was failing with ETXTBSY because micromamba was being re-downloaded during the test run. Adding `ref providers setup` ensures conda environments and micromamba are ready before tests execute. --- .github/workflows/ci.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0aaab4a..c60f06e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -87,6 +87,9 @@ jobs: - name: Install dependencies run: uv sync --all-extras + - name: Set up providers + run: uv run ref providers setup + - name: Fetch test data run: | mkdir -p "$REF_TEST_DATA_DIR" From 355beb081fef6119c1f719af49b2fe6480996a87 Mon Sep 17 00:00:00 2001 From: Jared Lewis Date: Sun, 22 Feb 2026 21:52:46 +1100 Subject: [PATCH 06/10] feat(ci): add helm packaging workflow with minikube deploy test Adds a packaging workflow adapted from climate-ref that handles OCI chart publishing and end-to-end helm deployment testing on minikube. Moves helm-lint from ci.yml into the new workflow. --- .github/workflows/ci.yml | 15 --- .github/workflows/packaging.yaml | 220 +++++++++++++++++++++++++++++++ 2 files changed, 220 insertions(+), 15 deletions(-) create mode 100644 .github/workflows/packaging.yaml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c60f06e..5f9ebf1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -58,21 +58,6 @@ jobs: print('All AFT providers discovered successfully') " - # Verify Helm chart is valid - helm-lint: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - name: Set up Helm - uses: azure/setup-helm@v4.3.1 - - - name: Build chart dependencies - run: helm dependency build helm/ - - - name: Lint chart - run: helm lint helm/ - # Integration test on self-hosted runner (requires conda environments) integration: if: github.repository == 'Climate-REF/climate-ref-aft' diff --git a/.github/workflows/packaging.yaml b/.github/workflows/packaging.yaml new file mode 100644 index 0000000..ae31d13 --- /dev/null +++ b/.github/workflows/packaging.yaml @@ -0,0 +1,220 @@ +name: Packaging + +on: + pull_request: + workflow_dispatch: + push: + branches: + - "main" + tags: + - "v*" + +permissions: + contents: read + packages: write + attestations: write + id-token: write + +jobs: + changes: + name: Detect Changes + runs-on: ubuntu-latest + outputs: + helm: ${{ steps.filter.outputs.helm }} + steps: + - uses: actions/checkout@v4 + - uses: dorny/paths-filter@v3 + id: filter + with: + filters: | + helm: + - 'helm/**' + + helm: + name: Helm Chart + runs-on: ubuntu-latest + needs: [changes] + if: needs.changes.outputs.helm == 'true' || github.event_name != 'pull_request' + permissions: + packages: write + outputs: + generated-semver: ${{ steps.semantic-version.outputs.generated-semver }} + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + - name: Install yq + run: pip install yq + - name: Generate SemVer + id: semantic-version + run: | + CHART_VERSION=$(yq -r '.version' helm/Chart.yaml) + if [ "${{ github.event_name }}" = "pull_request" ]; then + LOCAL_SEGMENT=+pr-${{ github.event.pull_request.number }} + elif [ "${{ github.ref_type }}" = "tag" ]; then + LOCAL_SEGMENT="" + else + SHORT_SHA=$(echo "${{ github.sha }}" | cut -c1-7) + LOCAL_SEGMENT=+${SHORT_SHA} + fi + GENERATED_VERSION=${CHART_VERSION}${LOCAL_SEGMENT} + yq -Y -i ".version = \"$GENERATED_VERSION\"" helm/Chart.yaml + echo "generated-semver=$GENERATED_VERSION" >> $GITHUB_OUTPUT + - name: Lint chart + run: | + helm dependency build helm/ + helm lint helm/ + - name: Chart | Push + uses: appany/helm-oci-chart-releaser@v0.5.0 + with: + name: ref-aft + repository: climate-ref/charts + tag: ${{ steps.semantic-version.outputs.generated-semver }} + path: helm + registry: ghcr.io + registry_username: ${{ github.actor }} + registry_password: ${{ secrets.GITHUB_TOKEN }} + update_dependencies: 'true' + + test: + name: Test Helm Deployment + runs-on: ubuntu-latest + timeout-minutes: 30 + if: github.event_name == 'pull_request' && needs.changes.outputs.helm == 'true' + needs: [changes, helm] + steps: + - uses: actions/checkout@v4 + - name: Cache Sample Data (Restore) + id: cache-sample-data-restore + uses: actions/cache/restore@v5 + with: + path: ${{ github.workspace }}/cache/ref-config + key: ${{ runner.os }}-sample-data + enableCrossOsArchive: true + - name: Set permissions for cached data + run: | + sudo install -d --owner=1000 --group=1000 ${GITHUB_WORKSPACE}/cache/ref-config + - name: Start minikube + uses: medyagh/setup-minikube@latest + with: + mount-path: '${{ github.workspace }}/cache/ref-config:/cache/ref-config' + - name: Set up Helm + uses: azure/setup-helm@v4.3.1 + - name: Install Chart + run: | + helm install test oci://ghcr.io/climate-ref/charts/ref-aft \ + --version=${{ needs.helm.outputs.generated-semver }} \ + -f helm/ci/gh-actions-values.yaml + + sleep 60 + kubectl get pods + echo "" + kubectl describe pod -l app.kubernetes.io/component=pmp + echo "" + kubectl logs -l app.kubernetes.io/component=pmp + - name: Run Migrations + run: | + kubectl exec deployment/test-ref-orchestrator -- ref config list + - name: Initialize Providers + run: | + kubectl exec deployment/test-ref-orchestrator -- ref providers setup --skip-data --skip-validate + kubectl exec deployment/test-ref-orchestrator -- ref providers setup --provider pmp + kubectl exec deployment/test-ref-orchestrator -- ref providers setup --provider ilamb + - name: Verify Workers Online + run: | + kubectl port-forward svc/test-ref-flower 5555:5555 & + PF_PID=$! + + echo "=== Flower /healthcheck ===" + HEALTHY=0 + for i in $(seq 1 30); do + if curl -sf http://localhost:5555/healthcheck; then + HEALTHY=1 + break + fi + echo "Waiting for port-forward... ($i/30)" + sleep 2 + done + if [ "$HEALTHY" -eq 0 ]; then + echo "Flower healthcheck failed after 30 attempts" + kill $PF_PID || true + exit 1 + fi + echo "" + + echo "=== Checking broker queues ===" + FAILED=1 + for attempt in $(seq 1 15); do + BROKER=$(curl -sf http://localhost:5555/broker) + + MISSING=0 + for queue in celery esmvaltool pmp ilamb example; do + if ! echo "$BROKER" | grep -q "id=\"${queue}\""; then + MISSING=1 + break + fi + done + + if [ "$MISSING" -eq 0 ]; then + echo "All expected queues found" + for queue in celery esmvaltool pmp ilamb example; do + echo "OK: ${queue} queue present" + done + FAILED=0 + break + fi + echo "Waiting for broker queues... ($attempt/15)" + sleep 4 + done + + kill $PF_PID || true + if [ "$FAILED" -eq 1 ]; then + echo "Not all expected queues are registered with the broker after 60s" + echo "Broker response:" + echo "$BROKER" + exit 1 + fi + - name: Fetch Test Data + run: | + kubectl exec deployment/test-ref-orchestrator -- ref datasets fetch-data --registry sample-data --output-directory /ref/sample-data + + - name: Cache Sample Data (Save) + uses: actions/cache/save@v5 + with: + path: ${{ github.workspace }}/cache/ref-config + key: ${{ runner.os }}-sample-data + + - name: Ingest Test Data (CMIP6) + run: | + kubectl exec deployment/test-ref-orchestrator -- ref -v datasets ingest --source-type cmip6 /ref/sample-data/CMIP6 + - name: Ingest Test Data (obs4mips) + run: | + kubectl exec deployment/test-ref-orchestrator -- ref -v datasets ingest --source-type obs4mips /ref/sample-data/obs4REF + - name: Simple Solve + run: | + kubectl exec deployment/test-ref-orchestrator -- ref -v solve --timeout 720 --one-per-provider \ + --diagnostic global-mean-timeseries \ + --diagnostic annual-cycle \ + --diagnostic gpp-wecann + - name: Capture Worker Logs on Failure + if: failure() + run: | + echo "=== PMP Worker Logs ===" + kubectl logs -l app.kubernetes.io/component=pmp --tail=500 || true + echo "" + echo "=== ESMValTool Worker Logs ===" + kubectl logs -l app.kubernetes.io/component=esmvaltool --tail=500 || true + echo "" + echo "=== ILAMB Worker Logs ===" + kubectl logs -l app.kubernetes.io/component=ilamb --tail=500 || true + echo "" + echo "=== Example Worker Logs ===" + kubectl logs -l app.kubernetes.io/component=example --tail=500 || true + echo "" + echo "=== Orchestrator Worker Logs ===" + kubectl logs -l app.kubernetes.io/component=orchestrator --tail=500 || true + echo "" + echo "=== Flower Logs ===" + kubectl logs -l app.kubernetes.io/component=flower --tail=200 || true + echo "" + echo "=== Dragonfly Logs ===" + kubectl logs -l app.kubernetes.io/name=dragonfly --tail=200 || true From 7d22879e907c113a7b46e2444b65abfb58ae7949 Mon Sep 17 00:00:00 2001 From: Jared Lewis Date: Mon, 23 Feb 2026 12:23:58 +1100 Subject: [PATCH 07/10] chore: update the packaging --- .github/workflows/packaging.yaml | 98 ++++++++------------------------ 1 file changed, 25 insertions(+), 73 deletions(-) diff --git a/.github/workflows/packaging.yaml b/.github/workflows/packaging.yaml index ae31d13..109b9e5 100644 --- a/.github/workflows/packaging.yaml +++ b/.github/workflows/packaging.yaml @@ -22,13 +22,14 @@ jobs: outputs: helm: ${{ steps.filter.outputs.helm }} steps: - - uses: actions/checkout@v4 - - uses: dorny/paths-filter@v3 - id: filter - with: - filters: | - helm: - - 'helm/**' + - uses: actions/checkout@v6 + # - uses: dorny/paths-filter@v3 + # id: filter + # with: + # filters: | + # helm: + # - 'helm/**' + helm: name: Helm Chart @@ -40,10 +41,14 @@ jobs: outputs: generated-semver: ${{ steps.semantic-version.outputs.generated-semver }} steps: - - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 + - uses: actions/checkout@v6 + - uses: actions/setup-python@v6 + - name: Install jq + run: | + sudo apt-get install --yes jq - name: Install yq - run: pip install yq + run: | + pip install yq - name: Generate SemVer id: semantic-version run: | @@ -59,14 +64,10 @@ jobs: GENERATED_VERSION=${CHART_VERSION}${LOCAL_SEGMENT} yq -Y -i ".version = \"$GENERATED_VERSION\"" helm/Chart.yaml echo "generated-semver=$GENERATED_VERSION" >> $GITHUB_OUTPUT - - name: Lint chart - run: | - helm dependency build helm/ - helm lint helm/ - name: Chart | Push uses: appany/helm-oci-chart-releaser@v0.5.0 with: - name: ref-aft + name: climate-ref-aft repository: climate-ref/charts tag: ${{ steps.semantic-version.outputs.generated-semver }} path: helm @@ -82,7 +83,7 @@ jobs: if: github.event_name == 'pull_request' && needs.changes.outputs.helm == 'true' needs: [changes, helm] steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Cache Sample Data (Restore) id: cache-sample-data-restore uses: actions/cache/restore@v5 @@ -101,8 +102,9 @@ jobs: uses: azure/setup-helm@v4.3.1 - name: Install Chart run: | - helm install test oci://ghcr.io/climate-ref/charts/ref-aft \ + helm install test oci://ghcr.io/climate-ref/charts/ref \ --version=${{ needs.helm.outputs.generated-semver }} \ + --set defaults.image.tag=pr-${{ github.event.pull_request.number }} \ -f helm/ci/gh-actions-values.yaml sleep 60 @@ -116,63 +118,12 @@ jobs: kubectl exec deployment/test-ref-orchestrator -- ref config list - name: Initialize Providers run: | + # Imports ilamb3 which tries to create /home/app/.config/ilamb3 on import, no way to tell it to live somewhere else + # First, set up all providers without fetching data (handles conda envs) kubectl exec deployment/test-ref-orchestrator -- ref providers setup --skip-data --skip-validate + # Fetch data for providers except esmvaltool (ERA5 data is too large for CI) kubectl exec deployment/test-ref-orchestrator -- ref providers setup --provider pmp kubectl exec deployment/test-ref-orchestrator -- ref providers setup --provider ilamb - - name: Verify Workers Online - run: | - kubectl port-forward svc/test-ref-flower 5555:5555 & - PF_PID=$! - - echo "=== Flower /healthcheck ===" - HEALTHY=0 - for i in $(seq 1 30); do - if curl -sf http://localhost:5555/healthcheck; then - HEALTHY=1 - break - fi - echo "Waiting for port-forward... ($i/30)" - sleep 2 - done - if [ "$HEALTHY" -eq 0 ]; then - echo "Flower healthcheck failed after 30 attempts" - kill $PF_PID || true - exit 1 - fi - echo "" - - echo "=== Checking broker queues ===" - FAILED=1 - for attempt in $(seq 1 15); do - BROKER=$(curl -sf http://localhost:5555/broker) - - MISSING=0 - for queue in celery esmvaltool pmp ilamb example; do - if ! echo "$BROKER" | grep -q "id=\"${queue}\""; then - MISSING=1 - break - fi - done - - if [ "$MISSING" -eq 0 ]; then - echo "All expected queues found" - for queue in celery esmvaltool pmp ilamb example; do - echo "OK: ${queue} queue present" - done - FAILED=0 - break - fi - echo "Waiting for broker queues... ($attempt/15)" - sleep 4 - done - - kill $PF_PID || true - if [ "$FAILED" -eq 1 ]; then - echo "Not all expected queues are registered with the broker after 60s" - echo "Broker response:" - echo "$BROKER" - exit 1 - fi - name: Fetch Test Data run: | kubectl exec deployment/test-ref-orchestrator -- ref datasets fetch-data --registry sample-data --output-directory /ref/sample-data @@ -191,6 +142,7 @@ jobs: kubectl exec deployment/test-ref-orchestrator -- ref -v datasets ingest --source-type obs4mips /ref/sample-data/obs4REF - name: Simple Solve run: | + # Use a fixed set of fast diagnostics to keep CI times predictable kubectl exec deployment/test-ref-orchestrator -- ref -v solve --timeout 720 --one-per-provider \ --diagnostic global-mean-timeseries \ --diagnostic annual-cycle \ @@ -214,7 +166,7 @@ jobs: kubectl logs -l app.kubernetes.io/component=orchestrator --tail=500 || true echo "" echo "=== Flower Logs ===" - kubectl logs -l app.kubernetes.io/component=flower --tail=200 || true + kubectl logs -l app.kubernetes.io/component=flower --tail=500 || true echo "" echo "=== Dragonfly Logs ===" - kubectl logs -l app.kubernetes.io/name=dragonfly --tail=200 || true + kubectl logs -l app.kubernetes.io/name=dragonfly --tail=500 || true From 2ab73863bb6f50f6f34f5a4be817ab286aeb030f Mon Sep 17 00:00:00 2001 From: Jared Lewis Date: Mon, 23 Feb 2026 12:25:17 +1100 Subject: [PATCH 08/10] chore: readd linting --- .github/workflows/ci.yml | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5f9ebf1..ce17d8b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -58,10 +58,25 @@ jobs: print('All AFT providers discovered successfully') " + # Verify Helm chart is valid + helm-lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Set up Helm + uses: azure/setup-helm@v4.3.1 + + - name: Build chart dependencies + run: helm dependency build helm/ + + - name: Lint chart + run: helm lint helm/ + # Integration test on self-hosted runner (requires conda environments) integration: if: github.repository == 'Climate-REF/climate-ref-aft' - runs-on: self-hosted + runs-on: arc needs: [install-pinned] steps: - uses: actions/checkout@v4 From ed1cb9f5b9ddf13d0d0ccda5436eed1ccbcd9880 Mon Sep 17 00:00:00 2001 From: Jared Lewis Date: Mon, 23 Feb 2026 13:38:51 +1100 Subject: [PATCH 09/10] fix(helm): rename chart to climate-ref-aft and update OCI paths Chart renamed from `ref` to `climate-ref-aft` to avoid collisions with the climate-ref chart in the shared OCI registry. Updates all resource name references, OCI paths, and documentation. --- .github/workflows/packaging.yaml | 18 +++++++++--------- .github/workflows/release.yml | 2 +- README.md | 3 ++- helm/Chart.yaml | 4 ++-- 4 files changed, 14 insertions(+), 13 deletions(-) diff --git a/.github/workflows/packaging.yaml b/.github/workflows/packaging.yaml index 109b9e5..1f539c5 100644 --- a/.github/workflows/packaging.yaml +++ b/.github/workflows/packaging.yaml @@ -102,7 +102,7 @@ jobs: uses: azure/setup-helm@v4.3.1 - name: Install Chart run: | - helm install test oci://ghcr.io/climate-ref/charts/ref \ + helm install test oci://ghcr.io/climate-ref/charts/climate-ref-aft \ --version=${{ needs.helm.outputs.generated-semver }} \ --set defaults.image.tag=pr-${{ github.event.pull_request.number }} \ -f helm/ci/gh-actions-values.yaml @@ -115,18 +115,18 @@ jobs: kubectl logs -l app.kubernetes.io/component=pmp - name: Run Migrations run: | - kubectl exec deployment/test-ref-orchestrator -- ref config list + kubectl exec deployment/test-climate-ref-aft-orchestrator -- ref config list - name: Initialize Providers run: | # Imports ilamb3 which tries to create /home/app/.config/ilamb3 on import, no way to tell it to live somewhere else # First, set up all providers without fetching data (handles conda envs) - kubectl exec deployment/test-ref-orchestrator -- ref providers setup --skip-data --skip-validate + kubectl exec deployment/test-climate-ref-aft-orchestrator -- ref providers setup --skip-data --skip-validate # Fetch data for providers except esmvaltool (ERA5 data is too large for CI) - kubectl exec deployment/test-ref-orchestrator -- ref providers setup --provider pmp - kubectl exec deployment/test-ref-orchestrator -- ref providers setup --provider ilamb + kubectl exec deployment/test-climate-ref-aft-orchestrator -- ref providers setup --provider pmp + kubectl exec deployment/test-climate-ref-aft-orchestrator -- ref providers setup --provider ilamb - name: Fetch Test Data run: | - kubectl exec deployment/test-ref-orchestrator -- ref datasets fetch-data --registry sample-data --output-directory /ref/sample-data + kubectl exec deployment/test-climate-ref-aft-orchestrator -- ref datasets fetch-data --registry sample-data --output-directory /ref/sample-data - name: Cache Sample Data (Save) uses: actions/cache/save@v5 @@ -136,14 +136,14 @@ jobs: - name: Ingest Test Data (CMIP6) run: | - kubectl exec deployment/test-ref-orchestrator -- ref -v datasets ingest --source-type cmip6 /ref/sample-data/CMIP6 + kubectl exec deployment/test-climate-ref-aft-orchestrator -- ref -v datasets ingest --source-type cmip6 /ref/sample-data/CMIP6 - name: Ingest Test Data (obs4mips) run: | - kubectl exec deployment/test-ref-orchestrator -- ref -v datasets ingest --source-type obs4mips /ref/sample-data/obs4REF + kubectl exec deployment/test-climate-ref-aft-orchestrator -- ref -v datasets ingest --source-type obs4mips /ref/sample-data/obs4REF - name: Simple Solve run: | # Use a fixed set of fast diagnostics to keep CI times predictable - kubectl exec deployment/test-ref-orchestrator -- ref -v solve --timeout 720 --one-per-provider \ + kubectl exec deployment/test-climate-ref-aft-orchestrator -- ref -v solve --timeout 720 --one-per-provider \ --diagnostic global-mean-timeseries \ --diagnostic annual-cycle \ --diagnostic gpp-wecann diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0a2150f..d6718d9 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -34,7 +34,7 @@ jobs: - name: Push chart run: | CHART_VERSION=$(grep '^version:' helm/Chart.yaml | awk '{print $2}') - helm push ref-${CHART_VERSION}.tgz oci://ghcr.io/climate-ref/charts + helm push climate-ref-aft-${CHART_VERSION}.tgz oci://ghcr.io/climate-ref/charts release: name: GitHub Release diff --git a/README.md b/README.md index 32f6a30..e83d40e 100644 --- a/README.md +++ b/README.md @@ -55,7 +55,7 @@ bash scripts/smoke-test.sh helm install ref ./helm -f helm/local-test-values.yaml # Or from the OCI registry -helm install ref oci://ghcr.io/climate-ref/charts/ref --version 0.9.1 +helm install ref oci://ghcr.io/climate-ref/charts/climate-ref-aft --version 0.9.1 ``` ### Integration Tests @@ -76,6 +76,7 @@ uv run pytest tests/ -v --slow | Workflow | Trigger | What It Does | |----------|---------|--------------| | `ci.yml` | Push, PR | Lint, install pinned versions, run integration tests | +| `packaging.yaml` | Push, PR | Helm chart OCI publish and minikube deployment test | | `nightly.yml` | Scheduled (daily) | Test against latest versions of all components | | `release.yml` | Tag push | Publish Helm chart, create GitHub release | diff --git a/helm/Chart.yaml b/helm/Chart.yaml index 016dc29..84a37e6 100644 --- a/helm/Chart.yaml +++ b/helm/Chart.yaml @@ -1,6 +1,6 @@ apiVersion: v2 -name: ref -description: A Helm chart for Kubernetes +name: climate-ref-aft +description: A Helm chart for deploying the Climate REF application for the CMIP7 Assessment Fasttrack (AFT) type: application # This is the chart version. This version number should be incremented each time you make changes From 2fe50bde8bf9e2edece89fa418c06174dcc60fbb Mon Sep 17 00:00:00 2001 From: Jared Lewis Date: Mon, 23 Feb 2026 14:36:07 +1100 Subject: [PATCH 10/10] revert: Use the self-hosted --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ce17d8b..c60f06e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -76,7 +76,7 @@ jobs: # Integration test on self-hosted runner (requires conda environments) integration: if: github.repository == 'Climate-REF/climate-ref-aft' - runs-on: arc + runs-on: self-hosted needs: [install-pinned] steps: - uses: actions/checkout@v4