From 862847f7a1aa70647446c9126a9d6292d4b79e96 Mon Sep 17 00:00:00 2001 From: Ben <105687719+ben-octo-data-dev@users.noreply.github.com> Date: Fri, 29 May 2026 15:53:54 +0800 Subject: [PATCH 1/3] Add convex steps --- gulpfile.babel.js | 2 + step-templates/convex-deploy.json | 74 ++++++++++++ step-templates/convex-export-data.json | 94 +++++++++++++++ step-templates/convex-run-function.json | 94 +++++++++++++++ .../convex-set-environment-variables.json | 74 ++++++++++++ .../convex-smoke-test-http-action.json | 114 ++++++++++++++++++ step-templates/logos/convex.png | Bin 0 -> 10711 bytes step-templates/supabase-run-migrations.json | 4 +- 8 files changed, 454 insertions(+), 2 deletions(-) create mode 100644 step-templates/convex-deploy.json create mode 100644 step-templates/convex-export-data.json create mode 100644 step-templates/convex-run-function.json create mode 100644 step-templates/convex-set-environment-variables.json create mode 100644 step-templates/convex-smoke-test-http-action.json create mode 100644 step-templates/logos/convex.png diff --git a/gulpfile.babel.js b/gulpfile.babel.js index f9b4a7fb6..43e1a1c97 100644 --- a/gulpfile.babel.js +++ b/gulpfile.babel.js @@ -186,6 +186,8 @@ function humanize(categoryId) { return "Chef"; case "clickonce": return "ClickOnce"; + case "convex": + return "Convex"; case "cyberark": return "CyberArk"; case "dll": diff --git a/step-templates/convex-deploy.json b/step-templates/convex-deploy.json new file mode 100644 index 000000000..e726635da --- /dev/null +++ b/step-templates/convex-deploy.json @@ -0,0 +1,74 @@ +{ + "Id": "22a4a875-e5fb-44c9-86d9-16911e58c0f0", + "Name": "Convex - Deploy", + "Description": "Deploys your Convex backend functions and schema to a target deployment using the [Convex CLI](https://docs.convex.dev/cli). Supports production, preview, and named deployments via a deploy key.\n\nRequires Node.js and npx available on the worker.", + "ActionType": "Octopus.Script", + "Version": 1, + "CommunityActionTemplateId": null, + "Packages": [], + "Properties": { + "Octopus.Action.Script.ScriptSource": "Inline", + "Octopus.Action.Script.Syntax": "Bash", + "Octopus.Action.Script.ScriptBody": "deployKey=$(get_octopusvariable \"ConvexDeploy.DeployKey\")\ndeploymentType=$(get_octopusvariable \"ConvexDeploy.DeploymentType\")\npreviewName=$(get_octopusvariable \"ConvexDeploy.PreviewName\")\nworkingDir=$(get_octopusvariable \"ConvexDeploy.WorkingDirectory\")\ncmdTimeout=$(get_octopusvariable \"ConvexDeploy.CommandTimeout\")\n\nif [ -z \"$deployKey\" ]; then\n echo \"ERROR: ConvexDeploy.DeployKey is required.\"\n exit 1\nfi\n\nif [ -z \"$deploymentType\" ]; then\n deploymentType=\"prod\"\nfi\n\nif [ -z \"$cmdTimeout\" ]; then\n cmdTimeout=\"300\"\nfi\n\nexport CONVEX_DEPLOY_KEY=\"$deployKey\"\n\nif [ -n \"$workingDir\" ]; then\n echo \"Changing to working directory: $workingDir\"\n cd \"$workingDir\" || { echo \"ERROR: Could not change to directory '$workingDir'\"; exit 1; }\nfi\n\necho \"Convex deployment type: $deploymentType\"\n\ncase \"$deploymentType\" in\n prod)\n echo \"Deploying to production...\"\n timeout \"$cmdTimeout\" npx convex deploy --yes\n ;;\n preview)\n if [ -z \"$previewName\" ]; then\n echo \"ERROR: ConvexDeploy.PreviewName is required when deployment type is 'preview'.\"\n exit 1\n fi\n echo \"Deploying to preview deployment: $previewName\"\n timeout \"$cmdTimeout\" npx convex deploy --preview-name \"$previewName\" --yes\n ;;\n dev)\n echo \"Deploying to dev deployment...\"\n timeout \"$cmdTimeout\" npx convex deploy --yes\n ;;\n *)\n echo \"ERROR: Unknown deployment type '$deploymentType'. Must be one of: prod, preview, dev\"\n exit 1\n ;;\nesac\n\nif [ $? -ne 0 ]; then\n echo \"ERROR: Convex deployment failed.\"\n exit 1\nfi\n\necho \"Convex deployment completed successfully.\"\n" + }, + "Parameters": [ + { + "Id": "6727833e-b393-470c-ab79-e72c3749e402", + "Name": "ConvexDeploy.DeployKey", + "Label": "Deploy Key", + "HelpText": "The Convex deploy key for the target project. Generate one with `npx convex deployment token` or via the Convex dashboard. Store this as a sensitive Octopus variable.\n\nSee: [Creating deploy keys](https://docs.convex.dev/cli#deploy-keys)", + "DefaultValue": "", + "DisplaySettings": { + "Octopus.ControlType": "Sensitive" + } + }, + { + "Id": "0b361a83-c5b8-441e-846a-9bc88b2d7114", + "Name": "ConvexDeploy.DeploymentType", + "Label": "Deployment Type", + "HelpText": "The type of Convex deployment to target.\n\n- `prod` \u2014 production deployment (default)\n- `preview` \u2014 preview deployment (requires a preview name)\n- `dev` \u2014 development deployment", + "DefaultValue": "prod", + "DisplaySettings": { + "Octopus.ControlType": "Select", + "Octopus.SelectOptions": "prod|Production\npreview|Preview\ndev|Development" + } + }, + { + "Id": "8adff0dc-16d9-44ff-b05a-fcb7b92ff3ce", + "Name": "ConvexDeploy.PreviewName", + "Label": "Preview Name", + "HelpText": "The name of the preview deployment. Only required when **Deployment Type** is set to `preview`.", + "DefaultValue": "", + "DisplaySettings": { + "Octopus.ControlType": "SingleLineText" + } + }, + { + "Id": "dc368708-12b9-4d03-aeda-e7cd8e8326c3", + "Name": "ConvexDeploy.WorkingDirectory", + "Label": "Working Directory", + "HelpText": "Optional. The directory containing your Convex project (where `convex/` lives). Defaults to the current working directory if left blank.", + "DefaultValue": "", + "DisplaySettings": { + "Octopus.ControlType": "SingleLineText" + } + }, + { + "Id": "17fc0144-7fdc-4c5b-80fb-7143d503fef6", + "Name": "ConvexDeploy.CommandTimeout", + "Label": "Command Timeout (seconds)", + "HelpText": "Maximum number of seconds to wait for the deploy command to complete. Defaults to 300 (5 minutes).", + "DefaultValue": "300", + "DisplaySettings": { + "Octopus.ControlType": "SingleLineText" + } + } + ], + "LastModifiedBy": "itsmebenwalker", + "$Meta": { + "ExportedAt": "2026-05-29T00:00:00.000Z", + "OctopusVersion": "2026.1.0", + "Type": "ActionTemplate" + }, + "Category": "convex" +} diff --git a/step-templates/convex-export-data.json b/step-templates/convex-export-data.json new file mode 100644 index 000000000..5741178bd --- /dev/null +++ b/step-templates/convex-export-data.json @@ -0,0 +1,94 @@ +{ + "Id": "3f4519f7-78f6-4fb9-8bc5-97e138825bb8", + "Name": "Convex - Export Data", + "Description": "Exports a snapshot of your Convex deployment's data to a local file using the [Convex CLI](https://docs.convex.dev/cli). Designed to be run before a production deployment as a data backup or rollback safety net.\n\nThe export file can optionally be captured as an Octopus build artifact for storage and auditing.", + "ActionType": "Octopus.Script", + "Version": 1, + "CommunityActionTemplateId": null, + "Packages": [], + "Properties": { + "Octopus.Action.Script.ScriptSource": "Inline", + "Octopus.Action.Script.Syntax": "Bash", + "Octopus.Action.Script.ScriptBody": "deployKey=$(get_octopusvariable \"ConvexExport.DeployKey\")\noutputPath=$(get_octopusvariable \"ConvexExport.OutputPath\")\ndeploymentType=$(get_octopusvariable \"ConvexExport.DeploymentType\")\npreviewName=$(get_octopusvariable \"ConvexExport.PreviewName\")\nworkingDir=$(get_octopusvariable \"ConvexExport.WorkingDirectory\")\ncaptureArtifact=$(get_octopusvariable \"ConvexExport.CaptureAsArtifact\")\ncmdTimeout=$(get_octopusvariable \"ConvexExport.CommandTimeout\")\n\nif [ -z \"$deployKey\" ]; then\n echo \"ERROR: ConvexExport.DeployKey is required.\"\n exit 1\nfi\n\nif [ -z \"$deploymentType\" ]; then\n deploymentType=\"prod\"\nfi\n\nif [ -z \"$cmdTimeout\" ]; then\n cmdTimeout=\"600\"\nfi\n\nexport CONVEX_DEPLOY_KEY=\"$deployKey\"\n\nif [ -n \"$workingDir\" ]; then\n echo \"Changing to working directory: $workingDir\"\n cd \"$workingDir\" || { echo \"ERROR: Could not change to directory '$workingDir'\"; exit 1; }\nfi\n\ntimestamp=$(date +\"%Y%m%d_%H%M%S\")\n\nif [ -z \"$outputPath\" ]; then\n outputPath=\"convex-export-${timestamp}.zip\"\nfi\n\ndeploymentFlag=\"\"\ncase \"$deploymentType\" in\n prod)\n deploymentFlag=\"--prod\"\n ;;\n preview)\n if [ -z \"$previewName\" ]; then\n echo \"ERROR: ConvexExport.PreviewName is required when deployment type is 'preview'.\"\n exit 1\n fi\n deploymentFlag=\"--preview-name $previewName\"\n ;;\n dev)\n deploymentFlag=\"\"\n ;;\nesac\n\necho \"Exporting Convex data from: $deploymentType\"\necho \"Output file: $outputPath\"\n\ntimeout \"$cmdTimeout\" npx convex export $deploymentFlag --path \"$outputPath\"\n\nexitCode=$?\nif [ $exitCode -ne 0 ]; then\n echo \"ERROR: Convex export failed with exit code $exitCode.\"\n exit $exitCode\nfi\n\nif [ ! -f \"$outputPath\" ]; then\n echo \"ERROR: Export completed but output file not found at '$outputPath'.\"\n exit 1\nfi\n\nfileSize=$(du -sh \"$outputPath\" | cut -f1)\necho \"Export complete. File: $outputPath ($fileSize)\"\n\nif [ \"$captureArtifact\" = \"True\" ]; then\n new_octopusartifact \"$outputPath\"\n echo \"Export captured as Octopus artifact.\"\nfi\n" + }, + "Parameters": [ + { + "Id": "ba76acd0-99e4-4aa1-8554-e0696b528ed7", + "Name": "ConvexExport.DeployKey", + "Label": "Deploy Key", + "HelpText": "The Convex deploy key for the target project. Store this as a sensitive Octopus variable.\n\nSee: [Creating deploy keys](https://docs.convex.dev/cli#deploy-keys)", + "DefaultValue": "", + "DisplaySettings": { + "Octopus.ControlType": "Sensitive" + } + }, + { + "Id": "17b1f813-7b43-4528-bafe-5b52eac6df1b", + "Name": "ConvexExport.OutputPath", + "Label": "Output File Path", + "HelpText": "Optional. The local path where the export ZIP file should be written.\n\nDefaults to `convex-export-{timestamp}.zip` in the current working directory if left blank.", + "DefaultValue": "", + "DisplaySettings": { + "Octopus.ControlType": "SingleLineText" + } + }, + { + "Id": "e7002edd-eb0d-4c2b-979e-972c095eede5", + "Name": "ConvexExport.DeploymentType", + "Label": "Deployment Type", + "HelpText": "The Convex deployment to export data from.\n\n- `prod` \u2014 production deployment (default)\n- `preview` \u2014 preview deployment (requires a preview name)\n- `dev` \u2014 development deployment", + "DefaultValue": "prod", + "DisplaySettings": { + "Octopus.ControlType": "Select", + "Octopus.SelectOptions": "prod|Production\npreview|Preview\ndev|Development" + } + }, + { + "Id": "81526834-4204-4696-bfc4-3e965dcb320d", + "Name": "ConvexExport.PreviewName", + "Label": "Preview Name", + "HelpText": "The name of the preview deployment. Only required when **Deployment Type** is `preview`.", + "DefaultValue": "", + "DisplaySettings": { + "Octopus.ControlType": "SingleLineText" + } + }, + { + "Id": "690649ca-3801-45d1-9a59-45e561c127f5", + "Name": "ConvexExport.WorkingDirectory", + "Label": "Working Directory", + "HelpText": "Optional. Path to the directory containing your Convex project. Defaults to the current working directory if left blank.", + "DefaultValue": "", + "DisplaySettings": { + "Octopus.ControlType": "SingleLineText" + } + }, + { + "Id": "036c1260-7b14-4c05-8948-858cc1b5c893", + "Name": "ConvexExport.CaptureAsArtifact", + "Label": "Capture as Octopus Artifact", + "HelpText": "When enabled, the exported file will be captured as an Octopus build artifact, making it available for download from the deployment details page.", + "DefaultValue": "True", + "DisplaySettings": { + "Octopus.ControlType": "Checkbox" + } + }, + { + "Id": "186fac8e-92c9-482f-adea-551cb64dd999", + "Name": "ConvexExport.CommandTimeout", + "Label": "Command Timeout (seconds)", + "HelpText": "Maximum number of seconds to wait for the export to complete. Defaults to 600 (10 minutes). Large datasets may require a higher value.", + "DefaultValue": "600", + "DisplaySettings": { + "Octopus.ControlType": "SingleLineText" + } + } + ], + "LastModifiedBy": "itsmebenwalker", + "$Meta": { + "ExportedAt": "2026-05-29T00:00:00.000Z", + "OctopusVersion": "2026.1.0", + "Type": "ActionTemplate" + }, + "Category": "convex" +} diff --git a/step-templates/convex-run-function.json b/step-templates/convex-run-function.json new file mode 100644 index 000000000..ef5aa2745 --- /dev/null +++ b/step-templates/convex-run-function.json @@ -0,0 +1,94 @@ +{ + "Id": "307071fd-c649-4ab6-8b14-549da0943273", + "Name": "Convex - Run Function", + "Description": "Invokes a Convex mutation, action, or query against a deployment using the [Convex CLI](https://docs.convex.dev/cli). Ideal for running post-deploy data migrations, seeding initial data, or executing smoke-test queries as part of a deployment pipeline.", + "ActionType": "Octopus.Script", + "Version": 1, + "CommunityActionTemplateId": null, + "Packages": [], + "Properties": { + "Octopus.Action.Script.ScriptSource": "Inline", + "Octopus.Action.Script.Syntax": "Bash", + "Octopus.Action.Script.ScriptBody": "deployKey=$(get_octopusvariable \"ConvexRun.DeployKey\")\nfunctionPath=$(get_octopusvariable \"ConvexRun.FunctionPath\")\nfunctionArgs=$(get_octopusvariable \"ConvexRun.FunctionArgs\")\ndeploymentType=$(get_octopusvariable \"ConvexRun.DeploymentType\")\npreviewName=$(get_octopusvariable \"ConvexRun.PreviewName\")\nworkingDir=$(get_octopusvariable \"ConvexRun.WorkingDirectory\")\ncmdTimeout=$(get_octopusvariable \"ConvexRun.CommandTimeout\")\n\nif [ -z \"$deployKey\" ]; then\n echo \"ERROR: ConvexRun.DeployKey is required.\"\n exit 1\nfi\n\nif [ -z \"$functionPath\" ]; then\n echo \"ERROR: ConvexRun.FunctionPath is required.\"\n exit 1\nfi\n\nif [ -z \"$deploymentType\" ]; then\n deploymentType=\"prod\"\nfi\n\nif [ -z \"$cmdTimeout\" ]; then\n cmdTimeout=\"120\"\nfi\n\nexport CONVEX_DEPLOY_KEY=\"$deployKey\"\n\nif [ -n \"$workingDir\" ]; then\n echo \"Changing to working directory: $workingDir\"\n cd \"$workingDir\" || { echo \"ERROR: Could not change to directory '$workingDir'\"; exit 1; }\nfi\n\ndeploymentFlag=\"\"\ncase \"$deploymentType\" in\n prod)\n deploymentFlag=\"--prod\"\n ;;\n preview)\n if [ -z \"$previewName\" ]; then\n echo \"ERROR: ConvexRun.PreviewName is required when deployment type is 'preview'.\"\n exit 1\n fi\n deploymentFlag=\"--preview-name $previewName\"\n ;;\n dev)\n deploymentFlag=\"\"\n ;;\nesac\n\necho \"Running Convex function: $functionPath\"\necho \"Deployment type: $deploymentType\"\n\nif [ -n \"$functionArgs\" ]; then\n echo \"Args: $functionArgs\"\n timeout \"$cmdTimeout\" npx convex run $deploymentFlag \"$functionPath\" \"$functionArgs\"\nelse\n timeout \"$cmdTimeout\" npx convex run $deploymentFlag \"$functionPath\"\nfi\n\nexitCode=$?\nif [ $exitCode -ne 0 ]; then\n echo \"ERROR: Convex function '$functionPath' failed with exit code $exitCode.\"\n exit $exitCode\nfi\n\necho \"Convex function '$functionPath' completed successfully.\"\n" + }, + "Parameters": [ + { + "Id": "2768e849-72d0-4542-a60e-cc7596a1da91", + "Name": "ConvexRun.DeployKey", + "Label": "Deploy Key", + "HelpText": "The Convex deploy key for the target project. Store this as a sensitive Octopus variable.\n\nSee: [Creating deploy keys](https://docs.convex.dev/cli#deploy-keys)", + "DefaultValue": "", + "DisplaySettings": { + "Octopus.ControlType": "Sensitive" + } + }, + { + "Id": "717bb5dd-7e32-4689-8016-bf781d612051", + "Name": "ConvexRun.FunctionPath", + "Label": "Function Path", + "HelpText": "The path to the Convex function to invoke, in the format `module:functionName`.\n\nExamples:\n- `migrations:runV2`\n- `seed:populateDefaults`\n- `healthcheck:ping`", + "DefaultValue": "", + "DisplaySettings": { + "Octopus.ControlType": "SingleLineText" + } + }, + { + "Id": "282ce782-e9dc-4cad-a3c2-68fecebda89b", + "Name": "ConvexRun.FunctionArgs", + "Label": "Function Arguments (JSON)", + "HelpText": "Optional. A JSON object of arguments to pass to the function.\n\nExample: `{\"dryRun\": false, \"batchSize\": 100}`\n\nLeave blank if the function takes no arguments.", + "DefaultValue": "", + "DisplaySettings": { + "Octopus.ControlType": "MultiLineText" + } + }, + { + "Id": "6cb1f84c-16af-4cfe-aaef-a3b8bb37d0bf", + "Name": "ConvexRun.DeploymentType", + "Label": "Deployment Type", + "HelpText": "The Convex deployment to target.\n\n- `prod` \u2014 production deployment (default)\n- `preview` \u2014 preview deployment (requires a preview name)\n- `dev` \u2014 development deployment", + "DefaultValue": "prod", + "DisplaySettings": { + "Octopus.ControlType": "Select", + "Octopus.SelectOptions": "prod|Production\npreview|Preview\ndev|Development" + } + }, + { + "Id": "8e0918a3-4625-4830-80fd-1b330da2101d", + "Name": "ConvexRun.PreviewName", + "Label": "Preview Name", + "HelpText": "The name of the preview deployment. Only required when **Deployment Type** is `preview`.", + "DefaultValue": "", + "DisplaySettings": { + "Octopus.ControlType": "SingleLineText" + } + }, + { + "Id": "fe0a3a69-6a44-4dcb-ba71-0b1e1546ea25", + "Name": "ConvexRun.WorkingDirectory", + "Label": "Working Directory", + "HelpText": "Optional. Path to the directory containing your Convex project. Defaults to the current working directory if left blank.", + "DefaultValue": "", + "DisplaySettings": { + "Octopus.ControlType": "SingleLineText" + } + }, + { + "Id": "ac421438-68fa-4c33-a984-fa9cd7f9e007", + "Name": "ConvexRun.CommandTimeout", + "Label": "Command Timeout (seconds)", + "HelpText": "Maximum number of seconds to wait for the function to complete. Defaults to 120.", + "DefaultValue": "120", + "DisplaySettings": { + "Octopus.ControlType": "SingleLineText" + } + } + ], + "LastModifiedBy": "itsmebenwalker", + "$Meta": { + "ExportedAt": "2026-05-29T00:00:00.000Z", + "OctopusVersion": "2026.1.0", + "Type": "ActionTemplate" + }, + "Category": "convex" +} diff --git a/step-templates/convex-set-environment-variables.json b/step-templates/convex-set-environment-variables.json new file mode 100644 index 000000000..275aebd6e --- /dev/null +++ b/step-templates/convex-set-environment-variables.json @@ -0,0 +1,74 @@ +{ + "Id": "a8504194-b28d-4887-9f55-b9bf0601ce95", + "Name": "Convex - Set Environment Variables", + "Description": "Pushes one or more environment variables to a Convex deployment using the [Convex CLI](https://docs.convex.dev/cli). Useful for syncing secrets and config values from Octopus into your Convex runtime environment prior to or after a deployment.\n\nVariables are provided as a newline-delimited list of `KEY=VALUE` pairs.", + "ActionType": "Octopus.Script", + "Version": 1, + "CommunityActionTemplateId": null, + "Packages": [], + "Properties": { + "Octopus.Action.Script.ScriptSource": "Inline", + "Octopus.Action.Script.Syntax": "Bash", + "Octopus.Action.Script.ScriptBody": "deployKey=$(get_octopusvariable \"ConvexEnvSet.DeployKey\")\nenvVars=$(get_octopusvariable \"ConvexEnvSet.EnvironmentVariables\")\ndeploymentType=$(get_octopusvariable \"ConvexEnvSet.DeploymentType\")\npreviewName=$(get_octopusvariable \"ConvexEnvSet.PreviewName\")\nworkingDir=$(get_octopusvariable \"ConvexEnvSet.WorkingDirectory\")\n\nif [ -z \"$deployKey\" ]; then\n echo \"ERROR: ConvexEnvSet.DeployKey is required.\"\n exit 1\nfi\n\nif [ -z \"$envVars\" ]; then\n echo \"ERROR: ConvexEnvSet.EnvironmentVariables is required.\"\n exit 1\nfi\n\nif [ -z \"$deploymentType\" ]; then\n deploymentType=\"prod\"\nfi\n\nexport CONVEX_DEPLOY_KEY=\"$deployKey\"\n\nif [ -n \"$workingDir\" ]; then\n echo \"Changing to working directory: $workingDir\"\n cd \"$workingDir\" || { echo \"ERROR: Could not change to directory '$workingDir'\"; exit 1; }\nfi\n\ndeploymentFlag=\"\"\ncase \"$deploymentType\" in\n prod)\n deploymentFlag=\"--prod\"\n ;;\n preview)\n if [ -z \"$previewName\" ]; then\n echo \"ERROR: ConvexEnvSet.PreviewName is required when deployment type is 'preview'.\"\n exit 1\n fi\n deploymentFlag=\"--preview-name $previewName\"\n ;;\n dev)\n deploymentFlag=\"\"\n ;;\nesac\n\necho \"Setting environment variables on Convex deployment ($deploymentType)...\"\n\nsuccessCount=0\nfailCount=0\n\nwhile IFS= read -r line; do\n line=$(echo \"$line\" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')\n [ -z \"$line\" ] && continue\n [[ \"$line\" == \\#* ]] && continue\n\n if [[ \"$line\" != *=* ]]; then\n echo \"WARNING: Skipping malformed entry (no '=' found): $line\"\n continue\n fi\n\n key=\"${line%%=*}\"\n value=\"${line#*=}\"\n\n echo \"Setting: $key\"\n if npx convex env set $deploymentFlag \"$key\" \"$value\"; then\n successCount=$((successCount + 1))\n else\n echo \"ERROR: Failed to set variable '$key'.\"\n failCount=$((failCount + 1))\n fi\ndone <<< \"$envVars\"\n\necho \"Done. $successCount variable(s) set successfully, $failCount failed.\"\n\nif [ \"$failCount\" -gt 0 ]; then\n exit 1\nfi\n" + }, + "Parameters": [ + { + "Id": "fdb646d3-d787-45ea-93d5-d5ab9f14b97b", + "Name": "ConvexEnvSet.DeployKey", + "Label": "Deploy Key", + "HelpText": "The Convex deploy key for the target project. Store this as a sensitive Octopus variable.\n\nSee: [Creating deploy keys](https://docs.convex.dev/cli#deploy-keys)", + "DefaultValue": "", + "DisplaySettings": { + "Octopus.ControlType": "Sensitive" + } + }, + { + "Id": "4a71c65b-235f-4ded-9036-1f682d45aa9b", + "Name": "ConvexEnvSet.EnvironmentVariables", + "Label": "Environment Variables", + "HelpText": "A newline-delimited list of `KEY=VALUE` pairs to set on the deployment. Blank lines and lines starting with `#` are ignored.\n\nExample:\n```\nNEXT_PUBLIC_API_URL=https://api.example.com\nSENDGRID_API_KEY=#{SomeOctopusSecret}\n```", + "DefaultValue": "", + "DisplaySettings": { + "Octopus.ControlType": "MultiLineText" + } + }, + { + "Id": "2f8b490d-dda1-4b25-937a-0c9dda365d48", + "Name": "ConvexEnvSet.DeploymentType", + "Label": "Deployment Type", + "HelpText": "The Convex deployment to target.\n\n- `prod` \u2014 production deployment (default)\n- `preview` \u2014 preview deployment (requires a preview name)\n- `dev` \u2014 development deployment", + "DefaultValue": "prod", + "DisplaySettings": { + "Octopus.ControlType": "Select", + "Octopus.SelectOptions": "prod|Production\npreview|Preview\ndev|Development" + } + }, + { + "Id": "90fc61e3-6de3-465b-87bc-04e1a365e0b3", + "Name": "ConvexEnvSet.PreviewName", + "Label": "Preview Name", + "HelpText": "The name of the preview deployment. Only required when **Deployment Type** is `preview`.", + "DefaultValue": "", + "DisplaySettings": { + "Octopus.ControlType": "SingleLineText" + } + }, + { + "Id": "f49e1b7c-7d72-4f66-8e1b-49d423cc60b1", + "Name": "ConvexEnvSet.WorkingDirectory", + "Label": "Working Directory", + "HelpText": "Optional. Path to the directory containing your Convex project. Defaults to the current working directory if left blank.", + "DefaultValue": "", + "DisplaySettings": { + "Octopus.ControlType": "SingleLineText" + } + } + ], + "LastModifiedBy": "itsmebenwalker", + "$Meta": { + "ExportedAt": "2026-05-29T00:00:00.000Z", + "OctopusVersion": "2026.1.0", + "Type": "ActionTemplate" + }, + "Category": "convex" +} diff --git a/step-templates/convex-smoke-test-http-action.json b/step-templates/convex-smoke-test-http-action.json new file mode 100644 index 000000000..246ddb871 --- /dev/null +++ b/step-templates/convex-smoke-test-http-action.json @@ -0,0 +1,114 @@ +{ + "Id": "e4bb4066-1919-49a4-a6f6-61b1fd97bb1f", + "Name": "Convex - Smoke Test HTTP Action", + "Description": "Performs a smoke test against a Convex [HTTP action](https://docs.convex.dev/functions/http-actions) endpoint after a deployment. Validates that the deployment is live and responding correctly by checking the HTTP status code and optionally asserting on the response body.\n\nUse this as a post-deploy verification step to catch failed or partial deployments early.", + "ActionType": "Octopus.Script", + "Version": 1, + "CommunityActionTemplateId": null, + "Packages": [], + "Properties": { + "Octopus.Action.Script.ScriptSource": "Inline", + "Octopus.Action.Script.Syntax": "Bash", + "Octopus.Action.Script.ScriptBody": "deploymentUrl=$(get_octopusvariable \"ConvexSmokeTest.DeploymentUrl\")\nactionPath=$(get_octopusvariable \"ConvexSmokeTest.ActionPath\")\nexpectedStatus=$(get_octopusvariable \"ConvexSmokeTest.ExpectedStatusCode\")\nbodyAssertion=$(get_octopusvariable \"ConvexSmokeTest.ResponseBodyAssertion\")\nhttpMethod=$(get_octopusvariable \"ConvexSmokeTest.HttpMethod\")\nrequestBody=$(get_octopusvariable \"ConvexSmokeTest.RequestBody\")\nmaxRetries=$(get_octopusvariable \"ConvexSmokeTest.MaxRetries\")\nretryDelay=$(get_octopusvariable \"ConvexSmokeTest.RetryDelay\")\ncurlTimeout=$(get_octopusvariable \"ConvexSmokeTest.CurlTimeout\")\n\nif [ -z \"$deploymentUrl\" ]; then\n echo \"ERROR: ConvexSmokeTest.DeploymentUrl is required.\"\n exit 1\nfi\n\nif [ -z \"$actionPath\" ]; then\n echo \"ERROR: ConvexSmokeTest.ActionPath is required.\"\n exit 1\nfi\n\nif [ -z \"$expectedStatus\" ]; then\n expectedStatus=\"200\"\nfi\n\nif [ -z \"$httpMethod\" ]; then\n httpMethod=\"GET\"\nfi\n\nif [ -z \"$maxRetries\" ]; then\n maxRetries=\"3\"\nfi\n\nif [ -z \"$retryDelay\" ]; then\n retryDelay=\"5\"\nfi\n\nif [ -z \"$curlTimeout\" ]; then\n curlTimeout=\"30\"\nfi\n\ndeploymentUrl=$(echo \"$deploymentUrl\" | sed 's|/$||')\nactionPath=$(echo \"$actionPath\" | sed 's|^/||')\ntargetUrl=\"${deploymentUrl}/${actionPath}\"\n\necho \"Smoke test target: $targetUrl\"\necho \"Method: $httpMethod | Expected status: $expectedStatus | Max retries: $maxRetries\"\n\nattempt=0\nsuccess=false\n\nwhile [ $attempt -lt $maxRetries ]; do\n attempt=$((attempt + 1))\n echo \"Attempt $attempt of $maxRetries...\"\n\n curlArgs=(\n -s\n -o /tmp/convex_smoke_body\n -w \"%{http_code}\"\n -X \"$httpMethod\"\n --max-time \"$curlTimeout\"\n )\n\n if [ -n \"$requestBody\" ]; then\n curlArgs+=(-H \"Content-Type: application/json\" -d \"$requestBody\")\n fi\n\n actualStatus=$(curl \"${curlArgs[@]}\" \"$targetUrl\")\n responseBody=$(cat /tmp/convex_smoke_body)\n\n echo \"Response status: $actualStatus\"\n\n if [ \"$actualStatus\" != \"$expectedStatus\" ]; then\n echo \"WARNING: Expected status $expectedStatus but got $actualStatus.\"\n echo \"Response body: $responseBody\"\n if [ $attempt -lt $maxRetries ]; then\n echo \"Retrying in ${retryDelay}s...\"\n sleep \"$retryDelay\"\n fi\n continue\n fi\n\n if [ -n \"$bodyAssertion\" ]; then\n if echo \"$responseBody\" | grep -qF \"$bodyAssertion\"; then\n echo \"Body assertion passed: '$bodyAssertion' found in response.\"\n else\n echo \"WARNING: Body assertion failed. '$bodyAssertion' not found in response.\"\n echo \"Response body: $responseBody\"\n if [ $attempt -lt $maxRetries ]; then\n echo \"Retrying in ${retryDelay}s...\"\n sleep \"$retryDelay\"\n fi\n continue\n fi\n fi\n\n success=true\n break\ndone\n\nif [ \"$success\" = false ]; then\n echo \"ERROR: Smoke test failed after $maxRetries attempt(s). Deployment may be unhealthy.\"\n exit 1\nfi\n\necho \"Smoke test passed. Convex deployment is healthy.\"\n" + }, + "Parameters": [ + { + "Id": "8e928a76-2256-4b34-886f-473bf53a4e21", + "Name": "ConvexSmokeTest.DeploymentUrl", + "Label": "Deployment URL", + "HelpText": "The base URL of your Convex deployment.\n\nExample: `https://happy-animal-123.convex.site`\n\nFind this in your Convex dashboard under **Settings \u2192 URL & Deploy Key**.", + "DefaultValue": "", + "DisplaySettings": { + "Octopus.ControlType": "SingleLineText" + } + }, + { + "Id": "8734c4d8-9d6c-4c33-93c8-66608f3c450e", + "Name": "ConvexSmokeTest.ActionPath", + "Label": "Action Path", + "HelpText": "The path to the HTTP action endpoint to test.\n\nExample: `/health` or `/api/ping`\n\nThis is the route registered in your Convex `http.ts` file.", + "DefaultValue": "/health", + "DisplaySettings": { + "Octopus.ControlType": "SingleLineText" + } + }, + { + "Id": "fc465072-d618-4487-ac00-95b40027d253", + "Name": "ConvexSmokeTest.HttpMethod", + "Label": "HTTP Method", + "HelpText": "The HTTP method to use for the request.", + "DefaultValue": "GET", + "DisplaySettings": { + "Octopus.ControlType": "Select", + "Octopus.SelectOptions": "GET|GET\nPOST|POST\nPUT|PUT\nDELETE|DELETE" + } + }, + { + "Id": "961a2dc5-1bdf-46b7-bb63-08541f20c241", + "Name": "ConvexSmokeTest.ExpectedStatusCode", + "Label": "Expected HTTP Status Code", + "HelpText": "The HTTP status code the endpoint should return for the test to pass. Defaults to `200`.", + "DefaultValue": "200", + "DisplaySettings": { + "Octopus.ControlType": "SingleLineText" + } + }, + { + "Id": "313c7f55-0291-4591-a941-dab64822b6b2", + "Name": "ConvexSmokeTest.ResponseBodyAssertion", + "Label": "Response Body Assertion", + "HelpText": "Optional. A string that must be present in the response body for the test to pass.\n\nExample: `{\"status\":\"ok\"}` or simply `ok`\n\nLeave blank to skip body assertion.", + "DefaultValue": "", + "DisplaySettings": { + "Octopus.ControlType": "SingleLineText" + } + }, + { + "Id": "e405bd82-b839-4de7-be5b-a6619b637631", + "Name": "ConvexSmokeTest.RequestBody", + "Label": "Request Body (JSON)", + "HelpText": "Optional. A JSON body to send with the request. Only relevant for POST or PUT requests.\n\nLeave blank for GET requests.", + "DefaultValue": "", + "DisplaySettings": { + "Octopus.ControlType": "MultiLineText" + } + }, + { + "Id": "2766feca-344e-45c9-b02b-e05b24725837", + "Name": "ConvexSmokeTest.MaxRetries", + "Label": "Max Retries", + "HelpText": "The number of times to retry the request if it fails. Useful for allowing a brief warm-up period after deployment. Defaults to `3`.", + "DefaultValue": "3", + "DisplaySettings": { + "Octopus.ControlType": "SingleLineText" + } + }, + { + "Id": "5f841ad3-12bd-4ba4-b065-26b15c1e5d71", + "Name": "ConvexSmokeTest.RetryDelay", + "Label": "Retry Delay (seconds)", + "HelpText": "Seconds to wait between retry attempts. Defaults to `5`.", + "DefaultValue": "5", + "DisplaySettings": { + "Octopus.ControlType": "SingleLineText" + } + }, + { + "Id": "f6063486-b004-4c6a-953d-2dc8190c8635", + "Name": "ConvexSmokeTest.CurlTimeout", + "Label": "Request Timeout (seconds)", + "HelpText": "Maximum seconds to wait for each individual HTTP request to complete. Defaults to `30`.", + "DefaultValue": "30", + "DisplaySettings": { + "Octopus.ControlType": "SingleLineText" + } + } + ], + "LastModifiedBy": "itsmebenwalker", + "$Meta": { + "ExportedAt": "2026-05-29T00:00:00.000Z", + "OctopusVersion": "2026.1.0", + "Type": "ActionTemplate" + }, + "Category": "convex" +} diff --git a/step-templates/logos/convex.png b/step-templates/logos/convex.png new file mode 100644 index 0000000000000000000000000000000000000000..4deb4af79cef74e31bd1a8557c63fb71711f9d1c GIT binary patch literal 10711 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 DPwyGe literal 0 HcmV?d00001 diff --git a/step-templates/supabase-run-migrations.json b/step-templates/supabase-run-migrations.json index 9fa6442f4..a7a1748ce 100644 --- a/step-templates/supabase-run-migrations.json +++ b/step-templates/supabase-run-migrations.json @@ -1,9 +1,9 @@ { "Id": "937be757-a954-42e3-b315-670578a346e0", "Name": "Supabase - Run Migrations", - "Description": "Runs database migrations against a Supabase project using the Supabase CLI.\n\nThis step will:\n1. Install the Supabase CLI if not already present\n2. Authenticate with Supabase using the access token\n3. Push pending migrations to the remote database\n\n**Prerequisites:**\n- An existing Supabase project\n- Database migrations defined in your project's `supabase/migrations/` directory\n\n**Package Reference Required:**\nThis step expects a referenced package named **`supabase-migrations`** attached to the deployment step with **Extract package** enabled. The package must contain a `supabase/migrations/` directory at its root. The step uses `Octopus.Action.Package[supabase-migrations].ExtractedPath` to locate the migrations at runtime. If no package is found it will fall back to the current working directory.\n\n**Finding your Project Ref:**\n- From the Supabase Dashboard URL: `https://app.supabase.com/project//...`\n- Or go to **Project Settings → General**\n\n[Supabase CLI Documentation](https://supabase.com/docs/reference/cli/introduction)\n[Database Migrations Guide](https://supabase.com/docs/guides/migrations)", + "Description": "Runs database migrations against a Supabase project using the Supabase CLI.\n\nThis step will:\n1. Install the Supabase CLI if not already present\n2. Authenticate with Supabase using the access token\n3. Push pending migrations to the remote database\n\n**Prerequisites:**\n- An existing Supabase project\n- Database migrations defined in your project's `supabase/migrations/` directory\n\n**Package Reference Required:**\nThis step expects a referenced package named **`supabase-migrations`** attached to the deployment step with **Extract package** enabled. The package must contain a `supabase/migrations/` directory at its root. The step uses `Octopus.Action.Package[supabase-migrations].ExtractedPath` to locate the migrations at runtime. If no package is found it will fall back to the current working directory.\n\n**Finding your Project Ref:**\n- From the Supabase Dashboard URL: `https://app.supabase.com/project//...`\n- Or go to **Project Settings → General**\n\n[Supabase CLI Documentation](https://supabase.com/docs/reference/cli/introduction)\n[Database Migrations Guide](https://supabase.com/docs/guides/deployment/database-migrations)", "ActionType": "Octopus.Script", - "Version": 1, + "Version": 2, "CommunityActionTemplateId": null, "Properties": { "Octopus.Action.Script.Syntax": "Bash", From 38a7f30dbbe0e076ee5739822575fef3a61ec680 Mon Sep 17 00:00:00 2001 From: Ben <105687719+ben-octo-data-dev@users.noreply.github.com> Date: Fri, 29 May 2026 16:54:04 +0800 Subject: [PATCH 2/3] Add npm package --- step-templates/convex-deploy.json | 2 +- step-templates/convex-export-data.json | 2 +- step-templates/convex-run-function.json | 2 +- step-templates/convex-set-environment-variables.json | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/step-templates/convex-deploy.json b/step-templates/convex-deploy.json index e726635da..85708fb50 100644 --- a/step-templates/convex-deploy.json +++ b/step-templates/convex-deploy.json @@ -9,7 +9,7 @@ "Properties": { "Octopus.Action.Script.ScriptSource": "Inline", "Octopus.Action.Script.Syntax": "Bash", - "Octopus.Action.Script.ScriptBody": "deployKey=$(get_octopusvariable \"ConvexDeploy.DeployKey\")\ndeploymentType=$(get_octopusvariable \"ConvexDeploy.DeploymentType\")\npreviewName=$(get_octopusvariable \"ConvexDeploy.PreviewName\")\nworkingDir=$(get_octopusvariable \"ConvexDeploy.WorkingDirectory\")\ncmdTimeout=$(get_octopusvariable \"ConvexDeploy.CommandTimeout\")\n\nif [ -z \"$deployKey\" ]; then\n echo \"ERROR: ConvexDeploy.DeployKey is required.\"\n exit 1\nfi\n\nif [ -z \"$deploymentType\" ]; then\n deploymentType=\"prod\"\nfi\n\nif [ -z \"$cmdTimeout\" ]; then\n cmdTimeout=\"300\"\nfi\n\nexport CONVEX_DEPLOY_KEY=\"$deployKey\"\n\nif [ -n \"$workingDir\" ]; then\n echo \"Changing to working directory: $workingDir\"\n cd \"$workingDir\" || { echo \"ERROR: Could not change to directory '$workingDir'\"; exit 1; }\nfi\n\necho \"Convex deployment type: $deploymentType\"\n\ncase \"$deploymentType\" in\n prod)\n echo \"Deploying to production...\"\n timeout \"$cmdTimeout\" npx convex deploy --yes\n ;;\n preview)\n if [ -z \"$previewName\" ]; then\n echo \"ERROR: ConvexDeploy.PreviewName is required when deployment type is 'preview'.\"\n exit 1\n fi\n echo \"Deploying to preview deployment: $previewName\"\n timeout \"$cmdTimeout\" npx convex deploy --preview-name \"$previewName\" --yes\n ;;\n dev)\n echo \"Deploying to dev deployment...\"\n timeout \"$cmdTimeout\" npx convex deploy --yes\n ;;\n *)\n echo \"ERROR: Unknown deployment type '$deploymentType'. Must be one of: prod, preview, dev\"\n exit 1\n ;;\nesac\n\nif [ $? -ne 0 ]; then\n echo \"ERROR: Convex deployment failed.\"\n exit 1\nfi\n\necho \"Convex deployment completed successfully.\"\n" + "Octopus.Action.Script.ScriptBody": "deployKey=$(get_octopusvariable \"ConvexDeploy.DeployKey\")\ndeploymentType=$(get_octopusvariable \"ConvexDeploy.DeploymentType\")\npreviewName=$(get_octopusvariable \"ConvexDeploy.PreviewName\")\nworkingDir=$(get_octopusvariable \"ConvexDeploy.WorkingDirectory\")\ncmdTimeout=$(get_octopusvariable \"ConvexDeploy.CommandTimeout\")\n\nif [ -z \"$deployKey\" ]; then\n echo \"ERROR: ConvexDeploy.DeployKey is required.\"\n exit 1\nfi\n\nif [ -z \"$deploymentType\" ]; then\n deploymentType=\"prod\"\nfi\n\nif [ -z \"$cmdTimeout\" ]; then\n cmdTimeout=\"300\"\nfi\n\nexport CONVEX_DEPLOY_KEY=\"$deployKey\"\n\nif [ -n \"$workingDir\" ]; then\n echo \"Changing to working directory: $workingDir\"\n cd \"$workingDir\" || { echo \"ERROR: Could not change to directory '$workingDir'\"; exit 1; }\nfi\n\nensure_node() {\n if command -v npx &>/dev/null; then\n echo \"Node.js found: $(node --version)\"\n return 0\n fi\n export NVM_DIR=\"${NVM_DIR:-$HOME/.nvm}\"\n if [ -s \"$NVM_DIR/nvm.sh\" ]; then\n \\. \"$NVM_DIR/nvm.sh\"\n if command -v npx &>/dev/null; then\n echo \"Node.js loaded via nvm: $(node --version)\"\n return 0\n fi\n fi\n echo \"Node.js not found. Installing via nvm...\"\n curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash\n \\. \"$NVM_DIR/nvm.sh\"\n nvm install --lts\n echo \"Node.js installed: $(node --version)\"\n}\nensure_node\n\necho \"Convex deployment type: $deploymentType\"\n\ncase \"$deploymentType\" in\n prod)\n echo \"Deploying to production...\"\n timeout \"$cmdTimeout\" npx convex deploy --yes\n ;;\n preview)\n if [ -z \"$previewName\" ]; then\n echo \"ERROR: ConvexDeploy.PreviewName is required when deployment type is 'preview'.\"\n exit 1\n fi\n echo \"Deploying to preview deployment: $previewName\"\n timeout \"$cmdTimeout\" npx convex deploy --preview-name \"$previewName\" --yes\n ;;\n dev)\n echo \"Deploying to dev deployment...\"\n timeout \"$cmdTimeout\" npx convex deploy --yes\n ;;\n *)\n echo \"ERROR: Unknown deployment type '$deploymentType'. Must be one of: prod, preview, dev\"\n exit 1\n ;;\nesac\n\nif [ $? -ne 0 ]; then\n echo \"ERROR: Convex deployment failed.\"\n exit 1\nfi\n\necho \"Convex deployment completed successfully.\"\n" }, "Parameters": [ { diff --git a/step-templates/convex-export-data.json b/step-templates/convex-export-data.json index 5741178bd..8987a85e0 100644 --- a/step-templates/convex-export-data.json +++ b/step-templates/convex-export-data.json @@ -9,7 +9,7 @@ "Properties": { "Octopus.Action.Script.ScriptSource": "Inline", "Octopus.Action.Script.Syntax": "Bash", - "Octopus.Action.Script.ScriptBody": "deployKey=$(get_octopusvariable \"ConvexExport.DeployKey\")\noutputPath=$(get_octopusvariable \"ConvexExport.OutputPath\")\ndeploymentType=$(get_octopusvariable \"ConvexExport.DeploymentType\")\npreviewName=$(get_octopusvariable \"ConvexExport.PreviewName\")\nworkingDir=$(get_octopusvariable \"ConvexExport.WorkingDirectory\")\ncaptureArtifact=$(get_octopusvariable \"ConvexExport.CaptureAsArtifact\")\ncmdTimeout=$(get_octopusvariable \"ConvexExport.CommandTimeout\")\n\nif [ -z \"$deployKey\" ]; then\n echo \"ERROR: ConvexExport.DeployKey is required.\"\n exit 1\nfi\n\nif [ -z \"$deploymentType\" ]; then\n deploymentType=\"prod\"\nfi\n\nif [ -z \"$cmdTimeout\" ]; then\n cmdTimeout=\"600\"\nfi\n\nexport CONVEX_DEPLOY_KEY=\"$deployKey\"\n\nif [ -n \"$workingDir\" ]; then\n echo \"Changing to working directory: $workingDir\"\n cd \"$workingDir\" || { echo \"ERROR: Could not change to directory '$workingDir'\"; exit 1; }\nfi\n\ntimestamp=$(date +\"%Y%m%d_%H%M%S\")\n\nif [ -z \"$outputPath\" ]; then\n outputPath=\"convex-export-${timestamp}.zip\"\nfi\n\ndeploymentFlag=\"\"\ncase \"$deploymentType\" in\n prod)\n deploymentFlag=\"--prod\"\n ;;\n preview)\n if [ -z \"$previewName\" ]; then\n echo \"ERROR: ConvexExport.PreviewName is required when deployment type is 'preview'.\"\n exit 1\n fi\n deploymentFlag=\"--preview-name $previewName\"\n ;;\n dev)\n deploymentFlag=\"\"\n ;;\nesac\n\necho \"Exporting Convex data from: $deploymentType\"\necho \"Output file: $outputPath\"\n\ntimeout \"$cmdTimeout\" npx convex export $deploymentFlag --path \"$outputPath\"\n\nexitCode=$?\nif [ $exitCode -ne 0 ]; then\n echo \"ERROR: Convex export failed with exit code $exitCode.\"\n exit $exitCode\nfi\n\nif [ ! -f \"$outputPath\" ]; then\n echo \"ERROR: Export completed but output file not found at '$outputPath'.\"\n exit 1\nfi\n\nfileSize=$(du -sh \"$outputPath\" | cut -f1)\necho \"Export complete. File: $outputPath ($fileSize)\"\n\nif [ \"$captureArtifact\" = \"True\" ]; then\n new_octopusartifact \"$outputPath\"\n echo \"Export captured as Octopus artifact.\"\nfi\n" + "Octopus.Action.Script.ScriptBody": "deployKey=$(get_octopusvariable \"ConvexExport.DeployKey\")\noutputPath=$(get_octopusvariable \"ConvexExport.OutputPath\")\ndeploymentType=$(get_octopusvariable \"ConvexExport.DeploymentType\")\npreviewName=$(get_octopusvariable \"ConvexExport.PreviewName\")\nworkingDir=$(get_octopusvariable \"ConvexExport.WorkingDirectory\")\ncaptureArtifact=$(get_octopusvariable \"ConvexExport.CaptureAsArtifact\")\ncmdTimeout=$(get_octopusvariable \"ConvexExport.CommandTimeout\")\n\nif [ -z \"$deployKey\" ]; then\n echo \"ERROR: ConvexExport.DeployKey is required.\"\n exit 1\nfi\n\nif [ -z \"$deploymentType\" ]; then\n deploymentType=\"prod\"\nfi\n\nif [ -z \"$cmdTimeout\" ]; then\n cmdTimeout=\"600\"\nfi\n\nexport CONVEX_DEPLOY_KEY=\"$deployKey\"\n\nif [ -n \"$workingDir\" ]; then\n echo \"Changing to working directory: $workingDir\"\n cd \"$workingDir\" || { echo \"ERROR: Could not change to directory '$workingDir'\"; exit 1; }\nfi\n\ntimestamp=$(date +\"%Y%m%d_%H%M%S\")\n\nif [ -z \"$outputPath\" ]; then\n outputPath=\"convex-export-${timestamp}.zip\"\nfi\n\ndeploymentFlag=\"\"\ncase \"$deploymentType\" in\n prod)\n deploymentFlag=\"--prod\"\n ;;\n preview)\n if [ -z \"$previewName\" ]; then\n echo \"ERROR: ConvexExport.PreviewName is required when deployment type is 'preview'.\"\n exit 1\n fi\n deploymentFlag=\"--preview-name $previewName\"\n ;;\n dev)\n deploymentFlag=\"\"\n ;;\nesac\n\nensure_node() {\n if command -v npx &>/dev/null; then\n echo \"Node.js found: $(node --version)\"\n return 0\n fi\n export NVM_DIR=\"${NVM_DIR:-$HOME/.nvm}\"\n if [ -s \"$NVM_DIR/nvm.sh\" ]; then\n \\. \"$NVM_DIR/nvm.sh\"\n if command -v npx &>/dev/null; then\n echo \"Node.js loaded via nvm: $(node --version)\"\n return 0\n fi\n fi\n echo \"Node.js not found. Installing via nvm...\"\n curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash\n \\. \"$NVM_DIR/nvm.sh\"\n nvm install --lts\n echo \"Node.js installed: $(node --version)\"\n}\nensure_node\n\necho \"Exporting Convex data from: $deploymentType\"\necho \"Output file: $outputPath\"\n\ntimeout \"$cmdTimeout\" npx convex export $deploymentFlag --path \"$outputPath\"\n\nexitCode=$?\nif [ $exitCode -ne 0 ]; then\n echo \"ERROR: Convex export failed with exit code $exitCode.\"\n exit $exitCode\nfi\n\nif [ ! -f \"$outputPath\" ]; then\n echo \"ERROR: Export completed but output file not found at '$outputPath'.\"\n exit 1\nfi\n\nfileSize=$(du -sh \"$outputPath\" | cut -f1)\necho \"Export complete. File: $outputPath ($fileSize)\"\n\nif [ \"$captureArtifact\" = \"True\" ]; then\n new_octopusartifact \"$outputPath\"\n echo \"Export captured as Octopus artifact.\"\nfi\n" }, "Parameters": [ { diff --git a/step-templates/convex-run-function.json b/step-templates/convex-run-function.json index ef5aa2745..d44f9d07d 100644 --- a/step-templates/convex-run-function.json +++ b/step-templates/convex-run-function.json @@ -9,7 +9,7 @@ "Properties": { "Octopus.Action.Script.ScriptSource": "Inline", "Octopus.Action.Script.Syntax": "Bash", - "Octopus.Action.Script.ScriptBody": "deployKey=$(get_octopusvariable \"ConvexRun.DeployKey\")\nfunctionPath=$(get_octopusvariable \"ConvexRun.FunctionPath\")\nfunctionArgs=$(get_octopusvariable \"ConvexRun.FunctionArgs\")\ndeploymentType=$(get_octopusvariable \"ConvexRun.DeploymentType\")\npreviewName=$(get_octopusvariable \"ConvexRun.PreviewName\")\nworkingDir=$(get_octopusvariable \"ConvexRun.WorkingDirectory\")\ncmdTimeout=$(get_octopusvariable \"ConvexRun.CommandTimeout\")\n\nif [ -z \"$deployKey\" ]; then\n echo \"ERROR: ConvexRun.DeployKey is required.\"\n exit 1\nfi\n\nif [ -z \"$functionPath\" ]; then\n echo \"ERROR: ConvexRun.FunctionPath is required.\"\n exit 1\nfi\n\nif [ -z \"$deploymentType\" ]; then\n deploymentType=\"prod\"\nfi\n\nif [ -z \"$cmdTimeout\" ]; then\n cmdTimeout=\"120\"\nfi\n\nexport CONVEX_DEPLOY_KEY=\"$deployKey\"\n\nif [ -n \"$workingDir\" ]; then\n echo \"Changing to working directory: $workingDir\"\n cd \"$workingDir\" || { echo \"ERROR: Could not change to directory '$workingDir'\"; exit 1; }\nfi\n\ndeploymentFlag=\"\"\ncase \"$deploymentType\" in\n prod)\n deploymentFlag=\"--prod\"\n ;;\n preview)\n if [ -z \"$previewName\" ]; then\n echo \"ERROR: ConvexRun.PreviewName is required when deployment type is 'preview'.\"\n exit 1\n fi\n deploymentFlag=\"--preview-name $previewName\"\n ;;\n dev)\n deploymentFlag=\"\"\n ;;\nesac\n\necho \"Running Convex function: $functionPath\"\necho \"Deployment type: $deploymentType\"\n\nif [ -n \"$functionArgs\" ]; then\n echo \"Args: $functionArgs\"\n timeout \"$cmdTimeout\" npx convex run $deploymentFlag \"$functionPath\" \"$functionArgs\"\nelse\n timeout \"$cmdTimeout\" npx convex run $deploymentFlag \"$functionPath\"\nfi\n\nexitCode=$?\nif [ $exitCode -ne 0 ]; then\n echo \"ERROR: Convex function '$functionPath' failed with exit code $exitCode.\"\n exit $exitCode\nfi\n\necho \"Convex function '$functionPath' completed successfully.\"\n" + "Octopus.Action.Script.ScriptBody": "deployKey=$(get_octopusvariable \"ConvexRun.DeployKey\")\nfunctionPath=$(get_octopusvariable \"ConvexRun.FunctionPath\")\nfunctionArgs=$(get_octopusvariable \"ConvexRun.FunctionArgs\")\ndeploymentType=$(get_octopusvariable \"ConvexRun.DeploymentType\")\npreviewName=$(get_octopusvariable \"ConvexRun.PreviewName\")\nworkingDir=$(get_octopusvariable \"ConvexRun.WorkingDirectory\")\ncmdTimeout=$(get_octopusvariable \"ConvexRun.CommandTimeout\")\n\nif [ -z \"$deployKey\" ]; then\n echo \"ERROR: ConvexRun.DeployKey is required.\"\n exit 1\nfi\n\nif [ -z \"$functionPath\" ]; then\n echo \"ERROR: ConvexRun.FunctionPath is required.\"\n exit 1\nfi\n\nif [ -z \"$deploymentType\" ]; then\n deploymentType=\"prod\"\nfi\n\nif [ -z \"$cmdTimeout\" ]; then\n cmdTimeout=\"120\"\nfi\n\nexport CONVEX_DEPLOY_KEY=\"$deployKey\"\n\nif [ -n \"$workingDir\" ]; then\n echo \"Changing to working directory: $workingDir\"\n cd \"$workingDir\" || { echo \"ERROR: Could not change to directory '$workingDir'\"; exit 1; }\nfi\n\ndeploymentFlag=\"\"\ncase \"$deploymentType\" in\n prod)\n deploymentFlag=\"--prod\"\n ;;\n preview)\n if [ -z \"$previewName\" ]; then\n echo \"ERROR: ConvexRun.PreviewName is required when deployment type is 'preview'.\"\n exit 1\n fi\n deploymentFlag=\"--preview-name $previewName\"\n ;;\n dev)\n deploymentFlag=\"\"\n ;;\nesac\n\nensure_node() {\n if command -v npx &>/dev/null; then\n echo \"Node.js found: $(node --version)\"\n return 0\n fi\n export NVM_DIR=\"${NVM_DIR:-$HOME/.nvm}\"\n if [ -s \"$NVM_DIR/nvm.sh\" ]; then\n \\. \"$NVM_DIR/nvm.sh\"\n if command -v npx &>/dev/null; then\n echo \"Node.js loaded via nvm: $(node --version)\"\n return 0\n fi\n fi\n echo \"Node.js not found. Installing via nvm...\"\n curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash\n \\. \"$NVM_DIR/nvm.sh\"\n nvm install --lts\n echo \"Node.js installed: $(node --version)\"\n}\nensure_node\n\necho \"Running Convex function: $functionPath\"\necho \"Deployment type: $deploymentType\"\n\nif [ -n \"$functionArgs\" ]; then\n echo \"Args: $functionArgs\"\n timeout \"$cmdTimeout\" npx convex run $deploymentFlag \"$functionPath\" \"$functionArgs\"\nelse\n timeout \"$cmdTimeout\" npx convex run $deploymentFlag \"$functionPath\"\nfi\n\nexitCode=$?\nif [ $exitCode -ne 0 ]; then\n echo \"ERROR: Convex function '$functionPath' failed with exit code $exitCode.\"\n exit $exitCode\nfi\n\necho \"Convex function '$functionPath' completed successfully.\"\n" }, "Parameters": [ { diff --git a/step-templates/convex-set-environment-variables.json b/step-templates/convex-set-environment-variables.json index 275aebd6e..82cc87c71 100644 --- a/step-templates/convex-set-environment-variables.json +++ b/step-templates/convex-set-environment-variables.json @@ -9,7 +9,7 @@ "Properties": { "Octopus.Action.Script.ScriptSource": "Inline", "Octopus.Action.Script.Syntax": "Bash", - "Octopus.Action.Script.ScriptBody": "deployKey=$(get_octopusvariable \"ConvexEnvSet.DeployKey\")\nenvVars=$(get_octopusvariable \"ConvexEnvSet.EnvironmentVariables\")\ndeploymentType=$(get_octopusvariable \"ConvexEnvSet.DeploymentType\")\npreviewName=$(get_octopusvariable \"ConvexEnvSet.PreviewName\")\nworkingDir=$(get_octopusvariable \"ConvexEnvSet.WorkingDirectory\")\n\nif [ -z \"$deployKey\" ]; then\n echo \"ERROR: ConvexEnvSet.DeployKey is required.\"\n exit 1\nfi\n\nif [ -z \"$envVars\" ]; then\n echo \"ERROR: ConvexEnvSet.EnvironmentVariables is required.\"\n exit 1\nfi\n\nif [ -z \"$deploymentType\" ]; then\n deploymentType=\"prod\"\nfi\n\nexport CONVEX_DEPLOY_KEY=\"$deployKey\"\n\nif [ -n \"$workingDir\" ]; then\n echo \"Changing to working directory: $workingDir\"\n cd \"$workingDir\" || { echo \"ERROR: Could not change to directory '$workingDir'\"; exit 1; }\nfi\n\ndeploymentFlag=\"\"\ncase \"$deploymentType\" in\n prod)\n deploymentFlag=\"--prod\"\n ;;\n preview)\n if [ -z \"$previewName\" ]; then\n echo \"ERROR: ConvexEnvSet.PreviewName is required when deployment type is 'preview'.\"\n exit 1\n fi\n deploymentFlag=\"--preview-name $previewName\"\n ;;\n dev)\n deploymentFlag=\"\"\n ;;\nesac\n\necho \"Setting environment variables on Convex deployment ($deploymentType)...\"\n\nsuccessCount=0\nfailCount=0\n\nwhile IFS= read -r line; do\n line=$(echo \"$line\" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')\n [ -z \"$line\" ] && continue\n [[ \"$line\" == \\#* ]] && continue\n\n if [[ \"$line\" != *=* ]]; then\n echo \"WARNING: Skipping malformed entry (no '=' found): $line\"\n continue\n fi\n\n key=\"${line%%=*}\"\n value=\"${line#*=}\"\n\n echo \"Setting: $key\"\n if npx convex env set $deploymentFlag \"$key\" \"$value\"; then\n successCount=$((successCount + 1))\n else\n echo \"ERROR: Failed to set variable '$key'.\"\n failCount=$((failCount + 1))\n fi\ndone <<< \"$envVars\"\n\necho \"Done. $successCount variable(s) set successfully, $failCount failed.\"\n\nif [ \"$failCount\" -gt 0 ]; then\n exit 1\nfi\n" + "Octopus.Action.Script.ScriptBody": "deployKey=$(get_octopusvariable \"ConvexEnvSet.DeployKey\")\nenvVars=$(get_octopusvariable \"ConvexEnvSet.EnvironmentVariables\")\ndeploymentType=$(get_octopusvariable \"ConvexEnvSet.DeploymentType\")\npreviewName=$(get_octopusvariable \"ConvexEnvSet.PreviewName\")\nworkingDir=$(get_octopusvariable \"ConvexEnvSet.WorkingDirectory\")\n\nif [ -z \"$deployKey\" ]; then\n echo \"ERROR: ConvexEnvSet.DeployKey is required.\"\n exit 1\nfi\n\nif [ -z \"$envVars\" ]; then\n echo \"ERROR: ConvexEnvSet.EnvironmentVariables is required.\"\n exit 1\nfi\n\nif [ -z \"$deploymentType\" ]; then\n deploymentType=\"prod\"\nfi\n\nexport CONVEX_DEPLOY_KEY=\"$deployKey\"\n\nif [ -n \"$workingDir\" ]; then\n echo \"Changing to working directory: $workingDir\"\n cd \"$workingDir\" || { echo \"ERROR: Could not change to directory '$workingDir'\"; exit 1; }\nfi\n\ndeploymentFlag=\"\"\ncase \"$deploymentType\" in\n prod)\n deploymentFlag=\"--prod\"\n ;;\n preview)\n if [ -z \"$previewName\" ]; then\n echo \"ERROR: ConvexEnvSet.PreviewName is required when deployment type is 'preview'.\"\n exit 1\n fi\n deploymentFlag=\"--preview-name $previewName\"\n ;;\n dev)\n deploymentFlag=\"\"\n ;;\nesac\n\nensure_node() {\n if command -v npx &>/dev/null; then\n echo \"Node.js found: $(node --version)\"\n return 0\n fi\n export NVM_DIR=\"${NVM_DIR:-$HOME/.nvm}\"\n if [ -s \"$NVM_DIR/nvm.sh\" ]; then\n \\. \"$NVM_DIR/nvm.sh\"\n if command -v npx &>/dev/null; then\n echo \"Node.js loaded via nvm: $(node --version)\"\n return 0\n fi\n fi\n echo \"Node.js not found. Installing via nvm...\"\n curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash\n \\. \"$NVM_DIR/nvm.sh\"\n nvm install --lts\n echo \"Node.js installed: $(node --version)\"\n}\nensure_node\n\necho \"Setting environment variables on Convex deployment ($deploymentType)...\"\n\nsuccessCount=0\nfailCount=0\n\nwhile IFS= read -r line; do\n line=$(echo \"$line\" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')\n [ -z \"$line\" ] && continue\n [[ \"$line\" == \\#* ]] && continue\n\n if [[ \"$line\" != *=* ]]; then\n echo \"WARNING: Skipping malformed entry (no '=' found): $line\"\n continue\n fi\n\n key=\"${line%%=*}\"\n value=\"${line#*=}\"\n\n echo \"Setting: $key\"\n if npx convex env set $deploymentFlag \"$key\" \"$value\"; then\n successCount=$((successCount + 1))\n else\n echo \"ERROR: Failed to set variable '$key'.\"\n failCount=$((failCount + 1))\n fi\ndone <<< \"$envVars\"\n\necho \"Done. $successCount variable(s) set successfully, $failCount failed.\"\n\nif [ \"$failCount\" -gt 0 ]; then\n exit 1\nfi\n" }, "Parameters": [ { From c58e36d933b907cff21d67b0a6783e7d041354b7 Mon Sep 17 00:00:00 2001 From: Ben <105687719+ben-octo-data-dev@users.noreply.github.com> Date: Fri, 29 May 2026 17:29:56 +0800 Subject: [PATCH 3/3] Add npm install to deploy step --- step-templates/convex-deploy.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/step-templates/convex-deploy.json b/step-templates/convex-deploy.json index 85708fb50..d135135cb 100644 --- a/step-templates/convex-deploy.json +++ b/step-templates/convex-deploy.json @@ -9,7 +9,7 @@ "Properties": { "Octopus.Action.Script.ScriptSource": "Inline", "Octopus.Action.Script.Syntax": "Bash", - "Octopus.Action.Script.ScriptBody": "deployKey=$(get_octopusvariable \"ConvexDeploy.DeployKey\")\ndeploymentType=$(get_octopusvariable \"ConvexDeploy.DeploymentType\")\npreviewName=$(get_octopusvariable \"ConvexDeploy.PreviewName\")\nworkingDir=$(get_octopusvariable \"ConvexDeploy.WorkingDirectory\")\ncmdTimeout=$(get_octopusvariable \"ConvexDeploy.CommandTimeout\")\n\nif [ -z \"$deployKey\" ]; then\n echo \"ERROR: ConvexDeploy.DeployKey is required.\"\n exit 1\nfi\n\nif [ -z \"$deploymentType\" ]; then\n deploymentType=\"prod\"\nfi\n\nif [ -z \"$cmdTimeout\" ]; then\n cmdTimeout=\"300\"\nfi\n\nexport CONVEX_DEPLOY_KEY=\"$deployKey\"\n\nif [ -n \"$workingDir\" ]; then\n echo \"Changing to working directory: $workingDir\"\n cd \"$workingDir\" || { echo \"ERROR: Could not change to directory '$workingDir'\"; exit 1; }\nfi\n\nensure_node() {\n if command -v npx &>/dev/null; then\n echo \"Node.js found: $(node --version)\"\n return 0\n fi\n export NVM_DIR=\"${NVM_DIR:-$HOME/.nvm}\"\n if [ -s \"$NVM_DIR/nvm.sh\" ]; then\n \\. \"$NVM_DIR/nvm.sh\"\n if command -v npx &>/dev/null; then\n echo \"Node.js loaded via nvm: $(node --version)\"\n return 0\n fi\n fi\n echo \"Node.js not found. Installing via nvm...\"\n curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash\n \\. \"$NVM_DIR/nvm.sh\"\n nvm install --lts\n echo \"Node.js installed: $(node --version)\"\n}\nensure_node\n\necho \"Convex deployment type: $deploymentType\"\n\ncase \"$deploymentType\" in\n prod)\n echo \"Deploying to production...\"\n timeout \"$cmdTimeout\" npx convex deploy --yes\n ;;\n preview)\n if [ -z \"$previewName\" ]; then\n echo \"ERROR: ConvexDeploy.PreviewName is required when deployment type is 'preview'.\"\n exit 1\n fi\n echo \"Deploying to preview deployment: $previewName\"\n timeout \"$cmdTimeout\" npx convex deploy --preview-name \"$previewName\" --yes\n ;;\n dev)\n echo \"Deploying to dev deployment...\"\n timeout \"$cmdTimeout\" npx convex deploy --yes\n ;;\n *)\n echo \"ERROR: Unknown deployment type '$deploymentType'. Must be one of: prod, preview, dev\"\n exit 1\n ;;\nesac\n\nif [ $? -ne 0 ]; then\n echo \"ERROR: Convex deployment failed.\"\n exit 1\nfi\n\necho \"Convex deployment completed successfully.\"\n" + "Octopus.Action.Script.ScriptBody": "deployKey=$(get_octopusvariable \"ConvexDeploy.DeployKey\")\ndeploymentType=$(get_octopusvariable \"ConvexDeploy.DeploymentType\")\npreviewName=$(get_octopusvariable \"ConvexDeploy.PreviewName\")\nworkingDir=$(get_octopusvariable \"ConvexDeploy.WorkingDirectory\")\ncmdTimeout=$(get_octopusvariable \"ConvexDeploy.CommandTimeout\")\n\nif [ -z \"$deployKey\" ]; then\n echo \"ERROR: ConvexDeploy.DeployKey is required.\"\n exit 1\nfi\n\nif [ -z \"$deploymentType\" ]; then\n deploymentType=\"prod\"\nfi\n\nif [ -z \"$cmdTimeout\" ]; then\n cmdTimeout=\"300\"\nfi\n\nexport CONVEX_DEPLOY_KEY=\"$deployKey\"\n\nif [ -n \"$workingDir\" ]; then\n echo \"Changing to working directory: $workingDir\"\n cd \"$workingDir\" || { echo \"ERROR: Could not change to directory '$workingDir'\"; exit 1; }\nfi\n\nensure_node() {\n if command -v npx &>/dev/null; then\n echo \"Node.js found: $(node --version)\"\n return 0\n fi\n export NVM_DIR=\"${NVM_DIR:-$HOME/.nvm}\"\n if [ -s \"$NVM_DIR/nvm.sh\" ]; then\n \\. \"$NVM_DIR/nvm.sh\"\n if command -v npx &>/dev/null; then\n echo \"Node.js loaded via nvm: $(node --version)\"\n return 0\n fi\n fi\n echo \"Node.js not found. Installing via nvm...\"\n curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash\n \\. \"$NVM_DIR/nvm.sh\"\n nvm install --lts\n echo \"Node.js installed: $(node --version)\"\n}\nensure_node\n\necho \"Installing dependencies...\"\nnpm install\n\necho \"Convex deployment type: $deploymentType\"\n\ncase \"$deploymentType\" in\n prod)\n echo \"Deploying to production...\"\n timeout \"$cmdTimeout\" npx convex deploy --yes\n ;;\n preview)\n if [ -z \"$previewName\" ]; then\n echo \"ERROR: ConvexDeploy.PreviewName is required when deployment type is 'preview'.\"\n exit 1\n fi\n echo \"Deploying to preview deployment: $previewName\"\n timeout \"$cmdTimeout\" npx convex deploy --preview-name \"$previewName\" --yes\n ;;\n dev)\n echo \"Deploying to dev deployment...\"\n timeout \"$cmdTimeout\" npx convex deploy --yes\n ;;\n *)\n echo \"ERROR: Unknown deployment type '$deploymentType'. Must be one of: prod, preview, dev\"\n exit 1\n ;;\nesac\n\nif [ $? -ne 0 ]; then\n echo \"ERROR: Convex deployment failed.\"\n exit 1\nfi\n\necho \"Convex deployment completed successfully.\"\n" }, "Parameters": [ {