diff --git a/cloud-build.py b/cloud-build.py index 031e462..a648f41 100755 --- a/cloud-build.py +++ b/cloud-build.py @@ -23,6 +23,8 @@ def parse_args(): result[key] = v return result + stages = ['build', 'test', 'copy_external_files', 'sign', 'sync'] + parser = argparse.ArgumentParser( formatter_class=argparse.ArgumentDefaultsHelpFormatter, ) @@ -32,6 +34,20 @@ def parse_args(): default=f'/etc/{PROG}/config.yaml', help='path to config', ) + parser.add_argument( + '--stages', + nargs='+', + default=stages, + choices=stages, + help='list of stages', + ) + parser.add_argument( + '--skip-stages', + nargs='+', + default=[], + choices=stages, + help='list of sipping stages', + ) parser.add_argument( '--create-remote-dirs', action='store_true', @@ -60,12 +76,22 @@ def parse_args(): def main(): args = parse_args() - cb = cloud_build.CB(**dict(args._get_kwargs())) - cb.create_images() - cb.copy_external_files() - if not args.no_sign: + stages = set(args.stages) - set(args.skip_stages) + + cb = cloud_build.CB( + config=args.config, + tasks=args.tasks, + create_remote_dirs=args.create_remote_dirs, + ) + if 'build' in stages: + no_tests = 'test' not in stages + cb.create_images(no_tests=no_tests) + if 'copy_external_files' in stages: + cb.copy_external_files() + if 'sign' in stages: cb.sign() - cb.sync() + if 'sync' in stages: + cb.sync() if __name__ == '__main__': diff --git a/cloud_build/cloud_build.py b/cloud_build/cloud_build.py index cda78dc..465bd91 100755 --- a/cloud_build/cloud_build.py +++ b/cloud_build/cloud_build.py @@ -54,15 +54,11 @@ class CB: config: str, *, data_dir: Optional[PathLike] = None, - no_tests: bool = False, - no_sign: bool = False, create_remote_dirs: bool = False, tasks: Optional[dict[str, List[str]]] = None, ) -> None: self.initialized = False self._save_cwd = os.getcwd() - self.no_tests = no_tests - self.no_sign = no_sign self.parse_config(config) self._create_remote_dirs = create_remote_dirs if tasks is None: @@ -192,10 +188,9 @@ class CB: try: self._remote = self.expand_path(cfg['remote']) - if not self.no_sign: - self.key = cfg['key'] - if isinstance(self.key, int): - self.key = '{:X}'.format(self.key) + self.key = cfg.get('key') + if isinstance(self.key, int): + self.key = '{:X}'.format(self.key) self._images = cfg['images'] self._branches = cfg['branches'] for _, branch in self._branches.items(): @@ -638,7 +633,7 @@ Dir::Etc::preferencesparts "/var/empty"; if self._build_errors: self.error(MultipleBuildErrors(self._build_errors)) - def create_images(self) -> None: + def create_images(self, no_tests: bool = False) -> None: self.clear_images_dir() self.ensure_mkimage_profiles() @@ -661,7 +656,7 @@ Dir::Etc::preferencesparts "/var/empty"; continue image_path = self.image_path(image, branch, arch, kind) self.copy_image(tarball, image_path) - if not self.no_tests: + if not no_tests: for test in self.tests_by_image(image): self.info(f'Test {image} {branch} {arch}') if not cloud_build.image_tests.test( @@ -688,8 +683,8 @@ Dir::Etc::preferencesparts "/var/empty"; self.images_dir / branch / image) def sign(self): - if self.no_sign: - return + if self.key is None: + self.error('Pass key to config file for sign') sum_file = self.checksum_command.upper() for branch in self.branches: diff --git a/tests/minimal_config.yaml b/tests/minimal_config.yaml index b0b64b5..b748618 100644 --- a/tests/minimal_config.yaml +++ b/tests/minimal_config.yaml @@ -1,6 +1,5 @@ --- remote: '/var/empty' -key: 0x00000000 images: rootfs-minimal: diff --git a/tests/test_errors.py b/tests/test_errors.py index cb81083..2b52183 100644 --- a/tests/test_errors.py +++ b/tests/test_errors.py @@ -46,8 +46,7 @@ class TestErrors(TestCase): with open('tests/minimal_config.yaml') as f: cfg = yaml.safe_load(f) - parameter = 'key' - for parameter in ['remote', 'key', 'images', 'branches']: + for parameter in ['remote', 'images', 'branches']: with open(config, 'w') as f: yaml.safe_dump(update(cfg, {parameter: None}), f) @@ -69,14 +68,14 @@ class TestErrors(TestCase): cloud_build = CB( config='tests/test_try_build_all.yaml', data_dir=self.kwargs['data_dir'], - no_tests=True, create_remote_dirs=True, ) regex = r'build.*:' self.assertRaisesRegex( MultipleBuildErrors, regex, - cloud_build.create_images + cloud_build.create_images, + no_tests=True ) def test_try_build_all_non_zero_rc(self): @@ -87,14 +86,14 @@ class TestErrors(TestCase): cloud_build = CB( config='tests/test_try_build_all.yaml', data_dir=self.kwargs['data_dir'], - no_tests=True, create_remote_dirs=True, ) regex = r'build.*:' self.assertRaisesRegex( MultipleBuildErrors, regex, - cloud_build.create_images + cloud_build.create_images, + no_tests=True ) def test_not_try_build_all(self): @@ -105,14 +104,14 @@ class TestErrors(TestCase): cloud_build = CB( config='tests/test_not_try_build_all.yaml', data_dir=self.kwargs['data_dir'], - no_tests=True, create_remote_dirs=True, ) regex = r'build.*aarch64' self.assertRaisesRegex( BuildError, regex, - cloud_build.create_images + cloud_build.create_images, + no_tests=True ) def test_rebuild_after_format(self): @@ -126,6 +125,20 @@ class TestErrors(TestCase): cloud_build = CB( config='tests/test_bad_size.yaml', data_dir=self.kwargs['data_dir'], - no_tests=True, ) - self.assertRaisesRegex(Error, regex, cloud_build.create_images) + self.assertRaisesRegex( + Error, + regex, + cloud_build.create_images, + no_tests=True + ) + + def test_sign_requires_key(self): + with mock.patch('subprocess.call', call.Call()): + regex = 'key.*config' + cloud_build = CB( + config='tests/minimal_config.yaml', + data_dir=self.kwargs['data_dir'], + ) + cloud_build.create_images(no_tests=True) + self.assertRaisesRegex(Error, regex, cloud_build.sign) diff --git a/tests/test_integration_images.py b/tests/test_integration_images.py index 4ddf712..1462285 100644 --- a/tests/test_integration_images.py +++ b/tests/test_integration_images.py @@ -26,10 +26,9 @@ class TestIntegrationImages(TestCase): cloud_build = CB( config='tests/test_integration_images.yaml', data_dir=(cls.work_dir / 'cloud_build').as_posix(), - no_tests=True, create_remote_dirs=True, ) - cloud_build.create_images() + cloud_build.create_images(no_tests=True) cloud_build.copy_external_files() cloud_build.sign() cloud_build.sync() diff --git a/tests/test_no_delete.py b/tests/test_no_delete.py index 8e9093c..b619263 100644 --- a/tests/test_no_delete.py +++ b/tests/test_no_delete.py @@ -25,12 +25,11 @@ class TestNoDelete(TestCase): cb = CB( config='tests/test_no_delete_false.yaml', data_dir=self.data_dir, - no_tests=True, create_remote_dirs=True, ) other_file = self.images_dir / 'other_file.txt' other_file.write_text('Some text') - cb.create_images() + cb.create_images(no_tests=True) cb.sync() del cb msg = 'Other files shoud be deleted if not no_delete' @@ -42,12 +41,11 @@ class TestNoDelete(TestCase): cb = CB( config='tests/test_no_delete_true.yaml', data_dir=self.data_dir, - no_tests=True, create_remote_dirs=True, ) other_file = self.images_dir / 'other_file.txt' other_file.write_text('Some text') - cb.create_images() + cb.create_images(no_tests=True) cb.sync() del cb msg = 'Other files shoud not be deleted if no_delete' diff --git a/tests/test_rebuild.py b/tests/test_rebuild.py index 27258c0..3b9ada4 100644 --- a/tests/test_rebuild.py +++ b/tests/test_rebuild.py @@ -22,7 +22,6 @@ class TestRebuild(TestCase): self.cb = CB( config='tests/test_rebuild.yaml', data_dir=self.data_dir, - no_tests=True, create_remote_dirs=True, ) @@ -37,7 +36,7 @@ class TestRebuild(TestCase): os.utime(tarball, times=(two_hours_ago, two_hours_ago)) msg = 'Do not try to rebuild with outdated cache' with self.assertRaises(BuildError, msg=msg): - self.cb.create_images() + self.cb.create_images(no_tests=True) @mock.patch('subprocess.call', call.Call(decorators=DS)) def test_dont_rebuild(self): @@ -45,7 +44,7 @@ class TestRebuild(TestCase): tarball.touch() msg = 'Try to rebuild with valid cache' try: - self.cb.create_images() + self.cb.create_images(no_tests=True) except BuildError: self.fail(msg) @@ -53,7 +52,7 @@ class TestRebuild(TestCase): def test_dont_create_image_when_rebuild(self): tarball = self.data_dir / 'out/docker_Sisyphus-x86_64.tar.xz' tarball.touch() - self.cb.create_images() + self.cb.create_images(no_tests=True) image = ( self.data_dir / 'images'