83 lines
5.0 KiB
Python
83 lines
5.0 KiB
Python
import hashlib
|
|
import subprocess
|
|
import sys
|
|
import tarfile
|
|
import tempfile
|
|
import unittest
|
|
from pathlib import Path
|
|
from unittest.mock import patch
|
|
|
|
from package.scripts import publish_latest_generic_package
|
|
|
|
class PackagePublishingTests(unittest.TestCase):
|
|
def test_configured_packager_matches_publisher(self):
|
|
root = Path(__file__).resolve().parents[1]
|
|
runtime = root / 'build/build_common/modulus'
|
|
if not (runtime / 'modulus/cli.py').is_file():
|
|
self.skipTest('Configure first to check the exported Modulus packager')
|
|
with patch.object(sys, 'path', [str(runtime), *sys.path]):
|
|
import modulus.cli
|
|
import modulus.config
|
|
with tempfile.TemporaryDirectory() as temporary:
|
|
directory = Path(temporary)
|
|
context = modulus.cli.build_context(directory, modulus.config.load_repo_config(root))
|
|
name, registry, targets = publish_latest_generic_package.read_config(root / 'modulus.json')
|
|
def fake_build(context, command, **kwargs):
|
|
if command[:2] == ['cmake', '--install']:
|
|
stage = Path(command[2]).parent / 'stage'
|
|
(stage / 'manifest.json').write_text('{}\n')
|
|
return 0
|
|
with patch.object(modulus.cli, 'in_docker', return_value=True), \
|
|
patch.object(modulus.cli, 'run', side_effect=fake_build), \
|
|
patch.object(modulus.cli, 'run_capture', return_value=subprocess.CompletedProcess([], 0, stdout='fixture\n', stderr='')), \
|
|
patch.object(modulus.cli, 'upload_generic_artifact') as upload:
|
|
self.assertEqual(modulus.cli.package_artifacts(context, ['--no-remote']), 0)
|
|
upload.assert_not_called()
|
|
try:
|
|
artifacts = publish_latest_generic_package.discover_artifacts(directory / 'build/packages', name, targets)
|
|
except SystemExit as error:
|
|
self.fail(str(error))
|
|
for archive, checksum in zip(artifacts[::2], artifacts[1::2]):
|
|
self.assertEqual(checksum.read_text(), f'{hashlib.sha256(archive.read_bytes()).hexdigest()} {archive.name}\n')
|
|
with tarfile.open(archive) as package:
|
|
self.assertIn('manifest.json', package.getnames())
|
|
def test_only_configured_target_archives_and_checksums_are_uploaded(self):
|
|
with tempfile.TemporaryDirectory() as temporary:
|
|
root = Path(temporary)
|
|
archive = root / 'product-vamp-arm_64_gcc12_release.tar.gz'
|
|
checksum = archive.with_name(archive.name + '.sha256')
|
|
for path in (archive, checksum, root / 'product-vamp-obsolete-arm_64_gcc12_release.tar.gz'):
|
|
path.write_bytes(b'fixture')
|
|
self.assertEqual(publish_latest_generic_package.discover_artifacts(root, 'product-vamp', ['arm_64_gcc12_release']), [archive, checksum])
|
|
checksum.unlink()
|
|
with self.assertRaisesRegex(SystemExit, 'missing artifact files'):
|
|
publish_latest_generic_package.discover_artifacts(root, 'product-vamp', ['arm_64_gcc12_release'])
|
|
archive.unlink()
|
|
with self.assertRaisesRegex(SystemExit, 'missing artifact files'):
|
|
publish_latest_generic_package.discover_artifacts(root, 'product-vamp', ['arm_64_gcc12_release'])
|
|
def test_mismatched_filenames_report_actual_artifacts_without_uploading(self):
|
|
with tempfile.TemporaryDirectory() as temporary, patch.object(publish_latest_generic_package, 'request') as request:
|
|
archive = Path(temporary) / 'product-vamp-abc123-arm_64_gcc12_release.tar.gz'
|
|
archive.write_bytes(b'fixture')
|
|
with self.assertRaises(SystemExit) as error:
|
|
publish_latest_generic_package.main(['--dist-dir', temporary, '--user', 'user', '--token', 'test-token'])
|
|
self.assertIn(f'Found: {archive.name}', str(error.exception))
|
|
self.assertIn('Publish the current Modulus tooling', str(error.exception))
|
|
request.assert_not_called()
|
|
def test_missing_artifacts_do_not_touch_the_registry(self):
|
|
with tempfile.TemporaryDirectory() as temporary, patch.object(publish_latest_generic_package, 'request') as request:
|
|
with self.assertRaisesRegex(SystemExit, 'missing artifact files'):
|
|
publish_latest_generic_package.main(['--dist-dir', temporary, '--user', 'user', '--token', 'test-token'])
|
|
request.assert_not_called()
|
|
def test_publication_replaces_the_single_registry_slot(self):
|
|
archive = Path('product-vamp-arm_64_gcc12_release.tar.gz')
|
|
with patch.object(publish_latest_generic_package, 'discover_artifacts', return_value=[archive]), \
|
|
patch.object(publish_latest_generic_package, 'list_versions', return_value=['latest', 'obsolete']), \
|
|
patch.object(publish_latest_generic_package, 'delete_version') as delete, \
|
|
patch.object(publish_latest_generic_package, 'upload_file') as upload:
|
|
self.assertEqual(publish_latest_generic_package.main(['--user', 'user', '--token', 'test-token']), 0)
|
|
self.assertEqual([call.args[-2] for call in delete.call_args_list], ['latest', 'obsolete'])
|
|
self.assertEqual(upload.call_args.args[2], archive)
|
|
url = publish_latest_generic_package.file_upload_url('https://example.test/generic', 'product-vamp', archive)
|
|
self.assertEqual(url, 'https://example.test/generic/product-vamp/latest/product-vamp-arm_64_gcc12_release.tar.gz')
|