This commit is contained in:
khodowany
2026-09-25 11:37:00 -05:00
parent 17326dbf56
commit 82b9541a03
4 changed files with 51 additions and 2 deletions
+2
View File
@@ -98,6 +98,8 @@ jobs:
restore-keys: product-vamp-conan-${{ runner.os }}-
- name: Configure native release
run: python3 modulus.py configure --target x86_64_gcc12_release --update
- name: Check package tooling
run: python3 -m unittest discover -s tests -p 'test_publish_package.py'
- name: Check code style
run: |
python3 -m pip install --no-cache-dir -r build/build_tools/docker/format-requirements.txt
+1 -1
View File
@@ -82,7 +82,7 @@ PACKAGE_REGISTRY_TOKEN=<token> \
python3 package/scripts/publish_latest_generic_package.py
```
Artifacts are published to the khodo generic package registry's required `latest` slot. Publish the updated Modulus tooling before running Product Vamp CI so packaging and publishing agree on the stable filenames.
Artifacts are published to the khodo generic package registry's required `latest` slot. Publish the updated Modulus tooling before running Product Vamp CI so packaging and publishing agree on the stable filenames. CI checks this contract immediately after configure using a tiny fixture archive, without compiling or contacting the registry. A failure here means the exported Modulus packager needs updating; rerun the full workflow after publishing Modulus, not just the upload step.
## Score Assets
@@ -139,7 +139,10 @@ def discover_artifacts(dist_dir, package_name, targets):
artifacts.extend((archive, archive.with_name(archive.name + ".sha256")))
missing = [path for path in artifacts if not path.is_file()]
if missing:
raise SystemExit("missing artifact files: " + ", ".join(str(path) for path in missing))
found = sorted(path.name for path in dist_dir.glob(f"{package_name}-*.tar.gz*") if path.is_file())
raise SystemExit("missing artifact files: " + ", ".join(str(path) for path in missing)
+ "\nFound: " + (", ".join(found) or "none")
+ "\nPublish the current Modulus tooling, run configure --update, and recreate the package so the builder and publisher use the same filenames.")
return artifacts
def upload_file(registry_url, package_name, path, auth):
+44
View File
@@ -1,3 +1,7 @@
import hashlib
import subprocess
import sys
import tarfile
import tempfile
import unittest
from pathlib import Path
@@ -6,6 +10,37 @@ 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)
@@ -20,6 +55,15 @@ class PackagePublishingTests(unittest.TestCase):
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'):