]> git.ipfire.org Git - people/jschlag/pbs.git/blame - src/manager/builds.py
Add command to restart any failed builds
[people/jschlag/pbs.git] / src / manager / builds.py
CommitLineData
83be3106
MT
1#!/usr/bin/python
2
3import datetime
4import logging
e6fa8404
MT
5import pakfire
6import pakfire.config
7import shutil
8import tempfile
9
2c909128
MT
10from .. import builds
11from .. import git
83be3106 12
2c909128 13from . import base
83be3106 14
2c909128 15from ..constants import *
e6fa8404 16
83be3106
MT
17class CheckBuildDependenciesEvent(base.Event):
18 # Process them as quickly as possible, but there may be more important events.
19 priority = 3
20
21 @property
22 def interval(self):
23 return self.pakfire.settings.get_int("dependency_checker_interval", 30)
24
25 def run(self):
26 query = self.db.query("SELECT id FROM jobs \
27 WHERE state = 'new' OR \
28 (state = 'dependency_error' AND \
9779008c 29 time_finished < NOW() - '5 minutes'::interval) \
83be3106
MT
30 ORDER BY time_finished LIMIT 50")
31
32 for row in query:
33 e = CheckBuildDependencyEvent(self.pakfire, row.id)
34 self.scheduler.add_event(e)
35
36
37class CheckBuildDependencyEvent(base.Event):
38 # Process them as quickly as possible, but there may be more important events.
39 priority = 3
40
41 def run(self, job_id):
e6fa8404
MT
42 self.run_subprocess(self._run, job_id)
43
44 @staticmethod
45 def _run(_pakfire, job_id):
83be3106 46 # Get the build job we are working on.
e6fa8404 47 job = _pakfire.jobs.get_by_id(job_id)
83be3106
MT
48 if not job:
49 logging.debug("Job %s does not exist." % job_id)
50 return
51
52 # Check if the job status has changed in the meanwhile.
53 if not job.state in ("new", "dependency_error", "failed"):
54 logging.warning("Job status has already changed: %s - %s" % (job.name, job.state))
55 return
56
57 # Resolve the dependencies.
58 job.resolvdep()
59
60
e6fa8404
MT
61class DistEvent(base.Event):
62 interval = 60
83be3106
MT
63
64 first_run = True
65
e6fa8404 66 def run(self):
83be3106
MT
67 if self.first_run:
68 self.first_run = False
69
70 self.process = self.init_repos()
71
e6fa8404
MT
72 for commit in self.pakfire.sources.get_pending_commits():
73 commit.state = "running"
83be3106 74
e6fa8404 75 logging.debug("Processing commit %s: %s" % (commit.revision, commit.subject))
83be3106 76
e6fa8404 77 # Get the repository of this commit.
78366294 78 repo = git.Repo(self.pakfire, commit.source)
83be3106 79
e6fa8404
MT
80 # Make sure, it is checked out.
81 if not repo.cloned:
82 repo.clone()
83be3106 83
e6fa8404
MT
84 # Navigate to the right revision.
85 repo.checkout(commit.revision)
83be3106 86
e6fa8404
MT
87 # Get all changed makefiles.
88 deleted_files = []
89 updated_files = []
83be3106 90
e6fa8404
MT
91 for file in repo.changed_files(commit.revision):
92 # Don't care about files that are not a makefile.
93 if not file.endswith(".%s" % MAKEFILE_EXTENSION):
94 continue
83be3106 95
e6fa8404
MT
96 if os.path.exists(file):
97 updated_files.append(file)
98 else:
99 deleted_files.append(file)
83be3106 100
e6fa8404
MT
101 e = DistFileEvent(self.pakfire, None, commit.id, updated_files, deleted_files)
102 self.scheduler.add_event(e)
83be3106
MT
103
104 def init_repos(self):
e6fa8404
MT
105 """
106 Initialize all repositories.
107 """
108 for source in self.pakfire.sources.get_all():
109 # Skip those which already have a revision.
83be3106
MT
110 if source.revision:
111 continue
112
e6fa8404 113 # Initialize the repository or and clone it if necessary.
78366294 114 repo = git.Repo(self.pakfire, source)
83be3106
MT
115 if not repo.cloned:
116 repo.clone()
117
e6fa8404 118 # Get a list of all files in the repository.
83be3106
MT
119 files = repo.get_all_files()
120
e6fa8404
MT
121 for file in [f for f in files if file.endswith(".%s" % MAKEFILE_EXTENSION)]:
122 e = DistFileEvent(self.pakfire, source.id, None, [file,], [])
123 self.scheduler.add_event(e)
83be3106 124
83be3106 125
e6fa8404
MT
126class DistFileEvent(base.Event):
127 def run(self, *args):
128 self.run_subprocess(self._run, *args)
83be3106
MT
129
130 @staticmethod
e6fa8404 131 def _run(_pakfire, source_id, commit_id, updated_files, deleted_files):
83be3106
MT
132 commit = None
133 source = None
134
135 if commit_id:
136 commit = _pakfire.sources.get_commit_by_id(commit_id)
137 assert commit
138
139 source = commit.source
140
141 if source_id and not source:
142 source = _pakfire.sources.get_by_id(source_id)
143
144 assert source
145
146 if updated_files:
147 # Create a temporary directory where to put all the files
148 # that are generated here.
149 pkg_dir = tempfile.mkdtemp()
150
151 try:
152 config = pakfire.config.Config(["general.conf",])
153 config.parse(source.distro.get_config())
154
e6fa8404 155 p = pakfire.PakfireServer(config=config)
83be3106
MT
156
157 pkgs = []
158 for file in updated_files:
159 try:
160 pkg_file = p.dist(file, pkg_dir)
161 pkgs.append(pkg_file)
162 except:
163 raise
164
165 # Import all packages in one swoop.
166 for pkg in pkgs:
167 # Import the package file and create a build out of it.
2c909128 168 builds.import_from_package(_pakfire, pkg,
83be3106
MT
169 distro=source.distro, commit=commit, type="release")
170
171 except:
172 if commit:
173 commit.state = "failed"
174
175 raise
176
177 finally:
178 if os.path.exists(pkg_dir):
179 shutil.rmtree(pkg_dir)
180
e6fa8404
MT
181 for file in deleted_files:
182 # Determine the name of the package.
183 name = os.path.basename(file)
184 name = name[:len(MAKEFILE_EXTENSION) + 1]
83be3106 185
e6fa8404 186 source.distro.delete_package(name)
83be3106 187
e6fa8404
MT
188 if commit:
189 commit.state = "finished"