at 22.05-pre 200 lines 6.6 kB view raw
1#!/usr/bin/env nix-shell 2#! nix-shell -I nixpkgs=../../../.. -i python3 -p bundix bundler nix-update nix nix-universal-prefetch python3 python3Packages.requests python3Packages.click python3Packages.click-log prefetch-yarn-deps 3 4import click 5import click_log 6import os 7import re 8import logging 9import subprocess 10import json 11import pathlib 12import tempfile 13from distutils.version import LooseVersion 14from typing import Iterable 15 16import requests 17 18logger = logging.getLogger(__name__) 19 20 21class GitLabRepo: 22 version_regex = re.compile(r"^v\d+\.\d+\.\d+(\-rc\d+)?(\-ee)?") 23 def __init__(self, owner: str = 'gitlab-org', repo: str = 'gitlab'): 24 self.owner = owner 25 self.repo = repo 26 27 @property 28 def url(self): 29 return f"https://gitlab.com/{self.owner}/{self.repo}" 30 31 @property 32 def tags(self) -> Iterable[str]: 33 r = requests.get(self.url + "/refs?sort=updated_desc&ref=master").json() 34 tags = r.get("Tags", []) 35 36 # filter out versions not matching version_regex 37 versions = list(filter(self.version_regex.match, tags)) 38 39 # sort, but ignore v and -ee for sorting comparisons 40 versions.sort(key=lambda x: LooseVersion(x.replace("v", "").replace("-ee", "")), reverse=True) 41 return versions 42 43 def get_git_hash(self, rev: str): 44 return subprocess.check_output(['nix-universal-prefetch', 'fetchFromGitLab', '--owner', self.owner, '--repo', self.repo, '--rev', rev]).decode('utf-8').strip() 45 46 def get_yarn_hash(self, rev: str): 47 with tempfile.TemporaryDirectory() as tmp_dir: 48 with open(tmp_dir + '/yarn.lock', 'w') as f: 49 f.write(self.get_file('yarn.lock', rev)) 50 return subprocess.check_output(['prefetch-yarn-deps', tmp_dir + '/yarn.lock']).decode('utf-8').strip() 51 52 @staticmethod 53 def rev2version(tag: str) -> str: 54 """ 55 normalize a tag to a version number. 56 This obviously isn't very smart if we don't pass something that looks like a tag 57 :param tag: the tag to normalize 58 :return: a normalized version number 59 """ 60 # strip v prefix 61 version = re.sub(r"^v", '', tag) 62 # strip -ee suffix 63 return re.sub(r"-ee$", '', version) 64 65 def get_file(self, filepath, rev): 66 """ 67 returns file contents at a given rev 68 :param filepath: the path to the file, relative to the repo root 69 :param rev: the rev to fetch at 70 :return: 71 """ 72 return requests.get(self.url + f"/raw/{rev}/{filepath}").text 73 74 def get_data(self, rev): 75 version = self.rev2version(rev) 76 77 passthru = {v: self.get_file(v, rev).strip() for v in ['GITALY_SERVER_VERSION', 'GITLAB_PAGES_VERSION', 78 'GITLAB_SHELL_VERSION']} 79 80 passthru["GITLAB_WORKHORSE_VERSION"] = version 81 82 return dict(version=self.rev2version(rev), 83 repo_hash=self.get_git_hash(rev), 84 yarn_hash=self.get_yarn_hash(rev), 85 owner=self.owner, 86 repo=self.repo, 87 rev=rev, 88 passthru=passthru) 89 90 91def _get_data_json(): 92 data_file_path = pathlib.Path(__file__).parent / 'data.json' 93 with open(data_file_path, 'r') as f: 94 return json.load(f) 95 96 97def _call_nix_update(pkg, version): 98 """calls nix-update from nixpkgs root dir""" 99 nixpkgs_path = pathlib.Path(__file__).parent / '../../../../' 100 return subprocess.check_output(['nix-update', pkg, '--version', version], cwd=nixpkgs_path) 101 102 103@click_log.simple_verbosity_option(logger) 104@click.group() 105def cli(): 106 pass 107 108 109@cli.command('update-data') 110@click.option('--rev', default='latest', help='The rev to use (vX.Y.Z-ee), or \'latest\'') 111def update_data(rev: str): 112 """Update data.nix""" 113 repo = GitLabRepo() 114 115 if rev == 'latest': 116 # filter out pre and re releases 117 rev = next(filter(lambda x: not ('rc' in x or x.endswith('pre')), repo.tags)) 118 logger.debug(f"Using rev {rev}") 119 120 version = repo.rev2version(rev) 121 logger.debug(f"Using version {version}") 122 123 data_file_path = pathlib.Path(__file__).parent / 'data.json' 124 125 data = repo.get_data(rev) 126 127 with open(data_file_path.as_posix(), 'w') as f: 128 json.dump(data, f, indent=2) 129 f.write("\n") 130 131 132@cli.command('update-rubyenv') 133def update_rubyenv(): 134 """Update rubyEnv""" 135 repo = GitLabRepo() 136 rubyenv_dir = pathlib.Path(__file__).parent / f"rubyEnv" 137 138 # load rev from data.json 139 data = _get_data_json() 140 rev = data['rev'] 141 142 with open(rubyenv_dir / 'Gemfile.lock', 'w') as f: 143 f.write(repo.get_file('Gemfile.lock', rev)) 144 with open(rubyenv_dir / 'Gemfile', 'w') as f: 145 original = repo.get_file('Gemfile', rev) 146 original += "\ngem 'sd_notify'\n" 147 f.write(re.sub(r".*mail-smtp_pool.*", "", original)) 148 149 subprocess.check_output(['bundle', 'lock'], cwd=rubyenv_dir) 150 subprocess.check_output(['bundix'], cwd=rubyenv_dir) 151 152 153@cli.command('update-gitaly') 154def update_gitaly(): 155 """Update gitaly""" 156 data = _get_data_json() 157 gitaly_server_version = data['passthru']['GITALY_SERVER_VERSION'] 158 repo = GitLabRepo(repo='gitaly') 159 gitaly_dir = pathlib.Path(__file__).parent / 'gitaly' 160 161 for fn in ['Gemfile.lock', 'Gemfile']: 162 with open(gitaly_dir / fn, 'w') as f: 163 f.write(repo.get_file(f"ruby/{fn}", f"v{gitaly_server_version}")) 164 165 subprocess.check_output(['bundle', 'lock'], cwd=gitaly_dir) 166 subprocess.check_output(['bundix'], cwd=gitaly_dir) 167 168 _call_nix_update('gitaly', gitaly_server_version) 169 170 171@cli.command('update-gitlab-shell') 172def update_gitlab_shell(): 173 """Update gitlab-shell""" 174 data = _get_data_json() 175 gitlab_shell_version = data['passthru']['GITLAB_SHELL_VERSION'] 176 _call_nix_update('gitlab-shell', gitlab_shell_version) 177 178 179@cli.command('update-gitlab-workhorse') 180def update_gitlab_workhorse(): 181 """Update gitlab-workhorse""" 182 data = _get_data_json() 183 gitlab_workhorse_version = data['passthru']['GITLAB_WORKHORSE_VERSION'] 184 _call_nix_update('gitlab-workhorse', gitlab_workhorse_version) 185 186 187@cli.command('update-all') 188@click.option('--rev', default='latest', help='The rev to use (vX.Y.Z-ee), or \'latest\'') 189@click.pass_context 190def update_all(ctx, rev: str): 191 """Update all gitlab components to the latest stable release""" 192 ctx.invoke(update_data, rev=rev) 193 ctx.invoke(update_rubyenv) 194 ctx.invoke(update_gitaly) 195 ctx.invoke(update_gitlab_shell) 196 ctx.invoke(update_gitlab_workhorse) 197 198 199if __name__ == '__main__': 200 cli()