2023-05-22 10:58:13 +00:00
< ? php
use Appwrite\Event\Build ;
use Appwrite\Extend\Exception ;
2025-01-17 04:31:39 +00:00
use Appwrite\SDK\AuthType ;
use Appwrite\SDK\Method ;
use Appwrite\SDK\Response as SDKResponse ;
2024-03-06 17:34:21 +00:00
use Appwrite\Utopia\Request ;
use Appwrite\Utopia\Response ;
2023-05-28 11:39:48 +00:00
use Appwrite\Vcs\Comment ;
2026-02-10 05:04:24 +00:00
use Utopia\Console ;
2024-03-06 17:34:21 +00:00
use Utopia\Database\Database ;
use Utopia\Database\Document ;
2025-02-24 15:22:23 +00:00
use Utopia\Database\Exception\Duplicate ;
2023-08-06 08:51:53 +00:00
use Utopia\Database\Helpers\ID ;
use Utopia\Database\Helpers\Permission ;
use Utopia\Database\Helpers\Role ;
2023-05-22 10:58:13 +00:00
use Utopia\Database\Query ;
use Utopia\Database\Validator\Authorization ;
2026-02-10 05:04:24 +00:00
use Utopia\Http\Http ;
2024-04-01 11:08:46 +00:00
use Utopia\System\System ;
2024-10-08 07:54:40 +00:00
use Utopia\Validator\Text ;
2024-03-06 17:34:21 +00:00
use Utopia\VCS\Adapter\Git\GitHub ;
2023-10-13 13:20:58 +00:00
use Utopia\VCS\Exception\RepositoryNotFound ;
2023-05-22 10:58:13 +00:00
2026-01-14 15:08:00 +00:00
$createGitDeployments = function ( GitHub $github , string $providerInstallationId , array $repositories , string $providerBranch , string $providerBranchUrl , string $providerRepositoryName , string $providerRepositoryUrl , string $providerRepositoryOwner , string $providerCommitHash , string $providerCommitAuthor , string $providerCommitAuthorUrl , string $providerCommitMessage , string $providerCommitUrl , string $providerPullRequestId , bool $external , Database $dbForPlatform , Authorization $authorization , Build $queueForBuilds , callable $getProjectDB , Request $request , array $platform ) {
2024-10-08 07:54:40 +00:00
$errors = [];
2024-10-25 12:41:14 +00:00
foreach ( $repositories as $repository ) {
2024-03-10 20:43:22 +00:00
try {
2024-10-25 12:41:14 +00:00
$resourceType = $repository -> getAttribute ( 'resourceType' );
2023-07-28 08:27:16 +00:00
2024-10-25 12:41:14 +00:00
if ( $resourceType !== " function " && $resourceType !== " site " ) {
2024-03-10 20:53:57 +00:00
continue ;
}
2023-07-28 08:27:16 +00:00
2024-10-25 12:41:14 +00:00
$projectId = $repository -> getAttribute ( 'projectId' );
2026-01-14 15:08:00 +00:00
$project = $authorization -> skip ( fn () => $dbForPlatform -> getDocument ( 'projects' , $projectId ));
2024-03-10 20:53:57 +00:00
$dbForProject = $getProjectDB ( $project );
2024-10-25 12:41:14 +00:00
$resourceCollection = $resourceType === " function " ? 'functions' : 'sites' ;
$resourceId = $repository -> getAttribute ( 'resourceId' );
2026-01-14 15:08:00 +00:00
$resource = $authorization -> skip ( fn () => $dbForProject -> getDocument ( $resourceCollection , $resourceId ));
2025-05-27 01:36:23 +00:00
$resourceInternalId = $resource -> getSequence ();
2024-03-10 20:53:57 +00:00
$deploymentId = ID :: unique ();
2024-10-25 12:41:14 +00:00
$repositoryId = $repository -> getId ();
2025-05-27 01:36:23 +00:00
$repositoryInternalId = $repository -> getSequence ();
2024-10-25 12:41:14 +00:00
$providerRepositoryId = $repository -> getAttribute ( 'providerRepositoryId' );
$installationId = $repository -> getAttribute ( 'installationId' );
$installationInternalId = $repository -> getAttribute ( 'installationInternalId' );
$productionBranch = $resource -> getAttribute ( 'providerBranch' );
2024-03-10 20:53:57 +00:00
$activate = false ;
if ( $providerBranch == $productionBranch && $external === false ) {
$activate = true ;
}
2023-08-09 09:52:34 +00:00
2024-03-10 20:53:57 +00:00
$owner = $github -> getOwnerName ( $providerInstallationId ) ? ? '' ;
try {
$repositoryName = $github -> getRepositoryName ( $providerRepositoryId ) ? ? '' ;
if ( empty ( $repositoryName )) {
2024-03-10 20:43:22 +00:00
throw new Exception ( Exception :: PROVIDER_REPOSITORY_NOT_FOUND );
}
2024-03-10 20:53:57 +00:00
} catch ( RepositoryNotFound $e ) {
throw new Exception ( Exception :: PROVIDER_REPOSITORY_NOT_FOUND );
}
2023-08-09 09:52:34 +00:00
2024-03-10 20:53:57 +00:00
if ( empty ( $repositoryName )) {
throw new Exception ( Exception :: PROVIDER_REPOSITORY_NOT_FOUND );
}
$isAuthorized = ! $external ;
if ( ! $isAuthorized && ! empty ( $providerPullRequestId )) {
2024-10-25 12:41:14 +00:00
if ( \in_array ( $providerPullRequestId , $repository -> getAttribute ( 'providerPullRequestIds' , []))) {
2024-03-10 20:53:57 +00:00
$isAuthorized = true ;
2024-03-10 20:43:22 +00:00
}
2024-03-10 20:53:57 +00:00
}
$commentStatus = $isAuthorized ? 'waiting' : 'failed' ;
2025-06-18 05:36:35 +00:00
$protocol = System :: getEnv ( '_APP_OPTIONS_FORCE_HTTPS' ) === 'disabled' ? 'http' : 'https' ;
2025-12-11 18:36:11 +00:00
$hostname = $platform [ 'consoleHostname' ] ? ? '' ;
2023-08-19 12:51:27 +00:00
2025-06-13 10:20:53 +00:00
$authorizeUrl = $protocol . '://' . $hostname . " /console/git/authorize-contributor?projectId= { $projectId } &installationId= { $installationId } &repositoryId= { $repositoryId } &providerPullRequestId= { $providerPullRequestId } " ;
2023-07-28 08:27:16 +00:00
2024-03-10 20:53:57 +00:00
$action = $isAuthorized ? [ 'type' => 'logs' ] : [ 'type' => 'authorize' , 'url' => $authorizeUrl ];
$latestCommentId = '' ;
2024-10-25 12:41:14 +00:00
if ( ! empty ( $providerPullRequestId ) && $resource -> getAttribute ( 'providerSilentMode' , false ) === false ) {
2026-01-14 15:08:00 +00:00
$latestComment = $authorization -> skip ( fn () => $dbForPlatform -> findOne ( 'vcsComments' , [
2024-03-10 20:53:57 +00:00
Query :: equal ( 'providerRepositoryId' , [ $providerRepositoryId ]),
Query :: equal ( 'providerPullRequestId' , [ $providerPullRequestId ]),
Query :: orderDesc ( '$createdAt' ),
]));
2024-10-31 08:13:23 +00:00
if ( ! $latestComment -> isEmpty ()) {
2024-03-10 20:53:57 +00:00
$latestCommentId = $latestComment -> getAttribute ( 'providerCommentId' , '' );
2024-10-28 14:20:36 +00:00
2025-09-03 11:27:15 +00:00
$retries = 0 ;
2025-09-04 06:20:12 +00:00
$lockAcquired = false ;
2025-09-03 11:27:15 +00:00
2025-09-04 06:20:12 +00:00
while ( $retries < 9 ) {
2025-09-03 11:27:15 +00:00
$retries ++ ;
try {
$dbForPlatform -> createDocument ( 'vcsCommentLocks' , new Document ([
'$id' => $latestCommentId
]));
2025-09-04 06:20:12 +00:00
$lockAcquired = true ;
2025-09-03 11:27:15 +00:00
break ;
} catch ( \Throwable $err ) {
if ( $retries >= 9 ) {
2025-09-03 13:15:43 +00:00
Console :: warning ( " Error creating vcs comment lock for " . $latestCommentId . " : " . $err -> getMessage ());
2025-09-03 11:27:15 +00:00
}
\sleep ( 1 );
}
}
2025-09-04 06:20:12 +00:00
if ( $lockAcquired ) {
// Wrap in try/finally to ensure lock file gets deleted
try {
2025-12-07 20:29:45 +00:00
$comment = new Comment ( $platform );
2025-09-04 06:20:12 +00:00
$comment -> parseComment ( $github -> getComment ( $owner , $repositoryName , $latestCommentId ));
$comment -> addBuild ( $project , $resource , $resourceType , $commentStatus , $deploymentId , $action , '' );
2024-03-10 20:53:57 +00:00
2025-09-04 06:20:12 +00:00
$latestCommentId = \strval ( $github -> updateComment ( $owner , $repositoryName , $latestCommentId , $comment -> generateComment ()));
} finally {
2026-01-14 15:08:00 +00:00
$authorization -> skip ( fn () => $dbForPlatform -> deleteDocument ( 'vcsCommentLocks' , $latestCommentId ));
2025-09-04 06:20:12 +00:00
}
2025-09-03 11:27:15 +00:00
}
2024-03-10 20:53:57 +00:00
} else {
2025-12-07 20:29:45 +00:00
$comment = new Comment ( $platform );
2025-03-31 16:51:33 +00:00
$comment -> addBuild ( $project , $resource , $resourceType , $commentStatus , $deploymentId , $action , '' );
2024-03-10 20:53:57 +00:00
$latestCommentId = \strval ( $github -> createComment ( $owner , $repositoryName , $providerPullRequestId , $comment -> generateComment ()));
if ( ! empty ( $latestCommentId )) {
$teamId = $project -> getAttribute ( 'teamId' , '' );
2026-01-14 15:08:00 +00:00
$latestComment = $authorization -> skip ( fn () => $dbForPlatform -> createDocument ( 'vcsComments' , new Document ([
2024-03-10 20:53:57 +00:00
'$id' => ID :: unique (),
'$permissions' => [
Permission :: read ( Role :: team ( ID :: custom ( $teamId ))),
Permission :: update ( Role :: team ( ID :: custom ( $teamId ), 'owner' )),
Permission :: update ( Role :: team ( ID :: custom ( $teamId ), 'developer' )),
Permission :: delete ( Role :: team ( ID :: custom ( $teamId ), 'owner' )),
Permission :: delete ( Role :: team ( ID :: custom ( $teamId ), 'developer' )),
],
'installationInternalId' => $installationInternalId ,
'installationId' => $installationId ,
2025-05-26 05:42:11 +00:00
'projectInternalId' => $project -> getSequence (),
2024-03-10 20:53:57 +00:00
'projectId' => $project -> getId (),
'providerRepositoryId' => $providerRepositoryId ,
'providerBranch' => $providerBranch ,
'providerPullRequestId' => $providerPullRequestId ,
'providerCommentId' => $latestCommentId
])));
2023-07-28 08:27:16 +00:00
}
}
2024-03-10 20:53:57 +00:00
} elseif ( ! empty ( $providerBranch )) {
2026-01-14 15:08:00 +00:00
$latestComments = $authorization -> skip ( fn () => $dbForPlatform -> find ( 'vcsComments' , [
2024-03-10 20:53:57 +00:00
Query :: equal ( 'providerRepositoryId' , [ $providerRepositoryId ]),
Query :: equal ( 'providerBranch' , [ $providerBranch ]),
Query :: orderDesc ( '$createdAt' ),
]));
2023-07-28 08:27:16 +00:00
2024-03-10 20:53:57 +00:00
foreach ( $latestComments as $comment ) {
$latestCommentId = $comment -> getAttribute ( 'providerCommentId' , '' );
2025-09-03 11:27:15 +00:00
$retries = 0 ;
2025-09-04 06:20:12 +00:00
$lockAcquired = false ;
2025-09-03 11:27:15 +00:00
2025-09-04 06:20:12 +00:00
while ( $retries < 9 ) {
2025-09-03 11:27:15 +00:00
$retries ++ ;
try {
$dbForPlatform -> createDocument ( 'vcsCommentLocks' , new Document ([
'$id' => $latestCommentId
]));
2025-09-04 06:20:12 +00:00
$lockAcquired = true ;
2025-09-03 11:27:15 +00:00
break ;
} catch ( \Throwable $err ) {
if ( $retries >= 9 ) {
2025-09-03 13:15:43 +00:00
Console :: warning ( " Error creating vcs comment lock for " . $latestCommentId . " : " . $err -> getMessage ());
2025-09-03 11:27:15 +00:00
}
\sleep ( 1 );
}
}
2025-09-04 06:20:12 +00:00
if ( $lockAcquired ) {
// Wrap in try/finally to ensure lock file gets deleted
try {
2025-12-07 20:29:45 +00:00
$comment = new Comment ( $platform );
2025-09-04 06:20:12 +00:00
$comment -> parseComment ( $github -> getComment ( $owner , $repositoryName , $latestCommentId ));
$comment -> addBuild ( $project , $resource , $resourceType , $commentStatus , $deploymentId , $action , '' );
2025-09-03 11:27:15 +00:00
2025-09-04 06:20:12 +00:00
$latestCommentId = \strval ( $github -> updateComment ( $owner , $repositoryName , $latestCommentId , $comment -> generateComment ()));
} finally {
2026-01-14 15:08:00 +00:00
$authorization -> skip ( fn () => $dbForPlatform -> deleteDocument ( 'vcsCommentLocks' , $latestCommentId ));
2025-09-04 06:20:12 +00:00
}
2025-09-03 11:27:15 +00:00
}
2023-08-19 12:51:27 +00:00
}
2024-03-10 20:53:57 +00:00
}
2023-07-28 08:27:16 +00:00
2024-03-10 20:53:57 +00:00
if ( ! $isAuthorized ) {
2024-10-25 12:41:14 +00:00
$resourceName = $resource -> getAttribute ( 'name' );
2024-03-10 20:53:57 +00:00
$projectName = $project -> getAttribute ( 'name' );
2024-10-25 12:41:14 +00:00
$name = " { $resourceName } ( { $projectName } ) " ;
2024-03-10 20:53:57 +00:00
$message = 'Authorization required for external contributor.' ;
2024-10-25 12:41:14 +00:00
$providerRepositoryId = $repository -> getAttribute ( 'providerRepositoryId' );
2024-03-10 20:53:57 +00:00
try {
$repositoryName = $github -> getRepositoryName ( $providerRepositoryId ) ? ? '' ;
if ( empty ( $repositoryName )) {
2023-10-27 14:08:33 +00:00
throw new Exception ( Exception :: PROVIDER_REPOSITORY_NOT_FOUND );
}
2024-03-10 20:53:57 +00:00
} catch ( RepositoryNotFound $e ) {
throw new Exception ( Exception :: PROVIDER_REPOSITORY_NOT_FOUND );
2023-10-27 14:08:33 +00:00
}
2024-03-10 20:53:57 +00:00
$owner = $github -> getOwnerName ( $providerInstallationId );
$github -> updateCommitStatus ( $repositoryName , $providerCommitHash , $owner , 'failure' , $message , $authorizeUrl , $name );
continue ;
}
2023-07-28 08:27:16 +00:00
2024-03-10 20:53:57 +00:00
if ( $external ) {
$pullRequestResponse = $github -> getPullRequest ( $owner , $repositoryName , $providerPullRequestId );
$providerRepositoryName = $pullRequestResponse [ 'head' ][ 'repo' ][ 'owner' ][ 'login' ];
$providerRepositoryOwner = $pullRequestResponse [ 'head' ][ 'repo' ][ 'name' ];
}
2023-08-11 16:52:13 +00:00
2025-03-07 19:14:11 +00:00
$commands = [];
if ( ! empty ( $resource -> getAttribute ( 'installCommand' , '' ))) {
$commands [] = $resource -> getAttribute ( 'installCommand' , '' );
}
2025-03-09 15:15:08 +00:00
if ( ! empty ( $resource -> getAttribute ( 'buildCommand' , '' ))) {
$commands [] = $resource -> getAttribute ( 'buildCommand' , '' );
}
2025-03-07 19:14:11 +00:00
if ( ! empty ( $resource -> getAttribute ( 'commands' , '' ))) {
$commands [] = $resource -> getAttribute ( 'commands' , '' );
}
2026-01-14 15:08:00 +00:00
$deployment = $authorization -> skip ( fn () => $dbForProject -> createDocument ( 'deployments' , new Document ([
2024-03-10 20:53:57 +00:00
'$id' => $deploymentId ,
'$permissions' => [
Permission :: read ( Role :: any ()),
Permission :: update ( Role :: any ()),
Permission :: delete ( Role :: any ()),
],
2024-10-25 12:41:14 +00:00
'resourceId' => $resourceId ,
'resourceInternalId' => $resourceInternalId ,
'resourceType' => $resourceCollection ,
'entrypoint' => $resource -> getAttribute ( 'entrypoint' , '' ),
2025-03-07 19:14:11 +00:00
'buildCommands' => \implode ( ' && ' , $commands ),
2026-01-16 12:23:46 +00:00
'startCommand' => $resource -> getAttribute ( 'startCommand' , '' ),
2025-03-07 19:14:11 +00:00
'buildOutput' => $resource -> getAttribute ( 'outputDirectory' , '' ),
2025-03-24 14:34:02 +00:00
'adapter' => $resource -> getAttribute ( 'adapter' , '' ),
'fallbackFile' => $resource -> getAttribute ( 'fallbackFile' , '' ),
2024-03-10 20:53:57 +00:00
'type' => 'vcs' ,
'installationId' => $installationId ,
'installationInternalId' => $installationInternalId ,
'providerRepositoryId' => $providerRepositoryId ,
'repositoryId' => $repositoryId ,
'repositoryInternalId' => $repositoryInternalId ,
'providerBranchUrl' => $providerBranchUrl ,
'providerRepositoryName' => $providerRepositoryName ,
'providerRepositoryOwner' => $providerRepositoryOwner ,
'providerRepositoryUrl' => $providerRepositoryUrl ,
'providerCommitHash' => $providerCommitHash ,
'providerCommitAuthorUrl' => $providerCommitAuthorUrl ,
'providerCommitAuthor' => $providerCommitAuthor ,
2025-03-05 08:10:15 +00:00
'providerCommitMessage' => mb_strimwidth ( $providerCommitMessage , 0 , 255 , '...' ),
2024-03-10 20:53:57 +00:00
'providerCommitUrl' => $providerCommitUrl ,
'providerCommentId' => \strval ( $latestCommentId ),
'providerBranch' => $providerBranch ,
'activate' => $activate ,
2025-03-31 16:51:33 +00:00
])));
2024-03-10 20:53:57 +00:00
2025-03-18 14:29:21 +00:00
$resource = $resource
-> setAttribute ( 'latestDeploymentId' , $deployment -> getId ())
2025-05-27 01:36:23 +00:00
-> setAttribute ( 'latestDeploymentInternalId' , $deployment -> getSequence ())
2025-03-18 14:29:21 +00:00
-> setAttribute ( 'latestDeploymentCreatedAt' , $deployment -> getCreatedAt ())
-> setAttribute ( 'latestDeploymentStatus' , $deployment -> getAttribute ( 'status' , '' ));
2026-01-14 15:08:00 +00:00
$authorization -> skip ( fn () => $dbForProject -> updateDocument ( $resource -> getCollection (), $resource -> getId (), $resource ));
2025-03-18 14:29:21 +00:00
2024-11-18 14:57:07 +00:00
if ( $resource -> getCollection () === 'sites' ) {
2025-02-15 03:38:21 +00:00
$projectId = $project -> getId ();
2025-02-24 15:22:23 +00:00
// Deployment preview
2026-01-30 20:30:00 +00:00
$sitesDomain = $platform [ 'sitesDomain' ];
2025-02-20 13:22:30 +00:00
$domain = ID :: unique () . " . " . $sitesDomain ;
2024-11-18 14:57:07 +00:00
$ruleId = md5 ( $domain );
2025-08-28 13:47:07 +00:00
$previewRuleId = $ruleId ;
2026-01-14 15:08:00 +00:00
$authorization -> skip (
2025-02-04 09:51:33 +00:00
fn () => $dbForPlatform -> createDocument ( 'rules' , new Document ([
2024-11-18 14:57:07 +00:00
'$id' => $ruleId ,
'projectId' => $project -> getId (),
2025-05-27 01:36:23 +00:00
'projectInternalId' => $project -> getSequence (),
2024-11-18 14:57:07 +00:00
'domain' => $domain ,
2025-02-23 20:34:14 +00:00
'type' => 'deployment' ,
2025-03-08 18:19:05 +00:00
'trigger' => 'deployment' ,
2025-03-07 09:14:45 +00:00
'deploymentId' => $deployment -> getId (),
2025-05-27 01:36:23 +00:00
'deploymentInternalId' => $deployment -> getSequence (),
2025-03-07 09:14:45 +00:00
'deploymentResourceType' => 'site' ,
'deploymentResourceId' => $resourceId ,
'deploymentResourceInternalId' => $resourceInternalId ,
'deploymentVcsProviderBranch' => $providerBranch ,
2024-11-18 14:57:07 +00:00
'status' => 'verified' ,
'certificateId' => '' ,
2025-02-25 09:47:47 +00:00
'search' => implode ( ' ' , [ $ruleId , $domain ]),
2025-03-17 10:41:02 +00:00
'owner' => 'Appwrite' ,
'region' => $project -> getAttribute ( 'region' )
2024-11-18 14:57:07 +00:00
]))
);
2025-02-24 15:22:23 +00:00
// VCS branch preview
if ( ! empty ( $providerBranch )) {
2025-05-28 07:20:47 +00:00
$branchPrefix = substr ( $providerBranch , 0 , 16 );
if ( strlen ( $providerBranch ) > 16 ) {
$remainingChars = substr ( $providerBranch , 16 );
2025-05-28 08:31:55 +00:00
$branchPrefix .= '-' . substr ( hash ( 'sha256' , $remainingChars ), 0 , 7 );
2025-05-28 07:20:47 +00:00
}
$resourceProjectHash = substr ( hash ( 'sha256' , $resource -> getId () . $project -> getId ()), 0 , 7 );
2025-05-28 07:25:50 +00:00
$domain = " branch- { $branchPrefix } - { $resourceProjectHash } . { $sitesDomain } " ;
2025-02-24 15:22:23 +00:00
$ruleId = md5 ( $domain );
try {
2026-01-14 15:08:00 +00:00
$authorization -> skip (
2025-02-24 15:22:23 +00:00
fn () => $dbForPlatform -> createDocument ( 'rules' , new Document ([
'$id' => $ruleId ,
'projectId' => $project -> getId (),
2025-05-27 01:36:23 +00:00
'projectInternalId' => $project -> getSequence (),
2025-02-24 15:22:23 +00:00
'domain' => $domain ,
'type' => 'deployment' ,
2025-03-08 18:19:05 +00:00
'trigger' => 'deployment' ,
2025-03-07 09:14:45 +00:00
'deploymentId' => $deployment -> getId (),
2025-05-27 01:36:23 +00:00
'deploymentInternalId' => $deployment -> getSequence (),
2025-03-07 09:14:45 +00:00
'deploymentResourceType' => 'site' ,
'deploymentResourceId' => $resourceId ,
'deploymentResourceInternalId' => $resourceInternalId ,
'deploymentVcsProviderBranch' => $providerBranch ,
2025-02-24 15:22:23 +00:00
'status' => 'verified' ,
'certificateId' => '' ,
2025-02-25 09:47:47 +00:00
'search' => implode ( ' ' , [ $ruleId , $domain ]),
2025-03-17 10:41:02 +00:00
'owner' => 'Appwrite' ,
'region' => $project -> getAttribute ( 'region' )
2025-02-24 15:22:23 +00:00
]))
);
} catch ( Duplicate $err ) {
// Ignore, rule already exists; will be updated by builds worker
}
}
2024-03-10 20:53:57 +00:00
2025-02-24 15:22:23 +00:00
// VCS commit preview
if ( ! empty ( $providerCommitHash )) {
2025-05-28 08:40:12 +00:00
$domain = " commit- " . substr ( $providerCommitHash , 0 , 16 ) . " . { $sitesDomain } " ;
2025-02-24 15:22:23 +00:00
$ruleId = md5 ( $domain );
try {
2026-01-14 15:08:00 +00:00
$authorization -> skip (
2025-02-24 15:22:23 +00:00
fn () => $dbForPlatform -> createDocument ( 'rules' , new Document ([
'$id' => $ruleId ,
'projectId' => $project -> getId (),
2025-05-27 01:36:23 +00:00
'projectInternalId' => $project -> getSequence (),
2025-02-24 15:22:23 +00:00
'domain' => $domain ,
'type' => 'deployment' ,
2025-03-08 18:19:05 +00:00
'trigger' => 'deployment' ,
2025-03-07 09:14:45 +00:00
'deploymentId' => $deployment -> getId (),
2025-05-27 01:36:23 +00:00
'deploymentInternalId' => $deployment -> getSequence (),
2025-03-07 09:14:45 +00:00
'deploymentResourceType' => 'site' ,
'deploymentResourceId' => $resourceId ,
'deploymentResourceInternalId' => $resourceInternalId ,
'deploymentVcsProviderBranch' => $providerBranch ,
2025-02-24 15:22:23 +00:00
'status' => 'verified' ,
'certificateId' => '' ,
2025-02-25 09:47:47 +00:00
'search' => implode ( ' ' , [ $ruleId , $domain ]),
2025-03-17 10:41:02 +00:00
'owner' => 'Appwrite' ,
'region' => $project -> getAttribute ( 'region' )
2025-02-24 15:22:23 +00:00
]))
);
} catch ( Duplicate $err ) {
// Ignore, rule already exists; will be updated by builds worker
}
}
2024-11-18 14:57:07 +00:00
}
2024-03-10 20:53:57 +00:00
2025-08-27 14:35:27 +00:00
if ( $resource -> getCollection () === 'sites' && ! empty ( $latestCommentId ) && ! empty ( $previewRuleId )) {
2025-09-03 11:27:15 +00:00
$retries = 0 ;
2025-09-04 06:20:12 +00:00
$lockAcquired = false ;
2025-09-03 11:27:15 +00:00
2025-09-04 06:20:12 +00:00
while ( $retries < 9 ) {
2025-09-03 11:27:15 +00:00
$retries ++ ;
try {
$dbForPlatform -> createDocument ( 'vcsCommentLocks' , new Document ([
'$id' => $latestCommentId
]));
2025-09-04 06:20:12 +00:00
$lockAcquired = true ;
2025-09-03 11:27:15 +00:00
break ;
} catch ( \Throwable $err ) {
if ( $retries >= 9 ) {
2025-09-03 13:15:43 +00:00
Console :: warning ( " Error creating vcs comment lock for " . $latestCommentId . " : " . $err -> getMessage ());
2025-09-03 11:27:15 +00:00
}
\sleep ( 1 );
}
}
2025-09-04 06:20:12 +00:00
if ( $lockAcquired ) {
// Wrap in try/finally to ensure lock file gets deleted
try {
2026-01-14 15:08:00 +00:00
$rule = $authorization -> skip ( fn () => $dbForPlatform -> getDocument ( 'rules' , $previewRuleId ));
2025-08-27 14:35:27 +00:00
2025-09-04 06:20:12 +00:00
$protocol = System :: getEnv ( '_APP_OPTIONS_FORCE_HTTPS' ) === 'disabled' ? 'http' : 'https' ;
$previewUrl = ! empty ( $rule ) ? ( " { $protocol } :// " . $rule -> getAttribute ( 'domain' , '' )) : '' ;
2025-08-27 14:35:27 +00:00
2025-09-04 06:20:12 +00:00
if ( ! empty ( $previewUrl )) {
2025-12-07 20:29:45 +00:00
$comment = new Comment ( $platform );
2025-09-04 06:20:12 +00:00
$comment -> parseComment ( $github -> getComment ( $owner , $repositoryName , $latestCommentId ));
$comment -> addBuild ( $project , $resource , $resourceType , $commentStatus , $deploymentId , $action , $previewUrl );
$github -> updateComment ( $owner , $repositoryName , $latestCommentId , $comment -> generateComment ());
}
} finally {
2026-01-14 15:08:00 +00:00
$authorization -> skip ( fn () => $dbForPlatform -> deleteDocument ( 'vcsCommentLocks' , $latestCommentId ));
2025-08-27 14:35:27 +00:00
}
}
}
2024-10-25 12:41:14 +00:00
if ( ! empty ( $providerCommitHash ) && $resource -> getAttribute ( 'providerSilentMode' , false ) === false ) {
$resourceName = $resource -> getAttribute ( 'name' );
2024-03-10 20:53:57 +00:00
$projectName = $project -> getAttribute ( 'name' );
2025-06-12 06:13:11 +00:00
$region = $project -> getAttribute ( 'region' , 'default' );
2024-10-25 12:41:14 +00:00
$name = " { $resourceName } ( { $projectName } ) " ;
2024-03-10 20:53:57 +00:00
$message = 'Starting...' ;
2023-07-28 08:27:16 +00:00
2024-10-25 12:41:14 +00:00
$providerRepositoryId = $repository -> getAttribute ( 'providerRepositoryId' );
2024-03-10 20:53:57 +00:00
try {
$repositoryName = $github -> getRepositoryName ( $providerRepositoryId ) ? ? '' ;
if ( empty ( $repositoryName )) {
2023-10-27 14:08:33 +00:00
throw new Exception ( Exception :: PROVIDER_REPOSITORY_NOT_FOUND );
}
2024-03-10 20:53:57 +00:00
} catch ( RepositoryNotFound $e ) {
throw new Exception ( Exception :: PROVIDER_REPOSITORY_NOT_FOUND );
2024-03-10 20:43:22 +00:00
}
2024-03-10 20:53:57 +00:00
$owner = $github -> getOwnerName ( $providerInstallationId );
2023-07-28 08:27:16 +00:00
2025-06-13 10:20:53 +00:00
$providerTargetUrl = $protocol . '://' . $hostname . " /console/project- $region - $projectId / $resourceCollection / $resourceType - $resourceId " ;
2024-03-10 20:53:57 +00:00
$github -> updateCommitStatus ( $repositoryName , $providerCommitHash , $owner , 'pending' , $message , $providerTargetUrl , $name );
}
2024-03-10 20:33:57 +00:00
2024-03-10 20:53:57 +00:00
$queueForBuilds
-> setType ( BUILD_TYPE_DEPLOYMENT )
2024-10-25 12:41:14 +00:00
-> setResource ( $resource )
2024-03-10 20:53:57 +00:00
-> setDeployment ( $deployment )
-> setProject ( $project ); // set the project because it won't be set for git deployments
2023-07-28 08:27:16 +00:00
2024-10-25 12:41:14 +00:00
$queueForBuilds -> trigger (); // must trigger here so that we create a build for each function/site
2024-03-10 20:53:57 +00:00
//TODO: Add event?
2024-03-10 20:43:22 +00:00
} catch ( Throwable $e ) {
$errors [] = $e -> getMessage ();
2023-07-28 08:27:16 +00:00
}
}
2024-03-10 20:33:57 +00:00
2024-03-11 10:17:40 +00:00
$queueForBuilds -> reset (); // prevent shutdown hook from triggering again
2024-03-10 20:43:22 +00:00
if ( ! empty ( $errors )) {
throw new Exception ( Exception :: GENERAL_UNKNOWN , \implode ( " \n " , $errors ));
}
2023-07-28 08:27:16 +00:00
};
2026-02-04 05:30:22 +00:00
Http :: post ( '/v1/vcs/github/events' )
2024-10-08 07:54:40 +00:00
-> desc ( 'Create event' )
2023-05-22 10:58:13 +00:00
-> groups ([ 'api' , 'vcs' ])
2023-08-30 18:44:33 +00:00
-> label ( 'scope' , 'public' )
2023-05-26 08:44:08 +00:00
-> inject ( 'gitHub' )
2023-05-22 10:58:13 +00:00
-> inject ( 'request' )
-> inject ( 'response' )
2024-12-12 10:30:26 +00:00
-> inject ( 'dbForPlatform' )
2026-01-14 15:08:00 +00:00
-> inject ( 'authorization' )
2023-05-23 04:37:25 +00:00
-> inject ( 'getProjectDB' )
2023-10-09 10:28:06 +00:00
-> inject ( 'queueForBuilds' )
2025-12-07 20:29:45 +00:00
-> inject ( 'platform' )
2023-05-22 10:58:13 +00:00
-> action (
2026-01-14 15:08:00 +00:00
function ( GitHub $github , Request $request , Response $response , Database $dbForPlatform , Authorization $authorization , callable $getProjectDB , Build $queueForBuilds , array $platform ) use ( $createGitDeployments ) {
2023-05-22 10:58:13 +00:00
$payload = $request -> getRawPayload ();
2023-09-06 17:04:03 +00:00
$signatureRemote = $request -> getHeader ( 'x-hub-signature-256' , '' );
2024-04-01 11:02:47 +00:00
$signatureLocal = System :: getEnv ( '_APP_VCS_GITHUB_WEBHOOK_SECRET' , '' );
2023-06-15 10:37:28 +00:00
2023-09-06 17:04:03 +00:00
$valid = empty ( $signatureRemote ) ? true : $github -> validateWebhookEvent ( $payload , $signatureRemote , $signatureLocal );
2023-06-15 10:38:03 +00:00
if ( ! $valid ) {
2023-09-06 17:57:46 +00:00
throw new Exception ( Exception :: GENERAL_ACCESS_FORBIDDEN , " Invalid webhook payload signature. Please make sure the webhook secret has same value in your GitHub app and in the _APP_VCS_GITHUB_WEBHOOK_SECRET environment variable " );
2023-06-15 10:37:28 +00:00
}
$event = $request -> getHeader ( 'x-github-event' , '' );
2024-04-01 11:02:47 +00:00
$privateKey = System :: getEnv ( '_APP_VCS_GITHUB_PRIVATE_KEY' );
$githubAppId = System :: getEnv ( '_APP_VCS_GITHUB_APP_ID' );
2023-07-24 10:11:30 +00:00
$parsedPayload = $github -> getEvent ( $event , $payload );
2023-05-22 10:58:13 +00:00
if ( $event == $github :: EVENT_PUSH ) {
2023-08-19 12:54:43 +00:00
$providerBranchCreated = $parsedPayload [ " branchCreated " ] ? ? false ;
2025-06-02 08:34:03 +00:00
$providerBranchDeleted = $parsedPayload [ " branchDeleted " ] ? ? false ;
2023-07-30 09:51:13 +00:00
$providerBranch = $parsedPayload [ " branch " ] ? ? '' ;
2023-08-09 17:35:23 +00:00
$providerBranchUrl = $parsedPayload [ " branchUrl " ] ? ? '' ;
2023-07-30 09:51:13 +00:00
$providerRepositoryId = $parsedPayload [ " repositoryId " ] ? ? '' ;
2023-08-09 10:54:46 +00:00
$providerRepositoryName = $parsedPayload [ " repositoryName " ] ? ? '' ;
2023-07-30 09:51:13 +00:00
$providerInstallationId = $parsedPayload [ " installationId " ] ? ? '' ;
2023-08-09 10:54:46 +00:00
$providerRepositoryUrl = $parsedPayload [ " repositoryUrl " ] ? ? '' ;
$providerCommitHash = $parsedPayload [ " commitHash " ] ? ? '' ;
$providerRepositoryOwner = $parsedPayload [ " owner " ] ? ? '' ;
2025-07-23 04:23:09 +00:00
$providerCommitAuthorName = $parsedPayload [ " headCommitAuthorName " ] ? ? '' ;
2025-07-22 15:09:36 +00:00
$providerCommitAuthorEmail = $parsedPayload [ " headCommitAuthorEmail " ] ? ? '' ;
2023-08-09 17:35:23 +00:00
$providerCommitAuthorUrl = $parsedPayload [ " authorUrl " ] ? ? '' ;
2023-08-09 10:54:46 +00:00
$providerCommitMessage = $parsedPayload [ " headCommitMessage " ] ? ? '' ;
$providerCommitUrl = $parsedPayload [ " headCommitUrl " ] ? ? '' ;
2023-05-22 10:58:13 +00:00
2023-08-09 17:35:23 +00:00
$github -> initializeVariables ( $providerInstallationId , $privateKey , $githubAppId );
2023-05-29 11:51:03 +00:00
2024-10-25 12:41:14 +00:00
//find resourceId from relevant resources table
2026-01-14 15:08:00 +00:00
$repositories = $authorization -> skip ( fn () => $dbForPlatform -> find ( 'repositories' , [
2023-07-30 09:51:13 +00:00
Query :: equal ( 'providerRepositoryId' , [ $providerRepositoryId ]),
2023-05-22 10:58:13 +00:00
Query :: limit ( 100 ),
2023-11-14 15:50:59 +00:00
]));
2023-05-22 10:58:13 +00:00
2025-07-22 15:09:36 +00:00
// create new deployment only on push (not committed by us) and not when branch is created or deleted
if ( $providerCommitAuthorEmail !== APP_VCS_GITHUB_EMAIL && ! $providerBranchCreated && ! $providerBranchDeleted ) {
2026-01-14 15:08:00 +00:00
$createGitDeployments ( $github , $providerInstallationId , $repositories , $providerBranch , $providerBranchUrl , $providerRepositoryName , $providerRepositoryUrl , $providerRepositoryOwner , $providerCommitHash , $providerCommitAuthorName , $providerCommitAuthorUrl , $providerCommitMessage , $providerCommitUrl , '' , false , $dbForPlatform , $authorization , $queueForBuilds , $getProjectDB , $request , $platform );
2023-08-09 15:53:58 +00:00
}
2023-05-22 10:58:13 +00:00
} elseif ( $event == $github :: EVENT_INSTALLATION ) {
if ( $parsedPayload [ " action " ] == " deleted " ) {
2024-10-25 12:41:14 +00:00
// TODO: Use worker for this job instead (update function/site as well)
2023-07-30 09:51:13 +00:00
$providerInstallationId = $parsedPayload [ " installationId " ];
2023-05-22 10:58:13 +00:00
2024-12-12 10:30:26 +00:00
$installations = $dbForPlatform -> find ( 'installations' , [
2023-07-30 09:51:13 +00:00
Query :: equal ( 'providerInstallationId' , [ $providerInstallationId ]),
2023-05-22 10:58:13 +00:00
Query :: limit ( 1000 )
]);
2023-07-30 09:51:13 +00:00
foreach ( $installations as $installation ) {
2026-01-14 15:08:00 +00:00
$repositories = $authorization -> skip ( fn () => $dbForPlatform -> find ( 'repositories' , [
2025-05-26 05:42:11 +00:00
Query :: equal ( 'installationInternalId' , [ $installation -> getSequence ()]),
2023-05-22 10:58:13 +00:00
Query :: limit ( 1000 )
2023-11-14 15:50:59 +00:00
]));
2023-05-22 10:58:13 +00:00
2023-07-30 09:51:13 +00:00
foreach ( $repositories as $repository ) {
2026-01-14 15:08:00 +00:00
$authorization -> skip ( fn () => $dbForPlatform -> deleteDocument ( 'repositories' , $repository -> getId ()));
2023-05-22 10:58:13 +00:00
}
2026-01-14 15:08:00 +00:00
$authorization -> skip ( fn () => $dbForPlatform -> deleteDocument ( 'installations' , $installation -> getId ()));
2023-05-22 10:58:13 +00:00
}
}
} elseif ( $event == $github :: EVENT_PULL_REQUEST ) {
2023-06-28 08:48:10 +00:00
if ( $parsedPayload [ " action " ] == " opened " || $parsedPayload [ " action " ] == " reopened " || $parsedPayload [ " action " ] == " synchronize " ) {
2023-07-30 09:51:13 +00:00
$providerBranch = $parsedPayload [ " branch " ] ? ? '' ;
2023-08-09 17:35:23 +00:00
$providerBranchUrl = $parsedPayload [ " branchUrl " ] ? ? '' ;
2023-07-30 09:51:13 +00:00
$providerRepositoryId = $parsedPayload [ " repositoryId " ] ? ? '' ;
2023-08-09 10:54:46 +00:00
$providerRepositoryName = $parsedPayload [ " repositoryName " ] ? ? '' ;
2023-07-30 09:51:13 +00:00
$providerInstallationId = $parsedPayload [ " installationId " ] ? ? '' ;
2023-08-09 10:54:46 +00:00
$providerRepositoryUrl = $parsedPayload [ " repositoryUrl " ] ? ? '' ;
2023-07-30 09:51:13 +00:00
$providerPullRequestId = $parsedPayload [ " pullRequestNumber " ] ? ? '' ;
2023-08-09 10:54:46 +00:00
$providerCommitHash = $parsedPayload [ " commitHash " ] ? ? '' ;
$providerRepositoryOwner = $parsedPayload [ " owner " ] ? ? '' ;
2023-07-28 07:40:19 +00:00
$external = $parsedPayload [ " external " ] ? ? true ;
2023-08-09 10:54:46 +00:00
$providerCommitUrl = $parsedPayload [ " headCommitUrl " ] ? ? '' ;
2023-08-09 17:35:23 +00:00
$providerCommitAuthorUrl = $parsedPayload [ " authorUrl " ] ? ? '' ;
2023-05-29 11:51:03 +00:00
2023-06-28 11:31:35 +00:00
// Ignore sync for non-external. We handle it in push webhook
2023-07-01 06:46:21 +00:00
if ( ! $external && $parsedPayload [ " action " ] == " synchronize " ) {
2023-06-28 11:31:35 +00:00
return $response -> json ( $parsedPayload );
}
2023-08-09 17:35:23 +00:00
$github -> initializeVariables ( $providerInstallationId , $privateKey , $githubAppId );
2023-05-22 10:58:13 +00:00
2023-08-09 10:54:46 +00:00
$commitDetails = $github -> getCommit ( $providerRepositoryOwner , $providerRepositoryName , $providerCommitHash );
$providerCommitAuthor = $commitDetails [ " commitAuthor " ] ? ? '' ;
$providerCommitMessage = $commitDetails [ " commitMessage " ] ? ? '' ;
2026-01-14 15:08:00 +00:00
$repositories = $authorization -> skip ( fn () => $dbForPlatform -> find ( 'repositories' , [
2023-07-30 09:51:13 +00:00
Query :: equal ( 'providerRepositoryId' , [ $providerRepositoryId ]),
2023-05-22 10:58:13 +00:00
Query :: orderDesc ( '$createdAt' )
2023-11-14 15:50:59 +00:00
]));
2023-05-22 10:58:13 +00:00
2026-01-14 15:08:00 +00:00
$createGitDeployments ( $github , $providerInstallationId , $repositories , $providerBranch , $providerBranchUrl , $providerRepositoryName , $providerRepositoryUrl , $providerRepositoryOwner , $providerCommitHash , $providerCommitAuthor , $providerCommitAuthorUrl , $providerCommitMessage , $providerCommitUrl , $providerPullRequestId , $external , $dbForPlatform , $authorization , $queueForBuilds , $getProjectDB , $request , $platform );
2023-06-28 08:48:10 +00:00
} elseif ( $parsedPayload [ " action " ] == " closed " ) {
// Allowed external contributions cleanup
2023-07-30 09:51:13 +00:00
$providerRepositoryId = $parsedPayload [ " repositoryId " ] ? ? '' ;
$providerPullRequestId = $parsedPayload [ " pullRequestNumber " ] ? ? '' ;
2023-07-28 07:40:19 +00:00
$external = $parsedPayload [ " external " ] ? ? true ;
2023-06-28 08:48:10 +00:00
if ( $external ) {
2026-01-14 15:08:00 +00:00
$repositories = $authorization -> skip ( fn () => $dbForPlatform -> find ( 'repositories' , [
2023-07-30 09:51:13 +00:00
Query :: equal ( 'providerRepositoryId' , [ $providerRepositoryId ]),
2023-06-28 08:48:10 +00:00
Query :: orderDesc ( '$createdAt' )
2023-11-14 15:50:59 +00:00
]));
2023-06-28 08:48:10 +00:00
2023-07-30 09:51:13 +00:00
foreach ( $repositories as $repository ) {
$providerPullRequestIds = $repository -> getAttribute ( 'providerPullRequestIds' , []);
2023-06-28 08:48:10 +00:00
2023-07-30 09:51:13 +00:00
if ( \in_array ( $providerPullRequestId , $providerPullRequestIds )) {
$providerPullRequestIds = \array_diff ( $providerPullRequestIds , [ $providerPullRequestId ]);
$repository = $repository -> setAttribute ( 'providerPullRequestIds' , $providerPullRequestIds );
2026-01-14 15:08:00 +00:00
$repository = $authorization -> skip ( fn () => $dbForPlatform -> updateDocument ( 'repositories' , $repository -> getId (), $repository ));
2023-06-28 08:48:10 +00:00
}
}
}
2023-05-22 10:58:13 +00:00
}
}
$response -> json ( $parsedPayload );
}
);
2026-02-04 05:30:22 +00:00
Http :: patch ( '/v1/vcs/github/installations/:installationId/repositories/:repositoryId' )
2025-04-14 18:40:48 +00:00
-> desc ( 'Update external deployment (authorize)' )
2023-06-28 08:48:10 +00:00
-> groups ([ 'api' , 'vcs' ])
2023-08-30 18:44:33 +00:00
-> label ( 'scope' , 'vcs.write' )
2025-01-17 04:31:39 +00:00
-> label ( 'sdk' , new Method (
namespace : 'vcs' ,
2025-03-31 05:48:17 +00:00
group : 'repositories' ,
2025-01-17 04:31:39 +00:00
name : 'updateExternalDeployments' ,
2025-01-17 07:44:25 +00:00
description : '/docs/references/vcs/update-external-deployments.md' ,
2025-01-17 04:31:39 +00:00
auth : [ AuthType :: ADMIN ],
responses : [
new SDKResponse (
code : Response :: STATUS_CODE_NOCONTENT ,
model : Response :: MODEL_NONE ,
)
]
))
2023-06-28 08:48:10 +00:00
-> param ( 'installationId' , '' , new Text ( 256 ), 'Installation Id' )
2023-07-30 09:51:13 +00:00
-> param ( 'repositoryId' , '' , new Text ( 256 ), 'VCS Repository Id' )
-> param ( 'providerPullRequestId' , '' , new Text ( 256 ), 'GitHub Pull Request Id' )
2023-06-28 08:48:10 +00:00
-> inject ( 'gitHub' )
-> inject ( 'response' )
-> inject ( 'project' )
2024-12-12 10:30:26 +00:00
-> inject ( 'dbForPlatform' )
2026-01-14 15:08:00 +00:00
-> inject ( 'authorization' )
2023-06-28 08:48:10 +00:00
-> inject ( 'getProjectDB' )
2023-10-09 10:28:06 +00:00
-> inject ( 'queueForBuilds' )
2025-12-07 20:29:45 +00:00
-> inject ( 'platform' )
2026-01-14 15:08:00 +00:00
-> action ( function ( string $installationId , string $repositoryId , string $providerPullRequestId , GitHub $github , Request $request , Response $response , Document $project , Database $dbForPlatform , Authorization $authorization , callable $getProjectDB , Build $queueForBuilds , array $platform ) use ( $createGitDeployments ) {
2024-12-12 10:30:26 +00:00
$installation = $dbForPlatform -> getDocument ( 'installations' , $installationId );
2023-06-28 08:48:10 +00:00
if ( $installation -> isEmpty ()) {
throw new Exception ( Exception :: INSTALLATION_NOT_FOUND );
}
2026-01-14 15:08:00 +00:00
$repository = $authorization -> skip ( fn () => $dbForPlatform -> findOne ( 'repositories' , [
2025-12-01 14:29:07 +00:00
Query :: equal ( '$id' , [ $repositoryId ]),
2025-05-26 05:42:11 +00:00
Query :: equal ( 'projectInternalId' , [ $project -> getSequence ()])
2023-11-14 15:50:59 +00:00
]));
2023-06-28 08:48:10 +00:00
2023-07-30 09:51:13 +00:00
if ( $repository -> isEmpty ()) {
2023-07-31 06:47:47 +00:00
throw new Exception ( Exception :: REPOSITORY_NOT_FOUND );
2023-06-28 08:48:10 +00:00
}
2023-07-30 09:51:13 +00:00
if ( \in_array ( $providerPullRequestId , $repository -> getAttribute ( 'providerPullRequestIds' , []))) {
2023-07-31 06:47:47 +00:00
throw new Exception ( Exception :: PROVIDER_CONTRIBUTION_CONFLICT );
2023-06-28 08:48:10 +00:00
}
2023-07-30 09:51:13 +00:00
$providerPullRequestIds = \array_unique ( \array_merge ( $repository -> getAttribute ( 'providerPullRequestIds' , []), [ $providerPullRequestId ]));
$repository = $repository -> setAttribute ( 'providerPullRequestIds' , $providerPullRequestIds );
2023-06-28 08:48:10 +00:00
// TODO: Delete from array when PR is closed
2026-01-14 15:08:00 +00:00
$repository = $authorization -> skip ( fn () => $dbForPlatform -> updateDocument ( 'repositories' , $repository -> getId (), $repository ));
2023-06-28 08:48:10 +00:00
2024-04-01 11:02:47 +00:00
$privateKey = System :: getEnv ( '_APP_VCS_GITHUB_PRIVATE_KEY' );
$githubAppId = System :: getEnv ( '_APP_VCS_GITHUB_APP_ID' );
2023-07-30 09:51:13 +00:00
$providerInstallationId = $installation -> getAttribute ( 'providerInstallationId' );
2023-08-09 17:35:23 +00:00
$github -> initializeVariables ( $providerInstallationId , $privateKey , $githubAppId );
2023-06-28 08:48:10 +00:00
2023-07-30 09:51:13 +00:00
$repositories = [ $repository ];
$providerRepositoryId = $repository -> getAttribute ( 'providerRepositoryId' );
2023-06-28 08:48:10 +00:00
2023-07-30 09:51:13 +00:00
$owner = $github -> getOwnerName ( $providerInstallationId );
2023-10-27 14:08:33 +00:00
try {
$repositoryName = $github -> getRepositoryName ( $providerRepositoryId ) ? ? '' ;
if ( empty ( $repositoryName )) {
throw new Exception ( Exception :: PROVIDER_REPOSITORY_NOT_FOUND );
}
} catch ( RepositoryNotFound $e ) {
throw new Exception ( Exception :: PROVIDER_REPOSITORY_NOT_FOUND );
}
2023-07-30 09:51:13 +00:00
$pullRequestResponse = $github -> getPullRequest ( $owner , $repositoryName , $providerPullRequestId );
2023-06-28 08:48:10 +00:00
2023-07-30 09:51:13 +00:00
$providerBranch = \explode ( ':' , $pullRequestResponse [ 'head' ][ 'label' ])[ 1 ] ? ? '' ;
$providerCommitHash = $pullRequestResponse [ 'head' ][ 'sha' ] ? ? '' ;
2025-12-07 20:29:45 +00:00
$providerBranchUrl = $pullRequestResponse [ 'head' ][ 'repo' ][ 'html_url' ] ? ? '' ;
$providerRepositoryName = $pullRequestResponse [ 'head' ][ 'repo' ][ 'name' ] ? ? '' ;
$providerRepositoryUrl = $pullRequestResponse [ 'head' ][ 'repo' ][ 'html_url' ] ? ? '' ;
$providerRepositoryOwner = $pullRequestResponse [ 'head' ][ 'repo' ][ 'owner' ][ 'login' ] ? ? '' ;
$providerCommitAuthor = $pullRequestResponse [ 'head' ][ 'user' ][ 'login' ] ? ? '' ;
$providerCommitAuthorUrl = $pullRequestResponse [ 'head' ][ 'user' ][ 'html_url' ] ? ? '' ;
$providerCommitMessage = $pullRequestResponse [ 'title' ] ? ? '' ;
$providerCommitUrl = $pullRequestResponse [ 'html_url' ] ? ? '' ;
2026-01-14 15:08:00 +00:00
$createGitDeployments ( $github , $providerInstallationId , $repositories , $providerBranch , '' , '' , '' , '' , $providerCommitHash , '' , '' , '' , '' , $providerPullRequestId , true , $dbForPlatform , $authorization , $queueForBuilds , $getProjectDB , $request , $platform );
2023-06-28 08:48:10 +00:00
$response -> noContent ();
});