1import os 2import sys 3 4sys.path.insert(1, os.path.dirname(sys.path[0])) # noqa - don't warn about imports 5 6from mozharness.base.log import FATAL 7from mozharness.base.script import BaseScript 8 9 10class Repackage(BaseScript): 11 12 def __init__(self, require_config_file=False): 13 script_kwargs = { 14 'all_actions': [ 15 "setup", 16 "repackage", 17 ], 18 } 19 BaseScript.__init__( 20 self, 21 require_config_file=require_config_file, 22 **script_kwargs 23 ) 24 25 def setup(self): 26 dirs = self.query_abs_dirs() 27 28 self._run_tooltool() 29 30 mar_path = os.path.join(dirs['abs_input_dir'], 'mar') 31 if self._is_windows(): 32 mar_path += '.exe' 33 if mar_path and os.path.exists(mar_path): 34 self.chmod(mar_path, 0o755) 35 if self.config.get("run_configure", True): 36 self._get_mozconfig() 37 self._run_configure() 38 39 def query_abs_dirs(self): 40 if self.abs_dirs: 41 return self.abs_dirs 42 abs_dirs = super(Repackage, self).query_abs_dirs() 43 config = self.config 44 45 dirs = {} 46 dirs['abs_input_dir'] = os.path.join(abs_dirs['base_work_dir'], 'fetches') 47 output_dir_suffix = [] 48 if config.get('locale'): 49 output_dir_suffix.append(config['locale']) 50 if config.get('repack_id'): 51 output_dir_suffix.append(config['repack_id']) 52 dirs['abs_output_dir'] = os.path.join( 53 abs_dirs['abs_work_dir'], 'outputs', *output_dir_suffix) 54 for key in dirs.keys(): 55 if key not in abs_dirs: 56 abs_dirs[key] = dirs[key] 57 self.abs_dirs = abs_dirs 58 return self.abs_dirs 59 60 def repackage(self): 61 config = self.config 62 dirs = self.query_abs_dirs() 63 64 subst = { 65 'package-name': config['package-name'], 66 # sfx-stub is only defined for Windows targets 67 'sfx-stub': config.get('sfx-stub'), 68 'installer-tag': config['installer-tag'], 69 'stub-installer-tag': config['stub-installer-tag'], 70 'wsx-stub': config['wsx-stub'], 71 } 72 subst.update(dirs) 73 if config.get('fetch-dir'): 74 subst.update({'fetch-dir': os.path.abspath(config['fetch-dir'])}) 75 76 # Make sure the upload dir is around. 77 self.mkdir_p(dirs['abs_output_dir']) 78 79 for repack_config in config["repackage_config"]: 80 command = [sys.executable, 'mach', '--log-no-times', 'repackage'] 81 command.extend([arg.format(**subst) for arg in repack_config['args']]) 82 for arg, filename in repack_config['inputs'].items(): 83 command.extend([ 84 '--{}'.format(arg), 85 os.path.join(dirs['abs_input_dir'], filename), 86 ]) 87 command.extend([ 88 '--output', os.path.join(dirs['abs_output_dir'], repack_config['output']), 89 ]) 90 self.run_command( 91 command=command, 92 cwd=dirs['abs_src_dir'], 93 halt_on_failure=True, 94 env=self.query_env(), 95 ) 96 97 def _run_tooltool(self): 98 config = self.config 99 dirs = self.query_abs_dirs() 100 toolchains = os.environ.get('MOZ_TOOLCHAINS') 101 manifest_src = os.environ.get('TOOLTOOL_MANIFEST') 102 if not manifest_src: 103 manifest_src = config.get('tooltool_manifest_src') 104 if not manifest_src and not toolchains: 105 return 106 107 cmd = [ 108 sys.executable, '-u', 109 os.path.join(dirs['abs_src_dir'], 'mach'), 110 'artifact', 111 'toolchain', 112 '-v', 113 '--retry', '4', 114 '--artifact-manifest', 115 os.path.join(dirs['abs_src_dir'], 'toolchains.json'), 116 ] 117 if manifest_src: 118 cmd.extend([ 119 '--tooltool-manifest', 120 os.path.join(dirs['abs_src_dir'], manifest_src), 121 ]) 122 auth_file = self._get_tooltool_auth_file() 123 if auth_file: 124 cmd.extend(['--authentication-file', auth_file]) 125 cache = config.get('tooltool_cache') 126 if cache: 127 cmd.extend(['--cache-dir', cache]) 128 if toolchains: 129 cmd.extend(toolchains.split()) 130 self.info(str(cmd)) 131 self.run_command(cmd, cwd=dirs['abs_src_dir'], halt_on_failure=True) 132 133 def _get_tooltool_auth_file(self): 134 # set the default authentication file based on platform; this 135 # corresponds to where puppet puts the token 136 if 'tooltool_authentication_file' in self.config: 137 fn = self.config['tooltool_authentication_file'] 138 elif self._is_windows(): 139 fn = r'c:\builds\relengapi.tok' 140 else: 141 fn = '/builds/relengapi.tok' 142 143 # if the file doesn't exist, don't pass it to tooltool (it will just 144 # fail). In taskcluster, this will work OK as the relengapi-proxy will 145 # take care of auth. Everywhere else, we'll get auth failures if 146 # necessary. 147 if os.path.exists(fn): 148 return fn 149 150 def _get_mozconfig(self): 151 """assign mozconfig.""" 152 c = self.config 153 dirs = self.query_abs_dirs() 154 abs_mozconfig_path = '' 155 156 # first determine the mozconfig path 157 if c.get('src_mozconfig'): 158 self.info('Using in-tree mozconfig') 159 abs_mozconfig_path = os.path.join(dirs['abs_src_dir'], c['src_mozconfig']) 160 else: 161 self.fatal("'src_mozconfig' must be in the config " 162 "in order to determine the mozconfig.") 163 164 # print its contents 165 self.read_from_file(abs_mozconfig_path, error_level=FATAL) 166 167 # finally, copy the mozconfig to a path that 'mach build' expects it to be 168 self.copyfile(abs_mozconfig_path, os.path.join(dirs['abs_src_dir'], '.mozconfig')) 169 170 def _run_configure(self): 171 dirs = self.query_abs_dirs() 172 command = [sys.executable, 'mach', '--log-no-times', 'configure'] 173 return self.run_command( 174 command=command, 175 cwd=dirs['abs_src_dir'], 176 output_timeout=60*3, 177 halt_on_failure=True, 178 ) 179 180 181if __name__ == '__main__': 182 repack = Repackage() 183 repack.run_and_exit() 184