Example #1
0
 /**
  * @todo make a real query
  */
 public function findOneByProjectAndName(Project $project, $ref)
 {
     $query = $this->createQueryBuilder('b')->select()->where('b.project = ?1')->andWhere('b.name = ?2')->setParameters([1 => $project->getId(), 2 => $ref])->getQuery();
     try {
         return $query->getSingleResult();
     } catch (NoResultException $e) {
         return null;
     }
 }
Example #2
0
 /**
  * @param Project $project
  *
  * @return Doctrine\Common\Collections\Collection
  */
 public function findLastByRefs(Project $project)
 {
     $query = 'SELECT b.* FROM (SELECT * FROM build WHERE build.project_id = ? ORDER BY created_at DESC) b GROUP BY b.ref';
     $rsm = new ResultSetMappingBuilder($this->getEntityManager());
     $rsm->addRootEntityFromClassMetadata('Model:Build', 'b');
     $query = $this->getEntityManager()->createNativeQuery($query, $rsm);
     $query->setParameter(1, $project->getId());
     return $query->execute();
 }
Example #3
0
 /**
  * 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;
 }
Example #4
0
 /**
  * @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];
 }
Example #5
0
 private function getAccessForm(Project $project)
 {
     return $this->createForm('project_access', new ProjectAccess(), ['action' => $this->generateUrl('app_core_project_access_create', ['id' => $project->getId()]), 'method' => 'POST']);
 }
Example #6
0
 protected function setCurrentProject(Project $project)
 {
     $this->get('request')->attributes->set('current_project_id', (int) $project->getId());
 }