/** * Schedules a build * * @see App\CoreBundle\EventListener\BuildBranchRelationSubscriber for automatic creation of non-existing branches */ public function schedule(Project $project, $ref, $hash, PayloadInterface $payload = null, $options = []) { $logger = $this->logger; $logger->info('scheduling build', ['project' => $project->getId(), 'ref' => $ref, 'hash' => $hash]); $em = $this->doctrine->getManager(); // @todo I guess this should be in a build.scheduled event listener $alreadyRunningBuilds = $em->getRepository('Model:Build')->findPendingByRef($project, $ref); foreach ($alreadyRunningBuilds as $build) { // @todo instead of retrieving then updating builds to be canceled, directly issue an UPDATE // it should avoid most race conditions if ($build->isScheduled()) { $logger->info('canceling same ref build', ['ref' => $ref, 'canceled_build' => $build->getId()]); $build->setStatus(Build::STATUS_CANCELED); $em->persist($build); $em->flush(); } else { $logger->info('killing same ref build', ['ref' => $ref, 'canceled_build' => $build->getId()]); $scheduler->kill($build); } } $build = new Build(); $build->setProject($project); $build->setStatus(Build::STATUS_SCHEDULED); $build->setRef($ref); $build->setHash($hash); $build->setCommitUrl(sprintf('https://github.com/%s/commit/%s', $project->getFullName(), $hash)); if (null !== $payload) { $build->setIsPullRequest($payload->isPullRequest()); $build->setRawPayload($payload->getRawContent()); } else { $build->setIsPullRequest(false); } if (isset($options['force_local_build_yml']) && $options['force_local_build_yml']) { $build->setForceLocalBuildYml(true); } $builderHost = null; $logger->info('electing builder', ['builder_host_allow' => $this->getOption('builder_host_allow')]); if (count($builderHostAllow = $this->getOption('builder_host_allow')) > 0) { $builderHost = $builderHostAllow[array_rand($builderHostAllow)]; } $build->setBuilderHost($builderHost); /** * @todo move this outside, it belongs in a controller * this will allow to remove the $options argument */ $em->persist($build); $em->flush(); $this->logger->info('sending build order', ['build' => $build->getId(), 'builder_host' => $builderHost]); $this->buildProducer->publish(json_encode(['build_id' => $build->getId()]), $build->getRoutingKey()); $message = $this->messageFactory->createBuildScheduled($build); $this->websocketProducer->publish($message); return $build; }
/** * @todo the policy check and Payload->isBuildable() could be implemented * as a voting system */ private function scheduleBranchPush(PayloadInterface $payload, Project $project) { $logger = $this->get('logger'); $em = $this->get('doctrine')->getManager(); if (!$payload->hasRef()) { return new JsonResponse(json_encode(null), 400); } $ref = $payload->getRef(); $hash = $payload->getHash(); # then, check if ref is configured to be automatically built $doBuild = false; switch ($project->getSettings()->getPolicy()) { case ProjectSettings::POLICY_ALL: $doBuild = true; break; case ProjectSettings::POLICY_NONE: case ProjectSettings::POLICY_PR: $doBuild = false; break; case ProjectSettings::POLICY_PATTERNS: $patterns = explode(PHP_EOL, $project->getSettings()->getBranchPatterns()); foreach ($patterns as $pattern) { $regex = strtr($pattern, ['*' => '.*', '?' => '.']); if (preg_match('/' . $regex . '/i', $ref)) { $doBuild = true; } } break; default: $logger->error('could not find a build policy', ['project' => $project->getId(), 'ref' => $ref]); return new JsonResponse(['class' => 'danger', 'message' => 'Could not find a build policy'], 400); } if (!$doBuild) { $logger->info('build declined by project policy', ['project' => $project->getId(), 'ref' => $ref]); return new JsonResponse(['class' => 'info', 'message' => 'Build declined by project policy (' . $project->getSettings()->getPolicy() . ')'], 200); } /** @todo this should be in the PayloadInterface as ->isDelete() or something */ if ($hash === '0000000000000000000000000000000000000000') { $branch = $em->getRepository('Model:Branch')->findOneByProjectAndName($project, $ref); $branch->setDeleted(true); $em->persist($branch); $em->flush(); return new JsonResponse(json_encode(null), 200); } $sameHashBuilds = $em->getRepository('Model:Build')->findByHash($hash); if (count($sameHashBuilds) > 0) { $logger->warn('found builds with same hash', ['count' => count($sameHashBuilds)]); $allowRebuild = array_reduce($sameHashBuilds, function ($result, $b) { return $result || $b->getAllowRebuild(); }, false); } if (isset($allowRebuild) && !$allowRebuild) { $logger->warn('build already scheduled for hash', ['hash' => $hash]); return new JsonResponse(['class' => 'danger', 'message' => 'Build already scheduled for hash'], 400); } else { $logger->info('scheduling build for hash', ['hash' => $hash]); } return [$ref, $hash]; }
public function findOneByPayload(PayloadInterface $payload) { return $this->createQueryBuilder('p')->where('p.providerName = :providerName and p.fullName = :fullName')->setParameters(['providerName' => $payload->getProviderName(), 'fullName' => $payload->getRepositoryFullName()])->getQuery()->getOneOrNullResult(); }