From 00d9b749d900b9ca9fff5ead149992a5eb9602fa Mon Sep 17 00:00:00 2001 From: Qixiang Wan Date: Feb 15 2017 05:29:03 +0000 Subject: [PATCH 1/3] compose-create-next-dir: create COMPOSE_ID and composeinfo_base.json After create the empty directory for next compose, need to create composeinfo_base.json as Pungi will look for it when start from the specified compose dir. Also create the COMPOSE_ID to align with Pungi's behaviour. Signed-off-by: Qixiang Wan --- diff --git a/compose_utils/create_next_dir.py b/compose_utils/create_next_dir.py index 8ef4664..5ac5183 100644 --- a/compose_utils/create_next_dir.py +++ b/compose_utils/create_next_dir.py @@ -57,6 +57,11 @@ def get_compose_dir(topdir, conf, compose_type="production", compose_date=None, continue break + open(os.path.join(compose_dir, "COMPOSE_ID"), "w").write(ci.compose.id) + work_dir = os.path.join(compose_dir, "work", "global") + os.makedirs(work_dir) + ci.dump(os.path.join(work_dir, "composeinfo-base.json")) + return compose_dir diff --git a/tests/test_create_next_dir.py b/tests/test_create_next_dir.py index 5fc36a0..bfb5652 100644 --- a/tests/test_create_next_dir.py +++ b/tests/test_create_next_dir.py @@ -1,5 +1,6 @@ # -*- encoding: utf-8 -*- +import json import mock import unittest import shutil @@ -147,3 +148,44 @@ class CreateNextDirTest(unittest.TestCase): self.assertIn("[Errno 13] Permission denied: '%s'" % compose_dir, str(ctx.exception)) # restore write permission so it can be removed os.chmod(self.target_dir, 777) + + @freeze_time("2016-01-01") + def test_create_compose_id(self): + cfg = """ + release_name = "Dummy Product" + release_short = "DP" + release_version = "1.0" + """ + compose_dir = os.path.join(self.target_dir, 'DP-1.0-20160101.0') + config = self._write_config_from_string(cfg) + with mock.patch('sys.stdout', new_callable=StringIO) as out: + create_next_dir.run(['--target-dir=%s' % self.target_dir, + '--config=%s' % config]) + + self.assertEqual(out.getvalue().strip(), compose_dir) + compose_id_file = os.path.join(compose_dir, 'COMPOSE_ID') + self.assertTrue(os.path.exists(compose_id_file)) + with open(compose_id_file, 'r') as f: + self.assertIn('DP-1.0-20160101.0', f.readlines()) + + @freeze_time("2016-01-01") + def test_create_base_composeinfo(self): + cfg = """ + release_name = "Dummy Product" + release_short = "DP" + release_version = "1.0" + """ + compose_dir = os.path.join(self.target_dir, 'DP-1.0-20160101.0') + config = self._write_config_from_string(cfg) + with mock.patch('sys.stdout', new_callable=StringIO) as out: + create_next_dir.run(['--target-dir=%s' % self.target_dir, + '--config=%s' % config]) + self.assertEqual(out.getvalue().strip(), compose_dir) + + work_dir = os.path.join(compose_dir, "work", "global") + base_composeinfo_file = os.path.join(work_dir, "composeinfo-base.json") + self.assertTrue(os.path.exists(base_composeinfo_file)) + with open(base_composeinfo_file, 'r') as f: + info = json.load(f) + compose = info.get('payload', {}).get('compose', {}) + self.assertEqual(compose.get('id', ''), 'DP-1.0-20160101.0') From 07e51ad83ac438df33167f7b4752aaa3d821553a Mon Sep 17 00:00:00 2001 From: Qixiang Wan Date: Feb 15 2017 05:39:51 +0000 Subject: [PATCH 2/3] compose-create-next-dir: add --label and --no-label options Add the two options, so the behaviour of compose-create-next-dir aligns with Pungi, and label won't be missed from composeinfo-base.json. Signed-off-by: Qixiang Wan --- diff --git a/compose_utils/create_next_dir.py b/compose_utils/create_next_dir.py index 5ac5183..f72dadf 100644 --- a/compose_utils/create_next_dir.py +++ b/compose_utils/create_next_dir.py @@ -66,9 +66,10 @@ def get_compose_dir(topdir, conf, compose_type="production", compose_date=None, def main(args): + conf = kobo.conf.PyConfigParser() conf.load_from_file(args.config) - next_dir = get_compose_dir(args.target_dir, conf, compose_type=args.type) + next_dir = get_compose_dir(args.target_dir, conf, compose_type=args.type, compose_label=args.label) print(next_dir) @@ -93,6 +94,20 @@ def run(arguments=None): default='production', help='compose type', ) + parser.add_argument( + "--label", + metavar="LABEL", + help="specify compose label (example: Snapshot-1.0); required for production composes" + ) + parser.add_argument( + "--no-label", + action="store_true", + default=False, + help="make a production compose without label" + ) args = parser.parse_args(arguments) + if args.type == "production" and not args.label and not args.no_label: + raise RuntimeError("label is required for a production compose, " + "or you can run this with '--no-label'") main(args) diff --git a/doc/compose-create-next-dir.1 b/doc/compose-create-next-dir.1 index 5382ce0..e474595 100644 --- a/doc/compose-create-next-dir.1 +++ b/doc/compose-create-next-dir.1 @@ -19,6 +19,12 @@ Print help and exit. .TP .BR \-\-type=\fITYPE\fR Compose type. Valid types: production, test, nightly, ci. Default is production. +.TP +.BR \-\-label=\fILABEL\fR +Specify compose label (example: Snapshot-1.0); required for production composes. +.TP +.BR \-\-no\-label +Make a production compose without label. It's required if compose type is production and no label is specified. .SH EXIT CODE On success, this tools exits with status code of \fB0\fR. On failure, the exit code will be \fB1\fR. diff --git a/tests/test_create_next_dir.py b/tests/test_create_next_dir.py index bfb5652..1ac7056 100644 --- a/tests/test_create_next_dir.py +++ b/tests/test_create_next_dir.py @@ -30,7 +30,7 @@ class CreateNextDirTest(unittest.TestCase): return config_file @freeze_time("2016-01-01") - def test_create_next_production_compose_dir(self): + def test_create_next_production_compose_dir_with_label(self): cfg = """ release_name = "Dummy Product" release_short = "DP" @@ -39,12 +39,43 @@ class CreateNextDirTest(unittest.TestCase): config = self._write_config_from_string(cfg) with mock.patch('sys.stdout', new_callable=StringIO) as out: create_next_dir.run(['--target-dir=%s' % self.target_dir, - '--config=%s' % config]) + '--config=%s' % config, + '--label=Snapshot-2.0']) compose_dir = os.path.join(self.target_dir, 'DP-1.0-20160101.0') self.assertEqual(out.getvalue().strip(), compose_dir) self.assertTrue(os.path.isdir(compose_dir)) @freeze_time("2016-01-01") + def test_create_next_production_compose_dir_with_no_label(self): + cfg = """ + release_name = "Dummy Product" + release_short = "DP" + release_version = "1.0" + """ + config = self._write_config_from_string(cfg) + with mock.patch('sys.stdout', new_callable=StringIO) as out: + create_next_dir.run(['--target-dir=%s' % self.target_dir, + '--config=%s' % config, + '--no-label']) + compose_dir = os.path.join(self.target_dir, 'DP-1.0-20160101.0') + self.assertEqual(out.getvalue().strip(), compose_dir) + self.assertTrue(os.path.isdir(compose_dir)) + + @freeze_time("2016-01-01") + def test_create_next_production_compose_dir_error_without_label(self): + cfg = """ + release_name = "Dummy Product" + release_short = "DP" + release_version = "1.0" + """ + config = self._write_config_from_string(cfg) + with self.assertRaises(RuntimeError) as ctx: + create_next_dir.run(['--target-dir=%s' % self.target_dir, + '--config=%s' % config]) + self.assertIn("label is required for a production compose, or you can run this with '--no-label'", + str(ctx.exception)) + + @freeze_time("2016-01-01") def test_create_next_test_compose_dir(self): cfg = """ release_name = "Dummy Product" @@ -104,7 +135,8 @@ class CreateNextDirTest(unittest.TestCase): os.makedirs(os.path.join(self.target_dir, 'DP-1.0-20160101.0')) with mock.patch('sys.stdout', new_callable=StringIO) as out: create_next_dir.run(['--target-dir=%s' % self.target_dir, - '--config=%s' % config]) + '--config=%s' % config, + '--no-label']) compose_dir = os.path.join(self.target_dir, 'DP-1.0-20160101.1') self.assertEqual(out.getvalue().strip(), compose_dir) @@ -113,7 +145,8 @@ class CreateNextDirTest(unittest.TestCase): os.makedirs(os.path.join(self.target_dir, 'DP-1.0-20160101.2')) with mock.patch('sys.stdout', new_callable=StringIO) as out: create_next_dir.run(['--target-dir=%s' % self.target_dir, - '--config=%s' % config]) + '--config=%s' % config, + '--no-label']) compose_dir = os.path.join(self.target_dir, 'DP-1.0-20160101.3') self.assertEqual(out.getvalue().strip(), compose_dir) @@ -128,7 +161,8 @@ class CreateNextDirTest(unittest.TestCase): config = self._write_config_from_string(cfg) with self.assertRaises(create_next_dir.MissingConfigOptionError) as ctx: create_next_dir.run(['--target-dir=%s' % self.target_dir, - '--config=%s' % config]) + '--config=%s' % config, + '--no-label']) self.assertIn("Option 'release_short' is missed from config", str(ctx.exception)) @@ -144,7 +178,8 @@ class CreateNextDirTest(unittest.TestCase): os.chmod(self.target_dir, 555) with self.assertRaises(OSError) as ctx: create_next_dir.run(['--target-dir=%s' % self.target_dir, - '--config=%s' % config]) + '--config=%s' % config, + '--no-label']) self.assertIn("[Errno 13] Permission denied: '%s'" % compose_dir, str(ctx.exception)) # restore write permission so it can be removed os.chmod(self.target_dir, 777) @@ -160,7 +195,8 @@ class CreateNextDirTest(unittest.TestCase): config = self._write_config_from_string(cfg) with mock.patch('sys.stdout', new_callable=StringIO) as out: create_next_dir.run(['--target-dir=%s' % self.target_dir, - '--config=%s' % config]) + '--config=%s' % config, + '--no-label']) self.assertEqual(out.getvalue().strip(), compose_dir) compose_id_file = os.path.join(compose_dir, 'COMPOSE_ID') @@ -179,7 +215,8 @@ class CreateNextDirTest(unittest.TestCase): config = self._write_config_from_string(cfg) with mock.patch('sys.stdout', new_callable=StringIO) as out: create_next_dir.run(['--target-dir=%s' % self.target_dir, - '--config=%s' % config]) + '--config=%s' % config, + '--no-label']) self.assertEqual(out.getvalue().strip(), compose_dir) work_dir = os.path.join(compose_dir, "work", "global") From d2a8f9e5ff05e090181fe4f29c86e7c8f3b2a257 Mon Sep 17 00:00:00 2001 From: Qixiang Wan Date: Feb 15 2017 05:48:46 +0000 Subject: [PATCH 3/3] Update README.rst Signed-off-by: Qixiang Wan --- diff --git a/README.rst b/README.rst index 4d076d7..4ff5d12 100644 --- a/README.rst +++ b/README.rst @@ -25,6 +25,9 @@ Contents composes. Useful for identification of packages which were moved from optional to main variant. +**compose-create-next-dir** + create compose dir for next compose + Related tools -------------