diff --git a/src/tito/release.py b/src/tito/release.py index 51f4430..3225643 100644 --- a/src/tito/release.py +++ b/src/tito/release.py @@ -10,6 +10,7 @@ # Red Hat trademarks are not licensed under GPLv2. No permission is # granted to use or replicate Red Hat trademarks that are incorporated # in this software or its documentation. +from ConfigParser import NoOptionError """ Code for submitting builds for release. @@ -362,13 +363,23 @@ class FedoraGitReleaser(Releaser): self.git_branches = \ self.releaser_config.get(self.target, "branches").split(" ") + self.package_workdir = os.path.join(self.working_dir, self.project_name) + build_target_parser = BuildTargetParser(self.releaser_config, self.target, + self.git_branches) + self.build_targets = build_target_parser.get_build_targets() + def release(self, dry_run=False): self.dry_run = dry_run self._git_release() + def _get_build_target_for_branch(self, branch): + if branch in self.build_targets: + return self.build_targets[branch] + return None + def _git_release(self): commands.getoutput("mkdir -p %s" % self.working_dir) @@ -475,7 +486,7 @@ class FedoraGitReleaser(Releaser): print(cmd) run_command(cmd) - self._build() + self._build(main_branch) for branch in self.git_branches[1:]: print("Merging branch: '%s' -> '%s'" % (main_branch, branch)) @@ -489,7 +500,7 @@ class FedoraGitReleaser(Releaser): print(cmd) run_command(cmd) - self._build() + self._build(branch) print def _merge(self, main_branch): @@ -511,9 +522,14 @@ class FedoraGitReleaser(Releaser): # TODO: maybe prompt y/n here os.system(os.environ['SHELL']) - def _build(self): + def _build(self, branch): """ Submit a Fedora build from current directory. """ - build_cmd = "%s build --nowait" % self.cli_tool + target_param = "" + build_target = self._get_build_target_for_branch(branch) + if build_target: + target_param = "--target %s" % build_target + + build_cmd = "%s build --nowait %s" % (self.cli_tool, target_param) if self.dry_run: self.print_dry_run_warning(build_cmd) @@ -956,3 +972,54 @@ class KojiGitReleaser(KojiReleaser): output = run_command(cmd) print(output) + + +class BuildTargetParser(object): + """ + Parses build targets from a string in the format of: + : : ... + + Each target must be associated with a valid branch. + """ + + def __init__(self, releaser_config, release_target, valid_branches): + self.releaser_config = releaser_config + self.release_target = release_target + self.valid_branches = valid_branches + + def get_build_targets(self): + build_targets = {} + if not self.releaser_config.has_option(self.release_target, "build_targets"): + return build_targets + + defined_build_targets = self.releaser_config.get(self.release_target, + "build_targets").split(" ") + for build_target in defined_build_targets: + # Ignore any empty from multiple spaces in the file. + if not build_target: + continue + + branch, target = self._parse_build_target(build_target) + build_targets[branch] = target + + return build_targets + + def _parse_build_target(self, build_target): + """ Parses a string in the format of branch:target """ + if not build_target: + raise TitoException("Invalid build_target: %s. Format: :" + % build_target) + + parts = build_target.split(":") + if len(parts) != 2: + raise TitoException("Invalid build_target: %s. Format: :" + % build_target) + branch = parts[0] + if not branch in self.valid_branches: + raise TitoException("Invalid build_target: %s. Unknown branch reference." + % build_target) + target = parts[1] + if not target: + raise TitoException("Invalid build_target: %s. Empty target" % build_target) + + return (branch, target) diff --git a/test/unit/test_build_target_parser.py b/test/unit/test_build_target_parser.py new file mode 100644 index 0000000..cff1460 --- /dev/null +++ b/test/unit/test_build_target_parser.py @@ -0,0 +1,76 @@ + +import unittest +from tito.release import BuildTargetParser +from ConfigParser import ConfigParser +from tito.exception import TitoException + + +class BuildTargetParserTests(unittest.TestCase): + + def setUp(self): + unittest.TestCase.setUp(self) + self.valid_branches = ["branch1", "branch2"] + + self.release_target = "project-x.y.z" + self.releasers_config = ConfigParser() + self.releasers_config.add_section(self.release_target) + self.releasers_config.set(self.release_target, "build_targets", + "branch1:project-x.y.z-candidate") + + def test_parser_gets_correct_targets(self): + parser = BuildTargetParser(self.releasers_config, self.release_target, + self.valid_branches) + release_targets = parser.get_build_targets() + self.assertTrue("branch1" in release_targets) + self.assertEqual("project-x.y.z-candidate", release_targets["branch1"]) + self.assertFalse("branch2" in release_targets) + + def test_invalid_branch_raises_exception(self): + self.releasers_config.set(self.release_target, "build_targets", + "invalid-branch:project-x.y.z-candidate") + parser = BuildTargetParser(self.releasers_config, self.release_target, + self.valid_branches) + self.assertRaises(TitoException, parser.get_build_targets) + + def test_missing_semicolon_raises_exception(self): + self.releasers_config.set(self.release_target, "build_targets", + "invalid-branchproject-x.y.z-candidate") + parser = BuildTargetParser(self.releasers_config, self.release_target, + self.valid_branches) + self.assertRaises(TitoException, parser.get_build_targets) + + def test_empty_branch_raises_exception(self): + self.releasers_config.set(self.release_target, "build_targets", + ":project-x.y.z-candidate") + parser = BuildTargetParser(self.releasers_config, self.release_target, + self.valid_branches) + self.assertRaises(TitoException, parser.get_build_targets) + + def test_empty_target_raises_exception(self): + self.releasers_config.set(self.release_target, "build_targets", + "branch1:") + parser = BuildTargetParser(self.releasers_config, self.release_target, + self.valid_branches) + self.assertRaises(TitoException, parser.get_build_targets) + + def test_multiple_spaces_ok(self): + self.releasers_config.set(self.release_target, "build_targets", + " branch1:project-x.y.z-candidate ") + parser = BuildTargetParser(self.releasers_config, self.release_target, + self.valid_branches) + release_targets = parser.get_build_targets() + self.assertEqual(1, len(release_targets)) + self.assertTrue("branch1" in release_targets) + self.assertEqual("project-x.y.z-candidate", release_targets["branch1"]) + + def test_multiple_branches_supported(self): + self.releasers_config.set(self.release_target, "build_targets", + "branch1:project-x.y.z-candidate branch2:second-target") + parser = BuildTargetParser(self.releasers_config, self.release_target, + self.valid_branches) + release_targets = parser.get_build_targets() + self.assertEquals(2, len(release_targets)) + self.assertTrue("branch1" in release_targets) + self.assertEqual("project-x.y.z-candidate", release_targets["branch1"]) + self.assertTrue("branch2" in release_targets) + self.assertEqual("second-target", release_targets['branch2'])