Merge pull request #9537 from appwrite/feat-latest-deployment-details

Feat: Latest deployment details
This commit is contained in:
Matej Bačo 2025-03-20 16:40:04 +01:00 committed by GitHub
commit d07b543e71
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
26 changed files with 674 additions and 26 deletions

View file

@ -590,6 +590,50 @@ return [
'array' => false,
'filters' => ['datetime'],
],
[
'$id' => ID::custom('latestDeploymentId'),
'type' => Database::VAR_STRING,
'format' => '',
'size' => Database::LENGTH_KEY,
'signed' => true,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
],
[
'$id' => ID::custom('latestDeploymentInternalId'),
'type' => Database::VAR_STRING,
'format' => '',
'size' => Database::LENGTH_KEY,
'signed' => true,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
],
[
'$id' => ID::custom('latestDeploymentCreatedAt'),
'type' => Database::VAR_DATETIME,
'format' => '',
'size' => 0,
'signed' => false,
'required' => false,
'default' => null,
'array' => false,
'filters' => ['datetime'],
],
[
'$id' => ID::custom('latestDeploymentStatus'),
'type' => Database::VAR_STRING,
'format' => '',
'size' => 16,
'signed' => true,
'required' => false,
'default' => '',
'array' => false,
'filters' => [],
],
[
'$id' => ID::custom('vars'),
'type' => Database::VAR_STRING,
@ -1047,6 +1091,50 @@ return [
'array' => false,
'filters' => [],
],
[
'$id' => ID::custom('latestDeploymentId'),
'type' => Database::VAR_STRING,
'format' => '',
'size' => Database::LENGTH_KEY,
'signed' => true,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
],
[
'$id' => ID::custom('latestDeploymentInternalId'),
'type' => Database::VAR_STRING,
'format' => '',
'size' => Database::LENGTH_KEY,
'signed' => true,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
],
[
'$id' => ID::custom('latestDeploymentCreatedAt'),
'type' => Database::VAR_DATETIME,
'format' => '',
'size' => 0,
'signed' => false,
'required' => false,
'default' => null,
'array' => false,
'filters' => ['datetime'],
],
[
'$id' => ID::custom('latestDeploymentStatus'),
'type' => Database::VAR_STRING,
'format' => '',
'size' => 16,
'signed' => true,
'required' => false,
'default' => '',
'array' => false,
'filters' => [],
],
[
'$id' => ID::custom('vars'),
'type' => Database::VAR_STRING,

View file

@ -10140,7 +10140,7 @@
},
{
"name": "queries",
"description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: buildSize, sourceSize, buildDuration, status, activate, type",
"description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: buildSize, sourceSize, totalSize, buildDuration, status, activate, type",
"required": false,
"schema": {
"type": "array",
@ -25699,7 +25699,7 @@
},
{
"name": "queries",
"description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: buildSize, sourceSize, buildDuration, status, activate, type",
"description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: buildSize, sourceSize, totalSize, buildDuration, status, activate, type",
"required": false,
"schema": {
"type": "array",
@ -36875,6 +36875,36 @@
"description": "Site's active deployment ID.",
"x-example": "5e5ea5c16897e"
},
"deploymentCreatedAt": {
"type": "string",
"description": "Active deployment creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"deploymentScreenshotLight": {
"type": "string",
"description": "Screenshot of active deployment with light theme preference file ID.",
"x-example": "5e5ea5c16897e"
},
"deploymentScreenshotDark": {
"type": "string",
"description": "Screenshot of active deployment with dark theme preference file ID.",
"x-example": "5e5ea5c16897e"
},
"latestDeploymentId": {
"type": "string",
"description": "Site's latest deployment ID.",
"x-example": "5e5ea5c16897e"
},
"latestDeploymentCreatedAt": {
"type": "string",
"description": "Latest deployment creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"latestDeploymentStatus": {
"type": "string",
"description": "Status of latest deployment. Possible values are \"waiting\", \"processing\", \"building\", \"ready\", and \"failed\".",
"x-example": "ready"
},
"vars": {
"type": "array",
"description": "Site variables.",
@ -36959,6 +36989,12 @@
"live",
"framework",
"deploymentId",
"deploymentCreatedAt",
"deploymentScreenshotLight",
"deploymentScreenshotDark",
"latestDeploymentId",
"latestDeploymentCreatedAt",
"latestDeploymentStatus",
"vars",
"timeout",
"installCommand",
@ -37183,6 +37219,26 @@
"description": "Function's active deployment ID.",
"x-example": "5e5ea5c16897e"
},
"deploymentCreatedAt": {
"type": "string",
"description": "Active deployment creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"latestDeploymentId": {
"type": "string",
"description": "Function's latest deployment ID.",
"x-example": "5e5ea5c16897e"
},
"latestDeploymentCreatedAt": {
"type": "string",
"description": "Latest deployment creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"latestDeploymentStatus": {
"type": "string",
"description": "Status of latest deployment. Possible values are \"waiting\", \"processing\", \"building\", \"ready\", and \"failed\".",
"x-example": "ready"
},
"scopes": {
"type": "array",
"description": "Allowed permission scopes.",
@ -37275,6 +37331,10 @@
"logging",
"runtime",
"deploymentId",
"deploymentCreatedAt",
"latestDeploymentId",
"latestDeploymentCreatedAt",
"latestDeploymentStatus",
"scopes",
"vars",
"events",
@ -37926,13 +37986,19 @@
"type": "string",
"description": "Default output directory of build.",
"x-example": ".\/dist"
},
"fallbackFile": {
"type": "string",
"description": "Name of fallback file to use instead of 404 page. If null, Appwrite 404 page will be displayed.",
"x-example": "index.html"
}
},
"required": [
"key",
"installCommand",
"buildCommand",
"outputDirectory"
"outputDirectory",
"fallbackFile"
]
},
"deployment": {
@ -37986,6 +38052,12 @@
"x-example": 128,
"format": "int32"
},
"totalSize": {
"type": "integer",
"description": "The total size in bytes (source and build output).",
"x-example": 128,
"format": "int32"
},
"buildId": {
"type": "string",
"description": "The current build ID.",
@ -38008,7 +38080,7 @@
},
"status": {
"type": "string",
"description": "The deployment status. Possible values are \"waiting\", \"processing\", \"building\", \"waiting\", \"ready\", and \"failed\".",
"description": "The deployment status. Possible values are \"waiting\", \"processing\", \"building\", \"ready\", and \"failed\".",
"x-example": "ready"
},
"buildLogs": {
@ -38083,6 +38155,7 @@
"entrypoint",
"sourceSize",
"buildSize",
"totalSize",
"buildId",
"activate",
"screenshotLight",

View file

@ -9005,7 +9005,7 @@
},
{
"name": "queries",
"description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: buildSize, sourceSize, buildDuration, status, activate, type",
"description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: buildSize, sourceSize, totalSize, buildDuration, status, activate, type",
"required": false,
"schema": {
"type": "array",
@ -17574,7 +17574,7 @@
},
{
"name": "queries",
"description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: buildSize, sourceSize, buildDuration, status, activate, type",
"description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: buildSize, sourceSize, totalSize, buildDuration, status, activate, type",
"required": false,
"schema": {
"type": "array",
@ -27423,6 +27423,36 @@
"description": "Site's active deployment ID.",
"x-example": "5e5ea5c16897e"
},
"deploymentCreatedAt": {
"type": "string",
"description": "Active deployment creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"deploymentScreenshotLight": {
"type": "string",
"description": "Screenshot of active deployment with light theme preference file ID.",
"x-example": "5e5ea5c16897e"
},
"deploymentScreenshotDark": {
"type": "string",
"description": "Screenshot of active deployment with dark theme preference file ID.",
"x-example": "5e5ea5c16897e"
},
"latestDeploymentId": {
"type": "string",
"description": "Site's latest deployment ID.",
"x-example": "5e5ea5c16897e"
},
"latestDeploymentCreatedAt": {
"type": "string",
"description": "Latest deployment creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"latestDeploymentStatus": {
"type": "string",
"description": "Status of latest deployment. Possible values are \"waiting\", \"processing\", \"building\", \"ready\", and \"failed\".",
"x-example": "ready"
},
"vars": {
"type": "array",
"description": "Site variables.",
@ -27507,6 +27537,12 @@
"live",
"framework",
"deploymentId",
"deploymentCreatedAt",
"deploymentScreenshotLight",
"deploymentScreenshotDark",
"latestDeploymentId",
"latestDeploymentCreatedAt",
"latestDeploymentStatus",
"vars",
"timeout",
"installCommand",
@ -27580,6 +27616,26 @@
"description": "Function's active deployment ID.",
"x-example": "5e5ea5c16897e"
},
"deploymentCreatedAt": {
"type": "string",
"description": "Active deployment creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"latestDeploymentId": {
"type": "string",
"description": "Function's latest deployment ID.",
"x-example": "5e5ea5c16897e"
},
"latestDeploymentCreatedAt": {
"type": "string",
"description": "Latest deployment creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"latestDeploymentStatus": {
"type": "string",
"description": "Status of latest deployment. Possible values are \"waiting\", \"processing\", \"building\", \"ready\", and \"failed\".",
"x-example": "ready"
},
"scopes": {
"type": "array",
"description": "Allowed permission scopes.",
@ -27672,6 +27728,10 @@
"logging",
"runtime",
"deploymentId",
"deploymentCreatedAt",
"latestDeploymentId",
"latestDeploymentCreatedAt",
"latestDeploymentStatus",
"scopes",
"vars",
"events",
@ -27825,13 +27885,19 @@
"type": "string",
"description": "Default output directory of build.",
"x-example": ".\/dist"
},
"fallbackFile": {
"type": "string",
"description": "Name of fallback file to use instead of 404 page. If null, Appwrite 404 page will be displayed.",
"x-example": "index.html"
}
},
"required": [
"key",
"installCommand",
"buildCommand",
"outputDirectory"
"outputDirectory",
"fallbackFile"
]
},
"deployment": {
@ -27885,6 +27951,12 @@
"x-example": 128,
"format": "int32"
},
"totalSize": {
"type": "integer",
"description": "The total size in bytes (source and build output).",
"x-example": 128,
"format": "int32"
},
"buildId": {
"type": "string",
"description": "The current build ID.",
@ -27907,7 +27979,7 @@
},
"status": {
"type": "string",
"description": "The deployment status. Possible values are \"waiting\", \"processing\", \"building\", \"waiting\", \"ready\", and \"failed\".",
"description": "The deployment status. Possible values are \"waiting\", \"processing\", \"building\", \"ready\", and \"failed\".",
"x-example": "ready"
},
"buildLogs": {
@ -27982,6 +28054,7 @@
"entrypoint",
"sourceSize",
"buildSize",
"totalSize",
"buildId",
"activate",
"screenshotLight",

View file

@ -10322,7 +10322,7 @@
},
{
"name": "queries",
"description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: buildSize, sourceSize, buildDuration, status, activate, type",
"description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: buildSize, sourceSize, totalSize, buildDuration, status, activate, type",
"required": false,
"type": "array",
"collectionFormat": "multi",
@ -26230,7 +26230,7 @@
},
{
"name": "queries",
"description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: buildSize, sourceSize, buildDuration, status, activate, type",
"description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: buildSize, sourceSize, totalSize, buildDuration, status, activate, type",
"required": false,
"type": "array",
"collectionFormat": "multi",
@ -37455,6 +37455,36 @@
"description": "Site's active deployment ID.",
"x-example": "5e5ea5c16897e"
},
"deploymentCreatedAt": {
"type": "string",
"description": "Active deployment creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"deploymentScreenshotLight": {
"type": "string",
"description": "Screenshot of active deployment with light theme preference file ID.",
"x-example": "5e5ea5c16897e"
},
"deploymentScreenshotDark": {
"type": "string",
"description": "Screenshot of active deployment with dark theme preference file ID.",
"x-example": "5e5ea5c16897e"
},
"latestDeploymentId": {
"type": "string",
"description": "Site's latest deployment ID.",
"x-example": "5e5ea5c16897e"
},
"latestDeploymentCreatedAt": {
"type": "string",
"description": "Latest deployment creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"latestDeploymentStatus": {
"type": "string",
"description": "Status of latest deployment. Possible values are \"waiting\", \"processing\", \"building\", \"ready\", and \"failed\".",
"x-example": "ready"
},
"vars": {
"type": "array",
"description": "Site variables.",
@ -37540,6 +37570,12 @@
"live",
"framework",
"deploymentId",
"deploymentCreatedAt",
"deploymentScreenshotLight",
"deploymentScreenshotDark",
"latestDeploymentId",
"latestDeploymentCreatedAt",
"latestDeploymentStatus",
"vars",
"timeout",
"installCommand",
@ -37766,6 +37802,26 @@
"description": "Function's active deployment ID.",
"x-example": "5e5ea5c16897e"
},
"deploymentCreatedAt": {
"type": "string",
"description": "Active deployment creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"latestDeploymentId": {
"type": "string",
"description": "Function's latest deployment ID.",
"x-example": "5e5ea5c16897e"
},
"latestDeploymentCreatedAt": {
"type": "string",
"description": "Latest deployment creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"latestDeploymentStatus": {
"type": "string",
"description": "Status of latest deployment. Possible values are \"waiting\", \"processing\", \"building\", \"ready\", and \"failed\".",
"x-example": "ready"
},
"scopes": {
"type": "array",
"description": "Allowed permission scopes.",
@ -37859,6 +37915,10 @@
"logging",
"runtime",
"deploymentId",
"deploymentCreatedAt",
"latestDeploymentId",
"latestDeploymentCreatedAt",
"latestDeploymentStatus",
"scopes",
"vars",
"events",
@ -38513,13 +38573,19 @@
"type": "string",
"description": "Default output directory of build.",
"x-example": ".\/dist"
},
"fallbackFile": {
"type": "string",
"description": "Name of fallback file to use instead of 404 page. If null, Appwrite 404 page will be displayed.",
"x-example": "index.html"
}
},
"required": [
"key",
"installCommand",
"buildCommand",
"outputDirectory"
"outputDirectory",
"fallbackFile"
]
},
"deployment": {
@ -38573,6 +38639,12 @@
"x-example": 128,
"format": "int32"
},
"totalSize": {
"type": "integer",
"description": "The total size in bytes (source and build output).",
"x-example": 128,
"format": "int32"
},
"buildId": {
"type": "string",
"description": "The current build ID.",
@ -38595,7 +38667,7 @@
},
"status": {
"type": "string",
"description": "The deployment status. Possible values are \"waiting\", \"processing\", \"building\", \"waiting\", \"ready\", and \"failed\".",
"description": "The deployment status. Possible values are \"waiting\", \"processing\", \"building\", \"ready\", and \"failed\".",
"x-example": "ready"
},
"buildLogs": {
@ -38670,6 +38742,7 @@
"entrypoint",
"sourceSize",
"buildSize",
"totalSize",
"buildId",
"activate",
"screenshotLight",

View file

@ -9188,7 +9188,7 @@
},
{
"name": "queries",
"description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: buildSize, sourceSize, buildDuration, status, activate, type",
"description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: buildSize, sourceSize, totalSize, buildDuration, status, activate, type",
"required": false,
"type": "array",
"collectionFormat": "multi",
@ -18075,7 +18075,7 @@
},
{
"name": "queries",
"description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: buildSize, sourceSize, buildDuration, status, activate, type",
"description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: buildSize, sourceSize, totalSize, buildDuration, status, activate, type",
"required": false,
"type": "array",
"collectionFormat": "multi",
@ -27974,6 +27974,36 @@
"description": "Site's active deployment ID.",
"x-example": "5e5ea5c16897e"
},
"deploymentCreatedAt": {
"type": "string",
"description": "Active deployment creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"deploymentScreenshotLight": {
"type": "string",
"description": "Screenshot of active deployment with light theme preference file ID.",
"x-example": "5e5ea5c16897e"
},
"deploymentScreenshotDark": {
"type": "string",
"description": "Screenshot of active deployment with dark theme preference file ID.",
"x-example": "5e5ea5c16897e"
},
"latestDeploymentId": {
"type": "string",
"description": "Site's latest deployment ID.",
"x-example": "5e5ea5c16897e"
},
"latestDeploymentCreatedAt": {
"type": "string",
"description": "Latest deployment creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"latestDeploymentStatus": {
"type": "string",
"description": "Status of latest deployment. Possible values are \"waiting\", \"processing\", \"building\", \"ready\", and \"failed\".",
"x-example": "ready"
},
"vars": {
"type": "array",
"description": "Site variables.",
@ -28059,6 +28089,12 @@
"live",
"framework",
"deploymentId",
"deploymentCreatedAt",
"deploymentScreenshotLight",
"deploymentScreenshotDark",
"latestDeploymentId",
"latestDeploymentCreatedAt",
"latestDeploymentStatus",
"vars",
"timeout",
"installCommand",
@ -28132,6 +28168,26 @@
"description": "Function's active deployment ID.",
"x-example": "5e5ea5c16897e"
},
"deploymentCreatedAt": {
"type": "string",
"description": "Active deployment creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"latestDeploymentId": {
"type": "string",
"description": "Function's latest deployment ID.",
"x-example": "5e5ea5c16897e"
},
"latestDeploymentCreatedAt": {
"type": "string",
"description": "Latest deployment creation date in ISO 8601 format.",
"x-example": "2020-10-15T06:38:00.000+00:00"
},
"latestDeploymentStatus": {
"type": "string",
"description": "Status of latest deployment. Possible values are \"waiting\", \"processing\", \"building\", \"ready\", and \"failed\".",
"x-example": "ready"
},
"scopes": {
"type": "array",
"description": "Allowed permission scopes.",
@ -28225,6 +28281,10 @@
"logging",
"runtime",
"deploymentId",
"deploymentCreatedAt",
"latestDeploymentId",
"latestDeploymentCreatedAt",
"latestDeploymentStatus",
"scopes",
"vars",
"events",
@ -28379,13 +28439,19 @@
"type": "string",
"description": "Default output directory of build.",
"x-example": ".\/dist"
},
"fallbackFile": {
"type": "string",
"description": "Name of fallback file to use instead of 404 page. If null, Appwrite 404 page will be displayed.",
"x-example": "index.html"
}
},
"required": [
"key",
"installCommand",
"buildCommand",
"outputDirectory"
"outputDirectory",
"fallbackFile"
]
},
"deployment": {
@ -28439,6 +28505,12 @@
"x-example": 128,
"format": "int32"
},
"totalSize": {
"type": "integer",
"description": "The total size in bytes (source and build output).",
"x-example": 128,
"format": "int32"
},
"buildId": {
"type": "string",
"description": "The current build ID.",
@ -28461,7 +28533,7 @@
},
"status": {
"type": "string",
"description": "The deployment status. Possible values are \"waiting\", \"processing\", \"building\", \"waiting\", \"ready\", and \"failed\".",
"description": "The deployment status. Possible values are \"waiting\", \"processing\", \"building\", \"ready\", and \"failed\".",
"x-example": "ready"
},
"buildLogs": {
@ -28536,6 +28608,7 @@
"entrypoint",
"sourceSize",
"buildSize",
"totalSize",
"buildId",
"activate",
"screenshotLight",

View file

@ -253,6 +253,13 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId
'activate' => $activate,
]));
$resource = $resource
->setAttribute('latestDeploymentId', $deployment->getId())
->setAttribute('latestDeploymentInternalId', $deployment->getInternalId())
->setAttribute('latestDeploymentCreatedAt', $deployment->getCreatedAt())
->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', ''));
$dbForProject->updateDocument($resource->getCollection(), $resource->getId(), $resource);
if ($resource->getCollection() === 'sites') {
$projectId = $project->getId();

View file

@ -94,6 +94,13 @@ class Base extends Action
'activate' => $activate,
]));
$function = $function
->setAttribute('latestDeploymentId', $deployment->getId())
->setAttribute('latestDeploymentInternalId', $deployment->getInternalId())
->setAttribute('latestDeploymentCreatedAt', $deployment->getCreatedAt())
->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', ''));
$dbForProject->updateDocument('functions', $function->getId(), $function);
$queueForBuilds
->setType(BUILD_TYPE_DEPLOYMENT)
->setResource($function)
@ -185,6 +192,13 @@ class Base extends Action
'activate' => $activate,
]));
$site = $site
->setAttribute('latestDeploymentId', $deployment->getId())
->setAttribute('latestDeploymentInternalId', $deployment->getInternalId())
->setAttribute('latestDeploymentCreatedAt', $deployment->getCreatedAt())
->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', ''));
$dbForProject->updateDocument('sites', $site->getId(), $site);
$sitesDomain = System::getEnv('_APP_DOMAIN_SITES', '');
$domain = ID::unique() . "." . $sitesDomain;

