diff --git a/.copier-answers.yml b/.copier-answers.yml index e8e748ed..ce6e9845 100644 --- a/.copier-answers.yml +++ b/.copier-answers.yml @@ -1,5 +1,5 @@ # Changes here will be overwritten by Copier; NEVER EDIT MANUALLY -_commit: 5.1.0 +_commit: 5.3.0 _src_path: https://github.com/epics-containers/services-template-helm athena_services: - rabbitmq diff --git a/.github/workflows/verify.yml b/.github/workflows/verify.yml index 401ae4c5..25472902 100644 --- a/.github/workflows/verify.yml +++ b/.github/workflows/verify.yml @@ -9,7 +9,9 @@ jobs: if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.repository steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 + with: + fetch-depth: 0 - name: run IOC checks run: | diff --git a/.helm-shared/Chart.yaml b/.helm-shared/Chart.yaml index 89ae5543..d3ced6f4 100644 --- a/.helm-shared/Chart.yaml +++ b/.helm-shared/Chart.yaml @@ -7,7 +7,7 @@ type: application dependencies: - name: ioc-instance - version: 5.0.0 + version: 5.2.4 repository: "oci://ghcr.io/epics-containers/charts" import-values: - child: ioc-instance diff --git a/.helm-shared/values.schema.json b/.helm-shared/values.schema.json index 73459154..d7e19527 100644 --- a/.helm-shared/values.schema.json +++ b/.helm-shared/values.schema.json @@ -13,7 +13,7 @@ "description": "Shared values for the root `services/values.yaml`. Use Anchor at the root to share the whole object between ioc-instance/dev-c7/fastcs as needed. Or use anchors on properties to create multiple sharable objects. Use a merge key (<<: *shared) to merge in the shared values where needed." }, "ioc-instance": { - "$ref": "https://github.com/epics-containers/ec-helm-charts/releases/download/5.0.0/ioc-instance.schema.json#/properties/ioc-instance", + "$ref": "https://github.com/epics-containers/ec-helm-charts/releases/download/5.1.0/ioc-instance.schema.json#/properties/ioc-instance", "type": "object", "additionalProperties": false, "description": "Shared values for ioc-instance charts. These represent ibek IOCs" diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 00000000..1c093bad --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,39 @@ +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v5.0.0 + hooks: + - id: check-added-large-files + - id: check-yaml + exclude: ^Charts/|/templates/ + - id: check-merge-conflict + # - id: end-of-file-fixer + + - repo: local + hooks: + - id: tech-ui + name: generate and validate the synoptic and component screens + language: system + # only do this if the techui support submodule has been added + entry: | + bash -c " + if [[ -f synoptic/techui-support/techui-support.yaml ]]; then + uvx techui-builder synoptic/techui.yaml + fi" + files: ^synoptic/ + pass_filenames: false + + - repo: local + hooks: + - id: ibek-runtime-schema + name: generate schema for local ibek entities + language: system + # only do this if there are ibek runtime support files present + entry: | + bash -c " + support=$(find ibek-runtime-support/ -name '*.ibek.support.yaml') + if [[ -n ${support} ]]; then + uvx --python 3.13 ibek ioc generate-schema ${support} \ + --output ibek-runtime-support/runtime.schema.json + fi" + files: ^ibek-runtime-support/ + pass_filenames: false diff --git a/README.md b/README.md index 05568ef6..4b4e64a3 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,17 @@ # p46 IOC Instances and Services -This repository holds the a definition of p46 IOC Instances and services. Each sub folder of the `services` directory contains a helm chart for a specific service or IOC. The corresponding deployments repo can be found at `https://gitlab.diamond.ac.uk/controls/containers/beamline/p46-deployment`. \ No newline at end of file +This repository holds the a definition of p46 IOC Instances and services. Each sub folder of the `services` directory contains a helm chart for a specific service or IOC. The corresponding deployments repo can be found at [https://gitlab.diamond.ac.uk/controls/containers/beamline/p46-deployment]. + +## Using pre-commit hooks + +Pre commit hooks will validate the synoptic and additional soft support if present. To install pre-commit hooks run: + +```bash +uvx pre-commit install +``` + +To force execution of the pre-commit hooks on all files run: + +```bash +uvx pre-commit run --all-files +``` diff --git a/ci_verify.sh b/ci_verify.sh index 1e3e670d..1d915162 100755 --- a/ci_verify.sh +++ b/ci_verify.sh @@ -13,6 +13,28 @@ set -xe rm -rf ${ROOT}/.ci_work/ mkdir -p ${ROOT}/.ci_work +# Perform pre-commit checks to ensure techui-builder has validated the synoptic +# and that the ibek-runtme-support schema is up to date +################################################################################ + + +cd ${ROOT} +git submodule update --init + +pip install uv +# use python 3.13 to ensure latest pydantic +uv venv --python 3.13 --clear +source .venv/bin/activate +uv pip install -r requirements.txt + +# run pre-commit checking which tool versions will be used. +uvx pre-commit install +uvx ibek --version +uvx techui-builder --version +uvx pre-commit run --all-files --show-diff-on-failure + +# Verify the IOC instance definitions +################################################################################ # if a docker provider is specified, use it if [[ $DOCKER_PROVIDER ]]; then docker=$DOCKER_PROVIDER @@ -21,9 +43,40 @@ else if ! docker version &>/dev/null; then docker=podman; else docker=docker; fi fi -# copy the services to a temporary location to avoid dirtying the repo -cp -r ${ROOT}/services/* ${ROOT}/.ci_work/ +# Determine diff base +if [[ -n "${CI_MERGE_REQUEST_TARGET_BRANCH_NAME:-}" ]]; then + # GitLab MR + DIFF_BASE="origin/${CI_MERGE_REQUEST_TARGET_BRANCH_NAME}" +elif [[ -n "${GITHUB_BASE_REF:-}" ]]; then + # GitHub PR + DIFF_BASE="origin/${GITHUB_BASE_REF}" +elif git rev-parse HEAD~1 >/dev/null 2>&1; then + # normal push + DIFF_BASE="HEAD~1" +else + # first commit + DIFF_BASE=$(git hash-object -t tree /dev/null) +fi + +# Get changed services (excluding values.yaml) +CHANGED_SERVICES=$(git diff --name-only "$DIFF_BASE" HEAD \ + | grep '^services/' \ + | grep -v 'values.yaml' \ + | cut -d/ -f2 \ + | sort -u) + + +# Need to make sure values.yaml is included in the ci +cp -L "${ROOT}/services/values.yaml" "${ROOT}/.ci_work/" + +# copy only the changed services to a temporary location to avoid dirtying the repo +for svc in $CHANGED_SERVICES; do + echo "Preparing service: $svc" + cp -Lr "${ROOT}/services/$svc" "${ROOT}/.ci_work/" +done +# enable nullglob so * is not taken literally if no services are changed +shopt -s nullglob for service in ${ROOT}/.ci_work/*/ # */ to skip files do ### Lint each service chart and validate if schema given ### diff --git a/ibek-runtime-support/p46-support/p46-support.ibek.support.yaml b/ibek-runtime-support/p46-support/p46-support.ibek.support.yaml new file mode 100644 index 00000000..aab4476f --- /dev/null +++ b/ibek-runtime-support/p46-support/p46-support.ibek.support.yaml @@ -0,0 +1,8 @@ +# yaml-language-server: $schema=https://github.com/epics-containers/ibek/releases/download/3.0.1/ibek.support.schema.json + +# A place to add additional EPICS Db templates or other features to +# be used by this beamline/tech area + +module: p46-support + +entity_models: [] diff --git a/ibek-runtime-support/runtime.schema.json b/ibek-runtime-support/runtime.schema.json new file mode 100644 index 00000000..5bff5544 --- /dev/null +++ b/ibek-runtime-support/runtime.schema.json @@ -0,0 +1,98 @@ +{ + "$defs": { + "RepeatEntity": { + "additionalProperties": false, + "description": "A definition of RepeatEntity for the type checker\n\nThis is not really used - instead the dynamic class is created\nby the make_entity_model function is used.", + "properties": { + "type": { + "const": "ibek.repeat", + "default": "ibek.repeat", + "title": "Type", + "type": "string" + }, + "entity_enabled": { + "default": true, + "description": "enable or disable this entity instance", + "title": "Entity Enabled", + "type": "boolean" + }, + "values": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "type": "string" + } + ], + "description": "The list of values to iterate over", + "title": "Values" + }, + "variable": { + "default": "index", + "description": "The variable name to use in the entity model", + "title": "Variable", + "type": "string" + }, + "entity": { + "additionalProperties": true, + "description": "The entity model to repeat", + "title": "Entity", + "type": "object" + } + }, + "required": [ + "values", + "entity" + ], + "title": "RepeatEntity", + "type": "object" + } + }, + "additionalProperties": false, + "properties": { + "ioc_name": { + "description": "Name of IOC instance", + "title": "Ioc Name", + "type": "string" + }, + "description": { + "description": "Description of what the IOC does", + "title": "Description", + "type": "string" + }, + "entities": { + "description": "List of entities this IOC instantiates", + "items": { + "discriminator": { + "mapping": { + "ibek.repeat": "#/$defs/RepeatEntity" + }, + "propertyName": "type" + }, + "oneOf": [ + { + "$ref": "#/$defs/RepeatEntity" + } + ] + }, + "title": "Entities", + "type": "array" + }, + "shared": { + "default": [], + "description": "A place to create any anchors required for repeating YAML", + "items": {}, + "title": "Shared", + "type": "array" + } + }, + "required": [ + "ioc_name", + "description", + "entities" + ], + "title": "NewIOC", + "type": "object" +} diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 00000000..54e6e12a --- /dev/null +++ b/requirements.txt @@ -0,0 +1,3 @@ +uv +urllib3<2.4.0 +Kodman diff --git a/services/.ioc_template/config/runtime.yaml b/services/.ioc_template/config/runtime.yaml new file mode 100644 index 00000000..1fa1b8f9 --- /dev/null +++ b/services/.ioc_template/config/runtime.yaml @@ -0,0 +1,15 @@ +# yaml-language-server: $schema=../../../ibek-runtime-support/runtime.schema.json +ioc_name: "{{ _global.get_env('IOC_NAME') }}" + +description: additional entities from the services repo + +# to create additional entities here: +# 1. add folders to /ibek-runtime-support containing: +# - XXX.ibek.support.yaml +# - possibly epics DB templates +# - plus any other files that XXX.ibek.support.yaml uses +# 2. symlink the files this ioc needs into this config folder +# 3. uvx pre-commit run to regenerate runtime.schema.json +# 4. add entities below, following the supplied schema + +entities: [] diff --git a/services/bl46p-synoptic/Chart.yaml b/services/bl46p-synoptic/Chart.yaml new file mode 120000 index 00000000..ed18fd61 --- /dev/null +++ b/services/bl46p-synoptic/Chart.yaml @@ -0,0 +1 @@ +../../.helm-shared/Chart.yaml \ No newline at end of file diff --git a/services/bl46p-synoptic/config/ioc.db b/services/bl46p-synoptic/config/ioc.db new file mode 100644 index 00000000..6568bdb1 --- /dev/null +++ b/services/bl46p-synoptic/config/ioc.db @@ -0,0 +1,4 @@ + +# This file will contain status records for compenents and is generated +# by techui-builder. Do not edit this file manually. +# diff --git a/services/bl46p-synoptic/config/st.cmd b/services/bl46p-synoptic/config/st.cmd new file mode 100644 index 00000000..03cd1a1e --- /dev/null +++ b/services/bl46p-synoptic/config/st.cmd @@ -0,0 +1,10 @@ +# basic IOC startup script to just load ioc.db +cd "/epics/ioc" + +epicsEnvSet EPICS_TZ GMT0BST + +dbLoadDatabase dbd/ioc.dbd +ioc_registerRecordDeviceDriver pdbbase + +dbLoadRecords /epics/ioc/config/ioc.db +iocInit diff --git a/services/bl46p-synoptic/templates b/services/bl46p-synoptic/templates new file mode 120000 index 00000000..367e2aae --- /dev/null +++ b/services/bl46p-synoptic/templates @@ -0,0 +1 @@ +../../.helm-shared/templates \ No newline at end of file diff --git a/services/bl46p-synoptic/values.yaml b/services/bl46p-synoptic/values.yaml new file mode 100644 index 00000000..ba7e5247 --- /dev/null +++ b/services/bl46p-synoptic/values.yaml @@ -0,0 +1,31 @@ +# yaml-language-server: $schema=../../.helm-shared/values.schema.json + +ioc-instance: + # use a lightweight IOC because epics-base has no ioc.dbd or start.sh + image: ghcr.io/epics-containers/ioc-asyn-runtime:2025.11.1 + + rebootEveryCommit: true + + initContainers: + - name: clone-synoptic + image: alpine/git + command: + - sh + - -c + args: + - | + set -xe + git config --global --add safe.directory /data/synoptic-git + if ! [ -d /data/synoptic-git ]; then + git clone $ARGOCD_SOURCE_REPO /data/synoptic-git + fi + cd /data/synoptic-git + git fetch + git checkout $ARGOCD_COMMIT_HASH + git submodule update --init + rm -rf /epics/opi/* + cp -r /data/synoptic-git/synoptic/* /epics/opi + + # don't use the ioc-instance livenesProbe, preStop which dont exist in fastcs image. + livenessExecutable: "" + preStopExecutable: "" diff --git a/services/p46-blueapi/values.yaml b/services/p46-blueapi/values.yaml index 64950184..0a8da7c2 100644 --- a/services/p46-blueapi/values.yaml +++ b/services/p46-blueapi/values.yaml @@ -36,8 +36,6 @@ blueapi: host: http://opentelemetry-collector.tracing worker: - numtracker: - url: https://numtracker-staging.diamond.ac.uk/graphql env: metadata: instrument: p46 @@ -68,6 +66,11 @@ blueapi: client_id: "blueapiCli" client_audience: "account" logout_redirect_endpoint: "oauth2/sign_out" + + + numtracker: + url: https://numtracker-staging.diamond.ac.uk/graphql + scratch: repositories: - name: dodal diff --git a/services/p46-epics-gateways/values.yaml b/services/p46-epics-gateways/values.yaml index a01522ef..05435def 100644 --- a/services/p46-epics-gateways/values.yaml +++ b/services/p46-epics-gateways/values.yaml @@ -2,4 +2,4 @@ epics-gateways: # switch to developer image for debugging image: ghcr.io/epics-containers/epics-gateways-developer:2025.11.1 # needs to be a server in controls dev network - nodeName: bl46p-ea-serv-01.diamond.ac.uk \ No newline at end of file + nodeName: bl46p-ea-serv-01.diamond.ac.uk diff --git a/services/p46-epics-opis/Chart.yaml b/services/p46-epics-opis/Chart.yaml index f852a6b9..63d7f420 100644 --- a/services/p46-epics-opis/Chart.yaml +++ b/services/p46-epics-opis/Chart.yaml @@ -8,5 +8,5 @@ type: application dependencies: - name: epics-opis - version: 5.0.0 + version: 5.2.4 repository: "oci://ghcr.io/epics-containers/charts" diff --git a/services/p46-epics-pvcs/Chart.yaml b/services/p46-epics-pvcs/Chart.yaml index c6499692..6db9fb34 100644 --- a/services/p46-epics-pvcs/Chart.yaml +++ b/services/p46-epics-pvcs/Chart.yaml @@ -8,5 +8,5 @@ type: application dependencies: - name: epics-pvcs - version: 5.0.0 + version: 5.2.4 repository: "oci://ghcr.io/epics-containers/charts" diff --git a/synoptic/index.bob b/synoptic/index.bob new file mode 100644 index 00000000..c377155e --- /dev/null +++ b/synoptic/index.bob @@ -0,0 +1,28 @@ + + + + P46 Synoptic + 1900 + 1100 + 4 + 4 + + Title + TITLE + P46 Synoptic + 0 + 0 + 1250 + 25 + + + + + + + + + true + 1 + + diff --git a/synoptic/techui.yaml b/synoptic/techui.yaml new file mode 100644 index 00000000..902ae6a9 --- /dev/null +++ b/synoptic/techui.yaml @@ -0,0 +1,11 @@ +beamline: + short_dom: "P46" + long_dom: "BL46P" + desc: "P46 Beamline or Tech Area" + +# add components for techUI-builder to build screens for +components: {} + + # DCAM1: + # desc: GigE camera EXAMPLE + # prefix: BL46P-DI-DCAM-01