|
1 | 1 | import hashlib |
| 2 | +import io |
2 | 3 | import json |
3 | 4 | import re |
4 | 5 | import tempfile |
@@ -44,7 +45,6 @@ def test_zcode_and_compatibility_manifests_match(self) -> None: |
44 | 45 |
|
45 | 46 | self.assertEqual(zcode_manifest, claude_manifest) |
46 | 47 | self.assertEqual(zcode_manifest["name"], "github") |
47 | | - self.assertEqual(zcode_manifest["version"], "0.1.2") |
48 | 48 | self.assertEqual( |
49 | 49 | zcode_manifest["author"], |
50 | 50 | {"name": "Z.ai", "url": "https://z.ai"}, |
@@ -247,6 +247,33 @@ def test_secret_sync_rejects_ambiguous_or_unsafe_files(self) -> None: |
247 | 247 | with self.assertRaises(secret_sync.DotenvError): |
248 | 248 | secret_sync.read_regular_file(str(link)) |
249 | 249 |
|
| 250 | + def test_secret_sync_rejects_case_insensitive_duplicates_before_submission(self) -> None: |
| 251 | + secret_sync = load_secret_sync_module() |
| 252 | + dotenv = "TOKEN=first\ntoken=second\n" |
| 253 | + |
| 254 | + with self.assertRaisesRegex(secret_sync.DotenvError, "duplicate secret name token"): |
| 255 | + secret_sync.parse_dotenv(dotenv) |
| 256 | + |
| 257 | + with tempfile.TemporaryDirectory() as directory: |
| 258 | + path = Path(directory) / "secrets.env" |
| 259 | + path.write_text(dotenv, encoding="utf-8") |
| 260 | + for action in ("preview", "apply"): |
| 261 | + argv = ["secret_sync.py", action, "--file", str(path)] |
| 262 | + if action == "apply": |
| 263 | + argv.extend([ |
| 264 | + "--repo", "example/repo", |
| 265 | + "--expect-sha256", secret_sync.content_sha256(dotenv), |
| 266 | + ]) |
| 267 | + with ( |
| 268 | + self.subTest(action=action), |
| 269 | + mock.patch("sys.argv", argv), |
| 270 | + mock.patch("sys.stderr", new_callable=io.StringIO) as stderr, |
| 271 | + mock.patch.object(secret_sync.subprocess, "run") as run, |
| 272 | + ): |
| 273 | + self.assertEqual(secret_sync.main(), 2) |
| 274 | + self.assertIn("duplicate secret name token", stderr.getvalue()) |
| 275 | + run.assert_not_called() |
| 276 | + |
250 | 277 | def test_secret_sync_digest_binds_preview_to_apply(self) -> None: |
251 | 278 | secret_sync = load_secret_sync_module() |
252 | 279 | original = "TOKEN=first\n" |
|
0 commit comments