Coverage for heliumcli/actions/buildrelease.py: 85.06%
87 statements
« prev ^ index » next coverage.py v7.3.2, created at 2023-11-22 17:35 +0000
« prev ^ index » next coverage.py v7.3.2, created at 2023-11-22 17:35 +0000
1import datetime
2import os
3import shutil
5import git
7from .. import utils
8from .prepcode import PrepCodeAction
10__author__ = "Alex Laird"
11__copyright__ = "Copyright 2018, Helium Edu"
12__version__ = "1.5.0"
15class BuildReleaseAction:
16 def __init__(self):
17 self.name = "build-release"
18 self.help = "Build a release version for all projects, tagging when complete"
20 def setup(self, subparsers):
21 parser = subparsers.add_parser(self.name, help=self.help)
22 parser.add_argument("version", help="The version number to be tagged")
23 parser.add_argument("--roles", action="store", type=str, nargs="*",
24 help="Limit the project roles to be built/tagged")
25 parser.set_defaults(action=self)
27 def run(self, args):
28 config = utils.get_config()
29 projects_dir = utils.get_projects_dir()
31 # First ensure all repos are in a clean state with all changes committed
32 dirty_repos = []
33 for project in utils.get_projects(config):
34 if args.roles and project not in args.roles:
35 continue
37 if config["projectsRelativeDir"] != ".":
38 project_path = os.path.join(projects_dir, project)
39 else:
40 project_path = os.path.join(projects_dir)
42 repo = git.Repo(project_path)
44 if repo.untracked_files or repo.is_dirty():
45 print("Untracked files in {}: {}".format(project, repo.untracked_files))
47 dirty_repos.append(project)
48 else:
49 repo.git.fetch(tags=True, prune=True)
50 repo.git.checkout(config["branchName"])
52 if len(dirty_repos) > 0:
53 print("WARN: this operation cannot be performed when a repo is dirty. Commit all changes to the following "
54 "repos before proceeding: {}".format(dirty_repos))
56 return
58 version = args.version.lstrip("v")
60 self._update_version_file(version,
61 os.path.join(config["versionInfo"]["project"], config["versionInfo"]["path"]))
63 prepcodeaction = PrepCodeAction()
64 prepcodeaction.run(args)
66 print("Committing changes and creating release tags ...")
68 for project in utils.get_projects(config):
69 print(project)
71 if config["projectsRelativeDir"] != ".":
72 project_path = os.path.join(projects_dir, project)
73 else:
74 project_path = os.path.join(projects_dir)
76 self._commit_and_tag(project_path, version, config["remoteName"], config["branchName"])
78 if config["projectsRelativeDir"] != ".":
79 root_dir = os.path.abspath(os.path.join(projects_dir, ".."))
80 if os.path.exists(os.path.join(root_dir, ".git")):
81 print(utils.get_repo_name(root_dir, config["remoteName"]))
82 self._commit_and_tag(root_dir, version, config["remoteName"], config["branchName"])
84 print("... release version {} built.".format(version))
86 def _commit_and_tag(self, path, version, remote_name, branch_name):
87 repo = git.Repo(path)
89 if version in repo.tags:
90 print("Version already exists, not doing anything.")
91 else:
92 if repo.is_dirty():
93 repo.git.add(u=True)
94 repo.git.commit(m="[heliumcli] Release {}".format(version))
95 repo.remotes[remote_name].push(branch_name)
96 tag = repo.create_tag(version, m="")
97 repo.remotes[remote_name].push(tag)
99 def _update_version_file(self, version, path):
100 config = utils.get_config()
102 version_file_path = os.path.join(utils.get_projects_dir(), path)
104 version_file = open(version_file_path, "r")
105 new_version_file = open(version_file_path + ".tmp", "w")
107 for line in version_file:
108 if version_file_path.endswith(".py"):
109 if line.strip().startswith("__version__ ="):
110 line = "__version__ = \"{}\"\n".format(version)
111 elif line.strip().startswith("__copyright__ = "):
112 line = "__copyright__ = \"Copyright {}, {}\"\n".format(str(datetime.date.today().year),
113 utils.get_copyright_name())
114 elif version_file.name == "package.json":
115 if line.strip().startswith("\"version\":"):
116 line = " \"version\": \"{}\",\n".format(version)
117 # TODO: implement other known types
118 else:
119 print("WARN: helium-cli does not know how to process this type of file for version file: {}".format(
120 config["versionInfo"]["path"]))
122 new_version_file.close()
123 os.remove(version_file_path + ".tmp")
125 return
127 new_version_file.write(line)
129 version_file.close()
130 new_version_file.close()
132 shutil.copy(version_file_path + ".tmp", version_file_path)
133 os.remove(version_file_path + ".tmp")