Merge pull request 'clan-vm-manager' (#556) from clan-vm-manager into main

This commit is contained in:
clan-bot
2023-11-23 14:32:52 +00:00
20 changed files with 281 additions and 22 deletions

4
.envrc
View File

@@ -1,5 +1,5 @@
if ! has nix_direnv_version || ! nix_direnv_version 2.3.0; then
source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/2.3.0/direnvrc" "sha256-Dmd+j63L84wuzgyjITIfSxSD57Tx7v51DMxVZOsiUD8="
if ! has nix_direnv_version || ! nix_direnv_version 2.4.0; then
source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/2.4.0/direnvrc" "sha256-Dmd+j63L84wuzgyjITIfSxSD57Tx7v51DMxVZOsiUD8="
fi
use flake

View File

@@ -78,6 +78,8 @@ Let's get your development environment up and running:
```
- Wait for the frontend to build.
NOTE: If you have the error "@clan/colors.json" you executed `npm install`, please do not do that. `direnv reload` will handle dependency management. Please delete node_modules with `rm -rf node_modules`.
9. **Start the Frontend**:
- To start the frontend, execute:
```bash

View File

@@ -33,7 +33,6 @@
"aarch64-darwin"
];
imports = [
./checks/flake-module.nix
./devShell.nix
./formatter.nix

View File

@@ -1,13 +1,6 @@
# Because we depend on nixpkgs sources, uploading to builders takes a long time
source_up
nix_direnv_watch_file flake-module.nix default.nix
if type nix_direnv_watch_file &>/dev/null; then
nix_direnv_watch_file flake-module.nix
nix_direnv_watch_file default.nix
else
direnv watch flake-module.nix
direnv watch default.nix
fi
# Because we depend on nixpkgs sources, uploading to builders takes a long time
use flake .#clan-cli --builders ''

View File

@@ -5,9 +5,12 @@ import tempfile
from pathlib import Path
from typing import Any
from .deal import deal
from .dirs import nixpkgs_flake, nixpkgs_source
from .errors import ClanError
@deal.raises(ClanError)
def nix_command(flags: list[str]) -> list[str]:
return ["nix", "--extra-experimental-features", "nix-command flakes"] + flags
@@ -25,6 +28,7 @@ def nix_flake_show(flake_url: str | Path) -> list[str]:
)
@deal.raises(ClanError)
def nix_build(
flags: list[str],
) -> list[str]:
@@ -41,6 +45,7 @@ def nix_build(
)
@deal.raises(ClanError)
def nix_config() -> dict[str, Any]:
cmd = nix_command(["show-config", "--json"])
proc = subprocess.run(cmd, check=True, text=True, stdout=subprocess.PIPE)
@@ -51,6 +56,7 @@ def nix_config() -> dict[str, Any]:
return config
@deal.raises(ClanError)
def nix_eval(flags: list[str]) -> list[str]:
default_flags = nix_command(
[
@@ -78,6 +84,7 @@ def nix_eval(flags: list[str]) -> list[str]:
return default_flags + flags
@deal.raises(ClanError)
def nix_shell(packages: list[str], cmd: list[str]) -> list[str]:
# we cannot use nix-shell inside the nix sandbox
# in our tests we just make sure we have all the packages

View File

@@ -187,9 +187,13 @@ def get_task(uuid: UUID) -> BaseTask:
T = TypeVar("T", bound="BaseTask")
@deal.raises(ClanError)
def create_task(task_type: Type[T], *args: Any) -> T:
global POOL
# check if task_type is a callable
if not callable(task_type):
raise ClanError("task_type must be callable")
uuid = uuid4()
task = task_type(uuid, *args)

View File

@@ -28,7 +28,6 @@
, tor
, git
, nixpkgs
, copyDesktopItems
, qemu
, gnupg
, e2fsprogs
@@ -36,7 +35,7 @@
, deal
, rope
, clan-core-path
, schemathesis
, schemathesis ? null
}:
let
@@ -129,7 +128,6 @@ python3.pkgs.buildPythonApplication {
nativeBuildInputs = [
setuptools
installShellFiles
copyDesktopItems
];
propagatedBuildInputs = dependencies;

View File

@@ -38,6 +38,11 @@ exclude = "clan_cli.nixpkgs"
module = "argcomplete.*"
ignore_missing_imports = true
[[tool.mypy.overrides]]
module = "gi.*"
ignore_missing_imports = true
[[tool.mypy.overrides]]
module = "jsonschema.*"
ignore_missing_imports = true
@@ -58,4 +63,4 @@ ignore_missing_imports = true
line-length = 88
select = [ "E", "F", "I", "N"]
ignore = [ "E501" ]
ignore = [ "E501", "E402" ]

View File

@@ -38,14 +38,12 @@ mkShell {
--prefix "$tmp_path/python" \
--editable $repo_root
rm -f clan_cli/nixpkgs clan_cli/webui/assets
ln -sf ${clan-cli.nixpkgs} clan_cli/nixpkgs
ln -sf ${ui-assets} clan_cli/webui/assets
ln -sfT ${clan-cli.nixpkgs} clan_cli/nixpkgs
ln -sfT ${ui-assets} clan_cli/webui/assets
export PATH="$tmp_path/python/bin:${checkScript}/bin:$PATH"
export PYTHONPATH="$repo_root:$tmp_path/python/${pythonWithDeps.sitePackages}:"
export XDG_DATA_DIRS="$tmp_path/share''${XDG_DATA_DIRS:+:$XDG_DATA_DIRS}"
export fish_complete_path="$tmp_path/share/fish/vendor_completions.d''${fish_complete_path:+:$fish_complete_path}"
mkdir -p \

View File

@@ -1,8 +1,38 @@
import deal
from clan_cli.task_manager import get_task
from clan_cli import nix, task_manager
@deal.cases(get_task)
@deal.cases(task_manager.get_task)
def test_get_task(case: deal.TestCase) -> None:
case()
@deal.cases(task_manager.create_task)
def test_create_task(case: deal.TestCase) -> None:
case()
@deal.cases(nix.nix_command)
def test_nix_command(case: deal.TestCase) -> None:
case()
@deal.cases(nix.nix_build)
def test_nix_build(case: deal.TestCase) -> None:
case()
@deal.cases(nix.nix_config)
def test_nix_config(case: deal.TestCase) -> None:
case()
@deal.cases(nix.nix_eval)
def test_nix_eval(case: deal.TestCase) -> None:
case()
@deal.cases(nix.nix_shell)
def test_nix_shell(case: deal.TestCase) -> None:
case()

View File

@@ -0,0 +1,6 @@
source_up
nix_direnv_watch_file flake-module.nix default.nix
# Because we depend on nixpkgs sources, uploading to builders takes a long time
use flake .#clan-vm-manager --builders ''

View File

@@ -0,0 +1,13 @@
#!/usr/bin/env python3
import sys
from pathlib import Path
module_path = Path(__file__).parent.parent.absolute()
sys.path.insert(0, str(module_path))
sys.path.insert(0, str(module_path.parent / "clan_cli"))
from clan_vm_manager import main # NOQA
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,13 @@
import argparse
from typing import Callable, Optional
start_app: Optional[Callable] = None
from .app import start_app
def main() -> None:
parser = argparse.ArgumentParser(description="clan-vm-manager")
parser.set_defaults(func=start_app)
args = parser.parse_args()
args.func(args)

View File

@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.40.0 -->
<interface>
<requires lib="gtk+" version="3.24"/>
<object class="GtkApplicationWindow" id="main-window">
<property name="can-focus">False</property>
<child>
<object class="GtkFixed">
<property name="name">asdasd</property>
<property name="visible">True</property>
<property name="can-focus">False</property>
<child>
<object class="GtkButton" id="help_button">
<property name="label" translatable="yes">May I help you?</property>
<property name="name">asdasd</property>
<property name="width-request">100</property>
<property name="height-request">80</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
<property name="image-position">top</property>
<signal name="clicked" handler="on_help_button_clicked" object="coffee_label" swapped="no"/>
</object>
<packing>
<property name="x">21</property>
<property name="y">21</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="coffee_label">
<property name="width-request">100</property>
<property name="height-request">80</property>
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Get me some coffe! </property>
<property name="width-chars">0</property>
</object>
<packing>
<property name="x">178</property>
<property name="y">120</property>
</packing>
</child>
<style>
<class name="asdasd"/>
</style>
</object>
</child>
</object>
</interface>

View File

@@ -0,0 +1,19 @@
# !/usr/bin/env python3
import argparse # noqa
from pathlib import Path # noqa
import gi # noqa
gi.require_version("Gtk", "3.0") # noqa
from gi.repository import Gtk # noqa
def start_app(args: argparse.Namespace) -> None:
builder = Gtk.Builder()
glade_file = Path(__file__).parent / "app.glade"
builder.add_from_file(str(glade_file))
window = builder.get_object("main-window")
window.show_all()
Gtk.main()

View File

@@ -0,0 +1,68 @@
{ python3
, runCommand
, setuptools
, copyDesktopItems
, pygobject3
, wrapGAppsHook
, gtk3
, gnome
, gobject-introspection
, clan-cli
, makeDesktopItem
}:
let
source = ./.;
in
python3.pkgs.buildPythonApplication {
name = "clan-vm-manager";
src = source;
format = "pyproject";
makeWrapperArgs = [
# This prevents problems with mixed glibc versions that might occur when the
# cli is called through a browser built against another glibc
"--unset LD_LIBRARY_PATH"
];
nativeBuildInputs = [
setuptools
copyDesktopItems
wrapGAppsHook
gobject-introspection
];
buildInputs = [ gtk3 gnome.adwaita-icon-theme ];
propagatedBuildInputs = [ pygobject3 clan-cli ];
# also re-expose dependencies so we test them in CI
passthru.tests = {
clan-vm-manager-no-breakpoints = runCommand "clan-vm-manager-no-breakpoints" { } ''
if grep --include \*.py -Rq "breakpoint()" ${source}; then
echo "breakpoint() found in ${source}:"
grep --include \*.py -Rn "breakpoint()" ${source}
exit 1
fi
touch $out
'';
};
# Don't leak python packages into a devshell.
# It can be very confusing if you `nix run` than load the cli from the devshell instead.
postFixup = ''
rm $out/nix-support/propagated-build-inputs
'';
checkPhase = ''
PYTHONPATH= $out/bin/clan-vm-manager --help
'';
meta.mainProgram = "clan";
desktopItems = [
(makeDesktopItem {
name = "clan-vm-manager";
# TODO: this subcommand is not implemented yet
exec = "clan-vm-manager join %u";
desktopName = "CLan VM Manager";
startupWMClass = "clan";
mimeTypes = [ "x-scheme-handler/clan" ];
})
];
}

View File

@@ -0,0 +1,12 @@
{ ... }: {
perSystem = { config, pkgs, ... }: {
devShells.clan-vm-manager = pkgs.callPackage ./shell.nix {
inherit (config.packages) clan-cli clan-vm-manager;
};
packages.clan-vm-manager = pkgs.python3.pkgs.callPackage ./default.nix {
inherit (config.packages) clan-cli;
};
checks = config.packages.clan-vm-manager.tests;
};
}

View File

@@ -0,0 +1,28 @@
[build-system]
requires = ["setuptools"]
build-backend = "setuptools.build_meta"
[project]
name = "clan-vm-manager"
dynamic = ["version"]
scripts = { clan-vm-manager = "clan_vm_manager:main" }
[tool.setuptools.package-data]
clan_vm_manager = ["*.glade"]
[tool.mypy]
python_version = "3.10"
warn_redundant_casts = true
disallow_untyped_calls = true
disallow_untyped_defs = true
no_implicit_optional = true
[[tool.mypy.overrides]]
module = "gi.*"
ignore_missing_imports = true
[tool.ruff]
line-length = 88
select = ["E", "F", "I", "N"]
ignore = ["E501", "E402"]

View File

@@ -0,0 +1,14 @@
{ clan-vm-manager, clan-cli, mkShell, ruff }:
mkShell {
inherit (clan-vm-manager) propagatedBuildInputs buildInputs;
nativeBuildInputs = [
ruff
] ++ clan-vm-manager.nativeBuildInputs;
shellHook = ''
ln -sfT ${clan-cli.nixpkgs} ../clan-cli/clan_cli/nixpkgs
# prepend clan-cli for development
export PYTHONPATH=../clan-cli:$PYTHONPATH
'';
}

View File

@@ -1,6 +1,7 @@
{ ... }: {
imports = [
./clan-cli/flake-module.nix
./clan-vm-manager/flake-module.nix
./installer/flake-module.nix
./ui/flake-module.nix
./theme/flake-module.nix