Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 14 additions & 7 deletions .github/workflows/conformance.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ name: Conformance

on:
push:
branches: [main]
branches: [main, v4.5]
pull_request:
branches: [main]
types: [opened, ready_for_review, reopened, synchronize]
branches: [main, v4.5]

jobs:
plugin-test:
Expand All @@ -19,20 +20,26 @@ jobs:
- uses: actions/checkout@v5
with:
repository: fruwehq/eve
ref: ${{ (github.base_ref == 'v4.5' || github.head_ref == 'v4.5' || github.ref_name == 'v4.5') && 'v4.5' || 'main' }}
path: eve

- uses: actions/setup-python@v6
with:
python-version: "3.12"

- run: pip install jsonschema pyyaml
- run: pip install ./eve pytest==9.0.3

- name: Validate manifest environment contracts
run: python tests/test-manifest-env-contract

- name: Run plugin-test against every package
run: |
set -e
for manifest in */eve-plugin.yaml; do
plugin="$(dirname "$manifest")"
echo "::group::plugin-test $plugin"
eve/scripts/plugin-test "$plugin"
git ls-files '*eve-plugin.yaml' | while IFS= read -r manifest; do
echo "::group::plugin-test $manifest"
eve/scripts/plugin-test "$manifest"
echo "::endgroup::"
done

- name: Launcher parity tests
run: python -m pytest -q tests
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
*.pyc
.pytest_cache/
__pycache__/
4 changes: 1 addition & 3 deletions gnome-desktop-headless/eve-plugin.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,7 @@ compatibility:
setup.
down:
destructive: true
env:
- VIRTUAL_MONITOR_WIDTH
- VIRTUAL_MONITOR_HEIGHT
env: []
desktop:
name: GNOME Headless
session: Wayland
Expand Down
2 changes: 2 additions & 0 deletions macos-desktop-theme/commands/ubuntu/down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#!/usr/bin/env sh
set -eu

# Variables in the command payload expand on the guest.
# shellcheck disable=SC2016
exec ./scripts/package-down-command macos-desktop-theme 'sudo rm -f "$EVE_HUMAN_HOME/.config/autostart/eve-gnome-macos-theme.desktop" "$EVE_HUMAN_HOME/.local/bin/eve-gnome-macos-theme"; sudo DEBIAN_FRONTEND=noninteractive apt-get remove -y gnome-shell-extension-ubuntu-dock papirus-icon-theme || true'
2 changes: 2 additions & 0 deletions macos-desktop-theme/commands/ubuntu/status
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#!/usr/bin/env sh
set -eu

# Variables in the command payload expand on the guest.
# shellcheck disable=SC2016
exec ./scripts/package-status-command macos-desktop-theme 'if [ -f "$HOME/.local/bin/eve-gnome-macos-theme" ]; then echo installed; else echo missing; fi'
2 changes: 1 addition & 1 deletion nomachine/commands/nomachine-info
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ def main() -> int:
ip = os.environ.get("EVE_REMOTE_IP", "(no IP)")
user = os.environ.get("VM_USER_NAME", "") or "the instance user"
print(f"Host: {ip}")
print(f"Port: 4000 (NX)")
print("Port: 4000 (NX)")
print(f"User: {user}")
print("Auth: the instance user's system password")
return 0
Expand Down
Binary file removed rdp/commands/__pycache__/_client.cpython-314.pyc
Binary file not shown.
2 changes: 2 additions & 0 deletions rdp/commands/ubuntu/status
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#!/usr/bin/env sh
set -eu

# Variables in the command payload expand on the guest.
# shellcheck disable=SC2016
exec ./scripts/package-status-command rdp 'if systemctl is-active --quiet gnome-remote-desktop.service 2>/dev/null || command -v xrdp >/dev/null 2>&1 || dpkg-query -W -f="${Status}" xrdp 2>/dev/null | grep -q "install ok installed"; then echo installed; else echo missing; fi'
1 change: 0 additions & 1 deletion rdp/commands/verify
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ from __future__ import annotations

