Files
wehub-resource-sync bcbd1bdb22
Test (Python) / test-python-gate (push) Blocked by required conditions
Test (TypeScript) / test-typescript-gate (push) Blocked by required conditions
CLI exit codes / cli-gate (push) Blocked by required conditions
Test (Install) / test-install-gate (push) Blocked by required conditions
Integ / integ-gate (push) Blocked by required conditions
CLI exit codes / Python CLI (push) Waiting to run
Integ / changes (push) Has been skipped
Test (Install) / python-minimal (3.11) (push) Waiting to run
Test (Install) / python-minimal (3.12) (push) Waiting to run
Test (Install) / python-extra (chroma, mirage.resource.chroma) (push) Waiting to run
Integ / integ-ts (push) Waiting to run
Integ / integ (push) Waiting to run
Test (Install) / python-extra (deepagents, mirage.agents.langchain) (push) Waiting to run
Integ / integ-database (push) Waiting to run
Test (Install) / python-extra (email, mirage.resource.email) (push) Waiting to run
Test (Install) / python-extra (hdf5, mirage.core.filetype.hdf5) (push) Waiting to run
Integ / integ-ssh (push) Waiting to run
Pre-commit / pre-commit (push) Failing after 1s
CLI exit codes / changes (push) Has been skipped
Test (Install) / changes (push) Has been skipped
CLI exit codes / TypeScript CLI (push) Waiting to run
CLI exit codes / Cross-language snapshot interop (push) Waiting to run
Test (Install) / python-extra (agno, mirage.agents.agno) (push) Waiting to run
Test (Install) / python-extra (databricks, mirage.resource.databricks_volume) (push) Waiting to run
Test (Python) / changes (push) Has been skipped
Integ / integ-database-ts (push) Waiting to run
Test (Install) / python-extra (fuse, mirage.fuse.mount) (push) Waiting to run
Integ / integ-data (push) Waiting to run
Test (Install) / python-extra (lancedb, mirage.resource.lancedb) (push) Waiting to run
Test (Python) / test (push) Waiting to run
Integ / integ-fuse (push) Waiting to run
Test (Install) / python-extra (langfuse, mirage.resource.langfuse) (push) Waiting to run
Test (Python) / import-isolation (deepagents, openai, mirage.agents.openai_agents) (push) Waiting to run
Test (Python) / audit (push) Waiting to run
Test (Install) / python-extra (hf, mirage.resource.hf_buckets) (push) Waiting to run
Integ / integ-ssh-ts (push) Waiting to run
Test (Install) / python-extra (mongodb, mirage.resource.mongodb) (push) Waiting to run
Test (Python) / import-isolation (deepagents, pydantic-ai, mirage.agents.pydantic_ai) (push) Waiting to run
Test (TypeScript) / changes (push) Has been skipped
Test (Install) / python-extra (nextcloud, mirage.resource.nextcloud) (push) Waiting to run
Test (Install) / python-extra (openai, mirage.agents.openai_agents) (push) Waiting to run
Test (Install) / python-extra (openhands, mirage.agents.openhands, 3.12) (push) Waiting to run
Test (Install) / python-extra (parquet, mirage.core.filetype.parquet) (push) Waiting to run
Test (TypeScript) / test (push) Waiting to run
Test (Install) / python-extra (pdf, mirage.core.filetype.pdf) (push) Waiting to run
Test (TypeScript) / python-fs-shim (push) Waiting to run
Test (Install) / python-extra (postgres, mirage.resource.postgres) (push) Waiting to run
Test (Install) / python-extra (pydantic-ai, mirage.agents.pydantic_ai) (push) Waiting to run
Test (Install) / python-extra (qdrant, mirage.resource.qdrant) (push) Waiting to run
Test (Install) / python-extra (redis, mirage.resource.redis) (push) Waiting to run
Test (Install) / python-extra (s3, mirage.resource.s3) (push) Waiting to run
Test (Install) / python-extra (ssh, mirage.resource.ssh) (push) Waiting to run
Test (Install) / ts-minimal (push) Waiting to run
chore: import upstream snapshot with attribution
2026-07-13 12:30:44 +08:00

204 lines
7.9 KiB
Python

# ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========
import pytest
from mirage.cli.settings import (DEFAULT_DAEMON_URL, config_path, get_config,
list_config, load_daemon_settings,
resolved_config, set_config, unset_config)
from mirage.server.daemon_config import DaemonConfigError
from mirage.server.env import ENV_HOME
def test_load_daemon_settings_falls_back_to_token_file(tmp_path, monkeypatch):
monkeypatch.delenv("MIRAGE_TOKEN", raising=False)
monkeypatch.delenv("MIRAGE_DAEMON_URL", raising=False)
monkeypatch.setenv(ENV_HOME, str(tmp_path))
config_file = tmp_path / "config.toml"
config_file.write_text("")
token_file = tmp_path / "auth_token"
token_file.write_text("file-token\n")
settings = load_daemon_settings(path=config_file)
assert settings.auth_token == "file-token"
def test_load_daemon_settings_env_wins_over_file(tmp_path, monkeypatch):
monkeypatch.setenv("MIRAGE_TOKEN", "from-env")
monkeypatch.delenv("MIRAGE_DAEMON_URL", raising=False)
monkeypatch.setenv(ENV_HOME, str(tmp_path))
config_file = tmp_path / "config.toml"
config_file.write_text("")
token_file = tmp_path / "auth_token"
token_file.write_text("from-file")
settings = load_daemon_settings(path=config_file)
assert settings.auth_token == "from-env"
def test_load_daemon_settings_config_wins_over_file(tmp_path, monkeypatch):
monkeypatch.delenv("MIRAGE_TOKEN", raising=False)
monkeypatch.delenv("MIRAGE_DAEMON_URL", raising=False)
monkeypatch.setenv(ENV_HOME, str(tmp_path))
config_file = tmp_path / "config.toml"
config_file.write_text('[daemon]\nauth_token = "from-config"\n')
token_file = tmp_path / "auth_token"
token_file.write_text("from-file")
settings = load_daemon_settings(path=config_file)
assert settings.auth_token == "from-config"
def test_load_daemon_settings_no_sources_yields_empty_token(
tmp_path, monkeypatch):
monkeypatch.delenv("MIRAGE_TOKEN", raising=False)
monkeypatch.delenv("MIRAGE_DAEMON_URL", raising=False)
monkeypatch.setenv(ENV_HOME, str(tmp_path))
config_file = tmp_path / "config.toml"
config_file.write_text("")
settings = load_daemon_settings(path=config_file)
assert settings.auth_token == ""
def test_config_path_follows_mirage_home(tmp_path, monkeypatch):
monkeypatch.setenv(ENV_HOME, str(tmp_path))
assert config_path() == tmp_path / "config.toml"
def test_load_daemon_settings_reads_config_under_mirage_home(
tmp_path, monkeypatch):
monkeypatch.delenv("MIRAGE_TOKEN", raising=False)
monkeypatch.delenv("MIRAGE_DAEMON_URL", raising=False)
monkeypatch.setenv(ENV_HOME, str(tmp_path))
(tmp_path /
"config.toml").write_text('[daemon]\nurl = "http://127.0.0.1:9999"\n')
settings = load_daemon_settings()
assert settings.url == "http://127.0.0.1:9999"
def test_set_config_creates_file(tmp_path):
p = tmp_path / "config.toml"
set_config("version_root", "/data/repos", path=p)
assert get_config("version_root", path=p) == "/data/repos"
assert '[daemon]' in p.read_text()
def test_set_config_updates_existing_key(tmp_path):
p = tmp_path / "config.toml"
set_config("url", "http://a:1", path=p)
set_config("url", "http://b:2", path=p)
assert get_config("url", path=p) == "http://b:2"
assert p.read_text().count("url =") == 1
def test_set_config_preserves_comments_and_other_keys(tmp_path):
p = tmp_path / "config.toml"
p.write_text('[daemon]\n# keep me\nurl = "http://a:1"\n')
set_config("pid_file", "/tmp/x.pid", path=p)
text = p.read_text()
assert "# keep me" in text
assert 'url = "http://a:1"' in text
assert get_config("pid_file", path=p) == "/tmp/x.pid"
def test_unset_config_removes_key(tmp_path):
p = tmp_path / "config.toml"
set_config("socket", "/tmp/s.sock", path=p)
unset_config("socket", path=p)
assert get_config("socket", path=p) is None
def test_list_config_returns_written_keys(tmp_path):
p = tmp_path / "config.toml"
set_config("url", "http://a:1", path=p)
set_config("snapshot_root", "/snaps", path=p)
assert list_config(path=p) == {
"url": "http://a:1",
"snapshot_root": "/snaps"
}
def test_set_config_rejects_unknown_key(tmp_path):
with pytest.raises(DaemonConfigError, match="unknown config key"):
set_config("MIRAGE_HOME", "/x", path=tmp_path / "config.toml")
def test_numeric_key_written_bare(tmp_path):
p = tmp_path / "config.toml"
set_config("idle_grace_seconds", "45", path=p)
assert "idle_grace_seconds = 45" in p.read_text()
def test_unset_config_accepts_unknown_key(tmp_path):
p = tmp_path / "config.toml"
p.write_text('[daemon]\ntypo_key = "x"\nurl = "http://a:1"\n')
unset_config("typo_key", path=p)
assert "typo_key" not in p.read_text()
assert 'url = "http://a:1"' in p.read_text()
def test_set_config_chmods_0600(tmp_path):
p = tmp_path / "config.toml"
set_config("auth_token", "s3cret", path=p)
assert (p.stat().st_mode & 0o777) == 0o600
def test_unset_config_chmods_0600(tmp_path):
p = tmp_path / "config.toml"
p.write_text('[daemon]\nurl = "http://a:1"\nsocket = "/tmp/s"\n')
unset_config("socket", path=p)
assert (p.stat().st_mode & 0o777) == 0o600
def test_load_daemon_settings_missing_explicit_path_returns_defaults(
tmp_path, monkeypatch):
monkeypatch.delenv("MIRAGE_TOKEN", raising=False)
monkeypatch.delenv("MIRAGE_DAEMON_URL", raising=False)
monkeypatch.setenv(ENV_HOME, str(tmp_path))
settings = load_daemon_settings(path=tmp_path / "nope.toml")
assert settings.url == DEFAULT_DAEMON_URL
def test_resolved_config_reports_origins(monkeypatch, tmp_path):
monkeypatch.setenv(ENV_HOME, str(tmp_path))
monkeypatch.setenv("MIRAGE_VERSION_ROOT", "/env/repos")
monkeypatch.delenv("MIRAGE_SNAPSHOT_ROOT", raising=False)
monkeypatch.delenv("MIRAGE_DAEMON_URL", raising=False)
(tmp_path / "config.toml").write_text(
'[daemon]\nversion_root = "/file/repos"\nurl = "http://f:1"\n')
resolved = resolved_config()
assert resolved["version_root"] == ("/env/repos",
"env MIRAGE_VERSION_ROOT")
assert resolved["url"] == ("http://f:1", "file")
assert resolved["snapshot_root"] == (str(tmp_path / "snapshots"),
"default")
def test_resolved_config_defaults_when_nothing_set(monkeypatch, tmp_path):
monkeypatch.setenv(ENV_HOME, str(tmp_path))
for name in ("MIRAGE_DAEMON_URL", "MIRAGE_TOKEN", "MIRAGE_PID_FILE",
"MIRAGE_VERSION_ROOT", "MIRAGE_SNAPSHOT_ROOT",
"MIRAGE_IDLE_GRACE_SECONDS"):
monkeypatch.delenv(name, raising=False)
resolved = resolved_config()
assert resolved["url"] == (DEFAULT_DAEMON_URL, "default")
assert resolved["pid_file"] == (str(tmp_path / "daemon.pid"), "default")
assert resolved["idle_grace_seconds"] == ("30", "default")
def test_resolved_config_includes_port(monkeypatch, tmp_path):
monkeypatch.setenv(ENV_HOME, str(tmp_path))
monkeypatch.delenv("MIRAGE_DAEMON_PORT", raising=False)
resolved = resolved_config()
assert resolved["port"] == ("8765", "default")
monkeypatch.setenv("MIRAGE_DAEMON_PORT", "9100")
assert resolved_config()["port"] == ("9100", "env MIRAGE_DAEMON_PORT")