Coverage for heliumcli/actions/deploybuild.py: 82.09%

67 statements  

« prev     ^ index     » next       coverage.py v7.4.1, created at 2024-02-06 15:29 +0000

1import os 

2import subprocess 

3import sys 

4 

5import git 

6 

7from .. import utils 

8 

9__author__ = "Alex Laird" 

10__copyright__ = "Copyright 2018, Helium Edu" 

11__version__ = "1.5.0" 

12 

13 

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" 

18 

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) 

33 

34 def run(self, args): 

35 config = utils.get_config() 

36 ansible_dir = utils.get_ansible_dir() 

37 

38 version = args.version.lstrip("v") 

39 

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 

52 

53 repo.git.checkout(version) 

54 

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"]]) 

59 

60 playbook_options = ["--inventory-file={}/hosts/{}".format(ansible_dir, args.env), "-v", 

61 "--extra-vars", "build_version={}".format(version)] 

62 

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)) 

77 

78 if args.roles: 

79 playbook_options.append("--limit") 

80 playbook_options.append(",".join(args.roles)) 

81 

82 cmd = ["ansible-playbook"] + playbook_options + ["{}/{}.yml".format(ansible_dir, args.env)] 

83 print("Executing Ansible command: {}".format(cmd)) 

84 ret = subprocess.call(cmd) 

85 

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)