import os
import subprocess
import sys

ROOT = os.environ.get("EVE_REMOTE_ROOT", ".")
INST = os.environ.get("EVE_REMOTE_INSTANCE", "")
Expand Down
4 changes: 3 additions & 1 deletion rdp/eve-plugin.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@ config_schema:
type: string
env_var: RDP_GATE_USER
description: "Username for the RDP gateway login on GNOME desktops."
secrets:
gate_password:
type: string
env_var: RDP_GATE_PASSWORD
description: "Password for the RDP gateway login on GNOME desktops."
compatibility_enforced: true
compatibility:
Expand Down Expand Up @@ -54,7 +56,7 @@ compatibility:
status: supported
notes: Uses krdp with lock and power management disabled for unattended sessions.
down: {destructive: true}
env: [RDP_GATE_USER, RDP_GATE_PASSWORD]
env: [EPHEMERAL_DISPLAY_RESOLUTION, RDP_GATE_PASSWORD, RDP_GATE_USER]
actions:
- id: rdp
label: RDP
Expand Down
11 changes: 9 additions & 2 deletions rdp/provision/ubuntu/rdp.sh
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,15 @@ configure_gnome_rdp() {
human_run grdctl rdp enable

if [ "$headless" = "headless" ]; then
local width="${VIRTUAL_MONITOR_WIDTH:-1920}"
local height="${VIRTUAL_MONITOR_HEIGHT:-1080}"
local resolution="$EPHEMERAL_DISPLAY_RESOLUTION"
local width="${resolution%x*}"
local height="${resolution#*x}"
case "$width:$height" in
*[!0-9:]*|:*|*:)
log "ERROR: display resolution must use the WxH format: $resolution"
return 1
;;
esac
if grdctl_supports "set-virtual-monitor"; then
log "### rdp: configuring GNOME virtual monitor ${width}x${height}"
human_run grdctl rdp set-virtual-monitor "${width}x${height}" || true
Expand Down
Binary file not shown.
2 changes: 2 additions & 0 deletions rustdesk/commands/ubuntu/status
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#!/usr/bin/env sh
set -eu

# Variables in the command payload expand on the guest.
# shellcheck disable=SC2016
exec ./scripts/package-status-command rustdesk 'if command -v rustdesk >/dev/null 2>&1 || dpkg-query -W -f="${Status}" rustdesk 2>/dev/null | grep -q "install ok installed"; then echo installed; else echo missing; fi'
1 change: 0 additions & 1 deletion rustdesk/commands/verify
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ from __future__ import annotations
import os
import re
import subprocess
import sys

ROOT = os.environ.get("EVE_REMOTE_ROOT", ".")
INST = os.environ.get("EVE_REMOTE_INSTANCE", "")
Expand Down
14 changes: 10 additions & 4 deletions rustdesk/eve-plugin.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,19 @@ commands:
supports: {os_families: [ubuntu]}
config_schema:
config:
password:
type: string
description: "RustDesk autonomic/one-time password."
server:
type: host
env_var: RUSTDESK_SERVER
description: "RustDesk relay/ID server address. Leave unset to use the public servers."
secrets:
key:
type: string
env_var: RUSTDESK_KEY
description: "RustDesk server public key."
password:
type: string
env_var: RUSTDESK_PASSWORD
description: "RustDesk permanent unattended-access password."
compatibility_enforced: true
compatibility:
- platform: windows
Expand Down Expand Up @@ -54,7 +60,7 @@ compatibility:
status: unsupported
notes: RustDesk unattended Wayland sharing is not a supported KDE path.
down: {destructive: true}
env: [RUSTDESK_SERVER, RUSTDESK_KEY, RUSTDESK_PASSWORD]
env: [RUSTDESK_KEY, RUSTDESK_PASSWORD, RUSTDESK_SERVER]
actions:
- id: rustdesk
label: RustDesk
Expand Down
2 changes: 2 additions & 0 deletions steam/commands/ubuntu/status
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#!/usr/bin/env sh
set -eu

