Skip to content

Commit 2b28cc2

Browse files
Add step templates for Convex backend deployments (#1687)
* Add convex steps * Add npm package * Add npm install to deploy step --------- Co-authored-by: Ben <105687719+ben-octo-data-dev@users.noreply.github.com>
1 parent 05b85d6 commit 2b28cc2

8 files changed

Lines changed: 454 additions & 2 deletions

gulpfile.babel.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,8 @@ function humanize(categoryId) {
186186
return "Chef";
187187
case "clickonce":
188188
return "ClickOnce";
189+
case "convex":
190+
return "Convex";
189191
case "cyberark":
190192
return "CyberArk";
191193
case "dll":

step-templates/convex-deploy.json

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
{
2+
"Id": "22a4a875-e5fb-44c9-86d9-16911e58c0f0",
3+
"Name": "Convex - Deploy",
4+
"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.",
5+
"ActionType": "Octopus.Script",
6+
"Version": 1,
7+
"CommunityActionTemplateId": null,
8+
"Packages": [],
9+
"Properties": {
10+
"Octopus.Action.Script.ScriptSource": "Inline",
11+
"Octopus.Action.Script.Syntax": "Bash",
12+
"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"
13+
},
14+
"Parameters": [
15+
{
16+
"Id": "6727833e-b393-470c-ab79-e72c3749e402",
17+
"Name": "ConvexDeploy.DeployKey",
18+
"Label": "Deploy Key",
19+
"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)",
20+
"DefaultValue": "",
21+
"DisplaySettings": {
22+
"Octopus.ControlType": "Sensitive"
23+
}
24+
},
25+
{
26+
"Id": "0b361a83-c5b8-441e-846a-9bc88b2d7114",
27+
"Name": "ConvexDeploy.DeploymentType",
28+
"Label": "Deployment Type",
29+
"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",
30+
"DefaultValue": "prod",
31+
"DisplaySettings": {
32+
"Octopus.ControlType": "Select",
33+
"Octopus.SelectOptions": "prod|Production\npreview|Preview\ndev|Development"
34+
}
35+
},
36+
{
37+
"Id": "8adff0dc-16d9-44ff-b05a-fcb7b92ff3ce",
38+
"Name": "ConvexDeploy.PreviewName",
39+
"Label": "Preview Name",
40+
"HelpText": "The name of the preview deployment. Only required when **Deployment Type** is set to `preview`.",
41+
"DefaultValue": "",
42+
"DisplaySettings": {
43+
"Octopus.ControlType": "SingleLineText"
44+
}
45+
},
46+
{
47+
"Id": "dc368708-12b9-4d03-aeda-e7cd8e8326c3",
48+
"Name": "ConvexDeploy.WorkingDirectory",
49+
"Label": "Working Directory",
50+
"HelpText": "Optional. The directory containing your Convex project (where `convex/` lives). Defaults to the current working directory if left blank.",
51+
"DefaultValue": "",
52+
"DisplaySettings": {
53+
"Octopus.ControlType": "SingleLineText"
54+
}
55+
},
56+
{
57+
"Id": "17fc0144-7fdc-4c5b-80fb-7143d503fef6",
58+
"Name": "ConvexDeploy.CommandTimeout",
59+
"Label": "Command Timeout (seconds)",
60+
"HelpText": "Maximum number of seconds to wait for the deploy command to complete. Defaults to 300 (5 minutes).",
61+
"DefaultValue": "300",
62+
"DisplaySettings": {
63+
"Octopus.ControlType": "SingleLineText"
64+
}
65+
}
66+
],
67+
"LastModifiedBy": "itsmebenwalker",
68+
"$Meta": {
69+
"ExportedAt": "2026-05-29T00:00:00.000Z",
70+
"OctopusVersion": "2026.1.0",
71+
"Type": "ActionTemplate"
72+
},
73+
"Category": "convex"
74+
}
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
{
2+
"Id": "3f4519f7-78f6-4fb9-8bc5-97e138825bb8",
3+
"Name": "Convex - Export Data",
4+
"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.",
5+
"ActionType": "Octopus.Script",
6+
"Version": 1,
7+
"CommunityActionTemplateId": null,
8+
"Packages": [],
9+
"Properties": {
10+
"Octopus.Action.Script.ScriptSource": "Inline",
11+
"Octopus.Action.Script.Syntax": "Bash",
12+
"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"
13+
},
14+
"Parameters": [
15+
{
16+
"Id": "ba76acd0-99e4-4aa1-8554-e0696b528ed7",
17+
"Name": "ConvexExport.DeployKey",
18+
"Label": "Deploy Key",
19+
"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)",
20+
"DefaultValue": "",
21+
"DisplaySettings": {
22+
"Octopus.ControlType": "Sensitive"
23+
}
24+
},
25+
{
26+
"Id": "17b1f813-7b43-4528-bafe-5b52eac6df1b",
27+
"Name": "ConvexExport.OutputPath",
28+
"Label": "Output File Path",
29+
"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.",
30+
"DefaultValue": "",
31+
"DisplaySettings": {
32+
"Octopus.ControlType": "SingleLineText"
33+
}
34+
},
35+
{
36+
"Id": "e7002edd-eb0d-4c2b-979e-972c095eede5",
37+
"Name": "ConvexExport.DeploymentType",
38+
"Label": "Deployment Type",
39+
"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",
40+
"DefaultValue": "prod",
41+
"DisplaySettings": {
42+
"Octopus.ControlType": "Select",
43+
"Octopus.SelectOptions": "prod|Production\npreview|Preview\ndev|Development"
44+
}
45+
},
46+
{
47+
"Id": "81526834-4204-4696-bfc4-3e965dcb320d",
48+
"Name": "ConvexExport.PreviewName",
49+
"Label": "Preview Name",
50+
"HelpText": "The name of the preview deployment. Only required when **Deployment Type** is `preview`.",
51+
"DefaultValue": "",
52+
"DisplaySettings": {
53+
"Octopus.ControlType": "SingleLineText"
54+
}
55+
},
56+
{
57+
"Id": "690649ca-3801-45d1-9a59-45e561c127f5",
58+
"Name": "ConvexExport.WorkingDirectory",
59+
"Label": "Working Directory",
60+
"HelpText": "Optional. Path to the directory containing your Convex project. Defaults to the current working directory if left blank.",
61+
"DefaultValue": "",
62+
"DisplaySettings": {
63+
"Octopus.ControlType": "SingleLineText"
64+
}
65+
},
66+
{
67+
"Id": "036c1260-7b14-4c05-8948-858cc1b5c893",
68+
"Name": "ConvexExport.CaptureAsArtifact",
69+
"Label": "Capture as Octopus Artifact",
70+
"HelpText": "When enabled, the exported file will be captured as an Octopus build artifact, making it available for download from the deployment details page.",
71+
"DefaultValue": "True",
72+
"DisplaySettings": {
73+
"Octopus.ControlType": "Checkbox"
74+
}
75+
},
76+
{
77+
"Id": "186fac8e-92c9-482f-adea-551cb64dd999",
78+
"Name": "ConvexExport.CommandTimeout",
79+
"Label": "Command Timeout (seconds)",
80+
"HelpText": "Maximum number of seconds to wait for the export to complete. Defaults to 600 (10 minutes). Large datasets may require a higher value.",
81+
"DefaultValue": "600",
82+
"DisplaySettings": {
83+
"Octopus.ControlType": "SingleLineText"
84+
}
85+
}
86+
],
87+
"LastModifiedBy": "itsmebenwalker",
88+
"$Meta": {
89+
"ExportedAt": "2026-05-29T00:00:00.000Z",
90+
"OctopusVersion": "2026.1.0",
91+
"Type": "ActionTemplate"
92+
},
93+
"Category": "convex"
94+
}
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
{
2+
"Id": "307071fd-c649-4ab6-8b14-549da0943273",
3+
"Name": "Convex - Run Function",
4+
"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.",
5+
"ActionType": "Octopus.Script",
6+
"Version": 1,
7+
"CommunityActionTemplateId": null,
8+
"Packages": [],
9+
"Properties": {
10+
"Octopus.Action.Script.ScriptSource": "Inline",
11+
"Octopus.Action.Script.Syntax": "Bash",
12+
"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"
13+
},
14+
"Parameters": [
15+
{
16+
"Id": "2768e849-72d0-4542-a60e-cc7596a1da91",
17+
"Name": "ConvexRun.DeployKey",
18+
"Label": "Deploy Key",
19+
"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)",
20+
"DefaultValue": "",
21+
"DisplaySettings": {
22+
"Octopus.ControlType": "Sensitive"
23+
}
24+
},
25+
{
26+
"Id": "717bb5dd-7e32-4689-8016-bf781d612051",
27+
"Name": "ConvexRun.FunctionPath",
28+
"Label": "Function Path",
29+
"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`",
30+
"DefaultValue": "",
31+
"DisplaySettings": {
32+
"Octopus.ControlType": "SingleLineText"
33+
}
34+
},
35+
{
36+
"Id": "282ce782-e9dc-4cad-a3c2-68fecebda89b",
37+
"Name": "ConvexRun.FunctionArgs",
38+
"Label": "Function Arguments (JSON)",
39+
"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.",
40+
"DefaultValue": "",
41+
"DisplaySettings": {
42+
"Octopus.ControlType": "MultiLineText"
43+
}
44+
},
45+
{
46+
"Id": "6cb1f84c-16af-4cfe-aaef-a3b8bb37d0bf",
47+
"Name": "ConvexRun.DeploymentType",
48+
"Label": "Deployment Type",
49+
"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",
50+
"DefaultValue": "prod",
51+
"DisplaySettings": {
52+
"Octopus.ControlType": "Select",
53+
"Octopus.SelectOptions": "prod|Production\npreview|Preview\ndev|Development"
54+
}
55+
},
56+
{
57+
"Id": "8e0918a3-4625-4830-80fd-1b330da2101d",
58+
"Name": "ConvexRun.PreviewName",
59+
"Label": "Preview Name",
60+
"HelpText": "The name of the preview deployment. Only required when **Deployment Type** is `preview`.",
61+
"DefaultValue": "",
62+
"DisplaySettings": {
63+
"Octopus.ControlType": "SingleLineText"
64+
}
65+
},
66+
{
67+
"Id": "fe0a3a69-6a44-4dcb-ba71-0b1e1546ea25",
68+
"Name": "ConvexRun.WorkingDirectory",
69+
"Label": "Working Directory",
70+
"HelpText": "Optional. Path to the directory containing your Convex project. Defaults to the current working directory if left blank.",
71+
"DefaultValue": "",
72+
"DisplaySettings": {
73+
"Octopus.ControlType": "SingleLineText"
74+
}
75+
},
76+
{
77+
"Id": "ac421438-68fa-4c33-a984-fa9cd7f9e007",
78+
"Name": "ConvexRun.CommandTimeout",
79+
"Label": "Command Timeout (seconds)",
80+
"HelpText": "Maximum number of seconds to wait for the function to complete. Defaults to 120.",
81+
"DefaultValue": "120",
82+
"DisplaySettings": {
83+
"Octopus.ControlType": "SingleLineText"
84+
}
85+
}
86+
],
87+
"LastModifiedBy": "itsmebenwalker",
88+
"$Meta": {
89+
"ExportedAt": "2026-05-29T00:00:00.000Z",
90+
"OctopusVersion": "2026.1.0",
91+
"Type": "ActionTemplate"
92+
},
93+
"Category": "convex"
94+
}

0 commit comments

Comments
 (0)