buildHomeAssistantComponent: init

Builder to package up custom components for Home Assistant.

These packages use `buildPythonPackage` with `format = "other"` and
rely on a custom install phase, that expects a standardized path,
and a custom check phase, that for now verifies python dependencies have
been satisified.

Co-Authored-By: Martin Weinelt <hexa@darmstadt.ccc.de>
Co-Authored-By: Sandro Jäckel <sandro.jaeckel@gmail.com>
This commit is contained in:
Graham Bennett 2023-11-06 22:50:16 +01:00 committed by Martin Weinelt
parent b1ddeedea6
commit 31e60c2fbb
No known key found for this signature in database
GPG Key ID: 87C1E9888F856759
6 changed files with 130 additions and 0 deletions

View File

@ -0,0 +1,46 @@
#!/usr/bin/env python3
import json
import importlib_metadata
import sys
from packaging.requirements import Requirement
def check_requirement(req: str):
# https://packaging.pypa.io/en/stable/requirements.html
requirement = Requirement(req)
try:
version = importlib_metadata.distribution(requirement.name).version
except importlib_metadata.PackageNotFoundError:
print(f" - Dependency {requirement.name} is missing", file=sys.stderr)
return False
# https://packaging.pypa.io/en/stable/specifiers.html
if not version in requirement.specifier:
print(
f" - {requirement.name}{requirement.specifier} expected, but got {version}",
file=sys.stderr,
)
return False
return True
def check_manifest(manifest_file: str):
with open(manifest_file) as fd:
manifest = json.load(fd)
if "requirements" in manifest:
ok = True
for requirement in manifest["requirements"]:
ok &= check_requirement(requirement)
if not ok:
print("Manifest requirements are not met", file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
if len(sys.argv) < 2:
raise RuntimeError(f"Usage {sys.argv[0]} <manifest>")
manifest_file = sys.argv[1]
check_manifest(manifest_file)

View File

@ -0,0 +1,38 @@
{ lib
, home-assistant
, makeSetupHook
}:
{ pname
, version
, format ? "other"
, ...
}@args:
let
manifestRequirementsCheckHook = import ./manifest-requirements-check-hook.nix {
inherit makeSetupHook;
inherit (home-assistant) python;
};
in
home-assistant.python.pkgs.buildPythonPackage (
{
inherit format;
installPhase = ''
runHook preInstall
mkdir $out
cp -r $src/custom_components/ $out/
runHook postInstall
'';
nativeCheckInputs = with home-assistant.python.pkgs; [
importlib-metadata
manifestRequirementsCheckHook
packaging
] ++ (args.nativeCheckInputs or []);
} // builtins.removeAttrs args [ "nativeCheckInputs" ]
)

View File

@ -0,0 +1,11 @@
{ python
, makeSetupHook
}:
makeSetupHook {
name = "manifest-requirements-check-hook";
substitutions = {
pythonCheckInterpreter = python.interpreter;
checkManifest = ./check_manifest.py;
};
} ./manifest-requirements-check-hook.sh

View File

@ -0,0 +1,25 @@
# Setup hook to check HA manifest requirements
echo "Sourcing manifest-requirements-check-hook"
function manifestCheckPhase() {
echo "Executing manifestCheckPhase"
runHook preCheck
manifests=$(shopt -s nullglob; echo $out/custom_components/*/manifest.json)
if [ ! -z "$manifests" ]; then
echo Checking manifests $manifests
@pythonCheckInterpreter@ @checkManifest@ $manifests
else
echo "No custom component manifests found in $out" >&2
exit 1
fi
runHook postCheck
echo "Finished executing manifestCheckPhase"
}
if [ -z "${dontCheckManifest-}" ] && [ -z "${installCheckPhase-}" ]; then
echo "Using manifestCheckPhase"
preDistPhases+=" manifestCheckPhase"
fi

View File

@ -0,0 +1,5 @@
{ callPackage
}:
{
}

View File

@ -26459,6 +26459,11 @@ with pkgs;
home-assistant = callPackage ../servers/home-assistant { };
buildHomeAssistantComponent = callPackage ../servers/home-assistant/build-custom-component { };
home-assistant-custom-components = lib.recurseIntoAttrs
(callPackage ../servers/home-assistant/custom-components {
inherit (home-assistant.python.pkgs) callPackage;
});
home-assistant-custom-lovelace-modules = lib.recurseIntoAttrs
(callPackage ../servers/home-assistant/custom-lovelace-modules {});