mirror of
https://github.com/ryan4yin/nix-config.git
synced 2026-09-07 10:37:14 +02:00
fix(agents): continue rule installation after target errors
This commit is contained in:
@@ -10,6 +10,7 @@ The primary workflow is to symlink files from here into each agent runtime/confi
|
||||
- `AGENTS.md`: global baseline rules for coding agents.
|
||||
- `evals/global-rules.md`: behavioral scenarios for validating changes to the global rules.
|
||||
- `install-rules.py`: installs the baseline by creating symlinks in supported agent config dirs.
|
||||
- `test_install_rules.py`: regression tests for file preservation and independent target handling.
|
||||
- `install-cli.md`: curated CLI install/update command snippets.
|
||||
- `install-skills.md`: curated `npx skills` command snippets.
|
||||
|
||||
@@ -38,6 +39,7 @@ Current targets:
|
||||
Behavior:
|
||||
|
||||
- Each target is handled independently.
|
||||
- Target errors are reported while remaining targets are attempted; any error yields a nonzero exit.
|
||||
- Missing destination directories are skipped.
|
||||
- Existing regular files are preserved as `.bak` backups (numbered when a backup already exists).
|
||||
- Destination links are replaced atomically; a failed link creation leaves the destination intact.
|
||||
@@ -49,6 +51,12 @@ the global rules source and is not installed by this script.
|
||||
Auto-approval controls tool prompting. The global rules still define task authorization, safety, and
|
||||
secret handling.
|
||||
|
||||
Run installer regression tests without changing installed rules:
|
||||
|
||||
```bash
|
||||
python3 -B -m unittest discover -s agents -p test_install_rules.py
|
||||
```
|
||||
|
||||
## About `install-cli.md` and `install-skills.md`
|
||||
|
||||
Use them as snippet libraries:
|
||||
|
||||
+14
-5
@@ -47,12 +47,21 @@ def main() -> int:
|
||||
opencode_dir = xdg_config_home / "opencode"
|
||||
claude_dir = Path("~/.claude").expanduser()
|
||||
agents_dir = Path("~/.agents").expanduser()
|
||||
install_one(codex_dir, agents_file, "AGENTS.md")
|
||||
install_one(opencode_dir, agents_file, "AGENTS.md")
|
||||
install_one(claude_dir, agents_file, "CLAUDE.md")
|
||||
install_one(agents_dir, agents_file, "AGENTS.md")
|
||||
targets = (
|
||||
(codex_dir, "AGENTS.md"),
|
||||
(opencode_dir, "AGENTS.md"),
|
||||
(claude_dir, "CLAUDE.md"),
|
||||
(agents_dir, "AGENTS.md"),
|
||||
)
|
||||
failed = False
|
||||
for target_dir, target_name in targets:
|
||||
try:
|
||||
install_one(target_dir, agents_file, target_name)
|
||||
except OSError as error:
|
||||
print(f"failed {target_dir / target_name}: {error}", file=sys.stderr)
|
||||
failed = True
|
||||
|
||||
return 0
|
||||
return 1 if failed else 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import importlib.util
|
||||
import io
|
||||
import tempfile
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
@@ -13,6 +14,22 @@ spec.loader.exec_module(installer)
|
||||
|
||||
|
||||
class InstallRulesTests(unittest.TestCase):
|
||||
def test_target_failure_does_not_stop_remaining_targets(self):
|
||||
with (
|
||||
patch.object(
|
||||
installer, "install_one", side_effect=[PermissionError("denied"), None, None, None]
|
||||
) as install,
|
||||
patch("sys.stderr", new_callable=io.StringIO) as stderr,
|
||||
):
|
||||
self.assertEqual(installer.main(), 1)
|
||||
self.assertEqual(install.call_count, 4)
|
||||
self.assertIn("denied", stderr.getvalue())
|
||||
|
||||
def test_successful_targets_return_success(self):
|
||||
with patch.object(installer, "install_one") as install:
|
||||
self.assertEqual(installer.main(), 0)
|
||||
self.assertEqual(install.call_count, 4)
|
||||
|
||||
def test_existing_file_is_backed_up_without_overwriting_backup(self):
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
root = Path(directory)
|
||||
|
||||
Reference in New Issue
Block a user