173 lines
6 KiB
Python
173 lines
6 KiB
Python
import json
|
|
|
|
from peewee import JOIN_LEFT_OUTER
|
|
from datetime import timedelta, datetime
|
|
|
|
from data.database import (BuildTriggerService, RepositoryBuildTrigger, Repository, Namespace, User,
|
|
RepositoryBuild, BUILD_PHASE, db_for_update)
|
|
from data.model import (InvalidBuildTriggerException, InvalidRepositoryBuildException,
|
|
db_transaction, user as user_model)
|
|
|
|
|
|
PRESUMED_DEAD_BUILD_AGE = timedelta(days=15)
|
|
|
|
|
|
def update_build_trigger(trigger, config, auth_token=None):
|
|
trigger.config = json.dumps(config or {})
|
|
if auth_token is not None:
|
|
trigger.auth_token = auth_token
|
|
trigger.save()
|
|
|
|
|
|
def create_build_trigger(repo, service_name, auth_token, user, pull_robot=None, config=None):
|
|
config = config or {}
|
|
service = BuildTriggerService.get(name=service_name)
|
|
trigger = RepositoryBuildTrigger.create(repository=repo, service=service,
|
|
auth_token=auth_token,
|
|
connected_user=user,
|
|
pull_robot=pull_robot,
|
|
config=json.dumps(config))
|
|
return trigger
|
|
|
|
|
|
def get_build_trigger(trigger_uuid):
|
|
try:
|
|
return (RepositoryBuildTrigger
|
|
.select(RepositoryBuildTrigger, BuildTriggerService, Repository, Namespace)
|
|
.join(BuildTriggerService)
|
|
.switch(RepositoryBuildTrigger)
|
|
.join(Repository)
|
|
.join(Namespace, on=(Repository.namespace_user == Namespace.id))
|
|
.switch(RepositoryBuildTrigger)
|
|
.join(User)
|
|
.where(RepositoryBuildTrigger.uuid == trigger_uuid)
|
|
.get())
|
|
except RepositoryBuildTrigger.DoesNotExist:
|
|
msg = 'No build trigger with uuid: %s' % trigger_uuid
|
|
raise InvalidBuildTriggerException(msg)
|
|
|
|
|
|
def list_build_triggers(namespace_name, repository_name):
|
|
return (RepositoryBuildTrigger
|
|
.select(RepositoryBuildTrigger, BuildTriggerService, Repository)
|
|
.join(BuildTriggerService)
|
|
.switch(RepositoryBuildTrigger)
|
|
.join(Repository)
|
|
.join(Namespace, on=(Repository.namespace_user == Namespace.id))
|
|
.where(Namespace.username == namespace_name, Repository.name == repository_name))
|
|
|
|
|
|
def list_trigger_builds(namespace_name, repository_name, trigger_uuid,
|
|
limit):
|
|
return (list_repository_builds(namespace_name, repository_name, limit)
|
|
.where(RepositoryBuildTrigger.uuid == trigger_uuid))
|
|
|
|
|
|
def get_repository_for_resource(resource_key):
|
|
try:
|
|
return (Repository
|
|
.select(Repository, Namespace)
|
|
.join(Namespace, on=(Repository.namespace_user == Namespace.id))
|
|
.switch(Repository)
|
|
.join(RepositoryBuild)
|
|
.where(RepositoryBuild.resource_key == resource_key)
|
|
.get())
|
|
except Repository.DoesNotExist:
|
|
return None
|
|
|
|
|
|
def _get_build_base_query():
|
|
return (RepositoryBuild
|
|
.select(RepositoryBuild, RepositoryBuildTrigger, BuildTriggerService, Repository,
|
|
Namespace, User)
|
|
.join(Repository)
|
|
.join(Namespace, on=(Repository.namespace_user == Namespace.id))
|
|
.switch(RepositoryBuild)
|
|
.join(User, JOIN_LEFT_OUTER)
|
|
.switch(RepositoryBuild)
|
|
.join(RepositoryBuildTrigger, JOIN_LEFT_OUTER)
|
|
.join(BuildTriggerService, JOIN_LEFT_OUTER)
|
|
.order_by(RepositoryBuild.started.desc()))
|
|
|
|
|
|
def get_repository_build(build_uuid):
|
|
try:
|
|
return _get_build_base_query().where(RepositoryBuild.uuid == build_uuid).get()
|
|
|
|
except RepositoryBuild.DoesNotExist:
|
|
msg = 'Unable to locate a build by id: %s' % build_uuid
|
|
raise InvalidRepositoryBuildException(msg)
|
|
|
|
|
|
def list_repository_builds(namespace_name, repository_name, limit,
|
|
include_inactive=True, since=None):
|
|
query = (_get_build_base_query()
|
|
.where(Repository.name == repository_name, Namespace.username == namespace_name)
|
|
.limit(limit))
|
|
|
|
if since is not None:
|
|
query = query.where(RepositoryBuild.started >= since)
|
|
|
|
if not include_inactive:
|
|
query = query.where(RepositoryBuild.phase != BUILD_PHASE.ERROR,
|
|
RepositoryBuild.phase != BUILD_PHASE.COMPLETE)
|
|
|
|
return query
|
|
|
|
|
|
def get_recent_repository_build(namespace_name, repository_name):
|
|
query = list_repository_builds(namespace_name, repository_name, 1)
|
|
try:
|
|
return query.get()
|
|
except RepositoryBuild.DoesNotExist:
|
|
return None
|
|
|
|
|
|
def create_repository_build(repo, access_token, job_config_obj, dockerfile_id,
|
|
display_name, trigger=None, pull_robot_name=None):
|
|
pull_robot = None
|
|
if pull_robot_name:
|
|
pull_robot = user_model.lookup_robot(pull_robot_name)
|
|
|
|
return RepositoryBuild.create(repository=repo, access_token=access_token,
|
|
job_config=json.dumps(job_config_obj),
|
|
display_name=display_name, trigger=trigger,
|
|
resource_key=dockerfile_id,
|
|
pull_robot=pull_robot)
|
|
|
|
|
|
def get_pull_robot_name(trigger):
|
|
if not trigger.pull_robot:
|
|
return None
|
|
|
|
return trigger.pull_robot.username
|
|
|
|
|
|
def cancel_repository_build(build, work_queue):
|
|
with db_transaction():
|
|
# Reload the build for update.
|
|
try:
|
|
build = db_for_update(RepositoryBuild.select().where(RepositoryBuild.id == build.id)).get()
|
|
except RepositoryBuild.DoesNotExist:
|
|
return False
|
|
|
|
if build.phase != BUILD_PHASE.WAITING or not build.queue_id:
|
|
return False
|
|
|
|
# Try to cancel the queue item.
|
|
if not work_queue.cancel(build.queue_id):
|
|
return False
|
|
|
|
# Delete the build row.
|
|
build.delete_instance()
|
|
return True
|
|
|
|
|
|
def archivable_buildlogs_query():
|
|
presumed_dead_date = datetime.utcnow() - PRESUMED_DEAD_BUILD_AGE
|
|
return (RepositoryBuild
|
|
.select()
|
|
.where((RepositoryBuild.phase == BUILD_PHASE.COMPLETE) |
|
|
(RepositoryBuild.phase == BUILD_PHASE.ERROR) |
|
|
(RepositoryBuild.started < presumed_dead_date),
|
|
RepositoryBuild.logs_archived == False))
|