# Variables in the command payload expand on the guest.
# shellcheck disable=SC2016
exec ./scripts/package-status-command steam 'if command -v steam >/dev/null 2>&1 || dpkg-query -W -f="${Status}" steam steam-installer 2>/dev/null | grep -q "install ok installed"; then echo installed; else echo missing; fi'
Binary file not shown.
2 changes: 2 additions & 0 deletions sunshine/commands/ubuntu/status
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#!/usr/bin/env sh
set -eu

# Variables in the command payload expand on the guest.
# shellcheck disable=SC2016
exec ./scripts/package-status-command sunshine 'if command -v sunshine >/dev/null 2>&1 || dpkg-query -W -f="${Status}" sunshine 2>/dev/null | grep -q "install ok installed"; then echo installed; else echo missing; fi'
1 change: 0 additions & 1 deletion sunshine/commands/verify
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ from __future__ import annotations

import os
import subprocess
import sys

ROOT = os.environ.get("EVE_REMOTE_ROOT", ".")
INST = os.environ.get("EVE_REMOTE_INSTANCE", "")
Expand Down
29 changes: 17 additions & 12 deletions sunshine/eve-plugin.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,33 +27,25 @@ config_schema:
type: integer
env_var: SUNSHINE_MAX_BITRATE_KBPS
description: Maximum Sunshine host streaming bitrate, in kilobits per second.
password:
type: string
env_var: EPHEMERAL_SUNSHINE_PASSWORD
description: Password for the Sunshine web UI / Moonlight pairing flow.
version:
type: string
env_var: SUNSHINE_VERSION
description: Sunshine version to install (pinned).
moonlight_bitrate_kbps:
type: integer
env_var: EPHEMERAL_MOONLIGHT_BITRATE_KBPS
description: Moonlight client streaming bitrate, in kilobits per second.
moonlight_display_mode:
type: enum
enum:
- fullscreen
- borderless
- fullscreen
- windowed
env_var: EPHEMERAL_MOONLIGHT_DISPLAY_MODE
description: Moonlight client window mode.
moonlight_video_codec:
type: enum
enum:
- auto
- AV1
- H.264
- HEVC
- AV1
- auto
env_var: EPHEMERAL_MOONLIGHT_VIDEO_CODEC
description: Preferred Moonlight client video codec.
moonlight_video_decoder:
Expand All @@ -64,6 +56,15 @@ config_schema:
- software
env_var: EPHEMERAL_MOONLIGHT_VIDEO_DECODER
description: Moonlight client video decoder selection.
version:
type: string
env_var: SUNSHINE_VERSION
description: Sunshine version to install (pinned).
secrets:
password:
type: string
env_var: EPHEMERAL_SUNSHINE_PASSWORD
description: Password for the Sunshine web UI / Moonlight pairing flow.
compatibility_enforced: true
compatibility:
- platform: windows
Expand Down Expand Up @@ -93,9 +94,13 @@ down:
env:
- EPHEMERAL_DISPLAY_FPS
- EPHEMERAL_DISPLAY_RESOLUTION
- EPHEMERAL_MOONLIGHT_BITRATE_KBPS
- EPHEMERAL_MOONLIGHT_DISPLAY_MODE
- EPHEMERAL_MOONLIGHT_VIDEO_CODEC
- EPHEMERAL_MOONLIGHT_VIDEO_DECODER
- EPHEMERAL_SUNSHINE_PASSWORD
- SUNSHINE_VERSION
- SUNSHINE_MAX_BITRATE_KBPS
- SUNSHINE_VERSION
actions:
- id: sunshine
label: Sunshine
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
26 changes: 26 additions & 0 deletions tests/test-manifest-env-contract
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#!/usr/bin/env python3
"""Validate package config/secret mappings against the declared env surface."""

from pathlib import Path

import yaml

ROOT = Path(__file__).resolve().parents[1]

