Added Nix Flake with dev shell

This commit is contained in:
2026-05-20 19:01:17 +02:00
parent 0859a0476c
commit b8f71efaf0
3 changed files with 258 additions and 0 deletions
+4
View File
@@ -1,3 +1,7 @@
.dev-packages/
.xonotic-data/
dev-config.toml
# Build artifacts # Build artifacts
build/ build/
*.egg-info/ *.egg-info/
Generated
+61
View File
@@ -0,0 +1,61 @@
{
"nodes": {
"flake-utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1731533236,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1778869304,
"narHash": "sha256-30sZNZoA1cqF5JNO9fVX+wgiQYjB7HJqqJ4ztCDeBZE=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "d233902339c02a9c334e7e593de68855ad26c4cb",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
}
},
"root": "root",
"version": 7
}
+193
View File
@@ -0,0 +1,193 @@
{
description = "xonotic-exporter dev shell";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
flake-utils.url = "github:numtide/flake-utils";
};
outputs =
{
self,
nixpkgs,
flake-utils,
}:
flake-utils.lib.eachDefaultSystem (
system:
let
pkgs = import nixpkgs { inherit system; };
# Python env with all runtime + dev deps
pythonEnv = pkgs.python313.withPackages (
ps: with ps; [
(ps.buildPythonPackage rec {
pname = "xrcon";
version = "0.2";
format = "setuptools";
src = ps.fetchPypi {
inherit pname version;
sha256 = "sha256-xRuZXgf09zrQUpneR2DTBYr7W08GYOc2TmaVp71rcqs=";
};
build-system = [ ps.setuptools ];
dependencies = [ ps.six ];
})
prometheus-client
pytest
pytest-asyncio
mypy
black
isort
ruff
pip
]
);
# Convenience script: start a local Xonotic dedicated server
startXonotic = pkgs.writeShellScriptBin "start-xonotic-server" ''
set -euo pipefail
PORT=''${XONOTIC_PORT:-26010}
RCON_PW=''${XONOTIC_RCON_PASSWORD:-devpassword}
DATADIR=''${XONOTIC_DATADIR:-$PWD/.xonotic-data}
CFGDIR="$DATADIR/data"
mkdir -p "$CFGDIR"
cat > "$CFGDIR/config.cfg" <<EOF
hostname "xonotic-dev-server"
sv_public -1
rcon_password "$RCON_PW"
rcon_secure 0
EOF
cat > "$CFGDIR/server.cfg" <<EOF
gametype dm
minplayers 0
bot_number 2
timelimit 20
fraglimit 30
EOF
echo "Starting Xonotic dedicated server on UDP :$PORT (rcon pw: $RCON_PW)"
exec ${pkgs.xonotic-dedicated}/bin/xonotic-dedicated \
-userdir "$DATADIR" \
-port "$PORT" \
"$@"
'';
# Convenience script: query the local test server
queryServer = pkgs.writeShellScriptBin "query-xonotic" ''
set -euo pipefail
PORT=''${XONOTIC_PORT:-26010}
PW=''${XONOTIC_RCON_PASSWORD:-devpassword}
exec xonotic-exporter query \
--host localhost \
--port "$PORT" \
--password "$PW" \
--mode 0 \
"$@"
'';
# Generate a minimal dev config for the exporter
genConfig = pkgs.writeShellScriptBin "gen-exporter-config" ''
PORT=''${XONOTIC_PORT:-26010}
PW=''${XONOTIC_RCON_PASSWORD:-devpassword}
OUT=''${1:-dev-config.toml}
cat > "$OUT" <<EOF
[exporter]
host = "0.0.0.0"
port = 9260
[[servers]]
name = "dev"
host = "localhost"
port = $PORT
rcon_password = "$PW"
rcon_mode = 0
EOF
echo "Wrote exporter config to $OUT"
'';
in
{
devShells.default = pkgs.mkShell {
name = "xonotic-exporter";
packages = [
pythonEnv
# Xonotic dedicated server
pkgs.xonotic-dedicated
# The project itself (editable install via pip in shellHook)
# Network / protocol debugging
pkgs.netcat-gnu # nc — poke UDP ports
pkgs.tcpdump # capture RCON UDP traffic
pkgs.wireshark-cli # tshark for scripted captures
pkgs.socat # relay / inspect UDP
pkgs.nmap # port scanning / service detection
# Metrics & observability
pkgs.prometheus # run a local prometheus instance
pkgs.grafana # dashboard for scraped metrics
pkgs.curl # hit the /metrics endpoint
# Dev tools
pkgs.git
pkgs.gnumake
pkgs.jq # inspect JSON / TOML-adjacent debugging
pkgs.ripgrep
pkgs.fd
pkgs.watchexec # re-run tests on file change
pkgs.just # task runner (justfile)
pkgs.entr # alternative file watcher
# Convenience scripts defined above
startXonotic
queryServer
genConfig
];
shellHook = ''
echo ""
echo " "
echo " xonotic-exporter dev shell "
echo " "
echo ""
export PYTHONPATH="$PWD/.dev-packages:$PYTHONPATH"
export PYTHONDONTWRITEBYTECODE=1
export PYTHONUNBUFFERED=1
DEV_PKG="$PWD/.dev-packages"
PTH="$DEV_PKG/__editable__.xonotic_exporter-1.0.0.pth"
export PATH="$PWD/.dev-packages/bin:$PATH"
if [ ! -f "$PTH" ]; then
echo " Installing xonotic-exporter (editable)..."
pip install -e . --target "$DEV_PKG" --quiet || echo " pip install failed check pyproject.toml"
else
echo " xonotic-exporter already installed, skipping pip."
fi
echo ""
echo " Commands:"
echo " start-xonotic-server spin up a local Xonotic dedicated server"
echo " query-xonotic one-shot RCON query against the dev server"
echo " gen-exporter-config write a dev config.toml"
echo " xonotic-exporter serve dev-config.toml start the HTTP exporter"
echo ""
echo " Env overrides:"
echo " XONOTIC_PORT (default 26010)"
echo " XONOTIC_RCON_PASSWORD (default devpassword)"
echo " XONOTIC_DATADIR (default .xonotic-data/)"
echo ""
'';
};
}
);
}