Package
ci / checks (push) Successful in 48m34s

This commit is contained in:
khodowany
2026-09-30 19:46:37 -05:00
parent 2a1aa2c67a
commit 09656a9d60
6621 changed files with 698 additions and 774 deletions
+68 -44
View File
@@ -42,6 +42,7 @@ elif command == 'docker':
elif command == 'systemctl' and args[0] == 'cat' and os.environ.get('FIRST_INSTALL'):
sys.exit(1)
elif command == 'nmcli' and args[:4] == ['-t', '-f', 'NAME', 'connection']:
print('product_vamp_control')
print('product-vamp-control')
print('unrelated-network')
'''
@@ -56,17 +57,17 @@ class InstallZeroTests(unittest.TestCase):
self.zero.mkdir(parents=True)
(self.zero / 'config').mkdir()
(self.zero / 'systemd').mkdir()
self.image_tag = 'product-vamp-zero:dev'
self.image_tag = 'product_vamp_zero:dev'
self.write_archive(self.image_tag)
shutil.copyfile(ROOT / 'package/config/vamp.example.json', self.zero / 'config/vamp.example.json')
for name in ('start-zero.sh', 'start-ap.sh'):
for name in ('start_zero.sh', 'start_ap.sh'):
shutil.copyfile(ROOT / 'package/zero' / name, self.zero / name)
for name in ('product-vamp-zero.service', 'product-vamp-ap.service'):
for name in ('product_vamp_zero.service', 'product_vamp_ap.service'):
shutil.copyfile(ROOT / 'package/zero' / name, self.zero / 'systemd' / name)
script = (ROOT / 'package/zero/install-zero.sh').read_text()
script = (ROOT / 'package/zero/install_zero.sh').read_text()
for prefix in ('/tmp/', '/etc/', '/var/', '/run/', '/usr/local/', '/usr/share/'):
script = script.replace(prefix, str(self.root) + prefix)
(self.zero / 'install-zero.sh').write_text(script)
(self.zero / 'install_zero.sh').write_text(script)
for path in ('etc/systemd/system', 'usr/local/bin', 'tmp', 'bin'):
(self.root / path).mkdir(parents=True, exist_ok=True)
for command in ('id', 'dpkg-query', 'apt-get', 'systemctl', 'docker', 'nmcli', 'sleep', 'chvt', 'setterm'):
@@ -78,21 +79,21 @@ class InstallZeroTests(unittest.TestCase):
configuration = b'{"architecture":"arm64","os":"linux"}'
self.image_id = 'sha256:' + hashlib.sha256(configuration).hexdigest()
manifest = json.dumps([{'Config': 'image.json', 'RepoTags': [tag]}]).encode()
with tarfile.open(self.zero / 'product-vamp-zero-linux-arm64.docker.tar', 'w') as archive:
with tarfile.open(self.zero / 'product_vamp_zero_linux_arm64.docker.tar', 'w') as archive:
for name, data in (('manifest.json', manifest), ('image.json', configuration)):
info = tarfile.TarInfo(name)
info.size = len(data)
archive.addfile(info, io.BytesIO(data))
(self.bundle / 'manifest.json').write_text(json.dumps({'zero': {'image_tag': tag}}))
def install(self, **environment):
return subprocess.run(['bash', str(self.zero / 'install-zero.sh')], env={**self.environment, **environment}, text=True, capture_output=True)
return subprocess.run(['bash', str(self.zero / 'install_zero.sh')], env={**self.environment, **environment}, text=True, capture_output=True)
def commands(self):
return [json.loads(line) for line in (self.root / 'commands').read_text().splitlines()]
def stale_state(self):
for name in ('etc/product-vamp/vamp.json', 'etc/product-vamp/obsolete', 'var/lib/product-vamp/vamp.db',
'var/lib/product-vamp/vamp.db-wal', 'var/lib/product-vamp/vamp.db-shm', 'run/product-vamp/heartbeat.json',
'usr/share/product-vamp/songs/removed.json', 'usr/share/product-vamp/practice/0001/electric.json', 'etc/systemd/system/product-vamp-zero.service.d/override.conf',
'run/systemd/system/product-vamp-ap.service.d/override.conf'):
for name in ('etc/product_vamp/vamp.json', 'etc/product_vamp/obsolete', 'var/lib/product_vamp/vamp.db',
'var/lib/product_vamp/vamp.db-wal', 'var/lib/product_vamp/vamp.db-shm', 'run/product_vamp/heartbeat.json',
'usr/share/product_vamp/songs/removed.json', 'usr/share/product_vamp/practice/0001/electric.json', 'etc/systemd/system/product_vamp_zero.service.d/override.conf',
'run/systemd/system/product_vamp_ap.service.d/override.conf'):
path = self.root / name
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text('previous installation')
@@ -105,79 +106,102 @@ class InstallZeroTests(unittest.TestCase):
self.stale_state()
second = self.install()
self.assertEqual(second.returncode, 0, second.stderr)
self.assertEqual((self.root / 'etc/product-vamp/vamp.json').read_bytes(), (self.zero / 'config/vamp.example.json').read_bytes())
self.assertEqual((self.root / 'etc/product-vamp/image-id').read_text().strip(), self.image_id)
self.assertFalse((self.root / 'etc/product-vamp/obsolete').exists())
self.assertFalse((self.root / 'var/lib/product-vamp').exists())
self.assertFalse((self.root / 'usr/share/product-vamp').exists())
self.assertFalse((self.root / 'etc/systemd/system/product-vamp-zero.service.d').exists())
self.assertFalse((self.root / 'run/systemd/system/product-vamp-ap.service.d').exists())
self.assertEqual(list((self.root / 'run/product-vamp').iterdir()), [])
self.assertEqual((self.root / 'etc/product_vamp/vamp.json').read_bytes(), (self.zero / 'config/vamp.example.json').read_bytes())
self.assertEqual((self.root / 'etc/product_vamp/image_id').read_text().strip(), self.image_id)
self.assertFalse((self.root / 'etc/product_vamp/obsolete').exists())
self.assertFalse((self.root / 'var/lib/product_vamp').exists())
self.assertFalse((self.root / 'usr/share/product_vamp').exists())
self.assertFalse((self.root / 'etc/systemd/system/product_vamp_zero.service.d').exists())
self.assertFalse((self.root / 'run/systemd/system/product_vamp_ap.service.d').exists())
self.assertEqual(list((self.root / 'run/product_vamp').iterdir()), [])
self.assertEqual((self.root / 'var/lib/unrelated/keep').read_text(), 'keep')
self.assertEqual(list((self.root / 'tmp').iterdir()), [])
commands = self.commands()
self.assertIn(['nmcli', 'connection', 'delete', 'product-vamp-control'], commands)
self.assertIn(['nmcli', 'connection', 'delete', 'product_vamp_control'], commands)
self.assertNotIn(['nmcli', 'connection', 'delete', 'unrelated-network'], commands)
self.assertFalse(any('prune' in command for command in commands))
probe = next(index for index, command in enumerate(commands) if command[:2] == ['docker', 'run'])
stop = commands.index(['systemctl', 'stop', 'product-vamp-zero.service'])
stop = commands.index(['systemctl', 'stop', 'product_vamp_zero.service'])
self.assertLess(probe, stop)
def test_failed_preflight_keeps_old_state_and_restores_image_tag(self):
self.stale_state()
result = self.install(FAIL_PREFLIGHT='1')
self.assertNotEqual(result.returncode, 0)
self.assertEqual((self.root / 'var/lib/product-vamp/vamp.db').read_text(), 'previous installation')
self.assertEqual((self.root / 'etc/product-vamp/vamp.json').read_text(), 'previous installation')
self.assertNotIn(['systemctl', 'stop', 'product-vamp-zero.service'], self.commands())
self.assertIn(['docker', 'tag', 'sha256:old', 'product-vamp-zero:dev'], self.commands())
def test_failed_health_leaves_services_stopped_without_success(self):
result = self.install(FAIL_HEALTH='1')
self.assertNotEqual(result.returncode, 0)
self.assertNotIn('Zero installed.', result.stdout)
self.assertIn(['systemctl', 'stop', 'product-vamp-zero.service', 'product-vamp-ap.service'], self.commands())
self.assertIn(['docker', 'rm', '-f', 'product-vamp-zero'], self.commands())
def test_symlink_target_aborts_without_deleting_external_data(self):
self.assertEqual((self.root / 'var/lib/product_vamp/vamp.db').read_text(), 'previous installation')
self.assertEqual((self.root / 'etc/product_vamp/vamp.json').read_text(), 'previous installation')
self.assertNotIn(['systemctl', 'stop', 'product_vamp_zero.service'], self.commands())
self.assertIn(['docker', 'tag', 'sha256:old', 'product_vamp_zero:dev'], self.commands())
def test_legacy_paths_are_removed_only_after_successful_preflight(self):
legacy = ('etc/product-vamp/vamp.json', 'var/lib/product-vamp/vamp.db', 'run/product-vamp/heartbeat.json', 'usr/share/product-vamp/catalog.db', 'usr/local/bin/product-vamp-start-zero', 'etc/systemd/system/product-vamp-zero.service', 'etc/systemd/system/product-vamp-zero.service.d/override.conf')
for name in legacy:
path = self.root / name
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text('previous installation')
failed = self.install(FAIL_PREFLIGHT='1')
self.assertNotEqual(failed.returncode, 0)
self.assertTrue(all((self.root / name).is_file() for name in legacy))
installed = self.install()
self.assertEqual(installed.returncode, 0, installed.stderr)
self.assertFalse(any((self.root / name).exists() for name in legacy))
self.assertIn(['systemctl', 'disable', 'product-vamp-zero.service'], self.commands())
self.assertIn(['nmcli', 'connection', 'delete', 'product-vamp-control'], self.commands())
def test_legacy_symlink_is_rejected_before_cleanup(self):
external = self.root / 'external'
external.mkdir()
(external / 'keep').write_text('keep')
(self.root / 'etc/product-vamp').symlink_to(external, target_is_directory=True)
result = self.install()
self.assertNotEqual(result.returncode, 0)
self.assertEqual((external / 'keep').read_text(), 'keep')
self.assertFalse(any(command[:2] == ['docker', 'load'] for command in self.commands()))
def test_failed_health_leaves_services_stopped_without_success(self):
result = self.install(FAIL_HEALTH='1')
self.assertNotEqual(result.returncode, 0)
self.assertNotIn('Zero installed.', result.stdout)
self.assertIn(['systemctl', 'stop', 'product_vamp_zero.service', 'product_vamp_ap.service'], self.commands())
self.assertIn(['docker', 'rm', '-f', 'product_vamp_zero'], self.commands())
def test_symlink_target_aborts_without_deleting_external_data(self):
external = self.root / 'external'
external.mkdir()
(external / 'keep').write_text('keep')
(self.root / 'etc/product_vamp').symlink_to(external, target_is_directory=True)
result = self.install()
self.assertNotEqual(result.returncode, 0)
self.assertIn('unsafe installation target', result.stderr)
self.assertEqual((external / 'keep').read_text(), 'keep')
self.assertNotIn(['systemctl', 'stop', 'product-vamp-zero.service'], self.commands())
self.assertNotIn(['systemctl', 'stop', 'product_vamp_zero.service'], self.commands())
def test_image_in_use_by_another_container_is_not_removed(self):
result = self.install(SHARED_IMAGE='ancestor=sha256:old')
self.assertEqual(result.returncode, 0, result.stderr)
self.assertNotIn(['docker', 'image', 'rm', 'sha256:old'], self.commands())
self.assertIn(['docker', 'image', 'rm', 'sha256:older'], self.commands())
def test_custom_bundle_tag_selects_and_pins_the_incoming_image(self):
self.write_archive('product-vamp-zero:release-test')
self.write_archive('product_vamp_zero:release-test')
result = self.install()
self.assertEqual(result.returncode, 0, result.stderr)
self.assertIn(['docker', 'image', 'inspect', '--format', '{{.Id}}', 'product-vamp-zero:release-test'], self.commands())
self.assertEqual((self.root / 'etc/product-vamp/image-id').read_text().strip(), self.image_id)
self.assertIn(['docker', 'image', 'inspect', '--format', '{{.Id}}', 'product_vamp_zero:release-test'], self.commands())
self.assertEqual((self.root / 'etc/product_vamp/image_id').read_text().strip(), self.image_id)
def test_wrong_archive_never_resets_the_old_installation(self):
self.stale_state()
(self.bundle / 'manifest.json').write_text(json.dumps({'zero': {'image_tag': 'product-vamp-zero:missing'}}))
(self.bundle / 'manifest.json').write_text(json.dumps({'zero': {'image_tag': 'product_vamp_zero:missing'}}))
result = self.install()
self.assertNotEqual(result.returncode, 0)
self.assertEqual((self.root / 'var/lib/product-vamp/vamp.db').read_text(), 'previous installation')
self.assertEqual((self.root / 'var/lib/product_vamp/vamp.db').read_text(), 'previous installation')
self.assertFalse(any(command[:2] == ['docker', 'load'] for command in self.commands()))
def test_loaded_image_must_match_archive_digest(self):
self.stale_state()
result = self.install(FIXTURE_IMAGE='sha256:unexpected')
self.assertNotEqual(result.returncode, 0)
self.assertIn('does not match', result.stderr)
self.assertEqual((self.root / 'var/lib/product-vamp/vamp.db').read_text(), 'previous installation')
self.assertIn(['docker', 'tag', 'sha256:old', 'product-vamp-zero:dev'], self.commands())
self.assertEqual((self.root / 'var/lib/product_vamp/vamp.db').read_text(), 'previous installation')
self.assertIn(['docker', 'tag', 'sha256:old', 'product_vamp_zero:dev'], self.commands())
def test_startup_uses_pinned_image_without_mounting_legacy_database(self):
result = self.install()
self.assertEqual(result.returncode, 0, result.stderr)
environment = {**self.environment, 'PRODUCT_VAMP_CONFIG_DIR': str(self.root / 'etc/product-vamp'),
'PRODUCT_VAMP_RUN_DIR': str(self.root / 'run/product-vamp'), 'PRODUCT_VAMP_DISPLAY_TTY': str(self.root / 'tty')}
started = subprocess.run(['bash', str(ROOT / 'package/zero/start-zero.sh')], env=environment, text=True, capture_output=True)
environment = {**self.environment, 'PRODUCT_VAMP_CONFIG_DIR': str(self.root / 'etc/product_vamp'),
'PRODUCT_VAMP_RUN_DIR': str(self.root / 'run/product_vamp'), 'PRODUCT_VAMP_DISPLAY_TTY': str(self.root / 'tty')}
started = subprocess.run(['bash', str(ROOT / 'package/zero/start_zero.sh')], env=environment, text=True, capture_output=True)
self.assertEqual(started.returncode, 0, started.stderr)
command = [item for item in self.commands() if item[:2] == ['docker', 'run']][-1]
self.assertIn(self.image_id, command)
self.assertFalse(any('/var/lib/product-vamp' in argument for argument in command))
self.assertFalse(any('/var/lib/product_vamp' in argument for argument in command))