for path in sorted(ROOT.glob("*/eve-plugin.yaml")):
plugin = yaml.safe_load(path.read_text(encoding="utf-8"))
declared = plugin.get("env") or []
assert declared == sorted(set(declared)), f"{path}: env must be sorted and unique"
mapped = {
str(name)
for section in ("config", "secrets")
for spec in ((plugin.get("config_schema") or {}).get(section) or {}).values()
if isinstance(spec, dict) and spec.get("env_var")
for name in (
spec["env_var"] if isinstance(spec["env_var"], list) else [spec["env_var"]]
)
}
missing = sorted(mapped - set(declared))
assert not missing, f"{path}: env omits config_schema mappings: {missing}"

print("manifest environment contracts passed")
1 change: 0 additions & 1 deletion tests/test_rustdesk_launcher.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
"""Argv parity for the rustdesk launcher builders (v4.4 §8)."""
from __future__ import annotations

import os

import pytest

Expand Down
1 change: 0 additions & 1 deletion tests/test_thinlinc_launcher.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
"""Argv parity for the thinlinc launcher builders (v4.4 §8)."""
from __future__ import annotations

import os

import pytest

Expand Down
1 change: 0 additions & 1 deletion tests/test_vnc_launcher.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
"""Argv parity for the vnc launcher builders (v4.4 §8)."""
from __future__ import annotations

import os

import pytest

Expand Down
Binary file not shown.
1 change: 0 additions & 1 deletion thinlinc/commands/thinlinc-client
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ from __future__ import annotations

import os
import platform
import subprocess
import sys
from pathlib import Path

Expand Down
1 change: 0 additions & 1 deletion thinlinc/commands/verify
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ from __future__ import annotations

import os
import subprocess
import sys

ROOT = os.environ.get("EVE_REMOTE_ROOT", ".")
INST = os.environ.get("EVE_REMOTE_INSTANCE", "")
Expand Down
2 changes: 1 addition & 1 deletion thinlinc/eve-plugin.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ compatibility:
status: unsupported
notes: ThinLinc serves X11 sessions, not the local GNOME Wayland compositor.
down: {destructive: true}
env: [THINLINC_ACCEPT_EULA, THINLINC_SERVER_BUNDLE_PATH, THINLINC_SERVER_BUNDLE_URL, THINLINC_WEBACCESS_PORT]
env: [THINLINC_ACCEPT_EULA, THINLINC_AGENT_HOSTNAME, THINLINC_SERVER_BUNDLE_PATH, THINLINC_SERVER_BUNDLE_URL, THINLINC_WEBACCESS_PORT]
actions:
- id: web
label: ThinLinc Web
Expand Down
2 changes: 1 addition & 1 deletion thinlinc/provision/ubuntu/thinlinc.sh
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ setup-selinux=no
EOF

log "### thinlinc: running tl-setup non-interactively"
DISPLAY= sudo /opt/thinlinc/sbin/tl-setup -a "$answer_template"
DISPLAY='' sudo /opt/thinlinc/sbin/tl-setup -a "$answer_template"

configure_agent_hostname

Expand Down
Binary file removed vnc/commands/__pycache__/_client.cpython-314.pyc
Binary file not shown.
1 change: 0 additions & 1 deletion vnc/commands/verify
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ from __future__ import annotations

import os
import subprocess
import sys

ROOT = os.environ.get("EVE_REMOTE_ROOT", ".")
INST = os.environ.get("EVE_REMOTE_INSTANCE", "")
Expand Down
Binary file removed waypipe/commands/__pycache__/_client.cpython-314.pyc
Binary file not shown.
Binary file removed xpra/commands/__pycache__/_client.cpython-314.pyc
Binary file not shown.
2 changes: 1 addition & 1 deletion xpra/commands/xpra-launch
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ def main() -> int:
print(f"xpra: remote 'xpra start :{display_num}' failed", file=sys.stderr)
print(f" Is xpra installed? Run: eve instance provision --instance {instance}", file=sys.stderr)
return 1
print(f"[xpra] server running. Attach via the TUI package action.")
print("[xpra] server running. Attach via the TUI package action.")
return 0

if action == "stop":
Expand Down
Loading