diff --git a/app/controllers/api/functions.php b/app/controllers/api/functions.php index 042a37989e..0bcd3d00f9 100644 --- a/app/controllers/api/functions.php +++ b/app/controllers/api/functions.php @@ -1311,7 +1311,7 @@ App::post('/v1/functions/:functionId/deployments/:deploymentId/builds/:buildId') throw new Exception(Exception::BUILD_NOT_FOUND); } - // TODO: Somehow set commit SHA for git deployments, and file path for manual. Redeploy should use exact same source code + // TODO: Somehow set commit SHA & ownerName & repoName for git deployments, and file path for manual. Redeploy should use exact same source code $installation = $dbForConsole->getDocument('vcsInstallations', $deployment->getAttribute('vcsInstallationId', '')); diff --git a/app/controllers/api/vcs.php b/app/controllers/api/vcs.php index 3b3674cf5d..97bc93539a 100644 --- a/app/controllers/api/vcs.php +++ b/app/controllers/api/vcs.php @@ -508,9 +508,9 @@ $createGitDeployments = function (GitHub $github, string $installationId, array $latestCommentId = \strval($github->createComment($owner, $repositoryName, $pullRequest, $comment->generateComment())); } elseif (!empty($branchName)) { $gitPullRequest = $github->getBranchPullRequest($owner, $repositoryName, $branchName); - $pullRequestId = \strval($gitPullRequest['number'] ?? ''); - if (!empty($pullRequestId)) { - $latestCommentId = \strval($github->createComment($owner, $repositoryName, $pullRequestId, $comment->generateComment())); + $pullRequest = \strval($gitPullRequest['number'] ?? ''); + if (!empty($pullRequest)) { + $latestCommentId = \strval($github->createComment($owner, $repositoryName, $pullRequest, $comment->generateComment())); } } @@ -596,10 +596,19 @@ $createGitDeployments = function (GitHub $github, string $installationId, array $github->updateCommitStatus($repositoryName, $SHA, $owner, 'pending', $message, $targetUrl, $name); } + $contribution = new Document([]); + if($external) { + $pullRequestResponse = $github->getPullRequest($owner, $repositoryName, $pullRequest); + + $contribution->setAttribute('ownerName', $pullRequestResponse['head']['repo']['owner']['login']); + $contribution->setAttribute('repositoryName', $pullRequestResponse['head']['repo']['name']); + } + $buildEvent = new Build(); $buildEvent ->setType(BUILD_TYPE_DEPLOYMENT) ->setResource($function) + ->setVcsContribution($contribution) ->setDeployment($deployment) ->setTargetUrl($targetUrl) ->setSHA($SHA) @@ -642,7 +651,6 @@ App::post('/v1/vcs/github/incomingwebhook') $repositoryId = $parsedPayload["repositoryId"]; $installationId = $parsedPayload["installationId"]; $SHA = $parsedPayload["SHA"]; - $owner = $parsedPayload["owner"]; $github->initialiseVariables($installationId, $privateKey, $githubAppId); @@ -685,6 +693,11 @@ App::post('/v1/vcs/github/incomingwebhook') $SHA = $parsedPayload["SHA"]; $external = $parsedPayload["external"]; + // Ignore sync for non-external. We handle it in push webhook + if(!$external && $parsedPayload["action"] == "synchronize") { + return $response->json($parsedPayload); + } + $github->initialiseVariables($installationId, $privateKey, $githubAppId); $vcsRepos = $dbForConsole->find('vcsRepos', [ diff --git a/app/workers/builds.php b/app/workers/builds.php index 5e8acfc373..0d2395c0ee 100644 --- a/app/workers/builds.php +++ b/app/workers/builds.php @@ -51,13 +51,14 @@ class BuildsV1 extends Worker $template = new Document($this->args['template'] ?? []); $SHA = $this->args['SHA'] ?? ''; $targetUrl = $this->args['targetUrl'] ?? ''; + $vcsContribution = new Document($this->args['vcsContribution'] ?? []); switch ($type) { case BUILD_TYPE_DEPLOYMENT: case BUILD_TYPE_RETRY: Console::info('Creating build for deployment: ' . $deployment->getId()); $github = new GitHub($this->getCache()); - $this->buildDeployment($github, $project, $resource, $deployment, $template, $SHA, $targetUrl); + $this->buildDeployment($github, $project, $resource, $deployment, $template, $SHA, $targetUrl, $vcsContribution); break; default: @@ -66,7 +67,7 @@ class BuildsV1 extends Worker } } - protected function buildDeployment(GitHub $github, Document $project, Document $function, Document $deployment, Document $template, string $SHA = '', string $targetUrl = '') + protected function buildDeployment(GitHub $github, Document $project, Document $function, Document $deployment, Document $template, string $SHA = '', string $targetUrl = '', Document $vcsContribution = null) { global $register; @@ -165,10 +166,15 @@ class BuildsV1 extends Worker $rootDirectory = \ltrim($rootDirectory, '/'); $github->initialiseVariables($installationId, $privateKey, $githubAppId); + $owner = $github->getOwnerName($installationId); $repositoryName = $github->getRepositoryName($repositoryId); + + $cloneOwner = !empty($vcsContribution) ? $vcsContribution->getAttribute('ownerName', $owner) : $owner; + $cloneRepository = !empty($vcsContribution) ? $vcsContribution->getAttribute('repositoryName', $repositoryName) : $repositoryName; + $branchName = $deployment->getAttribute('vcsBranch'); - $gitCloneCommand = $github->generateGitCloneCommand($owner, $repositoryName, $branchName, $tmpDirectory, $rootDirectory); + $gitCloneCommand = $github->generateGitCloneCommand($cloneOwner, $cloneRepository, $branchName, $tmpDirectory, $rootDirectory); $stdout = ''; $stderr = ''; Console::execute('mkdir -p /tmp/builds/' . $buildId, '', $stdout, $stderr); @@ -522,7 +528,6 @@ class BuildsV1 extends Worker $github->updateCommitStatus($repositoryName, $SHA, $owner, $state, $message, $targetUrl, $name); } - // TODO: Fix race condition if (!empty($commentId)) { $retries = 0; @@ -543,12 +548,23 @@ class BuildsV1 extends Worker \sleep(1); } - $comment = new Comment(); - $comment->parseComment($github->getComment($owner, $repositoryName, $commentId)); - $comment->addBuild($project, $function, $status, $deployment->getId()); - $github->updateComment($owner, $repositoryName, $commentId, $comment->generateComment()); + // Wrap in try/catch to ensure lock file gets deleted + $error = null; + try { + $comment = new Comment(); + $comment->parseComment($github->getComment($owner, $repositoryName, $commentId)); + $comment->addBuild($project, $function, $status, $deployment->getId()); + $github->updateComment($owner, $repositoryName, $commentId, $comment->generateComment()); + } catch (\Exception $e) { + $error = $e; + } finally { - $dbForConsole->deleteDocument('vcsCommentLocks', $commentId); + $dbForConsole->deleteDocument('vcsCommentLocks', $commentId); + } + + if (!empty($error)) { + throw $error; + } } } diff --git a/composer.lock b/composer.lock index 87779ace5b..95c279cfc3 100644 --- a/composer.lock +++ b/composer.lock @@ -2705,7 +2705,7 @@ "source": { "type": "git", "url": "https://github.com/utopia-php/vcs.git", - "reference": "80d1fa3022c20c6b391473c22265760a8551c5ed" + "reference": "580474fcbc5a88a908a1df3e124e47ebad2c014f" }, "require": { "adhocore/jwt": "^1.1", @@ -2750,7 +2750,7 @@ "utopia", "vcs" ], - "time": "2023-06-28T08:07:04+00:00" + "time": "2023-06-28T10:54:07+00:00" }, { "name": "utopia-php/websocket", diff --git a/src/Appwrite/Event/Build.php b/src/Appwrite/Event/Build.php index e868c9e9e2..261106f9ac 100644 --- a/src/Appwrite/Event/Build.php +++ b/src/Appwrite/Event/Build.php @@ -13,6 +13,7 @@ class Build extends Event protected ?Document $template = null; protected string $SHA = ''; protected string $targetUrl = ''; + protected ?Document $vcsContribution = null; public function __construct() { @@ -71,6 +72,19 @@ class Build extends Event return $this; } + /** + * Sets custom owner and repository for VCS clone command during build + * + * @param Document $owner + * @return self + */ + public function setVcsContribution(Document $vcsContribution): self + { + $this->vcsContribution = $vcsContribution; + + return $this; + } + /** * Returns set resource document for the build event. * @@ -142,7 +156,8 @@ class Build extends Event 'type' => $this->type, 'template' => $this->template, 'SHA' => $this->SHA, - 'targetUrl' => $this->targetUrl + 'targetUrl' => $this->targetUrl, + 'vcsContribution' => $this->vcsContribution ]); } }