def view_job(request, job_id): """ View the details of a job, along with any results. """ recipe_q = models.Recipe.objects.prefetch_related("depends_on", "auto_authorized", "viewable_by_teams") q = (models.Job.objects .select_related('recipe__repository__user__server', 'recipe__build_user__server', 'event__pull_request', 'event__base__branch__repository__user__server', 'event__head__branch__repository__user__server', 'config', 'client',) .prefetch_related(Prefetch("recipe", queryset=recipe_q), 'step_results', 'changelog')) job = get_object_or_404(q, pk=job_id) perms = Permissions.job_permissions(request.session, job) clients = None if perms['can_see_client']: clients = sorted_clients(models.Client.objects.exclude(status=models.Client.DOWN)) perms['job'] = job perms['clients'] = clients perms['update_interval'] = settings.JOB_PAGE_UPDATE_INTERVAL return render(request, 'ci/job.html', perms)
def get_job_results(request, job_id): """ Just download all the output of the job into a tarball. """ job = get_object_or_404(models.Job.objects.select_related( 'recipe', ).prefetch_related('step_results'), pk=job_id) perms = Permissions.job_permissions(request.session, job) if not perms['can_see_results']: return HttpResponseForbidden('Not allowed to see results') response = HttpResponse(content_type='application/x-gzip') base_name = 'results_{}_{}'.format(job.pk, job.recipe.name) response[ 'Content-Disposition'] = 'attachment; filename="{}.tar.gz"'.format( base_name) tar = tarfile.open(fileobj=response, mode='w:gz') for result in job.step_results.all(): info = tarfile.TarInfo( name='{}/{:02}_{}'.format(base_name, result.position, result.name)) s = BytesIO(result.plain_output().replace('\u2018', "'").replace( "\u2019", "'").encode("utf-8", "replace")) buf = s.getvalue() info.size = len(buf) info.mtime = time.time() tar.addfile(tarinfo=info, fileobj=s) tar.close() return response
def job_script(request, job_id): """ Creates a single shell script that would be similar to what the client ends up running. Used for debugging. Input: job_id: models.Job.pk Return: Http404 if the job doesn't exist or the user doesn't have permission, else HttpResponse """ job = get_object_or_404(models.Job, pk=job_id) perms = Permissions.job_permissions(request.session, job) if not perms['is_owner']: logger.warning("Tried to get job script for %s: %s but not the owner" % (job.pk, job)) raise Http404('Not the owner') script = '<pre>#!/bin/bash' script += '\n# Script for job {}'.format(job) script += '\n# Note that BUILD_ROOT and other environment variables set by the client are not set' script += '\n# It is a good idea to redirect stdin, ie "./script.sh < /dev/null"' script += '\n\n' script += '\nmodule purge' script += '\nexport BUILD_ROOT=""' script += '\nexport MOOSE_JOBS="1"' script += '\n\n' recipe = job.recipe for prestep in recipe.prestepsources.all(): script += '\n{}\n'.format(read_recipe_file(prestep.filename)) for env in recipe.environment_vars.all(): script += '\nexport {}="{}"'.format(env.name, env.value) script += '\nexport CIVET_RECIPE_NAME="{}"'.format(job.recipe.name) script += '\nexport CIVET_JOB_ID="{}"'.format(job.pk) script += '\nexport CIVET_RECIPE_ID="{}"'.format(job.recipe.pk) script += '\nexport CIVET_COMMENTS_URL="{}"'.format(job.event.comments_url) script += '\nexport CIVET_BASE_REPO="{}"'.format(job.event.base.repo()) script += '\nexport CIVET_BASE_REF="{}"'.format(job.event.base.branch.name) script += '\nexport CIVET_BASE_SHA="{}"'.format(job.event.base.sha) script += '\nexport CIVET_BASE_SSH_URL="{}"'.format(job.event.base.ssh_url) script += '\nexport CIVET_HEAD_REPO="{}"'.format(job.event.head.repo()) script += '\nexport CIVET_HEAD_REF="{}"'.format(job.event.head.branch.name) script += '\nexport CIVET_HEAD_SHA="{}"'.format(job.event.head.sha) script += '\nexport CIVET_HEAD_SSH_URL="{}"'.format(job.event.head.ssh_url) script += '\nexport CIVET_EVENT_CAUSE="{}"'.format(job.recipe.cause_str()) script += '\nexport CIVET_BUILD_CONFIG="{}"'.format(job.config.name) script += '\n\n' count = 0 step_cmds = '' for step in recipe.steps.order_by('position').all(): script += '\nfunction step_{}\n{{'.format(count) script += '\n\tlocal CIVET_STEP_NUM="{}"'.format(step.position) script += '\n\tlocal CIVET_STEP_POSITION="{}"'.format(step.position) script += '\n\tlocal CIVET_STEP_NAME="{}"'.format(step.name) script += '\n\tlocal CIVET_STEP_ABORT_ON_FAILURE="{}"'.format( step.abort_on_failure) script += '\n\tlocal CIVET_STEP_ALLOED_TO_FAIL="{}"'.format( step.allowed_to_fail) for env in step.step_environment.all(): script += '\n\tlocal {}="{}"'.format(env.name, env.value) for l in read_recipe_file(step.filename).split('\n'): script += '\n\t{}'.format(l.replace('exit 0', 'return 0')) script += '\n}\n' step_cmds += '\nstep_{}'.format(count) count += 1 script += step_cmds script += '</pre>' return HttpResponse(script)