View file

@ -240,6 +240,13 @@ class Create extends Action
'sourceMetadata' => $metadata,
'type' => $type
]));
$function = $function
->setAttribute('latestDeploymentId', $deployment->getId())
->setAttribute('latestDeploymentInternalId', $deployment->getInternalId())
->setAttribute('latestDeploymentCreatedAt', $deployment->getCreatedAt())
->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', ''));
$dbForProject->updateDocument('functions', $function->getId(), $function);
} else {
$deployment = $dbForProject->updateDocument('deployments', $deploymentId, $deployment->setAttribute('sourceSize', $fileSize)->setAttribute('sourceMetadata', $metadata));
}
@ -273,6 +280,13 @@ class Create extends Action
'sourceMetadata' => $metadata,
'type' => $type
]));
$function = $function
->setAttribute('latestDeploymentId', $deployment->getId())
->setAttribute('latestDeploymentInternalId', $deployment->getInternalId())
->setAttribute('latestDeploymentCreatedAt', $deployment->getCreatedAt())
->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', ''));
$dbForProject->updateDocument('functions', $function->getId(), $function);
} else {
$deployment = $dbForProject->updateDocument('deployments', $deploymentId, $deployment->setAttribute('sourceChunksUploaded', $chunksUploaded)->setAttribute('sourceMetadata', $metadata));
}

View file

@ -12,6 +12,7 @@ use Appwrite\SDK\Response as SDKResponse;
use Appwrite\Utopia\Response;
use Utopia\Database\Database;
use Utopia\Database\Document;
use Utopia\Database\Query;
use Utopia\Database\Validator\UID;
use Utopia\Platform\Action;
use Utopia\Platform\Scope\HTTP;
@ -96,6 +97,23 @@ class Delete extends Action
}
}
if ($function->getAttribute('latestDeploymentId') === $deployment->getId()) {
$latestDeployment = $dbForProject->findOne('deployments', [
Query::equal('resourceType', ['functions']),
Query::equal('resourceInternalId', [$function->getInternalId()]),
Query::orderDesc('$createdAt'),
]);
$function = $dbForProject->updateDocument(
'functions',
$function->getId(),
$function
->setAttribute('latestDeploymentCreatedAt', $latestDeployment->isEmpty() ? '' : $latestDeployment->getCreatedAt())
->setAttribute('latestDeploymentInternalId', $latestDeployment->isEmpty() ? '' : $latestDeployment->getInternalId())
->setAttribute('latestDeploymentId', $latestDeployment->isEmpty() ? '' : $latestDeployment->getId())
->setAttribute('latestDeploymentStatus', $latestDeployment->isEmpty() ? '' : $latestDeployment->getAttribute('status', ''))
);
}
if ($function->getAttribute('deploymentId') === $deployment->getId()) { // Reset function deployment
$function = $dbForProject->updateDocument('functions', $function->getId(), new Document(array_merge($function->getArrayCopy(), [
'deploymentId' => '',

View file

@ -113,6 +113,13 @@ class Create extends Action
'buildLogs' => '',
]));
$function = $function
->setAttribute('latestDeploymentId', $deployment->getId())
->setAttribute('latestDeploymentInternalId', $deployment->getInternalId())
->setAttribute('latestDeploymentCreatedAt', $deployment->getCreatedAt())
->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', ''));
$dbForProject->updateDocument('functions', $function->getId(), $function);
$queueForBuilds
->setType(BUILD_TYPE_DEPLOYMENT)
->setResource($function)

View file

@ -95,6 +95,11 @@ class Update extends Action
'status' => 'canceled'
]));
if ($deployment->getInternalId() === $function->getAttribute('latestDeploymentInternalId', '')) {
$function = $function->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', ''));
$dbForProject->updateDocument('functions', $function->getId(), $function);
}
try {
$executor = new Executor(App::getEnv('_APP_EXECUTOR_HOST'));
$executor->deleteRuntime($project->getId(), $deploymentId . "-build");

View file

@ -150,6 +150,13 @@ class Create extends Base
'activate' => $activate,
]));
$function = $function
->setAttribute('latestDeploymentId', $deployment->getId())
->setAttribute('latestDeploymentInternalId', $deployment->getInternalId())
->setAttribute('latestDeploymentCreatedAt', $deployment->getCreatedAt())
->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', ''));
$dbForProject->updateDocument('functions', $function->getId(), $function);
$queueForBuilds
->setType(BUILD_TYPE_DEPLOYMENT)
->setResource($function)

View file

@ -211,6 +211,11 @@ class Builds extends Action
$deployment->setAttribute('status', 'processing');
$deployment = $dbForProject->updateDocument('deployments', $deployment->getId(), $deployment);
if ($deployment->getInternalId() === $resource->getAttribute('latestDeploymentInternalId', '')) {
$resource = $resource->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', ''));
$dbForProject->updateDocument($resource->getCollection(), $resource->getId(), $resource);
}
$queueForRealtime
->setPayload($deployment->getArrayCopy())
->trigger();
@ -452,6 +457,11 @@ class Builds extends Action
$deployment->setAttribute('status', 'building');
$deployment = $dbForProject->updateDocument('deployments', $deployment->getId(), $deployment);
if ($deployment->getInternalId() === $resource->getAttribute('latestDeploymentInternalId', '')) {
$resource = $resource->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', ''));
$dbForProject->updateDocument($resource->getCollection(), $resource->getId(), $resource);
}
$queueForRealtime
->setPayload($deployment->getArrayCopy())
->trigger();
@ -732,6 +742,11 @@ class Builds extends Action
$deployment = $dbForProject->updateDocument('deployments', $deploymentId, $deployment);
if ($deployment->getInternalId() === $resource->getAttribute('latestDeploymentInternalId', '')) {
$resource = $resource->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', ''));
$dbForProject->updateDocument($resource->getCollection(), $resource->getId(), $resource);
}
$queueForRealtime
->setPayload($deployment->getArrayCopy())
->trigger();
@ -1017,6 +1032,11 @@ class Builds extends Action
$deployment = $dbForProject->updateDocument('deployments', $deploymentId, $deployment);
if ($deployment->getInternalId() === $resource->getAttribute('latestDeploymentInternalId', '')) {
$resource = $resource->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', ''));
$dbForProject->updateDocument($resource->getCollection(), $resource->getId(), $resource);
}
$queueForRealtime
->setPayload($deployment->getArrayCopy())
->trigger();

View file

@ -250,6 +250,13 @@ class Create extends Action
'type' => $type
]));
$site = $site
->setAttribute('latestDeploymentId', $deployment->getId())
->setAttribute('latestDeploymentInternalId', $deployment->getInternalId())
->setAttribute('latestDeploymentCreatedAt', $deployment->getCreatedAt())
->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', ''));
$dbForProject->updateDocument('sites', $site->getId(), $site);
$sitesDomain = System::getEnv('_APP_DOMAIN_SITES', '');
$domain = ID::unique() . "." . $sitesDomain;
@ -310,6 +317,13 @@ class Create extends Action
'type' => $type
]));
$site = $site
->setAttribute('latestDeploymentId', $deployment->getId())
->setAttribute('latestDeploymentInternalId', $deployment->getInternalId())
->setAttribute('latestDeploymentCreatedAt', $deployment->getCreatedAt())
->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', ''));
$dbForProject->updateDocument('sites', $site->getId(), $site);
$sitesDomain = System::getEnv('_APP_DOMAIN_SITES', '');
$domain = ID::unique() . "." . $sitesDomain;
$ruleId = md5($domain);

View file

@ -12,6 +12,7 @@ use Appwrite\SDK\Response as SDKResponse;
use Appwrite\Utopia\Response;
use Utopia\Database\Database;
use Utopia\Database\Document;
use Utopia\Database\Query;
use Utopia\Database\Validator\UID;
use Utopia\Platform\Action;
use Utopia\Platform\Scope\HTTP;
@ -96,6 +97,23 @@ class Delete extends Action
}
}
if ($site->getAttribute('latestDeploymentId') === $deployment->getId()) {
$latestDeployment = $dbForProject->findOne('deployments', [
Query::equal('resourceType', ['sites']),
Query::equal('resourceInternalId', [$site->getInternalId()]),
Query::orderDesc('$createdAt'),
]);
$site = $dbForProject->updateDocument(
'sites',
$site->getId(),
$site
->setAttribute('latestDeploymentCreatedAt', $latestDeployment->isEmpty() ? '' : $latestDeployment->getCreatedAt())
->setAttribute('latestDeploymentInternalId', $latestDeployment->isEmpty() ? '' : $latestDeployment->getInternalId())
->setAttribute('latestDeploymentId', $latestDeployment->isEmpty() ? '' : $latestDeployment->getId())
->setAttribute('latestDeploymentStatus', $latestDeployment->isEmpty() ? '' : $latestDeployment->getAttribute('status', ''))
);
}
if ($site->getAttribute('deploymentId') === $deployment->getId()) { // Reset site deployment
$site = $dbForProject->updateDocument('sites', $site->getId(), new Document(array_merge($site->getArrayCopy(), [
'deploymentId' => '',

View file

@ -126,6 +126,13 @@ class Create extends Action
'buildLogs' => '',
]));
$site = $site
->setAttribute('latestDeploymentId', $deployment->getId())
->setAttribute('latestDeploymentInternalId', $deployment->getInternalId())
->setAttribute('latestDeploymentCreatedAt', $deployment->getCreatedAt())
->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', ''));
$dbForProject->updateDocument('sites', $site->getId(), $site);
// Preview deployments for sites
$sitesDomain = System::getEnv('_APP_DOMAIN_SITES', '');
$domain = ID::unique() . "." . $sitesDomain;

View file

@ -93,6 +93,11 @@ class Update extends Action
'status' => 'canceled'
]));
if ($deployment->getInternalId() === $site->getAttribute('latestDeploymentInternalId', '')) {
$site = $site->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', ''));
$dbForProject->updateDocument('sites', $site->getId(), $site);
}
try {
$executor = new Executor(App::getEnv('_APP_EXECUTOR_HOST'));
$executor->deleteRuntime($project->getId(), $deploymentId . "-build");

View file

@ -161,6 +161,13 @@ class Create extends Base
'activate' => $activate,
]));
$site = $site
->setAttribute('latestDeploymentId', $deployment->getId())
->setAttribute('latestDeploymentInternalId', $deployment->getInternalId())
->setAttribute('latestDeploymentCreatedAt', $deployment->getCreatedAt())
->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', ''));
$dbForProject->updateDocument('sites', $site->getId(), $site);
$sitesDomain = System::getEnv('_APP_DOMAIN_SITES', '');
$domain = ID::unique() . "." . $sitesDomain;

View file

@ -96,7 +96,7 @@ class Deployment extends Model
])
->addRule('status', [
'type' => self::TYPE_STRING,
'description' => 'The deployment status. Possible values are "waiting", "processing", "building", "waiting", "ready", and "failed".',
'description' => 'The deployment status. Possible values are "waiting", "processing", "building", "ready", and "failed".',
'default' => '',
'example' => 'ready',
])

View file

@ -34,6 +34,12 @@ class FrameworkAdapter extends Model
'default' => '',
'example' => './dist',
])
->addRule('fallbackFile', [
'type' => self::TYPE_STRING,
'description' => 'Name of fallback file to use instead of 404 page. If null, Appwrite 404 page will be displayed.',
'default' => null,
'example' => 'index.html',
])
;
}

View file

@ -77,6 +77,24 @@ class Func extends Model
'default' => '',
'example' => self::TYPE_DATETIME_EXAMPLE,
])
->addRule('latestDeploymentId', [
'type' => self::TYPE_STRING,
'description' => 'Function\'s latest deployment ID.',
'default' => '',
'example' => '5e5ea5c16897e',
])
->addRule('latestDeploymentCreatedAt', [
'type' => self::TYPE_DATETIME,
'description' => 'Latest deployment creation date in ISO 8601 format.',
'default' => '',
'example' => self::TYPE_DATETIME_EXAMPLE,
])
->addRule('latestDeploymentStatus', [
'type' => self::TYPE_STRING,
'description' => 'Status of latest deployment. Possible values are "waiting", "processing", "building", "ready", and "failed".',
'default' => '',
'example' => 'ready',
])
->addRule('scopes', [
'type' => self::TYPE_STRING,
'description' => 'Allowed permission scopes.',

View file

@ -76,6 +76,24 @@ class Site extends Model
'default' => '',
'example' => '5e5ea5c16897e',
])
->addRule('latestDeploymentId', [
'type' => self::TYPE_STRING,
'description' => 'Site\'s latest deployment ID.',
'default' => '',
'example' => '5e5ea5c16897e',
])
->addRule('latestDeploymentCreatedAt', [
'type' => self::TYPE_DATETIME,
'description' => 'Latest deployment creation date in ISO 8601 format.',
'default' => '',
'example' => self::TYPE_DATETIME_EXAMPLE,
])
->addRule('latestDeploymentStatus', [
'type' => self::TYPE_STRING,
'description' => 'Status of latest deployment. Possible values are "waiting", "processing", "building", "ready", and "failed".',
'default' => '',
'example' => 'ready',
])
->addRule('vars', [
'type' => Response::MODEL_VARIABLE,
'description' => 'Site variables.',

View file

@ -231,6 +231,16 @@ trait FunctionsBase
return $deployment;
}
protected function deleteDeployment(string $functionId, string $deploymentId): mixed
{
$deployment = $this->client->call(Client::METHOD_DELETE, '/functions/' . $functionId . '/deployments/' . $deploymentId, array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), []);
return $deployment;
}
protected function createTemplateDeployment(string $functionId, mixed $params = []): mixed
{
$deployment = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/deployments/template', array_merge([

View file

@ -2101,12 +2101,27 @@ class FunctionsCustomServerTest extends Scope
]);
$this->assertNotEmpty($functionId);
$function = $this->getFunction($functionId);
$this->assertEquals(200, $function['headers']['status-code']);
$this->assertArrayHasKey('latestDeploymentId', $function['body']);
$this->assertArrayHasKey('latestDeploymentCreatedAt', $function['body']);
$this->assertArrayHasKey('latestDeploymentStatus', $function['body']);
$this->assertEmpty($function['body']['latestDeploymentId']);
$this->assertEmpty($function['body']['latestDeploymentCreatedAt']);
$this->assertEmpty($function['body']['latestDeploymentStatus']);
$deploymentId1 = $this->setupDeployment($functionId, [
'code' => $this->packageFunction('php-cookie'),
'activate' => true
]);
$this->assertNotEmpty($deploymentId1);
$function = $this->getFunction($functionId);
$this->assertEquals(200, $function['headers']['status-code']);
$this->assertEquals($deploymentId1, $function['body']['latestDeploymentId']);
$this->assertEquals('ready', $function['body']['latestDeploymentStatus']);
$execution = $this->createExecution($functionId, [
'headers' => [ 'cookie' => 'cookieName=cookieValue' ]
]);
@ -2120,6 +2135,11 @@ class FunctionsCustomServerTest extends Scope
]);
$this->assertNotEmpty($deploymentId2);
$function = $this->getFunction($functionId);
$this->assertEquals(200, $function['headers']['status-code']);
$this->assertEquals($deploymentId2, $function['body']['latestDeploymentId']);
$this->assertEquals('ready', $function['body']['latestDeploymentStatus']);
$execution = $this->createExecution($functionId);
$this->assertEquals(201, $execution['headers']['status-code']);
$this->assertNotEmpty($execution['body']['$id']);
@ -2128,6 +2148,8 @@ class FunctionsCustomServerTest extends Scope
$function = $this->getFunction($functionId);
$this->assertEquals(200, $function['headers']['status-code']);
$this->assertEquals($deploymentId2, $function['body']['deploymentId']);
$this->assertEquals($deploymentId2, $function['body']['latestDeploymentId']);
$this->assertEquals('ready', $function['body']['latestDeploymentStatus']);
$function = $this->updateFunctionDeployment($functionId, $deploymentId1);
$this->assertEquals(200, $function['headers']['status-code']);
@ -2136,6 +2158,8 @@ class FunctionsCustomServerTest extends Scope
$function = $this->getFunction($functionId);
$this->assertEquals(200, $function['headers']['status-code']);
$this->assertEquals($deploymentId1, $function['body']['deploymentId']);
$this->assertEquals($deploymentId2, $function['body']['latestDeploymentId']);
$this->assertEquals('ready', $function['body']['latestDeploymentStatus']);
$execution = $this->createExecution($functionId, [
'headers' => [ 'cookie' => 'cookieName=cookieValue' ]
@ -2144,6 +2168,14 @@ class FunctionsCustomServerTest extends Scope
$this->assertNotEmpty($execution['body']['$id']);
$this->assertStringContainsString('cookieValue', $execution['body']['responseBody']);
$deployment = $this->deleteDeployment($functionId, $deploymentId2);
$this->assertEquals(204, $deployment['headers']['status-code']);
$function = $this->getFunction($functionId);
$this->assertEquals(200, $function['headers']['status-code']);
$this->assertEquals($deploymentId1, $function['body']['latestDeploymentId']);
$this->assertEquals('ready', $function['body']['latestDeploymentStatus']);
$this->cleanupFunction($functionId);
}
}

View file

@ -244,6 +244,16 @@ trait SitesBase
return $deployment;
}
protected function deleteDeployment(string $siteId, string $deploymentId): mixed
{
$deployment = $this->client->call(Client::METHOD_DELETE, '/sites/' . $siteId . '/deployments/' . $deploymentId, array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), []);
return $deployment;
}
protected function setupDuplicateDeployment(string $siteId, string $deploymentId): string
{
$deployment = $this->createDuplicateDeployment($siteId, $deploymentId);

View file

@ -2057,6 +2057,15 @@ class SitesCustomServerTest extends Scope
]);
$this->assertNotEmpty($siteId);
$site = $this->getSite($siteId);
$this->assertEquals(200, $site['headers']['status-code']);
$this->assertArrayHasKey('latestDeploymentId', $site['body']);
$this->assertArrayHasKey('latestDeploymentCreatedAt', $site['body']);
$this->assertArrayHasKey('latestDeploymentStatus', $site['body']);
$this->assertEmpty($site['body']['latestDeploymentId']);
$this->assertEmpty($site['body']['latestDeploymentCreatedAt']);
$this->assertEmpty($site['body']['latestDeploymentStatus']);
$domain = $this->setupSiteDomain($siteId);
$this->assertNotEmpty($domain);
$proxyClient = new Client();
@ -2068,6 +2077,11 @@ class SitesCustomServerTest extends Scope
]);
$this->assertNotEmpty($deploymentId1);
$site = $this->getSite($siteId);
$this->assertEquals(200, $site['headers']['status-code']);
$this->assertEquals($deploymentId1, $site['body']['latestDeploymentId']);
$this->assertEquals('ready', $site['body']['latestDeploymentStatus']);
$response = $proxyClient->call(Client::METHOD_GET, '/');
$this->assertEquals(200, $response['headers']['status-code']);
$this->assertStringContainsString('Hello Appwrite', $response['body']);
@ -2078,26 +2092,43 @@ class SitesCustomServerTest extends Scope
]);
$this->assertNotEmpty($deploymentId2);
$site = $this->getSite($siteId);
$this->assertEquals(200, $site['headers']['status-code']);
$this->assertEquals($deploymentId2, $site['body']['latestDeploymentId']);
$this->assertEquals('ready', $site['body']['latestDeploymentStatus']);
$response = $proxyClient->call(Client::METHOD_GET, '/');
$this->assertEquals(200, $response['headers']['status-code']);
$this->assertStringContainsString('Index page', $response['body']);
$function = $this->getSite($siteId);
$this->assertEquals(200, $function['headers']['status-code']);
$this->assertEquals($deploymentId2, $function['body']['deploymentId']);
$site = $this->getSite($siteId);
$this->assertEquals(200, $site['headers']['status-code']);
$this->assertEquals($deploymentId2, $site['body']['deploymentId']);
$this->assertEquals($deploymentId2, $site['body']['latestDeploymentId']);
$this->assertEquals('ready', $site['body']['latestDeploymentStatus']);
$function = $this->updateSiteDeployment($siteId, $deploymentId1);
$this->assertEquals(200, $function['headers']['status-code']);
$this->assertEquals($deploymentId1, $function['body']['deploymentId']);
$site = $this->updateSiteDeployment($siteId, $deploymentId1);
$this->assertEquals(200, $site['headers']['status-code']);
$this->assertEquals($deploymentId1, $site['body']['deploymentId']);
$function = $this->getSite($siteId);
$this->assertEquals(200, $function['headers']['status-code']);
$this->assertEquals($deploymentId1, $function['body']['deploymentId']);
$site = $this->getSite($siteId);
$this->assertEquals(200, $site['headers']['status-code']);
$this->assertEquals($deploymentId1, $site['body']['deploymentId']);
$this->assertEquals($deploymentId2, $site['body']['latestDeploymentId']);
$this->assertEquals('ready', $site['body']['latestDeploymentStatus']);
$response = $proxyClient->call(Client::METHOD_GET, '/');
$this->assertEquals(200, $response['headers']['status-code']);
$this->assertStringContainsString('Hello Appwrite', $response['body']);
$deployment = $this->deleteDeployment($siteId, $deploymentId2);
$this->assertEquals(204, $deployment['headers']['status-code']);
$site = $this->getSite($siteId);
$this->assertEquals(200, $site['headers']['status-code']);
$this->assertEquals($deploymentId1, $site['body']['latestDeploymentId']);
$this->assertEquals('ready', $site['body']['latestDeploymentStatus']);
$this->cleanupSite($siteId);
}