import json import os import sys import tempfile import unittest from pathlib import Path from unittest import mock TOOLS = Path(__file__).resolve().parents[1] sys.path.insert(0, str(TOOLS)) from release_configuration import ConfigurationError, load_configuration class ReleaseConfigurationTests(unittest.TestCase): def test_public_checkout_uses_local_build_paths_and_requires_deploy_target(self): with tempfile.TemporaryDirectory() as temporary, mock.patch.dict(os.environ, {}, clear=True): root = Path(temporary) config = load_configuration(root) self.assertEqual(config.stable_app, root / '_workspace/builds/Stable/ProjectQuint.app') self.assertEqual(config.releases_root, root / '_workspace/releases') with self.assertRaisesRegex(ConfigurationError, 'DEPLOY_HOST'): config.require_deployment() def test_environment_overrides_local_config_and_preserves_spaces(self): with tempfile.TemporaryDirectory() as temporary: root = Path(temporary) key = root / 'test key' key.touch() (root / '.release.local.json').write_text(json.dumps({ 'deploy_host': 'release@host.invalid', 'ssh_key': str(key), 'remote_source': '/srv/projectquint/site-source', })) with mock.patch.dict(os.environ, {'PROJECTQUINT_DEPLOY_HOST': 'release@override.invalid'}, clear=True): config = load_configuration(root) config.require_deployment() self.assertEqual(config.deploy_host, 'release@override.invalid') self.assertEqual(config.ssh_key, key) self.assertEqual(config.remote_source, '/srv/projectquint/site-source') def test_invalid_configuration_fails_before_deployment(self): with tempfile.TemporaryDirectory() as temporary, mock.patch.dict(os.environ, {}, clear=True): root = Path(temporary) for text in ['{', '{"unexpected": "value"}', '{"ssh_key": "relative/key"}']: with self.subTest(text=text): (root / '.release.local.json').write_text(text) with self.assertRaises(ConfigurationError): load_configuration(root) def test_shell_export_quotes_values_and_does_not_execute_them(self): import subprocess with tempfile.TemporaryDirectory() as temporary, mock.patch.dict(os.environ, {}, clear=True): root = Path(temporary) key = root / "key with spaces" key.touch() (root / '.release.local.json').write_text(json.dumps({ 'deploy_host': 'release@host.invalid', 'ssh_key': str(key), 'remote_source': '/srv/projectquint/site-source', })) config = load_configuration(root) exports = config.shell_exports() output = subprocess.check_output(['bash', '-c', exports + '\nprintf "%s" "$PROJECTQUINT_DEPLOY_KEY"'], text=True) self.assertEqual(output, str(key))