From 3cd82a6f57e957b7f4bcdcbab0bdca38b40ff1e2 Mon Sep 17 00:00:00 2001 From: Minijackson Date: Thu, 23 May 2024 10:16:57 +0200 Subject: [PATCH 001/111] gitlab-ci: make pipeline/jobs interruptible --- .gitlab-ci.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 84cb8a60..43c0ff54 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,4 +1,9 @@ +workflow: + auto_cancel: + on_new_commit: interruptible + default: + interruptible: true tags: - nix From 7e18ed04d6446a3a184294a556bfbcdabf421943 Mon Sep 17 00:00:00 2001 From: Minijackson Date: Fri, 24 May 2024 08:29:49 +0200 Subject: [PATCH 002/111] phoebus-olog: build using buildMavenPackage function makes the packaging much simpler also use 'jre' instead of 'jdk' for running it, which makes the package smaller --- pkgs/epnix/tools/phoebus/olog/default.nix | 143 +++++++--------------- 1 file changed, 46 insertions(+), 97 deletions(-) diff --git a/pkgs/epnix/tools/phoebus/olog/default.nix b/pkgs/epnix/tools/phoebus/olog/default.nix index 213667ea..b7ad7c8d 100644 --- a/pkgs/epnix/tools/phoebus/olog/default.nix +++ b/pkgs/epnix/tools/phoebus/olog/default.nix @@ -1,103 +1,52 @@ { lib, epnixLib, - stdenv, fetchFromGitHub, + jre, maven, - libfaketime, - canonicalize-jars-hook, - jdk, - git, makeWrapper, -}: let - # TODO: upstream outputTimestamp - buildDate = "2022-02-24T07:56:00Z"; - mvnOptions = "-Dmaven.javadoc.skip=true -Dmaven.source.skip=true -Pdeployable-jar -Dproject.build.outputTimestamp=${buildDate}"; -in - stdenv.mkDerivation (final: { - pname = "phoebus-olog"; - version = "4.7.3"; - - src = fetchFromGitHub { - owner = "Olog"; - repo = "phoebus-olog"; - rev = "v${final.version}"; - hash = "sha256-WwRB4QtZBeH6GptTZJ02CBpP7BGzjZbwMYQrOmGevFo="; - }; - - deps = stdenv.mkDerivation { - name = with final; "${pname}-${version}-deps"; - inherit (final) src; - - nativeBuildInputs = [jdk maven git]; - - buildPhase = '' - runHook preBuild - - # Don't use the launch script, we use the jar file as a jar - mvn package ${mvnOptions} -Dmaven.repo.local=$out - - runHook postBuild - ''; - - # keep only *.{pom,jar,sha1,nbm} and delete all ephemeral files with - # lastModified timestamps inside - installPhase = '' - runHook preInstall - - find $out -type f \ - -name \*.lastUpdated -or \ - -name resolver-status.properties -or \ - -name _remote.repositories \ - -delete - - runHook postInstall - ''; - - outputHashAlgo = "sha256"; - outputHashMode = "recursive"; - outputHash = "sha256-40n06R2KBuuzqvVq1bWsd1jjQtcNQfK/4RbgtFmxTf8="; - - doCheck = false; - }; - - nativeBuildInputs = [maven makeWrapper libfaketime]; - - buildPhase = '' - runHook preBuild - - # Use faketime because files inside the jar have an mtime - faketime -f "1970-01-01 00:00:01" mvn package --offline ${mvnOptions} -Dmaven.repo.local="$deps" - - runHook postBuild - ''; - - installPhase = '' - runHook preInstall - - mkdir -p $out/bin - mkdir -p $out/share/java - - jarName="service-olog-${final.version}.jar" - - classpath=$(find $deps -name "*.jar" -printf ':%h/%f'); - install -Dm644 target/service-olog-4.7.3.jar $out/share/java - # Strip the script at the beginning of the jar, so that we are able to - # canonicalize it - sed -i '1,/^exit 0$/d' $out/share/java/$jarName - - makeWrapper ${jdk}/bin/java $out/bin/${final.pname} \ - --add-flags "-classpath ''${classpath#:}" \ - --add-flags "-jar $out/share/java/$jarName" - - runHook postInstall - ''; - - meta = { - description = "Online logbook for experimental and industrial logging"; - homepage = "https://olog.readthedocs.io/en/latest/"; - license = lib.licenses.epl10; - maintainers = with epnixLib.maintainers; [minijackson]; - inherit (jdk.meta) platforms; - }; - }) +}: +maven.buildMavenPackage rec { + pname = "phoebus-olog"; + version = "4.7.3"; + + src = fetchFromGitHub { + owner = "Olog"; + repo = "phoebus-olog"; + rev = "v${version}"; + hash = "sha256-WwRB4QtZBeH6GptTZJ02CBpP7BGzjZbwMYQrOmGevFo="; + }; + + mvnHash = "sha256-D1n5PfGulIgdjd60mChVLH1kQDOUcc/TvEw3oJUZ1h4="; + mvnParameters = "-Dmaven.javadoc.skip=true -Dmaven.source.skip=true -Pdeployable-jar -Dproject.build.outputTimestamp=1980-01-01T00:00:02Z"; + + nativeBuildInputs = [makeWrapper]; + + installPhase = '' + runHook preInstall + + mkdir -p $out/bin + mkdir -p $out/share/java + + jarName="service-olog-${version}.jar" + + install -Dm644 target/service-olog-4.7.3.jar $out/share/java + # Strip the script at the beginning of the jar, so that we are able to + # canonicalize it + sed -i '1,/^exit 0$/d' $out/share/java/$jarName + + makeWrapper ${lib.getExe jre} $out/bin/${meta.mainProgram} \ + --add-flags "-jar $out/share/java/$jarName" + + runHook postInstall + ''; + + meta = { + description = "Online logbook for experimental and industrial logging"; + homepage = "https://olog.readthedocs.io/en/latest/"; + mainProgram = "phoebus-olog"; + license = lib.licenses.epl10; + maintainers = with epnixLib.maintainers; [minijackson]; + inherit (jre.meta) platforms; + }; +} From 72bed6147f692d5ef75c59ca0009fc2fc1643255 Mon Sep 17 00:00:00 2001 From: Minijackson Date: Fri, 24 May 2024 12:57:42 +0200 Subject: [PATCH 003/111] phoebus-client: add webkit to openjfx fixes some applications, like the Log Entry Table, which couldn't be opened --- pkgs/epnix/tools/phoebus/client/default.nix | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/pkgs/epnix/tools/phoebus/client/default.nix b/pkgs/epnix/tools/phoebus/client/default.nix index 1c8de60e..44c58ad1 100644 --- a/pkgs/epnix/tools/phoebus/client/default.nix +++ b/pkgs/epnix/tools/phoebus/client/default.nix @@ -8,6 +8,7 @@ copyDesktopItems, epnix, jdk, + openjfx, }: let buildDate = "2022-02-24T07:56:00Z"; in @@ -21,6 +22,14 @@ in copyDesktopItems makeWrapper (epnix.phoebus-setup-hook.override {jdk = jdk.override {enableJavaFX = true;};}) + (epnix.phoebus-setup-hook.override { + jdk = jdk.override { + enableJavaFX = true; + openjfx = openjfx.override { + withWebKit = true; + }; + }; + }) ]; desktopItems = [ From 6535d50e646d89b5c0f0755f4ba8270a1d0b04cd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Jun 2024 09:00:17 +0000 Subject: [PATCH 004/111] build(deps): bump korthout/backport-action from 3.0.0 to 3.0.2 Bumps [korthout/backport-action](https://github.com/korthout/backport-action) from 3.0.0 to 3.0.2. - [Release notes](https://github.com/korthout/backport-action/releases) - [Commits](https://github.com/korthout/backport-action/compare/7e7cb1977d64d20339e8fdec12c0a1a065371de7...bd410d37cdcae80be6d969823ff5a225fe5c833f) --- updated-dependencies: - dependency-name: korthout/backport-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/backport.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml index 8cf872f4..a9c0d3d6 100644 --- a/.github/workflows/backport.yml +++ b/.github/workflows/backport.yml @@ -24,7 +24,7 @@ jobs: with: ref: ${{ github.event.pull_request.head.sha }} - name: Create backport PRs - uses: korthout/backport-action@7e7cb1977d64d20339e8fdec12c0a1a065371de7 # v3.0.0 + uses: korthout/backport-action@bd410d37cdcae80be6d969823ff5a225fe5c833f # v3.0.2 with: # Config README: https://github.com/korthout/backport-action#backport-action branch_name: backport/${pull_number}-to-${target_branch} From c52318c0a2b2f3ff8183ce26acf0ef4eb03bce6e Mon Sep 17 00:00:00 2001 From: Minijackson Date: Wed, 5 Jun 2024 10:37:04 +0200 Subject: [PATCH 005/111] templates/top: make EPNix release branch 23.11 the default --- templates/top/flake.nix | 51 ++++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 26 deletions(-) diff --git a/templates/top/flake.nix b/templates/top/flake.nix index b0aaa1d8..e934504b 100644 --- a/templates/top/flake.nix +++ b/templates/top/flake.nix @@ -2,7 +2,7 @@ description = "EPICS IOC for <...>"; inputs.flake-utils.url = "github:numtide/flake-utils"; - inputs.epnix.url = "github:epics-extensions/epnix"; + inputs.epnix.url = "github:epics-extensions/epnix/nixos-23.11"; # If you have a support module as a separate EPNix repository, # add it as an input here: @@ -80,35 +80,34 @@ # --- # "x86_64-linux" should still be specified so that the development # environment can be built on your machine. - flake-utils.lib.eachSystem ["x86_64-linux"] (system: - with epnix.lib; let - epnixDistribution = evalEpnixModules { - nixpkgsConfig = { - # This specifies the build architecture - inherit system; - - # This specifies the host architecture, uncomment for cross-compiling - # - # The complete of example architectures is here: - # https://github.com/NixOS/nixpkgs/blob/nixos-22.11/lib/systems/examples.nix - # --- - #crossSystem = epnix.inputs.nixpkgs.lib.systems.examples.armv7l-hf-multiplatform; - }; - epnixConfig = myEpnixConfig; + flake-utils.lib.eachSystem ["x86_64-linux"] (system: let + epnixDistribution = epnix.lib.evalEpnixModules { + nixpkgsConfig = { + # This specifies the build architecture + inherit system; + + # This specifies the host architecture, uncomment for cross-compiling + # + # The complete of example architectures is here: + # https://github.com/NixOS/nixpkgs/blob/nixos-22.11/lib/systems/examples.nix + # --- + #crossSystem = epnix.inputs.nixpkgs.lib.systems.examples.armv7l-hf-multiplatform; + }; + epnixConfig = myEpnixConfig; + }; + in { + packages = + epnixDistribution.outputs + // { + default = self.packages.${system}.build; }; - in { - packages = - epnixDistribution.outputs - // { - default = self.packages.${system}.build; - }; - inherit epnixDistribution; + inherit epnixDistribution; - devShells.default = self.packages.${system}.devShell; + devShells.default = self.packages.${system}.devShell; - checks = epnixDistribution.config.epnix.checks.derivations; - }) + checks = epnixDistribution.config.epnix.checks.derivations; + }) // { overlays.default = final: prev: self.epnixDistribution.x86_64-linux.generatedOverlay final prev; From 342c15968a76d8d2dd7aa57f4e66733b0f42fb4a Mon Sep 17 00:00:00 2001 From: Minijackson Date: Wed, 5 Jun 2024 10:54:14 +0200 Subject: [PATCH 006/111] doc/index: explain the concept of release branches --- doc/index.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/doc/index.md b/doc/index.md index cfb55370..d67fb159 100644 --- a/doc/index.md +++ b/doc/index.md @@ -41,11 +41,25 @@ However, since EPNix is a git repository, you will be able, through Nix, to use ```{=html} ``` + ## The epics-base package The epics-base package has no significant modification compared to the upstream version at [Launchpad]. One goal of EPNix is to keep those modifications to a minimum, and upstream what's possible. +# Release branches + +EPNix has a `master` branch, +which is considered unstable, +meaning breaking changes might happen without notice. + +EPNix also has release branches, +such as `nixos-23.11`, +tied to the nixpkgs release branches, +where breaking changes are forbidden. + +Backporting changes to older release branches is done on a "best-effort" basis. + ------------------------------------------------------------------------ This documentation follows the [Diátaxis] documentation framework. From 072198684d9706bc70533d6d6184b5f86d562a10 Mon Sep 17 00:00:00 2001 From: Minijackson Date: Wed, 5 Jun 2024 10:54:47 +0200 Subject: [PATCH 007/111] doc: use EPNix release branches in code excerpts --- doc/nixos/guides/_pre-requisites.md | 4 ++-- doc/nixos/tutorials/archiver-appliance.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/nixos/guides/_pre-requisites.md b/doc/nixos/guides/_pre-requisites.md index 82b49c70..d13fe83a 100644 --- a/doc/nixos/guides/_pre-requisites.md +++ b/doc/nixos/guides/_pre-requisites.md @@ -18,8 +18,8 @@ For example: ``` {.diff filename="flake.nix"} { # ... -+ inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11"; -+ inputs.epnix.url = "github:epics-extensions/EPNix"; + inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11"; ++ inputs.epnix.url = "github:epics-extensions/EPNix/nixos-23.11"; # ... outputs = { diff --git a/doc/nixos/tutorials/archiver-appliance.md b/doc/nixos/tutorials/archiver-appliance.md index 41681332..1e4a7e57 100644 --- a/doc/nixos/tutorials/archiver-appliance.md +++ b/doc/nixos/tutorials/archiver-appliance.md @@ -58,7 +58,7 @@ Fill the file with these lines: description = "Configuration for running Archiver Appliance in a VM"; inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11"; - inputs.epnix.url = "github:epics-extensions/EPNix"; + inputs.epnix.url = "github:epics-extensions/EPNix/nixos-23.11"; outputs = { self, nixpkgs, epnix }: { nixosConfigurations.nixos = nixpkgs.lib.nixosSystem { From 6d88fc0a787803ffd558b2f06f43e4c287665977 Mon Sep 17 00:00:00 2001 From: Minijackson Date: Wed, 5 Jun 2024 10:55:22 +0200 Subject: [PATCH 008/111] doc/_vale: move vale vocabulary to new location --- doc/_vale/{Vocab => config/vocabularies}/EPNix/accept.txt | 0 doc/_vale/{Vocab => config/vocabularies}/EPNix/reject.txt | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename doc/_vale/{Vocab => config/vocabularies}/EPNix/accept.txt (100%) rename doc/_vale/{Vocab => config/vocabularies}/EPNix/reject.txt (100%) diff --git a/doc/_vale/Vocab/EPNix/accept.txt b/doc/_vale/config/vocabularies/EPNix/accept.txt similarity index 100% rename from doc/_vale/Vocab/EPNix/accept.txt rename to doc/_vale/config/vocabularies/EPNix/accept.txt diff --git a/doc/_vale/Vocab/EPNix/reject.txt b/doc/_vale/config/vocabularies/EPNix/reject.txt similarity index 100% rename from doc/_vale/Vocab/EPNix/reject.txt rename to doc/_vale/config/vocabularies/EPNix/reject.txt From e72cbb41ded45b0c167299209389479e649e910e Mon Sep 17 00:00:00 2001 From: Minijackson Date: Wed, 5 Jun 2024 11:08:16 +0200 Subject: [PATCH 009/111] doc: fix dead link to old tutorial --- doc/ioc/faq.md | 4 ++-- doc/ioc/tutorials/integration-tests.md | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/doc/ioc/faq.md b/doc/ioc/faq.md index 3b521b9f..7d6b1b43 100644 --- a/doc/ioc/faq.md +++ b/doc/ioc/faq.md @@ -22,7 +22,7 @@ Use `_DEPEND_DIRS += `{.makefile} in your top-level `M Meaning, not versioning an App separate from the top. This might be justified if you don't intend to share an App in any other top. -1. First, create a top and an App, as in the [Getting Started] guide. +1. First, create a top and an App, as in the [StreamDevice tutorial]. 2. Make sure to add an exception for the `exampleApp` folder at the end of the top's `.gitignore` file: @@ -46,4 +46,4 @@ git add -N . 4. Finally, in your `flake.nix`, you can remove any input and value in `epnix.applications.apps` that refers to this directory. - [Getting Started]: ./tutorials/getting-started.md + [StreamDevice tutorial]: ./tutorials/streamdevice.md diff --git a/doc/ioc/tutorials/integration-tests.md b/doc/ioc/tutorials/integration-tests.md index c7b72773..0db48a66 100644 --- a/doc/ioc/tutorials/integration-tests.md +++ b/doc/ioc/tutorials/integration-tests.md @@ -6,7 +6,7 @@ title: Integration tests Through the [NixOS testing framework], EPNix provides a way of specifying a machine configuration, and running a Python script that can do various kind of testing. -If you created your IOC using the EPNix template, like suggested in the [Getting Started] documentation, you will see a `checks/` directory. +If you created your IOC using the EPNix template, like suggested in the [StreamDevice tutorial], you will see a `checks/` directory. This directory should contain the integration tests you want to run. To add an integration test to EPNix, record it in your `flake.nix` under the `epnix.checks.files` option. @@ -43,7 +43,7 @@ For an overview of what you can input in the machine configuration, please refer You can also read about the Python test script API [here][NixOS testing framework]. [NixOS testing framework]: https://nixos.org/manual/nixos/stable/index.html#sec-nixos-tests - [Getting Started]: ./getting-started.md + [StreamDevice tutorial]: ./streamdevice.md [NixOS documentation]: https://nixos.org/manual/nixos/stable/index.html#sec-configuration-syntax # Starting your IOC through systemd @@ -115,7 +115,6 @@ You can also look at examples either in the EPNix repository under the [`checks` ``` [here]: https://search.nixos.org/options?channel=21.11&from=0&size=50&sort=alpha_asc&type=packages&query=systemd.services. - [epics-systemd]: https://github.com/minijackson/epics-systemd [Packaging Python scripts]: ../guides/testing/packaging-python-scripts.md [NixOS tests documentation]: https://nixos.org/manual/nixos/stable/index.html#sec-nixos-tests [`checks` folder]: https://github.com/epics-extensions/epnix/tree/master/checks From 6d90961082771f80cfa55394cde9056c5f43ffdb Mon Sep 17 00:00:00 2001 From: Minijackson Date: Thu, 23 May 2024 09:55:57 +0200 Subject: [PATCH 010/111] phoebus-alarm-server: set meta.mainProgram --- pkgs/epnix/tools/phoebus/alarm-server/default.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/pkgs/epnix/tools/phoebus/alarm-server/default.nix b/pkgs/epnix/tools/phoebus/alarm-server/default.nix index 1563c8c1..9213422d 100644 --- a/pkgs/epnix/tools/phoebus/alarm-server/default.nix +++ b/pkgs/epnix/tools/phoebus/alarm-server/default.nix @@ -53,6 +53,7 @@ in meta = { description = "Monitor a configurable set of PVs and track their alarm state"; homepage = "https://control-system-studio.readthedocs.io/en/latest/services/alarm-server/doc/index.html"; + mainProgram = "phoebus-alarm-server"; license = lib.licenses.epl10; maintainers = with epnixLib.maintainers; [minijackson]; inherit (jdk.meta) platforms; From cfd42087efb726757702421b0425183eaa23f2cd Mon Sep 17 00:00:00 2001 From: Minijackson Date: Wed, 22 May 2024 10:43:49 +0200 Subject: [PATCH 011/111] nixos/phoebus-alarm-server: put config in /etc, install package useful for importing / exporting configs fixes #81 --- nixos/modules/phoebus/alarm-server.nix | 11 +++++++++-- nixos/tests/phoebus/alarm.py | 5 +++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/nixos/modules/phoebus/alarm-server.nix b/nixos/modules/phoebus/alarm-server.nix index d7ed08f4..736fc0b2 100644 --- a/nixos/modules/phoebus/alarm-server.nix +++ b/nixos/modules/phoebus/alarm-server.nix @@ -8,6 +8,7 @@ cfg = config.services.phoebus-alarm-server; settingsFormat = pkgs.formats.javaProperties {}; configFile = settingsFormat.generate "phoebus-alarm-server.properties" cfg.settings; + configLocation = "phoebus/alarm-server.properties"; in { options.services.phoebus-alarm-server = { enable = lib.mkEnableOption '' @@ -159,6 +160,12 @@ in { } ]; + environment = { + etc."${configLocation}".source = configFile; + # Useful for importing alarm sets + systemPackages = [pkgs.epnix.phoebus-alarm-server]; + }; + systemd.services.phoebus-alarm-server = { description = "Phoebus Alarm Server"; @@ -171,10 +178,10 @@ in { args = [ "-noshell" - "-settings ${configFile}" + "-settings /etc/${configLocation}" ] ++ (lib.optional cfg.createTopics "-create_topics"); - in "${pkgs.epnix.phoebus-alarm-server}/bin/phoebus-alarm-server ${lib.concatStringsSep " " args}"; + in "${lib.getExe pkgs.epnix.phoebus-alarm-server} ${lib.concatStringsSep " " args}"; DynamicUser = true; StateDirectory = "phoebus-alarm-server"; # TODO: systemd hardening diff --git a/nixos/tests/phoebus/alarm.py b/nixos/tests/phoebus/alarm.py index c17125ef..e6212a96 100644 --- a/nixos/tests/phoebus/alarm.py +++ b/nixos/tests/phoebus/alarm.py @@ -190,3 +190,8 @@ def logger_has_latest_state(_): assert alarm_states[2]["current_severity"] == "MAJOR" assert alarm_states[2]["severity"] == "MAJOR" assert alarm_states[2]["value"] == "4.0" + +with subtest("Can export alarm configuration"): + server.succeed("phoebus-alarm-server -settings /etc/phoebus/alarm-server.properties -export export.xml") + server.succeed("grep ALARM_TEST export.xml") + server.copy_from_vm("export.xml") From a6516b001dfb4d6c4c7ae73965ab81491080d903 Mon Sep 17 00:00:00 2001 From: Patrick Hilhorst Date: Thu, 13 Jun 2024 09:59:59 +0000 Subject: [PATCH 012/111] Archiver appliance: move to new owner --- pkgs/epnix/tools/archiver-appliance/default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/epnix/tools/archiver-appliance/default.nix b/pkgs/epnix/tools/archiver-appliance/default.nix index b28754b9..e27f5b03 100644 --- a/pkgs/epnix/tools/archiver-appliance/default.nix +++ b/pkgs/epnix/tools/archiver-appliance/default.nix @@ -14,7 +14,7 @@ stdenvNoCC.mkDerivation (self: { version = "1.1.0"; src = fetchFromGitHub { - owner = "slacmshankar"; + owner = "archiver-appliance"; repo = "epicsarchiverap"; rev = self.version; fetchSubmodules = true; From bb1f2b88d049f8cc91ab71245cb849c468faf104 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 17 Jun 2024 08:15:20 +0000 Subject: [PATCH 013/111] build(deps): bump actions/checkout from 4.1.6 to 4.1.7 Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.6 to 4.1.7. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/a5ac7e51b41094c92402da3b24376905380afc29...692973e3d937129bcbf40652eb9f2f61becf3332) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/backport.yml | 2 +- .github/workflows/book-gh-pages.yml | 2 +- .github/workflows/editorconfig.yml | 2 +- .github/workflows/formatting.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml index a9c0d3d6..3968462f 100644 --- a/.github/workflows/backport.yml +++ b/.github/workflows/backport.yml @@ -20,7 +20,7 @@ jobs: if: github.repository_owner == 'epics-extensions' && github.event.pull_request.merged == true && (github.event_name != 'labeled' || startsWith('backport', github.event.label.name)) runs-on: ubuntu-latest steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 with: ref: ${{ github.event.pull_request.head.sha }} - name: Create backport PRs diff --git a/.github/workflows/book-gh-pages.yml b/.github/workflows/book-gh-pages.yml index e3b8873c..96b3b6c3 100644 --- a/.github/workflows/book-gh-pages.yml +++ b/.github/workflows/book-gh-pages.yml @@ -23,7 +23,7 @@ jobs: url: ${{ steps.deployment.outputs.page_url }} runs-on: ubuntu-latest steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - uses: cachix/install-nix-action@ba0dd844c9180cbf77aa72a116d6fbc515d0e87b # v27 - name: "Build documentation book" run: | diff --git a/.github/workflows/editorconfig.yml b/.github/workflows/editorconfig.yml index 3c52c652..73bb11e0 100644 --- a/.github/workflows/editorconfig.yml +++ b/.github/workflows/editorconfig.yml @@ -10,7 +10,7 @@ jobs: editorconfig: runs-on: ubuntu-latest steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - uses: cachix/install-nix-action@ba0dd844c9180cbf77aa72a116d6fbc515d0e87b # v27 - name: "Check EditorConfig" run: nix run 'nixpkgs#eclint' --inputs-from . diff --git a/.github/workflows/formatting.yml b/.github/workflows/formatting.yml index f672e922..bc9e9142 100644 --- a/.github/workflows/formatting.yml +++ b/.github/workflows/formatting.yml @@ -10,7 +10,7 @@ jobs: alejandra: runs-on: ubuntu-latest steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - uses: cachix/install-nix-action@ba0dd844c9180cbf77aa72a116d6fbc515d0e87b # v27 - name: "Check Formatting" run: nix fmt -- --check . From abc9a0abb0f4b2cbdc2b72dab1471b3de1c79ccf Mon Sep 17 00:00:00 2001 From: Alexis Gaget Date: Wed, 20 Dec 2023 17:07:11 +0100 Subject: [PATCH 014/111] support/twincat-ads: add ESS ADS driver support (Beckhoff TwinCAT) --- pkgs/default.nix | 1 + pkgs/epnix/support/twincat-ads/default.nix | 40 ++++++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 pkgs/epnix/support/twincat-ads/default.nix diff --git a/pkgs/default.nix b/pkgs/default.nix index 7a8353de..5330dbe3 100644 --- a/pkgs/default.nix +++ b/pkgs/default.nix @@ -48,6 +48,7 @@ in snmp = callPackage ./epnix/support/snmp {}; sscan = callPackage ./epnix/support/sscan {}; StreamDevice = callPackage ./epnix/support/StreamDevice {}; + twincat-ads = callPackage ./epnix/support/twincat-ads {}; }); # EPICS related tools and extensions diff --git a/pkgs/epnix/support/twincat-ads/default.nix b/pkgs/epnix/support/twincat-ads/default.nix new file mode 100644 index 00000000..281f84d5 --- /dev/null +++ b/pkgs/epnix/support/twincat-ads/default.nix @@ -0,0 +1,40 @@ +{ + lib, + epnixLib, + epnix, + mkEpicsPackage, + fetchFromGitLab, + local_config_site ? {}, + local_release ? {}, +}: +mkEpicsPackage rec { + pname = "twincat-ads"; + version = "2024.01.11"; + varname = "TWINCATADS"; + + inherit local_config_site local_release; + + src = fetchFromGitLab { + domain = "gitlab.esss.lu.se"; + owner = "epics-modules"; + repo = "epics-twincat-ads"; + rev = "c8e8b52c1f34640eca97b8fb053e793dc68acc0a"; + fetchSubmodules = true; + sha256 = "sha256-f7hod1N1AzCh+W7nHl9VCA+nuwpJAboSh19Dq80n/2E="; + }; + + propagatedBuildInputs = with epnix.support; [asyn calc]; + + preBuild = '' + touch configure/RELEASE_PATHS.local + touch configure/RELEASE_LIBS.local + ''; + + meta = { + description = "Module providing EPICS support for ADS Protocol (Automation Device Specification)"; + homepage = "https://gitlab.esss.lu.se/epics-modules/epics-twincat-ads"; + # Wait for ESS team answer about the license : https://gitlab.esss.lu.se/epics-modules/epics-twincat-ads/-/issues/1 + license = lib.licenses.free; + maintainers = with epnixLib.maintainers; [agaget]; + }; +} From be5ebeac8690d248489701a66ad7f358185386ea Mon Sep 17 00:00:00 2001 From: Minijackson Date: Tue, 2 Jul 2024 09:20:05 +0200 Subject: [PATCH 015/111] python3Packages: define python packages for all python versions --- pkgs/default.nix | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/pkgs/default.nix b/pkgs/default.nix index 5330dbe3..3df759f8 100644 --- a/pkgs/default.nix +++ b/pkgs/default.nix @@ -9,10 +9,14 @@ in mkEpicsPackage = callPackage ./build-support/mk-epics-package.nix {}; - python3Packages = prev.python3Packages.overrideScope (final: prev: { - lewis = final.callPackage ./epnix/tools/lewis {}; - scanf = final.callPackage ./epnix/tools/scanf {}; - }); + pythonPackagesExtensions = + prev.pythonPackagesExtensions + ++ [ + (final: prev: { + lewis = final.callPackage ./epnix/tools/lewis {}; + scanf = final.callPackage ./epnix/tools/scanf {}; + }) + ]; epnix = recurseExtensible (self: { # EPICS base From 2f7bd2c88b7840deb4e06e5ff830298ee458b403 Mon Sep 17 00:00:00 2001 From: Minijackson Date: Tue, 2 Jul 2024 09:21:40 +0200 Subject: [PATCH 016/111] python3Packages.pyepics: init at 3.5.6 --- pkgs/default.nix | 3 +- pkgs/epnix/python-modules/pyepics/default.nix | 64 +++++++++++++++++++ 2 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 pkgs/epnix/python-modules/pyepics/default.nix diff --git a/pkgs/default.nix b/pkgs/default.nix index 3df759f8..d2c1817b 100644 --- a/pkgs/default.nix +++ b/pkgs/default.nix @@ -14,6 +14,7 @@ in ++ [ (final: prev: { lewis = final.callPackage ./epnix/tools/lewis {}; + pyepics = final.callPackage ./epnix/python-modules/pyepics {}; scanf = final.callPackage ./epnix/tools/scanf {}; }) ]; @@ -61,7 +62,7 @@ in ca-gateway = callPackage ./epnix/tools/ca-gateway {}; - inherit (final.python3Packages) lewis; + inherit (final.python3Packages) lewis pyepics; inherit (callPackage ./epnix/tools/lewis/lib.nix {}) mkLewisSimulator; pcas = callPackage ./epnix/tools/pcas {}; diff --git a/pkgs/epnix/python-modules/pyepics/default.nix b/pkgs/epnix/python-modules/pyepics/default.nix new file mode 100644 index 00000000..644a4978 --- /dev/null +++ b/pkgs/epnix/python-modules/pyepics/default.nix @@ -0,0 +1,64 @@ +{ + stdenv, + epnix, + epnixLib, + buildPythonPackage, + fetchPypi, + setuptools, + setuptools-scm, + pyparsing, + numpy, + importlib-resources, +}: +buildPythonPackage rec { + pname = "pyepics"; + version = "3.5.6"; + format = "pyproject"; + + src = fetchPypi { + inherit pname version; + hash = "sha256-NYj8EVZHTgZR13DZ46ggXRFkqBROJI/CzaNghB7OCwc="; + }; + + nativeBuildInputs = [ + setuptools + setuptools-scm + ]; + + buildInputs = [epnix.epics-base]; + + propagatedBuildInputs = [ + pyparsing + numpy + importlib-resources + ]; + + postInstall = let + # TODO: this only works for x86_64-linux + inherit (stdenv) hostPlatform; + kernel = hostPlatform.parsed.kernel.name; + arch = + if hostPlatform.isx86 + then "" + else hostPlatform.parsed.cpu.family; + bits = toString hostPlatform.parsed.cpu.bits; + system = "${kernel}${arch}${bits}"; + + epicsSystem = epnixLib.toEpicsArch hostPlatform; + in '' + clibsDir=($out/lib/python*/site-packages/epics/clibs) + rm -rf $clibsDir/*/ + mkdir $clibsDir/${system} + # No need to copy libCom, since libca depend on it + ln -st $clibsDir/${system} ${epnix.epics-base}/lib/${epicsSystem}/libca.so + ''; + + pythonImportsCheck = ["epics"]; + + meta = { + description = "Python interface to Epics Channel Access"; + homepage = "https://github.com/pyepics/pyepics"; + license = epnixLib.licenses.epics; + maintainers = with epnixLib.maintainers; [minijackson]; + }; +} From 3e53f2e2701df99ce7c08177ba1723ad9d81e41c Mon Sep 17 00:00:00 2001 From: Minijackson Date: Wed, 3 Jul 2024 16:06:37 +0200 Subject: [PATCH 017/111] ioc/tests/pyepics: init simple test --- ioc/tests/default.nix | 2 ++ ioc/tests/pyepics/default.nix | 47 +++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 ioc/tests/pyepics/default.nix diff --git a/ioc/tests/default.nix b/ioc/tests/default.nix index 7f7d020e..4150e7d8 100644 --- a/ioc/tests/default.nix +++ b/ioc/tests/default.nix @@ -4,6 +4,8 @@ with pkgs.lib; default-ioc-epics-base-3 = import ./default-ioc "3" args; default-ioc-epics-base-7 = import ./default-ioc "7" args; + pyepics = import ./pyepics args; + support-autosave-simple = import ./support/autosave/simple args; support-pvxs-ioc = import ./support/pvxs/ioc args; support-pvxs-qsrv2 = import ./support/pvxs/qsrv2 args; diff --git a/ioc/tests/pyepics/default.nix b/ioc/tests/pyepics/default.nix new file mode 100644 index 00000000..7c11aabc --- /dev/null +++ b/ioc/tests/pyepics/default.nix @@ -0,0 +1,47 @@ +{pkgs, ...}: let + inherit (pkgs) epnixLib lib; +in + pkgs.nixosTest { + name = "pytest"; + meta.maintainers = with epnixLib.maintainers; [minijackson]; + + extraPythonPackages = p: [p.pyepics]; + skipTypeCheck = true; + + nodes.ioc = { + imports = [ + (epnixLib.testing.softIoc '' + record(ai, "AI") { } + record(stringout, "STRINGOUT") { } + '') + ]; + }; + + testScript = let + python = lib.getExe (pkgs.python3.withPackages (p: [p.pyepics])); + iocTestScript = pkgs.writeText "iocTestScript.py" '' + import os + + import epics + + os.environ["EPICS_CA_AUTO_ADDR_LIST"] = "NO" + os.environ["EPICS_CA_ADDR_LIST"] = "localhost" + + stringout = epics.PV("STRINGOUT") + + assert epics.caget("AI") == 0 + assert stringout.get() == "" + + assert epics.caput("AI", 42.0, wait=True) == 1 + assert stringout.put("hello", wait=True) == 1 + + assert epics.caget("AI") == 42 + assert stringout.get() == "hello" + ''; + in '' + start_all() + ioc.wait_for_unit("ioc.service") + + print(ioc.succeed("${python} ${iocTestScript}")) + ''; + } From 39655aa47d0d76e16c078cde7e6dc40d24e74f8c Mon Sep 17 00:00:00 2001 From: Patrick Hilhorst Date: Fri, 5 Jul 2024 08:27:13 +0000 Subject: [PATCH 018/111] epics-base7: 7.0.8 -> 7.0.8.1 --- pkgs/default.nix | 4 ++-- pkgs/epnix/epics-base/default.nix | 8 ++++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/pkgs/default.nix b/pkgs/default.nix index 5330dbe3..00259966 100644 --- a/pkgs/default.nix +++ b/pkgs/default.nix @@ -18,8 +18,8 @@ in # EPICS base epics-base7 = callPackage ./epnix/epics-base { - version = "7.0.8"; - hash = "sha256-GEkUwlOkRhQ6LskxHV+eDvBe9UUzF2YWWmgiyuiHypM="; + version = "7.0.8.1"; + hash = "sha256-JDSMBwBLZj9aaxJHGg0QmZ1zYTSY8J7+ZGihAwEuz3w="; }; epics-base3 = callPackage ./epnix/epics-base { version = "3.15.9"; diff --git a/pkgs/epnix/epics-base/default.nix b/pkgs/epnix/epics-base/default.nix index 988ee2af..1ef55fdd 100644 --- a/pkgs/epnix/epics-base/default.nix +++ b/pkgs/epnix/epics-base/default.nix @@ -136,10 +136,14 @@ in # TODO: Some tests fail doCheck = false; - # _FORTIFY_SOURCE=3 causes a buffer overflow in some cases: + # _FORTIFY_SOURCE=3 detects a false-positive buffer overflow in some cases: # *** buffer overflow detected ***: terminated # - # Fall back to _FORTIFY_SOURCE=2 + # EPICS automatically falls back to _FORTIFY_SOURCE=2 since 7.0.8.1, but this doesn't work in + # the nix build. + # Being tracked in https://github.com/epics-base/epics-base/issues/514, hopefully with a fix + # in EPICS 7.0.9 + hardeningDisable = ["fortify3"]; meta = { From fb0f666092eee696f2e7816b66296ae633177c74 Mon Sep 17 00:00:00 2001 From: Minijackson Date: Mon, 8 Jul 2024 14:28:16 +0200 Subject: [PATCH 019/111] linuxPackages.mrf: init at 2.6.0 same version as mrfioc2 --- pkgs/default.nix | 9 +++++ pkgs/epnix/kernel-modules/mrf/default.nix | 43 +++++++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 pkgs/epnix/kernel-modules/mrf/default.nix diff --git a/pkgs/default.nix b/pkgs/default.nix index 5330dbe3..efa4b5ea 100644 --- a/pkgs/default.nix +++ b/pkgs/default.nix @@ -14,6 +14,15 @@ in scanf = final.callPackage ./epnix/tools/scanf {}; }); + linuxKernel = + prev.linuxKernel + // { + packagesFor = kernel: + (prev.linuxKernel.packagesFor kernel).extend (final: _prev: { + mrf = final.callPackage ./epnix/kernel-modules/mrf {}; + }); + }; + epnix = recurseExtensible (self: { # EPICS base diff --git a/pkgs/epnix/kernel-modules/mrf/default.nix b/pkgs/epnix/kernel-modules/mrf/default.nix new file mode 100644 index 00000000..2da2ef49 --- /dev/null +++ b/pkgs/epnix/kernel-modules/mrf/default.nix @@ -0,0 +1,43 @@ +{ + stdenv, + lib, + kernel, + epnix, +}: +stdenv.mkDerivation (finalAttrs: { + pname = "mrf-driver"; + + inherit (epnix.support.mrfioc2) version src; + + # Needed for kernel modules + hardeningDisable = ["format" "pic"]; + + nativeBuildInputs = kernel.moduleBuildDependencies; + + enableParallelBuilding = true; + + setSourceRoot = '' + export sourceRoot="$(pwd)/${finalAttrs.src.name}/mrmShared/linux"; + ''; + + makeFlags = + kernel.makeFlags + ++ [ + "-C" + "${kernel.dev}/lib/modules/${kernel.modDirVersion}/build" + "KERNELRELEASE=${kernel.modDirVersion}" + "INSTALL_MOD_PATH=$(out)" + "VERSION=${finalAttrs.version}" + "M=$(sourceRoot)" + # Uncomment this line to enable debugging + # "KCFLAGS=-DDBG" + ]; + + buildFlags = ["modules"]; + installTargets = ["modules_install"]; + + meta = { + description = "MRF kernel driver"; + inherit (epnix.support.mrfioc2.meta) homepage license maintainers; + }; +}) From 34d14bdca2e0b6d85f3ff80370002297d2541401 Mon Sep 17 00:00:00 2001 From: Minijackson Date: Mon, 8 Jul 2024 14:28:53 +0200 Subject: [PATCH 020/111] pkgs/tests: init for testing build of unexposed packages --- flake.nix | 1 + pkgs/tests/default.nix | 8 ++++++++ 2 files changed, 9 insertions(+) create mode 100644 pkgs/tests/default.nix diff --git a/flake.nix b/flake.nix index 63c68160..2a73ab8b 100644 --- a/flake.nix +++ b/flake.nix @@ -42,6 +42,7 @@ constituents = builtins.attrValues self.packages.${system}; }; } + // (import ./pkgs/tests {inherit pkgs self;}) // (import ./ioc/tests {inherit pkgs self;}) // (import ./nixos/tests/all-tests.nix {inherit nixpkgs pkgs self system;}); diff --git a/pkgs/tests/default.nix b/pkgs/tests/default.nix new file mode 100644 index 00000000..bb76486b --- /dev/null +++ b/pkgs/tests/default.nix @@ -0,0 +1,8 @@ +# For packages that are not directly exposed to the user, +# but should still work. +# +# For example kernel modules, which depend on the kernel version, +# or Python libraries, which depend on the Python version. +{pkgs, ...}: { + mrf-driver-default-linux = pkgs.linuxPackages.mrf; +} From 210c07d32ef1d2266cc535c3b529719713cc4470 Mon Sep 17 00:00:00 2001 From: Minijackson Date: Thu, 25 Jul 2024 14:09:56 +0200 Subject: [PATCH 021/111] github: init Update flake.lock action So that we stay up-to-date, even inside a release branch --- .github/workflows/update-flake-lock.yml | 37 +++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 .github/workflows/update-flake-lock.yml diff --git a/.github/workflows/update-flake-lock.yml b/.github/workflows/update-flake-lock.yml new file mode 100644 index 00000000..fc1aecc8 --- /dev/null +++ b/.github/workflows/update-flake-lock.yml @@ -0,0 +1,37 @@ +name: Update flake.lock +on: + workflow_dispatch: # allows manual triggering + schedule: + - cron: '0 0 * * 0' # runs weekly on Sunday at 00:00 + +# WARNING: +# When extending this action, be aware that $GITHUB_TOKEN allows write access to +# the GitHub repository. This means that it should not evaluate user input in a +# way that allows code injection. + +permissions: + contents: read + +jobs: + lockfile: + strategy: + matrix: + branch: + - master + - nixos-23.11 + - nixos-23.05 + permissions: + contents: write # to create branch + pull-requests: write # to create PR to backport + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + with: + ref: ${{ matrix.branch }} + - uses: cachix/install-nix-action@ba0dd844c9180cbf77aa72a116d6fbc515d0e87b # v27 + - uses: DeterminateSystems/update-flake-lock@db4ee38117a597ea8df8f7f75a187dd65093eade # v23 + with: + branch: "update-flake-lock/${{ matrix.branch }}" + pr-title: "[${{ matrix.branch }}] Update flake.lock" + pr-labels: | + dependencies From b333f3a0153e12908c61155022f15e3658f36568 Mon Sep 17 00:00:00 2001 From: Minijackson Date: Thu, 25 Jul 2024 15:10:15 +0200 Subject: [PATCH 022/111] phoebus-client: hardcode Python path for the console view Upstream defaults to /usr/bin/python3, which doesn't exist on NixOS Fixes #100 --- pkgs/epnix/tools/phoebus/client/default.nix | 17 +++++++++++++++++ .../tools/phoebus/client/fix-python-path.patch | 17 +++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 pkgs/epnix/tools/phoebus/client/fix-python-path.patch diff --git a/pkgs/epnix/tools/phoebus/client/default.nix b/pkgs/epnix/tools/phoebus/client/default.nix index 44c58ad1..e40263e6 100644 --- a/pkgs/epnix/tools/phoebus/client/default.nix +++ b/pkgs/epnix/tools/phoebus/client/default.nix @@ -2,6 +2,7 @@ lib, epnixLib, stdenv, + substituteAll, maven, makeWrapper, makeDesktopItem, @@ -9,6 +10,7 @@ epnix, jdk, openjfx, + python3, }: let buildDate = "2022-02-24T07:56:00Z"; in @@ -16,6 +18,13 @@ in pname = "phoebus"; inherit (epnix.phoebus-deps) version src; + patches = [ + (substituteAll { + src = ./fix-python-path.patch; + python = lib.getExe python3; + }) + ]; + # TODO: make a scope, so that we don't pass around the whole `epnix` nativeBuildInputs = [ maven @@ -32,6 +41,14 @@ in }) ]; + # Put runtime dependencies in propagated + # because references get thrown into a jar + # which is compressed, + # so the Nix scanner won't always be able to see them + propagatedBuildInputs = [ + python3 + ]; + desktopItems = [ (makeDesktopItem { name = "phoebus"; diff --git a/pkgs/epnix/tools/phoebus/client/fix-python-path.patch b/pkgs/epnix/tools/phoebus/client/fix-python-path.patch new file mode 100644 index 00000000..f9e2e8f9 --- /dev/null +++ b/pkgs/epnix/tools/phoebus/client/fix-python-path.patch @@ -0,0 +1,17 @@ +diff --git a/app/console/src/main/resources/console_preferences.properties b/app/console/src/main/resources/console_preferences.properties +index e00d6f8ec..e3bc52f3e 100644 +--- a/app/console/src/main/resources/console_preferences.properties ++++ b/app/console/src/main/resources/console_preferences.properties +@@ -28,9 +28,9 @@ prompt_info=Enter console command + # /bin/bash + # + # Value may include properties. +-shell=/usr/bin/python -i ++shell=@python@ -i + + # Folder where the shell process should be started + # + # Value may include properties. +-directory=$(user.home) +\ No newline at end of file ++directory=$(user.home) From d90443fecce486ab4e773d336e6e55069d744ef4 Mon Sep 17 00:00:00 2001 From: Minijackson Date: Thu, 25 Jul 2024 15:11:38 +0200 Subject: [PATCH 023/111] phoebus-client: remove outdated comment --- pkgs/default.nix | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/pkgs/default.nix b/pkgs/default.nix index 7ca5282a..c7260268 100644 --- a/pkgs/default.nix +++ b/pkgs/default.nix @@ -67,11 +67,7 @@ in pcas = callPackage ./epnix/tools/pcas {}; - phoebus = callPackage ./epnix/tools/phoebus/client { - # TODO: uncomment when this works: - # TODO: add libjfxwebkit.so into openjfx - # jdk = final.openjdk17.override {enableJavaFX = true;}; - }; + phoebus = callPackage ./epnix/tools/phoebus/client {}; phoebus-alarm-server = callPackage ./epnix/tools/phoebus/alarm-server {}; phoebus-alarm-logger = callPackage ./epnix/tools/phoebus/alarm-logger {}; phoebus-archive-engine = callPackage ./epnix/tools/phoebus/archive-engine {}; From 8562a1402d38825ddf3eb214abc9270ce922862e Mon Sep 17 00:00:00 2001 From: Minijackson Date: Thu, 25 Jul 2024 15:11:59 +0200 Subject: [PATCH 024/111] phoebus-client: fix .desktop file categories Reading through the spec[1] and the warnings, it says that an application should have only one "Main Category" to prevent the application to be displayed in multiple places in the menu. Apparently, "Additional Categories" also automatically inherits from their "Main Category", so I had to remove a bunch. [1]: https://specifications.freedesktop.org/menu-spec/menu-spec-1.0.html#category-registry --- pkgs/epnix/tools/phoebus/client/default.nix | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/pkgs/epnix/tools/phoebus/client/default.nix b/pkgs/epnix/tools/phoebus/client/default.nix index e40263e6..631362df 100644 --- a/pkgs/epnix/tools/phoebus/client/default.nix +++ b/pkgs/epnix/tools/phoebus/client/default.nix @@ -55,15 +55,14 @@ in exec = "phoebus -server 4918 -resource %f"; desktopName = "Phoebus"; keywords = ["epics" "css"]; + # https://specifications.freedesktop.org/menu-spec/menu-spec-1.0.html#category-registry categories = [ + # Main "Office" - "Graphics" - "GUIDesigner" - "Viewer" - "Science" - "Physics" - "Monitor" + + # Additional "Java" + "Viewer" ]; }) ]; From 0a8d7dad83db17553527a6618250152a5c28315e Mon Sep 17 00:00:00 2001 From: Minijackson Date: Thu, 25 Jul 2024 10:01:52 +0200 Subject: [PATCH 025/111] docs: init, converted and improved from Quarto to Sphinx this will hopefully be better for the future, as Sphinx & RST has some useful features for us, like documenting objects, custom link types, and overall a bigger community. --- docs/.gitignore | 1 + docs/Makefile | 20 + docs/_ext/pygments_styles.py | 197 +++++++++ docs/_static/.gitkeep | 0 docs/_templates/.gitkeep | 0 docs/conf.py | 107 +++++ docs/favicon.svg | 277 ++++++++++++ docs/index.rst | 103 +++++ docs/ioc/faq.rst | 50 +++ docs/ioc/index.rst | 44 ++ docs/ioc/tutorials/index.rst | 15 + docs/ioc/tutorials/integration-tests.rst | 141 ++++++ docs/ioc/tutorials/pre-requisites.rst | 80 ++++ docs/ioc/tutorials/streamdevice.rst | 303 +++++++++++++ docs/ioc/user-guides/developing-modules.rst | 99 +++++ docs/ioc/user-guides/flake-registry.rst | 34 ++ docs/ioc/user-guides/index.rst | 19 + docs/ioc/user-guides/private-repo-setup.rst | 165 +++++++ .../testing/packaging-python-scripts.rst | 200 +++++++++ docs/logo.svg | 411 ++++++++++++++++++ docs/nixos-services/index.rst | 9 + .../tutorials/archiver-appliance.rst | 365 ++++++++++++++++ docs/nixos-services/tutorials/index.rst | 13 + .../nixos-services/user-guides/ca-gateway.rst | 205 +++++++++ docs/nixos-services/user-guides/index.rst | 15 + .../user-guides/phoebus-alarm.rst | 223 ++++++++++ .../user-guides/phoebus-save-and-restore.rst | 52 +++ .../user-guides/pre-requisites.rst | 41 ++ pkgs/default.nix | 1 + pkgs/docs/default.nix | 127 ++++++ 30 files changed, 3317 insertions(+) create mode 100644 docs/.gitignore create mode 100644 docs/Makefile create mode 100644 docs/_ext/pygments_styles.py create mode 100644 docs/_static/.gitkeep create mode 100644 docs/_templates/.gitkeep create mode 100644 docs/conf.py create mode 100644 docs/favicon.svg create mode 100644 docs/index.rst create mode 100644 docs/ioc/faq.rst create mode 100644 docs/ioc/index.rst create mode 100644 docs/ioc/tutorials/index.rst create mode 100644 docs/ioc/tutorials/integration-tests.rst create mode 100644 docs/ioc/tutorials/pre-requisites.rst create mode 100644 docs/ioc/tutorials/streamdevice.rst create mode 100644 docs/ioc/user-guides/developing-modules.rst create mode 100644 docs/ioc/user-guides/flake-registry.rst create mode 100644 docs/ioc/user-guides/index.rst create mode 100644 docs/ioc/user-guides/private-repo-setup.rst create mode 100644 docs/ioc/user-guides/testing/packaging-python-scripts.rst create mode 100644 docs/logo.svg create mode 100644 docs/nixos-services/index.rst create mode 100644 docs/nixos-services/tutorials/archiver-appliance.rst create mode 100644 docs/nixos-services/tutorials/index.rst create mode 100644 docs/nixos-services/user-guides/ca-gateway.rst create mode 100644 docs/nixos-services/user-guides/index.rst create mode 100644 docs/nixos-services/user-guides/phoebus-alarm.rst create mode 100644 docs/nixos-services/user-guides/phoebus-save-and-restore.rst create mode 100644 docs/nixos-services/user-guides/pre-requisites.rst create mode 100644 pkgs/docs/default.nix diff --git a/docs/.gitignore b/docs/.gitignore new file mode 100644 index 00000000..e35d8850 --- /dev/null +++ b/docs/.gitignore @@ -0,0 +1 @@ +_build diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 00000000..d4bb2cbb --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line, and also +# from the environment for the first two. +SPHINXOPTS ?= +SPHINXBUILD ?= sphinx-build +SOURCEDIR = . +BUILDDIR = _build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/docs/_ext/pygments_styles.py b/docs/_ext/pygments_styles.py new file mode 100644 index 00000000..76e9ba1e --- /dev/null +++ b/docs/_ext/pygments_styles.py @@ -0,0 +1,197 @@ +"""Custom pygments highlight styles, based on Nord. + +Modified so that: + +- Nord has a light theme +- It is AA readable +- It uses the main blue colors of the EPNix logo +""" + +from pygments.style import Style +from pygments.token import ( + Comment, + Error, + Generic, + Keyword, + Name, + Number, + Operator, + Punctuation, + String, + Text, + Token, + Whitespace, +) + +# Nord palette +darker_nord0 = "#242933" +nord0 = "#2e3440" +nord1 = "#3b4252" +nord2 = "#434c5e" +nord3 = "#4c566a" +nord4 = "#d8dee9" +nord5 = "#e5e9f0" +nord6 = "#eceff4" +nord7 = "#8fbcbb" # blue green +nord8 = "#88c0d0" # light blue +nord9 = "#81a1c1" # blue +nord10 = "#5e81ac" # deep blue +nord11 = "#bf616a" # red +nord12 = "#d08770" # orange +nord13 = "#ebcb8b" # yellow +nord14 = "#a3be8c" # green +nord15 = "#b48ead" # purple + +# EPNix palette +epnix_blue0 = "#0b1924" +epnix_blue1 = "#18334b" +epnix_blue2 = "#5277c3" +epnix_blue3 = "#415e9a" +epnix_blue4 = "#7ebae4" + +epnix_dark_background = "#1a1c1e" # from the furo theme +epnix_light_background = "#f8f9fb" # from the furo theme + + +class EpnixNordLight(Style): + name = "epnix-nord-light" + + _green = "#577140" # nord11 with lightness darkened by 0.3 + _red = "#a9444e" # nord11 with lightness darkened by 0.1 + _orange = "#a45036" # nord12 with lightness darkened by 0.2 + _yellow = _orange # Can't get the yellow to work + _purple = "#84587c" # nord15 with lightness darkened by 0.2 + + _normal_text = nord0 + _faded_text = nord3 + _background = epnix_light_background + _highlight_background = nord4 + _comment = "#3f6e75" # stolen from the xcode style + _keyword = epnix_blue1 + _function = epnix_blue3 + _string = _green + + line_number_color = _faded_text + line_number_background_color = _background + line_number_special_color = _background + line_number_special_background_color = _faded_text + + background_color = _background + highlight_color = _highlight_background + + styles = { + Token: _normal_text, + Whitespace: _normal_text, + Punctuation: _normal_text, + Comment: f"italic {_comment}", + Comment.Preproc: _keyword, + Keyword: f"bold {_keyword}", + Keyword.Pseudo: f"nobold {_keyword}", + Keyword.Type: f"nobold {_keyword}", + Operator: f"bold {_keyword}", + Operator.Word: f"bold {_keyword}", + Name: _normal_text, + Name.Builtin: _keyword, + Name.Function: _function, + Name.Class: _function, + Name.Namespace: _function, + Name.Exception: _red, + Name.Variable: _normal_text, + Name.Constant: _function, + Name.Entity: _orange, + Name.Attribute: _function, + Name.Tag: _keyword, + Name.Decorator: _orange, + String: _string, + String.Doc: _comment, + String.Interpol: _string, + String.Escape: _yellow, + String.Regex: _yellow, + String.Symbol: _yellow, # modified, looks better with Nix + String.Other: _string, + Number: _purple, + Generic.Heading: f"bold {_function}", + Generic.Subheading: f"bold {_function}", + Generic.Deleted: _red, + Generic.Inserted: _green, + Generic.Error: _red, + Generic.Emph: "italic", + Generic.Strong: "bold", + Generic.Prompt: f"bold {_comment}", # modified + Generic.Output: _normal_text, + Generic.Traceback: _red, + Error: _red, + Text: _normal_text, + } + + +class EpnixNordDarker(Style): + """Based on "nord-darker".""" + + _green = nord14 + _red = "#ce858c" # nord11 with lightness lightened by 0.1 + _orange = nord12 + _yellow = nord13 + _purple = nord15 + + _normal_text = nord6 + _faded_text = nord4 + _background = epnix_dark_background # modified + _highlight_background = nord1 + _comment = nord9 # modified + _keyword = epnix_blue4 # modified + _function = nord7 # modified + _string = _green + + line_number_color = _faded_text + line_number_background_color = _background + line_number_special_color = _background + line_number_special_background_color = _faded_text + + background_color = _background + highlight_color = _highlight_background + + styles = { + Token: _normal_text, + Whitespace: _normal_text, + Punctuation: _normal_text, + Comment: f"italic {_comment}", + Comment.Preproc: _keyword, + Keyword: f"bold {_keyword}", + Keyword.Pseudo: f"nobold {_keyword}", + Keyword.Type: f"nobold {_keyword}", + Operator: f"bold {_keyword}", + Operator.Word: f"bold {_keyword}", + Name: _normal_text, + Name.Builtin: _keyword, + Name.Function: _function, + Name.Class: _function, + Name.Namespace: _function, + Name.Exception: _red, + Name.Variable: _normal_text, + Name.Constant: _function, + Name.Entity: _orange, + Name.Attribute: _function, + Name.Tag: _keyword, + Name.Decorator: _orange, + String: _string, + String.Doc: _comment, + String.Interpol: _string, + String.Escape: _yellow, + String.Regex: _yellow, + String.Symbol: _yellow, # modified, looks better with Nix + String.Other: _string, + Number: _purple, + Generic.Heading: f"bold {_function}", + Generic.Subheading: f"bold {_function}", + Generic.Deleted: _red, + Generic.Inserted: _green, + Generic.Error: _red, + Generic.Emph: "italic", + Generic.Strong: "bold", + Generic.Prompt: f"bold {_comment}", # modified + Generic.Output: _normal_text, + Generic.Traceback: _red, + Error: _red, + Text: _normal_text, + } diff --git a/docs/_static/.gitkeep b/docs/_static/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/docs/_templates/.gitkeep b/docs/_templates/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/docs/conf.py b/docs/conf.py new file mode 100644 index 00000000..f22ab5ea --- /dev/null +++ b/docs/conf.py @@ -0,0 +1,107 @@ +# Configuration file for the Sphinx documentation builder. +# +# For the full list of built-in configuration values, see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +import os +import sys + +# Enables importing our custom "pygments_styles" module +sys.path.append(os.path.abspath("./_ext")) + +# -- Project information ----------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information + +project = "EPNix" +copyright = "The EPNix Contributors" +author = "The EPNix Contributors" + +language = "en" + +nitpicky = True + +# -- General configuration --------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration + +extensions = [ + "myst_parser", + "sphinx.ext.githubpages", + "sphinx_copybutton", +] + +templates_path = ["_templates"] +exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] + +# numfig = True + +pygments_style = "pygments_styles.EpnixNordLight" +pygments_dark_style = "pygments_styles.EpnixNordDarker" + +# -- Options for MyST -------------------------------------------------------- +# https://myst-parser.readthedocs.io/en/latest/configuration.html + +myst_enable_extensions = [ + "attrs_inline", + "colon_fence", + "deflist", +] + +myst_url_schemes = { + "http": None, + "https": None, + "mailto": None, + "source": "https://github.com/epics-extensions/EPNix/blob/{{netloc}}{{path}}", + "gh-issue": { + "url": "https://github.com/executablebooks/MyST-Parser/issue/{{path}}#{{fragment}}", + "title": "Issue #{{path}}", + "classes": ["github"], + }, +} + +# -- Options for HTML output ------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output + +html_static_path = ["_static"] +html_baseurl = "https://epics-extensions.github.io/EPNix/" + +html_theme = "furo" +html_theme_options = { + "source_repository": "https://github.com/epics-extensions/EPNix", + "source_branch": "master", + "source_directory": "docs/", + "dark_css_variables": { + "color-brand-primary": "#7ebae4", + "color-brand-content": "#7ebae4", + }, + "light_css_variables": { + "color-brand-primary": "#415e9a", + "color-brand-content": "#415e9a", + }, + "footer_icons": [ + { + "name": "GitHub", + "url": "https://github.com/epics-extensions/EPNix", + "html": """ + + + + """, + "class": "", + }, + ], +} + +html_logo = "logo.svg" +html_favicon = "favicon.svg" + +# -- Options for Man output -------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-manual-page-output + +man_pages = [ + ("ioc/references/options", "epnix-ioc", "IOC options reference", "", 5), + ("ioc/references/packages", "epnix-ioc-packages", "", "", 5), + ("nixos-services/options", "epnix-nixos", "", "", 5), + ("pkgs/packages", "epnix-packages", "", "", 5), +] + +man_show_urls = True diff --git a/docs/favicon.svg b/docs/favicon.svg new file mode 100644 index 00000000..3a4bca6b --- /dev/null +++ b/docs/favicon.svg @@ -0,0 +1,277 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/docs/index.rst b/docs/index.rst new file mode 100644 index 00000000..5ee61f6c --- /dev/null +++ b/docs/index.rst @@ -0,0 +1,103 @@ +EPNix documentation +=================== + +.. figure:: logo.svg + :alt: EPNix logo + + EPNix logo + +Introduction +------------ + +EPNix (pronunciation: like you are high on mushrooms) packages EPICS-related software using the `Nix`_ package manager. + +It’s made of three parts: + +- the EPICS IOC framework +- other EPICS-related packages +- NixOS modules + +The EPICS IOC framework lets you package, deploy, and test EPICS IOCs +using the Nix package manager, which provides several benefits. +For more information, see the :doc:`EPICS IOCs introduction `. + +EPNix also packages other EPICS-related tools, like procServ, Phoebus, etc. +You can build them using Nix, and in the future download them pre-compiled, while having a strong guarantee that they will work as-is. +For a list of all supported EPICS-related packages, see the :doc:`pkgs/packages`. + +EPNix also provides NixOS modules, which are instructions on how to configure various EPICS-related services on NixOS machines (for example the Phoebus alarm server). +EPNix strives to have integration tests for each of those modules. +For more information, see the :doc:`NixOS services introduction `. + +.. _Nix: https://nixos.org/guides/how-nix-works/ + +Packaging policy +~~~~~~~~~~~~~~~~ + +As EPNix provides a package repository, packaging for example ``epics-base``, ``asyn``, ``StreamDevice``, ``procServ``, ``phoebus``, etc., it needs to have a packaging policy. + +In its package repository, EPNix officially supports the latest upstream version. + +However, since EPNix is a git repository, you will be able, through Nix, to use a fixed version of EPNix, without being forced to upgrade your dependencies. + +.. TODO: link to an explanation, from the IOC side, and from the NixOS side + +The epics-base package +^^^^^^^^^^^^^^^^^^^^^^ + +The epics-base package has no significant modification compared to the upstream version at `Launchpad`_. +One goal of EPNix is to keep those modifications to a minimum, and upstream what’s possible. + +.. _Launchpad: https://git.launchpad.net/epics-base + +Release branches +~~~~~~~~~~~~~~~~ + +EPNix has a ``master`` branch, +which is considered unstable, +meaning breaking changes might happen without notice. + +EPNix also has release branches, +such as ``nixos-23.11``, +tied to the nixpkgs release branches, +where breaking changes are forbidden. + +Backporting changes to older release branches is done on a “best-effort” basis. + +-------------- + +This documentation follows the `Diátaxis`_ documentation framework. + +.. _Diátaxis: https://diataxis.fr/ + +.. toctree:: + :caption: EPICS IOCs + :hidden: + :titlesonly: + + ioc/index + ioc/tutorials/index + ioc/user-guides/index + ioc/references/options + ioc/references/packages + ioc/faq + +.. toctree:: + :caption: Packages + :hidden: + :titlesonly: + + pkgs/packages + +.. toctree:: + :caption: NixOS services + :hidden: + :titlesonly: + + nixos-services/index + nixos-services/tutorials/index + nixos-services/user-guides/index + nixos-services/options + + +.. TODO: link an index to Nix options and packages diff --git a/docs/ioc/faq.rst b/docs/ioc/faq.rst new file mode 100644 index 00000000..b5ac60a0 --- /dev/null +++ b/docs/ioc/faq.rst @@ -0,0 +1,50 @@ +Frequently Asked Questions +========================== + +I am getting weird Git errors about an unknown ``-C`` option +------------------------------------------------------------ + +You may be using a system with an old version of Git. +You may install a recent version of Git for your user by running ``nix-env -iA nixpkgs.git``. + +A file I created isn’t found when I run ``nix build`` +----------------------------------------------------- + +If your top is a Git repository, you must ``git add`` those files to make them recognized by Nix. + +An App can’t find a build product from another App +-------------------------------------------------- + +EPNix enables parallel builds by default. +These means that if App dependencies aren’t specified, these Apps will compile in no particular order. +Use ``_DEPEND_DIRS += `` in your top-level ``Makefile``. + +How do I version a whole EPNix top? +----------------------------------- + +Meaning, not versioning an App separate from the top. +This might be justified if you don’t intend to share an App in any other top. + +1. First, create a top and an App, as in the :doc:`tutorials/streamdevice` tutorial. + +2. Make sure to add an exception for the ``exampleApp`` folder at the end of the top’s ``.gitignore`` file: + +.. code-block:: ini + + ... + # Applications and Support modules should be an EPNix dependency in flake.nix + *App + *Sup + # You can add exceptions like this: + # --- + #!myCustomLocalApp + !exampleApp + +3. Then, version both the top and the App: + +.. code-block:: bash + + git init + git add -N . + +4. Finally, in your ``flake.nix``, you can remove any input and value in ``epnix.applications.apps`` that refers to this directory. diff --git a/docs/ioc/index.rst b/docs/ioc/index.rst new file mode 100644 index 00000000..466275f3 --- /dev/null +++ b/docs/ioc/index.rst @@ -0,0 +1,44 @@ +Introduction +============ + +.. TODO: rewrite this into an introduction to the EPICS IOC part of EPNix + +EPNix (pronunciation: like you are high on mushrooms) provides a way of building and packaging EPICS IOCs using the `Nix`_ package manager. + +By leveraging the Nix package manager, +it provides several advantages compared to packaging EPICS the traditional way: + +Reproducibility: + Your development environment is the same as your coworker’s development environment, which is the same as your production environment. +Complete dependencies: + Your EPICS IOCs ship with the complete set of dependencies, which means you can to deploy your IOC without needing to install any dependency on the target machine (except for Nix itself). +Dependency traceability: + The version of your dependencies are locked, updated manually, and traced in your ``flake.lock`` file. + Combined with code versioning, you can build your project with the same environment years later, and you can roll back to any earlier version. +Development shell: + Provides you with a set of tools adapted to your project, no matter what you have installed on your machine. +Declarative configuration: + Define what you want in your IOC in a declarative and extendable manner. +Integration tests: + Write tests using Python, by starting a virtual machine with your IOC running. + +.. _Nix: https://nixos.org/guides/how-nix-works.html + +Packaging policy +~~~~~~~~~~~~~~~~ + +To be able to specify your dependencies in your EPNix configuration, EPNix provides a package repository, packaging for example ``epics-base``, ``asyn``, ``StreamDevice``, etc. + +In its package repository, EPNix officially supports the latest upstream version. + +However, since Nix “locks” your dependencies, this means you don’t need to upgrade your dependencies if you don’t want to. +What this means in practice: your IOC repository uses the EPNix project repository at a fixed commit, like using a repository at a fixed point in time. +Nix records this commit SHA in the ``flake.lock`` file, which should be checked out in your Git repository. + +The epics-base package +^^^^^^^^^^^^^^^^^^^^^^ + +The epics-base package has no significant modification compared to the upstream version at `Launchpad`_. +One goal of EPNix is to keep those modifications to a minimum, and upstream what’s possible. + +.. _Launchpad: https://git.launchpad.net/epics-base diff --git a/docs/ioc/tutorials/index.rst b/docs/ioc/tutorials/index.rst new file mode 100644 index 00000000..c4b48c61 --- /dev/null +++ b/docs/ioc/tutorials/index.rst @@ -0,0 +1,15 @@ +Tutorials +========= + +`Tutorials`_ for users of the EPNix project wanting to build and deploy EPICS IOCs. + +.. _Tutorials: https://diataxis.fr/tutorials/ + +---- + +.. toctree:: + :maxdepth: 1 + + ./pre-requisites.rst + ./streamdevice.rst + ./integration-tests.rst diff --git a/docs/ioc/tutorials/integration-tests.rst b/docs/ioc/tutorials/integration-tests.rst new file mode 100644 index 00000000..77be658e --- /dev/null +++ b/docs/ioc/tutorials/integration-tests.rst @@ -0,0 +1,141 @@ +Integration tests +================= + +Writing the test +---------------- + +Through the `NixOS testing framework`_, +EPNix provides a way of specifying a machine configuration, +and running a Python script that can do various kind of testing. + +If you created your IOC using the EPNix template, +like suggested in the :doc:`streamdevice` tutorial, +you will see a ``checks/`` directory. +This directory should contain the integration tests you want to run. + +To add an integration test to EPNix, +record it in your ``flake.nix`` under the ``epnix.checks.files`` option. + +For example, in the EPNix template, you will see in your ``flake.nix`` file: + +.. code-block:: nix + + checks.files = [ ./checks/simple.nix ]; + +The ``./checks/.nix`` file should contain a NixOS test like so: + +.. code-block:: nix + + { build, pkgs, ... }: + + pkgs.nixosTest { + name = "myTest"; + + machine = { + # Description of the NixOS machine... + }; + + testScript = '' + # Python script that does the testing... + ''; + } + +This test will create a NixOS virtual machine +from the given configuration, +and run the test script. +Note that the test script does *not* run on the virtual machine, +but communicates with it. +This is because the test script can start, +shut down, +or reboot the machine, +and also because NixOS tests can also manage several virtual machines, +not just one. + +For an overview of what you can input in the machine configuration, +please refer to the `NixOS documentation`_. +You can also read more about it +in the `Python test script API documentation`_. + +.. _NixOS testing framework: https://nixos.org/manual/nixos/stable/index.html#sec-nixos-tests +.. _NixOS documentation: https://nixos.org/manual/nixos/stable/index.html#sec-configuration-syntax +.. _Python test script API documentation: https://nixos.org/manual/nixos/stable/index.html#sec-nixos-tests + +Starting your IOC through systemd +--------------------------------- + +We recommend starting your IOC through a systemd service, +which you can describe in Nix like so: + +.. TODO: change that + +.. code-block:: nix + + # Inside the `machine` attribute + { + systemd.services.my-ioc = { + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + ExecStart = "${build}/iocBoot/iocexample/st.cmd"; + WorkingDirectory = "${build}/iocBoot/iocexample"; + + # Makes the EPICS command-line not quit for 100 seconds, if it doesn't + # receive anything on the standard input + StandardInputText = "epicsThreadSleep(100)"; + }; + }; + + # Provides the caget / caput / etc. commands to the test script + environment.systemPackages = [ pkgs.epnix.epics-base ]; + } + +You can view the list of options available for a NixOS machine `here `__. + +Then, you can write your test script. +Note that the test script doesn’t run directly on the machine, +but communicates with the machine through the ``machine`` variable. + +An example of a testing script: + +.. code-block:: python + + start_all() + + machine.wait_for_unit("default.target") + machine.wait_for_unit("my-ioc.service") + + machine.wait_until_succeeds("caget stringin") + machine.wait_until_succeeds("caget stringout") + machine.fail("caget non-existing") + + with subtest("testing stringout"): + def test_stringout(_) -> bool: + machine.succeed("caput stringout 'hello'") + status, _output = machine.execute("caget -t stringout | grep -qxF 'hello'") + + return status == 0 + + retry(test_stringout) + + assert "hello" not in machine.succeed("caget -t stringin") + +Note that the script extensively uses the ``wait_until_succeeds`` method and the ``retry`` function. +This is because EPICS has few guarantees about whether it propagates changes immediately, +and so it’s better to encourage the use of retries, +instead of hoping the timing lines up. + +If you would like to use a fully fledged python script on the machine, +which can use Python dependencies like pyepics, +please refer to the guide :doc:`../user-guides/testing/packaging-python-scripts`. + +You can find methods available on the ``machine`` variable and other particularities in the `NixOS tests documentation`_. + +You can also look at examples either in the EPNix repository, +under the `ioc/tests folder`_, +or in nixpkgs under the `nixos/tests folder`_. + +.. TODO: this doesn't explain how to run the test + +.. _Packaging Python scripts: ../guides/testing/packaging-python-scripts.md +.. _NixOS tests documentation: https://nixos.org/manual/nixos/stable/index.html#sec-nixos-tests +.. _ioc/tests folder: https://github.com/epics-extensions/epnix/tree/master/ioc/tests +.. _nixos/tests folder: https://github.com/NixOS/nixpkgs/tree/master/nixos/tests diff --git a/docs/ioc/tutorials/pre-requisites.rst b/docs/ioc/tutorials/pre-requisites.rst new file mode 100644 index 00000000..4fa38d15 --- /dev/null +++ b/docs/ioc/tutorials/pre-requisites.rst @@ -0,0 +1,80 @@ +Pre-requisites +============== + +The requirements for using EPNix are having curl, Nix, and Git installed, +either in a Linux system, +or in Windows’ WSL2. +Nix must be configured with “flakes” enabled. + +You *don’t* need to have EPICS base installed globally, +EPNix makes it available to you +when you enter your top’s development shell. + +Having a global EPICS base installation shouldn’t pose any issue. + +Installing Nix +-------------- + +.. warning:: + + If you use a Linux distribution with SELinux, + be sure to turn it off. + You can do this by adding the line ``SELINUX=disabled`` in ``/etc/sysconfig/selinux`` + on distributions based on RedHat Enterprise Linux (RHEL) like CentOS, Rocky Linux, and so on. + +If you don’t have Nix installed, +first follow the `official instructions`_. +Make sure to have the ``xz`` utility installed beforehand, +often part of the ``xzip`` or ``xz`` package. + +Unless you use WSL2, +use the multi-user installation, +because it builds packages in an isolated environment. + +.. _official instructions: https://nixos.org/download/#nix-install-linux + +Enabling Nix flakes and the ``nix`` command +------------------------------------------- + +Because Nix flakes and the unified ``nix`` command are experimental features at the time of writing, +you need to enable them in your ``/etc/nix/nix.conf``. + +To enable this feature, +add this line to your ``/etc/nix/nix.conf``: + +.. code-block:: ini + + experimental-features = nix-command flakes + +If you have installed Nix in multi-user mode, +then you have to restart the Nix daemon by running: + +.. code-block:: bash + + systemctl restart nix-daemon.service + +Untracked files and Nix flakes +------------------------------ + +One important thing with Nix flakes: +when your flake is in a Git repository, +Nix only considers files that Git tracks. + +For example, +if your ``flake.nix`` is in a Git repository, +and you create a file ``foobar.txt``, +you must run ``git add [-N] foobar.txt`` to make Nix recognize it. + +This prevents copying build products into the Nix store. + +Git version +----------- + +If you use an old system and see Git errors when using Nix, +install a recent version of Git by running this: + +.. code-block:: bash + + nix-env -iA nixpkgs.git + +This command installs a recent version of Git for your current user. diff --git a/docs/ioc/tutorials/streamdevice.rst b/docs/ioc/tutorials/streamdevice.rst new file mode 100644 index 00000000..528a7c9e --- /dev/null +++ b/docs/ioc/tutorials/streamdevice.rst @@ -0,0 +1,303 @@ +Creating a StreamDevice IOC +=========================== + +In this tutorial, +you’re going to learn how to create an EPICS IOC with EPNix +that communicates with a power supply, +using the `StreamDevice`_ support module. + +.. _StreamDevice: https://paulscherrerinstitute.github.io/StreamDevice/ + +Pre-requisites +-------------- + +Verify that you have all pre-requisites installed. +If not, +follow the :doc:`./pre-requisites` section. + +Running the power supply simulator +---------------------------------- + +EPNix has a power supply simulator +for you to test your IOC. + +To run it: + +.. code-block:: bash + + nix run 'github:epics-extensions/epnix#psu-simulator' + +For the rest of the tutorial, +leave it running in a separate terminal. + +Creating your top +----------------- + +We can use these command to create an EPNix top: + +.. code-block:: bash + + # Initialise an EPNix top + nix flake new -t 'github:epics-extensions/epnix' my-top + cd my-top + + # Enter the EPNix development shell, that has EPICS base installed in it. + nix develop + + # Create your app and ioc boot folder + makeBaseApp.pl -t ioc example + makeBaseApp.pl -i -t ioc -p example -a linux-x86_64 Example + + # Create a git repository, and make sure all files are tracked + git init + git add . + +After that, +you can already check that your top build with: + +.. code-block:: bash + + nix build -L + +This ``nix build`` command compiles your IOC, +and all its dependencies. +This makes the usual EPICS environment setup unneeded. + +If found in the official Nix cache server, +Nix downloads packages from there +instead of compiling them. + +This command puts a ``./result`` symbolic link in your current directory, +containing the compilation result. + +Adding StreamDevice to the EPNix environment +-------------------------------------------- + +Adding dependencies to the EPNix environment happen inside the ``flake.nix`` file. +This file is the main entry point for specifying your build environment: +most Nix commands used here read this file to work. + +For adding StreamDevice, +change yours like so: + +.. code-block:: diff + :caption: :file:`flake.nix` + + # Add one of the supported modules here: + # --- + - #support.modules = with pkgs.epnix.support; [ StreamDevice ]; + + support.modules = with pkgs.epnix.support; [ StreamDevice ]; + +Then, +leave your EPNix development shell by running ``exit``, +and re-enter it with ``nix develop``. + +Because you modified the support modules, +run ``eregen-config`` to regenerate ``configure/RELEASE.local``. + +With this, +your development shell has StreamDevice available, +and StreamDevice is also added in the ``RELEASE.local`` file. + +.. tip:: + + As a rule, + each time you edit the ``flake.nix`` file, + leave and re-enter your development shell (``exit`` then ``nix develop``), + and run ``eregen-config``. + +Adding StreamDevice to your EPICS app +------------------------------------- + +To add StreamDevice to your app, +make the following modifications: + +Change the ``exampleApp/src/Makefile`` +so that your App knows the record types of StreamDevice and its dependencies. +Also change that file so that it links to the StreamDevice library and its dependencies, +during compilation. +For example: + +.. code-block:: makefile + :caption: :file:`exampleApp/src/Makefile` + + # ... + + # Include dbd files from all support applications: + example_DBD += calc.dbd + example_DBD += asyn.dbd + example_DBD += stream.dbd + example_DBD += drvAsynIPPort.dbd + + # Add all the support libraries needed by this IOC + example_LIBS += calc + example_LIBS += asyn + example_LIBS += stream + + # ... + +Create the ``exampleApp/Db/example.proto`` file +that has the definition of the protocol. +This file tells StreamDevice what to send the power supply, +and what to expect in return. + +.. code-block:: perl + :caption: :file:`exampleApp/Db/example.proto` + + Terminator = LF; + + getVoltage { + out ":VOLT?"; in "%f"; + } + + setVoltage { + out ":VOLT %f"; + @init { getVoltage; } + } + +Create the ``exampleApp/Db/example.db`` file. +That file specifies the name, type, and properties of the Process Variables (PV) +that EPICS exposes over the network. +It also specifies how they relate to the functions written in the protocol file. + +.. code-block:: perl + :caption: :file:`exampleApp/Db/example.db` + + record(ai, "${PREFIX}VOLT-RB") { + field(DTYP, "stream") + field(INP, "@example.proto getVoltage ${PORT}") + } + + record(ao, "${PREFIX}VOLT") { + field(DTYP, "stream") + field(OUT, "@example.proto setVoltage ${PORT}") + } + +Change ``exampleApp/Db/Makefile`` +so that the EPICS build system installs ``example.proto`` and ``example.db``: + +.. code-block:: makefile + :caption: :file:`exampleApp/Db/Makefile` + + # ... + + #---------------------------------------------------- + # Create and install (or just install) into /db + # databases, templates, substitutions like this + DB += example.db + DB += example.proto + + # ... + +Change your ``st.cmd`` file +so that it knows where to load the protocol file, +and how to connect to the remote power supply. + +.. code-block:: csh + :caption: :file:`iocBoot/iocExample/st.cmd` + + #!../../bin/linux-x86_64/example + + < envPaths + + ## Register all support components + dbLoadDatabase("${TOP}/dbd/example.dbd") + example_registerRecordDeviceDriver(pdbbase) + + # Where to find the protocol files + epicsEnvSet("STREAM_PROTOCOL_PATH", "${TOP}/db") + # The TCP/IP address of the power supply + drvAsynIPPortConfigure("PS1", "localhost:8727") + + ## Load record instances + dbLoadRecords("${TOP}/db/example.db", "PREFIX=, PORT=PS1") + + iocInit() + +And run ``chmod +x iocBoot/iocExample/st.cmd`` +so that you can run your command file as-is. + +You can test that your top builds by running: + +.. code-block:: bash + + nix build -L + +You will see that your IOC does not build. +This is because we haven’t told Git to track those newly added files, +and so Nix ignores them too. + +Run ``git add .`` for Git and Nix to track all files, +and try a ``nix build -L`` again. + +If everything goes right, +you can examine your compiled top under ``./result``. + +You can observe that: + +- the ``example`` app is installed under ``bin/`` and ``bin/linux-x86_64``, + and links to the correct libraries +- ``example.proto`` and ``example.db`` are installed under ``db/`` +- ``example.dbd`` is generated and installed under ``dbd/`` + +Running your IOC +---------------- + +To run your IOC, +build it first with ``nix build -L``, +and change directory into the ``./result/iocBoot/iocExample`` folder. +Then, run: + +.. code-block:: bash + + ./st.cmd + +You should see the IOC starting and connecting to ``localhost:8727``. + +Recompiling with make +--------------------- + +Using ``nix build`` to compile your IOC each time might feel slow. +This is because Nix re-compiles your IOC from scratch each time. + +If you want a more “traditional” edit / compile / run workflow, +you can place yourself in the development shell with ``nix develop``, +and use ``make`` from here. + +Next steps +---------- + +More commands are available in the power supply simulator. +To view them, +close your IOC, +and open a direct connection to the simulator: + +.. code-block:: bash + + nc localhost 8727 + # or + telnet localhost 8727 + +You can install the ``nc`` command through the ``netcat`` package, +or you can install the ``telnet`` command through the ``telnet`` package, + +Either command opens a prompt +where you can type ``help`` then press enter +to view the available commands. + +Try to edit the protocol file and the database file +to add those features to your IOC. + +For more information about how to write the StreamDevice protocol, +have a look at the `Protocol Files`_ documentation. + +You might also be interested in reading :doc:`../user-guides/flake-registry`. + +.. _Protocol Files: https://paulscherrerinstitute.github.io/StreamDevice/protocol.html + +Pitfalls +-------- + +Although EPNix tries to be close to a standard EPICS development, +some differences might lead to confusion. +You can find more information about this in the :doc:`../faq`. diff --git a/docs/ioc/user-guides/developing-modules.rst b/docs/ioc/user-guides/developing-modules.rst new file mode 100644 index 00000000..31fa3afc --- /dev/null +++ b/docs/ioc/user-guides/developing-modules.rst @@ -0,0 +1,99 @@ +Developing support modules +========================== + +.. TODO: rewrite, not clear enough, probably move most of it into day-to-day tutorial + +It can happen that one needs to hack on an EPICS support module, +while also developing an App. +This might be to develop and test the support module, +or to patch and test the support module, etc. + +This is where Nix’s reproducibility guarantees might seem to be in the way: +dependencies are taken from the ``/nix/store`` instead of your local repository. +You can add it as a flake input instead, +but that requires to run ``nix flake lock --update-input mySupport`` on each modification, etc. + +To bypass these constraints, +there are several mechanisms that let you to temporarily weaken these constraints for development purposes. + +Packaging a starter module +-------------------------- + +First, clone the EPNix repository, and package your support module. + +.. You can look at the `Packaging modules`_ (TODO) guide, + this doesn’t even have to compile yet, + but you need to specify the dependencies of your support module. + + .. _Packaging modules: ../developer-guides/packaging-modules.md + +Hacking on your module +---------------------- + +From the directory containing the source code of your support module, run: + +.. code-block:: bash + + nix develop "/path/to/local/epnix#support/mySupport" + # Then, inside the development shell + dontUnpack=true + genericBuild + +This will put the result of your compilation under ``outputs/out``. +If you make modifications to your support module, +run ``buildPhase`` from the same development shell to recompile it. + +Using it on your EPICS top +-------------------------- + +Before trying to compile your top, +make sure that your support module is included in the ``support.modules`` option of your EPNix top: + +.. code-block:: nix + + support.modules = with pkgs.epnix.support; [ mySupport ]; + +Now that the support module is compiled and installed in a local directory, +you can ask Nix to use it as is. +This can be done by running this command from your EPICS top directory: + +.. code-block:: bash + + nix develop \ + --override-input epnix '/path/to/local/epnix' \ + --redirect '/path/to/local/epnix#support/mySupport' '/path/to/mySupport/outputs/out' + # Then, normal hacking on an EPICS top... + +The ``--override-input`` option instructs Nix to use your local EPNix fork +instead of the one hosted on GitHub. +Use this option to override flake inputs. + +The ``--redirect`` option instructs Nix to use your local directory for your support module, +instead of a module installed in the ``/nix/store``. +Use this option to override individual packages. + +-------------- + +With this setup, +you can hack and compile your support module, +and the changes will be directly visible to your top. +This enables you to hack on both project at the same time, +each on their own development shell. + +One question one may ask: + + What’s the difference between + running the complex ``nix develop`` command + and just putting ``/path/to/mySupport/outputs/out`` into ``RELEASE.local``? + +One thing that the complex ``nix develop`` command does correctly, +is replacing *everything* that would have been ``/nix/store/...-mySupport../`` into your development shell. +This includes the ``RELEASE.local`` file, +but this may not be the only thing: + +For example, +if you’re hacking on the ``seq`` support module, +not only will it put the path to your local ``seq`` module into ``RELEASE.local``, +but it will also put some ``seq`` specific programs into your ``$PATH``, like the ``snc`` utility. +These programs will be those from your local build, +not the ones coming from the EPNix repository. diff --git a/docs/ioc/user-guides/flake-registry.rst b/docs/ioc/user-guides/flake-registry.rst new file mode 100644 index 00000000..a945a50b --- /dev/null +++ b/docs/ioc/user-guides/flake-registry.rst @@ -0,0 +1,34 @@ +Setting up the flake registry +============================= + +While developing with EPNix, +it’s possible you will end up typing ``'github:epics-extensions/epnix'`` quite often. + +It happens when you need to create a “top” template, +or when you just want to have ``epics-base`` in your shell, +and so on. + +This is tedious. + +Nix provides a way of shortening these URLs, +by adding to the `Nix registry`_: + +.. code-block:: bash + + nix registry add epnix 'github:epics-extensions/epnix' + +Now, referring to ``epnix`` in Nix command-lines will be as if you referred to the full URL. +For example, the develop command to have EPICS based installed outside of a top would be: + +.. code-block:: bash + + nix develop epnix + +If you want to initialize an EPNix top, +you can run: + +.. code-block:: bash + + nix flake new -t epnix my-top + +.. _Nix registry: https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-registry.html#description diff --git a/docs/ioc/user-guides/index.rst b/docs/ioc/user-guides/index.rst new file mode 100644 index 00000000..4069e853 --- /dev/null +++ b/docs/ioc/user-guides/index.rst @@ -0,0 +1,19 @@ +User guides +=========== + +`How-to guides`_ for users of the EPNix project wanting to build and deploy EPICS IOCs. + +.. _How-to guides: https://diataxis.fr/how-to-guides/ + +---- + +.. toctree:: + :maxdepth: 1 + + ./private-repo-setup.rst + ./flake-registry.rst + ./developing-modules.rst + ./testing/packaging-python-scripts.rst + +.. TODO: make a NixOS test user-guide, + and add a toctree for testing-related guides there diff --git a/docs/ioc/user-guides/private-repo-setup.rst b/docs/ioc/user-guides/private-repo-setup.rst new file mode 100644 index 00000000..ae953085 --- /dev/null +++ b/docs/ioc/user-guides/private-repo-setup.rst @@ -0,0 +1,165 @@ +Private repository setup +======================== + +To avoid a great deal of confusion, +it’s best to configure your machine +so that it can clone your private repositories unattended. +This means that this command should succeed +without asking for user input on the terminal: + +.. code-block:: bash + + git clone 'ssh://git@your.gitlab.com/your/epicsApp.git' + +But, asking for user input graphically is acceptable. + +The reason is +that the Nix command-line tool often writes text on the terminal, +and does so over the questions asked by programs like SSH or Git. +If SSH or Git asks for a password on the terminal, +you probably won’t see it, +and confusion will follow when the Nix command hangs. + +There are two main ways to configure your machine for this: + +- SSH keys +- GitHub / GitLab tokens + +SSH keys +-------- + +Configuring the SSH key +~~~~~~~~~~~~~~~~~~~~~~~ + +To set up SSH keys to use with your GitHub account, +you can follow the `GitHub SSH documentation`_. + +To set up SSH keys to use with your GitLab account, +you can follow the `GitLab SSH documentation`_, +and particularly look at these sections: + +- See if you have an existing SSH key pair +- Generate an SSH key pair +- Add an SSH key to your GitLab account +- Verify that you can connect + +.. _GitHub SSH documentation: https://docs.github.com/en/authentication/connecting-to-github-with-ssh +.. _GitLab SSH documentation: https://docs.gitlab.com/ee/user/ssh.html + +Configuring the ssh-agent +~~~~~~~~~~~~~~~~~~~~~~~~~ + +If you have a GNOME installation, +chances are you already have an ssh-agent installed and running. + +To check, +open a *new* terminal, +and look at the value of the ``$SSH_AUTH_SOCK`` variable. + +If it returns nothing, +install ``gnome-keyring``, +then log out and log in again. + +Then reopen a new terminal, +and add your configured SSH key like so: + +.. code-block:: bash + + ssh-add 'path/to/key/id_ed25519' + +Check that logging in to GitLab doesn’t ask for user input on the terminal: + +.. code-block:: bash + + ssh -T 'git@your.gitlab.com' + # Welcome to GitLab, @user! + +If it doesn’t work, +but you have ``gnome-keyring-daemon`` installed and running, +you can add this line to your ``~/.bashrc``: + +.. code-block:: bash + + export SSH_AUTH_SOCK=/run/user/$UID/keyring/ssh + +GitHub / GitLab tokens +---------------------- + +GitHub and GitLab tokens offer a timed way of authenticating, +suitable for either quick and dirty access, +or for setting up services or scripts +that need access to GitHub / GitLab repositories. +In any case, +tokens shouldn’t be used for usual development. + +In GitLab, +you can create tokens either per-user, +per-group, +or per-project. + +In GitHub, +you can only create personal access tokens, +but their usage can be restricted in an organization. + +Creating a GitHub token, +or a GitLab token for your user means +that you can give it access to all projects and APIs that you have access to. +This can be useful for your personal applications, +or tools like `glab`_. + +In GitLab, +you can create a token for given group or project +so that it offers access to that specific group or project. +These kinds of tokens should be preferred. + +.. _glab: https://docs.gitlab.com/ee/editor_extensions/gitlab_cli/index.html + +GitHub +~~~~~~ + +To create a GitHub token, follow the `GitHub token documentation`_ + +.. _GitHub token documentation: https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens + +GitLab +~~~~~~ + +.. TODO: reference official documentation + +To create a GitLab token, +go to the user/group/project settings, +under the “Access Tokens” section. +Give your token a meaningful name, +an expiration date, +and for a group/project, +select the appropriate role. + +If you only want your token to be able to clone repositories, +you can just select the ``read_repository`` scope. +Else refer to GitLab’s official documentation by clicking “Learn more.” + +After creating the personal access token, +you can copy the token’s value. +Be careful, +as this value won’t be accessible after closing the page. + +If you want to clone any repository, +the URL will need to be: + +.. code-block:: bash + + https://gitlab-ci-token:${TOKEN}@your.gitlab.com" + +As EPNix uses SSH flake inputs, +you can use this command to instruct Git to rewrite GitLab URLs: + +.. code-block:: bash + + git config --global url."https://gitlab-ci-token:${TOKEN}@your.gitlab.com".insteadOf "ssh://git@your.gitlab.com" + +To check that your setup is working, +run the following command: + +.. code-block:: bash + + git clone 'ssh://git@your.gitlab.com/your/epicsApp.git' diff --git a/docs/ioc/user-guides/testing/packaging-python-scripts.rst b/docs/ioc/user-guides/testing/packaging-python-scripts.rst new file mode 100644 index 00000000..afa51fe5 --- /dev/null +++ b/docs/ioc/user-guides/testing/packaging-python-scripts.rst @@ -0,0 +1,200 @@ +Packaging Python scripts +======================== + +.. TODO: move most of it in tutorial + +As EPNix uses Nix, +you can package Python scripts as helpers for your integration tests, +by using the provided `infrastructure`_ of nixpkgs. +In fact, +you can package any program in any language, +but this document focuses on Python scripts with `Poetry`_ for their simplicity and popularity. + +.. _infrastructure: https://nixos.org/manual/nixpkgs/stable/#python +.. _Poetry: https://python-poetry.org/ + +Getting started +--------------- + +We recommend using the Poetry package in your EPNix environment, +through Nix, to use the same version as the one building the Python script. + +You can do this by adding this bit in your ``flake.nix`` file: + +.. code-block:: nix + + epnix.devShell.packages = [ + { package = pkg.poetry; category = "development tools"; } + ]; + +Next, you can start your development shell with ``nix develop``, +go to the directory of your test, +and create a new project with the command: + +.. code-block:: bash + + poetry new + +This will create a Python project under the ```` directory. +Under it, you will find a ``pyproject.toml`` +where you can specify the dependencies of your script. +For example, you can specify ``modbus`` to add the Python `modbus package`_, +if you want to test modbus communication. +You can remove the dependency on pytest if you won’t add unit tests to your Python script. + +To add an entry point to your Python code, +you can use the ``tool.poetry.scripts`` section like so: + +.. code-block:: toml + + [tool.poetry.scripts] + my_python_script = "my_python_script:main" + +This will add an executable named ``my_python_script`` +that will run the ``main()`` function of the ``my_python_script`` module. + +For more information on how to use poetry, +please refer to the `Poetry documentation`_. + +Before packaging this script using Nix, it’s important to generate the lock file, and to remember to re-generate it each time you change the ``pyproject.toml`` file. + +You can do this with the following command: + +.. code-block:: bash + + poetry lock + +Then, in your integration test file (see: :doc:`../../tutorials/integration-tests`), +you can package it like this: + +.. code-block:: nix + + { build, pkgs, ... }: + + let + pythonScript = pkgs.poetry2nix.mkPoetryApplication { + projectDir = ./path/to/my-python-script; + }; + in + pkgs.nixosTest { + name = "myTest"; + + # ... + } + +With this, you can use the ``pythonScript`` variable as you see fit. + +.. _modbus package: https://pypi.org/project/modbus/ +.. _Poetry documentation: https://python-poetry.org/docs/basic-usage/ + +Example usage: As a one shot test script +---------------------------------------- + +Using a packaged Python script instead of the provided ``testScript`` has several advantages. +It can use dependencies provided by the community (like ``modbus``, ``systemd``, etc.), and you can make it run on the running virtual machine. + +Python script: + +.. code-block:: python + + import subprocess + + from modbus.client import * + + + def main(): + c = client(host='HOSTNAME') + modbus_values = c.read(FC=3, ADR=10, LEN=8) + + for i in range(8): + epics_value = subprocess.run( + ["caget", "-t", "MyPV:" + i], + capture_output=True, + ).stdout.strip() + + assert modbus_values[i] == int(epics_value), "Wrong value provided by epics" + +Nix test: + +.. code-block:: nix + + { build, pkgs, ... }: + + let + pythonScript = pkgs.poetry2nix.mkPoetryApplication { + projectDir = ./path/to/my-python-script; + }; + in + pkgs.nixosTest { + name = "myTest"; + + machine = { + environment.systemPackages = [ pythonScript ]; + + # ... + }; + + testScript = '' + # ... + + my_python_script --my-flag --my-option=3 + + # ... + ''; + } + +Example usage: As a systemd service +----------------------------------- + +Using a Python script as a systemd service is useful for mocking devices. + +.. TODO: For more information, please see the `Creating a mocking server`_ guide. + +Python script: + +.. code-block:: python + + import logging + from logging import info + + + def main(): + logging.basicConfig(level=logging.INFO) + + while True: + info("doing things") + + # ... + +Nix test: + +.. code-block:: nix + + { build, pkgs, ... }: + + let + pythonScript = pkgs.poetry2nix.mkPoetryApplication { + projectDir = ./path/to/my-python-script; + }; + in + pkgs.nixosTest { + name = "myTest"; + + machine = { + systemd.services."my-python-service" = { + wantedBy = [ "multi-user.target" ]; + + serviceConfig.ExecStart = "${pythonScript}/bin/my_python_script"; + }; + + # ... + }; + + testScript = '' + # ... + + machine.wait_for_unit("my-python-service.service") + + # ... + ''; + } diff --git a/docs/logo.svg b/docs/logo.svg new file mode 100644 index 00000000..fe9f751c --- /dev/null +++ b/docs/logo.svg @@ -0,0 +1,411 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + diff --git a/docs/nixos-services/index.rst b/docs/nixos-services/index.rst new file mode 100644 index 00000000..dfcd6a95 --- /dev/null +++ b/docs/nixos-services/index.rst @@ -0,0 +1,9 @@ +Introduction +============ + +This section of the documentation covers the deployment and administration of EPICS-related services, +such as the Phoebus ecosystem, the Channel Access gateway, and so on. + +For an introduction on how to install NixOS, +and a guided tour into how to change NixOS options, +follow the :doc:`tutorials/archiver-appliance` tutorial. diff --git a/docs/nixos-services/tutorials/archiver-appliance.rst b/docs/nixos-services/tutorials/archiver-appliance.rst new file mode 100644 index 00000000..a684ddc4 --- /dev/null +++ b/docs/nixos-services/tutorials/archiver-appliance.rst @@ -0,0 +1,365 @@ +Creating an Archiver Appliance instance +======================================= + +In this tutorial, +we’re going to see how to create a virtual machine that runs Archiver Appliance, +under the NixOS Linux distribution. + +Installing Archiver Appliance on a physical machine is definitely possible, +but this tutorial focuses on virtual machines for simplicity’s sake. + +You will need: + +- A virtual machine, +- and the `NixOS ISO file`_. + Select the “Graphical ISO image.” + +.. _NixOS ISO file: https://nixos.org/download/#nixos-iso + +Installing NixOS +---------------- + +First things first, +create your virtual machine, +and select the ISO image that you downloaded. + +Then, start the virtual machine. + +From the booted virtual machine, +you can follow the graphical installation process, +and reboot once finished. + +You can select any desktop environment, +or no desktop. +This tutorial only uses the command-line. + +Making your configuration a flake +--------------------------------- + +The installation process created the ``/etc/nixos`` directory in your VM. +This directory describes the complete configuration of your machine. + +EPNix is a “Nix flake”, +which a way of managing Nix projects. +Using Nix flakes also enables you to use Nix code outside of your repository, +in a controlled manner. +For more information, +see the `Nix flake command manual`_ and the `Flake wiki page`_. + +To be able to import EPNix into you NixOS configuration, +you first need to turn your NixOS configuration into a Nix flake. + +As root, place yourself in the ``/etc/nixos`` directory in your virtual machine. +Create a ``flake.nix`` file under it, +by running ``nano flake.nix``. +Fill the file with these lines: + +.. code-block:: nix + :caption: flake.nix + :linenos: + + { + description = "Configuration for running Archiver Appliance in a VM"; + + inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11"; + inputs.epnix.url = "github:epics-extensions/EPNix/nixos-23.11"; + + outputs = { self, nixpkgs, epnix }: { + nixosConfigurations.nixos = nixpkgs.lib.nixosSystem { + modules = [ + epnix.nixosModules.nixos + + ./configuration.nix + ]; + }; + }; + } + +Save and quit by typing :kbd:`Ctrl-x`, then :kbd:`y`, and then :kbd:`Enter`, +and run ``nixos-rebuild test`` to test your changes. + +Some explanations: + +You can see in the ``flake.nix`` file that the flake has 2 inputs: +``nixpkgs`` and ``epnix``, +lines 4–5. + +Having the ``nixpkgs`` input enables you to use code from `Nixpkgs`_. +This is what enables you to use all those NixOS options, +and every package currently installed on your machine. +For more information, +you can read the `Nixpkgs preface`_. + +Having the ``epnix`` input is what’s going to enable you to use :doc:`packages from EPNix <../../pkgs/packages>`, +such as Archiver Appliance. +It also enables you to use :doc:`EPNix' extra NixOS options <../options>`, +such as the options configuring Tomcat, the systemd service, the ``archappl`` user and group, MariaDB, and so on. + +.. _Nix flake command manual: https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-flake.html +.. _Flake wiki page: https://nixos.wiki/wiki/Flakes +.. _Nixpkgs: https://github.com/NixOS/nixpkgs +.. _Nixpkgs preface: https://nixos.org/manual/nixpkgs/stable/#preface + +Configuring Archiver Appliance +------------------------------ + +Now for the fun part, +actually using those EPNix options to install and configure Archiver Appliance, +and all its dependencies. + +Create and edit the file ``archiver-appliance.nix`` under ``/etc/nixos``. +For now, here are the contents: + +.. code-block:: nix + :caption: :file:`archiver-appliance.nix` + + { + services.archiver-appliance.enable = true; + } + +In your ``flake.nix``, +import the newly created file by adding ``./archiver-appliance.nix``, +under ``./configuration.nix``: + +.. code-block:: diff + :caption: :file:`flake.nix` + + modules = [ + epnix.nixosModules.nixos + + ./configuration.nix + + ./archiver-appliance.nix + ]; + +If you try to test your changes by running ``nixos-rebuild test``, +you will see a helpful error message: + +.. code-block:: console + + root@machine /etc/nixos # nixos-rebuild test + error: The option `services.archiver-appliance.stores.lts.location' + is used but not defined. + (use '--show-trace' to show detailed location information) + +This tells you that setting the ``services.archiver-appliance.stores.lts.location`` option is mandatory, +but we didn’t set any value. + +To figure out what this option is about, +you can examine the :doc:`options reference <../options>`. + +The options reference gives a description for this option: + + Backing directory containing the LTS. + +and an example: + +.. code-block:: nix + + "/data/lts" + +It tells us that you need to choose where the Long Term Store (LTS) is. +See the “Architecture” section of the `Archiver Appliance Details`_ page for what the various stores are. + +Because this is a test VM, +let’s configure the LTS to a test location, +like ``/tmp/lts``. +You will also need to configure the location of the Medium Term Store (MTS). + +Here’s how to change ``archiver-appliance.nix``: + +.. code-block:: nix + :caption: :file:`archiver-appliance.nix` + + { + services.archiver-appliance.enable = true; + services.archiver-appliance.stores.lts.location = "/tmp/lts"; + services.archiver-appliance.stores.mts.location = "/tmp/mts"; + } + +If you don’t want to repeat yourself, +you can also change it like so: + +.. code-block:: nix + :caption: :file:`archiver-appliance.nix` + + { + services.archiver-appliance = { + enable = true; + stores.lts.location = "/tmp/lts"; + stores.mts.location = "/tmp/mts"; + }; + } + +And now, +this should succeed: + +.. code-block:: console + + root@machine /etc/nixos # nixos-rebuild test + building the system configuration... + activating the configuration... + setting up /etc... + reloading user units for admin... + setting up tmpfiles + reloading the following units: dbus.service + the following new units were started: arch-lts-ArchiverStore.mount, + arch-mts-ArchiverStore.mount, arch-sts-ArchiverStore.mount, + mysql.service, tomcat.service + +From the message, +we can guess that it started the Tomcat server running Archiver Appliance, +the MySQL (in fact, MariaDB) server, +and mounted some partitions. +Fantastic! + +You can run the ``systemctl list-units`` command to see if any systemd unit failed. + +In the default configuration, +Archiver Appliance and Tomcat are configured to output logs to journald. +You can see those logs by running: + +.. code-block:: bash + + journalctl -xeu tomcat.service + +You can also see the MariaDB logs by running: + +.. code-block:: bash + + journalctl -xeu mysql.service + +.. note:: + + Here are some details on what was done by EPNix’ ``services.archiver-appliance`` NixOS module: + + - Creation of the Linux user and group ``archappl`` + - Installation and configuration of MariaDB: + + - Creation of the ``archappl`` user, + with UNIX socket authentication + - Creation of the Archiver Appliance database + - Creation of the `various tables`_ in that database + - Giving access rights to this database for the ``archappl`` user + + - Installation and configuration of Tomcat: + + - Installation of the WAR files of Archiver Appliance + - Installation of the MariaDB connector and its dependencies + - Configuring the MariaDB connector to authenticate to the database + - Logging configuration to ``journald`` + + - Configuring mounts so that: + + - ``/arch/lts`` and ``/arch/mts`` are bind mounts to the configured locations, + with some added security options, + such as ``nodev`` and ``noexec`` + - Mounting ``/arch/sts`` as a new ``tmpfs`` + +Tomcat runs by default under port 8080, +and NixOS has a firewall enabled by default. + +Change your ``archiver-appliance.nix``: + +.. code-block:: nix + + { + services.archiver-appliance = { + enable = true; + stores.lts.location = "/tmp/lts"; + stores.mts.location = "/tmp/mts"; + + # New option: + openFirewall = true; + }; + } + +and run ``nixos-rebuild test``. +It will restart ``firewall.service``, +but configured to allow incoming connection on port 8080. + +Check the IP address of your VM with ``ip a``, +and open a browser to ``http://:8080/mgmt/ui/index.html``. + +Finally, +run ``nixos-rebuild switch`` to confirm your changes. +This will apply your changes for the next reboot, +by adding a new boot entry, +enabling you to go back to a previous configuration. + +You have now configured Archiver Appliance on NixOS. + +.. _Archiver Appliance Details: https://slacmshankar.github.io/epicsarchiver_docs/details.html +.. _various tables: https://github.com/slacmshankar/epicsarchiverap/blob/master/src/main/org/epics/archiverappliance/config/persistence/archappl_mysql.sql + +Next steps +---------- + +This VM configuration has some problems: + +- It stores the LTS and MTS in ``/tmp``, + which by default is cleaned on reboot +- The size of the Short Term Store (STS) isn’t configured +- Both “management” and “retrieval” URLs are accessible without authentication + +The following sections are some pointers to fix these issues. + +Configuring partitions +~~~~~~~~~~~~~~~~~~~~~~ + +If you want to change the location of the LST or MTS, +you can change the value of the corresponding options: + +- ``services.archiver-appliance.stores.lts.location`` +- ``services.archiver-appliance.stores.mts.location`` + +But these values won’t mean much if the configured directories are not backed by the appropriate hardware. + +As an example given by the `Archiver Appliance Details`_ page, +section “Architecture”, +we can have the LTS backed by a NAS or SAN, +and the MTS backed by SSD or SAS storage. + +The way to do that is to configure the ``fileSystems`` NixOS option. +See the `File Systems NixOS documentation`_ for more information. + +.. _File Systems NixOS documentation: https://nixos.org/manual/nixos/stable/#ch-file-systems + +Size of the short term store +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To configure the size of the short term store, +use the ``services.archiver-appliance.stores.sts.size`` option. + +For example: + +.. code-block:: nix + :caption: :file:`archiver-appliance.nix` + + { + services.archiver-appliance = { + enable = true; + stores.lts.location = "/tmp/lts"; + stores.mts.location = "/tmp/mts"; + + openFirewall = true; + + # New option: + stores.sts.size = "20g"; + }; + } + +See the :ref:`sts.size option ` in the reference for a more in-depth description. + +Restricting access +~~~~~~~~~~~~~~~~~~ + +Allowing access to ``mgmt`` URLs to anyone can be dangerous, +because it allows anyone to delete and archive PVs. + +To restrict access, +you can close the firewall and put an nginx server in front. + +You can configure the nginx server to disallow access to the URLs you want. +You can also configure nginx to require authentication. + +.. TODO: make a guide including HTTPS setup diff --git a/docs/nixos-services/tutorials/index.rst b/docs/nixos-services/tutorials/index.rst new file mode 100644 index 00000000..6a1fd94b --- /dev/null +++ b/docs/nixos-services/tutorials/index.rst @@ -0,0 +1,13 @@ +Tutorials +========= + +`Tutorials`_ for users of the EPNix project wanting to deploy EPICS-related services. + +.. _Tutorials: https://diataxis.fr/tutorials/ + +---- + +.. toctree:: + :maxdepth: 1 + + ./archiver-appliance.rst diff --git a/docs/nixos-services/user-guides/ca-gateway.rst b/docs/nixos-services/user-guides/ca-gateway.rst new file mode 100644 index 00000000..5c9a1976 --- /dev/null +++ b/docs/nixos-services/user-guides/ca-gateway.rst @@ -0,0 +1,205 @@ +Channel Access gateway setup +============================ + +The Channel Access (CA) gateway is a program +that acts as gateway, +which enables client from a network to access IOCs on another network. + +Setting up a CA gateway also enables you +to add extra access security rules on top of IOCs. + +For more details and documentation about the CA PV gateway, +you can examine the `gateway main page`_. + +.. include:: ./pre-requisites.rst + +.. _gateway main page: https://epics.anl.gov/extensions/gateway/ + +Enabling the gateway +-------------------- + +To enable the gateway, +add this to your configuration: + +.. code-block:: nix + :caption: :file:`ca-gateway.nix` + + { + services.ca-gateway = { + enable = true; + openFirewall = true; + }; + } + +This configuration starts the CA gateway in a ``ca-gateway.service`` systemd service. +In this configuration, +the gateway listens on all interface with a broadcast IP address, +and forwards all Channel Access request. + +The ``openFirewall`` option opens the +5064 TCP, +5064 UDP, +and 5065 UDP ports on all network interfaces. + +Firewall on specific interfaces +------------------------------- + +If you want to enable the firewall on specific interfaces, +you can remove the ``openFirewall`` option +and configure the firewall manually. + +You can also use the ``cip`` setting +to specify where the gateway should listen +for the CA server part. + +For example: + +.. code-block:: nix + :caption: :file:`ca-gateway.nix` + + {config, ...}: { + services.ca-gateway = { + enable = true; + # Server side listen address + # Let's say this IP address is on enp0s2 + settings.sip = ["10.0.2.1"]; + + # Let's also say the enp0s1 interface is + # where communication with "real" IOCs happen (client side) + + # openFirewall is left as false by default + }; + + networking.firewall = let + gwSettings = config.services.ca-gateway.settings; + in { + interfaces = { + # Open the firewall on the interface from the client side of the gateway, + # this will be the side of the gateway listening + # for replies to beacons and PV search requests + "enp0s1".allowedUDPPorts = [5065]; + + # Open the firewall on the interface from the server side of the gateway, + # this will be the side of the gateway listening for Channel Access requests + "enp0s2" = { + # Use the value of the `sport` setting + allowedTCPPorts = [gwSettings.sport]; + allowedUDPPorts = [gwSettings.sport]; + }; + }; + + # Allow incoming UDP packets with *source* port 5064, + # from the client side of the gateway. + # This is needed to listen to CA broadcast responses + extraCommands = '' + ip46tables -A nixos-fw -p udp --sport 5064 -j nixos-fw-accept -i enp0s1 + ''; + }; + } + +Filtering IOCs +-------------- + +By using the ``cip`` setting, +you can filter which IOCs get exposed by the gateway. +This is equivalent to setting the environment variable ``EPICS_CA_ADDR_LIST`` +and setting ``EPICS_CA_AUTO_ADDR_LIST=NO``. + +For example: + +.. code-block:: nix + :caption: :file:`ca-gateway.nix` + + { + services.ca-gateway = { + enable = true; + # These IOCs get exposed by the gateway + settings.cip = [ + "10.0.1.42" + "10.0.1.69" + + # you can specify the port, too, + # if your IOC listens on something other than 5064 + "10.0.1.237:5067" + + # domain names also work + "myioc" + ]; + }; + } + +Filtering process variables +--------------------------- + +By using the ``pvlist`` setting, +you can filter which PVs get exposed by the gateway. + +This option takes a file in the gateway ``pvlist`` format. +See the `GATEWAY.pvlist`_ example on the ca-gateway repository. +The list supports regular expressions (Perl style). + + +.. _GATEWAY.pvlist: https://github.com/epics-extensions/ca-gateway/blob/master/example/GATEWAY.pvlist + +In the configuration +~~~~~~~~~~~~~~~~~~~~ + +For example: + +.. code-block:: nix + :caption: :file:`ca-gateway.nix` + + {pkgs, ...}: { + services.ca-gateway = { + enable = true; + # These PVs get exposed by the gateway + # This list implements an "allowlist": + # DENY by default, some PVs explicitely ALLOW + settings.pvlist = pkgs.writeText "gateway.pvlist" '' + EVALUATION ORDER DENY, ALLOW + + .* DENY + + MY_PV1 ALLOW + MY_PV2 ALLOW + + # Or: + + MY_PV[0-9]+ ALLOW + ''; + }; + } + +In a separate file +~~~~~~~~~~~~~~~~~~ + +For long lists, +it can be better +to put it in a separate file. +You can do this +by adding a ``gateway.pvlist`` in the same directory as your configuration: + +.. code-block:: perl + + EVALUATION ORDER DENY, ALLOW + + .* DENY + + MY_PV1 ALLOW + MY_PV2 ALLOW + + # Or: + + MY_PV[0-9]+ ALLOW + +And in your configuration: + +.. code-block:: nix + + { + services.ca-gateway = { + enable = true; + # Make sure that the value is *not* quoted + settings.pvlist = ./gateway.pvlist; + }; + } diff --git a/docs/nixos-services/user-guides/index.rst b/docs/nixos-services/user-guides/index.rst new file mode 100644 index 00000000..2aa264af --- /dev/null +++ b/docs/nixos-services/user-guides/index.rst @@ -0,0 +1,15 @@ +User guides +=========== + +`How-to guides`_ for users of the EPNix project wanting to deploy EPICS-related services. + +.. _How-to guides: https://diataxis.fr/how-to-guides/ + +---- + +.. toctree:: + :maxdepth: 1 + + ./ca-gateway.rst + ./phoebus-alarm.rst + ./phoebus-save-and-restore.rst diff --git a/docs/nixos-services/user-guides/phoebus-alarm.rst b/docs/nixos-services/user-guides/phoebus-alarm.rst new file mode 100644 index 00000000..48a2d7c9 --- /dev/null +++ b/docs/nixos-services/user-guides/phoebus-alarm.rst @@ -0,0 +1,223 @@ +Phoebus Alarm single server setup +================================= + +The Phoebus Alarm collection of services enables monitoring EPICS PVs, +and report alarms in a server. +Phoebus clients can then contact this server, +to see a list of current alarms, earlier alarms, and so on. + +This guide focuses on installing and configuring these services on a single server. + +For more information about these services, +examine the official documentation: + +- `Service Architecture`_ +- `Alarm Server`_ +- `the README of Alarm Server`_ for reference only, don’t follow this guide on NixOS +- `Alarm Logging Service`_ + +The Phoebus Alarm Logging Service can also be called the Phoebus Alarm Logger. + +.. include:: ./pre-requisites.rst + +.. _Service Architecture: https://control-system-studio.readthedocs.io/en/latest/services_architecture.html +.. _Alarm Server: https://control-system-studio.readthedocs.io/en/latest/services/alarm-server/doc/index.html +.. _the README of Alarm Server: https://github.com/ControlSystemStudio/phoebus/blob/master/app/alarm/Readme.md +.. _Alarm Logging Service: https://control-system-studio.readthedocs.io/en/latest/services/alarm-logger/doc/index.html + +Single server Phoebus Alarm setup +--------------------------------- + +To configure Phoebus Alarm, Phoebus Alarm Logger, Apache Kafka, and ElasticSearch on a single server, +add this to your configuration, +while taking care of replacing the IP address +and Kafka’s ``clusterId``: + +.. code-block:: nix + :caption: :file:`phoebus-alarm.nix` + + {lib, pkgs, ...}: let + # Replace this with your machine's external IP address + # or DNS domain name + ip = "192.168.1.42"; + kafkaListenSockAddr = "${ip}:9092"; + kafkaControllerListenSockAddr = "${ip}:9093"; + in { + # The Phoebus Alarm server also automatically enables the Phoebus Alarm Logger + services.phoebus-alarm-server = { + enable = true; + openFirewall = true; + settings."org.phoebus.applications.alarm/server" = kafkaListenSockAddr; + }; + + services.phoebus-alarm-logger.settings."bootstrap.servers" = kafkaListenSockAddr; + + # Single-server Kafka setup + services.apache-kafka = { + enable = true; + # Replace with a randomly generated uuid. You can get one by running: + # nix shell 'nixpkgs#apacheKafka' -c kafka-storage.sh random-uuid + clusterId = "xxxxxxxxxxxxxxxxxxxxxx"; + formatLogDirs = true; + settings = { + listeners = [ + "PLAINTEXT://${kafkaListenSockAddr}" + "CONTROLLER://${kafkaControllerListenSockAddr}" + ]; + # Adapt depending on your security constraints + "listener.security.protocol.map" = [ + "PLAINTEXT:PLAINTEXT" + "CONTROLLER:PLAINTEXT" + ]; + "controller.quorum.voters" = [ + "1@${kafkaControllerListenSockAddr}" + ]; + "controller.listener.names" = ["CONTROLLER"]; + + "node.id" = 1; + "process.roles" = ["broker" "controller"]; + + "log.dirs" = ["/var/lib/apache-kafka"]; + "offsets.topic.replication.factor" = 1; + "transaction.state.log.replication.factor" = 1; + "transaction.state.log.min.isr" = 1; + }; + }; + + systemd.services.apache-kafka.unitConfig.StateDirectory = "apache-kafka"; + + # Open kafka to the outside world + networking.firewall.allowedTCPPorts = [9092]; + + services.elasticsearch = { + enable = true; + package = pkgs.elasticsearch7; + }; + + # Elasticsearch, needed by Phoebus Alarm Logger, is not free software (SSPL | Elastic License). + # To accept the license, add the code below: + nixpkgs.config.allowUnfreePredicate = pkg: + builtins.elem (lib.getName pkg) [ + "elasticsearch" + ]; + } + +From the Phoebus graphical client side, +add this configuration: + +.. code-block:: ini + :caption: :file:`phoebus-client-settings.ini` + + # For the Phoebus Alarm Server: + # Replace the IP address with your server's IP address or DNS domain name + org.phoebus.applications.alarm/server=192.168.1.42:9092 + + # For the Phoebus Alarm Logger: + # Replace the IP address again + org.phoebus.applications.alarm.logging.ui/service_uri=http://192.168.1.42:8080 + +Configuring topics +------------------ + +The Phoebus Alarm system uses “topics” as a way of grouping alarms. +These topics are the available roots of your alarm tree. +You need to synchronize the topic names between: + +- Phoebus Alarm Server +- Phoebus Alarm Logger +- Phoebus graphical clients + +Changing the topic names in the Phoebus Alarm Server NixOS modules automatically creates them. + +.. warning:: + + Currently, the Phoebus Alarm Server doesn’t support several topics. + +For example, +if you want to have the topic ``Project``, +add this configuration to the server: + +.. code-block:: nix + :caption: :file:`phoebus-alarm.nix` + + {config, lib, ...}: let + topics = ["Project"]; + in { + services.phoebus-alarm-server = { + # ... + settings = { + # ... + "org.phoebus.applications.alarm/config_names" = topics; + }; + }; + + services.phoebus-alarm-logger.settings.alarm_topics = topics; + } + +For the Phoebus graphical client, +add this configuration: + +.. code-block:: ini + :caption: :file:`phoebus-client-settings.ini` + + # config_name is only used in the Phoebus graphical client + org.phoebus.applications.alarm/config_name = Project + org.phoebus.applications.alarm/config_names = Project + +Configuring the address list +---------------------------- + +If you want to limit the IOCs reachable by the Phoebus Alarm Server, +use these option: + +.. code-block:: nix + :caption: :file:`phoebus-alarm.nix` + + { + services.phoebus-alarm-server = { + # ... + settings = { + # ... + + # The Phoebus Alarm Server will only have access to these IOCs + "org.phoebus.pv.ca/addr_list" = ["192.168.1.5" "192.168.1.42"]; + "org.phoebus.pv.ca/auto_addr_list" = false; + }; + }; + } + +Configuring email support +------------------------- + +To enable email support, +set the ``org.phoebus.email/mailport`` setting. +Here is a list of options you might want to set: + +.. code-block:: nix + :caption: :file:`phoebus-alarm.nix` + + { + services.phoebus-alarm-server = { + # ... + settings = { + # ... + + "org.phoebus.email/mailhost" = "smtp.my-company.org"; + + # Optional: + + # 25 for plain SMTP + "org.phoebus.email/mailport" = 25; + # If authentication is needed: + "org.phoebus.email/username" = "user"; + "org.phoebus.email/password" = "password"; + # Default address to be used for From: + # if unspecified, then the last used "from" address is used + "org.phoebus.email/from" = "Sender "; + }; + }; + } + +.. warning:: + + Currently, Phoebus Alarm Server only supports plain SMTP. diff --git a/docs/nixos-services/user-guides/phoebus-save-and-restore.rst b/docs/nixos-services/user-guides/phoebus-save-and-restore.rst new file mode 100644 index 00000000..c48bcbd6 --- /dev/null +++ b/docs/nixos-services/user-guides/phoebus-save-and-restore.rst @@ -0,0 +1,52 @@ +Phoebus Save-and-restore setup +============================== + +The Phoebus Save-and-restore service is used by clients +to manage configuration and snapshots of PV values. +These snapshots can then be used by clients for comparison or for restoring PVs. + +This guide focuses on installing and configuring the Save-and-Restore service on a single server. + +For more details and documentation about Phoebus Save-and-Restore, +you can examine the `Save-and-restore official documentation`_. + +.. include:: ./pre-requisites.rst + +.. _Save-and-restore official documentation: https://control-system-studio.readthedocs.io/en/latest/services/save-and-restore/doc/index.html + +Enabling the Phoebus Save-and-restore service +--------------------------------------------- + +To enable the Phoebus Save-and-restore service, +add this to your configuration: + +.. code-block:: nix + :caption: :file:`phoebus-save-and-restore.nix` + + {lib, ...}: { + services.phoebus-save-and-restore = { + enable = true; + openFirewall = true; + }; + + # Elasticsearch, needed by Phoebus Save-and-restore, is not free software (SSPL | Elastic License). + # To accept the license, add the code below: + nixpkgs.config.allowUnfreePredicate = pkg: + builtins.elem (lib.getName pkg) [ + "elasticsearch" + ]; + } + +From the Phoebus graphical client side, +add this configuration + +.. code-block:: ini + :caption: :file:`phoebus-client-settings.ini` + + # Replace the IP address with your server's IP address or domain name + org.phoebus.applications.saveandrestore/jmasar.service.url=http://192.168.1.42:8080 + +.. warning:: + + URLs for future versions of Phoebus Save-and-restore will need to change to: + ``http://192.168.1.42:8080/save-restore`` diff --git a/docs/nixos-services/user-guides/pre-requisites.rst b/docs/nixos-services/user-guides/pre-requisites.rst new file mode 100644 index 00000000..00ac0bed --- /dev/null +++ b/docs/nixos-services/user-guides/pre-requisites.rst @@ -0,0 +1,41 @@ +Pre-requisites +-------------- + +- Having a NixOS machine with a flake configuration. + +If you’re not sure how to do this, +you can follow the :doc:`../tutorials/archiver-appliance` tutorial, +which is a good introduction on how to make a NixOS VM. + +If you have such a configuration, +make sure that: + +- You have the ``epnix`` flake input +- You have added ``epnix`` as an argument to your flake outputs +- You have imported EPNix’ NixOS module + +For example: + +.. code-block:: diff + :caption: :file:`flake.nix` + + { + # ... + inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11"; + + inputs.epnix.url = "github:epics-extensions/EPNix/nixos-23.11"; + + # ... + outputs = { + self, + nixpkgs, + + epnix, + }: { + nixosConfigurations.nixos = nixpkgs.lib.nixosSystem { + modules = [ + + epnix.nixosModules.nixos + + # ... + ]; + }; + }; + } diff --git a/pkgs/default.nix b/pkgs/default.nix index 7ca5282a..35f64cab 100644 --- a/pkgs/default.nix +++ b/pkgs/default.nix @@ -89,6 +89,7 @@ in # EPNix specific packages book = callPackage ./book {}; + docs = callPackage ./docs {}; manpages = callPackage ./manpages {}; # Documentation support packages diff --git a/pkgs/docs/default.nix b/pkgs/docs/default.nix new file mode 100644 index 00000000..c893be01 --- /dev/null +++ b/pkgs/docs/default.nix @@ -0,0 +1,127 @@ +{ + stdenvNoCC, + lib, + epnix, + epnixLib, + writeText, + python3, + installShellFiles, + documentedEpnixPkgs ? epnix, + iocConfig ? {}, + nixosConfig ? {}, +}: let + inherit (epnixLib) documentation; + + iocOptions = documentation.options.iocOptions iocConfig; + nixosOptions = documentation.options.nixosOptions nixosConfig; + + iocOptionsContent = documentation.options.optionsContent iocOptions 3; + # Have a separate "Options" header for the Sphinx manpage output + iocOptionsPandoc = '' + IOC options reference + ===================== + + Options + ------- + + ${iocOptionsContent} + ''; + + nixosOptionsContent = documentation.options.optionsContent nixosOptions 3; + nixosOptionsPandoc = '' + NixOS options reference + ======================= + + Options + ------- + + ${nixosOptionsContent} + ''; + + iocPkgsListPandoc = '' + IOC packages list + ================= + + ::: note + This page references all EPNix packages that should be used when packaging an IOC. + For all other packages, see the [Packages list](../../pkgs/packages.md). + ::: + + Packages + -------- + + ${epnixLib.documentation.iocPkgsList 3 documentedEpnixPkgs} + ''; + + pkgsListPandoc = '' + Packages list + ============= + + ::: note + This page references all EPNix packages that may be used outside of an IOC. + For all IOC-specific packages, see the [IOC packages list](../ioc/references/packages.md). + ::: + + Packages + -------- + + ${epnixLib.documentation.pkgsList 3 documentedEpnixPkgs} + ''; +in + stdenvNoCC.mkDerivation { + pname = "epnix-docs"; + version = "23.11"; + + src = ../../docs; + + nativeBuildInputs = + (with python3.pkgs; [ + furo + myst-parser + sphinx + sphinx-copybutton + ]) + ++ [ + installShellFiles + ]; + + dontConfigure = true; + + postPatch = '' + mkdir ioc/references + mkdir pkgs + + cp "${writeText "ioc-options.md" iocOptionsPandoc}" ioc/references/options.md + cp "${writeText "ioc-packages.md" iocPkgsListPandoc}" ioc/references/packages.md + cp "${writeText "nixos-options.md" nixosOptionsPandoc}" nixos-services/options.md + cp "${writeText "packages.md" pkgsListPandoc}" pkgs/packages.md + ''; + + buildPhase = '' + runHook preBuild + + make html man + + runHook postBuild + ''; + + installPhase = '' + runHook preInstall + + mkdir -p $out/bin + mkdir -p $out/share/doc/epnix/ + + cp -r _build/html $out/share/doc/epnix/ + installManPage _build/man/*.? + + runHook postInstall + ''; + + meta = { + description = "The EPNix documentation"; + homepage = "https://epics-extensions.github.io/EPNix/"; + license = lib.licenses.asl20; + maintainers = with epnixLib.maintainers; [minijackson]; + # hidden = true; + }; + } From f97e1e49c4603b52eef4c1c2243ffc237d6a15b9 Mon Sep 17 00:00:00 2001 From: Minijackson Date: Thu, 25 Jul 2024 10:03:36 +0200 Subject: [PATCH 026/111] lib/documentation: filter out "_module" options in documentation --- lib/documentation/options.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/documentation/options.nix b/lib/documentation/options.nix index ffd86822..c6d95ee1 100644 --- a/lib/documentation/options.nix +++ b/lib/documentation/options.nix @@ -5,7 +5,7 @@ ... }: lib.fix (self: { - visibleOptionDocs = lib.filter (opt: opt.visible && !opt.internal); + visibleOptionDocs = lib.filter (opt: opt.visible && !opt.internal && (lib.head opt.loc) != "_module"); optionsContent = options: headingLevel: lib.concatStringsSep "\n" From 68696973d5a34cfe2d87b0cd4d609f41fd798919 Mon Sep 17 00:00:00 2001 From: Minijackson Date: Thu, 25 Jul 2024 10:03:59 +0200 Subject: [PATCH 027/111] lib/documentation: use custom source:// link for EPNix code links --- lib/documentation.nix | 9 ++------- lib/documentation/markdown.nix | 27 ++++++++++++++++++++++----- 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/lib/documentation.nix b/lib/documentation.nix index f3a6e1b0..0c169eea 100644 --- a/lib/documentation.nix +++ b/lib/documentation.nix @@ -95,14 +95,10 @@ ${lib.optionalString (pkg.meta ? position) (let filePath = lib.head (lib.splitString ":" pkg.meta.position); - relativePath = lib.pipe filePath [ - (lib.splitString "/") - (lib.sublist 4 255) - (lib.concatStringsSep "/") - ]; + declarationLink = self.markdown.sourceLink filePath; in '' Declared in - : ${self.markdown.inDefList "[${relativePath}](file://${filePath})"} + : ${self.markdown.inDefList declarationLink} '')} License(s) @@ -113,7 +109,6 @@ ${lib.optionalString ((lib.length pkg.meta.maintainers) > 1) " - [Mail to all maintainers](mailto:${lib.concatStringsSep "," (map (m: m.email) pkg.meta.maintainers)})"} - ''; }; in diff --git a/lib/documentation/markdown.nix b/lib/documentation/markdown.nix index 0cfbe459..fe32167f 100644 --- a/lib/documentation/markdown.nix +++ b/lib/documentation/markdown.nix @@ -1,5 +1,11 @@ -{lib, ...}: +{ + inputs, + lib, + ... +}: lib.fix (self: let + rev = inputs.self.sourceInfo.rev or "master"; + # Quote an option if it contains a "." in it maybeQuote = el: if lib.hasInfix "." el @@ -8,6 +14,7 @@ lib.fix (self: let # Add a suggested word break after each "." so that it is easier to read wordBreakOption = loc: lib.concatStringsSep "." (map maybeQuote loc); + optionName = loc: lib.concatStringsSep "." (map maybeQuote loc); isLiteral = value: value @@ -40,15 +47,25 @@ in { # '' inDefList = str: let lines = lib.splitString "\n" str; - firstLine = " ${lib.head lines}"; - otherLines = map (line: " ${line}") (lib.drop 1 lines); + firstLine = "${lib.head lines}"; + otherLines = map (line: " ${line}") (lib.drop 1 lines); in lib.concatStringsSep "\n" ([firstLine] ++ otherLines); + # Takes an absolute path, returns a source:// markdown link + sourceLink = path: let + relativePath = lib.pipe path [ + (lib.splitString "/") + (lib.sublist 4 255) + (lib.concatStringsSep "/") + ]; + in "[${relativePath}](source://${rev}/${relativePath})"; + fromOption = headingLevel: option: let header = lib.fixedWidthString headingLevel "#" ""; in '' - ${header} ${wordBreakOption (map lib.escapeXML option.loc)} + (opt-${optionName option.loc})= + ${header} `${optionName option.loc}` ${self.toText option.description} @@ -74,7 +91,7 @@ in { ''} Declared in - : ${self.inDefList (lib.concatStringsSep "\n" (map (decl: "- ${decl}") option.declarations))} + : ${self.inDefList (lib.concatStringsSep "\n" (map self.sourceLink option.declarations))} ''; }) From 063f7c53fe0baaab58faa1acafb637bc317a7663 Mon Sep 17 00:00:00 2001 From: Minijackson Date: Thu, 25 Jul 2024 10:04:38 +0200 Subject: [PATCH 028/111] flake: remove quarto, add inputs from the docs package for devShell --- flake.nix | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/flake.nix b/flake.nix index 63c68160..b7b8b19c 100644 --- a/flake.nix +++ b/flake.nix @@ -55,15 +55,14 @@ package = pkgs.poetry; category = "development tools"; } - { - package = pkgs.quartoMinimal; - category = "development tools"; - } { package = pkgs.vale; category = "development tools"; } ]; + devShell.attrs.inputsFrom = [ + pkgs.epnix.docs + ]; }; }; From 2daf4324e1268a8129bb6c8b355b1256c8fdbf52 Mon Sep 17 00:00:00 2001 From: Minijackson Date: Thu, 25 Jul 2024 10:16:10 +0200 Subject: [PATCH 029/111] docs: move vale over to new directory, configure for RST --- .vale.ini | 6 +++--- {doc => docs}/_vale/Google/AMPM.yml | 0 {doc => docs}/_vale/Google/Acronyms.yml | 0 {doc => docs}/_vale/Google/Colons.yml | 0 {doc => docs}/_vale/Google/Contractions.yml | 0 {doc => docs}/_vale/Google/DateFormat.yml | 0 {doc => docs}/_vale/Google/Ellipses.yml | 0 {doc => docs}/_vale/Google/EmDash.yml | 0 {doc => docs}/_vale/Google/EnDash.yml | 0 {doc => docs}/_vale/Google/Exclamation.yml | 0 {doc => docs}/_vale/Google/FirstPerson.yml | 0 {doc => docs}/_vale/Google/Gender.yml | 0 {doc => docs}/_vale/Google/GenderBias.yml | 0 {doc => docs}/_vale/Google/HeadingPunctuation.yml | 0 {doc => docs}/_vale/Google/Headings.yml | 0 {doc => docs}/_vale/Google/Latin.yml | 0 {doc => docs}/_vale/Google/LyHyphens.yml | 0 {doc => docs}/_vale/Google/OptionalPlurals.yml | 0 {doc => docs}/_vale/Google/Ordinal.yml | 0 {doc => docs}/_vale/Google/OxfordComma.yml | 0 {doc => docs}/_vale/Google/Parens.yml | 0 {doc => docs}/_vale/Google/Passive.yml | 0 {doc => docs}/_vale/Google/Periods.yml | 0 {doc => docs}/_vale/Google/Quotes.yml | 0 {doc => docs}/_vale/Google/Ranges.yml | 0 {doc => docs}/_vale/Google/Semicolons.yml | 0 {doc => docs}/_vale/Google/Slang.yml | 0 {doc => docs}/_vale/Google/Spacing.yml | 0 {doc => docs}/_vale/Google/Spelling.yml | 0 {doc => docs}/_vale/Google/Units.yml | 0 {doc => docs}/_vale/Google/We.yml | 0 {doc => docs}/_vale/Google/Will.yml | 0 {doc => docs}/_vale/Google/WordList.yml | 0 {doc => docs}/_vale/Google/meta.json | 0 {doc => docs}/_vale/Google/vocab.txt | 0 {doc => docs}/_vale/Microsoft/AMPM.yml | 0 {doc => docs}/_vale/Microsoft/Accessibility.yml | 0 {doc => docs}/_vale/Microsoft/Acronyms.yml | 0 {doc => docs}/_vale/Microsoft/Adverbs.yml | 0 {doc => docs}/_vale/Microsoft/Auto.yml | 0 {doc => docs}/_vale/Microsoft/Avoid.yml | 0 {doc => docs}/_vale/Microsoft/ComplexWords.yml | 0 {doc => docs}/_vale/Microsoft/Contractions.yml | 0 {doc => docs}/_vale/Microsoft/Dashes.yml | 0 {doc => docs}/_vale/Microsoft/DateFormat.yml | 0 {doc => docs}/_vale/Microsoft/DateNumbers.yml | 0 {doc => docs}/_vale/Microsoft/DateOrder.yml | 0 {doc => docs}/_vale/Microsoft/Ellipses.yml | 0 {doc => docs}/_vale/Microsoft/FirstPerson.yml | 0 {doc => docs}/_vale/Microsoft/Foreign.yml | 0 {doc => docs}/_vale/Microsoft/Gender.yml | 0 {doc => docs}/_vale/Microsoft/GenderBias.yml | 0 {doc => docs}/_vale/Microsoft/GeneralURL.yml | 0 {doc => docs}/_vale/Microsoft/HeadingAcronyms.yml | 0 {doc => docs}/_vale/Microsoft/HeadingColons.yml | 0 {doc => docs}/_vale/Microsoft/HeadingPunctuation.yml | 0 {doc => docs}/_vale/Microsoft/Headings.yml | 0 {doc => docs}/_vale/Microsoft/Hyphens.yml | 0 {doc => docs}/_vale/Microsoft/Negative.yml | 0 {doc => docs}/_vale/Microsoft/Ordinal.yml | 0 {doc => docs}/_vale/Microsoft/OxfordComma.yml | 0 {doc => docs}/_vale/Microsoft/Passive.yml | 0 {doc => docs}/_vale/Microsoft/Percentages.yml | 0 {doc => docs}/_vale/Microsoft/Quotes.yml | 0 {doc => docs}/_vale/Microsoft/RangeFormat.yml | 0 {doc => docs}/_vale/Microsoft/RangeTime.yml | 0 {doc => docs}/_vale/Microsoft/Ranges.yml | 0 {doc => docs}/_vale/Microsoft/Semicolon.yml | 0 {doc => docs}/_vale/Microsoft/SentenceLength.yml | 0 {doc => docs}/_vale/Microsoft/Spacing.yml | 0 {doc => docs}/_vale/Microsoft/Suspended.yml | 0 {doc => docs}/_vale/Microsoft/Terms.yml | 0 {doc => docs}/_vale/Microsoft/URLFormat.yml | 0 {doc => docs}/_vale/Microsoft/Units.yml | 0 {doc => docs}/_vale/Microsoft/Vocab.yml | 0 {doc => docs}/_vale/Microsoft/We.yml | 0 {doc => docs}/_vale/Microsoft/Wordiness.yml | 0 {doc => docs}/_vale/Microsoft/meta.json | 0 {doc => docs}/_vale/RedHat/Abbreviations.yml | 0 {doc => docs}/_vale/RedHat/CaseSensitiveTerms.yml | 0 {doc => docs}/_vale/RedHat/Conjunctions.yml | 0 {doc => docs}/_vale/RedHat/ConsciousLanguage.yml | 0 {doc => docs}/_vale/RedHat/Contractions.yml | 0 {doc => docs}/_vale/RedHat/Definitions.yml | 0 {doc => docs}/_vale/RedHat/DoNotUseTerms.yml | 0 {doc => docs}/_vale/RedHat/Ellipses.yml | 0 {doc => docs}/_vale/RedHat/HeadingPunctuation.yml | 0 {doc => docs}/_vale/RedHat/Headings.yml | 0 {doc => docs}/_vale/RedHat/Hyphens.yml | 0 {doc => docs}/_vale/RedHat/OxfordComma.yml | 0 {doc => docs}/_vale/RedHat/PascalCamelCase.yml | 0 {doc => docs}/_vale/RedHat/PassiveVoice.yml | 0 {doc => docs}/_vale/RedHat/README-IBM.adoc | 0 {doc => docs}/_vale/RedHat/README-proselint.md | 0 {doc => docs}/_vale/RedHat/README-write-good.md | 0 {doc => docs}/_vale/RedHat/ReadabilityGrade.yml | 0 {doc => docs}/_vale/RedHat/ReleaseNotes.yml | 0 {doc => docs}/_vale/RedHat/RepeatedWords.yml | 0 {doc => docs}/_vale/RedHat/SelfReferentialText.yml | 0 {doc => docs}/_vale/RedHat/SentenceLength.yml | 0 {doc => docs}/_vale/RedHat/SimpleWords.yml | 0 {doc => docs}/_vale/RedHat/Slash.yml | 0 {doc => docs}/_vale/RedHat/Spacing.yml | 0 {doc => docs}/_vale/RedHat/Spelling.yml | 0 {doc => docs}/_vale/RedHat/Symbols.yml | 0 {doc => docs}/_vale/RedHat/TermsErrors.yml | 0 {doc => docs}/_vale/RedHat/TermsSuggestions.yml | 0 {doc => docs}/_vale/RedHat/TermsWarnings.yml | 0 {doc => docs}/_vale/RedHat/UserReplacedValues.yml | 0 {doc => docs}/_vale/RedHat/collate-output.tmpl | 0 {doc => docs}/_vale/RedHat/meta.json | 0 {doc => docs}/_vale/alex/Ablist.yml | 0 {doc => docs}/_vale/alex/Condescending.yml | 0 {doc => docs}/_vale/alex/Gendered.yml | 0 {doc => docs}/_vale/alex/LGBTQ.yml | 0 {doc => docs}/_vale/alex/Press.yml | 0 {doc => docs}/_vale/alex/ProfanityLikely.yml | 0 {doc => docs}/_vale/alex/ProfanityMaybe.yml | 0 {doc => docs}/_vale/alex/ProfanityUnlikely.yml | 0 {doc => docs}/_vale/alex/README.md | 0 {doc => docs}/_vale/alex/Race.yml | 0 {doc => docs}/_vale/alex/Suicide.yml | 0 {doc => docs}/_vale/alex/meta.json | 0 {doc => docs}/_vale/config/vocabularies/EPNix/accept.txt | 0 {doc => docs}/_vale/config/vocabularies/EPNix/reject.txt | 0 {doc => docs}/_vale/proselint/Airlinese.yml | 0 {doc => docs}/_vale/proselint/AnimalLabels.yml | 0 {doc => docs}/_vale/proselint/Annotations.yml | 0 {doc => docs}/_vale/proselint/Apologizing.yml | 0 {doc => docs}/_vale/proselint/Archaisms.yml | 0 {doc => docs}/_vale/proselint/But.yml | 0 {doc => docs}/_vale/proselint/Cliches.yml | 0 {doc => docs}/_vale/proselint/CorporateSpeak.yml | 0 {doc => docs}/_vale/proselint/Currency.yml | 0 {doc => docs}/_vale/proselint/Cursing.yml | 0 {doc => docs}/_vale/proselint/DateCase.yml | 0 {doc => docs}/_vale/proselint/DateMidnight.yml | 0 {doc => docs}/_vale/proselint/DateRedundancy.yml | 0 {doc => docs}/_vale/proselint/DateSpacing.yml | 0 {doc => docs}/_vale/proselint/DenizenLabels.yml | 0 {doc => docs}/_vale/proselint/Diacritical.yml | 0 {doc => docs}/_vale/proselint/GenderBias.yml | 0 {doc => docs}/_vale/proselint/GroupTerms.yml | 0 {doc => docs}/_vale/proselint/Hedging.yml | 0 {doc => docs}/_vale/proselint/Hyperbole.yml | 0 {doc => docs}/_vale/proselint/Jargon.yml | 0 {doc => docs}/_vale/proselint/LGBTOffensive.yml | 0 {doc => docs}/_vale/proselint/LGBTTerms.yml | 0 {doc => docs}/_vale/proselint/Malapropisms.yml | 0 {doc => docs}/_vale/proselint/Needless.yml | 0 {doc => docs}/_vale/proselint/Nonwords.yml | 0 {doc => docs}/_vale/proselint/Oxymorons.yml | 0 {doc => docs}/_vale/proselint/P-Value.yml | 0 {doc => docs}/_vale/proselint/RASSyndrome.yml | 0 {doc => docs}/_vale/proselint/README.md | 0 {doc => docs}/_vale/proselint/Skunked.yml | 0 {doc => docs}/_vale/proselint/Spelling.yml | 0 {doc => docs}/_vale/proselint/Typography.yml | 0 {doc => docs}/_vale/proselint/Uncomparables.yml | 0 {doc => docs}/_vale/proselint/Very.yml | 0 {doc => docs}/_vale/proselint/meta.json | 0 {doc => docs}/_vale/write-good/Cliches.yml | 0 {doc => docs}/_vale/write-good/E-Prime.yml | 0 {doc => docs}/_vale/write-good/Illusions.yml | 0 {doc => docs}/_vale/write-good/Passive.yml | 0 {doc => docs}/_vale/write-good/README.md | 0 {doc => docs}/_vale/write-good/So.yml | 0 {doc => docs}/_vale/write-good/ThereIs.yml | 0 {doc => docs}/_vale/write-good/TooWordy.yml | 0 {doc => docs}/_vale/write-good/Weasel.yml | 0 {doc => docs}/_vale/write-good/meta.json | 0 docs/conf.py | 7 ++++++- 172 files changed, 9 insertions(+), 4 deletions(-) rename {doc => docs}/_vale/Google/AMPM.yml (100%) rename {doc => docs}/_vale/Google/Acronyms.yml (100%) rename {doc => docs}/_vale/Google/Colons.yml (100%) rename {doc => docs}/_vale/Google/Contractions.yml (100%) rename {doc => docs}/_vale/Google/DateFormat.yml (100%) rename {doc => docs}/_vale/Google/Ellipses.yml (100%) rename {doc => docs}/_vale/Google/EmDash.yml (100%) rename {doc => docs}/_vale/Google/EnDash.yml (100%) rename {doc => docs}/_vale/Google/Exclamation.yml (100%) rename {doc => docs}/_vale/Google/FirstPerson.yml (100%) rename {doc => docs}/_vale/Google/Gender.yml (100%) rename {doc => docs}/_vale/Google/GenderBias.yml (100%) rename {doc => docs}/_vale/Google/HeadingPunctuation.yml (100%) rename {doc => docs}/_vale/Google/Headings.yml (100%) rename {doc => docs}/_vale/Google/Latin.yml (100%) rename {doc => docs}/_vale/Google/LyHyphens.yml (100%) rename {doc => docs}/_vale/Google/OptionalPlurals.yml (100%) rename {doc => docs}/_vale/Google/Ordinal.yml (100%) rename {doc => docs}/_vale/Google/OxfordComma.yml (100%) rename {doc => docs}/_vale/Google/Parens.yml (100%) rename {doc => docs}/_vale/Google/Passive.yml (100%) rename {doc => docs}/_vale/Google/Periods.yml (100%) rename {doc => docs}/_vale/Google/Quotes.yml (100%) rename {doc => docs}/_vale/Google/Ranges.yml (100%) rename {doc => docs}/_vale/Google/Semicolons.yml (100%) rename {doc => docs}/_vale/Google/Slang.yml (100%) rename {doc => docs}/_vale/Google/Spacing.yml (100%) rename {doc => docs}/_vale/Google/Spelling.yml (100%) rename {doc => docs}/_vale/Google/Units.yml (100%) rename {doc => docs}/_vale/Google/We.yml (100%) rename {doc => docs}/_vale/Google/Will.yml (100%) rename {doc => docs}/_vale/Google/WordList.yml (100%) rename {doc => docs}/_vale/Google/meta.json (100%) rename {doc => docs}/_vale/Google/vocab.txt (100%) rename {doc => docs}/_vale/Microsoft/AMPM.yml (100%) rename {doc => docs}/_vale/Microsoft/Accessibility.yml (100%) rename {doc => docs}/_vale/Microsoft/Acronyms.yml (100%) rename {doc => docs}/_vale/Microsoft/Adverbs.yml (100%) rename {doc => docs}/_vale/Microsoft/Auto.yml (100%) rename {doc => docs}/_vale/Microsoft/Avoid.yml (100%) rename {doc => docs}/_vale/Microsoft/ComplexWords.yml (100%) rename {doc => docs}/_vale/Microsoft/Contractions.yml (100%) rename {doc => docs}/_vale/Microsoft/Dashes.yml (100%) rename {doc => docs}/_vale/Microsoft/DateFormat.yml (100%) rename {doc => docs}/_vale/Microsoft/DateNumbers.yml (100%) rename {doc => docs}/_vale/Microsoft/DateOrder.yml (100%) rename {doc => docs}/_vale/Microsoft/Ellipses.yml (100%) rename {doc => docs}/_vale/Microsoft/FirstPerson.yml (100%) rename {doc => docs}/_vale/Microsoft/Foreign.yml (100%) rename {doc => docs}/_vale/Microsoft/Gender.yml (100%) rename {doc => docs}/_vale/Microsoft/GenderBias.yml (100%) rename {doc => docs}/_vale/Microsoft/GeneralURL.yml (100%) rename {doc => docs}/_vale/Microsoft/HeadingAcronyms.yml (100%) rename {doc => docs}/_vale/Microsoft/HeadingColons.yml (100%) rename {doc => docs}/_vale/Microsoft/HeadingPunctuation.yml (100%) rename {doc => docs}/_vale/Microsoft/Headings.yml (100%) rename {doc => docs}/_vale/Microsoft/Hyphens.yml (100%) rename {doc => docs}/_vale/Microsoft/Negative.yml (100%) rename {doc => docs}/_vale/Microsoft/Ordinal.yml (100%) rename {doc => docs}/_vale/Microsoft/OxfordComma.yml (100%) rename {doc => docs}/_vale/Microsoft/Passive.yml (100%) rename {doc => docs}/_vale/Microsoft/Percentages.yml (100%) rename {doc => docs}/_vale/Microsoft/Quotes.yml (100%) rename {doc => docs}/_vale/Microsoft/RangeFormat.yml (100%) rename {doc => docs}/_vale/Microsoft/RangeTime.yml (100%) rename {doc => docs}/_vale/Microsoft/Ranges.yml (100%) rename {doc => docs}/_vale/Microsoft/Semicolon.yml (100%) rename {doc => docs}/_vale/Microsoft/SentenceLength.yml (100%) rename {doc => docs}/_vale/Microsoft/Spacing.yml (100%) rename {doc => docs}/_vale/Microsoft/Suspended.yml (100%) rename {doc => docs}/_vale/Microsoft/Terms.yml (100%) rename {doc => docs}/_vale/Microsoft/URLFormat.yml (100%) rename {doc => docs}/_vale/Microsoft/Units.yml (100%) rename {doc => docs}/_vale/Microsoft/Vocab.yml (100%) rename {doc => docs}/_vale/Microsoft/We.yml (100%) rename {doc => docs}/_vale/Microsoft/Wordiness.yml (100%) rename {doc => docs}/_vale/Microsoft/meta.json (100%) rename {doc => docs}/_vale/RedHat/Abbreviations.yml (100%) rename {doc => docs}/_vale/RedHat/CaseSensitiveTerms.yml (100%) rename {doc => docs}/_vale/RedHat/Conjunctions.yml (100%) rename {doc => docs}/_vale/RedHat/ConsciousLanguage.yml (100%) rename {doc => docs}/_vale/RedHat/Contractions.yml (100%) rename {doc => docs}/_vale/RedHat/Definitions.yml (100%) rename {doc => docs}/_vale/RedHat/DoNotUseTerms.yml (100%) rename {doc => docs}/_vale/RedHat/Ellipses.yml (100%) rename {doc => docs}/_vale/RedHat/HeadingPunctuation.yml (100%) rename {doc => docs}/_vale/RedHat/Headings.yml (100%) rename {doc => docs}/_vale/RedHat/Hyphens.yml (100%) rename {doc => docs}/_vale/RedHat/OxfordComma.yml (100%) rename {doc => docs}/_vale/RedHat/PascalCamelCase.yml (100%) rename {doc => docs}/_vale/RedHat/PassiveVoice.yml (100%) rename {doc => docs}/_vale/RedHat/README-IBM.adoc (100%) rename {doc => docs}/_vale/RedHat/README-proselint.md (100%) rename {doc => docs}/_vale/RedHat/README-write-good.md (100%) rename {doc => docs}/_vale/RedHat/ReadabilityGrade.yml (100%) rename {doc => docs}/_vale/RedHat/ReleaseNotes.yml (100%) rename {doc => docs}/_vale/RedHat/RepeatedWords.yml (100%) rename {doc => docs}/_vale/RedHat/SelfReferentialText.yml (100%) rename {doc => docs}/_vale/RedHat/SentenceLength.yml (100%) rename {doc => docs}/_vale/RedHat/SimpleWords.yml (100%) rename {doc => docs}/_vale/RedHat/Slash.yml (100%) rename {doc => docs}/_vale/RedHat/Spacing.yml (100%) rename {doc => docs}/_vale/RedHat/Spelling.yml (100%) rename {doc => docs}/_vale/RedHat/Symbols.yml (100%) rename {doc => docs}/_vale/RedHat/TermsErrors.yml (100%) rename {doc => docs}/_vale/RedHat/TermsSuggestions.yml (100%) rename {doc => docs}/_vale/RedHat/TermsWarnings.yml (100%) rename {doc => docs}/_vale/RedHat/UserReplacedValues.yml (100%) rename {doc => docs}/_vale/RedHat/collate-output.tmpl (100%) rename {doc => docs}/_vale/RedHat/meta.json (100%) rename {doc => docs}/_vale/alex/Ablist.yml (100%) rename {doc => docs}/_vale/alex/Condescending.yml (100%) rename {doc => docs}/_vale/alex/Gendered.yml (100%) rename {doc => docs}/_vale/alex/LGBTQ.yml (100%) rename {doc => docs}/_vale/alex/Press.yml (100%) rename {doc => docs}/_vale/alex/ProfanityLikely.yml (100%) rename {doc => docs}/_vale/alex/ProfanityMaybe.yml (100%) rename {doc => docs}/_vale/alex/ProfanityUnlikely.yml (100%) rename {doc => docs}/_vale/alex/README.md (100%) rename {doc => docs}/_vale/alex/Race.yml (100%) rename {doc => docs}/_vale/alex/Suicide.yml (100%) rename {doc => docs}/_vale/alex/meta.json (100%) rename {doc => docs}/_vale/config/vocabularies/EPNix/accept.txt (100%) rename {doc => docs}/_vale/config/vocabularies/EPNix/reject.txt (100%) rename {doc => docs}/_vale/proselint/Airlinese.yml (100%) rename {doc => docs}/_vale/proselint/AnimalLabels.yml (100%) rename {doc => docs}/_vale/proselint/Annotations.yml (100%) rename {doc => docs}/_vale/proselint/Apologizing.yml (100%) rename {doc => docs}/_vale/proselint/Archaisms.yml (100%) rename {doc => docs}/_vale/proselint/But.yml (100%) rename {doc => docs}/_vale/proselint/Cliches.yml (100%) rename {doc => docs}/_vale/proselint/CorporateSpeak.yml (100%) rename {doc => docs}/_vale/proselint/Currency.yml (100%) rename {doc => docs}/_vale/proselint/Cursing.yml (100%) rename {doc => docs}/_vale/proselint/DateCase.yml (100%) rename {doc => docs}/_vale/proselint/DateMidnight.yml (100%) rename {doc => docs}/_vale/proselint/DateRedundancy.yml (100%) rename {doc => docs}/_vale/proselint/DateSpacing.yml (100%) rename {doc => docs}/_vale/proselint/DenizenLabels.yml (100%) rename {doc => docs}/_vale/proselint/Diacritical.yml (100%) rename {doc => docs}/_vale/proselint/GenderBias.yml (100%) rename {doc => docs}/_vale/proselint/GroupTerms.yml (100%) rename {doc => docs}/_vale/proselint/Hedging.yml (100%) rename {doc => docs}/_vale/proselint/Hyperbole.yml (100%) rename {doc => docs}/_vale/proselint/Jargon.yml (100%) rename {doc => docs}/_vale/proselint/LGBTOffensive.yml (100%) rename {doc => docs}/_vale/proselint/LGBTTerms.yml (100%) rename {doc => docs}/_vale/proselint/Malapropisms.yml (100%) rename {doc => docs}/_vale/proselint/Needless.yml (100%) rename {doc => docs}/_vale/proselint/Nonwords.yml (100%) rename {doc => docs}/_vale/proselint/Oxymorons.yml (100%) rename {doc => docs}/_vale/proselint/P-Value.yml (100%) rename {doc => docs}/_vale/proselint/RASSyndrome.yml (100%) rename {doc => docs}/_vale/proselint/README.md (100%) rename {doc => docs}/_vale/proselint/Skunked.yml (100%) rename {doc => docs}/_vale/proselint/Spelling.yml (100%) rename {doc => docs}/_vale/proselint/Typography.yml (100%) rename {doc => docs}/_vale/proselint/Uncomparables.yml (100%) rename {doc => docs}/_vale/proselint/Very.yml (100%) rename {doc => docs}/_vale/proselint/meta.json (100%) rename {doc => docs}/_vale/write-good/Cliches.yml (100%) rename {doc => docs}/_vale/write-good/E-Prime.yml (100%) rename {doc => docs}/_vale/write-good/Illusions.yml (100%) rename {doc => docs}/_vale/write-good/Passive.yml (100%) rename {doc => docs}/_vale/write-good/README.md (100%) rename {doc => docs}/_vale/write-good/So.yml (100%) rename {doc => docs}/_vale/write-good/ThereIs.yml (100%) rename {doc => docs}/_vale/write-good/TooWordy.yml (100%) rename {doc => docs}/_vale/write-good/Weasel.yml (100%) rename {doc => docs}/_vale/write-good/meta.json (100%) diff --git a/.vale.ini b/.vale.ini index 82822175..12e05b07 100644 --- a/.vale.ini +++ b/.vale.ini @@ -1,12 +1,12 @@ -StylesPath = doc/_vale +StylesPath = docs/_vale MinAlertLevel = suggestion Vocab = EPNix # External packages Packages = alex, Google, Microsoft, proselint, RedHat, write-good -# Only Markdown and .txt files; change to whatever you're using. -[*.md] + +[*.{md,rst}] # List of styles to load. BasedOnStyles = alex, Google, Microsoft, proselint, RedHat, Vale, write-good diff --git a/doc/_vale/Google/AMPM.yml b/docs/_vale/Google/AMPM.yml similarity index 100% rename from doc/_vale/Google/AMPM.yml rename to docs/_vale/Google/AMPM.yml diff --git a/doc/_vale/Google/Acronyms.yml b/docs/_vale/Google/Acronyms.yml similarity index 100% rename from doc/_vale/Google/Acronyms.yml rename to docs/_vale/Google/Acronyms.yml diff --git a/doc/_vale/Google/Colons.yml b/docs/_vale/Google/Colons.yml similarity index 100% rename from doc/_vale/Google/Colons.yml rename to docs/_vale/Google/Colons.yml diff --git a/doc/_vale/Google/Contractions.yml b/docs/_vale/Google/Contractions.yml similarity index 100% rename from doc/_vale/Google/Contractions.yml rename to docs/_vale/Google/Contractions.yml diff --git a/doc/_vale/Google/DateFormat.yml b/docs/_vale/Google/DateFormat.yml similarity index 100% rename from doc/_vale/Google/DateFormat.yml rename to docs/_vale/Google/DateFormat.yml diff --git a/doc/_vale/Google/Ellipses.yml b/docs/_vale/Google/Ellipses.yml similarity index 100% rename from doc/_vale/Google/Ellipses.yml rename to docs/_vale/Google/Ellipses.yml diff --git a/doc/_vale/Google/EmDash.yml b/docs/_vale/Google/EmDash.yml similarity index 100% rename from doc/_vale/Google/EmDash.yml rename to docs/_vale/Google/EmDash.yml diff --git a/doc/_vale/Google/EnDash.yml b/docs/_vale/Google/EnDash.yml similarity index 100% rename from doc/_vale/Google/EnDash.yml rename to docs/_vale/Google/EnDash.yml diff --git a/doc/_vale/Google/Exclamation.yml b/docs/_vale/Google/Exclamation.yml similarity index 100% rename from doc/_vale/Google/Exclamation.yml rename to docs/_vale/Google/Exclamation.yml diff --git a/doc/_vale/Google/FirstPerson.yml b/docs/_vale/Google/FirstPerson.yml similarity index 100% rename from doc/_vale/Google/FirstPerson.yml rename to docs/_vale/Google/FirstPerson.yml diff --git a/doc/_vale/Google/Gender.yml b/docs/_vale/Google/Gender.yml similarity index 100% rename from doc/_vale/Google/Gender.yml rename to docs/_vale/Google/Gender.yml diff --git a/doc/_vale/Google/GenderBias.yml b/docs/_vale/Google/GenderBias.yml similarity index 100% rename from doc/_vale/Google/GenderBias.yml rename to docs/_vale/Google/GenderBias.yml diff --git a/doc/_vale/Google/HeadingPunctuation.yml b/docs/_vale/Google/HeadingPunctuation.yml similarity index 100% rename from doc/_vale/Google/HeadingPunctuation.yml rename to docs/_vale/Google/HeadingPunctuation.yml diff --git a/doc/_vale/Google/Headings.yml b/docs/_vale/Google/Headings.yml similarity index 100% rename from doc/_vale/Google/Headings.yml rename to docs/_vale/Google/Headings.yml diff --git a/doc/_vale/Google/Latin.yml b/docs/_vale/Google/Latin.yml similarity index 100% rename from doc/_vale/Google/Latin.yml rename to docs/_vale/Google/Latin.yml diff --git a/doc/_vale/Google/LyHyphens.yml b/docs/_vale/Google/LyHyphens.yml similarity index 100% rename from doc/_vale/Google/LyHyphens.yml rename to docs/_vale/Google/LyHyphens.yml diff --git a/doc/_vale/Google/OptionalPlurals.yml b/docs/_vale/Google/OptionalPlurals.yml similarity index 100% rename from doc/_vale/Google/OptionalPlurals.yml rename to docs/_vale/Google/OptionalPlurals.yml diff --git a/doc/_vale/Google/Ordinal.yml b/docs/_vale/Google/Ordinal.yml similarity index 100% rename from doc/_vale/Google/Ordinal.yml rename to docs/_vale/Google/Ordinal.yml diff --git a/doc/_vale/Google/OxfordComma.yml b/docs/_vale/Google/OxfordComma.yml similarity index 100% rename from doc/_vale/Google/OxfordComma.yml rename to docs/_vale/Google/OxfordComma.yml diff --git a/doc/_vale/Google/Parens.yml b/docs/_vale/Google/Parens.yml similarity index 100% rename from doc/_vale/Google/Parens.yml rename to docs/_vale/Google/Parens.yml diff --git a/doc/_vale/Google/Passive.yml b/docs/_vale/Google/Passive.yml similarity index 100% rename from doc/_vale/Google/Passive.yml rename to docs/_vale/Google/Passive.yml diff --git a/doc/_vale/Google/Periods.yml b/docs/_vale/Google/Periods.yml similarity index 100% rename from doc/_vale/Google/Periods.yml rename to docs/_vale/Google/Periods.yml diff --git a/doc/_vale/Google/Quotes.yml b/docs/_vale/Google/Quotes.yml similarity index 100% rename from doc/_vale/Google/Quotes.yml rename to docs/_vale/Google/Quotes.yml diff --git a/doc/_vale/Google/Ranges.yml b/docs/_vale/Google/Ranges.yml similarity index 100% rename from doc/_vale/Google/Ranges.yml rename to docs/_vale/Google/Ranges.yml diff --git a/doc/_vale/Google/Semicolons.yml b/docs/_vale/Google/Semicolons.yml similarity index 100% rename from doc/_vale/Google/Semicolons.yml rename to docs/_vale/Google/Semicolons.yml diff --git a/doc/_vale/Google/Slang.yml b/docs/_vale/Google/Slang.yml similarity index 100% rename from doc/_vale/Google/Slang.yml rename to docs/_vale/Google/Slang.yml diff --git a/doc/_vale/Google/Spacing.yml b/docs/_vale/Google/Spacing.yml similarity index 100% rename from doc/_vale/Google/Spacing.yml rename to docs/_vale/Google/Spacing.yml diff --git a/doc/_vale/Google/Spelling.yml b/docs/_vale/Google/Spelling.yml similarity index 100% rename from doc/_vale/Google/Spelling.yml rename to docs/_vale/Google/Spelling.yml diff --git a/doc/_vale/Google/Units.yml b/docs/_vale/Google/Units.yml similarity index 100% rename from doc/_vale/Google/Units.yml rename to docs/_vale/Google/Units.yml diff --git a/doc/_vale/Google/We.yml b/docs/_vale/Google/We.yml similarity index 100% rename from doc/_vale/Google/We.yml rename to docs/_vale/Google/We.yml diff --git a/doc/_vale/Google/Will.yml b/docs/_vale/Google/Will.yml similarity index 100% rename from doc/_vale/Google/Will.yml rename to docs/_vale/Google/Will.yml diff --git a/doc/_vale/Google/WordList.yml b/docs/_vale/Google/WordList.yml similarity index 100% rename from doc/_vale/Google/WordList.yml rename to docs/_vale/Google/WordList.yml diff --git a/doc/_vale/Google/meta.json b/docs/_vale/Google/meta.json similarity index 100% rename from doc/_vale/Google/meta.json rename to docs/_vale/Google/meta.json diff --git a/doc/_vale/Google/vocab.txt b/docs/_vale/Google/vocab.txt similarity index 100% rename from doc/_vale/Google/vocab.txt rename to docs/_vale/Google/vocab.txt diff --git a/doc/_vale/Microsoft/AMPM.yml b/docs/_vale/Microsoft/AMPM.yml similarity index 100% rename from doc/_vale/Microsoft/AMPM.yml rename to docs/_vale/Microsoft/AMPM.yml diff --git a/doc/_vale/Microsoft/Accessibility.yml b/docs/_vale/Microsoft/Accessibility.yml similarity index 100% rename from doc/_vale/Microsoft/Accessibility.yml rename to docs/_vale/Microsoft/Accessibility.yml diff --git a/doc/_vale/Microsoft/Acronyms.yml b/docs/_vale/Microsoft/Acronyms.yml similarity index 100% rename from doc/_vale/Microsoft/Acronyms.yml rename to docs/_vale/Microsoft/Acronyms.yml diff --git a/doc/_vale/Microsoft/Adverbs.yml b/docs/_vale/Microsoft/Adverbs.yml similarity index 100% rename from doc/_vale/Microsoft/Adverbs.yml rename to docs/_vale/Microsoft/Adverbs.yml diff --git a/doc/_vale/Microsoft/Auto.yml b/docs/_vale/Microsoft/Auto.yml similarity index 100% rename from doc/_vale/Microsoft/Auto.yml rename to docs/_vale/Microsoft/Auto.yml diff --git a/doc/_vale/Microsoft/Avoid.yml b/docs/_vale/Microsoft/Avoid.yml similarity index 100% rename from doc/_vale/Microsoft/Avoid.yml rename to docs/_vale/Microsoft/Avoid.yml diff --git a/doc/_vale/Microsoft/ComplexWords.yml b/docs/_vale/Microsoft/ComplexWords.yml similarity index 100% rename from doc/_vale/Microsoft/ComplexWords.yml rename to docs/_vale/Microsoft/ComplexWords.yml diff --git a/doc/_vale/Microsoft/Contractions.yml b/docs/_vale/Microsoft/Contractions.yml similarity index 100% rename from doc/_vale/Microsoft/Contractions.yml rename to docs/_vale/Microsoft/Contractions.yml diff --git a/doc/_vale/Microsoft/Dashes.yml b/docs/_vale/Microsoft/Dashes.yml similarity index 100% rename from doc/_vale/Microsoft/Dashes.yml rename to docs/_vale/Microsoft/Dashes.yml diff --git a/doc/_vale/Microsoft/DateFormat.yml b/docs/_vale/Microsoft/DateFormat.yml similarity index 100% rename from doc/_vale/Microsoft/DateFormat.yml rename to docs/_vale/Microsoft/DateFormat.yml diff --git a/doc/_vale/Microsoft/DateNumbers.yml b/docs/_vale/Microsoft/DateNumbers.yml similarity index 100% rename from doc/_vale/Microsoft/DateNumbers.yml rename to docs/_vale/Microsoft/DateNumbers.yml diff --git a/doc/_vale/Microsoft/DateOrder.yml b/docs/_vale/Microsoft/DateOrder.yml similarity index 100% rename from doc/_vale/Microsoft/DateOrder.yml rename to docs/_vale/Microsoft/DateOrder.yml diff --git a/doc/_vale/Microsoft/Ellipses.yml b/docs/_vale/Microsoft/Ellipses.yml similarity index 100% rename from doc/_vale/Microsoft/Ellipses.yml rename to docs/_vale/Microsoft/Ellipses.yml diff --git a/doc/_vale/Microsoft/FirstPerson.yml b/docs/_vale/Microsoft/FirstPerson.yml similarity index 100% rename from doc/_vale/Microsoft/FirstPerson.yml rename to docs/_vale/Microsoft/FirstPerson.yml diff --git a/doc/_vale/Microsoft/Foreign.yml b/docs/_vale/Microsoft/Foreign.yml similarity index 100% rename from doc/_vale/Microsoft/Foreign.yml rename to docs/_vale/Microsoft/Foreign.yml diff --git a/doc/_vale/Microsoft/Gender.yml b/docs/_vale/Microsoft/Gender.yml similarity index 100% rename from doc/_vale/Microsoft/Gender.yml rename to docs/_vale/Microsoft/Gender.yml diff --git a/doc/_vale/Microsoft/GenderBias.yml b/docs/_vale/Microsoft/GenderBias.yml similarity index 100% rename from doc/_vale/Microsoft/GenderBias.yml rename to docs/_vale/Microsoft/GenderBias.yml diff --git a/doc/_vale/Microsoft/GeneralURL.yml b/docs/_vale/Microsoft/GeneralURL.yml similarity index 100% rename from doc/_vale/Microsoft/GeneralURL.yml rename to docs/_vale/Microsoft/GeneralURL.yml diff --git a/doc/_vale/Microsoft/HeadingAcronyms.yml b/docs/_vale/Microsoft/HeadingAcronyms.yml similarity index 100% rename from doc/_vale/Microsoft/HeadingAcronyms.yml rename to docs/_vale/Microsoft/HeadingAcronyms.yml diff --git a/doc/_vale/Microsoft/HeadingColons.yml b/docs/_vale/Microsoft/HeadingColons.yml similarity index 100% rename from doc/_vale/Microsoft/HeadingColons.yml rename to docs/_vale/Microsoft/HeadingColons.yml diff --git a/doc/_vale/Microsoft/HeadingPunctuation.yml b/docs/_vale/Microsoft/HeadingPunctuation.yml similarity index 100% rename from doc/_vale/Microsoft/HeadingPunctuation.yml rename to docs/_vale/Microsoft/HeadingPunctuation.yml diff --git a/doc/_vale/Microsoft/Headings.yml b/docs/_vale/Microsoft/Headings.yml similarity index 100% rename from doc/_vale/Microsoft/Headings.yml rename to docs/_vale/Microsoft/Headings.yml diff --git a/doc/_vale/Microsoft/Hyphens.yml b/docs/_vale/Microsoft/Hyphens.yml similarity index 100% rename from doc/_vale/Microsoft/Hyphens.yml rename to docs/_vale/Microsoft/Hyphens.yml diff --git a/doc/_vale/Microsoft/Negative.yml b/docs/_vale/Microsoft/Negative.yml similarity index 100% rename from doc/_vale/Microsoft/Negative.yml rename to docs/_vale/Microsoft/Negative.yml diff --git a/doc/_vale/Microsoft/Ordinal.yml b/docs/_vale/Microsoft/Ordinal.yml similarity index 100% rename from doc/_vale/Microsoft/Ordinal.yml rename to docs/_vale/Microsoft/Ordinal.yml diff --git a/doc/_vale/Microsoft/OxfordComma.yml b/docs/_vale/Microsoft/OxfordComma.yml similarity index 100% rename from doc/_vale/Microsoft/OxfordComma.yml rename to docs/_vale/Microsoft/OxfordComma.yml diff --git a/doc/_vale/Microsoft/Passive.yml b/docs/_vale/Microsoft/Passive.yml similarity index 100% rename from doc/_vale/Microsoft/Passive.yml rename to docs/_vale/Microsoft/Passive.yml diff --git a/doc/_vale/Microsoft/Percentages.yml b/docs/_vale/Microsoft/Percentages.yml similarity index 100% rename from doc/_vale/Microsoft/Percentages.yml rename to docs/_vale/Microsoft/Percentages.yml diff --git a/doc/_vale/Microsoft/Quotes.yml b/docs/_vale/Microsoft/Quotes.yml similarity index 100% rename from doc/_vale/Microsoft/Quotes.yml rename to docs/_vale/Microsoft/Quotes.yml diff --git a/doc/_vale/Microsoft/RangeFormat.yml b/docs/_vale/Microsoft/RangeFormat.yml similarity index 100% rename from doc/_vale/Microsoft/RangeFormat.yml rename to docs/_vale/Microsoft/RangeFormat.yml diff --git a/doc/_vale/Microsoft/RangeTime.yml b/docs/_vale/Microsoft/RangeTime.yml similarity index 100% rename from doc/_vale/Microsoft/RangeTime.yml rename to docs/_vale/Microsoft/RangeTime.yml diff --git a/doc/_vale/Microsoft/Ranges.yml b/docs/_vale/Microsoft/Ranges.yml similarity index 100% rename from doc/_vale/Microsoft/Ranges.yml rename to docs/_vale/Microsoft/Ranges.yml diff --git a/doc/_vale/Microsoft/Semicolon.yml b/docs/_vale/Microsoft/Semicolon.yml similarity index 100% rename from doc/_vale/Microsoft/Semicolon.yml rename to docs/_vale/Microsoft/Semicolon.yml diff --git a/doc/_vale/Microsoft/SentenceLength.yml b/docs/_vale/Microsoft/SentenceLength.yml similarity index 100% rename from doc/_vale/Microsoft/SentenceLength.yml rename to docs/_vale/Microsoft/SentenceLength.yml diff --git a/doc/_vale/Microsoft/Spacing.yml b/docs/_vale/Microsoft/Spacing.yml similarity index 100% rename from doc/_vale/Microsoft/Spacing.yml rename to docs/_vale/Microsoft/Spacing.yml diff --git a/doc/_vale/Microsoft/Suspended.yml b/docs/_vale/Microsoft/Suspended.yml similarity index 100% rename from doc/_vale/Microsoft/Suspended.yml rename to docs/_vale/Microsoft/Suspended.yml diff --git a/doc/_vale/Microsoft/Terms.yml b/docs/_vale/Microsoft/Terms.yml similarity index 100% rename from doc/_vale/Microsoft/Terms.yml rename to docs/_vale/Microsoft/Terms.yml diff --git a/doc/_vale/Microsoft/URLFormat.yml b/docs/_vale/Microsoft/URLFormat.yml similarity index 100% rename from doc/_vale/Microsoft/URLFormat.yml rename to docs/_vale/Microsoft/URLFormat.yml diff --git a/doc/_vale/Microsoft/Units.yml b/docs/_vale/Microsoft/Units.yml similarity index 100% rename from doc/_vale/Microsoft/Units.yml rename to docs/_vale/Microsoft/Units.yml diff --git a/doc/_vale/Microsoft/Vocab.yml b/docs/_vale/Microsoft/Vocab.yml similarity index 100% rename from doc/_vale/Microsoft/Vocab.yml rename to docs/_vale/Microsoft/Vocab.yml diff --git a/doc/_vale/Microsoft/We.yml b/docs/_vale/Microsoft/We.yml similarity index 100% rename from doc/_vale/Microsoft/We.yml rename to docs/_vale/Microsoft/We.yml diff --git a/doc/_vale/Microsoft/Wordiness.yml b/docs/_vale/Microsoft/Wordiness.yml similarity index 100% rename from doc/_vale/Microsoft/Wordiness.yml rename to docs/_vale/Microsoft/Wordiness.yml diff --git a/doc/_vale/Microsoft/meta.json b/docs/_vale/Microsoft/meta.json similarity index 100% rename from doc/_vale/Microsoft/meta.json rename to docs/_vale/Microsoft/meta.json diff --git a/doc/_vale/RedHat/Abbreviations.yml b/docs/_vale/RedHat/Abbreviations.yml similarity index 100% rename from doc/_vale/RedHat/Abbreviations.yml rename to docs/_vale/RedHat/Abbreviations.yml diff --git a/doc/_vale/RedHat/CaseSensitiveTerms.yml b/docs/_vale/RedHat/CaseSensitiveTerms.yml similarity index 100% rename from doc/_vale/RedHat/CaseSensitiveTerms.yml rename to docs/_vale/RedHat/CaseSensitiveTerms.yml diff --git a/doc/_vale/RedHat/Conjunctions.yml b/docs/_vale/RedHat/Conjunctions.yml similarity index 100% rename from doc/_vale/RedHat/Conjunctions.yml rename to docs/_vale/RedHat/Conjunctions.yml diff --git a/doc/_vale/RedHat/ConsciousLanguage.yml b/docs/_vale/RedHat/ConsciousLanguage.yml similarity index 100% rename from doc/_vale/RedHat/ConsciousLanguage.yml rename to docs/_vale/RedHat/ConsciousLanguage.yml diff --git a/doc/_vale/RedHat/Contractions.yml b/docs/_vale/RedHat/Contractions.yml similarity index 100% rename from doc/_vale/RedHat/Contractions.yml rename to docs/_vale/RedHat/Contractions.yml diff --git a/doc/_vale/RedHat/Definitions.yml b/docs/_vale/RedHat/Definitions.yml similarity index 100% rename from doc/_vale/RedHat/Definitions.yml rename to docs/_vale/RedHat/Definitions.yml diff --git a/doc/_vale/RedHat/DoNotUseTerms.yml b/docs/_vale/RedHat/DoNotUseTerms.yml similarity index 100% rename from doc/_vale/RedHat/DoNotUseTerms.yml rename to docs/_vale/RedHat/DoNotUseTerms.yml diff --git a/doc/_vale/RedHat/Ellipses.yml b/docs/_vale/RedHat/Ellipses.yml similarity index 100% rename from doc/_vale/RedHat/Ellipses.yml rename to docs/_vale/RedHat/Ellipses.yml diff --git a/doc/_vale/RedHat/HeadingPunctuation.yml b/docs/_vale/RedHat/HeadingPunctuation.yml similarity index 100% rename from doc/_vale/RedHat/HeadingPunctuation.yml rename to docs/_vale/RedHat/HeadingPunctuation.yml diff --git a/doc/_vale/RedHat/Headings.yml b/docs/_vale/RedHat/Headings.yml similarity index 100% rename from doc/_vale/RedHat/Headings.yml rename to docs/_vale/RedHat/Headings.yml diff --git a/doc/_vale/RedHat/Hyphens.yml b/docs/_vale/RedHat/Hyphens.yml similarity index 100% rename from doc/_vale/RedHat/Hyphens.yml rename to docs/_vale/RedHat/Hyphens.yml diff --git a/doc/_vale/RedHat/OxfordComma.yml b/docs/_vale/RedHat/OxfordComma.yml similarity index 100% rename from doc/_vale/RedHat/OxfordComma.yml rename to docs/_vale/RedHat/OxfordComma.yml diff --git a/doc/_vale/RedHat/PascalCamelCase.yml b/docs/_vale/RedHat/PascalCamelCase.yml similarity index 100% rename from doc/_vale/RedHat/PascalCamelCase.yml rename to docs/_vale/RedHat/PascalCamelCase.yml diff --git a/doc/_vale/RedHat/PassiveVoice.yml b/docs/_vale/RedHat/PassiveVoice.yml similarity index 100% rename from doc/_vale/RedHat/PassiveVoice.yml rename to docs/_vale/RedHat/PassiveVoice.yml diff --git a/doc/_vale/RedHat/README-IBM.adoc b/docs/_vale/RedHat/README-IBM.adoc similarity index 100% rename from doc/_vale/RedHat/README-IBM.adoc rename to docs/_vale/RedHat/README-IBM.adoc diff --git a/doc/_vale/RedHat/README-proselint.md b/docs/_vale/RedHat/README-proselint.md similarity index 100% rename from doc/_vale/RedHat/README-proselint.md rename to docs/_vale/RedHat/README-proselint.md diff --git a/doc/_vale/RedHat/README-write-good.md b/docs/_vale/RedHat/README-write-good.md similarity index 100% rename from doc/_vale/RedHat/README-write-good.md rename to docs/_vale/RedHat/README-write-good.md diff --git a/doc/_vale/RedHat/ReadabilityGrade.yml b/docs/_vale/RedHat/ReadabilityGrade.yml similarity index 100% rename from doc/_vale/RedHat/ReadabilityGrade.yml rename to docs/_vale/RedHat/ReadabilityGrade.yml diff --git a/doc/_vale/RedHat/ReleaseNotes.yml b/docs/_vale/RedHat/ReleaseNotes.yml similarity index 100% rename from doc/_vale/RedHat/ReleaseNotes.yml rename to docs/_vale/RedHat/ReleaseNotes.yml diff --git a/doc/_vale/RedHat/RepeatedWords.yml b/docs/_vale/RedHat/RepeatedWords.yml similarity index 100% rename from doc/_vale/RedHat/RepeatedWords.yml rename to docs/_vale/RedHat/RepeatedWords.yml diff --git a/doc/_vale/RedHat/SelfReferentialText.yml b/docs/_vale/RedHat/SelfReferentialText.yml similarity index 100% rename from doc/_vale/RedHat/SelfReferentialText.yml rename to docs/_vale/RedHat/SelfReferentialText.yml diff --git a/doc/_vale/RedHat/SentenceLength.yml b/docs/_vale/RedHat/SentenceLength.yml similarity index 100% rename from doc/_vale/RedHat/SentenceLength.yml rename to docs/_vale/RedHat/SentenceLength.yml diff --git a/doc/_vale/RedHat/SimpleWords.yml b/docs/_vale/RedHat/SimpleWords.yml similarity index 100% rename from doc/_vale/RedHat/SimpleWords.yml rename to docs/_vale/RedHat/SimpleWords.yml diff --git a/doc/_vale/RedHat/Slash.yml b/docs/_vale/RedHat/Slash.yml similarity index 100% rename from doc/_vale/RedHat/Slash.yml rename to docs/_vale/RedHat/Slash.yml diff --git a/doc/_vale/RedHat/Spacing.yml b/docs/_vale/RedHat/Spacing.yml similarity index 100% rename from doc/_vale/RedHat/Spacing.yml rename to docs/_vale/RedHat/Spacing.yml diff --git a/doc/_vale/RedHat/Spelling.yml b/docs/_vale/RedHat/Spelling.yml similarity index 100% rename from doc/_vale/RedHat/Spelling.yml rename to docs/_vale/RedHat/Spelling.yml diff --git a/doc/_vale/RedHat/Symbols.yml b/docs/_vale/RedHat/Symbols.yml similarity index 100% rename from doc/_vale/RedHat/Symbols.yml rename to docs/_vale/RedHat/Symbols.yml diff --git a/doc/_vale/RedHat/TermsErrors.yml b/docs/_vale/RedHat/TermsErrors.yml similarity index 100% rename from doc/_vale/RedHat/TermsErrors.yml rename to docs/_vale/RedHat/TermsErrors.yml diff --git a/doc/_vale/RedHat/TermsSuggestions.yml b/docs/_vale/RedHat/TermsSuggestions.yml similarity index 100% rename from doc/_vale/RedHat/TermsSuggestions.yml rename to docs/_vale/RedHat/TermsSuggestions.yml diff --git a/doc/_vale/RedHat/TermsWarnings.yml b/docs/_vale/RedHat/TermsWarnings.yml similarity index 100% rename from doc/_vale/RedHat/TermsWarnings.yml rename to docs/_vale/RedHat/TermsWarnings.yml diff --git a/doc/_vale/RedHat/UserReplacedValues.yml b/docs/_vale/RedHat/UserReplacedValues.yml similarity index 100% rename from doc/_vale/RedHat/UserReplacedValues.yml rename to docs/_vale/RedHat/UserReplacedValues.yml diff --git a/doc/_vale/RedHat/collate-output.tmpl b/docs/_vale/RedHat/collate-output.tmpl similarity index 100% rename from doc/_vale/RedHat/collate-output.tmpl rename to docs/_vale/RedHat/collate-output.tmpl diff --git a/doc/_vale/RedHat/meta.json b/docs/_vale/RedHat/meta.json similarity index 100% rename from doc/_vale/RedHat/meta.json rename to docs/_vale/RedHat/meta.json diff --git a/doc/_vale/alex/Ablist.yml b/docs/_vale/alex/Ablist.yml similarity index 100% rename from doc/_vale/alex/Ablist.yml rename to docs/_vale/alex/Ablist.yml diff --git a/doc/_vale/alex/Condescending.yml b/docs/_vale/alex/Condescending.yml similarity index 100% rename from doc/_vale/alex/Condescending.yml rename to docs/_vale/alex/Condescending.yml diff --git a/doc/_vale/alex/Gendered.yml b/docs/_vale/alex/Gendered.yml similarity index 100% rename from doc/_vale/alex/Gendered.yml rename to docs/_vale/alex/Gendered.yml diff --git a/doc/_vale/alex/LGBTQ.yml b/docs/_vale/alex/LGBTQ.yml similarity index 100% rename from doc/_vale/alex/LGBTQ.yml rename to docs/_vale/alex/LGBTQ.yml diff --git a/doc/_vale/alex/Press.yml b/docs/_vale/alex/Press.yml similarity index 100% rename from doc/_vale/alex/Press.yml rename to docs/_vale/alex/Press.yml diff --git a/doc/_vale/alex/ProfanityLikely.yml b/docs/_vale/alex/ProfanityLikely.yml similarity index 100% rename from doc/_vale/alex/ProfanityLikely.yml rename to docs/_vale/alex/ProfanityLikely.yml diff --git a/doc/_vale/alex/ProfanityMaybe.yml b/docs/_vale/alex/ProfanityMaybe.yml similarity index 100% rename from doc/_vale/alex/ProfanityMaybe.yml rename to docs/_vale/alex/ProfanityMaybe.yml diff --git a/doc/_vale/alex/ProfanityUnlikely.yml b/docs/_vale/alex/ProfanityUnlikely.yml similarity index 100% rename from doc/_vale/alex/ProfanityUnlikely.yml rename to docs/_vale/alex/ProfanityUnlikely.yml diff --git a/doc/_vale/alex/README.md b/docs/_vale/alex/README.md similarity index 100% rename from doc/_vale/alex/README.md rename to docs/_vale/alex/README.md diff --git a/doc/_vale/alex/Race.yml b/docs/_vale/alex/Race.yml similarity index 100% rename from doc/_vale/alex/Race.yml rename to docs/_vale/alex/Race.yml diff --git a/doc/_vale/alex/Suicide.yml b/docs/_vale/alex/Suicide.yml similarity index 100% rename from doc/_vale/alex/Suicide.yml rename to docs/_vale/alex/Suicide.yml diff --git a/doc/_vale/alex/meta.json b/docs/_vale/alex/meta.json similarity index 100% rename from doc/_vale/alex/meta.json rename to docs/_vale/alex/meta.json diff --git a/doc/_vale/config/vocabularies/EPNix/accept.txt b/docs/_vale/config/vocabularies/EPNix/accept.txt similarity index 100% rename from doc/_vale/config/vocabularies/EPNix/accept.txt rename to docs/_vale/config/vocabularies/EPNix/accept.txt diff --git a/doc/_vale/config/vocabularies/EPNix/reject.txt b/docs/_vale/config/vocabularies/EPNix/reject.txt similarity index 100% rename from doc/_vale/config/vocabularies/EPNix/reject.txt rename to docs/_vale/config/vocabularies/EPNix/reject.txt diff --git a/doc/_vale/proselint/Airlinese.yml b/docs/_vale/proselint/Airlinese.yml similarity index 100% rename from doc/_vale/proselint/Airlinese.yml rename to docs/_vale/proselint/Airlinese.yml diff --git a/doc/_vale/proselint/AnimalLabels.yml b/docs/_vale/proselint/AnimalLabels.yml similarity index 100% rename from doc/_vale/proselint/AnimalLabels.yml rename to docs/_vale/proselint/AnimalLabels.yml diff --git a/doc/_vale/proselint/Annotations.yml b/docs/_vale/proselint/Annotations.yml similarity index 100% rename from doc/_vale/proselint/Annotations.yml rename to docs/_vale/proselint/Annotations.yml diff --git a/doc/_vale/proselint/Apologizing.yml b/docs/_vale/proselint/Apologizing.yml similarity index 100% rename from doc/_vale/proselint/Apologizing.yml rename to docs/_vale/proselint/Apologizing.yml diff --git a/doc/_vale/proselint/Archaisms.yml b/docs/_vale/proselint/Archaisms.yml similarity index 100% rename from doc/_vale/proselint/Archaisms.yml rename to docs/_vale/proselint/Archaisms.yml diff --git a/doc/_vale/proselint/But.yml b/docs/_vale/proselint/But.yml similarity index 100% rename from doc/_vale/proselint/But.yml rename to docs/_vale/proselint/But.yml diff --git a/doc/_vale/proselint/Cliches.yml b/docs/_vale/proselint/Cliches.yml similarity index 100% rename from doc/_vale/proselint/Cliches.yml rename to docs/_vale/proselint/Cliches.yml diff --git a/doc/_vale/proselint/CorporateSpeak.yml b/docs/_vale/proselint/CorporateSpeak.yml similarity index 100% rename from doc/_vale/proselint/CorporateSpeak.yml rename to docs/_vale/proselint/CorporateSpeak.yml diff --git a/doc/_vale/proselint/Currency.yml b/docs/_vale/proselint/Currency.yml similarity index 100% rename from doc/_vale/proselint/Currency.yml rename to docs/_vale/proselint/Currency.yml diff --git a/doc/_vale/proselint/Cursing.yml b/docs/_vale/proselint/Cursing.yml similarity index 100% rename from doc/_vale/proselint/Cursing.yml rename to docs/_vale/proselint/Cursing.yml diff --git a/doc/_vale/proselint/DateCase.yml b/docs/_vale/proselint/DateCase.yml similarity index 100% rename from doc/_vale/proselint/DateCase.yml rename to docs/_vale/proselint/DateCase.yml diff --git a/doc/_vale/proselint/DateMidnight.yml b/docs/_vale/proselint/DateMidnight.yml similarity index 100% rename from doc/_vale/proselint/DateMidnight.yml rename to docs/_vale/proselint/DateMidnight.yml diff --git a/doc/_vale/proselint/DateRedundancy.yml b/docs/_vale/proselint/DateRedundancy.yml similarity index 100% rename from doc/_vale/proselint/DateRedundancy.yml rename to docs/_vale/proselint/DateRedundancy.yml diff --git a/doc/_vale/proselint/DateSpacing.yml b/docs/_vale/proselint/DateSpacing.yml similarity index 100% rename from doc/_vale/proselint/DateSpacing.yml rename to docs/_vale/proselint/DateSpacing.yml diff --git a/doc/_vale/proselint/DenizenLabels.yml b/docs/_vale/proselint/DenizenLabels.yml similarity index 100% rename from doc/_vale/proselint/DenizenLabels.yml rename to docs/_vale/proselint/DenizenLabels.yml diff --git a/doc/_vale/proselint/Diacritical.yml b/docs/_vale/proselint/Diacritical.yml similarity index 100% rename from doc/_vale/proselint/Diacritical.yml rename to docs/_vale/proselint/Diacritical.yml diff --git a/doc/_vale/proselint/GenderBias.yml b/docs/_vale/proselint/GenderBias.yml similarity index 100% rename from doc/_vale/proselint/GenderBias.yml rename to docs/_vale/proselint/GenderBias.yml diff --git a/doc/_vale/proselint/GroupTerms.yml b/docs/_vale/proselint/GroupTerms.yml similarity index 100% rename from doc/_vale/proselint/GroupTerms.yml rename to docs/_vale/proselint/GroupTerms.yml diff --git a/doc/_vale/proselint/Hedging.yml b/docs/_vale/proselint/Hedging.yml similarity index 100% rename from doc/_vale/proselint/Hedging.yml rename to docs/_vale/proselint/Hedging.yml diff --git a/doc/_vale/proselint/Hyperbole.yml b/docs/_vale/proselint/Hyperbole.yml similarity index 100% rename from doc/_vale/proselint/Hyperbole.yml rename to docs/_vale/proselint/Hyperbole.yml diff --git a/doc/_vale/proselint/Jargon.yml b/docs/_vale/proselint/Jargon.yml similarity index 100% rename from doc/_vale/proselint/Jargon.yml rename to docs/_vale/proselint/Jargon.yml diff --git a/doc/_vale/proselint/LGBTOffensive.yml b/docs/_vale/proselint/LGBTOffensive.yml similarity index 100% rename from doc/_vale/proselint/LGBTOffensive.yml rename to docs/_vale/proselint/LGBTOffensive.yml diff --git a/doc/_vale/proselint/LGBTTerms.yml b/docs/_vale/proselint/LGBTTerms.yml similarity index 100% rename from doc/_vale/proselint/LGBTTerms.yml rename to docs/_vale/proselint/LGBTTerms.yml diff --git a/doc/_vale/proselint/Malapropisms.yml b/docs/_vale/proselint/Malapropisms.yml similarity index 100% rename from doc/_vale/proselint/Malapropisms.yml rename to docs/_vale/proselint/Malapropisms.yml diff --git a/doc/_vale/proselint/Needless.yml b/docs/_vale/proselint/Needless.yml similarity index 100% rename from doc/_vale/proselint/Needless.yml rename to docs/_vale/proselint/Needless.yml diff --git a/doc/_vale/proselint/Nonwords.yml b/docs/_vale/proselint/Nonwords.yml similarity index 100% rename from doc/_vale/proselint/Nonwords.yml rename to docs/_vale/proselint/Nonwords.yml diff --git a/doc/_vale/proselint/Oxymorons.yml b/docs/_vale/proselint/Oxymorons.yml similarity index 100% rename from doc/_vale/proselint/Oxymorons.yml rename to docs/_vale/proselint/Oxymorons.yml diff --git a/doc/_vale/proselint/P-Value.yml b/docs/_vale/proselint/P-Value.yml similarity index 100% rename from doc/_vale/proselint/P-Value.yml rename to docs/_vale/proselint/P-Value.yml diff --git a/doc/_vale/proselint/RASSyndrome.yml b/docs/_vale/proselint/RASSyndrome.yml similarity index 100% rename from doc/_vale/proselint/RASSyndrome.yml rename to docs/_vale/proselint/RASSyndrome.yml diff --git a/doc/_vale/proselint/README.md b/docs/_vale/proselint/README.md similarity index 100% rename from doc/_vale/proselint/README.md rename to docs/_vale/proselint/README.md diff --git a/doc/_vale/proselint/Skunked.yml b/docs/_vale/proselint/Skunked.yml similarity index 100% rename from doc/_vale/proselint/Skunked.yml rename to docs/_vale/proselint/Skunked.yml diff --git a/doc/_vale/proselint/Spelling.yml b/docs/_vale/proselint/Spelling.yml similarity index 100% rename from doc/_vale/proselint/Spelling.yml rename to docs/_vale/proselint/Spelling.yml diff --git a/doc/_vale/proselint/Typography.yml b/docs/_vale/proselint/Typography.yml similarity index 100% rename from doc/_vale/proselint/Typography.yml rename to docs/_vale/proselint/Typography.yml diff --git a/doc/_vale/proselint/Uncomparables.yml b/docs/_vale/proselint/Uncomparables.yml similarity index 100% rename from doc/_vale/proselint/Uncomparables.yml rename to docs/_vale/proselint/Uncomparables.yml diff --git a/doc/_vale/proselint/Very.yml b/docs/_vale/proselint/Very.yml similarity index 100% rename from doc/_vale/proselint/Very.yml rename to docs/_vale/proselint/Very.yml diff --git a/doc/_vale/proselint/meta.json b/docs/_vale/proselint/meta.json similarity index 100% rename from doc/_vale/proselint/meta.json rename to docs/_vale/proselint/meta.json diff --git a/doc/_vale/write-good/Cliches.yml b/docs/_vale/write-good/Cliches.yml similarity index 100% rename from doc/_vale/write-good/Cliches.yml rename to docs/_vale/write-good/Cliches.yml diff --git a/doc/_vale/write-good/E-Prime.yml b/docs/_vale/write-good/E-Prime.yml similarity index 100% rename from doc/_vale/write-good/E-Prime.yml rename to docs/_vale/write-good/E-Prime.yml diff --git a/doc/_vale/write-good/Illusions.yml b/docs/_vale/write-good/Illusions.yml similarity index 100% rename from doc/_vale/write-good/Illusions.yml rename to docs/_vale/write-good/Illusions.yml diff --git a/doc/_vale/write-good/Passive.yml b/docs/_vale/write-good/Passive.yml similarity index 100% rename from doc/_vale/write-good/Passive.yml rename to docs/_vale/write-good/Passive.yml diff --git a/doc/_vale/write-good/README.md b/docs/_vale/write-good/README.md similarity index 100% rename from doc/_vale/write-good/README.md rename to docs/_vale/write-good/README.md diff --git a/doc/_vale/write-good/So.yml b/docs/_vale/write-good/So.yml similarity index 100% rename from doc/_vale/write-good/So.yml rename to docs/_vale/write-good/So.yml diff --git a/doc/_vale/write-good/ThereIs.yml b/docs/_vale/write-good/ThereIs.yml similarity index 100% rename from doc/_vale/write-good/ThereIs.yml rename to docs/_vale/write-good/ThereIs.yml diff --git a/doc/_vale/write-good/TooWordy.yml b/docs/_vale/write-good/TooWordy.yml similarity index 100% rename from doc/_vale/write-good/TooWordy.yml rename to docs/_vale/write-good/TooWordy.yml diff --git a/doc/_vale/write-good/Weasel.yml b/docs/_vale/write-good/Weasel.yml similarity index 100% rename from doc/_vale/write-good/Weasel.yml rename to docs/_vale/write-good/Weasel.yml diff --git a/doc/_vale/write-good/meta.json b/docs/_vale/write-good/meta.json similarity index 100% rename from doc/_vale/write-good/meta.json rename to docs/_vale/write-good/meta.json diff --git a/docs/conf.py b/docs/conf.py index f22ab5ea..a56cfb77 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -30,7 +30,12 @@ ] templates_path = ["_templates"] -exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] +exclude_patterns = [ + "_build", + "Thumbs.db", + ".DS_Store", + "_vale", +] # numfig = True From cad8f810b24e159bad78bd2d880ab878e21d9624 Mon Sep 17 00:00:00 2001 From: Minijackson Date: Thu, 25 Jul 2024 10:17:16 +0200 Subject: [PATCH 030/111] ioc/devshell: use new docs for manpages and 'edoc' --- ioc/modules/devshell.nix | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ioc/modules/devshell.nix b/ioc/modules/devshell.nix index 3a8716da..a8d4962c 100644 --- a/ioc/modules/devshell.nix +++ b/ioc/modules/devshell.nix @@ -212,7 +212,7 @@ in { The value of each variable can be either a string or a list of strings. The latter is concatenated, interspersed with colon characters. - If null is given, the environment variable is explicitely unset, + If null is given, the environment variable is explicitly unset, preventing said environment variable to "leak" from the host environment to the development shell. ''; @@ -320,7 +320,7 @@ in { edoc = { text = '' - ${pkgs.python3}/bin/python -m http.server --bind 127.0.0.1 --directory "${pkgs.epnix.book}" + ${pkgs.python3}/bin/python -m http.server --bind 127.0.0.1 --directory "${pkgs.epnix.docs}/share/doc/epnix/html/" ''; category = "epnix commands"; description = "Show the EPNix documentation book for the distribution"; @@ -572,7 +572,7 @@ in { (map (cmd: cmd.package) cfg.packages) ++ scriptPackages ++ config.epnix.outputs.build.depsBuildBuild - ++ [pkgs.epnix.manpages]; + ++ [pkgs.epnix.docs]; inherit (config.epnix.outputs.build) local_config_site local_release; From bf53aa9a7d0dc7d0c3d160c62605df8a8ee5f284 Mon Sep 17 00:00:00 2001 From: Minijackson Date: Thu, 25 Jul 2024 10:33:18 +0200 Subject: [PATCH 031/111] docs: add release notes for 24.05 --- docs/index.rst | 8 ++++++++ docs/release-notes/2405.rst | 5 +++++ 2 files changed, 13 insertions(+) create mode 100644 docs/release-notes/2405.rst diff --git a/docs/index.rst b/docs/index.rst index 5ee61f6c..dd41b3a3 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -99,5 +99,13 @@ This documentation follows the `Diátaxis`_ documentation framework. nixos-services/user-guides/index nixos-services/options +.. toctree:: + :caption: Release notes + :hidden: + :titlesonly: + :glob: + :reversed: + + release-notes/* .. TODO: link an index to Nix options and packages diff --git a/docs/release-notes/2405.rst b/docs/release-notes/2405.rst new file mode 100644 index 00000000..2ced4364 --- /dev/null +++ b/docs/release-notes/2405.rst @@ -0,0 +1,5 @@ +24.05 Release notes +=================== + +.. role:: nix(code) + :language: nix From accfa28a541c71c44f5d6e1a6bb686a5848325b3 Mon Sep 17 00:00:00 2001 From: Minijackson Date: Thu, 25 Jul 2024 10:33:41 +0200 Subject: [PATCH 032/111] ioc/documentation: remove deprecated mdbook & manpages outputs --- docs/release-notes/2405.rst | 6 ++++++ ioc/modules/documentation.nix | 16 ---------------- ioc/modules/module-list.nix | 1 - 3 files changed, 6 insertions(+), 17 deletions(-) delete mode 100644 ioc/modules/documentation.nix diff --git a/docs/release-notes/2405.rst b/docs/release-notes/2405.rst index 2ced4364..6c8cc205 100644 --- a/docs/release-notes/2405.rst +++ b/docs/release-notes/2405.rst @@ -3,3 +3,9 @@ .. role:: nix(code) :language: nix + +Breaking changes +---------------- + +- The :nix:`config.epnix.outputs.mdbook` and :nix:`config.epnix.outputs.manpages` options + from the IOC module options, previously deprecated, are now removed. diff --git a/ioc/modules/documentation.nix b/ioc/modules/documentation.nix deleted file mode 100644 index bf45b0ca..00000000 --- a/ioc/modules/documentation.nix +++ /dev/null @@ -1,16 +0,0 @@ -{ - lib, - pkgs, - ... -}: { - config.epnix.outputs = { - mdbook = - lib.warn - "the mdbook output is deprecated, please use `pkgs.epnix.book` instead" - pkgs.epnix.book; - manpage = - lib.warn - "the manpage output is deprecated, please use `pkgs.epnix.manpages` instead" - pkgs.epnix.manpages; - }; -} diff --git a/ioc/modules/module-list.nix b/ioc/modules/module-list.nix index 0de3b556..a27f5f90 100644 --- a/ioc/modules/module-list.nix +++ b/ioc/modules/module-list.nix @@ -5,7 +5,6 @@ ./checks.nix ./common.nix ./devshell.nix - ./documentation.nix ./meta.nix ./nixos-integration.nix ./outputs.nix From c743e16a9eff56b88903804c12a9813f475baf9b Mon Sep 17 00:00:00 2001 From: Minijackson Date: Thu, 25 Jul 2024 10:51:36 +0200 Subject: [PATCH 033/111] github/book-gh-pages: build new Sphinx docs --- .github/workflows/book-gh-pages.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/book-gh-pages.yml b/.github/workflows/book-gh-pages.yml index 96b3b6c3..c85315be 100644 --- a/.github/workflows/book-gh-pages.yml +++ b/.github/workflows/book-gh-pages.yml @@ -27,8 +27,8 @@ jobs: - uses: cachix/install-nix-action@ba0dd844c9180cbf77aa72a116d6fbc515d0e87b # v27 - name: "Build documentation book" run: | - nix build '.#book' --print-build-logs - cp -Lr --no-preserve=mode,ownership ./result/ ./book + nix build '.#docs' --print-build-logs + cp -Lr --no-preserve=mode,ownership ./result/share/doc/epnix/html ./book - name: Setup Pages uses: actions/configure-pages@983d7736d9b0ae728b81ab479565c72886d7745b # v5.0.0 - name: Upload artifact From 6fb58655d08bb9c60841924d34e686fe4fa56cc6 Mon Sep 17 00:00:00 2001 From: Minijackson Date: Thu, 25 Jul 2024 13:08:39 +0200 Subject: [PATCH 034/111] gitlab-ci: build new Sphinx docs and manpages --- .gitlab-ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 43c0ff54..8c6daaf2 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -31,8 +31,8 @@ formatting: manpages: stage: deploy script: - - nix build $NIX_BUILD_FLAGS '.#manpages' - - cp -Lr ./result manpages + - nix build $NIX_BUILD_FLAGS '.#docs' + - cp -Lr ./result/share/man manpages artifacts: name: "manpages-$CI_COMMIT_REF_SLUG" paths: @@ -41,8 +41,8 @@ manpages: pages: stage: deploy script: - - nix build $NIX_BUILD_FLAGS '.#book' - - cp -Lr ./result public + - nix build $NIX_BUILD_FLAGS '.#docs' + - cp -Lr ./result/share/doc/epnix/html public artifacts: name: "book" paths: From 63bdfa30ee54e63177eff2310e2dd41421088cc8 Mon Sep 17 00:00:00 2001 From: Minijackson Date: Thu, 25 Jul 2024 10:34:31 +0200 Subject: [PATCH 035/111] doc: remove old Quarto documentation --- doc/.gitignore | 6 - doc/_quarto.yml | 97 ----- doc/index.md | 68 --- doc/ioc/developer-guides.md | 7 - doc/ioc/developer-guides/glossary.md | 5 - doc/ioc/developer-guides/guidelines.md | 5 - doc/ioc/developer-guides/packaging-modules.md | 5 - doc/ioc/developer-guides/packaging.md | 5 - doc/ioc/developer-tutorials.md | 7 - doc/ioc/explanations.md | 7 - doc/ioc/faq.md | 49 --- doc/ioc/guides.md | 7 - doc/ioc/guides/developing-modules.md | 74 ---- doc/ioc/guides/flake-registry.md | 35 -- doc/ioc/guides/override-package.md | 5 - doc/ioc/guides/pinning.md | 5 - doc/ioc/guides/private-repo-setup.md | 119 ----- doc/ioc/guides/testing.md | 5 - .../testing/packaging-python-scripts.md | 188 -------- doc/ioc/guides/testing/unit-tests.md | 11 - doc/ioc/introduction.md | 47 -- doc/ioc/references.md | 7 - doc/ioc/tutorials.md | 7 - doc/ioc/tutorials/adding-options.md | 5 - doc/ioc/tutorials/creating-a-mock-server.md | 5 - doc/ioc/tutorials/day-to-day-dev.md | 5 - doc/ioc/tutorials/integration-tests.md | 121 ------ doc/ioc/tutorials/porting.md | 5 - doc/ioc/tutorials/pre-requisites.md | 76 ---- doc/ioc/tutorials/streamdevice.md | 294 ------------- doc/logo.svg | 411 ------------------ doc/nixos/guides/_pre-requisites.md | 41 -- doc/nixos/guides/ca-gateway.md | 195 --------- doc/nixos/guides/phoebus-alarm.md | 214 --------- doc/nixos/guides/phoebus-save-and-restore.md | 50 --- doc/nixos/introduction.md | 5 - doc/nixos/tutorials/archiver-appliance.md | 359 --------------- doc/pkgs/introduction.md | 5 - pkgs/book/default.nix | 109 ----- pkgs/default.nix | 2 - pkgs/manpages/default.nix | 117 ----- 41 files changed, 2790 deletions(-) delete mode 100644 doc/.gitignore delete mode 100644 doc/_quarto.yml delete mode 100644 doc/index.md delete mode 100644 doc/ioc/developer-guides.md delete mode 100644 doc/ioc/developer-guides/glossary.md delete mode 100644 doc/ioc/developer-guides/guidelines.md delete mode 100644 doc/ioc/developer-guides/packaging-modules.md delete mode 100644 doc/ioc/developer-guides/packaging.md delete mode 100644 doc/ioc/developer-tutorials.md delete mode 100644 doc/ioc/explanations.md delete mode 100644 doc/ioc/faq.md delete mode 100644 doc/ioc/guides.md delete mode 100644 doc/ioc/guides/developing-modules.md delete mode 100644 doc/ioc/guides/flake-registry.md delete mode 100644 doc/ioc/guides/override-package.md delete mode 100644 doc/ioc/guides/pinning.md delete mode 100644 doc/ioc/guides/private-repo-setup.md delete mode 100644 doc/ioc/guides/testing.md delete mode 100644 doc/ioc/guides/testing/packaging-python-scripts.md delete mode 100644 doc/ioc/guides/testing/unit-tests.md delete mode 100644 doc/ioc/introduction.md delete mode 100644 doc/ioc/references.md delete mode 100644 doc/ioc/tutorials.md delete mode 100644 doc/ioc/tutorials/adding-options.md delete mode 100644 doc/ioc/tutorials/creating-a-mock-server.md delete mode 100644 doc/ioc/tutorials/day-to-day-dev.md delete mode 100644 doc/ioc/tutorials/integration-tests.md delete mode 100644 doc/ioc/tutorials/porting.md delete mode 100644 doc/ioc/tutorials/pre-requisites.md delete mode 100644 doc/ioc/tutorials/streamdevice.md delete mode 100644 doc/logo.svg delete mode 100644 doc/nixos/guides/_pre-requisites.md delete mode 100644 doc/nixos/guides/ca-gateway.md delete mode 100644 doc/nixos/guides/phoebus-alarm.md delete mode 100644 doc/nixos/guides/phoebus-save-and-restore.md delete mode 100644 doc/nixos/introduction.md delete mode 100644 doc/nixos/tutorials/archiver-appliance.md delete mode 100644 doc/pkgs/introduction.md delete mode 100644 pkgs/book/default.nix delete mode 100644 pkgs/manpages/default.nix diff --git a/doc/.gitignore b/doc/.gitignore deleted file mode 100644 index 081b57cd..00000000 --- a/doc/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -/src/options.md -/src/packages.md -book - -/.quarto/ -/_site diff --git a/doc/_quarto.yml b/doc/_quarto.yml deleted file mode 100644 index ff754c8f..00000000 --- a/doc/_quarto.yml +++ /dev/null @@ -1,97 +0,0 @@ -project: - type: website - -website: - title: "EPNix documentation" - description: "Build, package EPICS IOCs and more using the Nix package manager" - favicon: ./logo.svg - repo-url: "https://github.com/epics-extensions/EPNix" - repo-actions: [issue] - page-navigation: true - reader-mode: true - navbar: - search: true - logo: ./logo.svg - left: - - text: "EPICS IOCs" - file: ./ioc/introduction.md - - text: "Packages" - file: ./pkgs/introduction.md - - text: "NixOS" - file: ./nixos/introduction.md - sidebar: - - title: EPICS IOCs - contents: - - text: Introduction - file: ./ioc/introduction.md - - section: User Tutorials - file: ./ioc/tutorials.md - contents: - - ./ioc/tutorials/pre-requisites.md - - ./ioc/tutorials/streamdevice.md - - ./ioc/tutorials/porting.md - - ./ioc/tutorials/day-to-day-dev.md - - ./ioc/tutorials/integration-tests.md - - ./ioc/tutorials/creating-a-mock-server.md - - ./ioc/tutorials/adding-options.md - - file: ./ioc/guides.md - contents: - - ./ioc/guides/private-repo-setup.md - - ./ioc/guides/flake-registry.md - - ./ioc/guides/developing-modules.md - - ./ioc/guides/pinning.md - - ./ioc/guides/override-package.md - - section: Testing - file: ./ioc/guides/testing.md - contents: - - ./ioc/guides/testing/packaging-python-scripts.md - - ./ioc/guides/testing/unit-tests.md - - file: ./ioc/explanations.md - - file: ./ioc/developer-tutorials.md - - file: ./ioc/developer-guides.md - contents: - - ./ioc/developer-guides/packaging-modules.md - - ./ioc/developer-guides/guidelines.md - - ./ioc/developer-guides/packaging.md - - ./ioc/developer-guides/glossary.md - - file: ./ioc/references.md - contents: - - ./ioc/references/options.md - - ./ioc/references/packages.md - - ./ioc/faq.md - - title: Packages - contents: - - text: Introduction - file: ./pkgs/introduction.md - - section: References - contents: - - ./pkgs/packages.md - - title: NixOS - contents: - - title: NixOS - file: ./nixos/introduction.md - - section: Tutorials - contents: - - ./nixos/tutorials/archiver-appliance.md - - section: User Guides - contents: - - ./nixos/guides/ca-gateway.md - - ./nixos/guides/phoebus-alarm.md - - ./nixos/guides/phoebus-save-and-restore.md - - section: Explanations - - section: References - contents: - - ./nixos/options.md - -format: - html: - theme: - light: simplex - dark: darkly - highlight-style: gruvbox - number-sections: false - reference-location: margin - citation-location: margin - code-copy: true - toc: true - shift-heading-level-by: 1 diff --git a/doc/index.md b/doc/index.md deleted file mode 100644 index d67fb159..00000000 --- a/doc/index.md +++ /dev/null @@ -1,68 +0,0 @@ ---- -title: EPNix documentation ---- - -![](./logo.svg){width=70% fig-align=center} - -# Introduction - -EPNix (pronunciation: like you are high on mushrooms) packages EPICS-related software using the [Nix] package manager. - -It's made of three parts: - -- the EPICS IOC framework -- other EPICS-related packages -- NixOS modules - -The EPICS IOC framework lets you package, deploy, and test EPICS IOCs using the Nix package manager, which provides several benefits. -For more information, see the [EPICS IOCs introduction]. - -EPNix also packages other EPICS-related tools, like procServ, Phoebus, etc. -You can build them using Nix, and in the future download them pre-compiled, while having a strong guarantee that they will work as-is. -For a list of all supported EPICS-related packages, see the [Packages list]. - -EPNix also provides NixOS modules, which are instructions on how to configure various EPICS-related services on NixOS machines (for example the Phoebus alarm server). -EPNix strives to have integration tests for each of those module. -For more information, see the [NixOS modules introduction]. - - [Nix]: https://nixos.org/guides/how-nix-works.html - [EPICS IOCs introduction]: ./ioc/introduction.md - [Packages list]: ./pkgs/packages.md - [NixOS modules introduction]: ./nixos/introduction.md - -# Packaging policy - -As EPNix provides a package repository, packaging for example `epics-base`, `asyn`, `StreamDevice`, `procServ`, `phoebus`, etc., it needs to have a packaging policy. - -In its package repository, EPNix officially supports the latest upstream version. - -However, since EPNix is a git repository, you will be able, through Nix, to use a fixed version of EPNix, without being forced to upgrade your dependencies. - -```{=html} - -``` - -## The epics-base package - -The epics-base package has no significant modification compared to the upstream version at [Launchpad]. -One goal of EPNix is to keep those modifications to a minimum, and upstream what's possible. - -# Release branches - -EPNix has a `master` branch, -which is considered unstable, -meaning breaking changes might happen without notice. - -EPNix also has release branches, -such as `nixos-23.11`, -tied to the nixpkgs release branches, -where breaking changes are forbidden. - -Backporting changes to older release branches is done on a "best-effort" basis. - ------------------------------------------------------------------------- - -This documentation follows the [Diátaxis] documentation framework. - - [Launchpad]: https://git.launchpad.net/epics-base - [Diátaxis]: https://diataxis.fr/ diff --git a/doc/ioc/developer-guides.md b/doc/ioc/developer-guides.md deleted file mode 100644 index 1bcdb330..00000000 --- a/doc/ioc/developer-guides.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: Developer guides ---- - -This section of the documentation book contains how-to guides[^1] for contributors to the EPNix project, related to building and deploying EPICS IOCs. - -[^1]: diff --git a/doc/ioc/developer-guides/glossary.md b/doc/ioc/developer-guides/glossary.md deleted file mode 100644 index f46edec5..00000000 --- a/doc/ioc/developer-guides/glossary.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Glossary ---- - -TODO diff --git a/doc/ioc/developer-guides/guidelines.md b/doc/ioc/developer-guides/guidelines.md deleted file mode 100644 index aa6e3dce..00000000 --- a/doc/ioc/developer-guides/guidelines.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Guidelines ---- - -TODO diff --git a/doc/ioc/developer-guides/packaging-modules.md b/doc/ioc/developer-guides/packaging-modules.md deleted file mode 100644 index ddecb6f1..00000000 --- a/doc/ioc/developer-guides/packaging-modules.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Packaging modules ---- - -TODO diff --git a/doc/ioc/developer-guides/packaging.md b/doc/ioc/developer-guides/packaging.md deleted file mode 100644 index b4f88a7a..00000000 --- a/doc/ioc/developer-guides/packaging.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Packaging new software ---- - -TODO diff --git a/doc/ioc/developer-tutorials.md b/doc/ioc/developer-tutorials.md deleted file mode 100644 index 13be9899..00000000 --- a/doc/ioc/developer-tutorials.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: Developer Tutorials ---- - -This section of the documentation book contains tutorials[^1] for contributors to the EPNix project, related to building and deploying EPICS IOCs. - -[^1]: diff --git a/doc/ioc/explanations.md b/doc/ioc/explanations.md deleted file mode 100644 index 9642641c..00000000 --- a/doc/ioc/explanations.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: Explanations ---- - -This section of the documentation book contains explanations[^1] of various concepts and patterns related to building and deploying EPICS IOCs with EPNix. - -[^1]: diff --git a/doc/ioc/faq.md b/doc/ioc/faq.md deleted file mode 100644 index 7d6b1b43..00000000 --- a/doc/ioc/faq.md +++ /dev/null @@ -1,49 +0,0 @@ ---- -title: Frequently Asked Questions ---- - -# I am getting weird Git errors about an unknown `-C` option - -You may be using a system with an old version of Git. -You may install a recent version of Git for your user by running `nix-env -iA nixpkgs.git`{.bash}. - -# A file I created isn't found when I run `nix build`{.bash} - -If your top is a Git repository, you must `git add`{.bash} those files to make them recognized by Nix. - -# An App can't find a build product from another App - -EPNix enables parallel builds by default. -These means that if App dependencies aren't specified, these Apps will compile in no particular order. -Use `_DEPEND_DIRS += `{.makefile} in your top-level `Makefile`. - -# How do I version a whole EPNix top? - -Meaning, not versioning an App separate from the top. -This might be justified if you don't intend to share an App in any other top. - -1. First, create a top and an App, as in the [StreamDevice tutorial]. - -2. Make sure to add an exception for the `exampleApp` folder at the end of the top's `.gitignore` file: - -``` ini -... -# Applications and Support modules should be an EPNix dependency in flake.nix -*App -*Sup -# You can add exceptions like this: -# --- -#!myCustomLocalApp -!exampleApp -``` - -3. Then, version both the top and the App: - -``` bash -git init -git add -N . -``` - -4. Finally, in your `flake.nix`, you can remove any input and value in `epnix.applications.apps` that refers to this directory. - - [StreamDevice tutorial]: ./tutorials/streamdevice.md diff --git a/doc/ioc/guides.md b/doc/ioc/guides.md deleted file mode 100644 index c023ea30..00000000 --- a/doc/ioc/guides.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: User guides ---- - -This section of the documentation book contains how-to guides[^1] for users of the EPNix project wanting to build EPICS IOCs. - -[^1]: diff --git a/doc/ioc/guides/developing-modules.md b/doc/ioc/guides/developing-modules.md deleted file mode 100644 index 79beb475..00000000 --- a/doc/ioc/guides/developing-modules.md +++ /dev/null @@ -1,74 +0,0 @@ ---- -title: Developing support modules ---- - -```{=html} - -``` -It can happen that one needs to hack on an EPICS support module, while also developing an App. -This might be to develop and test the support module, or to patch and test the support module, etc. - -This is where Nix's reproducibility guarantees might seem to be in the way: dependencies are taken from the `/nix/store` instead of your local repository. -You can add it as a flake input instead, but that requires to run `nix flake lock --update-input mySupport`{.bash} on each modification, etc. - -To bypass these constraints, there are several mechanisms that lets you to temporarily weaken these constraints for development purposes. - -# Packaging a starter module - -First, clone the EPNix repository, and package your support module. -You can look at the [Packaging modules] guide, this doesn't even have to compile yet, but you need to specify the dependencies of your support module. - - [Packaging modules]: ../developer-guides/packaging-modules.md - -# Hacking on your module - -From the directory containing the source code of your support module, run: - -``` bash -nix develop "/path/to/local/epnix#support/mySupport" -# Then, inside the development shell -dontUnpack=true -genericBuild -``` - -This will put the result of your compilation under `outputs/out`. -If you make modifications to your support module, run `buildPhase`{.bash} from the same development shell to recompile it. - -# Using it on your EPICS top - -Before trying to compile your top, make sure that your support module is included in the `support.modules` option of your EPNix top: - -``` nix -support.modules = with pkgs.epnix.support; [ mySupport ]; -``` - -Now that the support module is compiled and installed in a local directory, you can ask Nix to use it as is. -This can be done by running this command from your EPICS top directory: - -``` bash -nix develop \ - --override-input epnix '/path/to/local/epnix' \ - --redirect '/path/to/local/epnix#support/mySupport' '/path/to/mySupport/outputs/out' -# Then, normal hacking on an EPICS top... -``` - -The `--override-input` option instructs Nix to use your local EPNix fork instead of the one hosted on GitHub. -Use this option to override flake inputs. - -The `--redirect` option instructs Nix to use your local directory for your support module, instead of a module installed in the `/nix/store`. -Use this option to override individual packages. - ------------------------------------------------------------------------- - -With this setup, you can hack and compile your support module, and the changes will be directly visible to your top. -This enables you to hack on both project at the same time, each on their own development shell. - -One question one may ask: - -> What's the difference between running the complex `nix develop`{.bash} command and just putting `/path/to/mySupport/outputs/out` into `RELEASE.local`? - -One thing that the complex `nix develop`{.bash} command does correctly, is replacing *everything* that would have been `/nix/store/...-mySupport../` into your development shell. -This includes the `RELEASE.local` file, but this may not be the only thing: - -For example, if you're hacking on the `seq` support module, not only will it put the path to your local `seq` module into `RELEASE.local`, but it will also put some `seq` specific programs into your `$PATH`{.bash}, like the `snc`{.bash} utility. -These programs will be those from your local build, not the ones coming from the EPNix repository. diff --git a/doc/ioc/guides/flake-registry.md b/doc/ioc/guides/flake-registry.md deleted file mode 100644 index 23483acd..00000000 --- a/doc/ioc/guides/flake-registry.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -title: Setting up the flake registry ---- - -While developing with EPNix, -it's possible you will end up typing `'github:epics-extensions/epnix'` quite often. - -It happens when you need to create a "top" template, -or when you just want to have `epics-base` in your shell, -and so on. - -This is tedious. - -Nix provides a way of shortening these URLs, -by adding to the [Nix registry][]: - -``` bash -nix registry add epnix 'github:epics-extensions/epnix' -``` - -Now, referring to `epnix` in Nix command-lines will be as if you referred to the full URL. -For example, the develop command to have EPICS based installed outside of a top would be: - -``` bash -nix develop epnix -``` - -If you want to initialize an EPNix top, -you can run: - -``` bash -nix flake new -t epnix my-top -``` - - [Nix registry]: https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-registry.html#description diff --git a/doc/ioc/guides/override-package.md b/doc/ioc/guides/override-package.md deleted file mode 100644 index 4609f0b2..00000000 --- a/doc/ioc/guides/override-package.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Override a support module ---- - -TODO diff --git a/doc/ioc/guides/pinning.md b/doc/ioc/guides/pinning.md deleted file mode 100644 index b2dc7175..00000000 --- a/doc/ioc/guides/pinning.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Pin the version of a Nix dependency ---- - -TODO diff --git a/doc/ioc/guides/private-repo-setup.md b/doc/ioc/guides/private-repo-setup.md deleted file mode 100644 index 685f3f9e..00000000 --- a/doc/ioc/guides/private-repo-setup.md +++ /dev/null @@ -1,119 +0,0 @@ ---- -title: Private repository setup ---- - -To avoid a great deal of confusion, it's best to configure your machine so that it can clone your private repositories unattended. -This means that this command should succeed without asking for user input on the terminal: - -``` bash -git clone 'ssh://git@your.gitlab.com/your/epicsApp.git' -``` - -But, asking for user input graphically is acceptable. - -The reason is that the Nix command-line tool often writes text on the terminal, and does so over the questions asked by programs like SSH or Git. -If SSH or Git asks for a password on the terminal, you probably won't see it, and confusion will follow when the Nix command hangs. - -There's two main ways to configure your machine for this: - -- SSH keys -- GitHub / GitLab tokens - -# SSH keys - -## Configuring the SSH key - -To setup SSH keys to use with your GitHub account, you can follow the [official documentation][github-ssh]. - -To setup SSH keys to use with your GitLab account, you can follow the [official documentation][gitlab-ssh], and particularly look at these sections: - -- See if you have an existing SSH key pair -- Generate an SSH key pair -- Add an SSH key to your GitLab account -- Verify that you can connect - - [github-ssh]: https://docs.github.com/en/authentication/connecting-to-github-with-ssh - [gitlab-ssh]: https://docs.gitlab.com/ee/user/ssh.html - -## Configuring the ssh-agent - -If you have a GNOME installation, chances are you already have an ssh-agent installed and running. - -To check, open a *new* terminal, and look at the value of the `$SSH_AUTH_SOCK`{.bash} variable. - -If it returns nothing, install `gnome-keyring`, then log out and log in again. - -Then, reopen a new terminal, and add your configured SSH key like so: - -``` bash -ssh-add 'path/to/key/id_ed25519' -``` - -Check that logging in to GitLab doesn't ask for user input on the terminal: - -``` bash -ssh -T 'git@your.gitlab.com' -# Welcome to GitLab, @user! -``` - -If it doesn't work, but you have `gnome-keyring-daemon` installed and running, -you can add this line to your `~/.bashrc`: - -``` bash -export SSH_AUTH_SOCK=/run/user/$UID/keyring/ssh -``` - -# GitHub / GitLab tokens - -GitHub and GitLab tokens offer a timed way of authenticating, suitable for either quick and dirty access, or for setting up services or scripts that need access to GitHub / GitLab repositories. -In any case, tokens shouldn't be used for usual development. - -In GitLab, you can create tokens either per-user, per-group, or per-project. - -In GitHub, you can only create personal access tokens, but their usage can be restricted in an organization. - -Creating a GitHub token, or a Gitlab token for your user means that you can give it access to all projects and APIs that you have access to. -This can be useful for your personal applications, or tools like [glab]. - -In GitLab, you can create a token for given group or project so that it offers access to that specific group or project. -These kinds of tokens should be preferred. - - [glab]: https://docs.gitlab.com/ee/integration/glab/ - -## GitHub - -To create a GitHub token, follow the [official documentation][github-token] - - [github-token]: https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token - -## GitLab - -```{=html} - -``` -To create a GitLab token, go to the user/group/project settings, under the "Access Tokens" section. -Give your token a meaningful name, an expiration date, and for a group/project, select the appropriate role. - -If you only want your token to be able to clone repositories, you can just select the `read_repository` scope. -Else refer to GitLab's official documentation by clicking "Learn more." - -After creating the personal access token, you can copy the token's value. -Be careful, as this value won't be accessible after closing the page. - -If you want to clone any repository, the URL will need to be: - -``` bash -https://gitlab-ci-token:${TOKEN}@your.gitlab.com" -``` - -As EPNix uses SSH flake inputs, you can use this command to instruct Git to rewrite GitLab URLs: - -``` bash -git config --global url."https://gitlab-ci-token:${TOKEN}@your.gitlab.com".insteadOf "ssh://git@your.gitlab.com" -``` - -To check that your setup is working, run the following command: - -``` bash -git clone 'ssh://git@your.gitlab.com/your/epicsApp.git' -``` diff --git a/doc/ioc/guides/testing.md b/doc/ioc/guides/testing.md deleted file mode 100644 index dadc5790..00000000 --- a/doc/ioc/guides/testing.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Testing ---- - -TODO diff --git a/doc/ioc/guides/testing/packaging-python-scripts.md b/doc/ioc/guides/testing/packaging-python-scripts.md deleted file mode 100644 index 2bd5d2d1..00000000 --- a/doc/ioc/guides/testing/packaging-python-scripts.md +++ /dev/null @@ -1,188 +0,0 @@ ---- -title: Packaging Python scripts ---- - -```{=html} - -``` -As EPNix uses Nix, you can package Python scripts as helpers for your integration tests, by using the provided [infrastructure] of nixpkgs. -In fact, you can package any program in any language, but this document focuses on Python scripts with [Poetry] for their simplicity and popularity. - - [infrastructure]: https://nixos.org/manual/nixpkgs/stable/#python - [Poetry]: https://python-poetry.org/ - -# Getting started - -We recommend using the Poetry package in your EPNix environment, through Nix, to use the same version as the one building the Python script. - -You can do this by adding this bit in your `flake.nix` file: - -``` nix -epnix.devShell.packages = [ - { package = pkg.poetry; category = "development tools"; } -]; -``` - -Next, you can start your development shell with `nix develop`, go to the directory of your test, and create a new project with the command: - -``` bash -poetry new -``` - -This will create a Python project under the `` directory. -Under it, you will find a `pyproject.toml` where you can specify the dependencies of your script. -For example, you can specify `modbus` to add the Python [modbus package], if you want to test modbus communication. -You can remove the dependency on pytest if won't add unit tests to your Python script. - -To add an entry point to your Python code, you can use the `tool.poetry.scripts` section like so: - -``` toml -[tool.poetry.scripts] -my_python_script = "my_python_script:main" -``` - -This will add an executable named `my_python_script`{.bash} that will run the `main()`{.python} function of the `my_python_script`{.python} module. - -For more information on how to use poetry, please refer to the [Poetry documentation]. - -Before packaging this script using Nix, it's important to generate the lock file, and to remember to re-generate it each time you change the `pyproject.toml` file. - -You can do this with the following command: - -``` bash -poetry lock -``` - -Then, in your [integration test] file, you can package it like this: - -``` nix -{ build, pkgs, ... }: - -let - pythonScript = pkgs.poetry2nix.mkPoetryApplication { - projectDir = ./path/to/my-python-script; - }; -in -pkgs.nixosTest { - name = "myTest"; - - # ... -} -``` - -With this, you can use the `pythonScript` variable as you see fit. - - [modbus package]: https://pypi.org/project/modbus/ - [Poetry documentation]: https://python-poetry.org/docs/basic-usage/ - [integration test]: ../../tutorials/integration-tests.md - -# Example usage: As a one shot test script - -Using a packaged Python script instead of the provided `testScript` has several advantages. -It can use dependencies provided by the community (like `modbus`, `systemd`, etc.), and you can make it run on the running virtual machine. - -Python script: - -``` python -import subprocess - -from modbus.client import * - - -def main(): - c = client(host='HOSTNAME') - modbus_values = c.read(FC=3, ADR=10, LEN=8) - - for i in range(8): - epics_value = subprocess.run( - ["caget", "-t", "MyPV:" + i], - capture_output=True, - ).stdout.strip() - - assert modbus_values[i] == int(epics_value), "Wrong value provided by epics" -``` - -Nix test: - -``` nix -{ build, pkgs, ... }: - -let - pythonScript = pkgs.poetry2nix.mkPoetryApplication { - projectDir = ./path/to/my-python-script; - }; -in -pkgs.nixosTest { - name = "myTest"; - - machine = { - environment.systemPackages = [ pythonScript ]; - - # ... - }; - - testScript = '' - # ... - - my_python_script --my-flag --my-option=3 - - # ... - ''; -} -``` - -# Example usage: As a systemd service - -Using a Python script as a systemd service is useful for mocking devices. -For more information, please see the [Creating a mocking server] guide. - -Python script: - -``` python -import logging -from logging import info - - -def main(): - logging.basicConfig(level=logging.INFO) - - while True: - info("doing things") - - # ... -``` - -Nix test: - -``` nix -{ build, pkgs, ... }: - -let - pythonScript = pkgs.poetry2nix.mkPoetryApplication { - projectDir = ./path/to/my-python-script; - }; -in -pkgs.nixosTest { - name = "myTest"; - - machine = { - systemd.services."my-python-service" = { - wantedBy = [ "multi-user.target" ]; - - serviceConfig.ExecStart = "${pythonScript}/bin/my_python_script"; - }; - - # ... - }; - - testScript = '' - # ... - - machine.wait_for_unit("my-python-service.service") - - # ... - ''; -} -``` - - [Creating a mocking server]: ../../tutorials/creating-a-mock-server.md diff --git a/doc/ioc/guides/testing/unit-tests.md b/doc/ioc/guides/testing/unit-tests.md deleted file mode 100644 index b5d0032f..00000000 --- a/doc/ioc/guides/testing/unit-tests.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -title: Writing unit tests ---- - -# EPICS unit tests primer - -TODO - -# EPICS unit test API - -# Example diff --git a/doc/ioc/introduction.md b/doc/ioc/introduction.md deleted file mode 100644 index 1da2c047..00000000 --- a/doc/ioc/introduction.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -title: EPICS IOCs ---- - -# Introduction - -EPNix (pronunciation: like you are high on mushrooms) provides a way of building and packaging EPICS IOCs using the [Nix] package manager. - -By leveraging the Nix package manager, it provides several advantages compared to packaging EPICS the traditional way: - -Reproducibility: -: Your development environment is the same as your coworker's development environment, which is the same as your production environment. - -Complete dependencies: -: Your EPICS IOCs ship with the complete set of dependencies, which means you can to deploy your IOC without needing to install any dependency on the target machine (except for Nix itself). - -Dependency traceability: -: The version of your dependencies are locked, updated manually, and traced in your `flake.lock` file. - Combined with code versioning, you can build your project with the same environment years later, and you can roll back to any earlier version. - -Development shell: -: Provides you with a set of tools adapted to your project, no matter what you have installed on your machine. - -Declarative configuration: -: Define what you want in your IOC in a declarative and extendable manner. - -Integration tests: -: Write tests using Python, by starting a virtual machine with your IOC running. - - [Nix]: https://nixos.org/guides/how-nix-works.html - -## Packaging policy - -To be able to specify your dependencies in your EPNix configuration, EPNix provides a package repository, packaging for example `epics-base`, `asyn`, `StreamDevice`, etc. - -In its package repository, EPNix officially supports the latest upstream version. - -However, since Nix "locks" your dependencies, this means you don't need to upgrade your dependencies if you don't want to. -What this means in practice: your IOC repository uses the EPNix project repository at a fixed commit, like using a repository at a fixed point in time. -Nix records this commit SHA in the `flake.lock` file, which should be checked out in your Git repository. - -### The epics-base package - -The epics-base package has no significant modification compared to the upstream version at [Launchpad]. -One goal of EPNix is to keep those modifications to a minimum, and upstream what's possible. - - [Launchpad]: https://git.launchpad.net/epics-base diff --git a/doc/ioc/references.md b/doc/ioc/references.md deleted file mode 100644 index cb56d640..00000000 --- a/doc/ioc/references.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: References ---- - -This section of the book contains reference documentation[^1] related to building and deploying EPICS IOCs with EPNix. - -[^1]: diff --git a/doc/ioc/tutorials.md b/doc/ioc/tutorials.md deleted file mode 100644 index 39c569ff..00000000 --- a/doc/ioc/tutorials.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: User tutorials ---- - -Tutorials[^1] for users of the EPNix project wanting to build and deploy EPICS IOCs. - -[^1]: diff --git a/doc/ioc/tutorials/adding-options.md b/doc/ioc/tutorials/adding-options.md deleted file mode 100644 index 60cbc4d8..00000000 --- a/doc/ioc/tutorials/adding-options.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Adding configuration options ---- - -TODO diff --git a/doc/ioc/tutorials/creating-a-mock-server.md b/doc/ioc/tutorials/creating-a-mock-server.md deleted file mode 100644 index 0bdc9738..00000000 --- a/doc/ioc/tutorials/creating-a-mock-server.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Creating a mocking server ---- - -TODO diff --git a/doc/ioc/tutorials/day-to-day-dev.md b/doc/ioc/tutorials/day-to-day-dev.md deleted file mode 100644 index d1417baf..00000000 --- a/doc/ioc/tutorials/day-to-day-dev.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Day to day development ---- - -TODO diff --git a/doc/ioc/tutorials/integration-tests.md b/doc/ioc/tutorials/integration-tests.md deleted file mode 100644 index 0db48a66..00000000 --- a/doc/ioc/tutorials/integration-tests.md +++ /dev/null @@ -1,121 +0,0 @@ ---- -title: Integration tests ---- - -# Writing the test - -Through the [NixOS testing framework], EPNix provides a way of specifying a machine configuration, and running a Python script that can do various kind of testing. - -If you created your IOC using the EPNix template, like suggested in the [StreamDevice tutorial], you will see a `checks/` directory. -This directory should contain the integration tests you want to run. - -To add an integration test to EPNix, record it in your `flake.nix` under the `epnix.checks.files` option. - -For example, in the EPNix template, you will see in your `flake.nix` file: - -``` nix -checks.files = [ ./checks/simple.nix ]; -``` - -The `./checks/.nix` file should contain a NixOS test like so: - -``` nix -{ build, pkgs, ... }: - -pkgs.nixosTest { - name = "myTest"; - - machine = { - # Description of the NixOS machine... - }; - - testScript = '' - # Python script that does the testing... - ''; -} -``` - -This test will create a NixOS virtual machine from the given configuration, and run the test script. -Note that the test script does *not* run on the virtual machine, but communicates with it. -This is because the test script can start, shut down, or reboot the machine, and also because NixOS tests can also manage several virtual machines, not just one. - -For an overview of what you can input in the machine configuration, please refer to the [NixOS documentation]. -You can also read about the Python test script API [here][NixOS testing framework]. - - [NixOS testing framework]: https://nixos.org/manual/nixos/stable/index.html#sec-nixos-tests - [StreamDevice tutorial]: ./streamdevice.md - [NixOS documentation]: https://nixos.org/manual/nixos/stable/index.html#sec-configuration-syntax - -# Starting your IOC through systemd - -We recommend starting your IOC through a systemd service, which you can describe in Nix like so: - - - -``` nix -# Inside the `machine` attribute -{ - systemd.services.my-ioc = { - wantedBy = [ "multi-user.target" ]; - serviceConfig = { - ExecStart = "${build}/iocBoot/iocexample/st.cmd"; - WorkingDirectory = "${build}/iocBoot/iocexample"; - - # Makes the EPICS command-line not quit for 100 seconds, if it doesn't - # receive anything on the standard input - StandardInputText = "epicsThreadSleep(100)"; - }; - }; - - # Provides the caget / caput / etc. commands to the test script - environment.systemPackages = [ pkgs.epnix.epics-base ]; -} -``` - -You can view the list of options available for a NixOS machine [here]. - -Then, you can write your test script. -Note that the test script doesn't run directly on the machine, but communicates with the machine through the `machine` variable. - -An example of a testing script: - -``` python -start_all() - -machine.wait_for_unit("default.target") -machine.wait_for_unit("my-ioc.service") - -machine.wait_until_succeeds("caget stringin") -machine.wait_until_succeeds("caget stringout") -machine.fail("caget non-existing") - -with subtest("testing stringout"): - def test_stringout(_) -> bool: - machine.succeed("caput stringout 'hello'") - status, _output = machine.execute("caget -t stringout | grep -qxF 'hello'") - - return status == 0 - - retry(test_stringout) - - assert "hello" not in machine.succeed("caget -t stringin") -``` - -Note that the script extensively uses the `wait_until_succeeds` method and the `retry` function. -This is because EPICS has few guarantees about whether it propagates changes immediately, and so it's better to encourage the use of retries, instead of hoping the timing lines up. - -If you would like to use a fully fledged python script on the machine, which can use Python dependencies like pyepics, please refer to the guide [Packaging Python scripts]. - -You can find methods available on the `machine` variable and other particularities in the [NixOS tests documentation]. - -You can also look at examples either in the EPNix repository under the [`checks` folder], or in nixpkgs under the [`nixos/tests` folder]. - -```{=html} - -``` - - [here]: https://search.nixos.org/options?channel=21.11&from=0&size=50&sort=alpha_asc&type=packages&query=systemd.services. - [Packaging Python scripts]: ../guides/testing/packaging-python-scripts.md - [NixOS tests documentation]: https://nixos.org/manual/nixos/stable/index.html#sec-nixos-tests - [`checks` folder]: https://github.com/epics-extensions/epnix/tree/master/checks - [`nixos/tests` folder]: https://github.com/NixOS/nixpkgs/tree/master/nixos/tests diff --git a/doc/ioc/tutorials/porting.md b/doc/ioc/tutorials/porting.md deleted file mode 100644 index d25efef1..00000000 --- a/doc/ioc/tutorials/porting.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Porting IOCs to EPNix ---- - -TODO diff --git a/doc/ioc/tutorials/pre-requisites.md b/doc/ioc/tutorials/pre-requisites.md deleted file mode 100644 index 6ea7a9dd..00000000 --- a/doc/ioc/tutorials/pre-requisites.md +++ /dev/null @@ -1,76 +0,0 @@ ---- -title: "Pre-requisites" ---- - -The requirements for using EPNix are having curl, Nix, and Git installed, -either in a Linux system, -or in Windows' WSL2. -Nix must be configured with "flakes" enabled. - -You *don't* need to have EPICS base installed globally, -EPNix makes it available to you -when you enter your top's development shell. - -Having a global EPICS base installation shouldn't pose any issue. - -# Installing Nix - -::: callout-warning -If you use a Linux distribution with SELinux, -be sure to turn it off. -You can do this by adding the line `SELINUX=disabled` in `/etc/sysconfig/selinux` on distributions based on RedHat Enterprise Linux (RHEL) like CentOS, Rocky Linux, and so on. -::: - -If you don't have Nix installed, -first follow the [official instructions]. -Make sure to have the `xz` utility installed beforehand, -often part of the `xzip` or `xz` package. - -Unless you use WSL2, -use the multi-user installation, -because it builds packages in an isolated environment. - - [official instructions]: https://nixos.org/download.html#download-nix - -# Enabling Nix flakes and the `nix`{.bash} command - -Because Nix flakes and the unified `nix` command are experimental features at the time of writing, -you need to enable them in your `/etc/nix/nix.conf`. - -To enable this feature, -add this line to your `/etc/nix/nix.conf`: - -``` ini -experimental-features = nix-command flakes -``` - -If you have installed Nix in multi-user mode, -then you have to restart the Nix daemon by running: - -``` bash -systemctl restart nix-daemon.service -``` - -# Untracked files and Nix flakes - -One important thing with Nix flakes: -when your flake is in a Git repository, -Nix only considers files that Git tracks. - -For example, -if your `flake.nix` is in a Git repository, -and you create a file `foobar.txt`, -you must run `git add [-N] foobar.txt`{.bash} to make Nix recognize it. - -This prevents copying build products into the Nix store. - -# Git version - -If you use an old system and see Git errors when using Nix, -install a recent version of Git by running this: - -``` bash -nix-env -iA nixpkgs.git -``` - -This command installs a recent version of Git for your current user. diff --git a/doc/ioc/tutorials/streamdevice.md b/doc/ioc/tutorials/streamdevice.md deleted file mode 100644 index 29441736..00000000 --- a/doc/ioc/tutorials/streamdevice.md +++ /dev/null @@ -1,294 +0,0 @@ ---- -title: "Creating a StreamDevice IOC" ---- - -In this tutorial, -you're gonna learn how to create an EPICS IOC with EPNix -that communicates with a power supply, -using the [StreamDevice] support module. - - [StreamDevice]: https://paulscherrerinstitute.github.io/StreamDevice/ - -# Pre-requisites - -Verify that you have all pre-requisites installed. -If not, -follow the [Pre-requisites] section. - - [Pre-requisites]: ./pre-requisites.md - -# Running the power supply simulator - -EPNix has a power supply simulator -for you to test your IOC. - -To run it: - -``` bash -nix run 'github:epics-extensions/epnix#psu-simulator' -``` - -For the rest of the tutorial, -leave it running in a separate terminal. - -# Creating your top - -We can use these command to create an EPNix top: - -``` bash -# Initialise an EPNix top -nix flake new -t 'github:epics-extensions/epnix' my-top -cd my-top - -# Enter the EPNix development shell, that has EPICS base installed in it. -nix develop - -# Create your app and ioc boot folder -makeBaseApp.pl -t ioc example -makeBaseApp.pl -i -t ioc -p example -a linux-x86_64 Example - -# Create a git repository, and make sure all files are tracked -git init -git add . -``` - -After that, -you can already check that your top build with: - -``` bash -nix build -L -``` - -This `nix build`{.sh} command compiles your IOC, -and all its dependencies. -This makes the usual EPICS environment setup unneeded. - -If found in the official Nix cache server, -Nix downloads packages from there -instead of compiling them. - -This command puts a `./result` symbolic link in your current directory, -containing the compilation result. - -# Adding StreamDevice to the EPNix environment - -Adding dependencies to the EPNix environment happen inside the `flake.nix` file. -This file is the main entry point for specifying your build environment: -most Nix commands used here read this file to work. - -For adding StreamDevice, -change yours like so: - -``` {.diff filename="flake.nix"} - # Add one of the supported modules here: - # --- -- #support.modules = with pkgs.epnix.support; [ StreamDevice ]; -+ support.modules = with pkgs.epnix.support; [ StreamDevice ]; -``` - -Then, -leave your EPNix development shell by running `exit`{.sh}, -and re-enter it with `nix develop`{.sh}. - -Because you modified the support modules, -run `eregen-config`{.sh} to regenerate `configure/RELEASE.local`. - -With this, -your development shell has StreamDevice available, -and StreamDevice is also added in the `RELEASE.local` file. - -::: callout-tip -As a rule, -each time you edit the `flake.nix` file, -leave and re-enter your development shell (`exit`{.sh} then `nix develop`{.sh}), -and run `eregen-config`{.sh}. -::: - -# Adding StreamDevice to your EPICS app - -To add StreamDevice to your app, -make the following modifications: - -Change the `exampleApp/src/Makefile` -so that your App knows the record types of StreamDevice and its dependencies. -Also change that file so that it links to the StreamDevice library and its dependencies, -during compilation. -For example: - -``` {.makefile filename="exampleApp/src/Makefile"} -# ... - -# Include dbd files from all support applications: -example_DBD += calc.dbd -example_DBD += asyn.dbd -example_DBD += stream.dbd -example_DBD += drvAsynIPPort.dbd - -# Add all the support libraries needed by this IOC -example_LIBS += calc -example_LIBS += asyn -example_LIBS += stream - -# ... -``` - -Create the `exampleApp/Db/example.proto` file -that has the definition of the protocol. -This file tells StreamDevice what to send the power supply, -and what to expect in return. - -``` {.perl filename="exampleApp/Db/example.proto"} -Terminator = LF; - -getVoltage { - out ":VOLT?"; in "%f"; -} - -setVoltage { - out ":VOLT %f"; - @init { getVoltage; } -} -``` - -Create the `exampleApp/Db/example.db` file. -That file specifies the name, type, and properties of the Process Variables (PV) -that EPICS exposes over the network. -It also specifies how they relate to the functions written in the protocol file. - -``` {.perl filename="exampleApp/Db/example.db"} -record(ai, "${PREFIX}VOLT-RB") { - field(DTYP, "stream") - field(INP, "@example.proto getVoltage ${PORT}") -} - -record(ao, "${PREFIX}VOLT") { - field(DTYP, "stream") - field(OUT, "@example.proto setVoltage ${PORT}") -} -``` - -Change `exampleApp/Db/Makefile` -so that the EPICS build system installs `example.proto` and `example.db`: - -``` {.makefile filename="exampleApp/Db/Makefile"} -# ... - -#---------------------------------------------------- -# Create and install (or just install) into /db -# databases, templates, substitutions like this -DB += example.db -DB += example.proto - -# ... -``` - -Change your `st.cmd` file -so that it knows where to load the protocol file, -and how to connect to the remote power supply. - -``` {.csh filename="iocBoot/iocExample/st.cmd"} -#!../../bin/linux-x86_64/example - -< envPaths - -## Register all support components -dbLoadDatabase("${TOP}/dbd/example.dbd") -example_registerRecordDeviceDriver(pdbbase) - -# Where to find the protocol files -epicsEnvSet("STREAM_PROTOCOL_PATH", "${TOP}/db") -# The TCP/IP address of the power supply -drvAsynIPPortConfigure("PS1", "localhost:8727") - -## Load record instances -dbLoadRecords("${TOP}/db/example.db", "PREFIX=, PORT=PS1") - -iocInit() -``` - -And run `chmod +x iocBoot/iocExample/st.cmd` -so that you can run your command file as-is. - -You can test that your top builds by running: - -``` bash -nix build -L -``` - -You will see that your IOC does not build. -This is because we haven't told Git to track those newly added files, -and so Nix ignores them too. - -Run `git add .`{.sh} for Git and Nix to track all files, -and try a `nix build -L`{.sh} again. - -If everything goes right, -you can examine your compiled top under `./result`. - -You can observe that: - -- the `example` app is installed under `bin/` and `bin/linux-x86_64`, - and links to the correct libraries -- `example.proto` and `example.db` are installed under `db/` -- `example.dbd` is generated and installed under `dbd/` - -# Running your IOC - -To run your IOC, -build it first with `nix build -L`{.sh}, -and change directory into the `./result/iocBoot/iocExample` folder. -Then, run: - -``` bash -./st.cmd -``` - -You should see the IOC starting and connecting to `localhost:8727`. - -# Recompiling with make - -Using `nix build`{.sh} to compile your IOC each time might feel slow. -This is because Nix re-compiles your IOC from scratch each time. - -If you want a more "traditional" edit / compile / run workflow, -you can place yourself in the development shell with `nix develop`{.sh}, -and use `make` from here. - -# Next steps - -More commands are available in the power supply simulator. -To view them, -close your IOC, -and open a direct connection to the simulator: - -``` bash -nc localhost 8727 -# or -telnet localhost 8727 -``` - -You can install the `nc` command through the `netcat` package, -or you can install the `telnet` command through the `telnet` package, - -Either command opens a prompt -where you can type `help` then press enter -to view the available commands. - -Try to edit the protocol file and the database file -to add those features to your IOC. - -For more information about how to write the StreamDevice protocol, -have a look at the [Protocol Files] documentation. - -You might also be interested in reading [Setting up the flake registry] - - [Protocol Files]: https://paulscherrerinstitute.github.io/StreamDevice/protocol.html - [Setting up the flake registry]: ../guides/flake-registry.md - -# Pitfalls - -Although EPNix tries to be close to a standard EPICS development, -some differences might lead to confusion. -You can find more information about this in the [FAQ]. - - [FAQ]: ../faq.md diff --git a/doc/logo.svg b/doc/logo.svg deleted file mode 100644 index fe9f751c..00000000 --- a/doc/logo.svg +++ /dev/null @@ -1,411 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - diff --git a/doc/nixos/guides/_pre-requisites.md b/doc/nixos/guides/_pre-requisites.md deleted file mode 100644 index d13fe83a..00000000 --- a/doc/nixos/guides/_pre-requisites.md +++ /dev/null @@ -1,41 +0,0 @@ -# Pre-requisites - -- Having a NixOS machine with a flake configuration. - -If you're not sure how to do this, -you can follow the [Archiver Appliance tutorial], -which is a good introduction on how to make a NixOS VM. - -If you have such a configuration, -make sure that: - -- You have the `epnix` flake input -- You have added `epnix` as an argument to your flake outputs -- You have imported EPNix' NixOS module - -For example: - -``` {.diff filename="flake.nix"} - { - # ... - inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11"; -+ inputs.epnix.url = "github:epics-extensions/EPNix/nixos-23.11"; - - # ... - outputs = { - self, - nixpkgs, -+ epnix, - }: { - nixosConfigurations.nixos = nixpkgs.lib.nixosSystem { - modules = [ -+ epnix.nixosModules.nixos - - # ... - ]; - }; - }; - } -``` - - [Archiver Appliance tutorial]: ../tutorials/archiver-appliance.md diff --git a/doc/nixos/guides/ca-gateway.md b/doc/nixos/guides/ca-gateway.md deleted file mode 100644 index ede4ea15..00000000 --- a/doc/nixos/guides/ca-gateway.md +++ /dev/null @@ -1,195 +0,0 @@ ---- -title: Channel Access gateway setup ---- - -The Channel Access (CA) gateway is a program -that acts as gateway, -which enables client from a network to access IOCs on another network. - -Setting up a CA gateway also enables you -to add extra access security rules on top of IOCs. - -For more details and documentation about the CA PV gateway, -you can examine the [gateway main page]. - - [gateway main page]: https://epics.anl.gov/extensions/gateway/ - -{{< include _pre-requisites.md >}} - -# Enabling the gateway - -To enable the gateway, -add this to your configuration: - -``` nix -{ - services.ca-gateway = { - enable = true; - openFirewall = true; - }; -} -``` - -This configuration starts the CA gateway in a `ca-gateway.service` systemd service. -In this configuration, -the gateway listens on all interface with a broadcast IP address, -and forwards all Channel Access request. - -The `openFirewall` option opens the -5064 TCP, -5064 UDP, -and 5065 UDP ports on all network interfaces. - -# Firewall on specific interfaces - -If you want to enable the firewall on specific interfaces, -you can remove the `openFirewall` option -and configure the firewall manually. - -You can also use the `cip` setting -to specify where the gateway should listen -for the CA server part. - -For example: - -``` nix -{config, ...}: { - services.ca-gateway = { - enable = true; - # Server side listen address - # Let's say this IP address is on enp0s2 - settings.sip = ["10.0.2.1"]; - - # Let's also say the enp0s1 interface is - # where communication with "real" IOCs happen (client side) - - # openFirewall is left as false by default - }; - - networking.firewall = let - gwSettings = config.services.ca-gateway.settings; - in { - interfaces = { - # Open the firewall on the interface from the client side of the gateway, - # this will be the side of the gateway listening - # for replies to beacons and PV search requests - "enp0s1".allowedUDPPorts = [5065]; - - # Open the firewall on the interface from the server side of the gateway, - # this will be the side of the gateway listening for Channel Access requests - "enp0s2" = { - # Use the value of the `sport` setting - allowedTCPPorts = [gwSettings.sport]; - allowedUDPPorts = [gwSettings.sport]; - }; - }; - - # Allow incoming UDP packets with *source* port 5064, - # from the client side of the gateway. - # This is needed to listen to CA broadcast responses - extraCommands = '' - ip46tables -A nixos-fw -p udp --sport 5064 -j nixos-fw-accept -i enp0s1 - ''; - }; -} -``` - -# Filtering IOCs - -By using the `cip` setting, -you can filter which IOCs get exposed by the gateway. -This is equivalent to setting the environment variable `EPICS_CA_ADDR_LIST` -and setting `EPICS_CA_AUTO_ADDR_LIST=NO`. - -For example: - -``` nix -{ - services.ca-gateway = { - enable = true; - # These IOCs get exposed by the gateway - settings.cip = [ - "10.0.1.42" - "10.0.1.69" - - # you can specify the port, too, - # if your IOC listens on something other than 5064 - "10.0.1.237:5067" - - # domain names also work - "myioc" - ]; - }; -} -``` - -# Filtering process variables - -By using the `pvlist` setting, -you can filter which PVs get exposed by the gateway. - -This option takes a file in the gateway `pvlist` format. -See the [`GATEWAY.pvlist`] example on the ca-gateway repository. -The list supports regular expressions (Perl style). - - [`GATEWAY.pvlist`]: https://github.com/epics-extensions/ca-gateway/blob/master/example/GATEWAY.pvlist - -## In the configuration - -For example: - -``` nix -{pkgs, ...}: { - services.ca-gateway = { - enable = true; - # These PVs get exposed by the gateway - # This list implements an "allowlist": - # DENY by default, some PVs explicitely ALLOW - settings.pvlist = pkgs.writeText "gateway.pvlist" '' - EVALUATION ORDER DENY, ALLOW - - .* DENY - - MY_PV1 ALLOW - MY_PV2 ALLOW - - # Or: - - MY_PV[0-9]+ ALLOW - ''; - }; -} -``` - -## In a separate file - -For long lists, -it can be better -to put it in a separate file. -You can do this -by adding a `gateway.pvlist` in the same directory as your configuration: - -``` {.perl filename="gateway.pvlist"} -EVALUATION ORDER DENY, ALLOW - -.* DENY - -MY_PV1 ALLOW -MY_PV2 ALLOW - -# Or: - -MY_PV[0-9]+ ALLOW -``` - -And in your configuration: - -``` nix -{ - services.ca-gateway = { - enable = true; - # Make sure that the value is *not* quoted - settings.pvlist = ./gateway.pvlist; - }; -} -``` diff --git a/doc/nixos/guides/phoebus-alarm.md b/doc/nixos/guides/phoebus-alarm.md deleted file mode 100644 index 6c941b50..00000000 --- a/doc/nixos/guides/phoebus-alarm.md +++ /dev/null @@ -1,214 +0,0 @@ ---- -title: Phoebus Alarm single server setup ---- - -The Phoebus Alarm collection of services enables monitoring EPICS PVs, -and report alarms in a server. -Phoebus clients can then contact this server, -to see a list of current alarms, earlier alarms, and so on. - -This guide focuses on installing and configuring these services on a single server. - -For more information about these services, -examine the official documentation: - -- [Service Architecture] -- [Alarm Server] -- [the README of Alarm Server] for reference only, don't follow this guide on NixOS -- [Alarm Logging Service] - -The Phoebus Alarm Logging Service can also be called the Phoebus Alarm Logger. - - [Service Architecture]: https://control-system-studio.readthedocs.io/en/latest/services_architecture.html - [Alarm Server]: https://control-system-studio.readthedocs.io/en/latest/services/alarm-server/doc/index.html - [the README of Alarm Server]: https://github.com/ControlSystemStudio/phoebus/blob/master/app/alarm/Readme.md - [Alarm Logging Service]: https://control-system-studio.readthedocs.io/en/latest/services/alarm-logger/doc/index.html - -{{< include _pre-requisites.md >}} - -# Single server Phoebus Alarm setup - -To configure Phoebus Alarm, Phoebus Alarm Logger, Apache Kafka, and ElasticSearch on a single server, -add this to your configuration, -while taking care of replacing the IP address -and Kafka's `clusterId`: - -``` nix -{lib, pkgs, ...}: let - # Replace this with your machine's external IP address - # or DNS domain name - ip = "192.168.1.42"; - kafkaListenSockAddr = "${ip}:9092"; - kafkaControllerListenSockAddr = "${ip}:9093"; -in { - # The Phoebus Alarm server also automatically enables the Phoebus Alarm Logger - services.phoebus-alarm-server = { - enable = true; - openFirewall = true; - settings."org.phoebus.applications.alarm/server" = kafkaListenSockAddr; - }; - - services.phoebus-alarm-logger.settings."bootstrap.servers" = kafkaListenSockAddr; - - # Single-server Kafka setup - services.apache-kafka = { - enable = true; - # Replace with a randomly generated uuid. You can get one by running: - # nix shell 'nixpkgs#apacheKafka' -c kafka-storage.sh random-uuid - clusterId = "xxxxxxxxxxxxxxxxxxxxxx"; - formatLogDirs = true; - settings = { - listeners = [ - "PLAINTEXT://${kafkaListenSockAddr}" - "CONTROLLER://${kafkaControllerListenSockAddr}" - ]; - # Adapt depending on your security constraints - "listener.security.protocol.map" = [ - "PLAINTEXT:PLAINTEXT" - "CONTROLLER:PLAINTEXT" - ]; - "controller.quorum.voters" = [ - "1@${kafkaControllerListenSockAddr}" - ]; - "controller.listener.names" = ["CONTROLLER"]; - - "node.id" = 1; - "process.roles" = ["broker" "controller"]; - - "log.dirs" = ["/var/lib/apache-kafka"]; - "offsets.topic.replication.factor" = 1; - "transaction.state.log.replication.factor" = 1; - "transaction.state.log.min.isr" = 1; - }; - }; - - systemd.services.apache-kafka.unitConfig.StateDirectory = "apache-kafka"; - - # Open kafka to the outside world - networking.firewall.allowedTCPPorts = [9092]; - - services.elasticsearch = { - enable = true; - package = pkgs.elasticsearch7; - }; - - # Elasticsearch, needed by Phoebus Alarm Logger, is not free software (SSPL | Elastic License). - # To accept the license, add the code below: - nixpkgs.config.allowUnfreePredicate = pkg: - builtins.elem (lib.getName pkg) [ - "elasticsearch" - ]; -} -``` - -From the Phoebus graphical client side, -add this configuration: - -``` ini -# For the Phoebus Alarm Server: -# Replace the IP address with your server's IP address or DNS domain name -org.phoebus.applications.alarm/server=192.168.1.42:9092 - -# For the Phoebus Alarm Logger: -# Replace the IP address again -org.phoebus.applications.alarm.logging.ui/service_uri=http://192.168.1.42:8080 -``` - -# Configuring topics - -The Phoebus Alarm system uses "topics" as a way of grouping alarms. -These topics are the available roots of your alarm tree. -You need to synchronize the topic names between: - -- Phoebus Alarm Server -- Phoebus Alarm Logger -- Phoebus graphical clients - -Changing the topic names in the Phoebus Alarm Server NixOS modules automatically creates them. - -::: callout-warning -Currently, the Phoebus Alarm Server doesn't support several topics. -::: - -For example, -if you want to have the topic `Project`, -add this configuration to the server: - -``` nix -{config, lib, ...}: let - topics = ["Project"]; -in { - services.phoebus-alarm-server = { - # ... - settings = { - # ... - "org.phoebus.applications.alarm/config_names" = topics; - }; - }; - - services.phoebus-alarm-logger.settings.alarm_topics = topics; -} -``` - -For the Phoebus graphical client, -add this configuration: - -``` ini -# config_name is only used in the Phoebus graphical client -org.phoebus.applications.alarm/config_name = Project -org.phoebus.applications.alarm/config_names = Project -``` - -# Configuring the address list - -If you want to limit the IOCs reachable by the Phoebus Alarm Server, -use these option: - -``` nix -{ - services.phoebus-alarm-server = { - # ... - settings = { - # ... - - # The Phoebus Alarm Server will only have access to these IOCs - "org.phoebus.pv.ca/addr_list" = ["192.168.1.5" "192.168.1.42"]; - "org.phoebus.pv.ca/auto_addr_list" = false; - }; - }; -} -``` - -# Configuring email support - -To enable email support, -set the `org.phoebus.email/mailport` setting. -Here is a list of options you might want to set: - -``` nix -{ - services.phoebus-alarm-server = { - # ... - settings = { - # ... - - "org.phoebus.email/mailhost" = "smtp.my-company.org"; - - # Optional: - - # 25 for plain SMTP - "org.phoebus.email/mailport" = 25; - # If authentication is needed: - "org.phoebus.email/username" = "user"; - "org.phoebus.email/password" = "password"; - # Default address to be used for From: - # if unspecified, then the last used "from" address is used - "org.phoebus.email/from" = "Sender "; - }; - }; -} -``` - -::: callout-warning -Currently, Phoebus Alarm Server only supports plain SMTP. -::: diff --git a/doc/nixos/guides/phoebus-save-and-restore.md b/doc/nixos/guides/phoebus-save-and-restore.md deleted file mode 100644 index f9a264f4..00000000 --- a/doc/nixos/guides/phoebus-save-and-restore.md +++ /dev/null @@ -1,50 +0,0 @@ ---- -title: Phoebus Save-and-restore setup ---- - -The Phoebus Save-and-restore service is used by clients -to manage configuration and snapshots of PV values. -These snapshots can then be used by clients for comparison or for restoring PVs. - -This guide focuses on installing and configuring the Save-and-Restore service on a single server. - -For more details and documentation about Phoebus Save-and-Restore, -you can examine the [Save-and-restore official documentation]. - - [Save-and-restore official documentation]: https://control-system-studio.readthedocs.io/en/latest/services/save-and-restore/doc/index.html - -{{< include _pre-requisites.md >}} - -# Enabling the Phoebus Save-and-restore service - -To enable the Phoebus Save-and-restore service, -add this to your configuration: - -``` nix -{lib, ...}: { - services.phoebus-save-and-restore = { - enable = true; - openFirewall = true; - }; - - # Elasticsearch, needed by Phoebus Save-and-restore, is not free software (SSPL | Elastic License). - # To accept the license, add the code below: - nixpkgs.config.allowUnfreePredicate = pkg: - builtins.elem (lib.getName pkg) [ - "elasticsearch" - ]; -} -``` - -From the Phoebus graphical client side, -add this configuration - -``` ini -# Replace the IP address with your server's IP address or domain name -org.phoebus.applications.saveandrestore/jmasar.service.url=http://192.168.1.42:8080 -``` - -::: callout-warning -URLs for future versions of Phoebus Save-and-restore will need to change to: -`http://192.168.1.42:8080/save-restore` -::: diff --git a/doc/nixos/introduction.md b/doc/nixos/introduction.md deleted file mode 100644 index ddc9d0a0..00000000 --- a/doc/nixos/introduction.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: NixOS ---- - -# Introduction diff --git a/doc/nixos/tutorials/archiver-appliance.md b/doc/nixos/tutorials/archiver-appliance.md deleted file mode 100644 index 1e4a7e57..00000000 --- a/doc/nixos/tutorials/archiver-appliance.md +++ /dev/null @@ -1,359 +0,0 @@ ---- -title: Creating an Archiver Appliance instance ---- - -In this tutorial, -we're going to see how to create a virtual machine that runs Archiver Appliance, -under the NixOS Linux distribution. - -Installing Archiver Appliance on a physical machine is definitely possible, -but this tutorial focuses on virtual machines for simplicity's sake. - -You will need: - -- A virtual machine, -- and the [NixOS ISO file]. - Select the "Graphical ISO image." - - [NixOS ISO file]: https://nixos.org/download#download-nixos - -# Installing NixOS - -First things first, -create your virtual machine, -and select the ISO image that you downloaded. - -Then, start the virtual machine. - -From the booted virtual machine, -you can follow the graphical installation process, -and reboot once finished. - -You can select any desktop environment, -or no desktop. -This tutorial only uses the command-line. - -# Making your configuration a flake - -The installation process created the `/etc/nixos` directory in your VM. -This directory describes the complete configuration of your machine. - -EPNix is a "Nix flake", -which a way of managing Nix projects. -Using Nix flakes also enables you to use Nix code outside of your repository, -in a controlled manner. -For more information, -see the [Nix flake command manual] and the [Flake wiki page]. - -To be able to import EPNix into you NixOS configuration, -you first need to turn your NixOS configuration into a Nix flake. - -As root, place yourself in the `/etc/nixos` directory in your virtual machine. -Create a `flake.nix` file under it, -by running `nano flake.nix`. -Fill the file with these lines: - -``` {.nix filename="flake.nix" code-line-numbers="true"} -{ - description = "Configuration for running Archiver Appliance in a VM"; - - inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11"; - inputs.epnix.url = "github:epics-extensions/EPNix/nixos-23.11"; - - outputs = { self, nixpkgs, epnix }: { - nixosConfigurations.nixos = nixpkgs.lib.nixosSystem { - modules = [ - epnix.nixosModules.nixos - - ./configuration.nix - ]; - }; - }; -} -``` - -Save and quit by typing {{< kbd Ctrl-x >}}, {{< kbd y >}}, and {{< kbd Enter >}}, -and run `nixos-rebuild test` to test your changes. - -Some explanations: - -You can see in the `flake.nix` file that the flake has 2 inputs: -`nixpkgs` and `epnix`, -lines 4--5. - -Having the `nixpkgs` input enables you to use code from [Nixpkgs]. -This is what enables you to use all those NixOS options, -and every package installed on your machine now. -For more information, -you can read the [Nixpkgs preface] -With the current configuration, -we are only using code from Nixpkgs. - -Having the `epnix` input is what's going to enable you to use [packages from EPNix], -such as Archiver Appliance. -It also enables you to use [EPNix' extra NixOS options], -such as the options configuring Tomcat, the systemd service, the `archappl` user and group, MariaDB, and so on. - - [Nix flake command manual]: https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-flake.html - [Flake wiki page]: https://nixos.wiki/wiki/Flakes - [Nixpkgs]: https://github.com/NixOS/nixpkgs - [Nixpkgs preface]: https://nixos.org/manual/nixpkgs/stable/#preface - [packages from EPNix]: ../../pkgs/packages.md - [EPNix' extra NixOS options]: ../options.md - -# Configuring Archiver Appliance - -Now for the fun part, -actually using those EPNix options to install and configure Archiver Appliance, -and all its dependencies. - -Create and edit the file `archiver-appliance.nix` under `/etc/nixos`. -For now, here are the contents: - -``` {.nix filename="archiver-appliance.nix"} -{ - services.archiver-appliance.enable = true; -} -``` - -In your `flake.nix`, -import the newly created file by adding `./archiver-appliance.nix`, -under `./configuration.nix`: - -``` diff - modules = [ - epnix.nixosModules.nixos - - ./configuration.nix -+ ./archiver-appliance.nix - ]; -``` - -If you try to test your changes by running `nixos-rebuild test`, -you will see a helpful error message: - -::: sourceCode -``` sourcecode -error: The option `services.archiver-appliance.stores.lts.location' - is used but not defined. -(use '--show-trace' to show detailed location information) -``` -::: - -This tells you that the `services.archiver-appliance.stores.lts.location` is mandatory, -but we didn't set any value. - -To figure out what this option is about, -you can examine the [options reference]. - -The options reference gives a description for this option: - -> Backing directory containing the LTS. - -and an example: - -``` nix -"/data/lts" -``` - -It tells us that you need to choose where the Long Term Store (LTS) is. -See the "Architecture" section of the [Archiver Appliance Details] page for what the various stores are. - -Because this is a test VM, -let's configure the LTS to a test location, -like `/tmp/lts`. -You will also need to configure the location of the Medium Term Store (MTS). - -Here's how to change `archiver-appliance.nix`: - -``` {.nix filename="archiver-appliance.nix"} -{ - services.archiver-appliance.enable = true; - services.archiver-appliance.stores.lts.location = "/tmp/lts"; - services.archiver-appliance.stores.mts.location = "/tmp/mts"; -} -``` - -If you don't want to repeat yourself, -you can also change it like so: - -``` {.nix filename="archiver-appliance.nix"} -{ - services.archiver-appliance = { - enable = true; - stores.lts.location = "/tmp/lts"; - stores.mts.location = "/tmp/mts"; - }; -} -``` - -And now, -`nixos-rebuild test` should succeed: - -::: sourceCode -``` sourcecode -building the system configuration... -activating the configuration... -setting up /etc... -reloading user units for admin... -setting up tmpfiles -reloading the following units: dbus.service -the following new units were started: arch-lts-ArchiverStore.mount, - arch-mts-ArchiverStore.mount, arch-sts-ArchiverStore.mount, - mysql.service, tomcat.service -``` -::: - -From the message, -we can guess it started the Tomcat server running Archiver Appliance, -the MySQL (in fact, MariaDB) server, -and mounted some partitions. -Fantastic! - -You can run the `systemctl list-units` command to see if any systemd unit failed. - -In the default configuration, -Archiver Appliance and Tomcat are configured to output logs to journald. -You can see those logs by running: - -``` bash -journalctl -xeu tomcat.service -``` - -You can also see the MariaDB logs by running: - -``` bash -journalctl -xeu mysql.service -``` - -::: callout-note -Here are some details on what was done by EPNix' `services.archiver-appliance` NixOS module: - -- Creation of the Linux user and group `archappl` -- Installation and configuration of MariaDB: - - Creation of the `archappl` user, - with UNIX socket authentication - - Creation of the Archiver Appliance database - - Creation of the [various tables] in that database - - Giving access rights to this database for the `archappl` user -- Installation and configuration of Tomcat: - - Installation of the WAR files of Archiver Appliance - - Installation of the MariaDB connector and its dependencies - - Configuring the MariaDB connector to authenticate to the database - - Logging configuration to `journald` -- Configuring mounts so that: - - `/arch/lts` and `/arch/mts` are bind mounts to the configured locations, - with some added security options, - such as `nodev` and `noexec` - - Mounting `/arch/sts` as a new `tmpfs` -::: - -Tomcat runs by default under port 8080, -and NixOS has a firewall enabled by default. - -Change your `archiver-appliance.nix`: - -``` {.nix filename="archiver-appliance.nix"} -{ - services.archiver-appliance = { - enable = true; - stores.lts.location = "/tmp/lts"; - stores.mts.location = "/tmp/mts"; - - # New option: - openFirewall = true; - }; -} -``` - -and run `nixos-rebuild test`. -It will restart `firewall.service`, -but configured to allow incoming connection on port 8080. - -Check the IP address of your VM with `ip a`, -and open a browser to `http://:8080/mgmt/ui/index.html`. - -Finally, -run `nixos-rebuild switch` to confirm your changes. -This will apply your changes for the next reboot, -by adding a new boot entry, -enabling you to go back to a previous configuration. - -You have now configured Archiver Appliance on NixOS. - - [options reference]: ../options.md - [Archiver Appliance Details]: https://slacmshankar.github.io/epicsarchiver_docs/details.html - [various tables]: https://github.com/slacmshankar/epicsarchiverap/blob/master/src/main/org/epics/archiverappliance/config/persistence/archappl_mysql.sql - -# Next steps - -This VM configuration has some problems: - -- It stores the LTS and MTS in `/tmp`, - which by default is cleaned on reboot -- The size of the Short Term Store (STS) isn't configured -- Both "management" and "retrieval" URLs are accessible without authentication - -The following sections are some pointers to fix these issues. - -## Configuring partitions - -If you want to change the location of the LST or MTS, -you can change the value of the corresponding options: - -- `services.archiver-appliance.stores.lts.location` -- `services.archiver-appliance.stores.mts.location` - -But these values won't mean much if the configured directories are not backed by the appropriate hardware. - -As an example given by the [Archiver Appliance Details] page, -section "Architecture", -we can have the LTS backed by a NAS or SAN, -and the MTS backed by SSD or SAS storage. - -The way to do that is to configure the `fileSystems` NixOS option. -See the [File Systems NixOS documentation] for more information. - - [Archiver Appliance Details]: https://slacmshankar.github.io/epicsarchiver_docs/details.html - [File Systems NixOS documentation]: https://nixos.org/manual/nixos/stable/#ch-file-systems - -## Size of the short term store - -To configure the size of the short term store, -use the `services.archiver-appliance.stores.sts.size` option. - -For example: - -``` {.nix filename="archiver-appliance.nix"} -{ - services.archiver-appliance = { - enable = true; - stores.lts.location = "/tmp/lts"; - stores.mts.location = "/tmp/mts"; - - openFirewall = true; - - # New option: - stores.sts.size = "20g"; - }; -} -``` - -See the [`sts.size` option] in the reference for a more in-depth description. - - [`sts.size` option]: ../options.md#services.archiver-appliance.stores.sts.size - -## Restricting access - -Allowing access to `mgmt` URLs to anyone can be dangerous, -because it allows anyone to delete and archive PVs. - -To restrict access, -you can close the firewall and put an nginx server in front. - -You can configure the nginx server to disallow access to the URLs you want. -You can also configure nginx to require authentication. - -```{=html} - -``` diff --git a/doc/pkgs/introduction.md b/doc/pkgs/introduction.md deleted file mode 100644 index 7baabb9d..00000000 --- a/doc/pkgs/introduction.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Packages ---- - -# Introduction diff --git a/pkgs/book/default.nix b/pkgs/book/default.nix deleted file mode 100644 index 23fcc96d..00000000 --- a/pkgs/book/default.nix +++ /dev/null @@ -1,109 +0,0 @@ -{ - stdenvNoCC, - lib, - epnixLib, - epnix, - quartoMinimal, - writeText, - documentedEpnixPkgs ? epnix, - iocConfig ? {}, - nixosConfig ? {}, -}: let - inherit (epnixLib) documentation; - - iocOptions = documentation.options.iocOptions iocConfig; - nixosOptions = documentation.options.nixosOptions nixosConfig; - - iocOptionsContent = documentation.options.optionsContent iocOptions 1; - iocOptionsPandoc = '' - --- - title: Options - format: - html: - # Disable the smart extensions so that the quotes in option names are not replaced - from: markdown-smart - --- - - ${iocOptionsContent} - ''; - - nixosOptionsContent = documentation.options.optionsContent nixosOptions 1; - nixosOptionsPandoc = '' - --- - title: NixOS Options - format: - html: - # Disable the smart extensions so that the quotes in option names are not replaced - from: markdown-smart - --- - - ${nixosOptionsContent} - ''; - - iocPkgsListPandoc = '' - --- - title: Packages list - --- - - ::: callout-note - This page references all EPNix packages that should be used when packaging an IOC. - For all other packages, see the [Packages list](../../pkgs/packages.md). - ::: - - ${epnixLib.documentation.iocPkgsList 1 documentedEpnixPkgs} - ''; - - pkgsListPandoc = '' - --- - title: Packages list - --- - - ::: callout-note - This page references all EPNix packages that may be used outside of an IOC. - For all IOC-specific packages, see the [IOC packages list](../ioc/references/packages.md). - ::: - - ${epnixLib.documentation.pkgsList 1 documentedEpnixPkgs} - ''; -in - stdenvNoCC.mkDerivation { - name = "epnix-book"; - src = ../../doc; - - nativeBuildInputs = [quartoMinimal]; - - dontConfigure = true; - - buildPhase = '' - runHook preBuild - - export HOME=$PWD - - mkdir ioc/references - - cp "${writeText "ioc-options.md" iocOptionsPandoc}" ioc/references/options.md - cp "${writeText "ioc-packages.md" iocPkgsListPandoc}" ioc/references/packages.md - cp "${writeText "nixos-options.md" nixosOptionsPandoc}" nixos/options.md - cp "${writeText "packages.md" pkgsListPandoc}" pkgs/packages.md - - quarto render - - runHook postBuild - ''; - - installPhase = '' - runHook preInstall - - cp -r _site/ "$out" - - runHook postInstall - ''; - - meta = { - description = "The EPNix documentation book"; - homepage = "https://epics-extensions.github.io/EPNix/"; - license = lib.licenses.asl20; - maintainers = with epnixLib.maintainers; [minijackson]; - hidden = true; - }; - } diff --git a/pkgs/default.nix b/pkgs/default.nix index 35f64cab..02ba4f3b 100644 --- a/pkgs/default.nix +++ b/pkgs/default.nix @@ -88,9 +88,7 @@ in mariadb_jdbc = callPackage ./epnix/tools/mariadb_jdbc {}; # EPNix specific packages - book = callPackage ./book {}; docs = callPackage ./docs {}; - manpages = callPackage ./manpages {}; # Documentation support packages psu-simulator = callPackage ./doc-support/psu-simulator {}; diff --git a/pkgs/manpages/default.nix b/pkgs/manpages/default.nix deleted file mode 100644 index 0027c55c..00000000 --- a/pkgs/manpages/default.nix +++ /dev/null @@ -1,117 +0,0 @@ -{ - stdenvNoCC, - lib, - epnix, - epnixLib, - emptyDirectory, - writeText, - pandoc, - documentedEpnixPkgs ? epnix, - iocConfig ? {}, - nixosConfig ? {}, -}: let - inherit (epnixLib) documentation; - - iocOptions = documentation.options.iocOptions iocConfig; - nixosOptions = documentation.options.nixosOptions nixosConfig; - - iocOptionsContent = documentation.options.optionsContent iocOptions 2; - iocPandoc = '' - --- - title: epnix-ioc - section: 5 - header: EPNix IOC options and packages - --- - - # PACKAGES - - This section references all EPNix packages that should be used when packaging an IOC. - For all other packages, see `epnix-packages(5)`. - - ${epnixLib.documentation.iocPkgsList 2 documentedEpnixPkgs} - - --- - - # OPTIONS - - ${iocOptionsContent} - - # SEE ALSO - - `epnix-nixos(5)`, `epnix-packages(5)` - ''; - - nixosOptionsContent = documentation.options.optionsContent nixosOptions 2; - nixosOptionsPandoc = '' - --- - title: epnix-nixos - section: 5 - header: EPNix NixOS options - --- - - # OPTIONS - - ${nixosOptionsContent} - - # SEE ALSO - - `epnix-ioc(5)`, `epnix-packages(5)` - ''; - - pkgsListPandoc = '' - --- - title: epnix-packages - section: 5 - header: EPNix packages - --- - - # DESCRIPTION - - This page references all EPNix packages that may be used outside of an IOC. - For all IOC-specific packages, see `epnix-ioc(5)`. - - # PACKAGES - - ${epnixLib.documentation.pkgsList 2 documentedEpnixPkgs} - - # SEE ALSO - - `epnix-ioc(5)`, `epnix-nixos(5)` - ''; -in - stdenvNoCC.mkDerivation { - name = "epnix-manpages"; - src = emptyDirectory; - - nativeBuildInputs = [pandoc]; - - dontConfigure = true; - - buildPhase = '' - runHook preBuild - - pandoc "${writeText "ioc-options.md" iocPandoc}" -t man -so epnix-ioc.5 - pandoc "${writeText "nixos-options.md" nixosOptionsPandoc}" -t man -so epnix-nixos.5 - pandoc "${writeText "epnix-packages.md" pkgsListPandoc}" -t man -so epnix-packages.5 - - runHook postBuild - ''; - - installPhase = '' - runHook preInstall - - install -Dt $out/share/man/man5/ epnix-ioc.5 epnix-nixos.5 epnix-packages.5 - # Add the bin folder so that the man path gets added to `manpath` - mkdir -p $out/bin - - runHook postInstall - ''; - - meta = { - description = "The EPNix documentation man page"; - homepage = "https://epics-extensions.github.io/EPNix/"; - license = lib.licenses.asl20; - maintainers = with epnixLib.maintainers; [minijackson]; - hidden = true; - }; - } From 3b79daa6667f3eef759d0d93e3480c6d27641ed2 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 26 Jul 2024 08:43:03 +0000 Subject: [PATCH 036/111] flake.lock: Update MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Flake lock file updates: • Updated input 'flake-utils': 'github:numtide/flake-utils/93a2b84fc4b70d9e089d029deacc3583435c2ed6?narHash=sha256-U02riOqrKKzwjsxc/400XnElV%2BUtPUQWpANPlyazjH0%3D' (2023-03-15) → 'github:numtide/flake-utils/b1d9ab70662946ef0850d488da1c9019f3a9752a?narHash=sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ%3D' (2024-03-11) • Added input 'flake-utils/systems': 'github:nix-systems/default/da67096a3b9bf56a91d16901293e51ba5b49a27e?narHash=sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768%3D' (2023-04-09) • Updated input 'nixpkgs': 'github:NixOS/nixpkgs/809cca784b9f72a5ad4b991e0e7bcf8890f9c3a6?narHash=sha256-dOhphIA4MGrH4ElNCy/OlwmN24MsnEqFjRR6%2BRY7jZw%3D' (2024-02-11) → 'github:NixOS/nixpkgs/205fd4226592cc83fd4c0885a3e4c9c400efabb5?narHash=sha256-zwVvxrdIzralnSbcpghA92tWu2DV2lwv89xZc8MTrbg%3D' (2024-07-09) • Updated input 'poetry2nix': 'github:nix-community/poetry2nix/4eb2ac54029af42a001c9901194e9ce19cbd8a40?narHash=sha256-xPFxTMe4rKE/ZWLlOWv22qpGwpozpR%2BU1zhyf1040Zk%3D' (2024-02-06) → 'github:nix-community/poetry2nix/d11c01e58587e5f21037ed6477465a7f26a32e27?narHash=sha256-XANsG9GYHip8pxZpbqKf/YGv8tIa0xTh289Y%2BWNBNfw%3D' (2024-07-15) • Updated input 'poetry2nix/flake-utils': 'github:numtide/flake-utils/ff7b65b44d01cf9ba6a71320833626af21126384?narHash=sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt%2BxmY%3D' (2023-09-12) → 'github:numtide/flake-utils/b1d9ab70662946ef0850d488da1c9019f3a9752a?narHash=sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ%3D' (2024-03-11) • Updated input 'poetry2nix/nix-github-actions': 'github:nix-community/nix-github-actions/4bb5e752616262457bc7ca5882192a564c0472d2?narHash=sha256-yPncV9Ohdz1zPZxYHQf47S8S0VrnhV7nNhCawY46hDA%3D' (2023-11-03) → 'github:nix-community/nix-github-actions/5163432afc817cf8bd1f031418d1869e4c9d5547?narHash=sha256-rXwqjtwiGKJheXB43ybM8NwWB8rO2dSRrEqes0S7F5Y%3D' (2023-12-29) • Updated input 'poetry2nix/treefmt-nix': 'github:numtide/treefmt-nix/e82f32aa7f06bbbd56d7b12186d555223dc399d1?narHash=sha256-3h3EH1FXQkIeAuzaWB%2BnK0XK54uSD46pp%2BdMD3gAcB4%3D' (2023-11-12) → 'github:numtide/treefmt-nix/8df5ff62195d4e67e2264df0b7f5e8c9995fd0bd?narHash=sha256-ddPKHcqaKCIFSFc/cvxS14goUhCOAwsM1PbMr0ZtHMg%3D' (2024-06-30) --- flake.lock | 58 +++++++++++++++++++++++++++++++++++------------------- 1 file changed, 38 insertions(+), 20 deletions(-) diff --git a/flake.lock b/flake.lock index acc7ae62..8c359b68 100644 --- a/flake.lock +++ b/flake.lock @@ -37,12 +37,15 @@ } }, "flake-utils_2": { + "inputs": { + "systems": "systems" + }, "locked": { - "lastModified": 1678901627, - "narHash": "sha256-U02riOqrKKzwjsxc/400XnElV+UtPUQWpANPlyazjH0=", + "lastModified": 1710146030, + "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", "owner": "numtide", "repo": "flake-utils", - "rev": "93a2b84fc4b70d9e089d029deacc3583435c2ed6", + "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", "type": "github" }, "original": { @@ -53,14 +56,14 @@ }, "flake-utils_3": { "inputs": { - "systems": "systems" + "systems": "systems_2" }, "locked": { - "lastModified": 1694529238, - "narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=", + "lastModified": 1710146030, + "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", "owner": "numtide", "repo": "flake-utils", - "rev": "ff7b65b44d01cf9ba6a71320833626af21126384", + "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", "type": "github" }, "original": { @@ -77,11 +80,11 @@ ] }, "locked": { - "lastModified": 1698974481, - "narHash": "sha256-yPncV9Ohdz1zPZxYHQf47S8S0VrnhV7nNhCawY46hDA=", + "lastModified": 1703863825, + "narHash": "sha256-rXwqjtwiGKJheXB43ybM8NwWB8rO2dSRrEqes0S7F5Y=", "owner": "nix-community", "repo": "nix-github-actions", - "rev": "4bb5e752616262457bc7ca5882192a564c0472d2", + "rev": "5163432afc817cf8bd1f031418d1869e4c9d5547", "type": "github" }, "original": { @@ -92,11 +95,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1707650010, - "narHash": "sha256-dOhphIA4MGrH4ElNCy/OlwmN24MsnEqFjRR6+RY7jZw=", + "lastModified": 1720535198, + "narHash": "sha256-zwVvxrdIzralnSbcpghA92tWu2DV2lwv89xZc8MTrbg=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "809cca784b9f72a5ad4b991e0e7bcf8890f9c3a6", + "rev": "205fd4226592cc83fd4c0885a3e4c9c400efabb5", "type": "github" }, "original": { @@ -113,15 +116,15 @@ "nixpkgs": [ "nixpkgs" ], - "systems": "systems_2", + "systems": "systems_3", "treefmt-nix": "treefmt-nix" }, "locked": { - "lastModified": 1707195113, - "narHash": "sha256-xPFxTMe4rKE/ZWLlOWv22qpGwpozpR+U1zhyf1040Zk=", + "lastModified": 1721039874, + "narHash": "sha256-XANsG9GYHip8pxZpbqKf/YGv8tIa0xTh289Y+WNBNfw=", "owner": "nix-community", "repo": "poetry2nix", - "rev": "4eb2ac54029af42a001c9901194e9ce19cbd8a40", + "rev": "d11c01e58587e5f21037ed6477465a7f26a32e27", "type": "github" }, "original": { @@ -154,6 +157,21 @@ } }, "systems_2": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_3": { "locked": { "lastModified": 1681028828, "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", @@ -175,11 +193,11 @@ ] }, "locked": { - "lastModified": 1699786194, - "narHash": "sha256-3h3EH1FXQkIeAuzaWB+nK0XK54uSD46pp+dMD3gAcB4=", + "lastModified": 1719749022, + "narHash": "sha256-ddPKHcqaKCIFSFc/cvxS14goUhCOAwsM1PbMr0ZtHMg=", "owner": "numtide", "repo": "treefmt-nix", - "rev": "e82f32aa7f06bbbd56d7b12186d555223dc399d1", + "rev": "8df5ff62195d4e67e2264df0b7f5e8c9995fd0bd", "type": "github" }, "original": { From 369dde7ac8296533ddbd6ebd7d05b1103a331a85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc?= Date: Fri, 19 Jul 2024 09:09:06 +0200 Subject: [PATCH 037/111] pkgs/phoebus-olog: 4.7.3 -> 4.7.7 removed sed because jar file was invalid --- pkgs/epnix/tools/phoebus/olog/default.nix | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/pkgs/epnix/tools/phoebus/olog/default.nix b/pkgs/epnix/tools/phoebus/olog/default.nix index b7ad7c8d..67a02d52 100644 --- a/pkgs/epnix/tools/phoebus/olog/default.nix +++ b/pkgs/epnix/tools/phoebus/olog/default.nix @@ -8,16 +8,16 @@ }: maven.buildMavenPackage rec { pname = "phoebus-olog"; - version = "4.7.3"; + version = "4.7.7"; src = fetchFromGitHub { owner = "Olog"; repo = "phoebus-olog"; rev = "v${version}"; - hash = "sha256-WwRB4QtZBeH6GptTZJ02CBpP7BGzjZbwMYQrOmGevFo="; + hash = "sha256-AHZowe4mmBpiFd5MMVRrnUHeTOJDwE6f0sZFUF+07lo="; }; - mvnHash = "sha256-D1n5PfGulIgdjd60mChVLH1kQDOUcc/TvEw3oJUZ1h4="; + mvnHash = "sha256-xaoaoL1a9VP7e4HdI2YuOUPOADnMYlPesVbkhgLz3+M="; mvnParameters = "-Dmaven.javadoc.skip=true -Dmaven.source.skip=true -Pdeployable-jar -Dproject.build.outputTimestamp=1980-01-01T00:00:02Z"; nativeBuildInputs = [makeWrapper]; @@ -30,10 +30,7 @@ maven.buildMavenPackage rec { jarName="service-olog-${version}.jar" - install -Dm644 target/service-olog-4.7.3.jar $out/share/java - # Strip the script at the beginning of the jar, so that we are able to - # canonicalize it - sed -i '1,/^exit 0$/d' $out/share/java/$jarName + install -Dm644 target/service-olog-${version}.jar $out/share/java makeWrapper ${lib.getExe jre} $out/bin/${meta.mainProgram} \ --add-flags "-jar $out/share/java/$jarName" From e90821145c46eae0d144af6debf9afa5f9f608d9 Mon Sep 17 00:00:00 2001 From: Minijackson Date: Fri, 26 Jul 2024 13:13:22 +0200 Subject: [PATCH 038/111] ca-gateway: use meta.mainProgram and lib.getExe See #62 --- nixos/modules/ca-gateway.nix | 2 +- pkgs/epnix/tools/ca-gateway/default.nix | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/nixos/modules/ca-gateway.nix b/nixos/modules/ca-gateway.nix index 14e6541c..4716a3d1 100644 --- a/nixos/modules/ca-gateway.nix +++ b/nixos/modules/ca-gateway.nix @@ -182,7 +182,7 @@ in { after = ["network-online.target"]; serviceConfig = { - ExecStart = "${pkg}/bin/gateway ${commandLine}"; + ExecStart = "${lib.getExe pkg} ${commandLine}"; # ca-gateway doesn't always exit with a positive status code, # even on failure Restart = "always"; diff --git a/pkgs/epnix/tools/ca-gateway/default.nix b/pkgs/epnix/tools/ca-gateway/default.nix index 0cf9a31c..c4018f3a 100644 --- a/pkgs/epnix/tools/ca-gateway/default.nix +++ b/pkgs/epnix/tools/ca-gateway/default.nix @@ -26,6 +26,7 @@ mkEpicsPackage rec { meta = { description = "Channel Access PV gateway"; homepage = "https://epics.anl.gov/extensions/gateway/"; + mainProgram = "gateway"; license = epnixLib.licenses.epics; maintainers = with epnixLib.maintainers; [minijackson]; }; From 999b01b8cfa5fba60c78993faa98a8078093d7ca Mon Sep 17 00:00:00 2001 From: Minijackson Date: Fri, 26 Jul 2024 13:14:38 +0200 Subject: [PATCH 039/111] nixos/phoebus-olog: use lib.getExe See #62 --- nixos/modules/phoebus/olog.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nixos/modules/phoebus/olog.nix b/nixos/modules/phoebus/olog.nix index 2b6dbb40..63740dc4 100644 --- a/nixos/modules/phoebus/olog.nix +++ b/nixos/modules/phoebus/olog.nix @@ -108,7 +108,7 @@ in { after = ["elasticsearch.service" "mongodb.service"]; serviceConfig = { - ExecStart = "${pkgs.epnix.phoebus-olog}/bin/phoebus-olog --spring.config.location=file://${configFile}"; + ExecStart = "${lib.getExe pkgs.epnix.phoebus-olog} --spring.config.location=file://${configFile}"; DynamicUser = true; # TODO: systemd hardening. Currently level 8.2 EXPOSED }; From f53a087180f99d07ce3b215a44373366c56fc51a Mon Sep 17 00:00:00 2001 From: Minijackson Date: Fri, 26 Jul 2024 13:16:47 +0200 Subject: [PATCH 040/111] phoebus-save-and-restore: use meta.mainProgram and lib.getExe See #62 --- nixos/modules/phoebus/save-and-restore.nix | 2 +- pkgs/epnix/tools/phoebus/save-and-restore/default.nix | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/nixos/modules/phoebus/save-and-restore.nix b/nixos/modules/phoebus/save-and-restore.nix index c3ee1dd3..220ce101 100644 --- a/nixos/modules/phoebus/save-and-restore.nix +++ b/nixos/modules/phoebus/save-and-restore.nix @@ -84,7 +84,7 @@ in { after = lib.mkIf localElasticsearch ["elasticsearch.service"]; serviceConfig = { - ExecStart = "${pkgs.epnix.phoebus-save-and-restore}/bin/phoebus-save-and-restore --spring.config.location=file://${configFile}"; + ExecStart = "${lib.getExe pkgs.epnix.phoebus-save-and-restore} --spring.config.location=file://${configFile}"; Restart = "on-failure"; DynamicUser = true; diff --git a/pkgs/epnix/tools/phoebus/save-and-restore/default.nix b/pkgs/epnix/tools/phoebus/save-and-restore/default.nix index d0efab5e..bf805448 100644 --- a/pkgs/epnix/tools/phoebus/save-and-restore/default.nix +++ b/pkgs/epnix/tools/phoebus/save-and-restore/default.nix @@ -50,6 +50,7 @@ in meta = { description = "Implements the MASAR (MAchine Save And Restore) service as a REST API"; homepage = "https://control-system-studio.readthedocs.io/en/latest/services/save-and-restore/doc/index.html"; + mainProgram = "phoebus-save-and-restore"; license = lib.licenses.epl10; maintainers = with epnixLib.maintainers; [minijackson]; inherit (jdk.meta) platforms; From 92d806c87c6c0ef0eedcf481470ec6dd954a51a5 Mon Sep 17 00:00:00 2001 From: Minijackson Date: Fri, 26 Jul 2024 13:19:02 +0200 Subject: [PATCH 041/111] phoebus-alarm-logger: use meta.mainProgram and lib.getExe See #62 --- nixos/modules/phoebus/alarm-logger.nix | 2 +- pkgs/epnix/tools/phoebus/alarm-logger/default.nix | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/nixos/modules/phoebus/alarm-logger.nix b/nixos/modules/phoebus/alarm-logger.nix index 47af9914..4cc6b4a6 100644 --- a/nixos/modules/phoebus/alarm-logger.nix +++ b/nixos/modules/phoebus/alarm-logger.nix @@ -146,7 +146,7 @@ in { "-noshell" "-properties ${configFile}" ]; - in "${pkgs.epnix.phoebus-alarm-logger}/bin/phoebus-alarm-logger ${lib.concatStringsSep " " args}"; + in "${lib.getExe pkgs.epnix.phoebus-alarm-logger} ${lib.concatStringsSep " " args}"; DynamicUser = true; StateDirectory = "phoebus-alarm-logger"; # TODO: systemd hardening diff --git a/pkgs/epnix/tools/phoebus/alarm-logger/default.nix b/pkgs/epnix/tools/phoebus/alarm-logger/default.nix index acdb223f..e093405f 100644 --- a/pkgs/epnix/tools/phoebus/alarm-logger/default.nix +++ b/pkgs/epnix/tools/phoebus/alarm-logger/default.nix @@ -50,6 +50,7 @@ in meta = { description = "Records all alarm messages to create an archive of all alarm state changes and the associated actions"; homepage = "https://control-system-studio.readthedocs.io/en/latest/services/alarm-logger/doc/index.html"; + mainProgram = "phoebus-alarm-logger"; license = lib.licenses.epl10; maintainers = with epnixLib.maintainers; [minijackson]; inherit (jdk.meta) platforms; From 93039e271903adb56a5556ea379ecd9e4d564f3a Mon Sep 17 00:00:00 2001 From: Minijackson Date: Fri, 26 Jul 2024 13:34:59 +0200 Subject: [PATCH 042/111] procServe: use meta.mainProgram and lib.getExe See #62 --- ioc/modules/nixos-integration.nix | 2 +- pkgs/epnix/tools/procServ/default.nix | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/ioc/modules/nixos-integration.nix b/ioc/modules/nixos-integration.nix index 0318ae2f..0282f197 100644 --- a/ioc/modules/nixos-integration.nix +++ b/ioc/modules/nixos-integration.nix @@ -103,7 +103,7 @@ in { serviceConfig = { ExecStart = let - procServ = "${pkgs.epnix.procServ}/bin/procServ"; + procServ = lib.getExe pkgs.epnix.procServ; arch = epnix.lib.toEpicsArch globalConfig.epnix.outputs.build.stdenv.hostPlatform; in '' ${procServ} ${lib.cli.toGNUCommandLineShell {} config.procServ.options} \ diff --git a/pkgs/epnix/tools/procServ/default.nix b/pkgs/epnix/tools/procServ/default.nix index f6cf65c2..4a6d35f9 100644 --- a/pkgs/epnix/tools/procServ/default.nix +++ b/pkgs/epnix/tools/procServ/default.nix @@ -27,6 +27,7 @@ stdenv.mkDerivation rec { meta = { description = "Wrapper to start arbitrary interactive commands in the background, with telnet or Unix domain socket access to stdin/stdout"; homepage = "https://github.com/ralphlange/procServ"; + mainProgram = "procServ"; license = lib.licenses.gpl3Plus; maintainers = with epnixLib.maintainers; [minijackson]; }; From c6335f76343435829b59401abbea4c56f6cd0d54 Mon Sep 17 00:00:00 2001 From: Minijackson Date: Fri, 26 Jul 2024 13:35:28 +0200 Subject: [PATCH 043/111] lewis: use meta.mainProgram See #62 --- pkgs/epnix/tools/lewis/default.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/pkgs/epnix/tools/lewis/default.nix b/pkgs/epnix/tools/lewis/default.nix index 1a67da55..3d20404d 100644 --- a/pkgs/epnix/tools/lewis/default.nix +++ b/pkgs/epnix/tools/lewis/default.nix @@ -49,6 +49,7 @@ buildPythonPackage rec { meta = with lib; { description = "Let's write intricate simulators"; homepage = "https://github.com/ess-dmsc/lewis"; + mainProgram = "lewis"; license = licenses.gpl3Only; maintainers = with maintainers; [minijackson]; }; From c5aea19699e12924bfb575059c83334890f7ab17 Mon Sep 17 00:00:00 2001 From: Minijackson Date: Fri, 26 Jul 2024 13:35:48 +0200 Subject: [PATCH 044/111] phoebus-archive-engine: use meta.mainProgram See #62 --- pkgs/epnix/tools/phoebus/archive-engine/default.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/pkgs/epnix/tools/phoebus/archive-engine/default.nix b/pkgs/epnix/tools/phoebus/archive-engine/default.nix index 413c7dbb..bf7a555a 100644 --- a/pkgs/epnix/tools/phoebus/archive-engine/default.nix +++ b/pkgs/epnix/tools/phoebus/archive-engine/default.nix @@ -50,6 +50,7 @@ in meta = { description = "Phoebus' RDB Archive Engine Service"; homepage = "https://control-system-studio.readthedocs.io/en/latest/services/archive-engine/doc/index.html"; + mainProgram = "phoebus-archive-engine"; license = lib.licenses.epl10; maintainers = with epnixLib.maintainers; [minijackson]; inherit (jdk.meta) platforms; From 3bd2ca9059770b7b0832f66f5adeb7374ae39bfa Mon Sep 17 00:00:00 2001 From: Minijackson Date: Fri, 26 Jul 2024 13:35:55 +0200 Subject: [PATCH 045/111] phoebus-client: use meta.mainProgram See #62 --- pkgs/epnix/tools/phoebus/client/default.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/pkgs/epnix/tools/phoebus/client/default.nix b/pkgs/epnix/tools/phoebus/client/default.nix index 631362df..5913b22c 100644 --- a/pkgs/epnix/tools/phoebus/client/default.nix +++ b/pkgs/epnix/tools/phoebus/client/default.nix @@ -104,6 +104,7 @@ in meta = { description = "Control System Studio's Phoebus client"; homepage = "https://control-system-studio.readthedocs.io/en/latest/index.html"; + mainProgram = "phoebus"; license = lib.licenses.epl10; maintainers = with epnixLib.maintainers; [minijackson]; inherit (jdk.meta) platforms; From 746ad8f9764ff1b147de528952732101d4de2b2e Mon Sep 17 00:00:00 2001 From: Minijackson Date: Fri, 26 Jul 2024 13:36:09 +0200 Subject: [PATCH 046/111] phoebus-pva: use meta.mainProgram See #62 --- pkgs/epnix/tools/phoebus/pva/default.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/pkgs/epnix/tools/phoebus/pva/default.nix b/pkgs/epnix/tools/phoebus/pva/default.nix index 939b100e..6857c9d8 100644 --- a/pkgs/epnix/tools/phoebus/pva/default.nix +++ b/pkgs/epnix/tools/phoebus/pva/default.nix @@ -50,6 +50,7 @@ in meta = { description = "Phoebus' PV Access client and server"; homepage = "https://github.com/ControlSystemStudio/phoebus/tree/master/core/pva"; + mainProgram = "phoebus-pva"; license = lib.licenses.epl10; maintainers = with epnixLib.maintainers; [minijackson]; inherit (jdk.meta) platforms; From 5dbbf2f48c5ed4b4c71ec406bc2ecc2782a12599 Mon Sep 17 00:00:00 2001 From: Minijackson Date: Fri, 26 Jul 2024 13:36:17 +0200 Subject: [PATCH 047/111] phoebus-scan-server: use meta.mainProgram See #62 --- pkgs/epnix/tools/phoebus/scan-server/default.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/pkgs/epnix/tools/phoebus/scan-server/default.nix b/pkgs/epnix/tools/phoebus/scan-server/default.nix index 8fa4e983..36d1508e 100644 --- a/pkgs/epnix/tools/phoebus/scan-server/default.nix +++ b/pkgs/epnix/tools/phoebus/scan-server/default.nix @@ -50,6 +50,7 @@ in meta = { description = "Simple, well tested, and robust set of predefined commands for use by Python users"; homepage = "https://epics.anl.gov/tech-talk/2022/msg01072.php"; + mainProgram = "phoebus-scan-server"; license = lib.licenses.epl10; maintainers = with epnixLib.maintainers; [minijackson]; inherit (jdk.meta) platforms; From 394901aa68b4d8ecd7da38c8fdca9a0cf6054a9e Mon Sep 17 00:00:00 2001 From: Minijackson Date: Mon, 29 Jul 2024 08:55:51 +0200 Subject: [PATCH 048/111] ioc/tests: init example-ioc test Tests that the example IOC generated by makeBaseApp.pl compiles, run, and is coherent. --- ioc/tests/default.nix | 1 + ioc/tests/example-ioc/default.nix | 69 +++++++++++++++++++++++++ ioc/tests/example-ioc/epnix.nix | 23 +++++++++ ioc/tests/example-ioc/example-top.patch | 21 ++++++++ 4 files changed, 114 insertions(+) create mode 100644 ioc/tests/example-ioc/default.nix create mode 100644 ioc/tests/example-ioc/epnix.nix create mode 100644 ioc/tests/example-ioc/example-top.patch diff --git a/ioc/tests/default.nix b/ioc/tests/default.nix index 4150e7d8..5ee713fb 100644 --- a/ioc/tests/default.nix +++ b/ioc/tests/default.nix @@ -3,6 +3,7 @@ with pkgs.lib; { default-ioc-epics-base-3 = import ./default-ioc "3" args; default-ioc-epics-base-7 = import ./default-ioc "7" args; + example-ioc = import ./example-ioc args; pyepics = import ./pyepics args; diff --git a/ioc/tests/example-ioc/default.nix b/ioc/tests/example-ioc/default.nix new file mode 100644 index 00000000..dcd711a5 --- /dev/null +++ b/ioc/tests/example-ioc/default.nix @@ -0,0 +1,69 @@ +{pkgs, ...}: let + inherit (pkgs) epnixLib; + inherit (pkgs.stdenv.hostPlatform) system; + + result = epnixLib.evalEpnixModules { + nixpkgsConfig.system = system; + epnixConfig.imports = [ + (import ./epnix.nix) + ]; + }; + + service = result.config.epnix.nixos.services.ioc.config; + + ioc = result.outputs.build; +in + pkgs.nixosTest { + name = "example-ioc"; + meta.maintainers = with epnixLib.maintainers; [minijackson]; + + nodes.machine = { + environment.systemPackages = [pkgs.epnix.epics-base]; + systemd.services.ioc = service; + }; + + testScript = '' + machine.wait_for_unit("default.target") + machine.wait_for_unit("ioc.service") + + def logs_has(content: str) -> None: + machine.wait_until_succeeds(f"journalctl --no-pager -u ioc.service | grep -F '{content}'") + + with subtest("wait until started"): + machine.wait_until_succeeds("caget -t epnix:aiExample") + + with subtest("EPICS revision is correct"): + logs_has("## EPICS R7") + + with subtest("ai/calc records"): + ai_example = int(machine.wait_until_succeeds("caget -t epnix:aiExample").strip()) + assert 0 <= ai_example <= 9 + + with subtest("version record"): + assert machine.succeed("caget -t epnix:simple:version").strip() == "EPNix" + + with subtest("aSub record"): + logs_has("Record epnix:aSubExample called myAsubInit") + logs_has("Record epnix:aSubExample called myAsubProcess") + + # Also needs the debug mode activated above + with subtest("sub record"): + logs_has("Record epnix:subExample called mySubInit") + machine.succeed("caput epnix:subExample 42") + logs_has("Record epnix:subExample called mySubProcess") + + with subtest("Sequencer program is running"): + logs_has("sncExample: Startup delay over") + logs_has("sncExample: Changing to") + + with subtest("Sequencer program is running"): + machine.succeed("echo 'hello world' | nc localhost 2000 -N") + logs_has("Hello world, from simple") + + # TODO: test QSRV, but it feels flaky, pvget times-out most of the time + ''; + + passthru = { + inherit ioc; + }; + } diff --git a/ioc/tests/example-ioc/epnix.nix b/ioc/tests/example-ioc/epnix.nix new file mode 100644 index 00000000..28911e17 --- /dev/null +++ b/ioc/tests/example-ioc/epnix.nix @@ -0,0 +1,23 @@ +{pkgs, ...}: { + epnix = { + meta.name = "checks-example-ioc"; + buildConfig.src = + pkgs.runCommand "example-top" { + nativeBuildInputs = [pkgs.epnix.epics-base]; + } '' + mkdir $out + cd $out + makeBaseApp.pl -u epnix -t example simple + makeBaseApp.pl -u epnix -t example -i -a linux-x86_64 -p simple Simple + ''; + + buildConfig.attrs.patches = [./example-top.patch]; + + support.modules = with pkgs.epnix.support; [seq]; + + nixos.services.ioc = { + app = "simple"; + ioc = "iocSimple"; + }; + }; +} diff --git a/ioc/tests/example-ioc/example-top.patch b/ioc/tests/example-ioc/example-top.patch new file mode 100644 index 00000000..95c2e9fb --- /dev/null +++ b/ioc/tests/example-ioc/example-top.patch @@ -0,0 +1,21 @@ +diff --git a/iocBoot/iocSimple/st.cmd b/iocBoot/iocSimple/st.cmd +index af59327..bc12277 100755 +--- a/iocBoot/iocSimple/st.cmd ++++ b/iocBoot/iocSimple/st.cmd +@@ -17,13 +17,13 @@ dbLoadRecords "db/simpleVersion.db", "user=epnix" + dbLoadRecords "db/dbSubExample.db", "user=epnix" + + #- Set this to see messages from mySub +-#-var mySubDebug 1 ++var mySubDebug 1 + + #- Run this to trace the stages of iocInit +-#-traceIocInit ++traceIocInit + + cd "${TOP}/iocBoot/${IOC}" + iocInit + + ## Start any sequence programs +-#seq sncExample, "user=epnix" ++seq sncExample, "user=epnix" From 4833ebd3e1fece559bd86db085a6da303b644b0c Mon Sep 17 00:00:00 2001 From: Minijackson Date: Mon, 29 Jul 2024 09:25:29 +0200 Subject: [PATCH 049/111] ioc/test/default-ioc: test IOC directly generated by makeBaseApp.pl --- ioc/tests/default-ioc/default-top-3.patch | 13 ++++++ ioc/tests/default-ioc/default-top-7.patch | 26 +++++++++++ ioc/tests/default-ioc/default.nix | 2 +- ioc/tests/default-ioc/epnix.nix | 28 ++++++++++++ .../{top/simpleApp/Db => }/simple.db | 0 ioc/tests/default-ioc/top/.gitignore | 29 ------------ ioc/tests/default-ioc/top/Makefile | 31 ------------- ioc/tests/default-ioc/top/configure/CONFIG | 45 ------------------- .../default-ioc/top/configure/CONFIG_SITE | 43 ------------------ ioc/tests/default-ioc/top/configure/Makefile | 8 ---- ioc/tests/default-ioc/top/configure/RELEASE | 42 ----------------- ioc/tests/default-ioc/top/configure/RULES | 6 --- ioc/tests/default-ioc/top/configure/RULES.ioc | 2 - .../default-ioc/top/configure/RULES_DIRS | 2 - ioc/tests/default-ioc/top/configure/RULES_TOP | 3 -- ioc/tests/default-ioc/top/epnix.nix | 13 ------ ioc/tests/default-ioc/top/iocBoot/Makefile | 6 --- .../top/iocBoot/iocsimple/Makefile | 5 --- .../default-ioc/top/iocBoot/iocsimple/st.cmd | 10 ----- .../default-ioc/top/simpleApp/Db/Makefile | 11 ----- ioc/tests/default-ioc/top/simpleApp/Makefile | 14 ------ .../default-ioc/top/simpleApp/src/Makefile | 29 ------------ .../top/simpleApp/src/simpleMain.cpp | 23 ---------- 23 files changed, 68 insertions(+), 323 deletions(-) create mode 100644 ioc/tests/default-ioc/default-top-3.patch create mode 100644 ioc/tests/default-ioc/default-top-7.patch create mode 100644 ioc/tests/default-ioc/epnix.nix rename ioc/tests/default-ioc/{top/simpleApp/Db => }/simple.db (100%) delete mode 100644 ioc/tests/default-ioc/top/.gitignore delete mode 100644 ioc/tests/default-ioc/top/Makefile delete mode 100644 ioc/tests/default-ioc/top/configure/CONFIG delete mode 100644 ioc/tests/default-ioc/top/configure/CONFIG_SITE delete mode 100644 ioc/tests/default-ioc/top/configure/Makefile delete mode 100644 ioc/tests/default-ioc/top/configure/RELEASE delete mode 100644 ioc/tests/default-ioc/top/configure/RULES delete mode 100644 ioc/tests/default-ioc/top/configure/RULES.ioc delete mode 100644 ioc/tests/default-ioc/top/configure/RULES_DIRS delete mode 100644 ioc/tests/default-ioc/top/configure/RULES_TOP delete mode 100644 ioc/tests/default-ioc/top/epnix.nix delete mode 100644 ioc/tests/default-ioc/top/iocBoot/Makefile delete mode 100644 ioc/tests/default-ioc/top/iocBoot/iocsimple/Makefile delete mode 100644 ioc/tests/default-ioc/top/iocBoot/iocsimple/st.cmd delete mode 100644 ioc/tests/default-ioc/top/simpleApp/Db/Makefile delete mode 100644 ioc/tests/default-ioc/top/simpleApp/Makefile delete mode 100644 ioc/tests/default-ioc/top/simpleApp/src/Makefile delete mode 100644 ioc/tests/default-ioc/top/simpleApp/src/simpleMain.cpp diff --git a/ioc/tests/default-ioc/default-top-3.patch b/ioc/tests/default-ioc/default-top-3.patch new file mode 100644 index 00000000..6a0c1449 --- /dev/null +++ b/ioc/tests/default-ioc/default-top-3.patch @@ -0,0 +1,13 @@ +diff --git a/simpleApp/Db/Makefile b/simpleApp/Db/Makefile +index 8eb9727..ea49598 100644 +--- a/simpleApp/Db/Makefile ++++ b/simpleApp/Db/Makefile +@@ -6,7 +6,7 @@ include $(TOP)/configure/CONFIG + #---------------------------------------------------- + # Create and install (or just install) into /db + # databases, templates, substitutions like this +-#DB += xxx.db ++DB += simple.db + + #---------------------------------------------------- + # If .db template is not named *.template add diff --git a/ioc/tests/default-ioc/default-top-7.patch b/ioc/tests/default-ioc/default-top-7.patch new file mode 100644 index 00000000..f767bb93 --- /dev/null +++ b/ioc/tests/default-ioc/default-top-7.patch @@ -0,0 +1,26 @@ +diff --git a/iocBoot/iocSimple/st.cmd b/iocBoot/iocSimple/st.cmd +index abda300..0d162ac 100644 +--- a/iocBoot/iocSimple/st.cmd ++++ b/iocBoot/iocSimple/st.cmd +@@ -10,7 +10,7 @@ dbLoadDatabase "../../dbd/simple.dbd" + simple_registerRecordDeviceDriver(pdbbase) + + ## Load record instances +-#dbLoadRecords("../../db/simple.db","user=epnix") ++dbLoadRecords("../../db/simple.db","user=epnix") + + iocInit() + +diff --git a/simpleApp/Db/Makefile b/simpleApp/Db/Makefile +index 8eb9727..ea49598 100644 +--- a/simpleApp/Db/Makefile ++++ b/simpleApp/Db/Makefile +@@ -6,7 +6,7 @@ include $(TOP)/configure/CONFIG + #---------------------------------------------------- + # Create and install (or just install) into /db + # databases, templates, substitutions like this +-#DB += xxx.db ++DB += simple.db + + #---------------------------------------------------- + # If .db template is not named *.template add diff --git a/ioc/tests/default-ioc/default.nix b/ioc/tests/default-ioc/default.nix index 0fd66191..08b80b0e 100644 --- a/ioc/tests/default-ioc/default.nix +++ b/ioc/tests/default-ioc/default.nix @@ -5,7 +5,7 @@ releaseBranch: {pkgs, ...}: let result = epnixLib.evalEpnixModules { nixpkgsConfig.system = system; epnixConfig.imports = [ - (import ./top/epnix.nix releaseBranch) + (import ./epnix.nix releaseBranch) ]; }; diff --git a/ioc/tests/default-ioc/epnix.nix b/ioc/tests/default-ioc/epnix.nix new file mode 100644 index 00000000..e1030646 --- /dev/null +++ b/ioc/tests/default-ioc/epnix.nix @@ -0,0 +1,28 @@ +releaseBranch: {pkgs, ...}: { + epnix = { + meta.name = "checks-default-ioc"; + buildConfig.src = + pkgs.runCommand "default-top" { + nativeBuildInputs = [pkgs.epnix.epics-base]; + } '' + mkdir $out + cd $out + makeBaseApp.pl -u epnix -t ioc simple + makeBaseApp.pl -u epnix -t ioc -i -a linux-x86_64 -p simple Simple + ''; + + buildConfig.attrs = { + patches = [./default-top-${releaseBranch}.patch]; + postPatch = '' + cp ${./simple.db} simpleApp/Db/simple.db + ''; + }; + + epics-base.releaseBranch = releaseBranch; + + nixos.services.ioc = { + app = "simple"; + ioc = "iocSimple"; + }; + }; +} diff --git a/ioc/tests/default-ioc/top/simpleApp/Db/simple.db b/ioc/tests/default-ioc/simple.db similarity index 100% rename from ioc/tests/default-ioc/top/simpleApp/Db/simple.db rename to ioc/tests/default-ioc/simple.db diff --git a/ioc/tests/default-ioc/top/.gitignore b/ioc/tests/default-ioc/top/.gitignore deleted file mode 100644 index 3d648caa..00000000 --- a/ioc/tests/default-ioc/top/.gitignore +++ /dev/null @@ -1,29 +0,0 @@ -# Install directories -/bin/ -/cfg/ -/db/ -/dbd/ -/html/ -/include/ -/lib/ -/templates/ - -# Local configuration files -/configure/*.local - -# iocBoot generated files -/iocBoot/*ioc*/cdCommands -/iocBoot/*ioc*/dllPath.bat -/iocBoot/*ioc*/envPaths -/iocBoot/*ioc*/relPaths.sh - -# Build directories -O.*/ - -# Common files created by other tools -/QtC-* -/.vscode/ -*.orig -*.log -.*.swp -.DS_Store diff --git a/ioc/tests/default-ioc/top/Makefile b/ioc/tests/default-ioc/top/Makefile deleted file mode 100644 index 19c9068d..00000000 --- a/ioc/tests/default-ioc/top/Makefile +++ /dev/null @@ -1,31 +0,0 @@ -# Makefile at top of application tree -TOP = . -include $(TOP)/configure/CONFIG - -# Directories to build, any order -DIRS += configure -DIRS += $(wildcard *Sup) -DIRS += $(wildcard *App) -DIRS += $(wildcard *Top) -DIRS += $(wildcard iocBoot) - -# The build order is controlled by these dependency rules: - -# All dirs except configure depend on configure -$(foreach dir, $(filter-out configure, $(DIRS)), \ - $(eval $(dir)_DEPEND_DIRS += configure)) - -# Any *App dirs depend on all *Sup dirs -$(foreach dir, $(filter %App, $(DIRS)), \ - $(eval $(dir)_DEPEND_DIRS += $(filter %Sup, $(DIRS)))) - -# Any *Top dirs depend on all *Sup and *App dirs -$(foreach dir, $(filter %Top, $(DIRS)), \ - $(eval $(dir)_DEPEND_DIRS += $(filter %Sup %App, $(DIRS)))) - -# iocBoot depends on all *App dirs -iocBoot_DEPEND_DIRS += $(filter %App,$(DIRS)) - -# Add any additional dependency rules here: - -include $(TOP)/configure/RULES_TOP diff --git a/ioc/tests/default-ioc/top/configure/CONFIG b/ioc/tests/default-ioc/top/configure/CONFIG deleted file mode 100644 index 34ace577..00000000 --- a/ioc/tests/default-ioc/top/configure/CONFIG +++ /dev/null @@ -1,45 +0,0 @@ -# CONFIG - Load build configuration data -# -# Do not make changes to this file! - -# Allow user to override where the build rules come from -RULES = $(EPICS_BASE) - -# RELEASE files point to other application tops -include $(TOP)/configure/RELEASE --include $(TOP)/configure/RELEASE.$(EPICS_HOST_ARCH).Common - -ifdef T_A - -include $(TOP)/configure/RELEASE.Common.$(T_A) - -include $(TOP)/configure/RELEASE.$(EPICS_HOST_ARCH).$(T_A) -endif - -# Check EPICS_BASE is set properly -ifneq (file,$(origin EPICS_BASE)) - $(error EPICS_BASE must be set in a configure/RELEASE file) -else - ifeq ($(wildcard $(EPICS_BASE)/configure/CONFIG_BASE),) - $(error EPICS_BASE does not point to an EPICS installation) - endif -endif - -CONFIG = $(RULES)/configure -include $(CONFIG)/CONFIG - -# Override the Base definition: -INSTALL_LOCATION = $(TOP) - -# CONFIG_SITE files contain local build configuration settings -include $(TOP)/configure/CONFIG_SITE - -# Host-arch specific settings --include $(TOP)/configure/CONFIG_SITE.$(EPICS_HOST_ARCH).Common - -ifdef T_A - # Target-arch specific settings - -include $(TOP)/configure/CONFIG_SITE.Common.$(T_A) - - # Host & target specific settings - -include $(TOP)/configure/CONFIG_SITE.$(EPICS_HOST_ARCH).$(T_A) -endif - diff --git a/ioc/tests/default-ioc/top/configure/CONFIG_SITE b/ioc/tests/default-ioc/top/configure/CONFIG_SITE deleted file mode 100644 index 212485eb..00000000 --- a/ioc/tests/default-ioc/top/configure/CONFIG_SITE +++ /dev/null @@ -1,43 +0,0 @@ -# CONFIG_SITE - -# Make any application-specific changes to the EPICS build -# configuration variables in this file. -# -# Host/target specific settings can be specified in files named -# CONFIG_SITE.$(EPICS_HOST_ARCH).Common -# CONFIG_SITE.Common.$(T_A) -# CONFIG_SITE.$(EPICS_HOST_ARCH).$(T_A) - -# CHECK_RELEASE controls the consistency checking of the support -# applications pointed to by the RELEASE* files. -# Normally CHECK_RELEASE should be set to YES. -# Set CHECK_RELEASE to NO to disable checking completely. -# Set CHECK_RELEASE to WARN to perform consistency checking but -# continue building even if conflicts are found. -CHECK_RELEASE = YES - -# Set this when you only want to compile this application -# for a subset of the cross-compiled target architectures -# that Base is built for. -#CROSS_COMPILER_TARGET_ARCHS = vxWorks-ppc32 - -# To install files into a location other than $(TOP) define -# INSTALL_LOCATION here. -#INSTALL_LOCATION= - -# Set this when the IOC and build host use different paths -# to the install location. This may be needed to boot from -# a Microsoft FTP server say, or on some NFS configurations. -#IOCS_APPL_TOP = - -# For application debugging purposes, override the HOST_OPT and/ -# or CROSS_OPT settings from base/configure/CONFIG_SITE -#HOST_OPT = NO -#CROSS_OPT = NO - -# These allow developers to override the CONFIG_SITE variable -# settings without having to modify the configure/CONFIG_SITE -# file itself. --include $(TOP)/../CONFIG_SITE.local --include $(TOP)/configure/CONFIG_SITE.local - diff --git a/ioc/tests/default-ioc/top/configure/Makefile b/ioc/tests/default-ioc/top/configure/Makefile deleted file mode 100644 index 92543094..00000000 --- a/ioc/tests/default-ioc/top/configure/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -TOP=.. - -include $(TOP)/configure/CONFIG - -TARGETS = $(CONFIG_TARGETS) -CONFIGS += $(subst ../,,$(wildcard $(CONFIG_INSTALLS))) - -include $(TOP)/configure/RULES diff --git a/ioc/tests/default-ioc/top/configure/RELEASE b/ioc/tests/default-ioc/top/configure/RELEASE deleted file mode 100644 index bbcffd23..00000000 --- a/ioc/tests/default-ioc/top/configure/RELEASE +++ /dev/null @@ -1,42 +0,0 @@ -# RELEASE - Location of external support modules -# -# IF YOU CHANGE ANY PATHS in this file or make API changes to -# any modules it refers to, you should do a "make rebuild" in -# this application's top level directory. -# -# The EPICS build process does not check dependencies against -# any files from outside the application, so it is safest to -# rebuild it completely if any modules it depends on change. -# -# Host- or target-specific settings can be given in files named -# RELEASE.$(EPICS_HOST_ARCH).Common -# RELEASE.Common.$(T_A) -# RELEASE.$(EPICS_HOST_ARCH).$(T_A) -# -# This file is parsed by both GNUmake and an EPICS Perl script, -# so it may ONLY contain definititions of paths to other support -# modules, variable definitions that are used in module paths, -# and include statements that pull in other RELEASE files. -# Variables may be used before their values have been set. -# Build variables that are NOT used in paths should be set in -# the CONFIG_SITE file. - -# Variables and paths to dependent modules: -#MODULES = /path/to/modules -#MYMODULE = $(MODULES)/my-module - -# If using the sequencer, point SNCSEQ at its top directory: -#SNCSEQ = $(MODULES)/seq-ver - -# EPICS_BASE should appear last so earlier modules can override stuff: -EPICS_BASE = /nix/store/gq8ysfw2yqwij1wd64vcc0nwy8p67vzx-epics-base-7.0.7 - -# Set RULES here if you want to use build rules from somewhere -# other than EPICS_BASE: -#RULES = $(MODULES)/build-rules - -# These lines allow developers to override these RELEASE settings -# without having to modify this file directly. --include $(TOP)/../RELEASE.local --include $(TOP)/../RELEASE.$(EPICS_HOST_ARCH).local --include $(TOP)/configure/RELEASE.local diff --git a/ioc/tests/default-ioc/top/configure/RULES b/ioc/tests/default-ioc/top/configure/RULES deleted file mode 100644 index 6d56e14e..00000000 --- a/ioc/tests/default-ioc/top/configure/RULES +++ /dev/null @@ -1,6 +0,0 @@ -# RULES - -include $(CONFIG)/RULES - -# Library should be rebuilt because LIBOBJS may have changed. -$(LIBNAME): ../Makefile diff --git a/ioc/tests/default-ioc/top/configure/RULES.ioc b/ioc/tests/default-ioc/top/configure/RULES.ioc deleted file mode 100644 index 901987c6..00000000 --- a/ioc/tests/default-ioc/top/configure/RULES.ioc +++ /dev/null @@ -1,2 +0,0 @@ -#RULES.ioc -include $(CONFIG)/RULES.ioc diff --git a/ioc/tests/default-ioc/top/configure/RULES_DIRS b/ioc/tests/default-ioc/top/configure/RULES_DIRS deleted file mode 100644 index 3ba269dc..00000000 --- a/ioc/tests/default-ioc/top/configure/RULES_DIRS +++ /dev/null @@ -1,2 +0,0 @@ -#RULES_DIRS -include $(CONFIG)/RULES_DIRS diff --git a/ioc/tests/default-ioc/top/configure/RULES_TOP b/ioc/tests/default-ioc/top/configure/RULES_TOP deleted file mode 100644 index d09d668d..00000000 --- a/ioc/tests/default-ioc/top/configure/RULES_TOP +++ /dev/null @@ -1,3 +0,0 @@ -#RULES_TOP -include $(CONFIG)/RULES_TOP - diff --git a/ioc/tests/default-ioc/top/epnix.nix b/ioc/tests/default-ioc/top/epnix.nix deleted file mode 100644 index 582e8ba8..00000000 --- a/ioc/tests/default-ioc/top/epnix.nix +++ /dev/null @@ -1,13 +0,0 @@ -releaseBranch: _: { - epnix = { - meta.name = "checks-default-ioc"; - buildConfig.src = ./.; - - epics-base.releaseBranch = releaseBranch; - - nixos.services.ioc = { - app = "simple"; - ioc = "iocsimple"; - }; - }; -} diff --git a/ioc/tests/default-ioc/top/iocBoot/Makefile b/ioc/tests/default-ioc/top/iocBoot/Makefile deleted file mode 100644 index 91e47d0b..00000000 --- a/ioc/tests/default-ioc/top/iocBoot/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -TOP = .. -include $(TOP)/configure/CONFIG -DIRS += $(wildcard *ioc*) -DIRS += $(wildcard as*) -include $(CONFIG)/RULES_DIRS - diff --git a/ioc/tests/default-ioc/top/iocBoot/iocsimple/Makefile b/ioc/tests/default-ioc/top/iocBoot/iocsimple/Makefile deleted file mode 100644 index e1b9aa4a..00000000 --- a/ioc/tests/default-ioc/top/iocBoot/iocsimple/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -TOP = ../.. -include $(TOP)/configure/CONFIG -ARCH = $(EPICS_HOST_ARCH) -TARGETS = envPaths -include $(TOP)/configure/RULES.ioc diff --git a/ioc/tests/default-ioc/top/iocBoot/iocsimple/st.cmd b/ioc/tests/default-ioc/top/iocBoot/iocsimple/st.cmd deleted file mode 100644 index 925f14f5..00000000 --- a/ioc/tests/default-ioc/top/iocBoot/iocsimple/st.cmd +++ /dev/null @@ -1,10 +0,0 @@ -#!../../bin/linux-x86_64/simple - -< envPaths - -dbLoadDatabase "../../dbd/simple.dbd" -simple_registerRecordDeviceDriver(pdbbase) - -dbLoadRecords("../../db/simple.db") - -iocInit() diff --git a/ioc/tests/default-ioc/top/simpleApp/Db/Makefile b/ioc/tests/default-ioc/top/simpleApp/Db/Makefile deleted file mode 100644 index 3717f9ef..00000000 --- a/ioc/tests/default-ioc/top/simpleApp/Db/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -TOP=../.. -include $(TOP)/configure/CONFIG -#---------------------------------------- -# ADD MACRO DEFINITIONS AFTER THIS LINE - -DB += simple.db - -include $(TOP)/configure/RULES -#---------------------------------------- -# ADD RULES AFTER THIS LINE - diff --git a/ioc/tests/default-ioc/top/simpleApp/Makefile b/ioc/tests/default-ioc/top/simpleApp/Makefile deleted file mode 100644 index 60ab8ae8..00000000 --- a/ioc/tests/default-ioc/top/simpleApp/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -# Makefile at top of application tree -TOP = .. -include $(TOP)/configure/CONFIG - -# Directories to be built, in any order. -# You can replace these wildcards with an explicit list -DIRS += $(wildcard src* *Src*) -DIRS += $(wildcard db* *Db*) - -# If the build order matters, add dependency rules like this, -# which specifies that xxxSrc must be built after src: -#xxxSrc_DEPEND_DIRS += src - -include $(TOP)/configure/RULES_DIRS diff --git a/ioc/tests/default-ioc/top/simpleApp/src/Makefile b/ioc/tests/default-ioc/top/simpleApp/src/Makefile deleted file mode 100644 index 483225ad..00000000 --- a/ioc/tests/default-ioc/top/simpleApp/src/Makefile +++ /dev/null @@ -1,29 +0,0 @@ -TOP=../.. - -include $(TOP)/configure/CONFIG -#---------------------------------------- -# ADD MACRO DEFINITIONS AFTER THIS LINE -#============================= - -PROD_IOC = simple -# simple.dbd will be created and installed -DBD += simple.dbd - -# simple.dbd will be made up from these files: -simple_DBD += base.dbd - -# simple_registerRecordDeviceDriver.cpp derives from simple.dbd -simple_SRCS += simple_registerRecordDeviceDriver.cpp - -# Build the main IOC entry point on workstation OSs. -simple_SRCS_DEFAULT += simpleMain.cpp - -# Finally link to the EPICS Base libraries -simple_LIBS += $(EPICS_BASE_IOC_LIBS) - -#=========================== - -include $(TOP)/configure/RULES -#---------------------------------------- -# ADD RULES AFTER THIS LINE - diff --git a/ioc/tests/default-ioc/top/simpleApp/src/simpleMain.cpp b/ioc/tests/default-ioc/top/simpleApp/src/simpleMain.cpp deleted file mode 100644 index e4e5e3b2..00000000 --- a/ioc/tests/default-ioc/top/simpleApp/src/simpleMain.cpp +++ /dev/null @@ -1,23 +0,0 @@ -/* simpleMain.cpp */ -/* Author: Marty Kraimer Date: 17MAR2000 */ - -#include -#include -#include -#include -#include - -#include "epicsExit.h" -#include "epicsThread.h" -#include "iocsh.h" - -int main(int argc,char *argv[]) -{ - if(argc>=2) { - iocsh(argv[1]); - epicsThreadSleep(.2); - } - iocsh(NULL); - epicsExit(0); - return(0); -} From 814bc72432fb017d421c1df757103e118e16b19c Mon Sep 17 00:00:00 2001 From: Minijackson Date: Mon, 29 Jul 2024 13:37:34 +0200 Subject: [PATCH 050/111] README: fix logo path --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7748fade..7ceaf210 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # EPNix -![](./doc/logo.svg) +![](./docs/logo.svg) EPNix (pronunciation: like you are high on mushrooms) packages EPICS-related software by using the [Nix] package manager. From 203de4bcb7a5561be2c3a991fe6c46aa3ae76675 Mon Sep 17 00:00:00 2001 From: Minijackson Date: Mon, 29 Jul 2024 13:37:59 +0200 Subject: [PATCH 051/111] README: fix documentation links --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 7ceaf210..a4f5ee8e 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ It's made of three parts: - NixOS modules The EPICS IOC framework lets you package, deploy, and test EPICS IOCs by using the Nix package manager, which provides several benefits. -For more information, see the [EPICS IOCs introduction]. +For more information, see the [EPICS IOC documentation]. EPNix also packages other EPICS-related tools, such as procServ, Phoebus, and so on. You can build them by using Nix, while having a strong guarantee that they work as-is. @@ -21,12 +21,12 @@ Note: providing a cache server that enables you to download dependencies pre-com EPNix also provides NixOS modules, which are instructions on how to configure various EPICS-related services on NixOS machines (for example the Phoebus alarm server). EPNix strives to have integration tests for each of those module. -For more information, see the [NixOS modules introduction]. +For more information, see the [NixOS services documentation]. [Nix]: https://nixos.org/guides/how-nix-works.html - [EPICS IOCs introduction]: https://epics-extensions.github.io/EPNix/ioc/introduction.html + [EPICS IOC documentation]: https://epics-extensions.github.io/EPNix/ioc/ [Packages list]: https://epics-extensions.github.io/EPNix/pkgs/packages.html - [NixOS modules introduction]: https://epics-extensions.github.io/EPNix/nixos/introduction.html + [NixOS services documentation]: https://epics-extensions.github.io/EPNix/nixos-services/ ## Getting started building IOCs From 851a2f468a386332e6b5306e845babf079345016 Mon Sep 17 00:00:00 2001 From: Minijackson Date: Mon, 29 Jul 2024 13:38:08 +0200 Subject: [PATCH 052/111] flake: fix documentation links of Nix template --- flake.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/flake.nix b/flake.nix index b7b8b19c..01763c2b 100644 --- a/flake.nix +++ b/flake.nix @@ -114,8 +114,8 @@ Useful links: - - EPNix IOC documentation: - - Getting Started: + - EPNix IOC documentation: + - EPNix IOC tutorials: ''; }; From b81357b63993502e41ab5e5e0dd428a7dfc7901d Mon Sep 17 00:00:00 2001 From: Minijackson Date: Mon, 29 Jul 2024 13:40:01 +0200 Subject: [PATCH 053/111] github: run jobs in pull_request_target This enables jobs to run even for new contributors, because the definition of the job will be from the base branch of the PR, instead of the PR's latest commit. So contributors can't modify the GitHub workflow and run whatever they want by just opening a PR. --- .github/workflows/editorconfig.yml | 4 ++-- .github/workflows/formatting.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/editorconfig.yml b/.github/workflows/editorconfig.yml index 73bb11e0..d5379ba5 100644 --- a/.github/workflows/editorconfig.yml +++ b/.github/workflows/editorconfig.yml @@ -3,8 +3,8 @@ name: "Check EditorConfig" permissions: read-all on: - push: - pull_request: + pull_request_target: + types: [opened, synchronize, reopened, edited] jobs: editorconfig: diff --git a/.github/workflows/formatting.yml b/.github/workflows/formatting.yml index bc9e9142..13cdb7ac 100644 --- a/.github/workflows/formatting.yml +++ b/.github/workflows/formatting.yml @@ -3,8 +3,8 @@ name: "Check Formatting" permissions: read-all on: - push: - pull_request: + pull_request_target: + types: [opened, synchronize, reopened, edited] jobs: alejandra: From af83f67e9b52fb3e41b23156129560b8c92d08f4 Mon Sep 17 00:00:00 2001 From: Minijackson Date: Mon, 29 Jul 2024 14:34:32 +0200 Subject: [PATCH 054/111] lib/documentation: remove epics-base from IOC packages list This would have caused issues with cross-referencing packages, because epics-base was in both the IOC packages list, and the "generic" Packages list --- lib/documentation.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/documentation.nix b/lib/documentation.nix index 0c169eea..34c1639d 100644 --- a/lib/documentation.nix +++ b/lib/documentation.nix @@ -6,7 +6,7 @@ isVisible = pkg: !(pkg.value.meta.hidden or false); isNotIocSpecific = base: pkg: (self.isVisible pkg) && base != "support."; - isIocSpecific = base: pkg: (self.isVisible pkg) && (pkg.value.pname == "epics-base" || base == "support."); + isIocSpecific = base: pkg: (self.isVisible pkg) && base == "support."; filteredPkgsList = filt: headingLevel: pkgs: lib.concatStringsSep From a12bda2fb47e8bab72d0954abecbe8da099d46b4 Mon Sep 17 00:00:00 2001 From: Minijackson Date: Mon, 29 Jul 2024 14:35:45 +0200 Subject: [PATCH 055/111] lib/documentation/markdown: remove unused function --- lib/documentation/markdown.nix | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/documentation/markdown.nix b/lib/documentation/markdown.nix index fe32167f..a98bd4aa 100644 --- a/lib/documentation/markdown.nix +++ b/lib/documentation/markdown.nix @@ -12,8 +12,6 @@ lib.fix (self: let then ''"${el}"'' else el; - # Add a suggested word break after each "." so that it is easier to read - wordBreakOption = loc: lib.concatStringsSep "." (map maybeQuote loc); optionName = loc: lib.concatStringsSep "." (map maybeQuote loc); isLiteral = value: From 7387668d1b5a58e3067786cb9d1f7bf9ee2c555d Mon Sep 17 00:00:00 2001 From: Minijackson Date: Mon, 29 Jul 2024 14:36:03 +0200 Subject: [PATCH 056/111] lib/documentation: add a way of referencing packages With RST, we can now do :ref:`pkg-support.mrfioc2` in the documentation to reference the mrfioc2 support module. --- lib/documentation.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/documentation.nix b/lib/documentation.nix index 34c1639d..1b30a844 100644 --- a/lib/documentation.nix +++ b/lib/documentation.nix @@ -79,6 +79,7 @@ package2pandoc = headingLevel: path: pkg: let header = lib.fixedWidthString headingLevel "#" ""; in '' + (pkg-${path})= ${header} ${pkg.pname or pkg.name} Path From 4ce3b556500ce5ee65880a9192435636b84727db Mon Sep 17 00:00:00 2001 From: Minijackson Date: Mon, 29 Jul 2024 14:36:47 +0200 Subject: [PATCH 057/111] support/mrfioc2: take description from mrfioc2's GitHub --- pkgs/epnix/support/mrfioc2/default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/epnix/support/mrfioc2/default.nix b/pkgs/epnix/support/mrfioc2/default.nix index a424cce0..5636ef2a 100644 --- a/pkgs/epnix/support/mrfioc2/default.nix +++ b/pkgs/epnix/support/mrfioc2/default.nix @@ -31,7 +31,7 @@ mkEpicsPackage rec { ''; meta = { - description = "Driver EPICS for MRF cards"; + description = "EPICS driver for Micro Research Finland event timing system devices"; homepage = "https://github.com/epics-modules/mrfioc2"; license = epnixLib.licenses.epics; maintainers = with epnixLib.maintainers; [agaget]; From bce974da2f746d6f2f8ba2452f2e976bb9698a9e Mon Sep 17 00:00:00 2001 From: Minijackson Date: Mon, 29 Jul 2024 14:38:10 +0200 Subject: [PATCH 058/111] docs/ioc: add guide for MRF devices --- docs/ioc/user-guides/index.rst | 1 + docs/ioc/user-guides/mrf-devices.rst | 46 ++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 docs/ioc/user-guides/mrf-devices.rst diff --git a/docs/ioc/user-guides/index.rst b/docs/ioc/user-guides/index.rst index 4069e853..70c488d2 100644 --- a/docs/ioc/user-guides/index.rst +++ b/docs/ioc/user-guides/index.rst @@ -13,6 +13,7 @@ User guides ./private-repo-setup.rst ./flake-registry.rst ./developing-modules.rst + ./mrf-devices.rst ./testing/packaging-python-scripts.rst .. TODO: make a NixOS test user-guide, diff --git a/docs/ioc/user-guides/mrf-devices.rst b/docs/ioc/user-guides/mrf-devices.rst new file mode 100644 index 00000000..e092d6dc --- /dev/null +++ b/docs/ioc/user-guides/mrf-devices.rst @@ -0,0 +1,46 @@ +Micro Research Finland timing devices +===================================== + +To control Micro Research Finland (MRF) devices, +we recommend using the :ref:`pkg-support.mrfioc2` EPICS module. + +Installing the ``mrfioc2`` EPICS support module +----------------------------------------------- + +To use the ``mrfioc2`` module in your EPNix IOC, +make sure to add the :ref:`pkg-support.mrfioc2` package in your support modules: + +.. code-block:: diff + :caption: :file:`flake.nix` + + # Add your support modules here: + # --- + - #support.modules = with pkgs.epnix.support; [ StreamDevice mySupportModule ]; + + support.modules = with pkgs.epnix.support; [ mrfioc2 ]; + +This makes sure that the ``mrfioc2`` is available during compilation. + +For developing your IOC using ``mrfioc2``, +follow the `mrfioc2 documentation`_. + +.. _mrfioc2 documentation: https://epics-modules.github.io/mrfioc2/ + +Installing the ``mrf`` kernel module +------------------------------------ + +To communicate with the MRF devices, +you also need to install and load the ``mrf`` kernel module. + +If you are using NixOS, +add this to the NixOS configuration of the board running the IOC: + +.. code-block:: nix + :caption: :file:`mrf.nix` + + { config, ... }: + { + # Install the MRF kernel module package + boot.extraModulePackages = with config.boot.kernelPackages; [ mrf ]; + # Load the "mrf" module at boot + boot.kernelModules = [ "mrf" ]; + } From 52387d62f91924ca580b16fff325a95267c05d07 Mon Sep 17 00:00:00 2001 From: Minijackson Date: Tue, 30 Jul 2024 10:07:51 +0200 Subject: [PATCH 059/111] docs/ioc: add unit testing user guide Document gtest first as a way to encourage people to use it, as gtest is more complete and well-known Still document epics-base based unit tests if people don't want / can't use the gtest support module --- docs/ioc/user-guides/index.rst | 7 +- docs/ioc/user-guides/testing/index.rst | 14 + docs/ioc/user-guides/testing/unit-testing.rst | 256 ++++++++++++++++++ 3 files changed, 273 insertions(+), 4 deletions(-) create mode 100644 docs/ioc/user-guides/testing/index.rst create mode 100644 docs/ioc/user-guides/testing/unit-testing.rst diff --git a/docs/ioc/user-guides/index.rst b/docs/ioc/user-guides/index.rst index 70c488d2..517fd5e7 100644 --- a/docs/ioc/user-guides/index.rst +++ b/docs/ioc/user-guides/index.rst @@ -8,13 +8,12 @@ User guides ---- .. toctree:: - :maxdepth: 1 + :titlesonly: ./private-repo-setup.rst ./flake-registry.rst ./developing-modules.rst ./mrf-devices.rst - ./testing/packaging-python-scripts.rst + ./testing/index.rst -.. TODO: make a NixOS test user-guide, - and add a toctree for testing-related guides there +.. TODO: make a NixOS test user-guide diff --git a/docs/ioc/user-guides/testing/index.rst b/docs/ioc/user-guides/testing/index.rst new file mode 100644 index 00000000..7ff77f89 --- /dev/null +++ b/docs/ioc/user-guides/testing/index.rst @@ -0,0 +1,14 @@ +Testing +======= + +`How-to guides`_ for users of the EPNix project wanting to test EPICS IOCs. + +.. _How-to guides: https://diataxis.fr/how-to-guides/ + +---- + +.. toctree:: + :titlesonly: + + ./unit-testing.rst + ./packaging-python-scripts.rst diff --git a/docs/ioc/user-guides/testing/unit-testing.rst b/docs/ioc/user-guides/testing/unit-testing.rst new file mode 100644 index 00000000..a6492723 --- /dev/null +++ b/docs/ioc/user-guides/testing/unit-testing.rst @@ -0,0 +1,256 @@ +Unit testing +============ + +This document is a user guide for adding unit tests +to your C and C++ functions. + +Using the gtest EPICS module +---------------------------- + +:ref:`pkg-support.gtest` is an EPICS module +that enables you to use `GoogleTest`_ as a framework for unit testing and mocking. + +The GoogleTest framework is a well-known framework for writing unit tests in C++. +You can test C functions using GoogleTest, +but the tests definitions must be in C++. + +.. _GoogleTest: https://google.github.io/googletest/ + +.. _is-library: + +Functions to test are in a library +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. note:: + Read this section if your top is an IOC. + + If the top you want to test already is a library / a support top, + you can skip this section. + +To test your C/C++ functions, +it's best to have a library +containing all the functions you want to test. +This makes it easier to have your functions both in your IOC and in your tests. + +For example, +if you have a :file:`myFunctions.cpp`, +don't add it to the sources of your IOC. +Instead, +create a library, +for example ``myLibrary``, +and add your :file:`myFunctions.cpp` to the sources of this library. + +Then, +link your IOC to ``myLibrary``. + +If you don't have a library, +change your :file:`src/Makefile` +so that it has these lines: + +.. code-block:: make + :caption: :file:`src/Makefile`: building a library + + LIBRARY += myLibrary + myLibrary_SRCS += myFunctions + # Libraries needed by 'myLibrary' + myLibrary_LIBS += Com + +Then make sure your IOC links with ``myLibrary``: + +.. code-block:: make + :caption: :file:`src/Makefile`: linking an IOC to a library + :emphasize-lines: 10-11 + + # ... + + #============================= + # Build the IOC application + + PROD_IOC += myIoc + + # ... + + # Link myIoc with myLibrary + myIoc_LIBS += myLibrary_LIBS + + +Adding gtest to the top +^^^^^^^^^^^^^^^^^^^^^^^ + +Add :ref:`pkg-support.gtest` to the build environment: + +.. code-block:: nix + :caption: :file:`flake.nix`: adding the ``gtest`` support module + :emphasize-lines: 5 + + # Add one of the supported modules here: + # --- + support.modules = with pkgs.epnix.support; [ + # other support modules... + gtest + ]; + + +Writing tests +^^^^^^^^^^^^^ + +To write your unit tests, +create a separate C++ file, +and follow the `GoogleTest documentation`_. + +Here is an example of a test: + +.. code-block:: cpp + :caption: :file:`myTest.cpp`: example ``gtest`` test definition + + #include + + #include "myLibrary.hpp" + + namespace { + class MyTest : public testing::Test { + protected: + MyTest() { /* Set-up work for each test */ } + ~MyTest() { /* Clean up work for each test */ } + }; + + TEST_F(MyTest, myTest1) + { + // Test something + EXPECT_EQ(2 + 2, 4) << "2 * 2 must be equal to 4"; + } + + TEST_F(MyTest, myTest2) + { + EXPECT_EQ(6 * 7, 42) << "6 * 7 must be equal to 42"; + } + + } // namespace + +.. _GoogleTest documentation: https://google.github.io/googletest/ + +Adding tests to the build +^^^^^^^^^^^^^^^^^^^^^^^^^ + +To add your tests to the build, +add these lines to your :file:`src/Makefile`: + +.. code-block:: make + :caption: :file:`src/Makefile`: adding ``gtest`` tests + + GTESTPROD_HOST += myTest + myTest_SRCS += myTest.cpp + myTest_LIBS += myLibrary + GTESTS += myTest + +.. _running-tests: + +Running the tests +^^^^^^^^^^^^^^^^^ + +To run the tests in your development shell, +run: + +.. code-block:: bash + + make runtests + +Running ``nix build`` also runs tests by default. + +To turn off tests inside the Nix build, +add this to your configuration: + +.. code-block:: nix + :caption: :file:`flake.nix`: turning tests off + :emphasize-lines: 4 + + # ... + # checks.imports = [./checks/simple.nix]; + + buildConfig.attrs.doCheck = false; + +Using the epics-base facility +----------------------------- + +epics-base provides the `epicsUnitTest.h`_ facility for declaring unit tests, +which can be useful if you don't want to import an external EPICS module. + +`epicsUnitTest.h`_ is made in C, +but tests can be written in either C or C++. + +.. _epicsUnitTest.h: https://github.com/epics-base/epics-base/blob/R7.0.8.1/modules/libcom/src/misc/epicsUnitTest.h + +Pre-requisites +^^^^^^^^^^^^^^ + +Examine gtest's :ref:`is-library`. + +Writing tests +^^^^^^^^^^^^^ + +To write epics-base unit tests, +make sure: + +- You include ``epicsUnitTest.h`` +- You include ``testMain.h`` + and use the ``MAIN`` macro + to define your main function +- Your main function starts with a :samp:`testPlan({n})`, + with *n* being the number of checks that your test will run +- Your main function returns ``testDone()`` +- You're using ``testOk``, ``testPass``, and ``testFail`` to add checks + +Here is an example test: + +.. code-block:: c + :caption: :file:`myTest.cpp`: example epics-base test definition + + #include + #include + + #include "myLibrary.hpp" + + static void succeed() + { + testPass("No issues succeeding"); + } + + static void checkAddition(int x) + { + testOk(x + x == 2 * x, "x + x must be equal to 2 * x"); + testOk(x + x + x == 3 * x, "x + x + x must be equal to 3 * x"); + } + + MAIN(myTest) + { + // 1 for succeed, + // 2 for checkAddition which is called 5 times + testPlan(1 + 5 * 2); + + succeed(); + + for(int i = 0; i < 5; ++i) { + checkAddition(i); + } + + return testDone(); + } + +Adding tests to the build +^^^^^^^^^^^^^^^^^^^^^^^^^ + +To add your tests to the build, +add these lines to your :file:`src/Makefile`: + +.. code-block:: make + :caption: :file:`src/Makefile`: adding epics-base tests + + TESTPROD_HOST += myTest + myTest_SRCS += myTest.cpp + myTest_LIBS += myLibrary + TESTSCRIPTS_HOST += myTest.t + +Running the tests +^^^^^^^^^^^^^^^^^ + +Examine gtest's :ref:`running-tests`. From 4047912cb47cf1cd3f74287243f4c078d80db01e Mon Sep 17 00:00:00 2001 From: Minijackson Date: Tue, 30 Jul 2024 10:09:58 +0200 Subject: [PATCH 060/111] ioc/common: make literal default value valid Nix code This fixes a warning when building documentation --- ioc/modules/common.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ioc/modules/common.nix b/ioc/modules/common.nix index 11838b6b..4954c92c 100644 --- a/ioc/modules/common.nix +++ b/ioc/modules/common.nix @@ -44,7 +44,7 @@ with lib; { `nixpkgs.overlays` option. ''; default = pkgs; - defaultText = literalExpression ""; + defaultText = literalExpression ""; readOnly = true; type = types.attrs; }; From cafd63380c9f8d0e1953eecf6c3805c3fe9cce2b Mon Sep 17 00:00:00 2001 From: Minijackson Date: Tue, 30 Jul 2024 10:11:27 +0200 Subject: [PATCH 061/111] nixos/arhiver-appliance: fix literal default value The quotes were missing, so the printed value was not valid Nix code. This fixes a warning when building documentation --- nixos/modules/archiver-appliance.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nixos/modules/archiver-appliance.nix b/nixos/modules/archiver-appliance.nix index 85407f00..6ba9db6f 100644 --- a/nixos/modules/archiver-appliance.nix +++ b/nixos/modules/archiver-appliance.nix @@ -167,7 +167,7 @@ in { ''; type = lib.types.path; default = "${cfg.package}/share/archappl/policies.py"; - defaultText = lib.literalExpression "\${cfg.package}/share/archappl/policies.py"; + defaultText = lib.literalExpression ''"''${cfg.package}/share/archappl/policies.py"''; }; ARCHAPPL_SHORT_TERM_FOLDER = lib.mkOption { From 808262314931f45b2f99db1151bacbb61de267ce Mon Sep 17 00:00:00 2001 From: Minijackson Date: Tue, 30 Jul 2024 15:49:12 +0200 Subject: [PATCH 062/111] docs: make copybutton not copy console prompts and outputs --- docs/conf.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/conf.py b/docs/conf.py index a56cfb77..852aff42 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -63,6 +63,12 @@ }, } +# -- Options for Sphinx Copybutton ------------------------------------------- +# https://sphinx-copybutton.readthedocs.io/en/latest/use.html + +# Exclude copying line numbers, prompts, and prompt outputs +copybutton_exclude = ".linenos, .gp, .go" + # -- Options for HTML output ------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output From 02fee0687de7e219eb17463664dc96b5889105cc Mon Sep 17 00:00:00 2001 From: Minijackson Date: Tue, 30 Jul 2024 15:50:06 +0200 Subject: [PATCH 063/111] templates/top: add timeout for first cagets Because the test is added by default, and run by default in GitLab CI, this means that by default the test will fail. With this change, the test fails in 10 seconds instead of 15 minutes, leaving more time for other jobs. --- templates/top/checks/simple.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/templates/top/checks/simple.nix b/templates/top/checks/simple.nix index 54a5948d..f511af04 100644 --- a/templates/top/checks/simple.nix +++ b/templates/top/checks/simple.nix @@ -22,8 +22,8 @@ pkgs.nixosTest { machine.wait_for_unit("default.target") machine.wait_for_unit("ioc.service") - machine.wait_until_succeeds("caget stringin") - machine.wait_until_succeeds("caget stringout") + machine.wait_until_succeeds("caget stringin", timeout=10) + machine.wait_until_succeeds("caget stringout", timeout=10) machine.fail("caget non-existing") with subtest("testing stringout"): From ed5d02d39ca5ef191514aa0c6ff4e8601aa82445 Mon Sep 17 00:00:00 2001 From: Minijackson Date: Tue, 30 Jul 2024 15:52:21 +0200 Subject: [PATCH 064/111] docs/ioc: adapt to default top template change --- docs/ioc/tutorials/streamdevice.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/ioc/tutorials/streamdevice.rst b/docs/ioc/tutorials/streamdevice.rst index 528a7c9e..d1a679b4 100644 --- a/docs/ioc/tutorials/streamdevice.rst +++ b/docs/ioc/tutorials/streamdevice.rst @@ -85,7 +85,7 @@ change yours like so: # Add one of the supported modules here: # --- - - #support.modules = with pkgs.epnix.support; [ StreamDevice ]; + - #support.modules = with pkgs.epnix.support; [ StreamDevice mySupportModule ]; + support.modules = with pkgs.epnix.support; [ StreamDevice ]; Then, From a5f45fa35bde9860cb102de2492a75650e77f503 Mon Sep 17 00:00:00 2001 From: Minijackson Date: Tue, 30 Jul 2024 15:53:02 +0200 Subject: [PATCH 065/111] docs/ioc: adapt to simulator changes The simulator was rewritten in Lewis, which changed its default port to 9999, and is now case-sensitive. --- docs/ioc/tutorials/streamdevice.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/ioc/tutorials/streamdevice.rst b/docs/ioc/tutorials/streamdevice.rst index d1a679b4..2fa2b38e 100644 --- a/docs/ioc/tutorials/streamdevice.rst +++ b/docs/ioc/tutorials/streamdevice.rst @@ -147,11 +147,11 @@ and what to expect in return. Terminator = LF; getVoltage { - out ":VOLT?"; in "%f"; + out ":volt?"; in "%f"; } setVoltage { - out ":VOLT %f"; + out ":volt %f"; @init { getVoltage; } } @@ -207,7 +207,7 @@ and how to connect to the remote power supply. # Where to find the protocol files epicsEnvSet("STREAM_PROTOCOL_PATH", "${TOP}/db") # The TCP/IP address of the power supply - drvAsynIPPortConfigure("PS1", "localhost:8727") + drvAsynIPPortConfigure("PS1", "localhost:9999") ## Load record instances dbLoadRecords("${TOP}/db/example.db", "PREFIX=, PORT=PS1") @@ -252,7 +252,7 @@ Then, run: ./st.cmd -You should see the IOC starting and connecting to ``localhost:8727``. +You should see the IOC starting and connecting to ``localhost:9999``. Recompiling with make --------------------- @@ -274,9 +274,9 @@ and open a direct connection to the simulator: .. code-block:: bash - nc localhost 8727 + nc localhost 9999 # or - telnet localhost 8727 + telnet localhost 9999 You can install the ``nc`` command through the ``netcat`` package, or you can install the ``telnet`` command through the ``telnet`` package, From a27299b57c303397adcaaa6eb0505a45bd63d294 Mon Sep 17 00:00:00 2001 From: Minijackson Date: Tue, 30 Jul 2024 15:53:46 +0200 Subject: [PATCH 066/111] docs/ioc: add tip for bash prompt in a result symlink --- docs/ioc/tutorials/streamdevice.rst | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/docs/ioc/tutorials/streamdevice.rst b/docs/ioc/tutorials/streamdevice.rst index 2fa2b38e..575084f9 100644 --- a/docs/ioc/tutorials/streamdevice.rst +++ b/docs/ioc/tutorials/streamdevice.rst @@ -254,6 +254,28 @@ Then, run: You should see the IOC starting and connecting to ``localhost:9999``. +.. tip:: + :file:`./result` is a symbolic link, + so if you made any changes to your IOC and re-ran ``nix build``, + a terminal window already in :file:`./result/iocBoot/iocExample` will still point to the old version. + + To run the new version, + either re-open a new window + and ``cd`` into the new :file:`./result/`, + or in the old location, + you can run: + + .. code-block:: console + + user@machine .../result/iocBoot/iocExample $ cd . + + For quickly re-running an IOC, + you can use this command: + + .. code-block:: console + + user@machine .../result/iocBoot/iocExample $ cd . ; ./st.cmd + Recompiling with make --------------------- From f7e96f106f3e764c4fd496b499665a57c68c061b Mon Sep 17 00:00:00 2001 From: Minijackson Date: Tue, 30 Jul 2024 15:54:17 +0200 Subject: [PATCH 067/111] docs/ioc: update VOLT-RB value after VOLT is set --- docs/ioc/tutorials/streamdevice.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/ioc/tutorials/streamdevice.rst b/docs/ioc/tutorials/streamdevice.rst index 575084f9..0898d7f1 100644 --- a/docs/ioc/tutorials/streamdevice.rst +++ b/docs/ioc/tutorials/streamdevice.rst @@ -160,7 +160,7 @@ That file specifies the name, type, and properties of the Process Variables (PV) that EPICS exposes over the network. It also specifies how they relate to the functions written in the protocol file. -.. code-block:: perl +.. code-block:: bash :caption: :file:`exampleApp/Db/example.db` record(ai, "${PREFIX}VOLT-RB") { @@ -171,6 +171,7 @@ It also specifies how they relate to the functions written in the protocol file. record(ao, "${PREFIX}VOLT") { field(DTYP, "stream") field(OUT, "@example.proto setVoltage ${PORT}") + field(FLNK, "${PREFIX}VOLT-RB") } Change ``exampleApp/Db/Makefile`` From b46224ce69fdbf2dfb8cbcbdcf01db7e692f34bd Mon Sep 17 00:00:00 2001 From: Minijackson Date: Tue, 30 Jul 2024 15:55:28 +0200 Subject: [PATCH 068/111] docs/ioc: expand Integration tests tutorial Renamed to "Adding integration tests to your IOC", because an "Integration tests" user guide is planned, and to make it a bit clearer that it is a continuation of the StreamDevice tutorial. Previously the tutorial was a mix between a guide and tutorial, not really guided enough. Now the tutorial builds upon the StreamDevice tutorial, and shows a complete path to have a fully functional integration test. Also introduce how to *run* tests, both non-interactively and interactively. Added a quick reference of useful Python test functions. The tutorial was also updated due to some changes in the default template, and some renamed options. --- .../imgs/integration-vm-ioc-screenshot.png | Bin 0 -> 10122 bytes .../integration-vm-simulator-screenshot.png | Bin 0 -> 11700 bytes docs/ioc/tutorials/integration-tests.rst | 488 +++++++++++++++--- 3 files changed, 412 insertions(+), 76 deletions(-) create mode 100644 docs/ioc/tutorials/imgs/integration-vm-ioc-screenshot.png create mode 100644 docs/ioc/tutorials/imgs/integration-vm-simulator-screenshot.png diff --git a/docs/ioc/tutorials/imgs/integration-vm-ioc-screenshot.png b/docs/ioc/tutorials/imgs/integration-vm-ioc-screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..a1948182cdc6a2e071f432d57ab89acafd998252 GIT binary patch literal 10122 zcmeHtRZyJ4^Wg5XcyIy)hu}^KZVL$^I0^0&+}&l7K!OH$NwDDVwh-KdI|R)Fi@V2GGbr)PRvX1-rBSmam$002ks{o9WK04nkmg%*s0L@^DM z14u;s>HS9~0KkU{0Dy)90Jq30=wAT9od*EeGX?-eQUL%`r_7cQV#o$ORYi3fB-VJ+ zC@Cp<($IK%dOFh7nMPItO%-I{f@7@~J|GL|ZgNU8=zr0vv9Vqho*Qce08Hv~Z>7|| z778wmQ2c9Mt0pmNWIz9xAoQ&9 z_(ZVtW=ZAvcRuH!q(dWorm*@-P^rjUCD5^^Wc6Lcoi+=48}_Ck2RAdUfP3}p_T?N{ z$iZ?0k?#p-*oPnW+jmrEEFD_(R)6fKaK?V5=v06TD%7#UGE{a+Rvb(;QCnnaboFM3 z{}@=6Bo~LZZ0pK#l{R*Ic(<>VTm|-%%l9z5B)*<%5Y)&nJOhp7*l4T_c{~!TJio4Z z%|DFDn>M3iD*Is7;gN9FSnZP@Pg32qC~y0=s3Eqqo~3pm*%l@bRS!Cn)2mhlwXHlx zcreio*02T<84tkoN!;cZiajzv-t3LdBukxUpStsx6xyS{e}0|qW(&i&0J*{2p*Fx< z-B(+QW%~p0Bd~*AiTnD0#)KJy<0hfyjFvLl3((qheY{b5StjSZf^~Fe>ns~ue6|qD&YAxPN}B%?HvZ0@ z4*?IRA)(d(Htr`(W!rvoA>8p!=Yc}7gMI?Yx^*2LSB8t%tO!j*V zc=(pmmdWcz7})L3qBWfjkbENx9qnsj=>6C#Q@kv#0&S3J?lh+YwbA+m!!&>%i%`v! z0(YQhcS0&3Nh~?gFgguTJD>>7J4hEWE+W-$1PPs1(vq^MaOqirbNou+M$4}H>0TB zpVP4o-_wWDB3B63JiiCyD$6Nc9(qX`Oe5_a>yf&9u@~}r^F#@_)4#+ax!xzK_4a%1 zv+jPx*JNIIawGil2RiEYiPqzb1$^VhG<1XO-D(zy zPBjzko>{Y0S7luv%Dyie(Eac^r%6G~+LBs5X#7)p06Xt}$qO82*x_wlBGI)_&}}o3 zB#&MBkr#nhdqhDLO`~3uzX6+M2Uo_XE%A60$Fd@H>e4~8FxtE+9UbIHZ3AJc?JOQS zy#+_^E4-$sVOEv6+CbkyB+n^~`c`V4C{B%VS1aQ2xf(qyFxhrEe%;93 zDFmwWYtCK{<>x5syn&IJ9v6mdj){BjtRd9dT-DwYlsxP93`%qvMmpF2=9K%-s+&N=Mp{SFF zaa1-N!E`=DnsG;ELsLtDth zU+@N3mqW7GrEfado?IL3s}Aja`FG8Wj&OVYx=d0_HmE`?1+{CQY z5V}ed2{0Nt5bm4-I3AiQwy(yzglof}TRQyF6rpE>T+FQ0ff7aGr_oaO`cnI!ckW)x z`#OHxH&X|Wq5sG$a}r<5Ptk4<8TUrt7d=crg^5-RzxTq&U(<6D{R$ug`Kd@y`?5?` zeot{m8WO z9oL&LDlUHqwJ#Irs~Hkw2ZiFao#~*G{ZfQ}S3|KW6Bk4n^&Y>0R(*~Qz7Plc?5jVr z598C?)v!Wl)*Fxm4)xU`&5gt(OLvCFuY#>AGdXylp)9>GlJfJJs`2~vjt`%TG1+LE zQ?&XLDY#NX#LM>Q`g#E^#EVsE{+|=AMs01Bfl0LodJRvm`&siFoQ1$pQR~8uEej`u zS&XVzFMAf`p`top7 zpz`;Gjqv43Hc>c+V#+9nlmb%@bbA@|mS`c@B;vp@d*F^dKCnCQ3m|0?iXG5(fc_SG z%t8fh_{CEXK)mR11)AzXeF=<=Oa$;bAEkbOI>Am(9cvlg;-~xx`lFM}i5xT%gd`E4 zuYNxv(1 zbjKBlqZ-A?-^vM17l_6U`K|sEHi1Yy9j>2Y1dGq6&ustDZ*rcy8K@NCU_r*lLRu4up)m;4CG{i z${J9#Ww>iE!NzB|3!RZ5yG1D7e8M!affYo&W@!6fgRa?xj3}4F;kWYpEOeO2-pL)I zNgYMhDO)p_N>0r;GE(Y!pK6Dey0$+X48 z_4qoqbWC{KTAysUSFI=HD6fFhS`&1DVK8EtTGd5iU?Djb-MPl8iRtQe{NU z_M7S?OZ3i`k>htiuhFpS)jePPmCse6c;WLK(C zZi?%JTWRZkQ9RKQ*}kXs8^0On+5wCNjv_-|P$=`uako-btM9Wtd>F^XOu#~KKL`!c zHw9iX931GLj0HAAE)_7I%MAG{n1*7qjf)9W8_4>`)5`o7lx-m@VGr>lJXK#yqfu>x zq69#^n0C=o#!#3`0=k(MLnw5t?*rz4>ZW1QlN_GjB77ppU+Y(o?0GotqleL zzDpgY56_3&8g3042SN(Y-}Qnv@xR2e~&f}|`JL_i#! z(=xz(b0bsT4{y#;8$DKkuzXnKNUEnvYrdU{gd`ENFnDH3xPiMF?iBV0`8 zFU(pP&2u)@A8k4ddRBA(ju~^p2y}2^TQ@TxtrR|bC(|_H|7K#(=Rj&b;}$i78^Z7P(Q`D z+4uR$8a{F`vafwpJh;k~B&d;8Ci;H=#o&v%643?aeg_k01|A!Y%H-zY5u#JI$juzr zePqB4esI6tDMusX-w05XKaCc|dCkvBtdM+*szBF6!E*EqgM%!#Zbx&=YP^IZ)aOW{TrN(Y*c7EhVh!hszJ^?*-D9t{ut>x$6r;TfWz zOeja(Zt#4xsMF8ObP%m8FQ6{&K4_YJVy~7~Y0G=Kq#4}0nfX}g@2!I~kHzD+fA0+( z5_xdeyhy;VF1xuvO_k<^oY)P;4K!}V=CRd&u`Nb(+dT;)ui}P0j3#zly=fH=dThM- z0x*A2!BlayWp}m=)~G?#jdlr_iE<5{a%f?)OHh$0<2x6l zD9rcw!H?K`*b};eixN?+=U}U%)%w;$7ciTbBuFobTnri@RmVrarrh-F z(UZsgv!}nF1o{3&YO&@gUg^=vll6D|cXD{heG3-`zA_dlH08%H9)Z`t^&E3{b+!y2 znjh=}L^qh;l z*$oD_Za2MKpA*<;4@Y8Goy7Gr6)@O+b%pbT#Da3{7d>BuIJyzerLzj~v$(bvdmiq6 zGGrOwM%A|PaO+LFxAWlId4yOKZn;d?g3AH!E~9redA(-mqX}DU{cdZqaQi9&~VF1XAodA!mvjpplzVRF=+; z{Cx`G5IotH9N+jmN$#xh_Hd%wGM4IO*2?&fvJ@i(L9j*#xpS_-P}PV4AVSsc6K!u6 z-kOOA8nZ*z&<-#sbSsNrBEQ`FecXW}lI!Q*VhUQPwcEpiHJfgauyu($iUhxLvH2Tb z6_cv-bjvJF-@f?E8IdN8cA^Je$tCs}GQ+-;dpkUu-(eJBAoZ7*w+q>UBb}Wp|2Rv-a9sgWmlqz2^@upLAQDnMdtJn-Qu>0Ko?92)M&uAP8(hS`#AjPjAc5? zn}_$wLR{obKU}}+`^Pxc2!$BVd+TYT$or}XU#KI*BjKjQAdnb(7I{@fkk)DuaY&^O zgZdDy6k`TJT-Q~{iO%}F#`y1NC=q_y46kPIB zH)=YzF91%qWVh$9Sr#0CVeg<7IDdbH-F9LegAWLEv3`aA2;uX@;z1A?BVz_A=t_hR z=bg-#5w1yFDq{_zQ=7s4X6<-R6! zn}N7ZhjJ-r%_>fQ|7N+at0+dZu+ooGryb;dpyKdu7nf-Y4dL(Ktn+Z!2MvTgGZJ!O)FLR6L~D22CDlU-uLa@3=P(?>T# zu{0A0`VFhwA%O8g?|Y~L@EzF8Wo!$5x(0sxosiZZM&v>+nY#r~|FJEEcwvG56`p*#2x26MNHI-eQ2`6%_ecwPK)8RWK0T7(8#tSmh`KlyN3AbIswKS@M z{K*D3sALSa51&KVwnhSA9LwtA2cxF5X$d@$setf}o&eY@qB441Q#yr3KQgmDhrfap z>)V+NcvkiL;(}SW+XsobOc2vv%2?Mspu#WO1x?+n=Liju-^E~<@a`oF(jOPg$^p$- zG?D)Z7SxuU<-fP|+`W1U`{e8(Y0TPsFaFaC9F;QdFrJ$M+7 z!zT~Ww##1`$y#sn9 zeA{&uBaDOf~K+1rkxEM?3CNerExG{^2dOGT~ zZ!1h*^*LIGWxX0hU_ZOOL%kpWlFXW7qusrJkZ&}*$_%zUNQUVbv1t>&HlJ_t9qJL6`cDC zO97=LY_Jo|ucKWKSXGTB1nW-bKrPM>Y4PZ+#6%VLiArFrMEM4j>p=Cz0 zlYZFmKn2cbm3mW5TzcBX9H3`j#tp&Fw0@A8WmrGk>8Md&b9>>(wO`O*dWStJ^}Zf} zE{v-s5y+9p^W!|&RYiOCE@)$Ke%Qs+q3{9TO!2W^X=Q3`-`uEjcH(>UDqN=`uELWG z7p9}^vo}(3k&GCCpYLvz3q1+JvqlPEM-69TBW=wHI=nB~{F6r2Vds!a*7upgKl@i8 zX2VzXke&mJ#S~t}`JD`{I6b+4JzWKpR>1 z6rD4$?jo&2rb`SLjQ;^DlCiA(;Jy>w>X5o_jv#)~Huys^shElbepAfVB^O|J$ss15 zb2N^mO!`1K-R}|$FwfQ`1&cm2Xk>(>ZAM#!eRDmxaTm)fy#>}2+Jl>x@W@7RXRuVC z5iN2q(m{N?i>9HZ)>wu!cwVsp%K*q6CLBvOkb@712A+4)kX#oBW!?bmU8u-`Ei`Xx z+80hIFeb)+>qAqT0O7;8KpCh8^IP&q-+O2?bm5NKIxC#}?xOF~qE>(D^Ulq%q4ddJ z(!;QDaDP)zC0Wd{4*1$N03t-}_xV2&usZksP=~vQCaq9!PjWcfRv^h8r4gr zrC;3u_fw%RnTw*>Nk=NCH%Zj?ho~wzUAfh0dG6AFx*GrqKoO4NkPi3@&9TxSb}&-2 zLbT|YC=KvaVr%{LKa7I;HU7)LA8|`jxmt~eL{T#qZFh3av3P__wZHwzR&MLEb!0BM82j;=DQTJDNm}x;iwsmU^rb-_rTE z#6{q-!(sJ?q1k$S7SzBAn|hWg5xa?WCl3)k{ly${nruarL63`bjTPLCG*pYb(g*)Y zZ_CouG@O#N&BB+YTwNGdS}4>#cq})HQ+;n-EW$hRxLddF1C#O?5%{@lIm3dLdIL*I zYo3#Pr&%;co%gHu4~?8KkH8%VosrfWcTR&~f^~Y?OO${&P-iB> z@}HS93ZC96fK4u-Pl4vfMgPn-cI8Oi12jPNW_)+;_Snqm3R`tZH>H-unE9wCZhHx1 zf=bq1vZ^j*6AFk$pw}TfCf_xS+6{)M&`5k*x;e37%^UY4DXL^Gy1L@rEr*{ClHXU) zJJ;b=!22jdb9P-MozC4j#^@n!fsR;4?8w!F0flR5Cbnm;0BE%mH|J`G-^o2ohxkJg zt8qIwo0gO|xCiKE7GokWBCFbtw;XLG=FVJ}K<9kljuprLpqDuk$Lda|HKqUBBe9G9 ziNEgXtS_1S8hD?;(B5CU$`vYWdI~>~t@EFE4gBzj2$_gfcXTeOBlM&k#bg-BB*#|ch$X?Xt^J$o_atA zvs#!x|N3gGp8+uWxjr;!09hRg(ziizz)(eKU>plkF5qd`1CK~@zYH`2Q$C$qFR%e) zo~9esyYXDjB#n>ZdCLsb`oaF-n{d<9!4=PtTUYtZ!7l8+Ej4x zFCv=}w!R7n$o|XoOTYKMIP52)z3I#}_*C1S{s!oYKYC;gtxpW*=^Xa;rIZ_BI3ec^ zGrNqE zk9A7gehlF3Tpz(Z($Ckqqgg8+Ai_7ZDlP6o_Al`}8I>rnA-T$UT_kC(Zmm5cM3xX=5M&azpQ%vc5G;eammm2oX0f zj{c!rZUK5$4tUcf3!P$YB*;aKkM);!-o0@$lU&zj-dX}Z^SB8}2b9O~1NR>BjeC*n zX#0!D#blKmW=Jt11~m__HA!98XSq?gU*5U=-GDQXF>!+qFS3`NksuUj8+wk(kqDKsT65pYnqV4QvZ*$kvYRqZ6#lhR@dQSE)f&6cW@h4MF7nC69Ekw0cwW8ckXnrf{88kqj*VLxP*Ny}7HKiM`YR&hzT^e}rh4dHvUG OC^;GBw-wUH!T$|TRcxvN literal 0 HcmV?d00001 diff --git a/docs/ioc/tutorials/imgs/integration-vm-simulator-screenshot.png b/docs/ioc/tutorials/imgs/integration-vm-simulator-screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..8e0ebcf93bf711925cb1c2b0f07242df0165b658 GIT binary patch literal 11700 zcmeHtXH*mKw{8+jC_+$a0ulw4UPPrsC;}qV1nE_zm(V*QNK;TydM6e{dhacOfE4L9 z1PHws=`G~u_y6B>*E;LoyVm)3zMS{Vo_A*U?Ad$v%slUY_IoW26&flQDgXdLqx$UW zO8|h3xJhz{l!Pc^s)v6Q#T~0>FVz76{|5j7G7JDXC+CG0XOzV2{MQD~T0939ycyZD2nen(6*$cvvA>##EF0jW$#okD)-2~^=j_58s)7Tl zR{8h|8Gs4F#+$wCC6s%C8Sj1QX2auuuC@eg^m=4s-MG|Za&E}J)7jU*`~=WsT>A>p zl+Bp-l+00LSQEt$VMJUaHNO-Xt*~t9I^M4<%DTdAA9+$`6S5q+uV??(ZtLsH()DBM zr!GZA=Sx;CUJ7LK?&+*MB#mV2#p54ZW`?ggik$^Y>T7xoK48>0w*R;`db|p!w`Q2~ zr(q_2#&DW?$k5A=9$7E3vt^8PN+%Hq{$SB?koU>XbnKEyDA_S_PQAAyVW$7hVbTn# z8vf8zXye=}}OCW-`%;7UQd@1|Qa-crcKF~RiR#(?UAcqF0W#eH-M5{r}1s0?*|G+Gf)IrrhP=fC#A{(V-U$bG`) zTmqPt6)!t*xHZ~7{b;j*DV5NCAHDyt+31Abq8%$J%#pk9`}(S=RAP1uEPJ2^E0TD2 z(KmXWm<@5xrqF83BqY8C%~K)5;s?ei3=tK-R|x$top_}-U6O1VX8p3+0%*-o{)7Nx zbbeIq+4#M3dk;_xIG?;>p^S9pv;`(TrbCfV(px;IpmSN^1!87y0o$BY00YCADRMR{ z*MeAb3o^gcl<5##x5NiZe)$5&-}x>MCo3LU&pl-sGX6%j#b03IqPX-NzYS zo$Lk^WTa^JC@(LVS_p8urIv$Z!a_9xZ_Lj3B6Qa>t2NQ}K$J-%#&V|>vNE@SL6Efk zgJIS4B_Kp0PYuZDLQD19avo>Jeq!2}O$h-Iyc~?}G{vOlknE(VWS0dsBOXOQL@SrO z`~`&mIYPno0LR4{|9m4LxNX3E`0!R zQSF(yjrpnE)fhO6w*qSYO8!be{8fiI%(ahDCA?#i2egi1PW@?jWfG-saxdO!fz>RUw2Z)>r%L&$74LqC_9op# zZIx7+y6;y=YV`tq`eL@R1`I4ZEcK{_Z37F#n^e9*7{h=E z_?&Ad?@#^QRcEe+n5F;U`RA`W5VZg=dTEAyZeNaY3DSR_?`*7Nqp$R7+e~d|bR=M& z@hU?jI8thFp%s1ygx%~&$ND^kt~sazRIUSejuyIoO9~mB9J}3wBKQVbgmX>J8mD&M z*$@7hA-JxQC) z1e*Oe|qZc=3C| z8cYkATi_<`nwurl&kX#62zD&hS>@-}_*$?p1K~1}Amt&Cw6&*^clgw&TLr+%QL3yUkX zr+rIbv1@^TSq^?+JwXFj(*uLm{5fc;@a>--?j{w7!lo!RVO{e!Y!rLmqjrPJew&l< zMzWF}c*XTIKhW}p-4)s&dye?HsbSUuow}4ElprMkEaXjV2nH}lYK}CE)8YQCnFKqN z>on~NqBpL*3(`7tDiyFPuu`X;BP*n!Te zAGh!XIraw1RC>Y9U#6}nPG+Ue712x(9;!N_{&Ay%ce$+*i)auGK zDj$UaUB^<*H{sqY>2>nz2hh%4_FpnyH1ZEQbag^Ky=`xs z#p7ABjp@3C2zTbE>0Z;)G<7d5QZ6wJ=2Q$HljSLb+@=*i&4?2GA^{z1T2k@psJ7Gh zVhV4#I+=f*o??8<2H<68YjZ;IcTa8ACa<@|N@p+yW+sDPRPENOsTW|PuEm_?_hSWh z@k?>HvXZ-ZG!rr``@-(hnsT; z$qTJI1V5C>d~4FghkHns=J43_BjgQF8S-0%a_-1Yh^9NX9Ds%7Qmr@XGdUbV^dupb zxJyN(?=>B@(8=-@Pl;>`8Xa|NmOP5m1hxWkM+hz1T3GQ_+gm{P+u1Dz8oP{PIb`*t zG1l#BK*wS(C}FXRe6*zBec9om4|;(y!(^f1b^(a~ixiO20liwvD_6xiBah76x?!PO zcEq(lO^=$)Z_4!NL9-pc2bf3BlGx7N@tX}E7Dc@)2!iQ|6;YRxO;3|wn-T7=x9lTq z)LTjdV`i!Ut|}pgdR}LmZ&MWigzRVr+$@w~(AQWWWq+!R+{l))C*x*sIR||T*m#v~ zS+KpLu{b`P{@pa?6|$ML{)}>2%^5Md+NLDDs4+LagwF0{;(sb@qSgUfrwv9$Ky___siOlD+RRK3ay zUBk+uA`+*SZEC9;#a<`zy-{Vp851bt6>s=seD$A0d;PYs)ma6kB(7v<;LXkRgnI`Y z@4H-rG+?9@v@q)N9{@ELs#4jMTBa~bpkS^pQKgn!j&SGU4U63+MWkz(GcbvWj!syM ztARp&>tIya*~#~qd?BY_??a>fcekF2+2Z_qizVi{;3H(d?{#)UY#4!su& zNLN;BV2^Ob&Ex~Ro`+3=Cse@w2msw=^J-D2dBYMwQ?gFvC` z!^FaN#);8GOHY4VA8NA_C7{1DsL$s2u-p77rIus&@f5XdmLeUnjolyUpB}`h?ge_$ z1W>eiatM=h+@p1>1Tulxs)^2F6}aT)I$jsGaLYkEHK(KkfNHDvNhjZYzooNj}%M@jK>0a&?ZkRzAGdO;dc%9l% zNyjJadRdiMh}R(}HckmCu02oT95gqq7jodj{3I(1U@QgK?w*o07GkzwiXTO6>!meh z+BO1m?O!4FXgK61ql;Zq(`RJ6GHq!oJ}n#0GjqsQVc?a(0HC)s`nydKDMf%ihuPIFWe>FiDoH%kiN*P@iGQ5 zA5usqT*&kRFfYI6k1hZ`4mOuZy23X?Rmxg&0<=xd9>aG(-jO>cqq`-|u+_Ksbj^{R zc$=pjn1#2N_kNuLt*NS?vR-GGzfBpF`A5W3duG6ZLi!UlRlr7hFYX}T2Y|h8IO4nx zHX)k%LF!6Gy3{b-_f7Px5s;$$9);(P(OC#LXzK+vz{mQY9Kkg6kw;ZZi3Ay1^62iH z83;4!Z{LSlR>Lu$It#C%I>H-Td!j?ZeULTLM1JbgXSs)?B|O*uci;d__G&^~HY^>V zyM%_%oJHJ4BoW)pr-8pnYA=u?AC}4i_XkI(QtQmgcQMeOZe{674l>0qE#UC zc}XiL-$m9cS)pE`qzX#xduQrRBXKv?-u*($umD~Te>`mOatM^j1PwDK{e268GUdo{b;4B7YV{K>nS=TEEYEHYC~;ITzF zDpFrAQyPRV#;lVW1k!NZ+HJDH)78=7<^;DH#gC*dzYH8kpY5rA*g+gd z0nkheBakdAP*^SpKE(N*^TVg()Sex?`VFtJ?hwD(wd14D)remn;zu_aYvv+0&ubH3 zuOH=&uhX{wW%Ls7giz5e)E2W1_ee)qrT0)ZJ&;?q%h)n_6maV4{XV6qnUdf8RP>^} zRy1p|mTA;_(&^~?6Wk|`@B*P)W1Mwv1*NbNjTG>_MbITW$5Z9kKsA+}uA%q?+UOFS z3oVIzo1W%RU-EY`z9c7)BCGK0!xRga@!gkt6AAbDzU#Okp;2m020YH|=Hu$qbMUsW zA!F9uHH(KnD6Xx&=zelSF}UmHx8+>#r-bb4l^>Sq@h&@UgM7bx}Pg zGfe16{A&_&6ZK)F=VWSxOF4X2NZe~y?z3W3?)XfjfnTnKj;%ZmLbHC1Ah{q&`UK95oujt+%!?Jl9J7kZ= zEls#HvKp($>xRbjg&H+K!7t1mHV+sH1_Y+}me&eqrIQ-8VOn{=p0)4_?=n?-MP`Z( z-eP)tR#5Z`yH(0F`__7P12Jk)RB7*?)t+bAV53@HcP;(JRFWGyy9`2#bIPuFP z5zzbLiRht&ed{Lnp?`l;ke{pldE&0e`E$Kkb-UFyi8qCYeUu!;&wtQbsfS;HlGoN~ z&=H5@?J>c3qON1a>Wt6XL2wXTSML`)GbQB9-pxOi_x^-3)Z>vywTzMMe16Gi0p+*U zu(8?$kGq}(Yf?`Px7F0?F{&)q<&lp@K5DT0f*X5*!-t=9KEtfs%w%xudUF$XUg}L% z`t;F+0`iAl(;auWz?H4^o2XuMXTic>Za>*F03)N6!a3Y>_N~qo!UAM#BNNnGR!QZW zJlp%u#R(nrzB@c}MP!w9>dwu$<&x@pqg&D6;~Kcl1m_t8HGvTegStYbYX`PRBO)kIfbV~&yM>1nNbv+Oe1gc7DlnQAp;s&(^|+1WBvyH0vf z?>QGIca-_MFrxfHItP^fW3GQzE@v*t(p$8uC*Jba2}H!Njz2qKujW!aq37TJaxjt} zW^bl+hOatS`pC)k-Z=Z^j7daZj(orVk~>pSX%FL%73~8Zhri2-;xS2~8H$au$JLhc zk&jg|ZuRO1@L4qi`TS^)I=g?M5&qXfGk<*VViMe=i9e>pBOL&Z$^6Z-%svPFE>JL* zQmlHsSRuKQxP?LOzzJvW=Xkfpz!|>SmIu*uQabdL_kl@b^cHqPH2u+lY~LTkzogSj zI(?36jJN$w*7JD@LvY};w2OJqO(TJsh|u>`I()g&+3@+3*_2b6Jd$g2NLTRly6XO? zMCrn4@mVmXd3%ibtsy*tGR73et`(DIeYYBKd^1JMj;9L@bPSz|K0J<0+?#;4{;nQ> zB*LBUX40OE%3S`wyd7mZPyIrqu+EN4sP_+p{Kp^HYJ{Xy1NIp~{IClv7bXj%buE)% z15;9CPuT>?467UqPD|O)s$dDo!XekRxLdMp3y&|=a)x_IWvFD)C7{!d=FbnQ-tJXH z2qhbTF*-X%xv0WLa4Y?--z&LefC>EQ)aNtmDS4Kg#p z>VjFPBmPofUcPYVZQ_kv7}(t}R7}^2 zb{2uye0Ch(zZdG*(9^x@+#}kvpq$CrlHqq!6(RTWMP$+8g$vY#X9Iqa1vAHqp05Pj zR^i&Kg=3`89xiAkbjNdhcwZ0B7>?Gf%*>aT2W<2o`D7F+RtH|(ll1$CyV4-OQ zqTc&PDZkeeeaV=UXnHGAhd;8(??5OowN7;XSc&HJ=8+eO{`rJ~%tB~`JaQxDv$N9G z^O-lr%zTq+NnT1N^ut*xW z^(zGEP%8Oli(1g3-Y8N1!HA~I)~bOL90DQ%MKnJJ%oFC`-!%1<*&6bcc5nV=iIsgcvZ!(O zv$2T?VWs4e|A7Smlib@`t5mHE@;bnuoyh3;cDU3jmp&~!GW(qU?u&Yc&RmxF22L+*8IrAx!riLLcqbu+Y1T6}L9@jW0M~U3v6G(t6lxFrU;o~Q*N%01FOUcf zS*9})KlJg~!rN`dT1_MX)pJp<^&Vsix+u`@*nx6D-Wp@8c zD$Mk=r@`pON2q#6t&o^S#Cc=i8vlL*tUpt4|Db(TT390&v@=PM8ujnccM+XYzPN2- z0;*hlYRp5iH$_JK*%YMv*?`rx2Jq@Rv4}gP_&Xn<dN+;}Ba2(l8>07(4rBy-T$fL^Ynuau;`U?2*?YYZXzetibD$!6 z=is&YWJx$H{w+pbpg$R#yDfK~TRkSQ#qa3G&xqNS1?w11$_j>c9LJF_SLq!XQY6vRE@*eEv>-CC$4?IHs+`6^AG-{DQu?(O%>_ep99ZvH)nju#ug}I;ub~Glp z{;uOA>X|LX_FtO#JSv^~+jBOS zRa#*FfMQQghsS!Fj69+Xk5m)un~ZryW?eNV2s7t1sT=YK_J|T(Z_IH@BwblB=>RcN ziPZuE}+H=zRLP9W*+jOib=E&^2dVCTP?>h!Z$F4XMSDWA_j80Hy(X zYS~O5o6X%H<0DBYi$bQ^oel$=X;O+_G!h2WIA1EB@9%?5I@b?`vbw7ltyl;9t4@e! zTb97mE2|#Pj09zDU~}~YR|Z8jW4CjOxGTeqjaN=?sw$r4xotx%wI0J2nFD7uYP};1 z0@5{%rAvN>W;*O0c^u=r+jE$|FBx_C=VT_fzWMfejG39`H}(YAEbnUTRYg<{qy29DhUE#Cj zOmdw!B;E1hXRa_5D+Oj7Y|^;2b0ESEPOr0BW+_b6_W7tB87|$z6tvPj0$Eeu_r3r! zae}`!)^3Z?*Z9-uQ6H28g0kkWT_V+pya~yVvBqb$5-=CG0EgxK?9GTB#VQYVZ+6)E zg7fRvMW6Yu{Wct!e<$E$a5hvcQzo==GNqj7^{mNK*J77dkyB^0B5PMQ)M8kqLgX3r z4*D<$fxc56gpk93zP4Y^i{>|LeIO@xV(EHrhbY`qQ0KS)y94?KnUqL=CEmpPK;RPT zt_EGURzvFTl8ubNM9#C^{}{}T_Guzp1UD)mgFF`E0PTttpldiVmJgi+b>$P{1dhX- z09I2UFv$DgXQ&60J>2|)IQK}B)~2P1XZ1wiUZfxDu@e-sr}nmfR3|MY^Y(m+-_PB? zFYbq!4ldMh9lA7P$~kfTquDdBnUQ`>(h7phGVd4(me?hkt@Kj<#u%`J!deqKD4fk6 zNyMUgCuFVWqI?LLaeMia9S1h?lyr>zYvI}IvuSU8d`BqMU3>|AIITGKEKYW1ofc;C zmooKR5D8CWL@8^4O{5T9KCYWE#d1ll!5;%fB_h|dTe zPcTTMc^tb7L7)ed3flSy_DIH;swKcP$FYoe5a=7R`tye_DTl5wT;O!S$a4CeEFCTv z`}Qx1*AnyL!vk zY4{h_-(qR3f76mvX4cD!hD=gnNoz+Sb~OPN`l{?vy^i9D4qc0~UuTxe5oGr6A39g= z7i#v7rcudeENMnQtN1=0^U-Q0uD{;AeSE(HAVw`5lnWi4vpqfsE~_lzgPz2a0F(4I zw-_v#WLX%aavB))-C!tL0i)?N*XG6}$s>@bU+G+M0qd6h_K!NMza%{ZGUMLS;P|A8 zG-Tmw;(mpZO0bkEP0H|Hp!Ylz$n$Sxz|)^VJk5_^ME&>@?rJjbPDt+}oI>l>{InLB z^yidjexd#W3HuF{)NTaeKoD3T`KgA^BKp)4bg2hJDVOr1%b>zkgZn7!Qach%86F$5 zD2fu&5ke;ojEP$CYo{ft+EOhcm}00KStdzDirbk04Km`m*DYfgc-Jbu8PW0F~3^kdnp zcK{VttfAo_<|P>x>ZH(&yTEZ2y=HYHbjNr(nXJ5Do2 zDRVkhjLWIV(&zx}Cp$Ws9>;VJ3`G}cd7lB50x>4suTY{QJ8hfHMbPHH^U(5#7;M)5SKK#J2EM>B3%;8~-lOP*UZdHp&!mWtMP(kz|@x3SpsR!VZMi9;IFCFgn0%(D3 zvl}(4yET0N8M615a{xyt{1{H_>sFG8ubX}>` zB@Fg~cTC*n*;hagxv5!f2w>!RZsIyBzpdsAaqSf?kymck4e>QV4rkq_&`M*SpwikO zrXGwIq!^52-uI{gJlQvA#EG2)Pbgj2!MYD02VBYmT}}@xX=)Cq&s=z?9yDz>^~dB zBdrbk&%XvRdBzV1G56nR21EVlQ0lLSU#IruE0604Ge=Dyj}%etar1!^Ha6W5azdRN zNTFRYe>+r3RfKIKd6}FVC^+(Xy~tVGlgqjgq#JOo0W@0$JH7wCy8*`Dz-^uZHznMq z`jyqsCCIJsDK>?gR#-hISTH;D?xdaFRTnd>6Bc+Dg!)2DGiSOA)(vUOgAP^!J^pSd z@+Kr7kT^{9c1c(^at+RiJM~R`{A`?miG5Ty#nB!rd3?KPDA^}!IRgX96_?p=xR0oT zYRRgUHDy7yx-y%N9hI9QDKwv>$3v63>{sQj(~?-@+l`{TTAamr98<&HKHWCJ7Mn1v*#* zN!OYkhD<_c!dJr0n7V6BlZDxfI_T16B)w-1U6&?h5i%#-+wO(FjLkEUHKnnz%()?m zK?PsibEDapEAmLg7xeedSQ$_q0jkJvr(;!*$Aa%}^P;8muEgN2EXxMS-5v1bFTE2d zha}IvUm;)47WI7tm|nVjJ#T(aR0se@R2Bg6>q3>lqrM>44U$V_BpI{d!saQE$lJ86 zM1vB3`2oHEK!P8=1kx@Lc~pCn1@Pm)aO%C=mq;@t69y@Z$c}hDp$;;t(bp(PlriCK zSY6eSdB1ONVNpM)TLvL1M#hDisQ0`s0bm%4e(aP-+$@<{@SLQI?a4x++r5)f({^<~ z`W9KT*x}jV^Yn$Dn0Y>ZPx$UhOfcsX`~z9b%OS!8ZDg#_YEuH3y0kG3 z&@#5WmybYqNQd}jiSIr0thL1DB^*DvnDOQ6}|Epsgrt` z4h7IH-Qec~ai33Sb zb>%pX&RRqWtDV)#xq@P~#%kV2mpEIZ0|oCE#TjdzKyf&Z{yZvp=_kNwa1 z?}&hGD1qdmn);4*(3clP`}aMS3_RahdRj|bxmyzjKtx#Nv4F6cz$0PZha!@~4<$u} z`Gkcfg@tbk+*bTg3eNC1_BMY1e+4_&90E~+`~O(*w0E}l@U(Px{l9e{N&MT0jee{1 QKT%Ot(s){|VDa{U0YY`!ApigX literal 0 HcmV?d00001 diff --git a/docs/ioc/tutorials/integration-tests.rst b/docs/ioc/tutorials/integration-tests.rst index 77be658e..0377eaf5 100644 --- a/docs/ioc/tutorials/integration-tests.rst +++ b/docs/ioc/tutorials/integration-tests.rst @@ -1,37 +1,53 @@ -Integration tests -================= +Adding integration tests to your IOC +==================================== + +.. note:: + This tutorial is a continuation of the :doc:`streamdevice` tutorial. + + If you haven't already, follow the StreamDevice tutorial first. + +In this tutorial, +you'll learn how to test your created StreamDevice IOC +by running it against the simulator, +inside a declared NixOS VM, +and checking that it behaves as expected. + +This method of testing can then be automated +by running it inside a Continuous Integration (CI) system. Writing the test ---------------- Through the `NixOS testing framework`_, EPNix provides a way of specifying a machine configuration, -and running a Python script that can do various kind of testing. +and running a Python script that can do various kinds of testing. -If you created your IOC using the EPNix template, -like suggested in the :doc:`streamdevice` tutorial, -you will see a ``checks/`` directory. -This directory should contain the integration tests you want to run. +With your IOC created during the :doc:`streamdevice` tutorial, +you'll see a :file:`checks/` directory, +which is the place to add your integration tests. -To add an integration test to EPNix, -record it in your ``flake.nix`` under the ``epnix.checks.files`` option. +These tests are imported using the :ref:`opt-epnix.checks.imports` option. -For example, in the EPNix template, you will see in your ``flake.nix`` file: +For example, +in the EPNix template, +you'll see in your :file:`flake.nix` file: .. code-block:: nix + :caption: :file:`flake.nix`: importing an integration test - checks.files = [ ./checks/simple.nix ]; + checks.imports = [ ./checks/simple.nix ]; -The ``./checks/.nix`` file should contain a NixOS test like so: +The :file:`./checks/simple.nix` file should contain a NixOS test such as this: .. code-block:: nix + :caption: :file:`checks/simple.nix`: structure of a test { build, pkgs, ... }: pkgs.nixosTest { - name = "myTest"; + name = "simple"; - machine = { + nodes.machine = {config, ...}: { # Description of the NixOS machine... }; @@ -40,102 +56,422 @@ The ``./checks/.nix`` file should contain a NixOS test like so: ''; } -This test will create a NixOS virtual machine +Running this test creates a NixOS virtual machine from the given configuration, -and run the test script. -Note that the test script does *not* run on the virtual machine, -but communicates with it. -This is because the test script can start, +and runs the test script. + +The test script can, +among other things, +run commands on the machine, +start, shut down, -or reboot the machine, -and also because NixOS tests can also manage several virtual machines, -not just one. +or reboot the machine. + +.. tip:: + The Python test script does *not* run on the virtual machine, + but communicates with it. + + If you want to run Python code on the VM machine, + you need to package it and run it as a command. -For an overview of what you can input in the machine configuration, -please refer to the `NixOS documentation`_. -You can also read more about it -in the `Python test script API documentation`_. +For a more detailed overview of what you can put in the machine configuration, +examine the `NixOS documentation`_, +or the :doc:`../../nixos-services/tutorials/archiver-appliance` tutorial. .. _NixOS testing framework: https://nixos.org/manual/nixos/stable/index.html#sec-nixos-tests .. _NixOS documentation: https://nixos.org/manual/nixos/stable/index.html#sec-configuration-syntax -.. _Python test script API documentation: https://nixos.org/manual/nixos/stable/index.html#sec-nixos-tests Starting your IOC through systemd --------------------------------- -We recommend starting your IOC through a systemd service, -which you can describe in Nix like so: +First, you need to ensure that your IOC will start inside the VM. + +In the default template, +you'll see this particular configuration: + +.. code-block:: nix + :caption: :file:`checks/simple.nix`: config for starting an IOC + :emphasize-lines: 3-4,8 + + nodes.machine = {config, ...}: { + imports = [ + epnix.nixosModules.ioc + epnixConfig + ]; + environment.systemPackages = [pkgs.epnix.epics-base]; + + systemd.services.ioc = config.epnix.nixos.services.ioc.config; + }; + +The first two emphasized lines are about importing the ability to define an IOC, +and then importing your IOC configuration +that you defined in your :file:`flake.nix`. -.. TODO: change that +Then, +on the last emphasized line, +the systemd service configuration generated by EPNix is used +to generate ``ioc.service``. + +EPNix uses the configuration :ref:`opt-epnix.nixos.services` +from your :file:`flake.nix` +to figure out the name of your app +and the name of your :file:`iocBoot` folder. + +Make sure yours is correct in your :file:`flake.nix`: .. code-block:: nix + :caption: :file:`flake.nix`: configuring the name of your app + and iocBoot folder for the test systemd service + :emphasize-lines: 5-6 + + # Used when generating NixOS systemd services, for example for + # deployment to production, or for the NixOS tests in checks/ + # --- + nixos.services.ioc = { + app = "example"; # Name of your app + ioc = "iocExample"; # Name of your iocBoot folder + }; + +Also take note of the package :ref:`pkg-epics-base` being installed, +with the ``environment.systemPackages`` option. +This enables you to use the :command:`caget`, :command:`caput` commands +inside the VM. + +.. _run-test: + +Running the test +---------------- + +To run the test, +run this command: + +.. code-block:: bash + :caption: Running the test "simple" + + nix build -L '.#checks.x86_64-linux.simple' + +If you left the test script as-is, +you should see that the test fails. +That's because the test script is currently not adapted to our IOC. + +We'll change it afterward, +but for now in the logs you should see your IOC being run. + +If you have several tests, +you can run them all using: + +.. code-block:: bash + :caption: Running all tests + + nix flake check -L + +.. _run-driverInteractive: + +Running the test interactively +------------------------------ + +It's often desirable to run the VM interactively, +to figure out what works and what doesn't, +before writing the test. - # Inside the `machine` attribute - { - systemd.services.my-ioc = { - wantedBy = [ "multi-user.target" ]; - serviceConfig = { - ExecStart = "${build}/iocBoot/iocexample/st.cmd"; - WorkingDirectory = "${build}/iocBoot/iocexample"; - - # Makes the EPICS command-line not quit for 100 seconds, if it doesn't - # receive anything on the standard input - StandardInputText = "epicsThreadSleep(100)"; +To do so, +run: + +.. code-block:: bash + :caption: Running the test "simple" interactively + + nix run -L '.#checks.x86_64-linux.simple.driverInteractive' + +This runs a Python shell prompt in the same environment as the test script. +Any command run here is the same as running it in the test script, +but interactively. + +You can use the ``start_all()`` functions +to start all VMs that you declared in ``nodes``: + +.. code-block:: pycon + + >>> start_all() + +In our case, +we only defined ``machine``, +so this starts a single VM, +and runs your IOC inside it. + +You can log in to that VM with the user ``root`` and no password. +You can then run any command you want +to inspect the state of the VM. + +.. figure:: ./imgs/integration-vm-ioc-screenshot.png + :alt: Integration VM screenshot showing the IOC running + + Integration VM screenshot showing the IOC running + +.. tip:: + If you have a non-English-language keyboard, + change your keyboard layout inside the VM by using :command:`loadkeys`. + + For example, + to set the keyboard to "french": + + .. code-block:: console + + [root@machine:~]# loadkeys fr + +.. tip:: + To exit the Python shell prompt, + press :kbd:`Ctrl-d`, then :kbd:`y`. + + Exiting the Python shell prompt automatically shuts down the VMs. + +Adding the simulator +-------------------- + +The simulator is a program listening on port 9999. +Inside the test VM, +it should be a program run by a systemd service. + +Same as the IOC, +you should use the ``systemd.services`` options. + +Change your Nix test file like this: + +.. code-block:: nix + :caption: Adding the simulator as systemd service, + important changes emphasized + :emphasize-lines: 1,10-13 + + nodes.machine = {config, lib, ...}: { + imports = [ + epnix.nixosModules.ioc + epnixConfig + ]; + environment.systemPackages = [pkgs.epnix.epics-base]; + + systemd.services = { + ioc = config.epnix.nixos.services.ioc.config; + simulator = { + serviceConfig.ExecStart = lib.getExe pkgs.epnix.psu-simulator; + wantedBy = ["multi-user.target"]; + }; }; }; - # Provides the caget / caput / etc. commands to the test script - environment.systemPackages = [ pkgs.epnix.epics-base ]; - } +The first emphasized line is about adding the ``lib`` argument used below. + +The second set of emphasized lines is about creating the ``simulator.service`` systemd service. These lines will generate the following service file: + +.. code-block:: dosini + :caption: generated :file:`/etc/systemd/system/simulator.service` + + [Unit] + + [Service] + # ... + ExecStart=/nix/store/...-psu-simulator/bin/psu-simulator + +And this service is automatically started at boot, +by being a dependency of ``multi-user.target``. -You can view the list of options available for a NixOS machine `here `__. +The ``serviceConfig`` option adds configuration keys to the ``[Service]`` section. +Here, +we set ``ExecStart`` to main executable program of the ``psu-simulator`` package, +by using the ``lib.getExe`` function. -Then, you can write your test script. -Note that the test script doesn’t run directly on the machine, -but communicates with the machine through the ``machine`` variable. +A ``unitConfig`` for the ``[Unit]`` section also exists. -An example of a testing script: +The ``[Install]`` section isn't present in NixOS, +because managed differently, +by using options such as ``wantedBy``, ``requiredBy``, etc. + +For more information, +see the `systemd.services`_ options in the NixOS manual. + +.. _systemd.services: https://nixos.org/manual/nixos/stable/options#opt-systemd.services + +---- + +With this configuration, +you can run the VM interactively +(see :ref:`run-driverInteractive`), +and you should see the simulator up and running after booting. + +.. tip:: + If you make changes to your configuration, + or your IOC, + you *don't* need to rebuild anything + before running the ``nix run`` command. + + Nix will by itself figure out what it needs to rebuild, + and rebuild it before running the test. + +.. figure:: ./imgs/integration-vm-simulator-screenshot.png + :alt: Integration VM screenshot showing the simulator running + + Integration VM screenshot showing the simulator running + +Writing the test +---------------- + +Now that the VM configuration is appropriate, +you can start writing your test script. + +Here is a sample of useful Python functions: + +.. py:function:: start_all() + + Start all defined VMs + +.. py:function:: Machine.wait_for_unit(self, unit: str, user: str | None = None, timeout: int = 900) + + Wait for a systemd unit to get into “active” state. + Throws exceptions on “failed” and “inactive” states + as well as after timing out. + + .. code-block:: python + :caption: Example + + machine.wait_for_unit("ioc.service") + +.. py:function:: Machine.succeed(self, command: str, timeout: int | None = None) + + Execute a shell command, + raising an exception if the exit status is not zero, + otherwise returning the standard output + + .. code-block:: python + :caption: Example + + machine.succeed("caput VOLT 42") + +.. py:function:: Machine.wait_until_succeeds(self, command: str, timeout: int = 900) + + Repeat a shell command with 1-second intervals until it succeeds. + + Be careful of the ``s`` in ``succeeds``. + + .. code-block:: python + :caption: Example + + machine.wait_until_succeeds("caget -t my:stringout | grep -qxF 'expected value'") + +.. py:function:: Machine.fail(self, command: str, timeout: int | None = None) + + Like :py:func:`succeed`, + but raising an exception if the command returns a zero status. + + .. code-block:: python + :caption: Example + + machine.fail("caget unknown-PV") + +.. py:function:: Machine.wait_for_open_port(self, addr: int | str, timeout: int = 900) + + Wait until a process is listening on the given TCP port and IP address (default ``localhost``). + + .. code-block:: python + :caption: Example + + machine.wait_for_open_port(9999) + +.. py:function:: retry(fn: Callable, timeout: int = 900) + + Call the given function repeatedly, with 1-second intervals, + until it returns ``True`` or a timeout is reached. + + .. code-block:: python + :caption: Example + + def check_value(_last_call: bool) -> bool: + """Check whether the VOLT-RB PV is 42.""" + value = float(machine.succeed("caget -t VOLT-RB")) + return value == 42. + + retry(check_value, timeout=10) + +.. py:function:: subtest(name: str) + + Group logs under a given test name. + + To be used with the ``with`` syntax. + + .. code-block:: python + :caption: Example + + with subtest("check voltage"): + test_setting_voltage() + test_voltage_readback() + ... + +You can also read more about the Python functions available in the test script +in the `NixOS tests documentation`_. + +.. _NixOS tests documentation: https://nixos.org/manual/nixos/stable/index.html#sec-nixos-tests + +Example test script +^^^^^^^^^^^^^^^^^^^ + +Here an example test script +that should work with your StreamDevice IOC: .. code-block:: python + :caption: :file:`checks/simple.nix`: Example test script start_all() - machine.wait_for_unit("default.target") - machine.wait_for_unit("my-ioc.service") + with subtest("check services"): + machine.wait_for_unit("ioc.service") + machine.wait_for_unit("simulator.service") + machine.wait_for_unit("default.target") - machine.wait_until_succeeds("caget stringin") - machine.wait_until_succeeds("caget stringout") - machine.fail("caget non-existing") + machine.wait_for_open_port(9999) - with subtest("testing stringout"): - def test_stringout(_) -> bool: - machine.succeed("caput stringout 'hello'") - status, _output = machine.execute("caget -t stringout | grep -qxF 'hello'") + # Prefer using 'wait_until_succeeds', + # since the 'ioc.service' being active doesn't necessarily means + # that the IOC is initialized + machine.wait_until_succeeds("caget VOLT-RB", timeout=10) + machine.fail("caget unknown-PV") - return status == 0 + with subtest("check voltage"): + # Initial value is zero + machine.succeed("caget -t VOLT-RB | grep -qxF '0'") - retry(test_stringout) + machine.succeed("caput VOLT 42") - assert "hello" not in machine.succeed("caget -t stringin") + def check_value(_last_call: bool) -> bool: + """Check whether the VOLT-RB PV is 42.""" + value = float(machine.succeed("caget -t VOLT-RB")) + return value == 42. -Note that the script extensively uses the ``wait_until_succeeds`` method and the ``retry`` function. -This is because EPICS has few guarantees about whether it propagates changes immediately, -and so it’s better to encourage the use of retries, + retry(check_value, timeout=10) + +Note that the script uses the ``wait_until_succeeds`` method and the ``retry`` function. +This is because EPICS has few guarantees about whether it propagates changes immediately. +It’s better to encourage the use of retries, instead of hoping the timing lines up. -If you would like to use a fully fledged python script on the machine, -which can use Python dependencies like pyepics, -please refer to the guide :doc:`../user-guides/testing/packaging-python-scripts`. +After changing your test script, +run your test as explained in :ref:`run-test`. -You can find methods available on the ``machine`` variable and other particularities in the `NixOS tests documentation`_. +Next steps +---------- -You can also look at examples either in the EPNix repository, -under the `ioc/tests folder`_, -or in nixpkgs under the `nixos/tests folder`_. +You can examine other NixOS test examples: -.. TODO: this doesn't explain how to run the test +- In the `EPNix' ioc/tests`_ folder, for IOC tests, +- In the `EPNix' nixos/tests`_ folder, for EPICS-related NixOS services tests, +- Or in the `nixpkgs' nixos/tests`_ folder. -.. _Packaging Python scripts: ../guides/testing/packaging-python-scripts.md -.. _NixOS tests documentation: https://nixos.org/manual/nixos/stable/index.html#sec-nixos-tests -.. _ioc/tests folder: https://github.com/epics-extensions/epnix/tree/master/ioc/tests -.. _nixos/tests folder: https://github.com/NixOS/nixpkgs/tree/master/nixos/tests +If you'd like to run a complete python script on the test VM, +which can use Python dependencies such as ``pyepics``, +examine the guide :doc:`../user-guides/testing/packaging-python-scripts`. + +If you're interested in adding unit tests, +examine the :doc:`../user-guides/testing/unit-testing` guide. + +For all testing related guides, +see :doc:`../user-guides/testing/index`. + +.. _EPNix' ioc/tests: https://github.com/epics-extensions/epnix/tree/master/ioc/tests +.. _EPNix' nixos/tests: https://github.com/epics-extensions/epnix/tree/master/nixos/tests +.. _nixpkgs' nixos/tests: https://github.com/NixOS/nixpkgs/tree/master/nixos/tests From a0e3f8a4298ec376a79ea3c449eadaa85e4ab3e0 Mon Sep 17 00:00:00 2001 From: Minijackson Date: Wed, 31 Jul 2024 15:46:13 +0200 Subject: [PATCH 069/111] docs/ioc: add section on KVM for integration test tutorial Nix will show an error running tests if KVM is not present. --- docs/ioc/tutorials/integration-tests.rst | 44 ++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/docs/ioc/tutorials/integration-tests.rst b/docs/ioc/tutorials/integration-tests.rst index 0377eaf5..7ef2fbf4 100644 --- a/docs/ioc/tutorials/integration-tests.rst +++ b/docs/ioc/tutorials/integration-tests.rst @@ -15,6 +15,50 @@ and checking that it behaves as expected. This method of testing can then be automated by running it inside a Continuous Integration (CI) system. +Pre-requisites +-------------- + +.. warning:: + Nix assumes you can run hardware-accelerated VMs, + through KVM. + +Make sure that you have KVM on your Linux machine +by checking if the file :file:`/dev/kvm` is present. + +If the file is present, +you can proceed to the next section. + +If you don't have KVM, +and you're running Nix on a physical machine, +examine your firmware settings +to see if you can enable hardware-accelerated virtualization. +The setting can show up as: + +- Virtualization +- Intel Virtualization Technology +- Intel VT +- VT-d +- SVM Mode +- AMD-v + +If you don't have KVM, +and you're running Nix on a virtual machine, +check your firmware settings +as said before, +and look up your hypervisor documentation +to enable nested virtualization. + +If this doesn't work, +you can still proceed without hardware acceleration +by adding this line to your :file:`nix.conf`: + +.. code-block:: + :caption: :file:`/etc/nix/nix.conf` + + extra-system-features = kvm + +Note that this means much slower integration tests. + Writing the test ---------------- From fb00ef99dbb77b7783c956397e91c99ef405ec55 Mon Sep 17 00:00:00 2001 From: Minijackson Date: Mon, 29 Apr 2024 14:25:28 +0200 Subject: [PATCH 070/111] nixos/phoebus-olog: don't automatically enable elasticsearch see #75, #54, follow-up of #60 --- nixos/modules/phoebus/olog.nix | 12 +----------- nixos/tests/phoebus/olog.nix | 7 ++++++- 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/nixos/modules/phoebus/olog.nix b/nixos/modules/phoebus/olog.nix index 63740dc4..0ac3a078 100644 --- a/nixos/modules/phoebus/olog.nix +++ b/nixos/modules/phoebus/olog.nix @@ -113,18 +113,8 @@ in { # TODO: systemd hardening. Currently level 8.2 EXPOSED }; }; - - services.elasticsearch = { - enable = true; - # Should be kept in sync with the phoebus-alarm-logger and phoebus-save-and-restore services - package = pkgs.elasticsearch7; - }; services.mongodb.enable = true; }; - meta = { - maintainers = with epnixLib.maintainers; [minijackson]; - # TODO: - # doc = ./olog.md; - }; + meta.maintainers = with epnixLib.maintainers; [minijackson]; } diff --git a/nixos/tests/phoebus/olog.nix b/nixos/tests/phoebus/olog.nix index 7adca693..3538ca30 100644 --- a/nixos/tests/phoebus/olog.nix +++ b/nixos/tests/phoebus/olog.nix @@ -7,12 +7,17 @@ meta.maintainers = with epnixLib.maintainers; [minijackson]; nodes = { - server = { + server = {pkgs, ...}: { services.phoebus-olog = { enable = true; settings."demo_auth.enabled" = true; }; + services.elasticsearch = { + enable = true; + package = pkgs.elasticsearch7; + }; + nixpkgs.config.allowUnfreePredicate = pkg: builtins.elem (lib.getName pkg) [ # Elasticsearch can be used as an SSPL-licensed software, which is From 148dc026c3f8de23adfa912805b5971d3cb91d3f Mon Sep 17 00:00:00 2001 From: Minijackson Date: Tue, 18 Jun 2024 15:52:11 +0200 Subject: [PATCH 071/111] flake: upgrade NixOS 23.11 -> 24.05 and related changes to documentation and templates, and to the Phoebus deps output hash --- docs/index.rst | 2 +- docs/nixos-services/tutorials/archiver-appliance.rst | 4 ++-- docs/nixos-services/user-guides/pre-requisites.rst | 4 ++-- flake.lock | 8 ++++---- flake.nix | 2 +- pkgs/docs/default.nix | 2 +- pkgs/epnix/tools/phoebus/deps/default.nix | 2 +- templates/top/flake.nix | 2 +- 8 files changed, 13 insertions(+), 13 deletions(-) diff --git a/docs/index.rst b/docs/index.rst index dd41b3a3..1d0dde55 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -58,7 +58,7 @@ which is considered unstable, meaning breaking changes might happen without notice. EPNix also has release branches, -such as ``nixos-23.11``, +such as ``nixos-24.05``, tied to the nixpkgs release branches, where breaking changes are forbidden. diff --git a/docs/nixos-services/tutorials/archiver-appliance.rst b/docs/nixos-services/tutorials/archiver-appliance.rst index a684ddc4..5c1203a7 100644 --- a/docs/nixos-services/tutorials/archiver-appliance.rst +++ b/docs/nixos-services/tutorials/archiver-appliance.rst @@ -61,8 +61,8 @@ Fill the file with these lines: { description = "Configuration for running Archiver Appliance in a VM"; - inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11"; - inputs.epnix.url = "github:epics-extensions/EPNix/nixos-23.11"; + inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.05"; + inputs.epnix.url = "github:epics-extensions/EPNix/nixos-24.05"; outputs = { self, nixpkgs, epnix }: { nixosConfigurations.nixos = nixpkgs.lib.nixosSystem { diff --git a/docs/nixos-services/user-guides/pre-requisites.rst b/docs/nixos-services/user-guides/pre-requisites.rst index 00ac0bed..fefca4c6 100644 --- a/docs/nixos-services/user-guides/pre-requisites.rst +++ b/docs/nixos-services/user-guides/pre-requisites.rst @@ -21,8 +21,8 @@ For example: { # ... - inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11"; - + inputs.epnix.url = "github:epics-extensions/EPNix/nixos-23.11"; + inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.05"; + + inputs.epnix.url = "github:epics-extensions/EPNix/nixos-24.05"; # ... outputs = { diff --git a/flake.lock b/flake.lock index 8c359b68..f66747bf 100644 --- a/flake.lock +++ b/flake.lock @@ -95,16 +95,16 @@ }, "nixpkgs": { "locked": { - "lastModified": 1720535198, - "narHash": "sha256-zwVvxrdIzralnSbcpghA92tWu2DV2lwv89xZc8MTrbg=", + "lastModified": 1722221733, + "narHash": "sha256-sga9SrrPb+pQJxG1ttJfMPheZvDOxApFfwXCFO0H9xw=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "205fd4226592cc83fd4c0885a3e4c9c400efabb5", + "rev": "12bf09802d77264e441f48e25459c10c93eada2e", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixos-23.11", + "ref": "nixos-24.05", "repo": "nixpkgs", "type": "github" } diff --git a/flake.nix b/flake.nix index c17fc539..ad1f8c11 100644 --- a/flake.nix +++ b/flake.nix @@ -2,7 +2,7 @@ description = "A Nix flake containing EPICS-related modules and packages"; inputs = { - nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11"; + nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.05"; bash-lib = { url = "github:minijackson/bash-lib"; inputs.nixpkgs.follows = "nixpkgs"; diff --git a/pkgs/docs/default.nix b/pkgs/docs/default.nix index c893be01..38c371b1 100644 --- a/pkgs/docs/default.nix +++ b/pkgs/docs/default.nix @@ -70,7 +70,7 @@ in stdenvNoCC.mkDerivation { pname = "epnix-docs"; - version = "23.11"; + version = "24.05"; src = ../../docs; diff --git a/pkgs/epnix/tools/phoebus/deps/default.nix b/pkgs/epnix/tools/phoebus/deps/default.nix index ed7a43da..d0d1f793 100644 --- a/pkgs/epnix/tools/phoebus/deps/default.nix +++ b/pkgs/epnix/tools/phoebus/deps/default.nix @@ -58,7 +58,7 @@ stdenv.mkDerivation { outputHashAlgo = "sha256"; outputHashMode = "recursive"; - outputHash = "sha256-6pUHn6tU54e4r5tJwoailVX3YEqO9BouWM3fweAdyt8="; + outputHash = "sha256-tJMULUSwH0rCmNeKvesPqMVTBH3PQWInx6gzGxwdPwY="; doCheck = false; diff --git a/templates/top/flake.nix b/templates/top/flake.nix index e934504b..fa1efd70 100644 --- a/templates/top/flake.nix +++ b/templates/top/flake.nix @@ -2,7 +2,7 @@ description = "EPICS IOC for <...>"; inputs.flake-utils.url = "github:numtide/flake-utils"; - inputs.epnix.url = "github:epics-extensions/epnix/nixos-23.11"; + inputs.epnix.url = "github:epics-extensions/epnix/nixos-24.05"; # If you have a support module as a separate EPNix repository, # add it as an input here: From ef68b80df8fadf9721e559a7e86145a95f908983 Mon Sep 17 00:00:00 2001 From: Minijackson Date: Fri, 19 Jul 2024 09:24:00 +0200 Subject: [PATCH 072/111] pkgs/open62541_1_3: init at 1.3.10, use in support/opcua this is needed by the EPICS OPCUA support module, which doesn't support open62541 v1.4+ yet. See https://github.com/epics-modules/opcua/commit/bd6f9e011d0b471d0538608ae4698797e3b601d5 --- pkgs/default.nix | 4 +- pkgs/epnix/tools/open62541_1_3/default.nix | 177 +++++++++++++++++++++ 2 files changed, 180 insertions(+), 1 deletion(-) create mode 100644 pkgs/epnix/tools/open62541_1_3/default.nix diff --git a/pkgs/default.nix b/pkgs/default.nix index 94c90691..3a4481bf 100644 --- a/pkgs/default.nix +++ b/pkgs/default.nix @@ -56,7 +56,7 @@ in ipac = callPackage ./epnix/support/ipac {}; modbus = callPackage ./epnix/support/modbus {}; mrfioc2 = callPackage ./epnix/support/mrfioc2 {}; - opcua = callPackage ./epnix/support/opcua {}; + opcua = callPackage ./epnix/support/opcua {open62541 = self.open62541_1_3;}; pvxs = callPackage ./epnix/support/pvxs {}; seq = callPackage ./epnix/support/seq {}; snmp = callPackage ./epnix/support/snmp {}; @@ -91,6 +91,8 @@ in # Other utilities mariadb_jdbc = callPackage ./epnix/tools/mariadb_jdbc {}; + # Needed by support/opcua + open62541_1_3 = callPackage ./epnix/tools/open62541_1_3 {}; # EPNix specific packages docs = callPackage ./docs {}; diff --git a/pkgs/epnix/tools/open62541_1_3/default.nix b/pkgs/epnix/tools/open62541_1_3/default.nix new file mode 100644 index 00000000..6be7f217 --- /dev/null +++ b/pkgs/epnix/tools/open62541_1_3/default.nix @@ -0,0 +1,177 @@ +{ + stdenv, + lib, + epnixLib, + fetchFromGitHub, + fetchpatch, + cmake, + pkg-config, + check, + libxcrypt, + subunit, + python3Packages, + nix-update-script, + withDoc ? false, + graphviz-nox, + withExamples ? false, + withEncryption ? false, # or "openssl" or "mbedtls" + openssl, + mbedtls, + withPubSub ? false, + # for passthru.tests only + open62541, +}: let + encryptionBackend = + { + inherit openssl mbedtls; + } + ."${withEncryption}" + or (throw "Unsupported encryption backend: ${withEncryption}"); +in + stdenv.mkDerivation (finalAttrs: { + pname = "open62541"; + version = "1.3.10"; + + src = fetchFromGitHub { + owner = "open62541"; + repo = "open62541"; + rev = "v${finalAttrs.version}"; + hash = "sha256-FekO0cKgpYulMXz4r0/TUPz2tawC4k3Sq07Og4xqh4I="; + fetchSubmodules = true; + }; + + patches = [ + (fetchpatch { + name = "Ensure-absolute-paths-in-pkg-config-file.patch"; + url = "https://github.com/open62541/open62541/commit/023d4b6b8bdec987f8f3ffee6c09801bbee4fa2d.patch"; + sha256 = "sha256-mq4h32js2RjI0Ljown/01SXA3gc+7+zX8meIcvDPvoA="; + }) + ]; + + cmakeFlags = + [ + "-DOPEN62541_VERSION=v${finalAttrs.version}" + + "-DBUILD_SHARED_LIBS=${ + if stdenv.hostPlatform.isStatic + then "OFF" + else "ON" + }" + "-DUA_NAMESPACE_ZERO=FULL" + + "-DUA_BUILD_UNIT_TESTS=${ + if finalAttrs.doCheck + then "ON" + else "OFF" + }" + ] + ++ lib.optional withExamples "-DUA_BUILD_EXAMPLES=ON" + ++ lib.optional (withEncryption != false) + "-DUA_ENABLE_ENCRYPTION=${lib.toUpper withEncryption}" + ++ lib.optional withPubSub "-DUA_ENABLE_PUBSUB=ON"; + + nativeBuildInputs = + [ + cmake + pkg-config + python3Packages.python + ] + ++ lib.optionals withDoc (with python3Packages; [ + sphinx + sphinx_rtd_theme + graphviz-nox + ]); + + buildInputs = lib.optional (withEncryption != false) encryptionBackend; + + buildFlags = ["all"] ++ lib.optional withDoc "doc"; + + doCheck = true; + + checkInputs = [ + check + libxcrypt + subunit + ]; + + # Tests must run sequentially to avoid port collisions on localhost + enableParallelChecking = false; + + preCheck = let + disabledTests = lib.optionals withPubSub [ + # "Cannot set socket option IP_ADD_MEMBERSHIP" + "pubsub_publish" + "check_pubsub_get_state" + "check_pubsub_publish_rt_levels" + "check_pubsub_subscribe_config_freeze" + "check_pubsub_subscribe_rt_levels" + "check_pubsub_multiple_subscribe_rt_levels" + ]; + regex = "^(${builtins.concatStringsSep "|" disabledTests})\$"; + in + lib.optionalString (disabledTests != []) '' + checkFlagsArray+=(ARGS="-E ${lib.escapeRegex regex}") + ''; + + postInstall = + lib.optionalString withDoc '' + # excluded files, see doc/CMakeLists.txt + rm -r doc/{_sources/,CMakeFiles/,cmake_install.cmake} + + # doc is not installed automatically + mkdir -p $out/share/doc/open62541 + cp -r doc/ $out/share/doc/open62541/html + '' + + lib.optionalString withExamples '' + # install sources of examples + mkdir -p $out/share/open62541 + cp -r ../examples $out/share/open62541 + + ${lib.optionalString (!stdenv.hostPlatform.isWindows) '' + # remove .exe suffix + mv -v $out/bin/ua_server_ctt.exe $out/bin/ua_server_ctt + ''} + + # remove duplicate libraries in build/bin/, which cause forbidden + # references to /build/ in ua_server_ctt + rm -r bin/libopen62541* + ''; + + passthru.updateScript = nix-update-script {}; + + passthru.tests = let + open62541Full = encBackend: + open62541.override { + withDoc = true; + # if (withExamples && withPubSub), one of the example currently fails to build + #withExamples = true; + withEncryption = encBackend; + withPubSub = true; + }; + in { + open62541Full = open62541Full false; + open62541Full-openssl = open62541Full "openssl"; + open62541Full-mbedtls = open62541Full "mbedtls"; + }; + + meta = with lib; { + description = "Open source implementation of OPC UA, version 1.3"; + longDescription = '' + open62541 (http://open62541.org) is an open source and free implementation + of OPC UA (OPC Unified Architecture) written in the common subset of the + C99 and C++98 languages. + The library is usable with all major compilers and provides the necessary + tools to implement dedicated OPC UA clients and servers, or to integrate + OPC UA-based communication into existing applications. + + This version of Open62541 was added in EPNix, as a stopgap measure, + while waiting for the EPICS OPCUA support module to support the + breaking changes made in 1.4. + ''; + homepage = "https://www.open62541.org"; + changelog = "https://github.com/open62541/open62541/releases/tag/v${finalAttrs.version}"; + license = licenses.mpl20; + maintainers = with epnixLib.maintainers; [minijackson]; + platforms = platforms.linux; + }; + }) From 7413e22e0c19cd11d7191a399bf6c29c36e29fff Mon Sep 17 00:00:00 2001 From: Minijackson Date: Thu, 1 Aug 2024 09:11:39 +0200 Subject: [PATCH 073/111] pkgs.support.twincat-ads: fix missing header with gcc 13 --- pkgs/epnix/support/twincat-ads/default.nix | 3 +++ .../support/twincat-ads/fix-missing-header.patch | 13 +++++++++++++ 2 files changed, 16 insertions(+) create mode 100644 pkgs/epnix/support/twincat-ads/fix-missing-header.patch diff --git a/pkgs/epnix/support/twincat-ads/default.nix b/pkgs/epnix/support/twincat-ads/default.nix index 281f84d5..9ad2e6db 100644 --- a/pkgs/epnix/support/twincat-ads/default.nix +++ b/pkgs/epnix/support/twincat-ads/default.nix @@ -23,6 +23,9 @@ mkEpicsPackage rec { sha256 = "sha256-f7hod1N1AzCh+W7nHl9VCA+nuwpJAboSh19Dq80n/2E="; }; + # See: https://gitlab.esss.lu.se/epics-modules/epics-twincat-ads/-/issues/2 + patches = [./fix-missing-header.patch]; + propagatedBuildInputs = with epnix.support; [asyn calc]; preBuild = '' diff --git a/pkgs/epnix/support/twincat-ads/fix-missing-header.patch b/pkgs/epnix/support/twincat-ads/fix-missing-header.patch new file mode 100644 index 00000000..9255222b --- /dev/null +++ b/pkgs/epnix/support/twincat-ads/fix-missing-header.patch @@ -0,0 +1,13 @@ +diff --git a/BeckhoffADS/AdsLib/AdsLib.cpp b/BeckhoffADS/AdsLib/AdsLib.cpp +index f1b2116..8a82a95 100644 +--- a/BeckhoffADS/AdsLib/AdsLib.cpp ++++ b/BeckhoffADS/AdsLib/AdsLib.cpp +@@ -20,6 +20,8 @@ + SOFTWARE. + */ + ++#include ++ + #include "AdsLib.h" + #include "AmsRouter.h" + From 3dbad097e0893ca02b9323e239b906fcdd05fdb2 Mon Sep 17 00:00:00 2001 From: Minijackson Date: Thu, 1 Aug 2024 13:54:02 +0200 Subject: [PATCH 074/111] pkgs.mrf-driver: fix build with Linux >= 6.3 --- pkgs/epnix/kernel-modules/mrf/default.nix | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/pkgs/epnix/kernel-modules/mrf/default.nix b/pkgs/epnix/kernel-modules/mrf/default.nix index 2da2ef49..2afa0185 100644 --- a/pkgs/epnix/kernel-modules/mrf/default.nix +++ b/pkgs/epnix/kernel-modules/mrf/default.nix @@ -1,14 +1,23 @@ { stdenv, - lib, kernel, epnix, + fetchpatch, }: stdenv.mkDerivation (finalAttrs: { pname = "mrf-driver"; inherit (epnix.support.mrfioc2) version src; + patches = [ + (fetchpatch { + name = "use-vm_flags_set-on-kernels-6-3.patch"; + url = "https://github.com/epics-modules/mrfioc2/commit/64634a23a035d336de5d720b2e1ecafcc918d737.patch"; + hash = "sha256-6/obmLfLKfhcwn12O0KKpogWCzg7Evs1kIoNm0x7Puw="; + stripLen = 2; + }) + ]; + # Needed for kernel modules hardeningDisable = ["format" "pic"]; From 366ba04f1336b665f791e44a06547b3d83d965ee Mon Sep 17 00:00:00 2001 From: Minijackson Date: Mon, 29 Apr 2024 14:49:46 +0200 Subject: [PATCH 075/111] nixos/phoebus-save-and-restore: don't automatically enable elasticsearch see #75, #54, follow-up of #60 Specify in documentation that enabling ElasticSearch needs to be done only once. --- docs/nixos-services/user-guides/phoebus-alarm.rst | 7 ++++++- .../user-guides/phoebus-save-and-restore.rst | 8 ++++++++ docs/release-notes/2405.rst | 8 ++++++++ nixos/modules/phoebus/save-and-restore.nix | 10 +--------- nixos/tests/phoebus/save-and-restore.nix | 7 ++++++- 5 files changed, 29 insertions(+), 11 deletions(-) diff --git a/docs/nixos-services/user-guides/phoebus-alarm.rst b/docs/nixos-services/user-guides/phoebus-alarm.rst index 48a2d7c9..e0716015 100644 --- a/docs/nixos-services/user-guides/phoebus-alarm.rst +++ b/docs/nixos-services/user-guides/phoebus-alarm.rst @@ -52,7 +52,9 @@ and Kafka’s ``clusterId``: services.phoebus-alarm-logger.settings."bootstrap.servers" = kafkaListenSockAddr; - # Single-server Kafka setup + # Phoebus alarm needs Kafka. + # If not already enabled elsewhere in your configuration, + # the code below shows a single-server Kafka setup: services.apache-kafka = { enable = true; # Replace with a randomly generated uuid. You can get one by running: @@ -89,6 +91,9 @@ and Kafka’s ``clusterId``: # Open kafka to the outside world networking.firewall.allowedTCPPorts = [9092]; + # Phoebus alarm needs ElasticSearch. + # If not already enabled elsewhere in your configuration, + # Enable it with the code below: services.elasticsearch = { enable = true; package = pkgs.elasticsearch7; diff --git a/docs/nixos-services/user-guides/phoebus-save-and-restore.rst b/docs/nixos-services/user-guides/phoebus-save-and-restore.rst index c48bcbd6..5dd1c43c 100644 --- a/docs/nixos-services/user-guides/phoebus-save-and-restore.rst +++ b/docs/nixos-services/user-guides/phoebus-save-and-restore.rst @@ -29,6 +29,14 @@ add this to your configuration: openFirewall = true; }; + # Phoebus save-and-restore needs ElasticSearch. + # If not already enabled elsewhere in your configuration, + # Enable it with the code below: + services.elasticsearch = { + enable = true; + package = pkgs.elasticsearch7; + }; + # Elasticsearch, needed by Phoebus Save-and-restore, is not free software (SSPL | Elastic License). # To accept the license, add the code below: nixpkgs.config.allowUnfreePredicate = pkg: diff --git a/docs/release-notes/2405.rst b/docs/release-notes/2405.rst index 6c8cc205..6debc952 100644 --- a/docs/release-notes/2405.rst +++ b/docs/release-notes/2405.rst @@ -9,3 +9,11 @@ Breaking changes - The :nix:`config.epnix.outputs.mdbook` and :nix:`config.epnix.outputs.manpages` options from the IOC module options, previously deprecated, are now removed. + +- The :ref:`opt-services.phoebus-alarm-server.enable`, + :ref:`opt-services.phoebus-olog.enable`, + and :ref:`opt-services.phoebus-save-and-restore.enable` options + don't enable ElasticSearch automatically anymore. + See :doc:`../nixos-services/user-guides/phoebus-alarm` + and :doc:`../nixos-services/user-guides/phoebus-save-and-restore` + for how to enable it yourself on the same server. diff --git a/nixos/modules/phoebus/save-and-restore.nix b/nixos/modules/phoebus/save-and-restore.nix index 220ce101..60004872 100644 --- a/nixos/modules/phoebus/save-and-restore.nix +++ b/nixos/modules/phoebus/save-and-restore.nix @@ -8,8 +8,6 @@ cfg = config.services.phoebus-save-and-restore; settingsFormat = pkgs.formats.javaProperties {}; configFile = settingsFormat.generate "phoebus-save-and-restore.properties" cfg.settings; - - localElasticsearch = cfg.settings."elasticsearch.network.host" == "localhost"; in { options.services.phoebus-save-and-restore = { enable = lib.mkEnableOption '' @@ -81,7 +79,7 @@ in { description = "Phoebus Save-and-restore"; wantedBy = ["multi-user.target"]; - after = lib.mkIf localElasticsearch ["elasticsearch.service"]; + after = ["elasticsearch.service"]; serviceConfig = { ExecStart = "${lib.getExe pkgs.epnix.phoebus-save-and-restore} --spring.config.location=file://${configFile}"; @@ -140,12 +138,6 @@ in { }; }; - services.elasticsearch = lib.mkIf localElasticsearch { - enable = true; - # Should be kept in sync with the phoebus-alarm-logger and phoebus-olog services - package = pkgs.elasticsearch7; - }; - networking.firewall.allowedTCPPorts = lib.mkIf cfg.openFirewall [ (lib.toInt cfg.settings."server.port") ]; diff --git a/nixos/tests/phoebus/save-and-restore.nix b/nixos/tests/phoebus/save-and-restore.nix index 5ac36e6e..6b626c23 100644 --- a/nixos/tests/phoebus/save-and-restore.nix +++ b/nixos/tests/phoebus/save-and-restore.nix @@ -7,12 +7,17 @@ meta.maintainers = with epnixLib.maintainers; [minijackson]; nodes = { - server = { + server = {pkgs, ...}: { services.phoebus-save-and-restore = { enable = true; openFirewall = true; }; + services.elasticsearch = { + enable = true; + package = pkgs.elasticsearch7; + }; + nixpkgs.config.allowUnfreePredicate = pkg: builtins.elem (lib.getName pkg) [ # Elasticsearch can be used as an SSPL-licensed software, which is From 3b107d1743922055b0531e6e8c6d039a1cbe1319 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 4 Aug 2024 01:12:07 +0000 Subject: [PATCH 076/111] flake.lock: Update MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Flake lock file updates: • Updated input 'nixpkgs': 'github:NixOS/nixpkgs/12bf09802d77264e441f48e25459c10c93eada2e?narHash=sha256-sga9SrrPb%2BpQJxG1ttJfMPheZvDOxApFfwXCFO0H9xw%3D' (2024-07-29) → 'github:NixOS/nixpkgs/05405724efa137a0b899cce5ab4dde463b4fd30b?narHash=sha256-VEdJmVU2eLFtLqCjTYJd1J7%2BGo8idAcZoT11IewFiRg%3D' (2024-08-01) • Updated input 'poetry2nix': 'github:nix-community/poetry2nix/d11c01e58587e5f21037ed6477465a7f26a32e27?narHash=sha256-XANsG9GYHip8pxZpbqKf/YGv8tIa0xTh289Y%2BWNBNfw%3D' (2024-07-15) → 'github:nix-community/poetry2nix/8c25e871bba3f472e1569bbf6c0f52dcc34bf2a4?narHash=sha256-6FVPz1WzHak65xJQg8tRjVyFEWMesGxfskKaCxDUnRk%3D' (2024-08-01) --- flake.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/flake.lock b/flake.lock index f66747bf..0d883e33 100644 --- a/flake.lock +++ b/flake.lock @@ -95,11 +95,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1722221733, - "narHash": "sha256-sga9SrrPb+pQJxG1ttJfMPheZvDOxApFfwXCFO0H9xw=", + "lastModified": 1722519197, + "narHash": "sha256-VEdJmVU2eLFtLqCjTYJd1J7+Go8idAcZoT11IewFiRg=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "12bf09802d77264e441f48e25459c10c93eada2e", + "rev": "05405724efa137a0b899cce5ab4dde463b4fd30b", "type": "github" }, "original": { @@ -120,11 +120,11 @@ "treefmt-nix": "treefmt-nix" }, "locked": { - "lastModified": 1721039874, - "narHash": "sha256-XANsG9GYHip8pxZpbqKf/YGv8tIa0xTh289Y+WNBNfw=", + "lastModified": 1722515463, + "narHash": "sha256-6FVPz1WzHak65xJQg8tRjVyFEWMesGxfskKaCxDUnRk=", "owner": "nix-community", "repo": "poetry2nix", - "rev": "d11c01e58587e5f21037ed6477465a7f26a32e27", + "rev": "8c25e871bba3f472e1569bbf6c0f52dcc34bf2a4", "type": "github" }, "original": { From 0935b647fc7c98b57423fba25919af639a78a874 Mon Sep 17 00:00:00 2001 From: Minijackson Date: Mon, 5 Aug 2024 08:56:34 +0200 Subject: [PATCH 077/111] github/update-flake-lock: add nixos-24.05 branch --- .github/workflows/update-flake-lock.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/update-flake-lock.yml b/.github/workflows/update-flake-lock.yml index fc1aecc8..53b01059 100644 --- a/.github/workflows/update-flake-lock.yml +++ b/.github/workflows/update-flake-lock.yml @@ -18,6 +18,7 @@ jobs: matrix: branch: - master + - nixos-24.05 - nixos-23.11 - nixos-23.05 permissions: From 488dec87431b78d07398817694b131d2024490df Mon Sep 17 00:00:00 2001 From: Minijackson Date: Mon, 5 Aug 2024 08:57:24 +0200 Subject: [PATCH 078/111] github: don't run some jobs on forks --- .github/workflows/book-gh-pages.yml | 1 + .github/workflows/update-flake-lock.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/.github/workflows/book-gh-pages.yml b/.github/workflows/book-gh-pages.yml index c85315be..5fa5b3e9 100644 --- a/.github/workflows/book-gh-pages.yml +++ b/.github/workflows/book-gh-pages.yml @@ -18,6 +18,7 @@ concurrency: jobs: deploy: + if: "github.repository_owner == 'epics-extensions'" environment: name: github-pages url: ${{ steps.deployment.outputs.page_url }} diff --git a/.github/workflows/update-flake-lock.yml b/.github/workflows/update-flake-lock.yml index 53b01059..05021fa9 100644 --- a/.github/workflows/update-flake-lock.yml +++ b/.github/workflows/update-flake-lock.yml @@ -14,6 +14,7 @@ permissions: jobs: lockfile: + if: "github.repository_owner == 'epics-extensions'" strategy: matrix: branch: From fab73a6f06cfb2e57ef67db3feb1447990b6b416 Mon Sep 17 00:00:00 2001 From: Minijackson Date: Mon, 5 Aug 2024 08:58:28 +0200 Subject: [PATCH 079/111] github/dependabot: group PRs for non-breaking-changes --- .github/dependabot.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 5ace4600..71871696 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -4,3 +4,6 @@ updates: directory: "/" schedule: interval: "weekly" + groups: + non-breaking-changes: + update-types: [minor, patch] From cc2d3f67db8f4cc00407d8bf7a0f46fbcc47b9f0 Mon Sep 17 00:00:00 2001 From: Minijackson Date: Tue, 6 Aug 2024 09:34:50 +0200 Subject: [PATCH 080/111] nixos/phoebus-alarm-logger: forward configuration to SpringBoot phoebus-alarm-logger does not forward the given configuration to SpringBoot, so we use an environment variable to forward it ourselves. this caused options like "server.port" to be ignored, since they are SpringBoto specific. Use the "server.port" option in the test to test regressions. fixes #56 --- nixos/modules/phoebus/alarm-logger.nix | 12 ++++++++++-- nixos/tests/phoebus/alarm.nix | 6 ++++-- nixos/tests/phoebus/alarm.py | 4 ++-- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/nixos/modules/phoebus/alarm-logger.nix b/nixos/modules/phoebus/alarm-logger.nix index 4cc6b4a6..1d24f62e 100644 --- a/nixos/modules/phoebus/alarm-logger.nix +++ b/nixos/modules/phoebus/alarm-logger.nix @@ -137,8 +137,16 @@ in { wantedBy = ["multi-user.target"]; - # Weirdly not "phoebus.user" - environment.JAVA_OPTS = "-Djava.util.prefs.userRoot=/var/lib/phoebus-alarm-logger"; + environment = { + # Weirdly not "phoebus.user" + JAVA_OPTS = "-Djava.util.prefs.userRoot=/var/lib/phoebus-alarm-logger"; + + # Our config file is both the config file for phoebus-alarm-logger, + # and for SpringBoot. + # The '-properties' command-line argument is only for phoebus-alarm-logger, + # *not* SpringBoot. + SPRING_CONFIG_IMPORT = configFile; + }; serviceConfig = { ExecStart = let diff --git a/nixos/tests/phoebus/alarm.nix b/nixos/tests/phoebus/alarm.nix index 5db6467b..c845ae8f 100644 --- a/nixos/tests/phoebus/alarm.nix +++ b/nixos/tests/phoebus/alarm.nix @@ -26,7 +26,6 @@ }; server = { - config, lib, pkgs, ... @@ -45,7 +44,10 @@ }; }; - services.phoebus-alarm-logger.settings."bootstrap.servers" = kafkaListenSockAddr; + services.phoebus-alarm-logger.settings = { + "bootstrap.servers" = kafkaListenSockAddr; + "server.port" = 8082; + }; services.apache-kafka = { enable = true; diff --git a/nixos/tests/phoebus/alarm.py b/nixos/tests/phoebus/alarm.py index e6212a96..20a624f3 100644 --- a/nixos/tests/phoebus/alarm.py +++ b/nixos/tests/phoebus/alarm.py @@ -13,7 +13,7 @@ def wait_for_boot(): server.wait_for_unit("phoebus-alarm-logger.service") server.wait_for_open_port(9092, "192.168.1.3") server.wait_for_open_port(9200) - server.wait_for_open_port(8080) + server.wait_for_open_port(8082) ioc.wait_for_unit("ioc.service") @@ -47,7 +47,7 @@ def get_alarm() -> dict[str, Any]: def get_logger(uri: str): - result_s = client.succeed(f"curl 'http://server:8080{uri}'") + result_s = client.succeed(f"curl 'http://server:8082{uri}'") return json.loads(result_s) From 37c2242444a33d8c57cb4d1c74719e5f76b64ecc Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 18 Aug 2024 01:12:02 +0000 Subject: [PATCH 081/111] flake.lock: Update MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Flake lock file updates: • Updated input 'nixpkgs': 'github:NixOS/nixpkgs/05405724efa137a0b899cce5ab4dde463b4fd30b?narHash=sha256-VEdJmVU2eLFtLqCjTYJd1J7%2BGo8idAcZoT11IewFiRg%3D' (2024-08-01) → 'github:NixOS/nixpkgs/c3d4ac725177c030b1e289015989da2ad9d56af0?narHash=sha256-sqLwJcHYeWLOeP/XoLwAtYjr01TISlkOfz%2BNG82pbdg%3D' (2024-08-15) • Updated input 'poetry2nix': 'github:nix-community/poetry2nix/8c25e871bba3f472e1569bbf6c0f52dcc34bf2a4?narHash=sha256-6FVPz1WzHak65xJQg8tRjVyFEWMesGxfskKaCxDUnRk%3D' (2024-08-01) → 'github:nix-community/poetry2nix/d650118bce34c0238b9b54f23f7f173f9e4db867?narHash=sha256-%2BBrHfNuXrqeE7PoV6xDaoh0joYiJkvTTCIV0fFR3THw%3D' (2024-08-17) --- flake.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/flake.lock b/flake.lock index 0d883e33..ee5d83b6 100644 --- a/flake.lock +++ b/flake.lock @@ -95,11 +95,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1722519197, - "narHash": "sha256-VEdJmVU2eLFtLqCjTYJd1J7+Go8idAcZoT11IewFiRg=", + "lastModified": 1723688146, + "narHash": "sha256-sqLwJcHYeWLOeP/XoLwAtYjr01TISlkOfz+NG82pbdg=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "05405724efa137a0b899cce5ab4dde463b4fd30b", + "rev": "c3d4ac725177c030b1e289015989da2ad9d56af0", "type": "github" }, "original": { @@ -120,11 +120,11 @@ "treefmt-nix": "treefmt-nix" }, "locked": { - "lastModified": 1722515463, - "narHash": "sha256-6FVPz1WzHak65xJQg8tRjVyFEWMesGxfskKaCxDUnRk=", + "lastModified": 1723854676, + "narHash": "sha256-+BrHfNuXrqeE7PoV6xDaoh0joYiJkvTTCIV0fFR3THw=", "owner": "nix-community", "repo": "poetry2nix", - "rev": "8c25e871bba3f472e1569bbf6c0f52dcc34bf2a4", + "rev": "d650118bce34c0238b9b54f23f7f173f9e4db867", "type": "github" }, "original": { From 58b561a3ff87dce0604eb68618a245cbd2704812 Mon Sep 17 00:00:00 2001 From: Minijackson Date: Thu, 22 Aug 2024 09:27:40 +0200 Subject: [PATCH 082/111] github: don't persist checkout credentials by default the backport action however still needs the credentials --- .github/workflows/backport.yml | 3 +++ .github/workflows/book-gh-pages.yml | 2 ++ .github/workflows/editorconfig.yml | 2 ++ .github/workflows/formatting.yml | 2 ++ .github/workflows/update-flake-lock.yml | 1 + 5 files changed, 10 insertions(+) diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml index 3968462f..17f4f854 100644 --- a/.github/workflows/backport.yml +++ b/.github/workflows/backport.yml @@ -23,6 +23,9 @@ jobs: - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 with: ref: ${{ github.event.pull_request.head.sha }} + # Credentials are needed to push to a remote branch, + # before creating a pull request + persist-credentials: true - name: Create backport PRs uses: korthout/backport-action@bd410d37cdcae80be6d969823ff5a225fe5c833f # v3.0.2 with: diff --git a/.github/workflows/book-gh-pages.yml b/.github/workflows/book-gh-pages.yml index c85315be..5a604a13 100644 --- a/.github/workflows/book-gh-pages.yml +++ b/.github/workflows/book-gh-pages.yml @@ -24,6 +24,8 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + with: + persist-credentials: false - uses: cachix/install-nix-action@ba0dd844c9180cbf77aa72a116d6fbc515d0e87b # v27 - name: "Build documentation book" run: | diff --git a/.github/workflows/editorconfig.yml b/.github/workflows/editorconfig.yml index d5379ba5..bb1744d0 100644 --- a/.github/workflows/editorconfig.yml +++ b/.github/workflows/editorconfig.yml @@ -11,6 +11,8 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + with: + persist-credentials: false - uses: cachix/install-nix-action@ba0dd844c9180cbf77aa72a116d6fbc515d0e87b # v27 - name: "Check EditorConfig" run: nix run 'nixpkgs#eclint' --inputs-from . diff --git a/.github/workflows/formatting.yml b/.github/workflows/formatting.yml index 13cdb7ac..ee2861d8 100644 --- a/.github/workflows/formatting.yml +++ b/.github/workflows/formatting.yml @@ -11,6 +11,8 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + with: + persist-credentials: false - uses: cachix/install-nix-action@ba0dd844c9180cbf77aa72a116d6fbc515d0e87b # v27 - name: "Check Formatting" run: nix fmt -- --check . diff --git a/.github/workflows/update-flake-lock.yml b/.github/workflows/update-flake-lock.yml index fc1aecc8..536a35c4 100644 --- a/.github/workflows/update-flake-lock.yml +++ b/.github/workflows/update-flake-lock.yml @@ -28,6 +28,7 @@ jobs: - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 with: ref: ${{ matrix.branch }} + persist-credentials: false - uses: cachix/install-nix-action@ba0dd844c9180cbf77aa72a116d6fbc515d0e87b # v27 - uses: DeterminateSystems/update-flake-lock@db4ee38117a597ea8df8f7f75a187dd65093eade # v23 with: From e7ca48bad08a7eab33f9e7bfc4d66e14a56ff34c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 1 Sep 2024 01:21:39 +0000 Subject: [PATCH 083/111] flake.lock: Update MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Flake lock file updates: • Updated input 'nixpkgs': 'github:NixOS/nixpkgs/c3d4ac725177c030b1e289015989da2ad9d56af0?narHash=sha256-sqLwJcHYeWLOeP/XoLwAtYjr01TISlkOfz%2BNG82pbdg%3D' (2024-08-15) → 'github:NixOS/nixpkgs/6e99f2a27d600612004fbd2c3282d614bfee6421?narHash=sha256-eV%2B63gK0Mp7ygCR0Oy4yIYSNcum2VQwnZamHxYTNi%2BM%3D' (2024-08-30) • Updated input 'poetry2nix': 'github:nix-community/poetry2nix/d650118bce34c0238b9b54f23f7f173f9e4db867?narHash=sha256-%2BBrHfNuXrqeE7PoV6xDaoh0joYiJkvTTCIV0fFR3THw%3D' (2024-08-17) → 'github:nix-community/poetry2nix/7619e43c2b48c29e24b88a415256f09df96ec276?narHash=sha256-gD0N0pnKxWJcKtbetlkKOIumS0Zovgxx/nMfOIJIzoI%3D' (2024-08-23) --- flake.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/flake.lock b/flake.lock index ee5d83b6..5f93c7bc 100644 --- a/flake.lock +++ b/flake.lock @@ -95,11 +95,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1723688146, - "narHash": "sha256-sqLwJcHYeWLOeP/XoLwAtYjr01TISlkOfz+NG82pbdg=", + "lastModified": 1725001927, + "narHash": "sha256-eV+63gK0Mp7ygCR0Oy4yIYSNcum2VQwnZamHxYTNi+M=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "c3d4ac725177c030b1e289015989da2ad9d56af0", + "rev": "6e99f2a27d600612004fbd2c3282d614bfee6421", "type": "github" }, "original": { @@ -120,11 +120,11 @@ "treefmt-nix": "treefmt-nix" }, "locked": { - "lastModified": 1723854676, - "narHash": "sha256-+BrHfNuXrqeE7PoV6xDaoh0joYiJkvTTCIV0fFR3THw=", + "lastModified": 1724417163, + "narHash": "sha256-gD0N0pnKxWJcKtbetlkKOIumS0Zovgxx/nMfOIJIzoI=", "owner": "nix-community", "repo": "poetry2nix", - "rev": "d650118bce34c0238b9b54f23f7f173f9e4db867", + "rev": "7619e43c2b48c29e24b88a415256f09df96ec276", "type": "github" }, "original": { From 146f3b34c52ad823def9740cc6cb4c54306e8500 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 Sep 2024 09:25:58 +0000 Subject: [PATCH 084/111] build(deps): bump korthout/backport-action from 3.0.2 to 3.1.0 Bumps [korthout/backport-action](https://github.com/korthout/backport-action) from 3.0.2 to 3.1.0. - [Release notes](https://github.com/korthout/backport-action/releases) - [Commits](https://github.com/korthout/backport-action/compare/bd410d37cdcae80be6d969823ff5a225fe5c833f...be567af183754f6a5d831ae90f648954763f17f5) --- updated-dependencies: - dependency-name: korthout/backport-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/backport.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml index 17f4f854..8e248517 100644 --- a/.github/workflows/backport.yml +++ b/.github/workflows/backport.yml @@ -27,7 +27,7 @@ jobs: # before creating a pull request persist-credentials: true - name: Create backport PRs - uses: korthout/backport-action@bd410d37cdcae80be6d969823ff5a225fe5c833f # v3.0.2 + uses: korthout/backport-action@be567af183754f6a5d831ae90f648954763f17f5 # v3.1.0 with: # Config README: https://github.com/korthout/backport-action#backport-action branch_name: backport/${pull_number}-to-${target_branch} From 996a9485b3f15538029e9c048b2df43954d11b14 Mon Sep 17 00:00:00 2001 From: Minijackson Date: Tue, 6 Aug 2024 10:35:55 +0200 Subject: [PATCH 085/111] pkgs.channel-finder-service: init at 4.7.2 --- pkgs/default.nix | 2 + .../tools/channel-finder/service/default.nix | 53 +++++++++++++++++++ .../service/fix-reproducibility.patch | 13 +++++ 3 files changed, 68 insertions(+) create mode 100644 pkgs/epnix/tools/channel-finder/service/default.nix create mode 100644 pkgs/epnix/tools/channel-finder/service/fix-reproducibility.patch diff --git a/pkgs/default.nix b/pkgs/default.nix index 3a4481bf..6380fd11 100644 --- a/pkgs/default.nix +++ b/pkgs/default.nix @@ -71,6 +71,8 @@ in ca-gateway = callPackage ./epnix/tools/ca-gateway {}; + channel-finder-service = callPackage ./epnix/tools/channel-finder/service {}; + inherit (final.python3Packages) lewis pyepics; inherit (callPackage ./epnix/tools/lewis/lib.nix {}) mkLewisSimulator; diff --git a/pkgs/epnix/tools/channel-finder/service/default.nix b/pkgs/epnix/tools/channel-finder/service/default.nix new file mode 100644 index 00000000..97bc91df --- /dev/null +++ b/pkgs/epnix/tools/channel-finder/service/default.nix @@ -0,0 +1,53 @@ +{ + lib, + epnixLib, + fetchFromGitHub, + jre, + maven, + makeWrapper, +}: +maven.buildMavenPackage rec { + pname = "ChannelFinderService"; + version = "4.7.2"; + + src = fetchFromGitHub { + owner = "ChannelFinder"; + repo = pname; + rev = "refs/tags/ChannelFinder-${version}"; + hash = "sha256-mRZ9lnkSMSW07GjihDJUDsQFE/f0Sn4T1WbwpUTY16Y="; + }; + + patches = [./fix-reproducibility.patch]; + + mvnHash = "sha256-R5lsFM+yn9xc3Wbpy9Js5r9d7IEOJR301mEoz5SGI/0="; + # TODO: remove if this PR is merged: + # https://github.com/ChannelFinder/ChannelFinderService/pull/153 + mvnParameters = "-Dproject.build.outputTimestamp=1980-01-01T00:00:02Z"; + + nativeBuildInputs = [makeWrapper]; + + installPhase = '' + runHook preInstall + + mkdir -p $out/bin + mkdir -p $out/share/java + + jarName="ChannelFinder-${version}.jar" + + install -Dm644 "target/$jarName" "$out/share/java" + + makeWrapper ${lib.getExe jre} $out/bin/${meta.mainProgram} \ + --add-flags "-jar $out/share/java/$jarName" + + runHook postInstall + ''; + + meta = { + description = "A RESTful directory services for a list channels"; + homepage = "https://channelfinder.readthedocs.io/en/latest/"; + mainProgram = "channel-finder-service"; + license = lib.licenses.mit; + maintainers = with epnixLib.maintainers; [minijackson]; + inherit (jre.meta) platforms; + }; +} diff --git a/pkgs/epnix/tools/channel-finder/service/fix-reproducibility.patch b/pkgs/epnix/tools/channel-finder/service/fix-reproducibility.patch new file mode 100644 index 00000000..37066765 --- /dev/null +++ b/pkgs/epnix/tools/channel-finder/service/fix-reproducibility.patch @@ -0,0 +1,13 @@ +diff --git a/pom.xml b/pom.xml +index b878804..7894d94 100644 +--- a/pom.xml ++++ b/pom.xml +@@ -230,7 +230,7 @@ + + org.apache.maven.plugins + maven-jar-plugin +- 3.1.0 ++ 3.3.0 + + + From 2d4c536f8e6dbfdc4942d842f58fc7dc843fdc4a Mon Sep 17 00:00:00 2001 From: Minijackson Date: Tue, 6 Aug 2024 16:32:03 +0200 Subject: [PATCH 086/111] pkgs.python3Packages.channelfinder: init at 3.0.0 --- pkgs/default.nix | 1 + .../channel-finder/pyCFClient/default.nix | 44 +++++++++++++++++++ pkgs/tests/default.nix | 1 + 3 files changed, 46 insertions(+) create mode 100644 pkgs/epnix/tools/channel-finder/pyCFClient/default.nix diff --git a/pkgs/default.nix b/pkgs/default.nix index 6380fd11..383f6f7e 100644 --- a/pkgs/default.nix +++ b/pkgs/default.nix @@ -14,6 +14,7 @@ in ++ [ (final: prev: { lewis = final.callPackage ./epnix/tools/lewis {}; + channelfinder = final.callPackage ./epnix/tools/channel-finder/pyCFClient {}; pyepics = final.callPackage ./epnix/python-modules/pyepics {}; scanf = final.callPackage ./epnix/tools/scanf {}; }) diff --git a/pkgs/epnix/tools/channel-finder/pyCFClient/default.nix b/pkgs/epnix/tools/channel-finder/pyCFClient/default.nix new file mode 100644 index 00000000..9802005f --- /dev/null +++ b/pkgs/epnix/tools/channel-finder/pyCFClient/default.nix @@ -0,0 +1,44 @@ +{ + epnixLib, + lib, + buildPythonPackage, + fetchFromGitHub, + python, + setuptools, + requests, + simplejson, + urllib3, +}: +buildPythonPackage rec { + pname = "channelfinder"; + version = "3.0.0"; + pyproject = true; + + src = fetchFromGitHub { + owner = "ChannelFinder"; + repo = "pyCFClient"; + rev = "refs/tags/v${version}"; + hash = "sha256-83V6OgKUgkui1elroKdVr/KBNriSb9nfo8Ggd68AO/Y="; + }; + + # TODO: when a new version is released, switch to flit-core + build-system = [setuptools]; + + dependencies = [ + requests + simplejson + urllib3 + ]; + + # Tests not run as they need a running ChannelFinder instance + + pythonImportsCheck = ["channelfinder"]; + + meta = { + description = "Python ChannelFinder Client Lib"; + homepage = "https://github.com/ChannelFinder/pyCFClient"; + license = lib.licenses.mit; + maintainers = with epnixLib.maintainers; [minijackson]; + inherit (python.meta) platforms; + }; +} diff --git a/pkgs/tests/default.nix b/pkgs/tests/default.nix index bb76486b..d2979f81 100644 --- a/pkgs/tests/default.nix +++ b/pkgs/tests/default.nix @@ -4,5 +4,6 @@ # For example kernel modules, which depend on the kernel version, # or Python libraries, which depend on the Python version. {pkgs, ...}: { + channelfinder-default-python = pkgs.python3Packages.channelfinder; mrf-driver-default-linux = pkgs.linuxPackages.mrf; } From b62e11c5289941f0613e72555e97b868ff77faad Mon Sep 17 00:00:00 2001 From: Minijackson Date: Tue, 6 Aug 2024 11:19:14 +0200 Subject: [PATCH 087/111] pkgs.python3Packages.recceiver: init at 1.6 --- pkgs/default.nix | 1 + .../channel-finder/recceiver/default.nix | 52 ++++++++ .../recceiver/fix-reactor-import.patch | 120 ++++++++++++++++++ pkgs/tests/default.nix | 1 + 4 files changed, 174 insertions(+) create mode 100644 pkgs/epnix/tools/channel-finder/recceiver/default.nix create mode 100644 pkgs/epnix/tools/channel-finder/recceiver/fix-reactor-import.patch diff --git a/pkgs/default.nix b/pkgs/default.nix index 383f6f7e..5d2eb307 100644 --- a/pkgs/default.nix +++ b/pkgs/default.nix @@ -16,6 +16,7 @@ in lewis = final.callPackage ./epnix/tools/lewis {}; channelfinder = final.callPackage ./epnix/tools/channel-finder/pyCFClient {}; pyepics = final.callPackage ./epnix/python-modules/pyepics {}; + recceiver = final.callPackage ./epnix/tools/channel-finder/recceiver {}; scanf = final.callPackage ./epnix/tools/scanf {}; }) ]; diff --git a/pkgs/epnix/tools/channel-finder/recceiver/default.nix b/pkgs/epnix/tools/channel-finder/recceiver/default.nix new file mode 100644 index 00000000..2ae4ba6a --- /dev/null +++ b/pkgs/epnix/tools/channel-finder/recceiver/default.nix @@ -0,0 +1,52 @@ +{ + epnixLib, + buildPythonPackage, + fetchFromGitHub, + python, + setuptools-scm, + channelfinder, + requests, + twisted, +}: +buildPythonPackage rec { + pname = "RecCeiver"; + version = "1.6"; + pyproject = true; + + src = fetchFromGitHub { + owner = "ChannelFinder"; + repo = "recsync"; + rev = "refs/tags/${version}"; + hash = "sha256-9ApS4e1+oDgZfx7njOuGhezr4ekP2ekJVCc7yiTXRKo="; + }; + + sourceRoot = "${src.name}/server"; + + patches = [ + # Defer Python imports of twisted's reactor, to prevent initializing it, + # preventing the error "reactor already installed" + # TODO: remove when upgrading to the next release + ./fix-reactor-import.patch + ]; + + build-system = [setuptools-scm]; + + dependencies = [ + channelfinder + requests + twisted + ]; + + pythonImportsCheck = [ + "recceiver" + "recceiver.cfstore" + ]; + + meta = { + description = "Collects reccaster reports on the state of IOCs within the corresponding subnet and updates ChannelFinder"; + homepage = "https://channelfinder.readthedocs.io/en/latest/"; + license = epnixLib.licenses.epics; + maintainers = with epnixLib.maintainers; [minijackson]; + inherit (python.meta) platforms; + }; +} diff --git a/pkgs/epnix/tools/channel-finder/recceiver/fix-reactor-import.patch b/pkgs/epnix/tools/channel-finder/recceiver/fix-reactor-import.patch new file mode 100644 index 00000000..34bdd39d --- /dev/null +++ b/pkgs/epnix/tools/channel-finder/recceiver/fix-reactor-import.patch @@ -0,0 +1,120 @@ +diff --git a/recceiver/announce.py b/recceiver/announce.py +index f315e46..10be4a6 100644 +--- a/recceiver/announce.py ++++ b/recceiver/announce.py +@@ -3,7 +3,7 @@ + import sys + import struct + +-from twisted.internet import protocol, reactor ++from twisted.internet import protocol + import logging + + _log = logging.getLogger(__name__) +@@ -14,12 +14,14 @@ + __all__ = ['Announcer'] + + class Announcer(protocol.DatagramProtocol): +- reactor = reactor +- + def __init__(self, tcpport, key=0, + tcpaddr='\xff\xff\xff\xff', + udpaddrs=[('',5049)], + period=15.0): ++ from twisted.internet import reactor ++ ++ self.reactor = reactor ++ + if sys.version_info[0] < 3: + self.msg = _Ann.pack(0x5243, 0, tcpaddr, tcpport, 0, key) + else: +diff --git a/recceiver/application.py b/recceiver/application.py +index 50da82b..9bee474 100644 +--- a/recceiver/application.py ++++ b/recceiver/application.py +@@ -7,7 +7,7 @@ + + from twisted import plugin + from twisted.python import usage, log +-from twisted.internet import reactor, defer ++from twisted.internet import defer + from twisted.internet.error import CannotListenError + from twisted.application import service + +@@ -31,9 +31,12 @@ def flush(self): + pass + + class RecService(service.MultiService): +- reactor = reactor + + def __init__(self, config): ++ from twisted.internet import reactor ++ ++ self.reactor = reactor ++ + service.MultiService.__init__(self) + self.annperiod = float(config.get('announceInterval', '15.0')) + self.tcptimeout = float(config.get('tcptimeout', '15.0')) +diff --git a/recceiver/recast.py b/recceiver/recast.py +index 6f6fce2..daa91b4 100644 +--- a/recceiver/recast.py ++++ b/recceiver/recast.py +@@ -16,7 +16,6 @@ + from twisted.protocols import stateful + from twisted.internet import defer + from twisted.internet import protocol +-from twisted.internet import reactor + + from .interfaces import ITransaction + +@@ -42,11 +41,14 @@ + + class CastReceiver(stateful.StatefulProtocol): + +- reactor = reactor + timeout = 3.0 + version = 0 + + def __init__(self, active=True): ++ from twisted.internet import reactor ++ ++ self.reactor = reactor ++ + self.sess, self.active = None, active + self.uploadSize, self.uploadStart = 0, 0 + +@@ -238,9 +240,12 @@ def __str__(self): + class CollectionSession(object): + timeout = 5.0 + trlimit = 0 +- reactor = reactor + + def __init__(self, proto, endpoint): ++ from twisted.internet import reactor ++ ++ self.reactor = reactor ++ + _log.info("Open session from %s",endpoint) + self.proto, self.ep = proto, endpoint + self.TR = Transaction(self.ep, id(self)) +diff --git a/recceiver/udpbcast.py b/recceiver/udpbcast.py +index 1f424aa..1b28a61 100644 +--- a/recceiver/udpbcast.py ++++ b/recceiver/udpbcast.py +@@ -1,6 +1,6 @@ + # -*- coding: utf-8 -*- + +-from twisted.internet import udp, reactor ++from twisted.internet import udp + from twisted.application import internet + + __all__ = ['SharedUDP','SharedUDPServer'] +@@ -29,6 +29,8 @@ class SharedUDPServer(internet.UDPServer): + """A UDP server using SharedUDP + """ + def _getPort(self): ++ from twisted.internet import reactor ++ + R = getattr(self, 'reactor', reactor) + port = SharedUDP(reactor=R, *self.args, **self.kwargs) + port.startListening() diff --git a/pkgs/tests/default.nix b/pkgs/tests/default.nix index d2979f81..9181d16e 100644 --- a/pkgs/tests/default.nix +++ b/pkgs/tests/default.nix @@ -6,4 +6,5 @@ {pkgs, ...}: { channelfinder-default-python = pkgs.python3Packages.channelfinder; mrf-driver-default-linux = pkgs.linuxPackages.mrf; + recceiver-default-python = pkgs.python3Packages.recceiver; } From fa16edba84d79980e9fe4a79788192f9efd0aa1d Mon Sep 17 00:00:00 2001 From: Minijackson Date: Tue, 6 Aug 2024 11:31:45 +0200 Subject: [PATCH 088/111] pkgs.support.reccaster: init at 1.6 --- pkgs/default.nix | 1 + pkgs/epnix/support/reccaster/default.nix | 36 +++++++++++++++++++ .../reccaster/fix-example-shebang.patch | 20 +++++++++++ 3 files changed, 57 insertions(+) create mode 100644 pkgs/epnix/support/reccaster/default.nix create mode 100644 pkgs/epnix/support/reccaster/fix-example-shebang.patch diff --git a/pkgs/default.nix b/pkgs/default.nix index 5d2eb307..9fcee2c1 100644 --- a/pkgs/default.nix +++ b/pkgs/default.nix @@ -60,6 +60,7 @@ in mrfioc2 = callPackage ./epnix/support/mrfioc2 {}; opcua = callPackage ./epnix/support/opcua {open62541 = self.open62541_1_3;}; pvxs = callPackage ./epnix/support/pvxs {}; + reccaster = callPackage ./epnix/support/reccaster {}; seq = callPackage ./epnix/support/seq {}; snmp = callPackage ./epnix/support/snmp {}; sscan = callPackage ./epnix/support/sscan {}; diff --git a/pkgs/epnix/support/reccaster/default.nix b/pkgs/epnix/support/reccaster/default.nix new file mode 100644 index 00000000..a1440ce2 --- /dev/null +++ b/pkgs/epnix/support/reccaster/default.nix @@ -0,0 +1,36 @@ +{ + epnixLib, + mkEpicsPackage, + fetchFromGitHub, + local_config_site ? {}, + local_release ? {}, +}: +mkEpicsPackage rec { + pname = "RecCaster"; + version = "1.6"; + varname = "RECCASTER"; + + inherit local_config_site local_release; + + src = fetchFromGitHub { + owner = "ChannelFinder"; + repo = "recsync"; + rev = "refs/tags/${version}"; + hash = "sha256-9ApS4e1+oDgZfx7njOuGhezr4ekP2ekJVCc7yiTXRKo="; + }; + + sourceRoot = "${src.name}/client"; + + patches = [./fix-example-shebang.patch]; + + postInstall = '' + cp -rafv iocBoot -t "$out" + ''; + + meta = { + description = "Informs ChannelFinder of the state of the IOC and the list of PVs contained in that IOC"; + homepage = "https://channelfinder.readthedocs.io/en/latest/"; + license = epnixLib.licenses.epics; + maintainers = with epnixLib.maintainers; [minijackson]; + }; +} diff --git a/pkgs/epnix/support/reccaster/fix-example-shebang.patch b/pkgs/epnix/support/reccaster/fix-example-shebang.patch new file mode 100644 index 00000000..bd7c0db2 --- /dev/null +++ b/pkgs/epnix/support/reccaster/fix-example-shebang.patch @@ -0,0 +1,20 @@ +diff --git a/iocBoot/iocdemo/st.cmd b/iocBoot/iocdemo/st.cmd +index 2dd8cda..4c39612 100755 +--- a/iocBoot/iocdemo/st.cmd ++++ b/iocBoot/iocdemo/st.cmd +@@ -1,4 +1,4 @@ +-#!../../bin/linux-x86_64-debug/demo ++#!../../bin/linux-x86_64/demo + + ## You may have to change demo to something else + ## everywhere it appears in this file +diff --git a/iocBoot/iocdemo/st_test.cmd b/iocBoot/iocdemo/st_test.cmd +index 420f865..12a74b7 100755 +--- a/iocBoot/iocdemo/st_test.cmd ++++ b/iocBoot/iocdemo/st_test.cmd +@@ -1,4 +1,4 @@ +-#!../../bin/linux-x86_64-debug/demo ++#!../../bin/linux-x86_64/demo + + ## You may have to change demo to something else + ## everywhere it appears in this file From 8a0561ac4f5f815e517469b582ddfd139e429ba4 Mon Sep 17 00:00:00 2001 From: Minijackson Date: Wed, 28 Aug 2024 14:44:42 +0200 Subject: [PATCH 089/111] nixos/channel-finder: init module --- nixos/module-list.nix | 1 + nixos/modules/channel-finder/service.nix | 216 +++++++++++++++++++++++ 2 files changed, 217 insertions(+) create mode 100644 nixos/modules/channel-finder/service.nix diff --git a/nixos/module-list.nix b/nixos/module-list.nix index 52cb3bae..f0db4b67 100644 --- a/nixos/module-list.nix +++ b/nixos/module-list.nix @@ -1,6 +1,7 @@ [ ./modules/archiver-appliance.nix ./modules/ca-gateway.nix + ./modules/channel-finder/service.nix ./modules/phoebus/alarm-logger.nix ./modules/phoebus/alarm-server.nix ./modules/phoebus/olog.nix diff --git a/nixos/modules/channel-finder/service.nix b/nixos/modules/channel-finder/service.nix new file mode 100644 index 00000000..bd915543 --- /dev/null +++ b/nixos/modules/channel-finder/service.nix @@ -0,0 +1,216 @@ +{ + config, + epnixLib, + lib, + pkgs, + ... +}: let + cfg = config.services.channel-finder; + settingsFormat = pkgs.formats.javaProperties {}; + configFile = settingsFormat.generate "channel-finder.properties" cfg.settings; +in { + options.services.channel-finder = { + enable = lib.mkEnableOption "the ChannelFinder service"; + + openFirewall = lib.mkOption { + description = '' + Open the firewall for the ChannelFinder service. + + ```{warning} + This opens the firewall on all network interfaces. + ``` + + This option opens firewall for the HTTP/HTTPS API, + and pvAccess server. + ''; + type = lib.types.bool; + default = false; + }; + + settings = lib.mkOption { + description = '' + Configuration for the ChannelFinder service. + + These options will be put into a `.properties` file. + + Note that options containing a "." must be quoted. + + See upstream documentation for all supported options: + + ''; + default = {}; + type = lib.types.submodule { + freeformType = settingsFormat.type; + options = { + "server.port" = lib.mkOption { + type = lib.types.port; + default = 8443; + # TODO: Weirdness of the javaProperties format? + # It says it supports integers and booleans, but during the build + # only accepts strings? + apply = toString; + description = "The HTTPS server port for the ChannelFinder service"; + }; + + "server.http.enable" = lib.mkOption { + type = lib.types.bool; + default = true; + apply = lib.boolToString; + description = "Enable unsecure HTTP"; + }; + + "server.http.port" = lib.mkOption { + type = lib.types.port; + default = 8080; + apply = toString; + description = "The HTTP server port for the ChannelFinder service"; + }; + + "elasticsearch.host_urls" = lib.mkOption { + type = with lib.types; listOf str; + default = ["http://localhost:9200"]; + description = '' + List of URLs for the Elasticsearch hosts. + + All hosts listed here must belong to the same Elasticsearch cluster. + ''; + apply = lib.concatStringsSep ","; + }; + + "elasticsearch.create.indices" = lib.mkOption { + type = lib.types.bool; + default = true; + description = '' + List of URLs for the Elasticsearch hosts. + + All hosts listed here must belong to the same Elasticsearch cluster. + ''; + apply = lib.boolToString; + }; + + "demo_auth.enabled" = lib.mkOption { + type = lib.types.bool; + default = false; + apply = lib.boolToString; + description = '' + Enable the demo authentication. + + ChannelFinder will provide two users: + + - `admin:adminPass` + - `user:userPass` + ''; + }; + + "ldap.enabled" = lib.mkOption { + type = lib.types.bool; + default = false; + apply = lib.boolToString; + description = '' + Enable authenticating to an external LDAP server. + ''; + }; + + "embedded_ldap.enabled" = lib.mkOption { + type = lib.types.bool; + default = false; + apply = lib.boolToString; + description = '' + Enable the embedded LDAP authentication. + ''; + }; + }; + }; + }; + }; + + config = lib.mkIf cfg.enable { + assertions = [ + { + assertion = with cfg; + settings."ldap.enabled" + == "true" + || settings."embedded_ldap.enabled" == "true" + || settings."demo_auth.enabled" == "true"; + message = "One type of authentication for Phoebus Olog must be provided"; + } + ]; + + networking.firewall = lib.mkIf cfg.openFirewall { + allowedTCPPorts = [ + (lib.toInt cfg.settings."server.port") + (lib.mkIf (cfg.settings."server.http.enable" == "true") ( + lib.toInt cfg.settings."server.http.port" or "8080" + )) + + # pvAccess + 5075 + ]; + allowedUDPPorts = [5076]; + }; + + systemd.services.channel-finder = { + inherit (pkgs.epnix.channel-finder-service.meta) description; + + wantedBy = ["multi-user.target"]; + after = ["elasticsearch.service"]; + + serviceConfig = { + ExecStart = "${lib.getExe pkgs.epnix.channel-finder-service} --spring.config.location=file://${configFile}"; + DynamicUser = true; + Restart = "on-failure"; + + # Security options: + # --- + + RestrictAddressFamilies = ["AF_INET" "AF_INET6"]; + # Service may not create new namespaces + RestrictNamespaces = true; + + # Service does not have access to other users + PrivateUsers = true; + # Service has no access to hardware devices + PrivateDevices = true; + + # Service cannot write to the hardware clock or system clock + ProtectClock = true; + # Service cannot modify the control group file system + ProtectControlGroups = true; + # Service has no access to home directories + ProtectHome = true; + # Service cannot change system host/domainname + ProtectHostname = true; + # Service cannot read from or write to the kernel log ring buffer + ProtectKernelLogs = true; + # Service cannot load or read kernel modules + ProtectKernelModules = true; + # Service cannot alter kernel tunables (/proc/sys, …) + ProtectKernelTunables = true; + # Service has restricted access to process tree (/proc hidepid=) + ProtectProc = "invisible"; + + # Service may not acquire new capabilities + CapabilityBoundingSet = ""; + # Service cannot change ABI personality + LockPersonality = true; + # Service has no access to non-process /proc files (/proc subset=) + ProcSubset = "pid"; + # Service may execute system calls only with native ABI + SystemCallArchitectures = "native"; + # Access write directories + UMask = "0077"; + # Service may create writable executable memory mappings + # This option isn't set due to the JVM marking some memory pages as executable + #MemoryDenyWriteExecute = true; + + # Service can only use a reasonable set of system calls, + # used by common system services + SystemCallFilter = ["@system-service"]; + # Disallowed system calls return EPERM instead of terminating the service + SystemCallErrorNumber = "EPERM"; + }; + }; + }; + + meta.maintainers = with epnixLib.maintainers; [minijackson]; +} From c80b472fd26ceb2a864a1986f791e6875dd5f621 Mon Sep 17 00:00:00 2001 From: Minijackson Date: Wed, 28 Aug 2024 14:45:52 +0200 Subject: [PATCH 090/111] nixos/recceiver: init module --- nixos/module-list.nix | 1 + nixos/modules/channel-finder/recceiver.nix | 215 +++++++++++++++++++++ 2 files changed, 216 insertions(+) create mode 100644 nixos/modules/channel-finder/recceiver.nix diff --git a/nixos/module-list.nix b/nixos/module-list.nix index f0db4b67..399e1d06 100644 --- a/nixos/module-list.nix +++ b/nixos/module-list.nix @@ -1,6 +1,7 @@ [ ./modules/archiver-appliance.nix ./modules/ca-gateway.nix + ./modules/channel-finder/recceiver.nix ./modules/channel-finder/service.nix ./modules/phoebus/alarm-logger.nix ./modules/phoebus/alarm-server.nix diff --git a/nixos/modules/channel-finder/recceiver.nix b/nixos/modules/channel-finder/recceiver.nix new file mode 100644 index 00000000..065d851c --- /dev/null +++ b/nixos/modules/channel-finder/recceiver.nix @@ -0,0 +1,215 @@ +{ + config, + epnixLib, + lib, + pkgs, + ... +}: let + cfg = config.services.recceiver; + + pkg = pkgs.python3Packages.recceiver; + python = pkgs.python3.withPackages ( + ps: [ + ps.recceiver + ps.twisted + ] + ); + + settingsFormat = pkgs.formats.ini {}; + configFile = settingsFormat.generate "recceiver.conf" cfg.settings; + channelfinderapiConfFile = settingsFormat.generate "channelfinderapi.conf" cfg.channelfinderapi; +in { + options.services.recceiver = { + enable = lib.mkEnableOption "the RecCeiver service"; + + channelfinderapi = lib.mkOption { + description = '' + Configuration for the ChannelFinder client. + + See upstream documentation for all supported options: + + ''; + default = {}; + type = lib.types.submodule { + freeformType = settingsFormat.type; + options.DEFAULT = { + BaseURL = lib.mkOption { + type = lib.types.str; + default = "http://localhost:8080/ChannelFinder"; + description = "URL of the remote ChannelFinder server."; + }; + + username = lib.mkOption { + type = with lib.types; nullOr str; + default = null; + description = "Username for authentication."; + }; + + password = lib.mkOption { + type = with lib.types; nullOr str; + default = null; + description = "Password for authentication."; + }; + }; + }; + }; + + settings = lib.mkOption { + description = '' + Configuration for the RecCeiver service. + + See upstream documentation for all supported options: + + ''; + default = {}; + type = lib.types.submodule { + freeformType = settingsFormat.type; + options = { + recceiver = { + bind = lib.mkOption { + type = lib.types.str; + default = "0.0.0.0:0"; + description = '' + Listen for TCP connections on this interface and port. + + Port also used as source for UDP broadcasts + + Default uses wildcard address and a random port. + ''; + }; + + addrlist = lib.mkOption { + type = with lib.types; listOf str; + default = ["255.255.255.255:5049"]; + apply = lib.concatStringsSep ","; + description = '' + Listen for TCP connections on this interface and port. + + Port also used as source for UDP broadcasts + + Default uses wildcard address and a random port. + ''; + }; + + procs = lib.mkOption { + type = with lib.types; listOf str; + default = ["show"]; + example = ["show" "cf"]; + apply = lib.concatStringsSep ","; + description = '' + Processing chain, sequence of plugin names. + + Plugin names may be followed by an instance name (eg. `db:arbitrary`) + which allows for more than one instance of a plugin with different + configuration. + + Default plugins: + + `show` + : Prints information to daemon log + + `db` + : Stores in sqlite3 database + + `cf` + : Stores in a ChannelFinder server + ''; + }; + }; + + cf = { + environment_vars = lib.mkOption { + type = with lib.types; attrsOf str; + default = {}; + example = { + ENGINEER = "Engineer"; + EPICS_BASE = "EpicsVersion"; + PWD = "WorkingDirectory"; + }; + apply = val: lib.concatStringsSep "," (lib.mapAttrsToList (k: v: "${k}:${v}") val); + description = '' + Attribute set of `VARIABLE = "PropertyName";` + + Specifies which environment `VARIABLE`s to pass on to the ChannelFinder server, + and defining the corresponding `PropertyName`. + ''; + }; + }; + }; + }; + }; + }; + + config = lib.mkIf cfg.enable { + systemd.services.recceiver = { + inherit (pkg.meta) description; + + wantedBy = ["multi-user.target"]; + after = ["channel-finder.service"]; + + preStart = '' + ln -sfn "${channelfinderapiConfFile}" "$STATE_DIRECTORY/channelfinderapi.conf" + ''; + + serviceConfig = { + ExecStart = "${python}/bin/twistd --nodaemon --no_save --reactor=poll --pidfile= --logfile=- recceiver --config=${configFile}"; + DynamicUser = true; + Restart = "on-failure"; + StateDirectory = "recceiver"; + + # channelfinderapi.conf needs to be in the working directory + WorkingDirectory = "/var/lib/recceiver"; + + # Security options: + # --- + + RestrictAddressFamilies = ["AF_INET" "AF_INET6"]; + # Service may not create new namespaces + RestrictNamespaces = true; + + # Service does not have access to other users + PrivateUsers = true; + # Service has no access to hardware devices + PrivateDevices = true; + + # Service cannot write to the hardware clock or system clock + ProtectClock = true; + # Service cannot modify the control group file system + ProtectControlGroups = true; + # Service has no access to home directories + ProtectHome = true; + # Service cannot change system host/domainname + ProtectHostname = true; + # Service cannot read from or write to the kernel log ring buffer + ProtectKernelLogs = true; + # Service cannot load or read kernel modules + ProtectKernelModules = true; + # Service cannot alter kernel tunables (/proc/sys, …) + ProtectKernelTunables = true; + # Service has restricted access to process tree (/proc hidepid=) + ProtectProc = "invisible"; + + # Service may not acquire new capabilities + CapabilityBoundingSet = ""; + # Service cannot change ABI personality + LockPersonality = true; + # Service has no access to non-process /proc files (/proc subset=) + ProcSubset = "pid"; + # Service may execute system calls only with native ABI + SystemCallArchitectures = "native"; + # Access write directories + UMask = "0077"; + # Service may not create writable executable memory mappings + MemoryDenyWriteExecute = true; + + # Service can only use a reasonable set of system calls, + # used by common system services + SystemCallFilter = ["@system-service"]; + # Disallowed system calls return EPERM instead of terminating the service + SystemCallErrorNumber = "EPERM"; + }; + }; + }; + + meta.maintainers = with epnixLib.maintainers; [minijackson]; +} From 2c16126bfaac2268e338fc3bf9cfd7b3a8cb4809 Mon Sep 17 00:00:00 2001 From: Minijackson Date: Wed, 28 Aug 2024 14:52:34 +0200 Subject: [PATCH 091/111] nixos/test: init channel-finder test --- nixos/tests/all-tests.nix | 1 + nixos/tests/channel-finder/default.nix | 97 ++++++++++++++ nixos/tests/channel-finder/ioc.nix | 13 ++ nixos/tests/channel-finder/ioc/.gitignore | 32 +++++ nixos/tests/channel-finder/ioc/Makefile | 31 +++++ .../tests/channel-finder/ioc/configure/CONFIG | 45 +++++++ .../channel-finder/ioc/configure/CONFIG_SITE | 43 +++++++ .../channel-finder/ioc/configure/Makefile | 8 ++ .../channel-finder/ioc/configure/RELEASE | 42 ++++++ .../tests/channel-finder/ioc/configure/RULES | 6 + .../channel-finder/ioc/configure/RULES.ioc | 2 + .../channel-finder/ioc/configure/RULES_DIRS | 2 + .../channel-finder/ioc/configure/RULES_TOP | 3 + .../tests/channel-finder/ioc/iocBoot/Makefile | 6 + .../ioc/iocBoot/iocSimple/Makefile | 5 + .../ioc/iocBoot/iocSimple/st.cmd | 27 ++++ .../channel-finder/ioc/simpleApp/Db/Makefile | 18 +++ .../channel-finder/ioc/simpleApp/Db/simple.db | 13 ++ .../channel-finder/ioc/simpleApp/Makefile | 14 ++ .../channel-finder/ioc/simpleApp/src/Makefile | 39 ++++++ .../ioc/simpleApp/src/simpleMain.cpp | 23 ++++ nixos/tests/channel-finder/test_script.py | 121 ++++++++++++++++++ 22 files changed, 591 insertions(+) create mode 100644 nixos/tests/channel-finder/default.nix create mode 100644 nixos/tests/channel-finder/ioc.nix create mode 100644 nixos/tests/channel-finder/ioc/.gitignore create mode 100644 nixos/tests/channel-finder/ioc/Makefile create mode 100644 nixos/tests/channel-finder/ioc/configure/CONFIG create mode 100644 nixos/tests/channel-finder/ioc/configure/CONFIG_SITE create mode 100644 nixos/tests/channel-finder/ioc/configure/Makefile create mode 100644 nixos/tests/channel-finder/ioc/configure/RELEASE create mode 100644 nixos/tests/channel-finder/ioc/configure/RULES create mode 100644 nixos/tests/channel-finder/ioc/configure/RULES.ioc create mode 100644 nixos/tests/channel-finder/ioc/configure/RULES_DIRS create mode 100644 nixos/tests/channel-finder/ioc/configure/RULES_TOP create mode 100644 nixos/tests/channel-finder/ioc/iocBoot/Makefile create mode 100644 nixos/tests/channel-finder/ioc/iocBoot/iocSimple/Makefile create mode 100644 nixos/tests/channel-finder/ioc/iocBoot/iocSimple/st.cmd create mode 100644 nixos/tests/channel-finder/ioc/simpleApp/Db/Makefile create mode 100644 nixos/tests/channel-finder/ioc/simpleApp/Db/simple.db create mode 100644 nixos/tests/channel-finder/ioc/simpleApp/Makefile create mode 100644 nixos/tests/channel-finder/ioc/simpleApp/src/Makefile create mode 100644 nixos/tests/channel-finder/ioc/simpleApp/src/simpleMain.cpp create mode 100644 nixos/tests/channel-finder/test_script.py diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index 01289bc3..e1f05e53 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -17,6 +17,7 @@ in { archiver-appliance = handleTest ./archiver-appliance {}; ca-gateway = handleTest ./ca-gateway.nix {}; + channel-finder = handleTest ./channel-finder {}; phoebus-alarm = handleTest ./phoebus/alarm.nix {}; phoebus-olog = handleTest ./phoebus/olog.nix {}; phoebus-save-and-restore = handleTest ./phoebus/save-and-restore.nix {}; diff --git a/nixos/tests/channel-finder/default.nix b/nixos/tests/channel-finder/default.nix new file mode 100644 index 00000000..e01364de --- /dev/null +++ b/nixos/tests/channel-finder/default.nix @@ -0,0 +1,97 @@ +{ + lib, + epnixLib, + pkgs, + ... +}: let + inherit (pkgs.stdenv.hostPlatform) system; + + iocConfig = epnixLib.evalEpnixModules { + nixpkgsConfig.system = system; + epnixConfig.imports = [./ioc.nix]; + }; + + iocService = iocConfig.config.epnix.nixos.services.ioc.config; +in { + name = "channel-finder-simple-check"; + meta.maintainers = with epnixLib.maintainers; [minijackson]; + + nodes = let + serverPort = 5050; + announcerPort = 5049; + in { + server = {pkgs, ...}: { + environment.systemPackages = [pkgs.epnix.epics-base]; + + services.recceiver = { + enable = lib.mkDefault true; + + channelfinderapi.DEFAULT = { + BaseURL = "http://localhost:8082/ChannelFinder"; + username = "admin"; + password = "adminPass"; + }; + + settings = { + recceiver = { + loglevel = "DEBUG"; + bind = "0.0.0.0:${toString serverPort}"; + addrlist = ["192.168.1.255:${toString announcerPort}"]; + procs = ["show" "cf"]; + }; + cf = { + alias = "on"; + recordDesc = "on"; + recordType = "on"; + environment_vars = { + ENGINEER = "Engineer"; + EPICS_BASE = "EpicsBase"; + EPICS_VERSION = "EpicsVersion"; + PWD = "WorkingDirectory"; + }; + }; + }; + }; + + networking.firewall.allowedTCPPorts = [serverPort]; + + services.channel-finder = { + enable = true; + openFirewall = true; + settings = { + "demo_auth.enabled" = true; + "server.port" = 8444; + "server.http.port" = 8082; + }; + }; + + services.elasticsearch = { + enable = true; + package = pkgs.elasticsearch7; + }; + + nixpkgs.config.allowUnfreePredicate = pkg: + builtins.elem (lib.getName pkg) [ + # Elasticsearch can be used as an SSPL-licensed software, which is + # not open-source. But as we're using it run tests, not exposing + # any service, this should be fine. + "elasticsearch" + ]; + + # Else some applications might get killed by the OOM killer + virtualisation.memorySize = 2047; + }; + + client = { + environment.systemPackages = [pkgs.epnix.epics-base]; + systemd.services.ioc = iocService; + networking.firewall.allowedUDPPorts = [announcerPort]; + }; + }; + + extraPythonPackages = p: [p.json5]; + # Type checking on extra packages doesn't work yet + skipTypeCheck = true; + + testScript = builtins.readFile ./test_script.py; +} diff --git a/nixos/tests/channel-finder/ioc.nix b/nixos/tests/channel-finder/ioc.nix new file mode 100644 index 00000000..32f5dc85 --- /dev/null +++ b/nixos/tests/channel-finder/ioc.nix @@ -0,0 +1,13 @@ +{pkgs, ...}: { + epnix = { + meta.name = "channel-finder-test-ioc"; + buildConfig.src = ./ioc; + + support.modules = [pkgs.epnix.support.reccaster]; + + nixos.services.ioc = { + app = "simple"; + ioc = "iocSimple"; + }; + }; +} diff --git a/nixos/tests/channel-finder/ioc/.gitignore b/nixos/tests/channel-finder/ioc/.gitignore new file mode 100644 index 00000000..8b27edce --- /dev/null +++ b/nixos/tests/channel-finder/ioc/.gitignore @@ -0,0 +1,32 @@ +# Install directories +/bin/ +/cfg/ +/db/ +/dbd/ +/html/ +/include/ +/lib/ +/templates/ + +# Local configuration files +/configure/*.local + +# iocBoot generated files +/iocBoot/*ioc*/cdCommands +/iocBoot/*ioc*/dllPath.bat +/iocBoot/*ioc*/envPaths +/iocBoot/*ioc*/relPaths.sh + +# iocsh +.iocsh_history + +# Build directories +O.*/ + +# Common files created by other tools +/QtC-* +/.vscode/ +*.orig +*.log +.*.swp +.DS_Store diff --git a/nixos/tests/channel-finder/ioc/Makefile b/nixos/tests/channel-finder/ioc/Makefile new file mode 100644 index 00000000..19c9068d --- /dev/null +++ b/nixos/tests/channel-finder/ioc/Makefile @@ -0,0 +1,31 @@ +# Makefile at top of application tree +TOP = . +include $(TOP)/configure/CONFIG + +# Directories to build, any order +DIRS += configure +DIRS += $(wildcard *Sup) +DIRS += $(wildcard *App) +DIRS += $(wildcard *Top) +DIRS += $(wildcard iocBoot) + +# The build order is controlled by these dependency rules: + +# All dirs except configure depend on configure +$(foreach dir, $(filter-out configure, $(DIRS)), \ + $(eval $(dir)_DEPEND_DIRS += configure)) + +# Any *App dirs depend on all *Sup dirs +$(foreach dir, $(filter %App, $(DIRS)), \ + $(eval $(dir)_DEPEND_DIRS += $(filter %Sup, $(DIRS)))) + +# Any *Top dirs depend on all *Sup and *App dirs +$(foreach dir, $(filter %Top, $(DIRS)), \ + $(eval $(dir)_DEPEND_DIRS += $(filter %Sup %App, $(DIRS)))) + +# iocBoot depends on all *App dirs +iocBoot_DEPEND_DIRS += $(filter %App,$(DIRS)) + +# Add any additional dependency rules here: + +include $(TOP)/configure/RULES_TOP diff --git a/nixos/tests/channel-finder/ioc/configure/CONFIG b/nixos/tests/channel-finder/ioc/configure/CONFIG new file mode 100644 index 00000000..34ace577 --- /dev/null +++ b/nixos/tests/channel-finder/ioc/configure/CONFIG @@ -0,0 +1,45 @@ +# CONFIG - Load build configuration data +# +# Do not make changes to this file! + +# Allow user to override where the build rules come from +RULES = $(EPICS_BASE) + +# RELEASE files point to other application tops +include $(TOP)/configure/RELEASE +-include $(TOP)/configure/RELEASE.$(EPICS_HOST_ARCH).Common + +ifdef T_A + -include $(TOP)/configure/RELEASE.Common.$(T_A) + -include $(TOP)/configure/RELEASE.$(EPICS_HOST_ARCH).$(T_A) +endif + +# Check EPICS_BASE is set properly +ifneq (file,$(origin EPICS_BASE)) + $(error EPICS_BASE must be set in a configure/RELEASE file) +else + ifeq ($(wildcard $(EPICS_BASE)/configure/CONFIG_BASE),) + $(error EPICS_BASE does not point to an EPICS installation) + endif +endif + +CONFIG = $(RULES)/configure +include $(CONFIG)/CONFIG + +# Override the Base definition: +INSTALL_LOCATION = $(TOP) + +# CONFIG_SITE files contain local build configuration settings +include $(TOP)/configure/CONFIG_SITE + +# Host-arch specific settings +-include $(TOP)/configure/CONFIG_SITE.$(EPICS_HOST_ARCH).Common + +ifdef T_A + # Target-arch specific settings + -include $(TOP)/configure/CONFIG_SITE.Common.$(T_A) + + # Host & target specific settings + -include $(TOP)/configure/CONFIG_SITE.$(EPICS_HOST_ARCH).$(T_A) +endif + diff --git a/nixos/tests/channel-finder/ioc/configure/CONFIG_SITE b/nixos/tests/channel-finder/ioc/configure/CONFIG_SITE new file mode 100644 index 00000000..212485eb --- /dev/null +++ b/nixos/tests/channel-finder/ioc/configure/CONFIG_SITE @@ -0,0 +1,43 @@ +# CONFIG_SITE + +# Make any application-specific changes to the EPICS build +# configuration variables in this file. +# +# Host/target specific settings can be specified in files named +# CONFIG_SITE.$(EPICS_HOST_ARCH).Common +# CONFIG_SITE.Common.$(T_A) +# CONFIG_SITE.$(EPICS_HOST_ARCH).$(T_A) + +# CHECK_RELEASE controls the consistency checking of the support +# applications pointed to by the RELEASE* files. +# Normally CHECK_RELEASE should be set to YES. +# Set CHECK_RELEASE to NO to disable checking completely. +# Set CHECK_RELEASE to WARN to perform consistency checking but +# continue building even if conflicts are found. +CHECK_RELEASE = YES + +# Set this when you only want to compile this application +# for a subset of the cross-compiled target architectures +# that Base is built for. +#CROSS_COMPILER_TARGET_ARCHS = vxWorks-ppc32 + +# To install files into a location other than $(TOP) define +# INSTALL_LOCATION here. +#INSTALL_LOCATION= + +# Set this when the IOC and build host use different paths +# to the install location. This may be needed to boot from +# a Microsoft FTP server say, or on some NFS configurations. +#IOCS_APPL_TOP = + +# For application debugging purposes, override the HOST_OPT and/ +# or CROSS_OPT settings from base/configure/CONFIG_SITE +#HOST_OPT = NO +#CROSS_OPT = NO + +# These allow developers to override the CONFIG_SITE variable +# settings without having to modify the configure/CONFIG_SITE +# file itself. +-include $(TOP)/../CONFIG_SITE.local +-include $(TOP)/configure/CONFIG_SITE.local + diff --git a/nixos/tests/channel-finder/ioc/configure/Makefile b/nixos/tests/channel-finder/ioc/configure/Makefile new file mode 100644 index 00000000..92543094 --- /dev/null +++ b/nixos/tests/channel-finder/ioc/configure/Makefile @@ -0,0 +1,8 @@ +TOP=.. + +include $(TOP)/configure/CONFIG + +TARGETS = $(CONFIG_TARGETS) +CONFIGS += $(subst ../,,$(wildcard $(CONFIG_INSTALLS))) + +include $(TOP)/configure/RULES diff --git a/nixos/tests/channel-finder/ioc/configure/RELEASE b/nixos/tests/channel-finder/ioc/configure/RELEASE new file mode 100644 index 00000000..19ed8920 --- /dev/null +++ b/nixos/tests/channel-finder/ioc/configure/RELEASE @@ -0,0 +1,42 @@ +# RELEASE - Location of external support modules +# +# IF YOU CHANGE ANY PATHS in this file or make API changes to +# any modules it refers to, you should do a "make rebuild" in +# this application's top level directory. +# +# The EPICS build process does not check dependencies against +# any files from outside the application, so it is safest to +# rebuild it completely if any modules it depends on change. +# +# Host- or target-specific settings can be given in files named +# RELEASE.$(EPICS_HOST_ARCH).Common +# RELEASE.Common.$(T_A) +# RELEASE.$(EPICS_HOST_ARCH).$(T_A) +# +# This file is parsed by both GNUmake and an EPICS Perl script, +# so it may ONLY contain definititions of paths to other support +# modules, variable definitions that are used in module paths, +# and include statements that pull in other RELEASE files. +# Variables may be used before their values have been set. +# Build variables that are NOT used in paths should be set in +# the CONFIG_SITE file. + +# Variables and paths to dependent modules: +#MODULES = /path/to/modules +#MYMODULE = $(MODULES)/my-module + +# If using the sequencer, point SNCSEQ at its top directory: +#SNCSEQ = $(MODULES)/seq-ver + +# EPICS_BASE should appear last so earlier modules can override stuff: +EPICS_BASE = /nix/store/bqlyj9i6g2a7jrwks24wj7bnk22agbs0-epics-base-7.0.8.1 + +# Set RULES here if you want to use build rules from somewhere +# other than EPICS_BASE: +#RULES = $(MODULES)/build-rules + +# These lines allow developers to override these RELEASE settings +# without having to modify this file directly. +-include $(TOP)/../RELEASE.local +-include $(TOP)/../RELEASE.$(EPICS_HOST_ARCH).local +-include $(TOP)/configure/RELEASE.local diff --git a/nixos/tests/channel-finder/ioc/configure/RULES b/nixos/tests/channel-finder/ioc/configure/RULES new file mode 100644 index 00000000..6d56e14e --- /dev/null +++ b/nixos/tests/channel-finder/ioc/configure/RULES @@ -0,0 +1,6 @@ +# RULES + +include $(CONFIG)/RULES + +# Library should be rebuilt because LIBOBJS may have changed. +$(LIBNAME): ../Makefile diff --git a/nixos/tests/channel-finder/ioc/configure/RULES.ioc b/nixos/tests/channel-finder/ioc/configure/RULES.ioc new file mode 100644 index 00000000..901987c6 --- /dev/null +++ b/nixos/tests/channel-finder/ioc/configure/RULES.ioc @@ -0,0 +1,2 @@ +#RULES.ioc +include $(CONFIG)/RULES.ioc diff --git a/nixos/tests/channel-finder/ioc/configure/RULES_DIRS b/nixos/tests/channel-finder/ioc/configure/RULES_DIRS new file mode 100644 index 00000000..3ba269dc --- /dev/null +++ b/nixos/tests/channel-finder/ioc/configure/RULES_DIRS @@ -0,0 +1,2 @@ +#RULES_DIRS +include $(CONFIG)/RULES_DIRS diff --git a/nixos/tests/channel-finder/ioc/configure/RULES_TOP b/nixos/tests/channel-finder/ioc/configure/RULES_TOP new file mode 100644 index 00000000..d09d668d --- /dev/null +++ b/nixos/tests/channel-finder/ioc/configure/RULES_TOP @@ -0,0 +1,3 @@ +#RULES_TOP +include $(CONFIG)/RULES_TOP + diff --git a/nixos/tests/channel-finder/ioc/iocBoot/Makefile b/nixos/tests/channel-finder/ioc/iocBoot/Makefile new file mode 100644 index 00000000..91e47d0b --- /dev/null +++ b/nixos/tests/channel-finder/ioc/iocBoot/Makefile @@ -0,0 +1,6 @@ +TOP = .. +include $(TOP)/configure/CONFIG +DIRS += $(wildcard *ioc*) +DIRS += $(wildcard as*) +include $(CONFIG)/RULES_DIRS + diff --git a/nixos/tests/channel-finder/ioc/iocBoot/iocSimple/Makefile b/nixos/tests/channel-finder/ioc/iocBoot/iocSimple/Makefile new file mode 100644 index 00000000..e1b9aa4a --- /dev/null +++ b/nixos/tests/channel-finder/ioc/iocBoot/iocSimple/Makefile @@ -0,0 +1,5 @@ +TOP = ../.. +include $(TOP)/configure/CONFIG +ARCH = $(EPICS_HOST_ARCH) +TARGETS = envPaths +include $(TOP)/configure/RULES.ioc diff --git a/nixos/tests/channel-finder/ioc/iocBoot/iocSimple/st.cmd b/nixos/tests/channel-finder/ioc/iocBoot/iocSimple/st.cmd new file mode 100644 index 00000000..a8ad4884 --- /dev/null +++ b/nixos/tests/channel-finder/ioc/iocBoot/iocSimple/st.cmd @@ -0,0 +1,27 @@ +#!../../bin/linux-x86_64/simple + +< envPaths + +## Register all support components +dbLoadDatabase "${TOP}/dbd/simple.dbd" +simple_registerRecordDeviceDriver(pdbbase) + +## Inspired by the reccaster demo IOC +epicsEnvSet("IOCNAME", "myioc") +epicsEnvSet("ENGINEER", "myself") +epicsEnvSet("LOCATION", "myplace") + +epicsEnvSet("CONTACT", "mycontact") +epicsEnvSet("BUILDING", "mybuilding") +epicsEnvSet("SECTOR", "mysector") + +addReccasterEnvVars("CONTACT", "SECTOR") +addReccasterEnvVars("BUILDING") + +## Load record instances +dbLoadRecords("${TOP}/db/simple.db") + +## Load RecCaster records +dbLoadRecords("${RECCASTER}/db/reccaster.db", "P=") + +iocInit() diff --git a/nixos/tests/channel-finder/ioc/simpleApp/Db/Makefile b/nixos/tests/channel-finder/ioc/simpleApp/Db/Makefile new file mode 100644 index 00000000..ea495989 --- /dev/null +++ b/nixos/tests/channel-finder/ioc/simpleApp/Db/Makefile @@ -0,0 +1,18 @@ +TOP=../.. +include $(TOP)/configure/CONFIG +#---------------------------------------- +# ADD MACRO DEFINITIONS AFTER THIS LINE + +#---------------------------------------------------- +# Create and install (or just install) into /db +# databases, templates, substitutions like this +DB += simple.db + +#---------------------------------------------------- +# If .db template is not named *.template add +# _template = + +include $(TOP)/configure/RULES +#---------------------------------------- +# ADD RULES AFTER THIS LINE + diff --git a/nixos/tests/channel-finder/ioc/simpleApp/Db/simple.db b/nixos/tests/channel-finder/ioc/simpleApp/Db/simple.db new file mode 100644 index 00000000..3345f75c --- /dev/null +++ b/nixos/tests/channel-finder/ioc/simpleApp/Db/simple.db @@ -0,0 +1,13 @@ +record(ai, "RECORD1") { + alias("ALIAS_RECORD1") + info("test", "testing") +} + +record(ai, "RECORD2") { + alias("ALIAS_RECORD2") + info("hello", "world") +} + +record(ai, "RECORD3") { + field(DESC, "An empty ai record") +} diff --git a/nixos/tests/channel-finder/ioc/simpleApp/Makefile b/nixos/tests/channel-finder/ioc/simpleApp/Makefile new file mode 100644 index 00000000..60ab8ae8 --- /dev/null +++ b/nixos/tests/channel-finder/ioc/simpleApp/Makefile @@ -0,0 +1,14 @@ +# Makefile at top of application tree +TOP = .. +include $(TOP)/configure/CONFIG + +# Directories to be built, in any order. +# You can replace these wildcards with an explicit list +DIRS += $(wildcard src* *Src*) +DIRS += $(wildcard db* *Db*) + +# If the build order matters, add dependency rules like this, +# which specifies that xxxSrc must be built after src: +#xxxSrc_DEPEND_DIRS += src + +include $(TOP)/configure/RULES_DIRS diff --git a/nixos/tests/channel-finder/ioc/simpleApp/src/Makefile b/nixos/tests/channel-finder/ioc/simpleApp/src/Makefile new file mode 100644 index 00000000..d0954f2a --- /dev/null +++ b/nixos/tests/channel-finder/ioc/simpleApp/src/Makefile @@ -0,0 +1,39 @@ +TOP=../.. + +include $(TOP)/configure/CONFIG +#---------------------------------------- +# ADD MACRO DEFINITIONS AFTER THIS LINE +#============================= + +#============================= +# Build the IOC application + +PROD_IOC = simple +# simple.dbd will be created and installed +DBD += simple.dbd + +# simple.dbd will be made up from these files: +simple_DBD += base.dbd +simple_DBD += reccaster.dbd + +simple_LIBS += reccaster + +# simple_registerRecordDeviceDriver.cpp derives from simple.dbd +simple_SRCS += simple_registerRecordDeviceDriver.cpp + +# Build the main IOC entry point on workstation OSs. +simple_SRCS_DEFAULT += simpleMain.cpp +simple_SRCS_vxWorks += -nil- + +# Add support from base/src/vxWorks if needed +#simple_OBJS_vxWorks += $(EPICS_BASE_BIN)/vxComLibrary + +# Finally link to the EPICS Base libraries +simple_LIBS += $(EPICS_BASE_IOC_LIBS) + +#=========================== + +include $(TOP)/configure/RULES +#---------------------------------------- +# ADD RULES AFTER THIS LINE + diff --git a/nixos/tests/channel-finder/ioc/simpleApp/src/simpleMain.cpp b/nixos/tests/channel-finder/ioc/simpleApp/src/simpleMain.cpp new file mode 100644 index 00000000..e4e5e3b2 --- /dev/null +++ b/nixos/tests/channel-finder/ioc/simpleApp/src/simpleMain.cpp @@ -0,0 +1,23 @@ +/* simpleMain.cpp */ +/* Author: Marty Kraimer Date: 17MAR2000 */ + +#include +#include +#include +#include +#include + +#include "epicsExit.h" +#include "epicsThread.h" +#include "iocsh.h" + +int main(int argc,char *argv[]) +{ + if(argc>=2) { + iocsh(argv[1]); + epicsThreadSleep(.2); + } + iocsh(NULL); + epicsExit(0); + return(0); +} diff --git a/nixos/tests/channel-finder/test_script.py b/nixos/tests/channel-finder/test_script.py new file mode 100644 index 00000000..5f27e773 --- /dev/null +++ b/nixos/tests/channel-finder/test_script.py @@ -0,0 +1,121 @@ +import json +from typing import Any + +import json5 + +start_all() + +server.wait_for_unit("channel-finder.service") +server.wait_for_open_port(8082) +server.wait_for_open_port(8444) + +client.wait_for_unit("multi-user.target") + +with subtest("ChannelFinder is listening on HTTP(S)"): + client.succeed("curl -sSfL http://server:8082/") + client.succeed("curl -sSfL -k https://server:8444/") + + +def get(uri: str) -> Any: + result = client.succeed(f"curl -sSfL http://server:8082/ChannelFinder{uri}") + return json.loads(result) + + +with subtest("ChannelFinder connected to ElasticSearch"): + status = get("/") + assert status["elastic"]["status"] == "Connected" + +server.wait_for_unit("recceiver.service") + +all_properties = { + "Engineer", + "EpicsBase", + "EpicsVersion", + "WorkingDirectory", + "alias", + "hostName", + "iocName", + "iocid", + "pvStatus", + "recceiverID", + "recordDesc", + "recordType", + "time", +} + +all_channels = { + "ALIAS_RECORD1", + "ALIAS_RECORD2", + "Msg-I", + "RECORD1", + "RECORD2", + "RECORD3", + "State-Sts", +} + +with subtest("RecCeiver sent all properties"): + + def has_all_properties(_last: bool) -> bool: + properties = get("/resources/properties") + property_names = {prop["name"] for prop in properties} + return property_names == all_properties + + retry(has_all_properties, timeout=30) + +with subtest("RecCeiver sent all channels"): + + def property_is(props: list[Any], name: str, value: Any) -> bool: + for prop in props: + if prop["name"] == name: + return prop["value"] == value + + # Property not found, fail + print(f"Property {name} not found") + return False + + def has_all_channels(_last: bool) -> bool: + channels = get("/resources/channels") + + channels = {chan["name"]: chan for chan in channels} + + if channels.keys() != all_channels: + print("Not all channel names are here") + return False + + for name, chan in channels.items(): + properties = {prop["name"]: prop["value"] for prop in chan["properties"]} + + assert properties["hostName"] == "client", f"wrong hostName for {name}" + assert properties["iocName"] == "myioc", f"wrong iocName for {name}" + assert properties["Engineer"] == "myself", f"wrong Engineer for {name}" + + chan["properties"] = properties + + # Description + assert ( + channels["RECORD3"]["properties"]["recordDesc"] == "An empty ai record" + ), "wrong description for RECORD3" + + # Aliases + assert ( + channels["ALIAS_RECORD1"]["properties"]["alias"] == "RECORD1" + ), "wrong alias for RECORD1" + assert ( + channels["ALIAS_RECORD2"]["properties"]["alias"] == "RECORD2" + ), "wrong alias for RECORD2" + + return True + + retry(has_all_channels, timeout=30) + +with subtest("Client considers itself synchronized"): + client.succeed("caget -t Msg-I | grep -qxF Synchronized") + client.succeed("caget -t State-Sts | grep -qxF Done") + +with subtest("ChannelFinder pvAccess server"): + server.wait_for_open_port(5075) + server.wait_until_succeeds("pvlist localhost", timeout=30) + data = json5.loads(server.succeed("pvcall -M json cfService:query")) + + assert set(data["labels"]).issuperset(all_properties), "not all labels found" + assert set(data["value"]["channelName"]) == all_channels, "not all channels found" From fb676bee6f264ba185a1240fd48d907ffdce1f59 Mon Sep 17 00:00:00 2001 From: Minijackson Date: Tue, 3 Sep 2024 14:55:57 +0200 Subject: [PATCH 092/111] docs/ioc: add reccaster user-guide --- docs/ioc/user-guides/index.rst | 1 + docs/ioc/user-guides/reccaster.rst | 121 +++++++++++++++++++++++++++++ 2 files changed, 122 insertions(+) create mode 100644 docs/ioc/user-guides/reccaster.rst diff --git a/docs/ioc/user-guides/index.rst b/docs/ioc/user-guides/index.rst index 517fd5e7..8a5cf175 100644 --- a/docs/ioc/user-guides/index.rst +++ b/docs/ioc/user-guides/index.rst @@ -13,6 +13,7 @@ User guides ./private-repo-setup.rst ./flake-registry.rst ./developing-modules.rst + ./reccaster.rst ./mrf-devices.rst ./testing/index.rst diff --git a/docs/ioc/user-guides/reccaster.rst b/docs/ioc/user-guides/reccaster.rst new file mode 100644 index 00000000..6bd1859b --- /dev/null +++ b/docs/ioc/user-guides/reccaster.rst @@ -0,0 +1,121 @@ +RecCaster configuration +======================= + +RecCaster is an EPICS support module +that sends PV names and IOC metadata to a "RecCeiver" server. +This setup is often used to send such metadata to a ChannelFinder database. + +.. seealso:: + + If you want to set up a RecCeiver and ChannelFinder server, + examine the guide + :doc:`../../nixos-services/user-guides/channel-finder`. + +Configuration +------------- + +To configure RecCaster, +first add it to your build environment: + +.. code-block:: diff + :caption: :file:`flake.nix` + + # Add your support modules here: + # --- + - #support.modules = with pkgs.epnix.support; [ StreamDevice mySupportModule ]; + + support.modules = with pkgs.epnix.support; [ reccaster ]; + +Make sure your app depends on the RecCaster library and DBD file: + +.. code-block:: make + :caption: :file:`{example}App/src/Makefile` + + # Replace "example" by the name of your application + example_DBD += reccaster.dbd + example_LIBS += reccaster + +And load the RecCaster database: + +.. code-block:: csh + :caption: :file:`iocBoot/ioc{Example}/st.cmd` + + ## Load RecCaster records + ## Optional but useful for checking the synchronization state + ## Make sure to choose your prefix by setting the 'P' macro + dbLoadRecords("${RECCASTER}/db/reccaster.db", "P=YOUR-PV-PREFIX:") + +This configuration is enough to start the RecCaster client. + +.. note:: + + RecCaster doesn't need the address of the RecCeiver server. + The RecCeiver server scans for available IOCs on the network. + +Firewall +-------- + +To accept connection from the RecCeiver service, +the firewall needs to allow the UDP announcert port, +which by default is 5049. + +If your IOC is a NixOS machine, +you can open the firewall with this NixOS configuration: + +.. code-block:: nix + :caption: Opening the firewall for RecCeiver + + networking.firewall.allowedUDPPorts = [5049]; + +Checking synchronization status +------------------------------- + +To check the RecCaster status of your IOC, +you can run: + +.. code-block:: bash + + # Replace 'YOUR-PV-PREFIX:' with your PV prefix + caget "YOUR-PV-PREFIX:Msg-I" + caget "YOUR-PV-PREFIX:State-Sts" + +Adding IOC metadata +------------------- + +You can choose to send more information to the RecCeiver server. + +If you want to add metadata about the global IOC, +set it as environment variable +and expose it using the ``addReccasterEnvVars`` function. +For example: + +.. code-block:: csh + :caption: :file:`iocBoot/ioc{Example}/st.cmd` + + epicsEnvSet("CONTACT", "mycontact") + addReccasterEnvVars("CONTACT") + +Make sure RecCeveiver forward those variables to ChannelFinder. +See the RecCeiver guide's :ref:`recceiver-custom-metadata`. + +For more information about what information RecCaster sends to the server, +examine the `RecSync README`_. + +.. tip:: + + RecCaster automatically sends some environment variables to RecCeiver, + without needing to call ``addReccasterEnvVars``, + for example: + + - PWD + - EPICS_VERSION + - EPICS_HOST_ARCH + - IOCNAME + - HOSTNAME + - ENGINEER + - LOCATION + + But those variables aren't automatically forwarded to ChannelFinder. + For how to forward them to ChannelFinder, + examine the RecCeiver guide's :ref:`recceiver-custom-metadata`. + +.. _RecSync README: https://github.com/ChannelFinder/recsync?tab=readme-ov-file#information-uploaded From ad8ebd0dd6b62ac7663878eea439943992bac508 Mon Sep 17 00:00:00 2001 From: Minijackson Date: Wed, 4 Sep 2024 15:05:14 +0200 Subject: [PATCH 093/111] doc/nixos-services: add ChannelFinder user guide --- .../user-guides/channel-finder.rst | 334 ++++++++++++++++++ docs/nixos-services/user-guides/index.rst | 1 + 2 files changed, 335 insertions(+) create mode 100644 docs/nixos-services/user-guides/channel-finder.rst diff --git a/docs/nixos-services/user-guides/channel-finder.rst b/docs/nixos-services/user-guides/channel-finder.rst new file mode 100644 index 00000000..5cfddc2f --- /dev/null +++ b/docs/nixos-services/user-guides/channel-finder.rst @@ -0,0 +1,334 @@ +ChannelFinder service setup +=========================== + +ChannelFinder is a directory service which enables searching for PV names, +called *channels names*, +and associated metadata. + +A ChannelFinder server is usually combined with a "RecCaster" module in the IOC, +that sends the metadata, +and a "RecCeiver" server +that scans and retrieves the metadata from "RecCaster." + +For more information on the ChannelFinder architecture, +see the official `ChannelFinder introduction`_. + +.. _ChannelFinder introduction: https://channelfinder.readthedocs.io/en/latest/overview.html + +.. include:: ./pre-requisites.rst + +ChannelFinder service +--------------------- + +To enable the ChannelFinder service, +use :ref:`opt-services.channel-finder.enable` and related options. +You will also need to enable ElasticSearch. + +For example: + +.. code-block:: nix + :caption: :file:`channel-finder.nix` --- ChannelFinder configuration example + + {lib, pkgs, ...}: { + services.channel-finder = { + enable = true; + openFirewall = true; + settings = { + + # Choose your authentication type (see below for explanations) + # --- + #"demo_auth.enabled" = true; + #"ldap.enabled" = true; + + "server.port" = 8444; + "server.http.port" = 8082; + }; + }; + + # Install Elasticsearch, + # because it's a ChannelFinder service dependency + services.elasticsearch = { + enable = true; + package = pkgs.elasticsearch7; + }; + + # Elasticsearch, needed by ChannelFinder, is not free software (SSPL | Elastic License). + # To accept the license, add the code below: + nixpkgs.config.allowUnfreePredicate = pkg: + builtins.elem (lib.getName pkg) [ + "elasticsearch" + ]; + } + +This configuration starts the ChannelFinder service on port 8082. +You can open your browser at http://localhost:8082/ to see the ChannelFinder admin page. + +For more settings, +examine the `ChannelFinder configuration`_ reference +and the :ref:`opt-services.channel-finder.settings` option. + +.. _ChannelFinder configuration: https://channelfinder.readthedocs.io/en/latest/config.html + +Authentication +^^^^^^^^^^^^^^ + +ChannelFinder supports different types of authentication backends: + +Demo authentication + *Not recommended for production servers*. + Users, + their roles, + and passwords + are specified in the configuration file, + in plain text. + +External LDAP server + The ChannelFinder service connects to an external LDAP server, + and uses it for authentication and role assignment. + + .. note:: + Configuring an fully-featured LDAP server is out of scope for this guide, + but the ChannelFinder service can connect to another service's embedded LDAP server. + + For example, + ChannelFinder could connect to a Phoebus Olog's embedded LDAP server configured beforehand. + +Demo authentication +~~~~~~~~~~~~~~~~~~~ + +.. caution:: + + This authentication type is not recommended for production servers. + +Users, +roles, +and passwords +are stored as comma-separated list in the configuration. + +For example: + +.. code-block:: nix + :caption: :file:`channel-finder.nix` --- demo authentication example + + services.channel-finder = { + settings = { + "demo_auth.enabled" = true; + "demo_auth.users" = "admin,operator,expert"; + "demo_auth.pwd" = "adminPass,operatorPass,expertPass"; + # Multiple roles can be given by separating them with ':' + "demo_auth.roles" = "ADMIN:EXPERT,USER,USER:EXPERT"; + }; + }; + +External LDAP server +~~~~~~~~~~~~~~~~~~~~ + +This section assumes you already have a configured LDAP server. +This configured LDAP server can be an embedded LDAP server of another service. + +If you want to use your company's LDAP server, +contact your IT team for the LDAP configuration: + +- URL, +- base DN, +- user DN pattern, +- search base, +- and search path. + +Here is an example configuration: + +.. code-block:: nix + :caption: :file:`channel-finder.nix` --- external LDAP authentication example + + services.channel-finder = { + settings = { + "ldap.enabled" = true; + "ldap.urls" = "ldaps://auth.mycompany.com/dc=mycompany,dc=com"; + "ldap.user.dn.pattern" = "uid={0},ou=People,dc=mycompany,dc=com"; + "ldap.groups.search.base" = "ou=Group,dc=mycompany,dc=com"; + "ldap.groups.search.pattern" = "(memberUid= {1})"; + }; + }; + +RecCeiver +--------- + +The RecCeiver service scans for IOCs in the network, +and fetches the list of PV names and other metadata. +You can configure it to put this information into the ChannelFinder service. + +Use the ``channelfinderapi.DEFAULT`` setting for configuring the connection to the ChannelFinder service, +and use the ``settings`` option for configuring all other settings. + +For a list of available ``settings``, +examine the `RecCeiver demo.conf`_ file. + +Also examine the :ref:`opt-services.recceiver.channelfinderapi` +and :ref:`opt-services.recceiver.settings` options. + +TODO: explain which cf role is needed + +For example: + +.. code-block:: nix + :caption: :file:`channel-finder.nix` --- RecCeiver configuration example + :name: recceiver-configuration-example + + {lib, pkgs, ...}: { + # Other previous options... + + services.recceiver = { + enable = true; + + channelfinderapi.DEFAULT = { + username = "admin"; + password = "adminPass"; + }; + + settings = { + recceiver = { + # Necessary if you want a firewall, + # which is enabled by default in NixOS. + bind = "0.0.0.0:5050"; + + # When receiving metadata, + # print it on the command-line (show), + # and send it to ChannelFinder (cf). + procs = ["show" "cf"]; + }; + cf = { + # PV metadata to send to ChannelFinder + alias = "on"; + recordDesc = "on"; + recordType = "on"; + }; + }; + }; + + networking.firewall.allowedTCPPorts = [5050]; + } + +.. _RecCeiver demo.conf: https://github.com/ChannelFinder/recsync/blob/1.6/server/demo.conf + +.. _recceiver-firewall: + +Firewall +^^^^^^^^ + +If ``settings.bind`` is unset, +RecCeiver listens on a random port, +which makes it difficult to open the firewall. + +To open the firewall, +make sure to set the bind address to a fixed port, +and open it in the firewall as TCP, +as shown in the :ref:`recceiver-configuration-example`. + +On the IOC side, +the firewall needs to allow the UDP announcer port, +which by default is 5049. + +If your IOC is a NixOS machine, +you can open the firewall with this configuration: + +.. code-block:: nix + :caption: Opening the IOC's firewall for RecCaster + + networking.firewall.allowedUDPPorts = [5049]; + +Setting the address list +^^^^^^^^^^^^^^^^^^^^^^^^ + +If you want to scan a specific network, +or if you want to change the port number used for scanning, +you can use the ``settings.recceiver.addrlist`` option. + +.. warning:: + + If you change the port, + make sure to also change it in the IOC firewall rules. + + See :ref:`recceiver-firewall`. + +.. code-block:: nix + :caption: :file:`channel-finder.nix` --- changing the RecCeiver address list + + {lib, pkgs, ...}: { + # ... + + services.recceiver = { + # ... + settings = { + recceiver = { + # ... + + # If you change the port, + # make sure to also change it in the IOC firewall rules + addrlist = ["192.168.1.255:5049"]; + }; + # ... + }; + }; + + # ... + } + +.. _recceiver-custom-metadata: + +Custom metadata +^^^^^^^^^^^^^^^ + +To add custom metadata variable to the ChannelFinder service, +use the ``settings.cf.environment_vars`` option, +for example: + +.. code-block:: nix + :caption: :file:`channel-finder.nix` --- adding custom metadata to ChannelFinder + + {lib, pkgs, ...}: { + # ... + + services.recceiver = { + # ... + settings = { + # ... + cf = { + # ... + environment_vars = { + # Follows the pattern: + # IOC_VARIABLE = "ChannelFinderProperty"; + CONTACT = "Concact"; + EPICS_BASE = "EpicsBase"; + EPICS_VERSION = "EpicsVersion"; + PWD = "WorkingDirectory"; + }; + }; + }; + }; + }; + +External ChannelFinder server +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If your ChannelFinder server is located on another machine, +use the ``channelfinderapi.DEFAULT.BaseURL`` option: + +.. code-block:: nix + :caption: :file:`channel-finder.nix` --- specifying an external ChannelFinder server + + services.recceiver = { + # ... + + channelfinderapi.DEFAULT = { + BaseURL = "http://192.168.1.42:8082/ChannelFinder"; + # ... + }; + + # ... + }; + +RecCaster +--------- + +To configure RecCaster in your IOCs, +examine the guide :doc:`../../ioc/user-guides/reccaster`. diff --git a/docs/nixos-services/user-guides/index.rst b/docs/nixos-services/user-guides/index.rst index 2aa264af..4ff8641a 100644 --- a/docs/nixos-services/user-guides/index.rst +++ b/docs/nixos-services/user-guides/index.rst @@ -11,5 +11,6 @@ User guides :maxdepth: 1 ./ca-gateway.rst + ./channel-finder.rst ./phoebus-alarm.rst ./phoebus-save-and-restore.rst From 5b04629de7b0db85c6093ef7d142fe917257d938 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 15 Sep 2024 01:19:26 +0000 Subject: [PATCH 094/111] flake.lock: Update MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Flake lock file updates: • Updated input 'nixpkgs': 'github:NixOS/nixpkgs/6e99f2a27d600612004fbd2c3282d614bfee6421?narHash=sha256-eV%2B63gK0Mp7ygCR0Oy4yIYSNcum2VQwnZamHxYTNi%2BM%3D' (2024-08-30) → 'github:NixOS/nixpkgs/e65aa8301ba4f0ab8cb98f944c14aa9da07394f8?narHash=sha256-PyFVySdGj3enKqm8RQuo4v1KLJLmNLOq2yYOHsI6e2Q%3D' (2024-09-11) • Updated input 'poetry2nix': 'github:nix-community/poetry2nix/7619e43c2b48c29e24b88a415256f09df96ec276?narHash=sha256-gD0N0pnKxWJcKtbetlkKOIumS0Zovgxx/nMfOIJIzoI%3D' (2024-08-23) → 'github:nix-community/poetry2nix/9a04664289506c27ddbf098d98ce520155af574c?narHash=sha256-QMdPMN%2BI9pwuE7/9d5Dane0VwGxtoTVNWIp3TMSIrgI%3D' (2024-09-14) --- flake.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/flake.lock b/flake.lock index 5f93c7bc..a00d45fb 100644 --- a/flake.lock +++ b/flake.lock @@ -95,11 +95,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1725001927, - "narHash": "sha256-eV+63gK0Mp7ygCR0Oy4yIYSNcum2VQwnZamHxYTNi+M=", + "lastModified": 1726062281, + "narHash": "sha256-PyFVySdGj3enKqm8RQuo4v1KLJLmNLOq2yYOHsI6e2Q=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "6e99f2a27d600612004fbd2c3282d614bfee6421", + "rev": "e65aa8301ba4f0ab8cb98f944c14aa9da07394f8", "type": "github" }, "original": { @@ -120,11 +120,11 @@ "treefmt-nix": "treefmt-nix" }, "locked": { - "lastModified": 1724417163, - "narHash": "sha256-gD0N0pnKxWJcKtbetlkKOIumS0Zovgxx/nMfOIJIzoI=", + "lastModified": 1726275961, + "narHash": "sha256-QMdPMN+I9pwuE7/9d5Dane0VwGxtoTVNWIp3TMSIrgI=", "owner": "nix-community", "repo": "poetry2nix", - "rev": "7619e43c2b48c29e24b88a415256f09df96ec276", + "rev": "9a04664289506c27ddbf098d98ce520155af574c", "type": "github" }, "original": { From c849f3025471c53420770e12880d893e6e777fa1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Sep 2024 09:00:20 +0000 Subject: [PATCH 095/111] build(deps): bump cachix/install-nix-action from 27 to 28 Bumps [cachix/install-nix-action](https://github.com/cachix/install-nix-action) from 27 to 28. - [Release notes](https://github.com/cachix/install-nix-action/releases) - [Commits](https://github.com/cachix/install-nix-action/compare/ba0dd844c9180cbf77aa72a116d6fbc515d0e87b...3715ab1a11cac9e991980d7b4a28d80c7ebdd8f9) --- updated-dependencies: - dependency-name: cachix/install-nix-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/book-gh-pages.yml | 2 +- .github/workflows/editorconfig.yml | 2 +- .github/workflows/formatting.yml | 2 +- .github/workflows/update-flake-lock.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/book-gh-pages.yml b/.github/workflows/book-gh-pages.yml index 64c60f6a..cf40a630 100644 --- a/.github/workflows/book-gh-pages.yml +++ b/.github/workflows/book-gh-pages.yml @@ -27,7 +27,7 @@ jobs: - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 with: persist-credentials: false - - uses: cachix/install-nix-action@ba0dd844c9180cbf77aa72a116d6fbc515d0e87b # v27 + - uses: cachix/install-nix-action@3715ab1a11cac9e991980d7b4a28d80c7ebdd8f9 # v27 - name: "Build documentation book" run: | nix build '.#docs' --print-build-logs diff --git a/.github/workflows/editorconfig.yml b/.github/workflows/editorconfig.yml index bb1744d0..8f304a62 100644 --- a/.github/workflows/editorconfig.yml +++ b/.github/workflows/editorconfig.yml @@ -13,6 +13,6 @@ jobs: - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 with: persist-credentials: false - - uses: cachix/install-nix-action@ba0dd844c9180cbf77aa72a116d6fbc515d0e87b # v27 + - uses: cachix/install-nix-action@3715ab1a11cac9e991980d7b4a28d80c7ebdd8f9 # v27 - name: "Check EditorConfig" run: nix run 'nixpkgs#eclint' --inputs-from . diff --git a/.github/workflows/formatting.yml b/.github/workflows/formatting.yml index ee2861d8..3623c05b 100644 --- a/.github/workflows/formatting.yml +++ b/.github/workflows/formatting.yml @@ -13,6 +13,6 @@ jobs: - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 with: persist-credentials: false - - uses: cachix/install-nix-action@ba0dd844c9180cbf77aa72a116d6fbc515d0e87b # v27 + - uses: cachix/install-nix-action@3715ab1a11cac9e991980d7b4a28d80c7ebdd8f9 # v27 - name: "Check Formatting" run: nix fmt -- --check . diff --git a/.github/workflows/update-flake-lock.yml b/.github/workflows/update-flake-lock.yml index 4ee2fa21..7c4bfe74 100644 --- a/.github/workflows/update-flake-lock.yml +++ b/.github/workflows/update-flake-lock.yml @@ -31,7 +31,7 @@ jobs: with: ref: ${{ matrix.branch }} persist-credentials: false - - uses: cachix/install-nix-action@ba0dd844c9180cbf77aa72a116d6fbc515d0e87b # v27 + - uses: cachix/install-nix-action@3715ab1a11cac9e991980d7b4a28d80c7ebdd8f9 # v27 - uses: DeterminateSystems/update-flake-lock@db4ee38117a597ea8df8f7f75a187dd65093eade # v23 with: branch: "update-flake-lock/${{ matrix.branch }}" From 7e40c6e73e91c78c233d5010b651abf3dff31364 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 17 Sep 2024 17:28:43 +0000 Subject: [PATCH 096/111] build(deps): bump DeterminateSystems/update-flake-lock from 23 to 24 Bumps [DeterminateSystems/update-flake-lock](https://github.com/determinatesystems/update-flake-lock) from 23 to 24. - [Release notes](https://github.com/determinatesystems/update-flake-lock/releases) - [Commits](https://github.com/determinatesystems/update-flake-lock/compare/db4ee38117a597ea8df8f7f75a187dd65093eade...a2bbe0274e3a0c4194390a1e445f734c597ebc37) --- updated-dependencies: - dependency-name: DeterminateSystems/update-flake-lock dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/update-flake-lock.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/update-flake-lock.yml b/.github/workflows/update-flake-lock.yml index 7c4bfe74..d34d2845 100644 --- a/.github/workflows/update-flake-lock.yml +++ b/.github/workflows/update-flake-lock.yml @@ -32,7 +32,7 @@ jobs: ref: ${{ matrix.branch }} persist-credentials: false - uses: cachix/install-nix-action@3715ab1a11cac9e991980d7b4a28d80c7ebdd8f9 # v27 - - uses: DeterminateSystems/update-flake-lock@db4ee38117a597ea8df8f7f75a187dd65093eade # v23 + - uses: DeterminateSystems/update-flake-lock@a2bbe0274e3a0c4194390a1e445f734c597ebc37 # v24 with: branch: "update-flake-lock/${{ matrix.branch }}" pr-title: "[${{ matrix.branch }}] Update flake.lock" From 0fa9ee16e32a367da4e9e6faed1ba25849bc12fb Mon Sep 17 00:00:00 2001 From: Minijackson Date: Thu, 19 Sep 2024 22:21:51 -0400 Subject: [PATCH 097/111] support.calc: 3-7-4 -> 3-7-5 --- pkgs/epnix/support/calc/default.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/epnix/support/calc/default.nix b/pkgs/epnix/support/calc/default.nix index e3a4cb8a..6b55bb37 100644 --- a/pkgs/epnix/support/calc/default.nix +++ b/pkgs/epnix/support/calc/default.nix @@ -8,7 +8,7 @@ }: mkEpicsPackage rec { pname = "calc"; - version = "3-7-4"; + version = "3-7-5"; varname = "CALC"; inherit local_config_site local_release; @@ -19,7 +19,7 @@ mkEpicsPackage rec { owner = "epics-modules"; repo = "calc"; rev = "R${version}"; - sha256 = "sha256-cZA9M60YAzCeBZB7amxQES6W4Bh1KFrm3ko7Js7Oa5I="; + sha256 = "sha256-S40HtO7HXDS27u7wmlxuo7oV1abtj1EaXfIz0Kj1IM0="; }; meta = { From 72f24b4992b4e38089ced1081957379025f5e256 Mon Sep 17 00:00:00 2001 From: Minijackson Date: Thu, 19 Sep 2024 22:22:22 -0400 Subject: [PATCH 098/111] support.calc: reorder attributes --- pkgs/epnix/support/calc/default.nix | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pkgs/epnix/support/calc/default.nix b/pkgs/epnix/support/calc/default.nix index 6b55bb37..40a89a03 100644 --- a/pkgs/epnix/support/calc/default.nix +++ b/pkgs/epnix/support/calc/default.nix @@ -11,10 +11,6 @@ mkEpicsPackage rec { version = "3-7-5"; varname = "CALC"; - inherit local_config_site local_release; - - buildInputs = with epnix.support; [sscan]; - src = fetchFromGitHub { owner = "epics-modules"; repo = "calc"; @@ -22,6 +18,10 @@ mkEpicsPackage rec { sha256 = "sha256-S40HtO7HXDS27u7wmlxuo7oV1abtj1EaXfIz0Kj1IM0="; }; + buildInputs = with epnix.support; [sscan]; + + inherit local_config_site local_release; + meta = { description = "Support for run-time expression evaluation"; homepage = "https://epics.anl.gov/bcda/synApps/calc/calc.html"; From e6f42a91283e6f5c7f971a0e93fa3af12818a0f9 Mon Sep 17 00:00:00 2001 From: Minijackson Date: Thu, 19 Sep 2024 22:31:29 -0400 Subject: [PATCH 099/111] support.sscan: 2-11-5 -> 2-11-6 --- pkgs/epnix/support/sscan/default.nix | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/pkgs/epnix/support/sscan/default.nix b/pkgs/epnix/support/sscan/default.nix index 542a04ab..d74282df 100644 --- a/pkgs/epnix/support/sscan/default.nix +++ b/pkgs/epnix/support/sscan/default.nix @@ -1,16 +1,14 @@ { - lib, epnixLib, mkEpicsPackage, fetchFromGitHub, - fetchpatch, epnix, local_config_site ? {}, local_release ? {}, }: mkEpicsPackage rec { pname = "sscan"; - version = "2-11-5"; + version = "2-11-6"; varname = "SSCAN"; inherit local_config_site local_release; @@ -19,9 +17,9 @@ mkEpicsPackage rec { src = fetchFromGitHub { owner = "epics-modules"; - repo = "sscan"; + repo = pname; rev = "R${version}"; - sha256 = "sha256-WVjQS4b4VBJezKqXqSFaiNLGjKUgoPqHPyNBvKKN77U="; + sha256 = "sha256-hrPap4FBKMD4ddMrADOeTAmsG+rLFxALibT3qsAHNsk="; }; meta = { From 9724618d2ab0b012a6911482968e3839b3ee448e Mon Sep 17 00:00:00 2001 From: Minijackson Date: Thu, 19 Sep 2024 22:31:54 -0400 Subject: [PATCH 100/111] support.sscan: reorder attributes --- pkgs/epnix/support/sscan/default.nix | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pkgs/epnix/support/sscan/default.nix b/pkgs/epnix/support/sscan/default.nix index d74282df..2ff09596 100644 --- a/pkgs/epnix/support/sscan/default.nix +++ b/pkgs/epnix/support/sscan/default.nix @@ -11,10 +11,6 @@ mkEpicsPackage rec { version = "2-11-6"; varname = "SSCAN"; - inherit local_config_site local_release; - - buildInputs = with epnix.support; [seq]; - src = fetchFromGitHub { owner = "epics-modules"; repo = pname; @@ -22,6 +18,10 @@ mkEpicsPackage rec { sha256 = "sha256-hrPap4FBKMD4ddMrADOeTAmsG+rLFxALibT3qsAHNsk="; }; + buildInputs = with epnix.support; [seq]; + + inherit local_config_site local_release; + meta = { description = "Contains the sscan record and related software for systematically moving positioners, triggering detectors, and acquiring and storing resulting data"; homepage = "https://epics.anl.gov/bcda/synApps/sscan/sscan.html"; From be97c68a2fcc6ca9c43824dd82d2686b37099b6e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 22 Sep 2024 01:19:47 +0000 Subject: [PATCH 101/111] flake.lock: Update MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Flake lock file updates: • Updated input 'flake-utils': 'github:numtide/flake-utils/b1d9ab70662946ef0850d488da1c9019f3a9752a?narHash=sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ%3D' (2024-03-11) → 'github:numtide/flake-utils/c1dfcf08411b08f6b8615f7d8971a2bfa81d5e8a?narHash=sha256-X6rJYSESBVr3hBoH0WbKE5KvhPU5bloyZ2L4K60/fPQ%3D' (2024-09-17) • Updated input 'nixpkgs': 'github:NixOS/nixpkgs/e65aa8301ba4f0ab8cb98f944c14aa9da07394f8?narHash=sha256-PyFVySdGj3enKqm8RQuo4v1KLJLmNLOq2yYOHsI6e2Q%3D' (2024-09-11) → 'github:NixOS/nixpkgs/944b2aea7f0a2d7c79f72468106bc5510cbf5101?narHash=sha256-NmcVhGElxDbmEWzgXsyAjlRhUus/nEqPC5So7BOJLUM%3D' (2024-09-20) • Updated input 'poetry2nix': 'github:nix-community/poetry2nix/9a04664289506c27ddbf098d98ce520155af574c?narHash=sha256-QMdPMN%2BI9pwuE7/9d5Dane0VwGxtoTVNWIp3TMSIrgI%3D' (2024-09-14) → 'github:nix-community/poetry2nix/1f4d4dcab3ee4b6a674e9d9ca9c8d125c7811634?narHash=sha256-OUpbkEbpkRh91WX8XYq5rugIHhzJUS84qwvCd%2BHBer8%3D' (2024-09-19) --- flake.lock | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/flake.lock b/flake.lock index a00d45fb..6d939ea0 100644 --- a/flake.lock +++ b/flake.lock @@ -41,11 +41,11 @@ "systems": "systems" }, "locked": { - "lastModified": 1710146030, - "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", + "lastModified": 1726560853, + "narHash": "sha256-X6rJYSESBVr3hBoH0WbKE5KvhPU5bloyZ2L4K60/fPQ=", "owner": "numtide", "repo": "flake-utils", - "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", + "rev": "c1dfcf08411b08f6b8615f7d8971a2bfa81d5e8a", "type": "github" }, "original": { @@ -95,11 +95,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1726062281, - "narHash": "sha256-PyFVySdGj3enKqm8RQuo4v1KLJLmNLOq2yYOHsI6e2Q=", + "lastModified": 1726838390, + "narHash": "sha256-NmcVhGElxDbmEWzgXsyAjlRhUus/nEqPC5So7BOJLUM=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "e65aa8301ba4f0ab8cb98f944c14aa9da07394f8", + "rev": "944b2aea7f0a2d7c79f72468106bc5510cbf5101", "type": "github" }, "original": { @@ -120,11 +120,11 @@ "treefmt-nix": "treefmt-nix" }, "locked": { - "lastModified": 1726275961, - "narHash": "sha256-QMdPMN+I9pwuE7/9d5Dane0VwGxtoTVNWIp3TMSIrgI=", + "lastModified": 1726715047, + "narHash": "sha256-OUpbkEbpkRh91WX8XYq5rugIHhzJUS84qwvCd+HBer8=", "owner": "nix-community", "repo": "poetry2nix", - "rev": "9a04664289506c27ddbf098d98ce520155af574c", + "rev": "1f4d4dcab3ee4b6a674e9d9ca9c8d125c7811634", "type": "github" }, "original": { From 09906d5b7e1d77975a46d786c064f5e516fe156c Mon Sep 17 00:00:00 2001 From: Minijackson Date: Wed, 25 Sep 2024 11:48:07 +0200 Subject: [PATCH 102/111] python3Packages.pyepics: 3.5.6 -> 3.5.7 --- pkgs/epnix/python-modules/pyepics/default.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/epnix/python-modules/pyepics/default.nix b/pkgs/epnix/python-modules/pyepics/default.nix index 644a4978..5425ff66 100644 --- a/pkgs/epnix/python-modules/pyepics/default.nix +++ b/pkgs/epnix/python-modules/pyepics/default.nix @@ -12,12 +12,12 @@ }: buildPythonPackage rec { pname = "pyepics"; - version = "3.5.6"; + version = "3.5.7"; format = "pyproject"; src = fetchPypi { inherit pname version; - hash = "sha256-NYj8EVZHTgZR13DZ46ggXRFkqBROJI/CzaNghB7OCwc="; + hash = "sha256-vj/YeBcaZvukK/QFFASxKzbe2KRIrBiU8PgcnyszDX8="; }; nativeBuildInputs = [ From d504d6d39d15dc73fec26ce85119e2c882e53119 Mon Sep 17 00:00:00 2001 From: Minijackson Date: Thu, 19 Sep 2024 22:10:08 -0400 Subject: [PATCH 103/111] support.StreamDevice: 2.8.24 -> 2.8.26 --- pkgs/epnix/support/StreamDevice/default.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/epnix/support/StreamDevice/default.nix b/pkgs/epnix/support/StreamDevice/default.nix index 1c8bd810..806d425c 100644 --- a/pkgs/epnix/support/StreamDevice/default.nix +++ b/pkgs/epnix/support/StreamDevice/default.nix @@ -8,7 +8,7 @@ local_config_site ? {}, local_release ? {}, }: let - version = "2.8.24"; + version = "2.8.26"; in mkEpicsPackage { pname = "StreamDevice"; @@ -39,7 +39,7 @@ in # export-subst in .gitattributes for .VERSION # See: https://epics.anl.gov/tech-talk/2022/msg01842.php forceFetchGit = true; - hash = "sha256-2MJ6CSNFc5rKijx5TFwwXStzj6zypS4cpMrcSuW4+F0="; + hash = "sha256-/OgjdHvFr6sBRhOLa9F3KJeaxMiKuUuBduHUc4YLYBI="; }; meta = { From 9f6cab61ef07ca69e53b561adab994f33b1250b6 Mon Sep 17 00:00:00 2001 From: Minijackson Date: Thu, 19 Sep 2024 22:14:34 -0400 Subject: [PATCH 104/111] support.StreamDevice: reorder attributes --- pkgs/epnix/support/StreamDevice/default.nix | 30 ++++++++++----------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/pkgs/epnix/support/StreamDevice/default.nix b/pkgs/epnix/support/StreamDevice/default.nix index 806d425c..e0e6c5c1 100644 --- a/pkgs/epnix/support/StreamDevice/default.nix +++ b/pkgs/epnix/support/StreamDevice/default.nix @@ -15,6 +15,21 @@ in inherit version; varname = "STREAM"; + src = fetchFromGitHub { + owner = "paulscherrerinstitute"; + repo = "StreamDevice"; + rev = version; + # Tarball from GitHub is not completely reproducible due to usage of + # export-subst in .gitattributes for .VERSION + # See: https://epics.anl.gov/tech-talk/2022/msg01842.php + forceFetchGit = true; + hash = "sha256-/OgjdHvFr6sBRhOLa9F3KJeaxMiKuUuBduHUc4YLYBI="; + }; + + nativeBuildInputs = [pcre]; + buildInputs = [pcre] ++ (with epnix.support; [sscan]); + propagatedBuildInputs = with epnix.support; [asyn calc]; + inherit local_config_site; local_release = local_release @@ -27,21 +42,6 @@ in STREAM = null; }; - nativeBuildInputs = [pcre]; - buildInputs = [pcre] ++ (with epnix.support; [sscan]); - propagatedBuildInputs = with epnix.support; [asyn calc]; - - src = fetchFromGitHub { - owner = "paulscherrerinstitute"; - repo = "StreamDevice"; - rev = version; - # Tarball from GitHub is not completely reproducible due to usage of - # export-subst in .gitattributes for .VERSION - # See: https://epics.anl.gov/tech-talk/2022/msg01842.php - forceFetchGit = true; - hash = "sha256-/OgjdHvFr6sBRhOLa9F3KJeaxMiKuUuBduHUc4YLYBI="; - }; - meta = { description = "A generic EPICS device support for devices with a \"byte stream\" based communication interface"; homepage = "https://paulscherrerinstitute.github.io/StreamDevice/"; From 9dcf88db1613c8ba47a42469ce7af9a4301c61b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Tzvetkov?= <> Date: Thu, 26 Sep 2024 14:55:47 +0200 Subject: [PATCH 105/111] support.autosave: 5-10-2 -> 5-11 --- pkgs/epnix/support/autosave/default.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/epnix/support/autosave/default.nix b/pkgs/epnix/support/autosave/default.nix index bd1d26b3..b63684a1 100644 --- a/pkgs/epnix/support/autosave/default.nix +++ b/pkgs/epnix/support/autosave/default.nix @@ -7,7 +7,7 @@ }: mkEpicsPackage rec { pname = "autosave"; - version = "5-10-2"; + version = "5-11"; varname = "AUTOSAVE"; inherit local_config_site local_release; @@ -16,7 +16,7 @@ mkEpicsPackage rec { owner = "epics-modules"; repo = "autosave"; rev = "R${version}"; - sha256 = "sha256-PUUPkiQS3MSrnjG4PzvZ6XrK9Tmt0OohvpduBqnxyyw="; + sha256 = "sha256-T6b2SUxgh2l+F4Vi3oF1aaLIjghlg34tLlwJOgGceLQ="; }; meta = { From 0f2427b0ff85bd63b7fcf583146fd263da92c1d1 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 29 Sep 2024 01:20:52 +0000 Subject: [PATCH 106/111] flake.lock: Update MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Flake lock file updates: • Updated input 'nixpkgs': 'github:NixOS/nixpkgs/944b2aea7f0a2d7c79f72468106bc5510cbf5101?narHash=sha256-NmcVhGElxDbmEWzgXsyAjlRhUus/nEqPC5So7BOJLUM%3D' (2024-09-20) → 'github:NixOS/nixpkgs/fbca5e745367ae7632731639de5c21f29c8744ed?narHash=sha256-40J9tW7Y794J7Uw4GwcAKlMxlX2xISBl6IBigo83ih8%3D' (2024-09-28) • Updated input 'poetry2nix': 'github:nix-community/poetry2nix/1f4d4dcab3ee4b6a674e9d9ca9c8d125c7811634?narHash=sha256-OUpbkEbpkRh91WX8XYq5rugIHhzJUS84qwvCd%2BHBer8%3D' (2024-09-19) → 'github:nix-community/poetry2nix/d8928e5929c2344704264e8447452e0f73c72497?narHash=sha256-dtOOYKGcfYTf0bSPuiY%2BBVEKdSw/zd/u2QvNXciQ0/E%3D' (2024-09-28) • Updated input 'poetry2nix/flake-utils': 'github:numtide/flake-utils/b1d9ab70662946ef0850d488da1c9019f3a9752a?narHash=sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ%3D' (2024-03-11) → 'github:numtide/flake-utils/c1dfcf08411b08f6b8615f7d8971a2bfa81d5e8a?narHash=sha256-X6rJYSESBVr3hBoH0WbKE5KvhPU5bloyZ2L4K60/fPQ%3D' (2024-09-17) • Updated input 'poetry2nix/nix-github-actions': 'github:nix-community/nix-github-actions/5163432afc817cf8bd1f031418d1869e4c9d5547?narHash=sha256-rXwqjtwiGKJheXB43ybM8NwWB8rO2dSRrEqes0S7F5Y%3D' (2023-12-29) → 'github:nix-community/nix-github-actions/622f829f5fe69310a866c8a6cd07e747c44ef820?narHash=sha256-uPlLYH2S0ACj0IcgaK9Lsf4spmJoGejR9DotXiXSBZQ%3D' (2024-07-04) • Updated input 'poetry2nix/treefmt-nix': 'github:numtide/treefmt-nix/8df5ff62195d4e67e2264df0b7f5e8c9995fd0bd?narHash=sha256-ddPKHcqaKCIFSFc/cvxS14goUhCOAwsM1PbMr0ZtHMg%3D' (2024-06-30) → 'github:numtide/treefmt-nix/879b29ae9a0378904fbbefe0dadaed43c8905754?narHash=sha256-uGRlRT47ecicF9iLD1G3g43jn2e%2Bb5KaMptb59LHnvM%3D' (2024-09-27) --- flake.lock | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/flake.lock b/flake.lock index 6d939ea0..50d05523 100644 --- a/flake.lock +++ b/flake.lock @@ -59,11 +59,11 @@ "systems": "systems_2" }, "locked": { - "lastModified": 1710146030, - "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", + "lastModified": 1726560853, + "narHash": "sha256-X6rJYSESBVr3hBoH0WbKE5KvhPU5bloyZ2L4K60/fPQ=", "owner": "numtide", "repo": "flake-utils", - "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", + "rev": "c1dfcf08411b08f6b8615f7d8971a2bfa81d5e8a", "type": "github" }, "original": { @@ -80,11 +80,11 @@ ] }, "locked": { - "lastModified": 1703863825, - "narHash": "sha256-rXwqjtwiGKJheXB43ybM8NwWB8rO2dSRrEqes0S7F5Y=", + "lastModified": 1720066371, + "narHash": "sha256-uPlLYH2S0ACj0IcgaK9Lsf4spmJoGejR9DotXiXSBZQ=", "owner": "nix-community", "repo": "nix-github-actions", - "rev": "5163432afc817cf8bd1f031418d1869e4c9d5547", + "rev": "622f829f5fe69310a866c8a6cd07e747c44ef820", "type": "github" }, "original": { @@ -95,11 +95,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1726838390, - "narHash": "sha256-NmcVhGElxDbmEWzgXsyAjlRhUus/nEqPC5So7BOJLUM=", + "lastModified": 1727540905, + "narHash": "sha256-40J9tW7Y794J7Uw4GwcAKlMxlX2xISBl6IBigo83ih8=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "944b2aea7f0a2d7c79f72468106bc5510cbf5101", + "rev": "fbca5e745367ae7632731639de5c21f29c8744ed", "type": "github" }, "original": { @@ -120,11 +120,11 @@ "treefmt-nix": "treefmt-nix" }, "locked": { - "lastModified": 1726715047, - "narHash": "sha256-OUpbkEbpkRh91WX8XYq5rugIHhzJUS84qwvCd+HBer8=", + "lastModified": 1727546745, + "narHash": "sha256-dtOOYKGcfYTf0bSPuiY+BVEKdSw/zd/u2QvNXciQ0/E=", "owner": "nix-community", "repo": "poetry2nix", - "rev": "1f4d4dcab3ee4b6a674e9d9ca9c8d125c7811634", + "rev": "d8928e5929c2344704264e8447452e0f73c72497", "type": "github" }, "original": { @@ -193,11 +193,11 @@ ] }, "locked": { - "lastModified": 1719749022, - "narHash": "sha256-ddPKHcqaKCIFSFc/cvxS14goUhCOAwsM1PbMr0ZtHMg=", + "lastModified": 1727431250, + "narHash": "sha256-uGRlRT47ecicF9iLD1G3g43jn2e+b5KaMptb59LHnvM=", "owner": "numtide", "repo": "treefmt-nix", - "rev": "8df5ff62195d4e67e2264df0b7f5e8c9995fd0bd", + "rev": "879b29ae9a0378904fbbefe0dadaed43c8905754", "type": "github" }, "original": { From 60203f11998aa99f66ffe3152bb6382eac3a5300 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Sep 2024 09:03:05 +0000 Subject: [PATCH 107/111] build(deps): bump actions/checkout in the non-breaking-changes group Bumps the non-breaking-changes group with 1 update: [actions/checkout](https://github.com/actions/checkout). Updates `actions/checkout` from 4.1.7 to 4.2.0 - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/692973e3d937129bcbf40652eb9f2f61becf3332...d632683dd7b4114ad314bca15554477dd762a938) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor dependency-group: non-breaking-changes ... Signed-off-by: dependabot[bot] --- .github/workflows/backport.yml | 2 +- .github/workflows/book-gh-pages.yml | 2 +- .github/workflows/editorconfig.yml | 2 +- .github/workflows/formatting.yml | 2 +- .github/workflows/update-flake-lock.yml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml index 8e248517..13e5ec48 100644 --- a/.github/workflows/backport.yml +++ b/.github/workflows/backport.yml @@ -20,7 +20,7 @@ jobs: if: github.repository_owner == 'epics-extensions' && github.event.pull_request.merged == true && (github.event_name != 'labeled' || startsWith('backport', github.event.label.name)) runs-on: ubuntu-latest steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: ref: ${{ github.event.pull_request.head.sha }} # Credentials are needed to push to a remote branch, diff --git a/.github/workflows/book-gh-pages.yml b/.github/workflows/book-gh-pages.yml index cf40a630..4ec699a2 100644 --- a/.github/workflows/book-gh-pages.yml +++ b/.github/workflows/book-gh-pages.yml @@ -24,7 +24,7 @@ jobs: url: ${{ steps.deployment.outputs.page_url }} runs-on: ubuntu-latest steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: persist-credentials: false - uses: cachix/install-nix-action@3715ab1a11cac9e991980d7b4a28d80c7ebdd8f9 # v27 diff --git a/.github/workflows/editorconfig.yml b/.github/workflows/editorconfig.yml index 8f304a62..b10f269d 100644 --- a/.github/workflows/editorconfig.yml +++ b/.github/workflows/editorconfig.yml @@ -10,7 +10,7 @@ jobs: editorconfig: runs-on: ubuntu-latest steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: persist-credentials: false - uses: cachix/install-nix-action@3715ab1a11cac9e991980d7b4a28d80c7ebdd8f9 # v27 diff --git a/.github/workflows/formatting.yml b/.github/workflows/formatting.yml index 3623c05b..fc840cf8 100644 --- a/.github/workflows/formatting.yml +++ b/.github/workflows/formatting.yml @@ -10,7 +10,7 @@ jobs: alejandra: runs-on: ubuntu-latest steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: persist-credentials: false - uses: cachix/install-nix-action@3715ab1a11cac9e991980d7b4a28d80c7ebdd8f9 # v27 diff --git a/.github/workflows/update-flake-lock.yml b/.github/workflows/update-flake-lock.yml index d34d2845..62dfbf3c 100644 --- a/.github/workflows/update-flake-lock.yml +++ b/.github/workflows/update-flake-lock.yml @@ -27,7 +27,7 @@ jobs: pull-requests: write # to create PR to backport runs-on: ubuntu-latest steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: ref: ${{ matrix.branch }} persist-credentials: false From 9ddb483660cdf8cfc7ec71e343ebc9b2cbb686b1 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 6 Oct 2024 01:20:24 +0000 Subject: [PATCH 108/111] flake.lock: Update MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Flake lock file updates: • Updated input 'nixpkgs': 'github:NixOS/nixpkgs/fbca5e745367ae7632731639de5c21f29c8744ed?narHash=sha256-40J9tW7Y794J7Uw4GwcAKlMxlX2xISBl6IBigo83ih8%3D' (2024-09-28) → 'github:NixOS/nixpkgs/6e6b3dd395c3b1eb9be9f2d096383a8d05add030?narHash=sha256-/uJcVXuBt%2BVFCPQIX%2B4YnYrHaubJSx4HoNsJVNRgANM%3D' (2024-10-04) • Updated input 'poetry2nix': 'github:nix-community/poetry2nix/d8928e5929c2344704264e8447452e0f73c72497?narHash=sha256-dtOOYKGcfYTf0bSPuiY%2BBVEKdSw/zd/u2QvNXciQ0/E%3D' (2024-09-28) → 'github:nix-community/poetry2nix/ef877b8e159b23f36ebc39155021657bed744a68?narHash=sha256-zkkL5gw%2BTNXhVO2zpeH70TKh2dSzUbkBbO6gKHO37s0%3D' (2024-09-30) --- flake.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/flake.lock b/flake.lock index 50d05523..38d4c54c 100644 --- a/flake.lock +++ b/flake.lock @@ -95,11 +95,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1727540905, - "narHash": "sha256-40J9tW7Y794J7Uw4GwcAKlMxlX2xISBl6IBigo83ih8=", + "lastModified": 1728067476, + "narHash": "sha256-/uJcVXuBt+VFCPQIX+4YnYrHaubJSx4HoNsJVNRgANM=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "fbca5e745367ae7632731639de5c21f29c8744ed", + "rev": "6e6b3dd395c3b1eb9be9f2d096383a8d05add030", "type": "github" }, "original": { @@ -120,11 +120,11 @@ "treefmt-nix": "treefmt-nix" }, "locked": { - "lastModified": 1727546745, - "narHash": "sha256-dtOOYKGcfYTf0bSPuiY+BVEKdSw/zd/u2QvNXciQ0/E=", + "lastModified": 1727711975, + "narHash": "sha256-zkkL5gw+TNXhVO2zpeH70TKh2dSzUbkBbO6gKHO37s0=", "owner": "nix-community", "repo": "poetry2nix", - "rev": "d8928e5929c2344704264e8447452e0f73c72497", + "rev": "ef877b8e159b23f36ebc39155021657bed744a68", "type": "github" }, "original": { From b6bedd66624ea8df44a59c5fb10244bddd3aff11 Mon Sep 17 00:00:00 2001 From: Vivien Loriot Date: Mon, 7 Oct 2024 10:39:12 +0200 Subject: [PATCH 109/111] support.opcua: 0-10-0-dev -> 0-10-0 --- pkgs/epnix/support/opcua/default.nix | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkgs/epnix/support/opcua/default.nix b/pkgs/epnix/support/opcua/default.nix index 73eaa9f3..2d10ac83 100644 --- a/pkgs/epnix/support/opcua/default.nix +++ b/pkgs/epnix/support/opcua/default.nix @@ -13,14 +13,14 @@ }: mkEpicsPackage { pname = "opcua"; - version = "0.10.0-dev"; + version = "0.10.0"; varname = "OPCUA"; src = fetchFromGitHub { owner = "epics-modules"; repo = "opcua"; - rev = "3d10053"; - hash = "sha256-EQra8PesO7Rlhj+pBlAfiqh5yjJwRkuh7gbGziY58iI="; + rev = "v0.10.0"; + hash = "sha256-l2+TUqVeDh9yRSBXMV0xGrdqBETvc5lfvMRuoqYy1wg="; }; inherit local_release; From 5e958398eb047c4d9888138983c65163c2018d60 Mon Sep 17 00:00:00 2001 From: Vivien Loriot Date: Mon, 7 Oct 2024 15:03:05 +0200 Subject: [PATCH 110/111] open62541_1_3: patch to export required function --- pkgs/epnix/tools/open62541_1_3/default.nix | 2 ++ pkgs/epnix/tools/open62541_1_3/shared_build.patch | 13 +++++++++++++ 2 files changed, 15 insertions(+) create mode 100644 pkgs/epnix/tools/open62541_1_3/shared_build.patch diff --git a/pkgs/epnix/tools/open62541_1_3/default.nix b/pkgs/epnix/tools/open62541_1_3/default.nix index 6be7f217..da3a39cb 100644 --- a/pkgs/epnix/tools/open62541_1_3/default.nix +++ b/pkgs/epnix/tools/open62541_1_3/default.nix @@ -41,6 +41,8 @@ in }; patches = [ + # https://github.com/epics-modules/opcua/blob/b5db09477eb6404187199753df9e626d9a432210/devOpcuaSup/open62541/README.md#bugfix-for-shared-build + ./shared_build.patch (fetchpatch { name = "Ensure-absolute-paths-in-pkg-config-file.patch"; url = "https://github.com/open62541/open62541/commit/023d4b6b8bdec987f8f3ffee6c09801bbee4fa2d.patch"; diff --git a/pkgs/epnix/tools/open62541_1_3/shared_build.patch b/pkgs/epnix/tools/open62541_1_3/shared_build.patch new file mode 100644 index 00000000..b8faa802 --- /dev/null +++ b/pkgs/epnix/tools/open62541_1_3/shared_build.patch @@ -0,0 +1,13 @@ +diff --git a/src/ua_types.c b/src/ua_types.c +index b8f6739bb..7e8f7c43d 100644 +--- a/src/ua_types.c ++++ b/src/ua_types.c +@@ -1880,7 +1880,7 @@ UA_Array_delete(void *p, size_t size, const UA_DataType *type) { + } + + #ifdef UA_ENABLE_TYPEDESCRIPTION +-UA_Boolean ++UA_Boolean UA_EXPORT + UA_DataType_getStructMember(const UA_DataType *type, const char *memberName, + size_t *outOffset, const UA_DataType **outMemberType, + UA_Boolean *outIsArray) { From 667409fcdc4ff122212e55e360c4ccdf79e7e659 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Tzvetkov?= <> Date: Tue, 22 Oct 2024 11:22:14 +0200 Subject: [PATCH 111/111] fix: remove manpage and pages stages from template CI --- templates/top/.gitlab-ci.yml | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/templates/top/.gitlab-ci.yml b/templates/top/.gitlab-ci.yml index bd8b5854..411f2191 100644 --- a/templates/top/.gitlab-ci.yml +++ b/templates/top/.gitlab-ci.yml @@ -18,26 +18,3 @@ test: script: - nix flake check $NIX_BUILD_FLAGS dependencies: [] - -manpage: - stage: deploy - script: - - nix build $NIX_BUILD_FLAGS '.#manpage' - - cp -Lr ./result manpage - artifacts: - name: "manpage-$CI_COMMIT_REF_SLUG" - paths: - - manpage - -pages: - stage: deploy - script: - - nix build $NIX_BUILD_FLAGS '.#mdbook' - - cp -Lr ./result public - artifacts: - name: "mdbook" - paths: - - public - dependencies: [] - rules: - - if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH