From 6e16340f16c7388e3e2fdfe1c73659052d392c11 Mon Sep 17 00:00:00 2001 From: Atharva Deosthale Date: Sat, 13 Sep 2025 17:56:19 +0530 Subject: [PATCH] feat: add branch deployments to appwrite --- .../specs/open-api3-latest-console.json | 151 ++++++++++-- app/config/specs/open-api3-latest-server.json | 126 ++++++++-- app/config/specs/swagger2-latest-console.json | 159 ++++++++++-- app/config/specs/swagger2-latest-server.json | 134 ++++++++-- .../Modules/Functions/Workers/Builds.php | 12 +- .../Sites/Http/Deployments/Direct/Create.php | 231 ++++++++++++++++++ .../Platform/Modules/Sites/Services/Http.php | 2 + 7 files changed, 731 insertions(+), 84 deletions(-) create mode 100644 src/Appwrite/Platform/Modules/Sites/Http/Deployments/Direct/Create.php diff --git a/app/config/specs/open-api3-latest-console.json b/app/config/specs/open-api3-latest-console.json index 02d97fffc7..0de652e3fb 100644 --- a/app/config/specs/open-api3-latest-console.json +++ b/app/config/specs/open-api3-latest-console.json @@ -4888,7 +4888,7 @@ "x-appwrite": { "method": "getResource", "group": null, - "weight": 496, + "weight": 497, "cookies": false, "type": "", "demo": "console\/get-resource.md", @@ -28209,7 +28209,7 @@ "x-appwrite": { "method": "listRules", "group": null, - "weight": 502, + "weight": 503, "cookies": false, "type": "", "demo": "proxy\/list-rules.md", @@ -28283,7 +28283,7 @@ "x-appwrite": { "method": "createAPIRule", "group": null, - "weight": 497, + "weight": 498, "cookies": false, "type": "", "demo": "proxy\/create-api-rule.md", @@ -28350,7 +28350,7 @@ "x-appwrite": { "method": "createFunctionRule", "group": null, - "weight": 499, + "weight": 500, "cookies": false, "type": "", "demo": "proxy\/create-function-rule.md", @@ -28428,7 +28428,7 @@ "x-appwrite": { "method": "createRedirectRule", "group": null, - "weight": 500, + "weight": 501, "cookies": false, "type": "", "demo": "proxy\/create-redirect-rule.md", @@ -28541,7 +28541,7 @@ "x-appwrite": { "method": "createSiteRule", "group": null, - "weight": 498, + "weight": 499, "cookies": false, "type": "", "demo": "proxy\/create-site-rule.md", @@ -28619,7 +28619,7 @@ "x-appwrite": { "method": "getRule", "group": null, - "weight": 501, + "weight": 502, "cookies": false, "type": "", "demo": "proxy\/get-rule.md", @@ -28670,7 +28670,7 @@ "x-appwrite": { "method": "deleteRule", "group": null, - "weight": 503, + "weight": 504, "cookies": false, "type": "", "demo": "proxy\/delete-rule.md", @@ -28730,7 +28730,7 @@ "x-appwrite": { "method": "updateRuleVerification", "group": null, - "weight": 504, + "weight": 505, "cookies": false, "type": "", "demo": "proxy\/update-rule-verification.md", @@ -29085,6 +29085,103 @@ } } }, + "\/sites\/direct": { + "post": { + "summary": "Create direct deployment", + "operationId": "sitesCreateDirectDeployment", + "tags": [ + "sites" + ], + "description": "Create a deployment directly from a repository branch.", + "responses": { + "202": { + "description": "Deployment", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/deployment" + } + } + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "createDirectDeployment", + "group": "deployments", + "weight": 483, + "cookies": false, + "type": "", + "demo": "sites\/create-direct-deployment.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a deployment directly from a repository branch.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "siteId": { + "type": "string", + "description": "Site ID.", + "x-example": "" + }, + "repository": { + "type": "string", + "description": "Repository name of the template.", + "x-example": "" + }, + "owner": { + "type": "string", + "description": "The name of the owner of the template.", + "x-example": "" + }, + "rootDirectory": { + "type": "string", + "description": "Path to site code in the template repo.", + "x-example": "" + }, + "branch": { + "type": "string", + "description": "Branch to create deployment from.", + "x-example": "" + }, + "activate": { + "type": "boolean", + "description": "Automatically activate the deployment when it is finished building.", + "x-example": false + } + }, + "required": [ + "siteId", + "repository", + "owner", + "rootDirectory", + "branch" + ] + } + } + } + } + } + }, "\/sites\/frameworks": { "get": { "summary": "List frameworks", @@ -29158,7 +29255,7 @@ "x-appwrite": { "method": "listSpecifications", "group": "frameworks", - "weight": 495, + "weight": 496, "cookies": false, "type": "", "demo": "sites\/list-specifications.md", @@ -29208,7 +29305,7 @@ "x-appwrite": { "method": "listTemplates", "group": "templates", - "weight": 491, + "weight": 492, "cookies": false, "type": "", "demo": "sites\/list-templates.md", @@ -29308,7 +29405,7 @@ "x-appwrite": { "method": "getTemplate", "group": "templates", - "weight": 492, + "weight": 493, "cookies": false, "type": "", "demo": "sites\/get-template.md", @@ -29368,7 +29465,7 @@ "x-appwrite": { "method": "listUsage", "group": null, - "weight": 493, + "weight": 494, "cookies": false, "type": "", "demo": "sites\/list-usage.md", @@ -30637,7 +30734,7 @@ "x-appwrite": { "method": "listLogs", "group": "logs", - "weight": 484, + "weight": 485, "cookies": false, "type": "", "demo": "sites\/list-logs.md", @@ -30708,7 +30805,7 @@ "x-appwrite": { "method": "getLog", "group": "logs", - "weight": 483, + "weight": 484, "cookies": false, "type": "", "demo": "sites\/get-log.md", @@ -30770,7 +30867,7 @@ "x-appwrite": { "method": "deleteLog", "group": "logs", - "weight": 485, + "weight": 486, "cookies": false, "type": "", "demo": "sites\/delete-log.md", @@ -30841,7 +30938,7 @@ "x-appwrite": { "method": "getUsage", "group": null, - "weight": 494, + "weight": 495, "cookies": false, "type": "", "demo": "sites\/get-usage.md", @@ -30923,7 +31020,7 @@ "x-appwrite": { "method": "listVariables", "group": "variables", - "weight": 488, + "weight": 489, "cookies": false, "type": "", "demo": "sites\/list-variables.md", @@ -30982,7 +31079,7 @@ "x-appwrite": { "method": "createVariable", "group": "variables", - "weight": 486, + "weight": 487, "cookies": false, "type": "", "demo": "sites\/create-variable.md", @@ -31073,7 +31170,7 @@ "x-appwrite": { "method": "getVariable", "group": "variables", - "weight": 487, + "weight": 488, "cookies": false, "type": "", "demo": "sites\/get-variable.md", @@ -31142,7 +31239,7 @@ "x-appwrite": { "method": "updateVariable", "group": "variables", - "weight": 489, + "weight": 490, "cookies": false, "type": "", "demo": "sites\/update-variable.md", @@ -31233,7 +31330,7 @@ "x-appwrite": { "method": "deleteVariable", "group": "variables", - "weight": 490, + "weight": 491, "cookies": false, "type": "", "demo": "sites\/delete-variable.md", @@ -39984,7 +40081,7 @@ "x-appwrite": { "method": "list", "group": "files", - "weight": 507, + "weight": 508, "cookies": false, "type": "", "demo": "tokens\/list.md", @@ -40064,7 +40161,7 @@ "x-appwrite": { "method": "createFileToken", "group": "files", - "weight": 505, + "weight": 506, "cookies": false, "type": "", "demo": "tokens\/create-file-token.md", @@ -40153,7 +40250,7 @@ "x-appwrite": { "method": "get", "group": "tokens", - "weight": 506, + "weight": 507, "cookies": false, "type": "", "demo": "tokens\/get.md", @@ -40213,7 +40310,7 @@ "x-appwrite": { "method": "update", "group": "tokens", - "weight": 508, + "weight": 509, "cookies": false, "type": "", "demo": "tokens\/update.md", @@ -40283,7 +40380,7 @@ "x-appwrite": { "method": "delete", "group": "tokens", - "weight": 509, + "weight": 510, "cookies": false, "type": "", "demo": "tokens\/delete.md", diff --git a/app/config/specs/open-api3-latest-server.json b/app/config/specs/open-api3-latest-server.json index 09d53dbdf0..d8d7178eb2 100644 --- a/app/config/specs/open-api3-latest-server.json +++ b/app/config/specs/open-api3-latest-server.json @@ -20014,6 +20014,104 @@ } } }, + "\/sites\/direct": { + "post": { + "summary": "Create direct deployment", + "operationId": "sitesCreateDirectDeployment", + "tags": [ + "sites" + ], + "description": "Create a deployment directly from a repository branch.", + "responses": { + "202": { + "description": "Deployment", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/deployment" + } + } + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "createDirectDeployment", + "group": "deployments", + "weight": 483, + "cookies": false, + "type": "", + "demo": "sites\/create-direct-deployment.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a deployment directly from a repository branch.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "siteId": { + "type": "string", + "description": "Site ID.", + "x-example": "" + }, + "repository": { + "type": "string", + "description": "Repository name of the template.", + "x-example": "" + }, + "owner": { + "type": "string", + "description": "The name of the owner of the template.", + "x-example": "" + }, + "rootDirectory": { + "type": "string", + "description": "Path to site code in the template repo.", + "x-example": "" + }, + "branch": { + "type": "string", + "description": "Branch to create deployment from.", + "x-example": "" + }, + "activate": { + "type": "boolean", + "description": "Automatically activate the deployment when it is finished building.", + "x-example": false + } + }, + "required": [ + "siteId", + "repository", + "owner", + "rootDirectory", + "branch" + ] + } + } + } + } + } + }, "\/sites\/frameworks": { "get": { "summary": "List frameworks", @@ -20088,7 +20186,7 @@ "x-appwrite": { "method": "listSpecifications", "group": "frameworks", - "weight": 495, + "weight": 496, "cookies": false, "type": "", "demo": "sites\/list-specifications.md", @@ -21349,7 +21447,7 @@ "x-appwrite": { "method": "listLogs", "group": "logs", - "weight": 484, + "weight": 485, "cookies": false, "type": "", "demo": "sites\/list-logs.md", @@ -21421,7 +21519,7 @@ "x-appwrite": { "method": "getLog", "group": "logs", - "weight": 483, + "weight": 484, "cookies": false, "type": "", "demo": "sites\/get-log.md", @@ -21484,7 +21582,7 @@ "x-appwrite": { "method": "deleteLog", "group": "logs", - "weight": 485, + "weight": 486, "cookies": false, "type": "", "demo": "sites\/delete-log.md", @@ -21556,7 +21654,7 @@ "x-appwrite": { "method": "listVariables", "group": "variables", - "weight": 488, + "weight": 489, "cookies": false, "type": "", "demo": "sites\/list-variables.md", @@ -21616,7 +21714,7 @@ "x-appwrite": { "method": "createVariable", "group": "variables", - "weight": 486, + "weight": 487, "cookies": false, "type": "", "demo": "sites\/create-variable.md", @@ -21708,7 +21806,7 @@ "x-appwrite": { "method": "getVariable", "group": "variables", - "weight": 487, + "weight": 488, "cookies": false, "type": "", "demo": "sites\/get-variable.md", @@ -21778,7 +21876,7 @@ "x-appwrite": { "method": "updateVariable", "group": "variables", - "weight": 489, + "weight": 490, "cookies": false, "type": "", "demo": "sites\/update-variable.md", @@ -21870,7 +21968,7 @@ "x-appwrite": { "method": "deleteVariable", "group": "variables", - "weight": 490, + "weight": 491, "cookies": false, "type": "", "demo": "sites\/delete-variable.md", @@ -30024,7 +30122,7 @@ "x-appwrite": { "method": "list", "group": "files", - "weight": 507, + "weight": 508, "cookies": false, "type": "", "demo": "tokens\/list.md", @@ -30105,7 +30203,7 @@ "x-appwrite": { "method": "createFileToken", "group": "files", - "weight": 505, + "weight": 506, "cookies": false, "type": "", "demo": "tokens\/create-file-token.md", @@ -30195,7 +30293,7 @@ "x-appwrite": { "method": "get", "group": "tokens", - "weight": 506, + "weight": 507, "cookies": false, "type": "", "demo": "tokens\/get.md", @@ -30256,7 +30354,7 @@ "x-appwrite": { "method": "update", "group": "tokens", - "weight": 508, + "weight": 509, "cookies": false, "type": "", "demo": "tokens\/update.md", @@ -30327,7 +30425,7 @@ "x-appwrite": { "method": "delete", "group": "tokens", - "weight": 509, + "weight": 510, "cookies": false, "type": "", "demo": "tokens\/delete.md", diff --git a/app/config/specs/swagger2-latest-console.json b/app/config/specs/swagger2-latest-console.json index 6d5721c73b..22823cd40e 100644 --- a/app/config/specs/swagger2-latest-console.json +++ b/app/config/specs/swagger2-latest-console.json @@ -5052,7 +5052,7 @@ "x-appwrite": { "method": "getResource", "group": null, - "weight": 496, + "weight": 497, "cookies": false, "type": "", "demo": "console\/get-resource.md", @@ -28351,7 +28351,7 @@ "x-appwrite": { "method": "listRules", "group": null, - "weight": 502, + "weight": 503, "cookies": false, "type": "", "demo": "proxy\/list-rules.md", @@ -28424,7 +28424,7 @@ "x-appwrite": { "method": "createAPIRule", "group": null, - "weight": 497, + "weight": 498, "cookies": false, "type": "", "demo": "proxy\/create-api-rule.md", @@ -28494,7 +28494,7 @@ "x-appwrite": { "method": "createFunctionRule", "group": null, - "weight": 499, + "weight": 500, "cookies": false, "type": "", "demo": "proxy\/create-function-rule.md", @@ -28577,7 +28577,7 @@ "x-appwrite": { "method": "createRedirectRule", "group": null, - "weight": 500, + "weight": 501, "cookies": false, "type": "", "demo": "proxy\/create-redirect-rule.md", @@ -28697,7 +28697,7 @@ "x-appwrite": { "method": "createSiteRule", "group": null, - "weight": 498, + "weight": 499, "cookies": false, "type": "", "demo": "proxy\/create-site-rule.md", @@ -28778,7 +28778,7 @@ "x-appwrite": { "method": "getRule", "group": null, - "weight": 501, + "weight": 502, "cookies": false, "type": "", "demo": "proxy\/get-rule.md", @@ -28831,7 +28831,7 @@ "x-appwrite": { "method": "deleteRule", "group": null, - "weight": 503, + "weight": 504, "cookies": false, "type": "", "demo": "proxy\/delete-rule.md", @@ -28891,7 +28891,7 @@ "x-appwrite": { "method": "updateRuleVerification", "group": null, - "weight": 504, + "weight": 505, "cookies": false, "type": "", "demo": "proxy\/update-rule-verification.md", @@ -29264,6 +29264,111 @@ ] } }, + "\/sites\/direct": { + "post": { + "summary": "Create direct deployment", + "operationId": "sitesCreateDirectDeployment", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "Create a deployment directly from a repository branch.", + "responses": { + "202": { + "description": "Deployment", + "schema": { + "$ref": "#\/definitions\/deployment" + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "createDirectDeployment", + "group": "deployments", + "weight": 483, + "cookies": false, + "type": "", + "demo": "sites\/create-direct-deployment.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a deployment directly from a repository branch.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "siteId": { + "type": "string", + "description": "Site ID.", + "default": null, + "x-example": "" + }, + "repository": { + "type": "string", + "description": "Repository name of the template.", + "default": null, + "x-example": "" + }, + "owner": { + "type": "string", + "description": "The name of the owner of the template.", + "default": null, + "x-example": "" + }, + "rootDirectory": { + "type": "string", + "description": "Path to site code in the template repo.", + "default": null, + "x-example": "" + }, + "branch": { + "type": "string", + "description": "Branch to create deployment from.", + "default": null, + "x-example": "" + }, + "activate": { + "type": "boolean", + "description": "Automatically activate the deployment when it is finished building.", + "default": true, + "x-example": false + } + }, + "required": [ + "siteId", + "repository", + "owner", + "rootDirectory", + "branch" + ] + } + } + ] + } + }, "\/sites\/frameworks": { "get": { "summary": "List frameworks", @@ -29337,7 +29442,7 @@ "x-appwrite": { "method": "listSpecifications", "group": "frameworks", - "weight": 495, + "weight": 496, "cookies": false, "type": "", "demo": "sites\/list-specifications.md", @@ -29387,7 +29492,7 @@ "x-appwrite": { "method": "listTemplates", "group": "templates", - "weight": 491, + "weight": 492, "cookies": false, "type": "", "demo": "sites\/list-templates.md", @@ -29481,7 +29586,7 @@ "x-appwrite": { "method": "getTemplate", "group": "templates", - "weight": 492, + "weight": 493, "cookies": false, "type": "", "demo": "sites\/get-template.md", @@ -29539,7 +29644,7 @@ "x-appwrite": { "method": "listUsage", "group": null, - "weight": 493, + "weight": 494, "cookies": false, "type": "", "demo": "sites\/list-usage.md", @@ -30811,7 +30916,7 @@ "x-appwrite": { "method": "listLogs", "group": "logs", - "weight": 484, + "weight": 485, "cookies": false, "type": "", "demo": "sites\/list-logs.md", @@ -30882,7 +30987,7 @@ "x-appwrite": { "method": "getLog", "group": "logs", - "weight": 483, + "weight": 484, "cookies": false, "type": "", "demo": "sites\/get-log.md", @@ -30946,7 +31051,7 @@ "x-appwrite": { "method": "deleteLog", "group": "logs", - "weight": 485, + "weight": 486, "cookies": false, "type": "", "demo": "sites\/delete-log.md", @@ -31013,7 +31118,7 @@ "x-appwrite": { "method": "getUsage", "group": null, - "weight": 494, + "weight": 495, "cookies": false, "type": "", "demo": "sites\/get-usage.md", @@ -31091,7 +31196,7 @@ "x-appwrite": { "method": "listVariables", "group": "variables", - "weight": 488, + "weight": 489, "cookies": false, "type": "", "demo": "sites\/list-variables.md", @@ -31150,7 +31255,7 @@ "x-appwrite": { "method": "createVariable", "group": "variables", - "weight": 486, + "weight": 487, "cookies": false, "type": "", "demo": "sites\/create-variable.md", @@ -31240,7 +31345,7 @@ "x-appwrite": { "method": "getVariable", "group": "variables", - "weight": 487, + "weight": 488, "cookies": false, "type": "", "demo": "sites\/get-variable.md", @@ -31307,7 +31412,7 @@ "x-appwrite": { "method": "updateVariable", "group": "variables", - "weight": 489, + "weight": 490, "cookies": false, "type": "", "demo": "sites\/update-variable.md", @@ -31399,7 +31504,7 @@ "x-appwrite": { "method": "deleteVariable", "group": "variables", - "weight": 490, + "weight": 491, "cookies": false, "type": "", "demo": "sites\/delete-variable.md", @@ -39916,7 +40021,7 @@ "x-appwrite": { "method": "list", "group": "files", - "weight": 507, + "weight": 508, "cookies": false, "type": "", "demo": "tokens\/list.md", @@ -39996,7 +40101,7 @@ "x-appwrite": { "method": "createFileToken", "group": "files", - "weight": 505, + "weight": 506, "cookies": false, "type": "", "demo": "tokens\/create-file-token.md", @@ -40080,7 +40185,7 @@ "x-appwrite": { "method": "get", "group": "tokens", - "weight": 506, + "weight": 507, "cookies": false, "type": "", "demo": "tokens\/get.md", @@ -40140,7 +40245,7 @@ "x-appwrite": { "method": "update", "group": "tokens", - "weight": 508, + "weight": 509, "cookies": false, "type": "", "demo": "tokens\/update.md", @@ -40211,7 +40316,7 @@ "x-appwrite": { "method": "delete", "group": "tokens", - "weight": 509, + "weight": 510, "cookies": false, "type": "", "demo": "tokens\/delete.md", diff --git a/app/config/specs/swagger2-latest-server.json b/app/config/specs/swagger2-latest-server.json index 98077f1050..c7a5a20c24 100644 --- a/app/config/specs/swagger2-latest-server.json +++ b/app/config/specs/swagger2-latest-server.json @@ -20226,6 +20226,112 @@ ] } }, + "\/sites\/direct": { + "post": { + "summary": "Create direct deployment", + "operationId": "sitesCreateDirectDeployment", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "Create a deployment directly from a repository branch.", + "responses": { + "202": { + "description": "Deployment", + "schema": { + "$ref": "#\/definitions\/deployment" + } + } + }, + "deprecated": false, + "x-appwrite": { + "method": "createDirectDeployment", + "group": "deployments", + "weight": 483, + "cookies": false, + "type": "", + "demo": "sites\/create-direct-deployment.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a deployment directly from a repository branch.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "siteId": { + "type": "string", + "description": "Site ID.", + "default": null, + "x-example": "" + }, + "repository": { + "type": "string", + "description": "Repository name of the template.", + "default": null, + "x-example": "" + }, + "owner": { + "type": "string", + "description": "The name of the owner of the template.", + "default": null, + "x-example": "" + }, + "rootDirectory": { + "type": "string", + "description": "Path to site code in the template repo.", + "default": null, + "x-example": "" + }, + "branch": { + "type": "string", + "description": "Branch to create deployment from.", + "default": null, + "x-example": "" + }, + "activate": { + "type": "boolean", + "description": "Automatically activate the deployment when it is finished building.", + "default": true, + "x-example": false + } + }, + "required": [ + "siteId", + "repository", + "owner", + "rootDirectory", + "branch" + ] + } + } + ] + } + }, "\/sites\/frameworks": { "get": { "summary": "List frameworks", @@ -20300,7 +20406,7 @@ "x-appwrite": { "method": "listSpecifications", "group": "frameworks", - "weight": 495, + "weight": 496, "cookies": false, "type": "", "demo": "sites\/list-specifications.md", @@ -21566,7 +21672,7 @@ "x-appwrite": { "method": "listLogs", "group": "logs", - "weight": 484, + "weight": 485, "cookies": false, "type": "", "demo": "sites\/list-logs.md", @@ -21638,7 +21744,7 @@ "x-appwrite": { "method": "getLog", "group": "logs", - "weight": 483, + "weight": 484, "cookies": false, "type": "", "demo": "sites\/get-log.md", @@ -21703,7 +21809,7 @@ "x-appwrite": { "method": "deleteLog", "group": "logs", - "weight": 485, + "weight": 486, "cookies": false, "type": "", "demo": "sites\/delete-log.md", @@ -21771,7 +21877,7 @@ "x-appwrite": { "method": "listVariables", "group": "variables", - "weight": 488, + "weight": 489, "cookies": false, "type": "", "demo": "sites\/list-variables.md", @@ -21831,7 +21937,7 @@ "x-appwrite": { "method": "createVariable", "group": "variables", - "weight": 486, + "weight": 487, "cookies": false, "type": "", "demo": "sites\/create-variable.md", @@ -21922,7 +22028,7 @@ "x-appwrite": { "method": "getVariable", "group": "variables", - "weight": 487, + "weight": 488, "cookies": false, "type": "", "demo": "sites\/get-variable.md", @@ -21990,7 +22096,7 @@ "x-appwrite": { "method": "updateVariable", "group": "variables", - "weight": 489, + "weight": 490, "cookies": false, "type": "", "demo": "sites\/update-variable.md", @@ -22083,7 +22189,7 @@ "x-appwrite": { "method": "deleteVariable", "group": "variables", - "weight": 490, + "weight": 491, "cookies": false, "type": "", "demo": "sites\/delete-variable.md", @@ -30036,7 +30142,7 @@ "x-appwrite": { "method": "list", "group": "files", - "weight": 507, + "weight": 508, "cookies": false, "type": "", "demo": "tokens\/list.md", @@ -30117,7 +30223,7 @@ "x-appwrite": { "method": "createFileToken", "group": "files", - "weight": 505, + "weight": 506, "cookies": false, "type": "", "demo": "tokens\/create-file-token.md", @@ -30202,7 +30308,7 @@ "x-appwrite": { "method": "get", "group": "tokens", - "weight": 506, + "weight": 507, "cookies": false, "type": "", "demo": "tokens\/get.md", @@ -30263,7 +30369,7 @@ "x-appwrite": { "method": "update", "group": "tokens", - "weight": 508, + "weight": 509, "cookies": false, "type": "", "demo": "tokens\/update.md", @@ -30335,7 +30441,7 @@ "x-appwrite": { "method": "delete", "group": "tokens", - "weight": 509, + "weight": 510, "cookies": false, "type": "", "demo": "tokens\/delete.md", diff --git a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php index 9547a752ef..2ac05eae77 100644 --- a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php +++ b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php @@ -311,19 +311,27 @@ class Builds extends Action $templateRepositoryName = $template->getAttribute('repositoryName', ''); $templateOwnerName = $template->getAttribute('ownerName', ''); $templateVersion = $template->getAttribute('version', ''); + $templateBranch = $template->getAttribute('branch', ''); $templateRootDirectory = $template->getAttribute('rootDirectory', ''); $templateRootDirectory = \rtrim($templateRootDirectory, '/'); $templateRootDirectory = \ltrim($templateRootDirectory, '.'); $templateRootDirectory = \ltrim($templateRootDirectory, '/'); - if (!empty($templateRepositoryName) && !empty($templateOwnerName) && !empty($templateVersion)) { + if (!empty($templateRepositoryName) && !empty($templateOwnerName) && (!empty($templateVersion) || !empty($templateBranch))) { $stdout = ''; $stderr = ''; // Clone template repo $tmpTemplateDirectory = '/tmp/builds/' . $deploymentId . '-template'; - $gitCloneCommandForTemplate = $github->generateCloneCommand($templateOwnerName, $templateRepositoryName, $templateVersion, GitHub::CLONE_TYPE_TAG, $tmpTemplateDirectory, $templateRootDirectory); + + if(empty($templateVersion)) { + $gitCloneCommandForTemplate = $github->generateCloneCommand($templateOwnerName, $templateRepositoryName, $templateBranch, GitHub::CLONE_TYPE_BRANCH, $tmpTemplateDirectory, $templateRootDirectory); + } else { + // True template + $gitCloneCommandForTemplate = $github->generateCloneCommand($templateOwnerName, $templateRepositoryName, $templateVersion, GitHub::CLONE_TYPE_TAG, $tmpTemplateDirectory, $templateRootDirectory); + } + $exit = Console::execute($gitCloneCommandForTemplate, '', $stdout, $stderr); if ($exit !== 0) { diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Direct/Create.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Direct/Create.php new file mode 100644 index 0000000000..092a7702df --- /dev/null +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Direct/Create.php @@ -0,0 +1,231 @@ +setHttpMethod(Action::HTTP_REQUEST_METHOD_POST) + ->setHttpPath('/v1/sites/direct') + ->desc('Create direct deployment') + ->groups(['api', 'sites']) + ->label('scope', 'sites.write') + ->label('resourceType', RESOURCE_TYPE_SITES) + ->label('event', 'sites.[siteId].deployments.[deploymentId].create') + ->label('audits.event', 'deployment.create') + ->label('audits.resource', 'site/{request.siteId}') + ->label('sdk', new Method( + namespace: 'sites', + group: 'deployments', + name: 'createDirectDeployment', + description: <<param('siteId', '', new UID(), 'Site ID.') + ->param('repository', '', new Text(128, 0), 'Repository name of the template.') + ->param('owner', '', new Text(128, 0), 'The name of the owner of the template.') + ->param('rootDirectory', '', new Text(128, 0), 'Path to site code in the template repo.') + ->param('branch', '', new Text(128, 0), 'Branch to create deployment from.') + ->param('activate', true, new Boolean(), 'Automatically activate the deployment when it is finished building.', true) + ->inject('request') + ->inject('response') + ->inject('dbForProject') + ->inject('dbForPlatform') + ->inject('project') + ->inject('queueForEvents') + ->inject('queueForBuilds') + ->inject('gitHub') + ->callback($this->action(...)); + } + + public function action( + string $siteId, + string $repository, + string $owner, + string $rootDirectory, + string $branch, + bool $activate, + Request $request, + Response $response, + Database $dbForProject, + Database $dbForPlatform, + Document $project, + Event $queueForEvents, + Build $queueForBuilds, + GitHub $github + ) { + $site = $dbForProject->getDocument('sites', $siteId); + + if ($site->isEmpty()) { + throw new Exception(Exception::SITE_NOT_FOUND); + } + + $template = new Document([ + 'repositoryName' => $repository, + 'ownerName' => $owner, + 'rootDirectory' => $rootDirectory, + 'branch' => $branch + ]); + + + if (!empty($site->getAttribute('providerRepositoryId'))) { + $installation = $dbForPlatform->getDocument('installations', $site->getAttribute('installationId')); + + $deployment = $this->redeployVcsSite( + request: $request, + site: $site, + project: $project, + installation: $installation, + dbForProject: $dbForProject, + dbForPlatform: $dbForPlatform, + queueForBuilds: $queueForBuilds, + template: $template, + github: $github, + activate: $activate, + ); + + $queueForEvents + ->setParam('siteId', $site->getId()) + ->setParam('deploymentId', $deployment->getId()); + + $response + ->setStatusCode(Response::STATUS_CODE_ACCEPTED) + ->dynamic($deployment, Response::MODEL_DEPLOYMENT); + + return; + } + + $branchUrl = "https://github.com/$owner/$repository/tree/$branch"; + $repositoryUrl = "https://github.com/$owner/$repository"; + + try { + $commitDetails = $github->getLatestCommit($owner, $repository, $branch); + } catch (\Throwable $error) { + // Ignore; deployment can continue + } + + $commands = []; + if (!empty($site->getAttribute('installCommand', ''))) { + $commands[] = $site->getAttribute('installCommand', ''); + } + if (!empty($site->getAttribute('buildCommand', ''))) { + $commands[] = $site->getAttribute('buildCommand', ''); + } + + $deploymentId = ID::unique(); + $deployment = $dbForProject->createDocument('deployments', new Document([ + '$id' => $deploymentId, + '$permissions' => [ + Permission::read(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + 'resourceId' => $site->getId(), + 'resourceInternalId' => $site->getSequence(), + 'resourceType' => 'sites', + 'buildCommands' => \implode(' && ', $commands), + 'buildOutput' => $site->getAttribute('outputDirectory', ''), + 'adapter' => $site->getAttribute('adapter', ''), + 'fallbackFile' => $site->getAttribute('fallbackFile', ''), + 'providerRepositoryName' => $repository, + 'providerRepositoryOwner' => $owner, + 'providerRepositoryUrl' => $repositoryUrl, + 'providerBranchUrl' => $branchUrl, + 'providerBranch' => $branch, + 'providerCommitHash' => $commitDetails['commitHash'] ?? '', + 'providerCommitAuthorUrl' => $commitDetails['commitAuthorUrl'] ?? '', + 'providerCommitAuthor' => $commitDetails['commitAuthor'] ?? '', + 'providerCommitMessage' => mb_strimwidth($commitDetails['commitMessage'] ?? '', 0, 255, '...'), + 'providerCommitUrl' => $commitDetails['commitUrl'] ?? '', + 'type' => 'vcs', + 'activate' => $activate, + ])); + + $site = $site + ->setAttribute('latestDeploymentId', $deployment->getId()) + ->setAttribute('latestDeploymentInternalId', $deployment->getSequence()) + ->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; + + // TODO: @christyjacob remove once we migrate the rules in 1.7.x + $ruleId = System::getEnv('_APP_RULES_FORMAT') === 'md5' ? md5($domain) : ID::unique(); + + Authorization::skip( + fn () => $dbForPlatform->createDocument('rules', new Document([ + '$id' => $ruleId, + 'projectId' => $project->getId(), + 'projectInternalId' => $project->getSequence(), + 'domain' => $domain, + 'type' => 'deployment', + 'trigger' => 'deployment', + 'deploymentId' => $deployment->isEmpty() ? '' : $deployment->getId(), + 'deploymentInternalId' => $deployment->isEmpty() ? '' : $deployment->getSequence(), + 'deploymentResourceType' => 'site', + 'deploymentResourceId' => $site->getId(), + 'deploymentResourceInternalId' => $site->getSequence(), + 'status' => 'verified', + 'certificateId' => '', + 'owner' => 'Appwrite', + 'region' => $project->getAttribute('region') + ])) + ); + + $queueForBuilds + ->setType(BUILD_TYPE_DEPLOYMENT) + ->setResource($site) + ->setDeployment($deployment) + ->setTemplate($template); + + $queueForEvents + ->setParam('siteId', $site->getId()) + ->setParam('deploymentId', $deployment->getId()); + + $response + ->setStatusCode(Response::STATUS_CODE_ACCEPTED) + ->dynamic($deployment, Response::MODEL_DEPLOYMENT); + } +} diff --git a/src/Appwrite/Platform/Modules/Sites/Services/Http.php b/src/Appwrite/Platform/Modules/Sites/Services/Http.php index 6bd151f97e..f19b9b6d71 100644 --- a/src/Appwrite/Platform/Modules/Sites/Services/Http.php +++ b/src/Appwrite/Platform/Modules/Sites/Services/Http.php @@ -6,6 +6,7 @@ use Appwrite\Platform\Modules\Sites\Http\Deployments\Create as CreateDeployment; use Appwrite\Platform\Modules\Sites\Http\Deployments\Delete as DeleteDeployment; use Appwrite\Platform\Modules\Sites\Http\Deployments\Download\Get as DownloadDeployment; use Appwrite\Platform\Modules\Sites\Http\Deployments\Duplicate\Create as CreateDuplicateDeployment; +use Appwrite\Platform\Modules\Sites\Http\Deployments\Direct\Create as CreateDirectDeployment; use Appwrite\Platform\Modules\Sites\Http\Deployments\Get as GetDeployment; use Appwrite\Platform\Modules\Sites\Http\Deployments\Status\Update as UpdateDeploymentStatus; use Appwrite\Platform\Modules\Sites\Http\Deployments\Template\Create as CreateTemplateDeployment; @@ -60,6 +61,7 @@ class Http extends Service $this->addAction(DownloadDeployment::getName(), new DownloadDeployment()); $this->addAction(CreateDuplicateDeployment::getName(), new CreateDuplicateDeployment()); $this->addAction(UpdateDeploymentStatus::getName(), new UpdateDeploymentStatus()); + $this->addAction(CreateDirectDeployment::getName(), new CreateDirectDeployment()); // Logs $this->addAction(GetLog::getName(), new GetLog());