diff options
author | Lars Wirzenius <liw@liw.fi> | 2015-05-10 10:25:11 +0300 |
---|---|---|
committer | Lars Wirzenius <liw@liw.fi> | 2015-05-10 11:32:56 +0300 |
commit | 813e198fcd83aa2ae4fea5a66ef592f42aa6c293 (patch) | |
tree | 0c4bd1412d7b8044c0ddfbc3450ba0ff133346f9 /ick | |
parent | 3fdbb1e7351839a3e08d9783620fba6d4ad8e9a6 (diff) | |
download | ick-813e198fcd83aa2ae4fea5a66ef592f42aa6c293.tar.gz |
Add state and don't build unless git's changed
Diffstat (limited to 'ick')
-rwxr-xr-x | ick | 103 |
1 files changed, 86 insertions, 17 deletions
@@ -18,9 +18,8 @@ import logging -import shutil +import os import subprocess -import tempfile import cliapp import yaml @@ -53,10 +52,11 @@ class Ick(cliapp.Application): return yaml.safe_load(f) def build_projects(self, ick): + statedir = ick['state'] targets = self.get_targets(ick) projects = self.get_projects(ick) for project_name, project in projects.items(): - self.build_project(project_name, project, targets) + self.build_project(statedir, project_name, project, targets) def get_targets(self, ick): return self.pick_from_dict( @@ -74,24 +74,76 @@ class Ick(cliapp.Application): ick.get('projects', {}), self.settings['project']) - def build_project(self, project_name, project, targets): + def build_project(self, statedir, project_name, project, targets): with self.logger: self.logger.log( 'Building project {project_name}', project_name=project_name) - git_dir = self.clone_git_repository_locally( - project['git'], project['branch']) - try: - for target_name, target in targets.items(): - self.build_on_target( - project_name, project, target_name, target, git_dir) - except Exception: - shutil.rmtree(git_dir) - raise - def clone_git_repository_locally(self, url, branch): - git_dir = tempfile.mkdtemp() - cliapp.runcmd(['git', 'clone', '--verbose', '--branch', branch, url, git_dir]) - return git_dir + git_dir = self.get_git_dir(statedir, project_name) + self.clone_or_update_git_repository_locally( + git_dir, project['git'], project['branch']) + meta = BuildMetadata() + meta.commit = self.get_head_commit(git_dir) + + if not self.needs_to_be_built(statedir, project_name, meta.commit): + with self.logger: + self.logger.log( + 'No need to build {project_name}', + project_name=project_name) + return + + build_dir = self.get_next_build_dir(statedir, project_name) + for target_name, target in targets.items(): + self.build_on_target( + project_name, project, target_name, target, git_dir) + self.save_build_metadata(build_dir, meta) + + def needs_to_be_built(self, statedir, project_name, current_commit): + builds_dir = os.path.join(statedir, project_name, 'builds') + if os.path.exists(builds_dir): + basenames = os.listdir(builds_dir) + if basenames: + numbers = [int(x) for x in basenames] + latest = sorted(numbers)[-1] + latest_dir = os.path.join(builds_dir, str(latest)) + latest_meta = self.load_build_metadata(latest_dir) + return latest_meta.commit != current_commit + return True + + def load_build_metadata(self, build_dir): + filename = os.path.join(build_dir, 'meta.yaml') + with open(filename) as f: + obj = yaml.safe_load(f) + meta = BuildMetadata() + meta.commit = obj['commit'] + return meta + + def get_next_build_dir(self, statedir, project_name): + builds_dir = os.path.join(statedir, project_name, 'builds') + if os.path.exists(builds_dir): + basenames = os.listdir(builds_dir) + else: + basenames = [] + if basenames: + numbers = [int(x) for x in basenames] + next = sorted(numbers)[-1] + 1 + else: + next = 1 + build_dir = os.path.join(builds_dir, str(next)) + os.makedirs(build_dir) + return build_dir + + def get_git_dir(self, statedir, project_name): + return os.path.join(statedir, project_name, 'git') + + def clone_or_update_git_repository_locally(self, git_dir, url, branch): + cliapp.runcmd(['rm', '-rf', git_dir]) + cliapp.runcmd( + ['git', 'clone', '--verbose', '--branch', branch, url, git_dir]) + + def get_head_commit(self, git_dir): + output = cliapp.runcmd(['git', 'rev-parse', 'HEAD'], cwd=git_dir) + return output.strip() def build_on_target(self, project_name, project, target_name, target, git_dir): @@ -136,6 +188,10 @@ class Ick(cliapp.Application): lineno=lineno+1, line=line) + def save_build_metadata(self, build_dir, meta): + filename = os.path.join(build_dir, 'meta.yaml') + meta.save(filename) + class Logger(object): @@ -157,5 +213,18 @@ class Logger(object): self._output.write(formatted + '\n') +class BuildMetadata(object): + + def __init__(self): + self.commit = None + + def save(self, filename): + obj = { + "commit": self.commit, + } + with open(filename, 'w') as f: + yaml.safe_dump(obj, stream=f, default_flow_style=False, indent=4) + + if __name__ == '__main__': Ick().run() |