Coverage for heliumcli/actions/deploybuild.py: 82.09%
67 statements
« prev ^ index » next coverage.py v7.3.2, created at 2023-12-01 17:33 +0000
« prev ^ index » next coverage.py v7.3.2, created at 2023-12-01 17:33 +0000
1import os
2import subprocess
3import sys
5import git
7from .. import utils
9__author__ = "Alex Laird"
10__copyright__ = "Copyright 2018, Helium Edu"
11__version__ = "1.5.0"
14class DeployBuildAction:
15 def __init__(self):
16 self.name = "deploy-build"
17 self.help = "Deploy the specified build, which may be a versioned release or a branch"
19 def setup(self, subparsers):
20 parser = subparsers.add_parser(self.name, help=self.help)
21 parser.add_argument("version", help="The build version to be deployed, which may be a version or a branch")
22 parser.add_argument("env", help="The environment to deploy to")
23 parser.add_argument("--roles", action="store", type=str, nargs="*",
24 help="Limit the project roles to be deployed")
25 parser.add_argument("--migrate", action="store_true", help="Install code dependencies and run migrations")
26 parser.add_argument("--code", action="store_true", help="Only deploy code")
27 parser.add_argument("--envvars", action="store_true", help="Only deploy environment variables")
28 parser.add_argument("--conf", action="store_true",
29 help="Only deploy configuration files and restart necessary services")
30 parser.add_argument("--ssl", action="store_true",
31 help="Only deploy SSL certificates and restart necessary services")
32 parser.set_defaults(action=self)
34 def run(self, args):
35 config = utils.get_config()
36 ansible_dir = utils.get_ansible_dir()
38 version = args.version.lstrip("v")
40 if config["projectsRelativeDir"] != ".":
41 root_dir = os.path.abspath(os.path.join(ansible_dir, ".."))
42 if os.path.exists(os.path.join(root_dir, ".git")):
43 repo = git.Repo(root_dir)
44 try:
45 repo.git.fetch(tags=True, prune=True,
46 force=os.environ.get("HELIUMCLI_FORCE_FETCH", "False") == "True")
47 except git.GitCommandError as ex:
48 if ex.status == 128:
49 print("WARN: if you want to get the latest code updates, verify your network connection.")
50 else:
51 raise ex
53 repo.git.checkout(version)
55 hosts = utils.parse_hosts_file(args.env)
56 for host in hosts:
57 subprocess.call(["ssh", "-t", "{}@{}".format(host[0], host[1]),
58 config["hostProvisionCommand"]])
60 playbook_options = ["--inventory-file={}/hosts/{}".format(ansible_dir, args.env), "-v",
61 "--extra-vars", "build_version={}".format(version)]
63 if args.migrate or args.code or args.envvars or args.conf or args.ssl:
64 tags = []
65 if args.code:
66 tags.append("code")
67 if args.migrate:
68 tags.append("migrate")
69 if args.envvars:
70 tags.append("envvars")
71 if args.conf:
72 tags.append("conf")
73 if args.ssl:
74 tags.append("ssl")
75 playbook_options.append("--tags")
76 playbook_options.append(",".join(tags))
78 if args.roles:
79 playbook_options.append("--limit")
80 playbook_options.append(",".join(args.roles))
82 cmd = ["ansible-playbook"] + playbook_options + ["{}/{}.yml".format(ansible_dir, args.env)]
83 print("Executing Ansible command: {}".format(cmd))
84 ret = subprocess.call(cmd)
86 if isinstance(ret, int) and ret != 0:
87 if ret < 0:
88 print("Error: Ansible killed by signal")
89 else:
90 print("Error: Ansible failed with return value {}".format(ret))
91 sys.exit(1)