@digitalocean/mcp 1.0.22 → 1.0.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/apps/docs/vercel-migration-guide.md +1505 -150
- package/dist/mcp-digitalocean-darwin-amd64 +0 -0
- package/dist/mcp-digitalocean-darwin-arm64 +0 -0
- package/dist/mcp-digitalocean-linux-386 +0 -0
- package/dist/mcp-digitalocean-linux-amd64 +0 -0
- package/dist/mcp-digitalocean-linux-arm +0 -0
- package/dist/mcp-digitalocean-linux-arm64 +0 -0
- package/dist/mcp-digitalocean-windows-386.exe +0 -0
- package/dist/mcp-digitalocean-windows-amd64.exe +0 -0
- package/dist/mcp-digitalocean-windows-arm.exe +0 -0
- package/dist/mcp-digitalocean-windows-arm64.exe +0 -0
- package/package.json +1 -1
|
@@ -1,29 +1,116 @@
|
|
|
1
|
-
# Vercel to App Platform Migration Instructions
|
|
1
|
+
# Vercel to App Platform Migration Instructions (v3)
|
|
2
|
+
|
|
3
|
+
📦 **Version 3 Updates:**
|
|
4
|
+
- **NEW: Step 1.5 - Monorepo Dependency Consolidation** - Critical section on how App Platform handles monorepo dependencies
|
|
5
|
+
- **KEY INSIGHT:** App Platform only installs dependencies from root `package.json` in monorepos
|
|
6
|
+
- **PROACTIVE APPROACH:** Analyze and consolidate dependencies before deployment to avoid build failures
|
|
7
|
+
- **HYBRID STRATEGY:** Combine proactive analysis with fallback iterative fixing for best results
|
|
8
|
+
|
|
9
|
+
⚠️ **Important: This is a Starter Guide for AI Coding Assistants**
|
|
10
|
+
|
|
11
|
+
This guide helps AI coding assistants (Claude Code, Cursor, Gemini, etc.) collaborate with you to deploy applications to DigitalOcean App Platform.
|
|
12
|
+
|
|
13
|
+
**Constants:**
|
|
14
|
+
- **RETRY_LIMIT:** 3
|
|
15
|
+
|
|
16
|
+
**What this guide IS:**
|
|
17
|
+
- A structured workflow for AI-assisted deployment and migration
|
|
18
|
+
- A comprehensive checklist of steps and considerations
|
|
19
|
+
- Assisted error detection with fix suggestions (up to **RETRY_LIMIT** retry attempts)
|
|
20
|
+
- Truthful about limitations and manual steps required
|
|
21
|
+
- A starting point that handles common scenarios
|
|
22
|
+
|
|
23
|
+
**What this guide IS NOT:**
|
|
24
|
+
- A "magic migration button" that works without human oversight
|
|
25
|
+
- A guarantee of 1:1 feature parity with Vercel
|
|
26
|
+
- A replacement for understanding your application's architecture
|
|
27
|
+
- Suitable for highly complex, non-standard architectures without modifications
|
|
28
|
+
- Fully automated - you remain in control of all decisions
|
|
29
|
+
|
|
30
|
+
**Your role (the human):**
|
|
31
|
+
- Understand your application's architecture and requirements
|
|
32
|
+
- Make decisions about trade-offs and implementation approaches
|
|
33
|
+
- Verify deployment results and test functionality
|
|
34
|
+
- Implement code changes for unsupported features
|
|
35
|
+
- Monitor and validate production deployment
|
|
36
|
+
|
|
37
|
+
**AI assistant's role:**
|
|
38
|
+
- Guide you through the migration process step-by-step
|
|
39
|
+
- Automate repository and infrastructure setup tasks
|
|
40
|
+
- Detect common errors and suggest fixes
|
|
41
|
+
- Provide alternatives for unsupported features
|
|
42
|
+
- Generate configuration files and commands
|
|
43
|
+
|
|
44
|
+
**Success requires active collaboration between you and your AI assistant.**
|
|
2
45
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
## Initial Setup
|
|
46
|
+
---
|
|
6
47
|
|
|
7
|
-
|
|
48
|
+
## Supported Deployment Scenarios
|
|
8
49
|
|
|
9
|
-
|
|
50
|
+
This guide supports multiple scenarios:
|
|
51
|
+
1. **Migrating from existing Vercel deployment** - Moving a working Vercel app to App Platform (with or without Vercel CLI access)
|
|
52
|
+
2. **Deploying from GitHub repository** - App may be running on Vercel, but you just provide the repo to deploy to App Platform
|
|
53
|
+
3. **Deploying source code directly** - Getting source code working on App Platform (no Vercel deployment required)
|
|
54
|
+
4. **Deploying without repository access** - Creating new repository or deploying from local source
|
|
10
55
|
|
|
11
|
-
|
|
12
|
-
- You have access to **Vercel MCP server** and **DigitalOcean MCP server**
|
|
13
|
-
- **Vercel CLI is installed** (`vercel` command available) - **Required for retrieving environment variables**
|
|
14
|
-
- Check if the current directory is a github repository and it is the same as the project that needs to be migrated
|
|
15
|
-
- Clone the repository to local disk if code change is needed
|
|
16
|
-
- User has confirmed they want to proceed with migration
|
|
56
|
+
Follow these instructions carefully to ensure a smooth deployment.
|
|
17
57
|
|
|
18
|
-
|
|
19
|
-
1. Installed Vercel CLI: `npm i -g vercel`
|
|
20
|
-
2. Authenticated: `vercel login`
|
|
58
|
+
## Initial Setup
|
|
21
59
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
60
|
+
### Determine Deployment Scenario
|
|
61
|
+
|
|
62
|
+
First, determine the user's scenario:
|
|
63
|
+
|
|
64
|
+
1. **Scenario A: Full Vercel Migration (with credentials)**
|
|
65
|
+
- User has an existing live Vercel app they want to migrate
|
|
66
|
+
- User has access to Vercel account/CLI
|
|
67
|
+
- Ask for the Vercel app name
|
|
68
|
+
- Will use Vercel CLI to pull environment variables and app configuration
|
|
69
|
+
- Will migrate domains and settings
|
|
70
|
+
|
|
71
|
+
2. **Scenario B: Repository-based Deployment (app may be on Vercel)**
|
|
72
|
+
- User provides a GitHub repository URL
|
|
73
|
+
- App may or may not be currently running on Vercel
|
|
74
|
+
- User says: "Here's my GitHub repo, deploy it to App Platform"
|
|
75
|
+
- No need for Vercel CLI access - work directly from repository
|
|
76
|
+
- Environment variables collected manually from .env.example or user input
|
|
77
|
+
|
|
78
|
+
3. **Scenario C: Source Code Only (no Vercel, no repo)**
|
|
79
|
+
- User has source code and wants to deploy to App Platform
|
|
80
|
+
- No Vercel deployment exists
|
|
81
|
+
- May or may not have existing GitHub repository
|
|
82
|
+
- Goal is to get the application working on App Platform
|
|
83
|
+
|
|
84
|
+
4. **Scenario D: No Repository Access**
|
|
85
|
+
- User wants to deploy without giving access to personal/private repo
|
|
86
|
+
- Can create new repository in their account using `gh` CLI
|
|
87
|
+
- Can fork existing repository
|
|
88
|
+
- Can deploy from local source (less recommended)
|
|
89
|
+
|
|
90
|
+
**For most migrations:** Scenario A or B are most common. Scenario B is simpler if user doesn't need/want to provide Vercel credentials.
|
|
91
|
+
|
|
92
|
+
### Verify Available Tools
|
|
93
|
+
|
|
94
|
+
**Primary Method: CLI Tools (Recommended)**
|
|
95
|
+
- **doctl CLI:** Primary method for App Platform operations (create apps, manage deployments, configure domains)
|
|
96
|
+
- **gh CLI:** For GitHub repository operations (create repo, fork, push code)
|
|
97
|
+
- **Vercel CLI (if migrating from Vercel):** For pulling environment variables and app details
|
|
98
|
+
|
|
99
|
+
**Alternative Method: MCP Servers (Optional)**
|
|
100
|
+
- **Vercel MCP server:** For project information (where available) - Optional
|
|
101
|
+
- **DigitalOcean MCP server:** For App Platform operations - Optional
|
|
102
|
+
- **Note:** CLI tools are preferred and don't require MCP server setup
|
|
103
|
+
|
|
104
|
+
**Verify available tools:**
|
|
105
|
+
- Check `doctl` is installed and authenticated: `doctl auth list`
|
|
106
|
+
- Check `gh` CLI is installed and authenticated: `gh auth status`
|
|
107
|
+
- If migrating from Vercel, check `vercel` CLI is installed: `vercel --version`
|
|
108
|
+
|
|
109
|
+
**Important Notes:**
|
|
110
|
+
- **CLI tools are the primary method** - MCP servers are optional
|
|
111
|
+
- Users don't need MCP servers - `doctl` and `gh` CLI are sufficient
|
|
112
|
+
- If user doesn't have a GitHub repository, we can create one using `gh` CLI
|
|
113
|
+
- If user doesn't want to give repo access, we can deploy from local source or create new repo
|
|
27
114
|
|
|
28
115
|
## Relevant App Platform Documentations
|
|
29
116
|
|
|
@@ -33,9 +120,70 @@ Then verify:
|
|
|
33
120
|
|
|
34
121
|
## Migration Process
|
|
35
122
|
|
|
36
|
-
### Step
|
|
123
|
+
### Step 0: Local Testing and Validation (Recommended)
|
|
124
|
+
|
|
125
|
+
**Before deploying to App Platform, test locally to catch issues early and avoid deployment wait time.**
|
|
126
|
+
|
|
127
|
+
1. **Verify local environment:**
|
|
128
|
+
- Check Node.js version: `node --version`
|
|
129
|
+
- Check package manager: `pnpm --version`, `npm --version`, or `yarn --version`
|
|
130
|
+
- Verify lockfile exists: `pnpm-lock.yaml`, `package-lock.json`, or `yarn.lock`
|
|
131
|
+
|
|
132
|
+
2. **Install dependencies locally:**
|
|
133
|
+
- Run: `pnpm install` (or `npm install` or `yarn install`)
|
|
134
|
+
- Verify all dependencies install successfully
|
|
135
|
+
- Check for any errors or warnings
|
|
136
|
+
|
|
137
|
+
3. **Test build locally:**
|
|
138
|
+
- Run: `pnpm build` (or `npm run build` or `yarn build`)
|
|
139
|
+
- Verify build completes successfully
|
|
140
|
+
- Check for build errors or warnings
|
|
141
|
+
- Verify build output directory exists (`.next` for Next.js, `dist` for others)
|
|
142
|
+
|
|
143
|
+
4. **Verify build artifacts:**
|
|
144
|
+
- Check build output directory structure
|
|
145
|
+
- Verify static files are generated
|
|
146
|
+
- Check for API routes in build output (if applicable)
|
|
147
|
+
- Verify middleware is compiled (if applicable)
|
|
148
|
+
|
|
149
|
+
5. **Check for hardcoded values:**
|
|
150
|
+
- Search codebase for hardcoded URLs or Vercel-specific code
|
|
151
|
+
- Verify environment variable usage
|
|
152
|
+
- Check for PORT usage (should use `process.env.PORT`)
|
|
153
|
+
|
|
154
|
+
6. **Validate database migrations (if applicable):**
|
|
155
|
+
- Check migration files exist
|
|
156
|
+
- Verify database configuration
|
|
157
|
+
- Test migration command (if database available)
|
|
158
|
+
|
|
159
|
+
### Step 1: Repository Setup
|
|
160
|
+
|
|
161
|
+
#### 1.1 Determine Repository Strategy
|
|
162
|
+
|
|
163
|
+
**Option A: Use Existing Repository (if user has one)**
|
|
164
|
+
- Check if current directory is a git repository: `git remote -v`
|
|
165
|
+
- If repository exists, verify it's accessible
|
|
166
|
+
- Use existing repository URL for App Platform
|
|
167
|
+
|
|
168
|
+
**Option B: Create New Repository (if user wants new repo)**
|
|
169
|
+
- Use `gh` CLI to create new repository: `gh repo create <repo-name> --private --source=. --push`
|
|
170
|
+
- Or: `gh repo create <repo-name> --public --source=. --push`
|
|
171
|
+
- Push current code to new repository
|
|
172
|
+
- Use new repository URL for App Platform
|
|
37
173
|
|
|
38
|
-
|
|
174
|
+
**Option C: Fork Existing Repository**
|
|
175
|
+
- Use `gh` CLI to fork: `gh repo fork <owner>/<repo-name> --clone=false`
|
|
176
|
+
- Add fork as remote: `git remote add fork https://github.com/<user>/<repo-name>.git`
|
|
177
|
+
- Push to fork: `git push fork main`
|
|
178
|
+
- Use forked repository URL for App Platform
|
|
179
|
+
|
|
180
|
+
**Option D: Deploy from Local Source (if user doesn't want repo access)**
|
|
181
|
+
- Can deploy directly from local source using `doctl apps create --spec app-spec.yaml`
|
|
182
|
+
- Note: This requires manual code updates - recommend using repository for easier updates
|
|
183
|
+
|
|
184
|
+
#### 1.2 Get App Information (If Migrating from Vercel)
|
|
185
|
+
|
|
186
|
+
**Only perform this step if user has existing Vercel deployment:**
|
|
39
187
|
|
|
40
188
|
1. **Create a local migration folder:**
|
|
41
189
|
- Pattern: `./vercel-migration/<vercel-app-name>-migration/`
|
|
@@ -57,34 +205,435 @@ Then verify:
|
|
|
57
205
|
- Verify the file was created: `ls -la .env.<environment>`
|
|
58
206
|
- If unable to pull environment variables, leave them blank or empty when creating the App Platform app
|
|
59
207
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
1. **Get app information:**
|
|
208
|
+
4. **Get app information using Vercel CLI:**
|
|
63
209
|
- Use `vercel inspect <app-name>` or `vercel ls` to find the app
|
|
210
|
+
- Collect: App name, repository URL, deployment branch, build command, custom domains, etc.
|
|
64
211
|
|
|
65
|
-
|
|
66
|
-
-
|
|
67
|
-
- GitHub/GitLab/BitBucket repository URL. This can also be obtained via Vercel MCP.
|
|
68
|
-
- Current deployment branch
|
|
69
|
-
- Build command
|
|
70
|
-
- Output directory (only for static sites)
|
|
71
|
-
- Root directory / source_dir for monorepos
|
|
72
|
-
- Node.js version or runtime
|
|
73
|
-
- **Custom domains** (list all domains attached to this app, including apex and subdomains)
|
|
74
|
-
- Any serverless function routes (paths under `/api/*`)
|
|
75
|
-
- Cron job configurations
|
|
76
|
-
|
|
77
|
-
3. **Verify environment variables:**
|
|
78
|
-
- Check that `.env.<environment>` file exists in your migration folder
|
|
79
|
-
- All environment variables should be transferred as it is. Do not change the names.
|
|
80
|
-
|
|
81
|
-
3. **Show the user** what you found and confirm they want to proceed
|
|
82
|
-
- Include the list of domains that will need DNS updates
|
|
212
|
+
5. **Show the user** what you found and confirm they want to proceed
|
|
213
|
+
- Include the list of domains that will need DNS updates (if migrating from Vercel)
|
|
83
214
|
- **Note:** Build and run commands will be validated in the next step by checking the repository
|
|
84
215
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
216
|
+
**If NOT migrating from Vercel (deploying source code directly):**
|
|
217
|
+
- Skip Vercel-specific steps
|
|
218
|
+
- Proceed directly to Step 1.5: Monorepo Dependency Consolidation (if applicable)
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
### Step 1.5: Monorepo Dependency Consolidation (CRITICAL for Monorepos)
|
|
223
|
+
|
|
224
|
+
⚠️ **IMPORTANT: App Platform Monorepo Behavior**
|
|
225
|
+
|
|
226
|
+
When deploying a monorepo with multiple components, App Platform has a specific behavior that you MUST understand:
|
|
227
|
+
|
|
228
|
+
**Key Insight:**
|
|
229
|
+
- App Platform installs dependencies **only from the root `package.json`**
|
|
230
|
+
- Each component's `source_dir` only affects where build/run commands execute
|
|
231
|
+
- Dependencies in component-specific `package.json` files are NOT automatically installed
|
|
232
|
+
- This means build tools like `tsx`, `typescript`, `pnpm`, etc. must be in root `package.json`
|
|
233
|
+
|
|
234
|
+
**Why This Matters:**
|
|
235
|
+
|
|
236
|
+
If your monorepo structure looks like this:
|
|
237
|
+
```
|
|
238
|
+
monorepo/
|
|
239
|
+
├── package.json # Root - App Platform installs dependencies from HERE
|
|
240
|
+
├── apps/
|
|
241
|
+
│ ├── dashboard/
|
|
242
|
+
│ │ └── package.json # Component - dependencies NOT installed automatically
|
|
243
|
+
│ └── api/
|
|
244
|
+
│ └── package.json # Component - dependencies NOT installed automatically
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
And `apps/api/package.json` has `tsx` as a dependency, but root `package.json` doesn't, the API build will fail with "command not found: tsx".
|
|
248
|
+
|
|
249
|
+
---
|
|
250
|
+
|
|
251
|
+
#### 1.5.1: Analyze Monorepo Dependencies (Proactive Approach - Recommended)
|
|
252
|
+
|
|
253
|
+
**Before deploying**, analyze all component package.json files and consolidate dependencies:
|
|
254
|
+
|
|
255
|
+
1. **Detect if this is a monorepo:**
|
|
256
|
+
- Check for `pnpm-workspace.yaml`, `lerna.json`, `nx.json`
|
|
257
|
+
- Check if root `package.json` has "workspaces" field
|
|
258
|
+
- Look for multiple `package.json` files in subdirectories
|
|
259
|
+
|
|
260
|
+
2. **If monorepo detected, analyze component dependencies:**
|
|
261
|
+
|
|
262
|
+
```bash
|
|
263
|
+
# Read all component package.json files
|
|
264
|
+
# Extract dependencies and devDependencies
|
|
265
|
+
# Identify build-time tools needed
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
3. **Categorize required packages:**
|
|
269
|
+
|
|
270
|
+
**Build-Time Tools (must be in root devDependencies):**
|
|
271
|
+
- `tsx` - TypeScript execution for Node.js
|
|
272
|
+
- `typescript` - TypeScript compiler
|
|
273
|
+
- `@types/node` - Node.js type definitions
|
|
274
|
+
- `@types/*` - Any TypeScript type packages
|
|
275
|
+
- Build tools: `vite`, `webpack`, `rollup`, `esbuild`
|
|
276
|
+
- Linters: `eslint`, `prettier`
|
|
277
|
+
- Testing: `jest`, `vitest`, `playwright`
|
|
278
|
+
|
|
279
|
+
**Runtime Dependencies (must be in root dependencies):**
|
|
280
|
+
- Framework packages: `next`, `react`, `express`, `vue`
|
|
281
|
+
- Runtime utilities needed by any component
|
|
282
|
+
- Shared packages used across components
|
|
283
|
+
|
|
284
|
+
4. **Propose root package.json updates to user:**
|
|
285
|
+
|
|
286
|
+
```
|
|
287
|
+
I detected this is a monorepo with 2 services. App Platform only installs
|
|
288
|
+
dependencies from the root package.json.
|
|
289
|
+
|
|
290
|
+
I need to add these build-time tools to root package.json:
|
|
291
|
+
- tsx (for API TypeScript execution)
|
|
292
|
+
- typescript (for type checking)
|
|
293
|
+
- @types/node (for Node types)
|
|
294
|
+
|
|
295
|
+
Would you like me to:
|
|
296
|
+
A) Add these automatically and proceed
|
|
297
|
+
B) Skip this and let build fail (then fix iteratively)
|
|
298
|
+
C) Review the full dependency list first
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
5. **If user approves, update root package.json:**
|
|
302
|
+
|
|
303
|
+
```bash
|
|
304
|
+
# Merge component dependencies into root package.json
|
|
305
|
+
# Keep existing root dependencies
|
|
306
|
+
# Add missing build tools to devDependencies
|
|
307
|
+
# Add missing runtime deps to dependencies
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
**Example Transformation:**
|
|
311
|
+
|
|
312
|
+
**Before (will fail on App Platform):**
|
|
313
|
+
```json
|
|
314
|
+
// Root package.json
|
|
315
|
+
{
|
|
316
|
+
"name": "my-monorepo",
|
|
317
|
+
"private": true,
|
|
318
|
+
"devDependencies": {
|
|
319
|
+
"turbo": "^2.5.5"
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// apps/api/package.json
|
|
324
|
+
{
|
|
325
|
+
"name": "api",
|
|
326
|
+
"dependencies": {
|
|
327
|
+
"express": "^4.18.2"
|
|
328
|
+
},
|
|
329
|
+
"devDependencies": {
|
|
330
|
+
"tsx": "^4.20.6",
|
|
331
|
+
"typescript": "^5.0.0"
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
**After (will work on App Platform):**
|
|
337
|
+
```json
|
|
338
|
+
// Root package.json
|
|
339
|
+
{
|
|
340
|
+
"name": "my-monorepo",
|
|
341
|
+
"private": true,
|
|
342
|
+
"dependencies": {
|
|
343
|
+
"express": "^4.18.2" // Added from api
|
|
344
|
+
},
|
|
345
|
+
"devDependencies": {
|
|
346
|
+
"turbo": "^2.5.5",
|
|
347
|
+
"tsx": "^4.20.6", // Added from api
|
|
348
|
+
"typescript": "^5.0.0", // Added from api
|
|
349
|
+
"@types/node": "^20.0.0" // Added from api
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
---
|
|
355
|
+
|
|
356
|
+
#### 1.5.2: Iterative Dependency Fixing (Fallback Approach)
|
|
357
|
+
|
|
358
|
+
If you skip proactive analysis or it misses something:
|
|
359
|
+
|
|
360
|
+
1. **Let the build attempt**
|
|
361
|
+
2. **Parse build error logs for missing dependencies:**
|
|
362
|
+
|
|
363
|
+
Common error patterns:
|
|
364
|
+
```
|
|
365
|
+
/bin/sh: tsx: not found
|
|
366
|
+
/bin/sh: tsc: not found
|
|
367
|
+
Error: Cannot find module 'typescript'
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
3. **Suggest fix to user:**
|
|
371
|
+
|
|
372
|
+
```
|
|
373
|
+
Build failed because 'tsx' is not found.
|
|
374
|
+
|
|
375
|
+
This is a monorepo and App Platform only installs dependencies from
|
|
376
|
+
root package.json.
|
|
377
|
+
|
|
378
|
+
Fix: Add 'tsx' to root package.json devDependencies
|
|
379
|
+
|
|
380
|
+
Would you like me to add it and redeploy?
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
4. **Update root package.json and retry:**
|
|
384
|
+
- Add missing package to appropriate section
|
|
385
|
+
- Commit and push changes
|
|
386
|
+
- Redeploy (automatic if `deploy_on_push: true`)
|
|
387
|
+
|
|
388
|
+
5. **Repeat up to 3 times** for different missing packages
|
|
389
|
+
|
|
390
|
+
---
|
|
391
|
+
|
|
392
|
+
#### 1.5.3: Trade-offs and Considerations
|
|
393
|
+
|
|
394
|
+
**Approach A: Consolidate All Dependencies (Proactive)**
|
|
395
|
+
|
|
396
|
+
**Pros:**
|
|
397
|
+
- ✅ Works on first deployment
|
|
398
|
+
- ✅ No iteration needed
|
|
399
|
+
- ✅ Predictable behavior
|
|
400
|
+
- ✅ User stays in control (approves changes)
|
|
401
|
+
|
|
402
|
+
**Cons:**
|
|
403
|
+
- ❌ All components get ALL dependencies
|
|
404
|
+
- ❌ Larger `node_modules` in each component
|
|
405
|
+
- ❌ Slower installs
|
|
406
|
+
- ❌ Slightly larger deployment artifacts
|
|
407
|
+
|
|
408
|
+
**When to use:**
|
|
409
|
+
- Small monorepos (2-4 services)
|
|
410
|
+
- "Just make it work" scenarios
|
|
411
|
+
- User wants fast deployment
|
|
412
|
+
|
|
413
|
+
**Approach B: Iterative Fixing (Reactive)**
|
|
414
|
+
|
|
415
|
+
**Pros:**
|
|
416
|
+
- ✅ Only adds truly needed packages
|
|
417
|
+
- ✅ Cleaner dependency tree
|
|
418
|
+
- ✅ Educational for user
|
|
419
|
+
|
|
420
|
+
**Cons:**
|
|
421
|
+
- ❌ Requires multiple deploy attempts (2-5 minutes each)
|
|
422
|
+
- ❌ More complex error detection
|
|
423
|
+
- ❌ Could miss cascading errors
|
|
424
|
+
|
|
425
|
+
**When to use:**
|
|
426
|
+
- Large monorepos with many services
|
|
427
|
+
- Production apps where bundle size matters
|
|
428
|
+
- User wants optimal configuration
|
|
429
|
+
|
|
430
|
+
**Approach C: Hybrid (Recommended)**
|
|
431
|
+
|
|
432
|
+
1. Proactively analyze and propose changes
|
|
433
|
+
2. User reviews and approves
|
|
434
|
+
3. If build still fails, fall back to iterative fixing
|
|
435
|
+
4. Usually works first time, graceful degradation
|
|
436
|
+
|
|
437
|
+
---
|
|
438
|
+
|
|
439
|
+
#### 1.5.4: Special Cases
|
|
440
|
+
|
|
441
|
+
**Case 1: Using pnpm workspaces**
|
|
442
|
+
|
|
443
|
+
If `pnpm-workspace.yaml` exists:
|
|
444
|
+
```yaml
|
|
445
|
+
packages:
|
|
446
|
+
- 'apps/*'
|
|
447
|
+
- 'packages/*'
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
App Platform buildpack automatically:
|
|
451
|
+
- Detects pnpm from `pnpm-lock.yaml`
|
|
452
|
+
- Runs `pnpm install` at root
|
|
453
|
+
- Respects workspace configuration
|
|
454
|
+
|
|
455
|
+
**Still need**: Build tools in root package.json
|
|
456
|
+
|
|
457
|
+
**Case 2: Using npm/yarn workspaces**
|
|
458
|
+
|
|
459
|
+
If root `package.json` has:
|
|
460
|
+
```json
|
|
461
|
+
{
|
|
462
|
+
"workspaces": ["apps/*", "packages/*"]
|
|
463
|
+
}
|
|
464
|
+
```
|
|
465
|
+
|
|
466
|
+
App Platform buildpack automatically:
|
|
467
|
+
- Detects workspaces
|
|
468
|
+
- Runs `npm install` or `yarn install` at root
|
|
469
|
+
- Links workspace packages
|
|
470
|
+
|
|
471
|
+
**Still need**: Build tools in root package.json
|
|
472
|
+
|
|
473
|
+
**Case 3: Components use different runtimes**
|
|
474
|
+
|
|
475
|
+
If dashboard uses `pnpm build` but API uses `tsx src/index.ts`:
|
|
476
|
+
- Both commands must have their dependencies in root
|
|
477
|
+
- `pnpm` must be in root (detected from lockfile)
|
|
478
|
+
- `tsx` must be in root devDependencies
|
|
479
|
+
|
|
480
|
+
---
|
|
481
|
+
|
|
482
|
+
#### 1.5.5: Implementation Example (AI Assistant Instructions)
|
|
483
|
+
|
|
484
|
+
**When detecting a monorepo:**
|
|
485
|
+
|
|
486
|
+
```typescript
|
|
487
|
+
// Pseudo-code for AI assistant
|
|
488
|
+
|
|
489
|
+
function analyzeMonorepo(repoPath) {
|
|
490
|
+
// 1. Detect monorepo structure
|
|
491
|
+
const isMonorepo = hasWorkspaceConfig(repoPath);
|
|
492
|
+
if (!isMonorepo) return null;
|
|
493
|
+
|
|
494
|
+
// 2. Find all component package.json files
|
|
495
|
+
const components = findComponents(repoPath);
|
|
496
|
+
|
|
497
|
+
// 3. Extract dependencies from each component
|
|
498
|
+
const allDeps = {
|
|
499
|
+
dependencies: new Set(),
|
|
500
|
+
devDependencies: new Set()
|
|
501
|
+
};
|
|
502
|
+
|
|
503
|
+
for (const component of components) {
|
|
504
|
+
const pkg = readPackageJson(component.path);
|
|
505
|
+
|
|
506
|
+
// Merge runtime dependencies
|
|
507
|
+
Object.keys(pkg.dependencies || {}).forEach(dep =>
|
|
508
|
+
allDeps.dependencies.add({ name: dep, version: pkg.dependencies[dep] })
|
|
509
|
+
);
|
|
510
|
+
|
|
511
|
+
// Merge build-time dependencies
|
|
512
|
+
Object.keys(pkg.devDependencies || {}).forEach(dep =>
|
|
513
|
+
allDeps.devDependencies.add({ name: dep, version: pkg.devDependencies[dep] })
|
|
514
|
+
);
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
// 4. Check what's missing from root
|
|
518
|
+
const rootPkg = readPackageJson(`${repoPath}/package.json`);
|
|
519
|
+
const missing = {
|
|
520
|
+
dependencies: [],
|
|
521
|
+
devDependencies: []
|
|
522
|
+
};
|
|
523
|
+
|
|
524
|
+
allDeps.dependencies.forEach(dep => {
|
|
525
|
+
if (!rootPkg.dependencies?.[dep.name]) {
|
|
526
|
+
missing.dependencies.push(dep);
|
|
527
|
+
}
|
|
528
|
+
});
|
|
529
|
+
|
|
530
|
+
allDeps.devDependencies.forEach(dep => {
|
|
531
|
+
if (!rootPkg.devDependencies?.[dep.name]) {
|
|
532
|
+
missing.devDependencies.push(dep);
|
|
533
|
+
}
|
|
534
|
+
});
|
|
535
|
+
|
|
536
|
+
// 5. Return analysis
|
|
537
|
+
return {
|
|
538
|
+
isMonorepo: true,
|
|
539
|
+
components: components.length,
|
|
540
|
+
missing,
|
|
541
|
+
recommendation: missing.dependencies.length + missing.devDependencies.length > 0
|
|
542
|
+
? "CONSOLIDATE_DEPENDENCIES"
|
|
543
|
+
: "NO_ACTION_NEEDED"
|
|
544
|
+
};
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
// Then ask user
|
|
548
|
+
if (analysis.recommendation === "CONSOLIDATE_DEPENDENCIES") {
|
|
549
|
+
askUser(`
|
|
550
|
+
Detected monorepo with ${analysis.components} components.
|
|
551
|
+
|
|
552
|
+
App Platform only installs dependencies from root package.json.
|
|
553
|
+
|
|
554
|
+
Missing from root:
|
|
555
|
+
${formatDependencies(analysis.missing)}
|
|
556
|
+
|
|
557
|
+
Add these to root package.json?
|
|
558
|
+
A) Yes, add automatically
|
|
559
|
+
B) No, I'll handle it manually
|
|
560
|
+
C) Show me the full proposed package.json
|
|
561
|
+
`);
|
|
562
|
+
}
|
|
563
|
+
```
|
|
564
|
+
|
|
565
|
+
---
|
|
566
|
+
|
|
567
|
+
#### 1.5.6: Troubleshooting Monorepo Dependency Issues
|
|
568
|
+
|
|
569
|
+
**Symptom:** Build fails with "command not found: tsx"
|
|
570
|
+
|
|
571
|
+
**Diagnosis:**
|
|
572
|
+
```bash
|
|
573
|
+
# Check build logs
|
|
574
|
+
doctl apps logs <app-id> --type build
|
|
575
|
+
|
|
576
|
+
# Look for:
|
|
577
|
+
/bin/sh: tsx: not found
|
|
578
|
+
/bin/sh: 1: tsx: not found
|
|
579
|
+
```
|
|
580
|
+
|
|
581
|
+
**Root Cause:** `tsx` is in component `package.json` but not in root
|
|
582
|
+
|
|
583
|
+
**Fix:**
|
|
584
|
+
```bash
|
|
585
|
+
# Add to root package.json devDependencies
|
|
586
|
+
{
|
|
587
|
+
"devDependencies": {
|
|
588
|
+
"tsx": "^4.20.6"
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
# Commit and push
|
|
593
|
+
git add package.json
|
|
594
|
+
git commit -m "Add tsx to root for App Platform build"
|
|
595
|
+
git push
|
|
596
|
+
```
|
|
597
|
+
|
|
598
|
+
**Symptom:** Build succeeds but run fails with "Cannot find module 'express'"
|
|
599
|
+
|
|
600
|
+
**Diagnosis:**
|
|
601
|
+
```bash
|
|
602
|
+
# Check runtime logs
|
|
603
|
+
doctl apps logs <app-id> --type run
|
|
604
|
+
|
|
605
|
+
# Look for:
|
|
606
|
+
Error: Cannot find module 'express'
|
|
607
|
+
```
|
|
608
|
+
|
|
609
|
+
**Root Cause:** `express` is in component `package.json` but not in root
|
|
610
|
+
|
|
611
|
+
**Fix:**
|
|
612
|
+
```bash
|
|
613
|
+
# Add to root package.json dependencies (NOT devDependencies)
|
|
614
|
+
{
|
|
615
|
+
"dependencies": {
|
|
616
|
+
"express": "^4.18.2"
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
```
|
|
620
|
+
|
|
621
|
+
---
|
|
622
|
+
|
|
623
|
+
#### 1.5.7: Validation Checklist
|
|
624
|
+
|
|
625
|
+
Before proceeding to deployment:
|
|
626
|
+
|
|
627
|
+
- [ ] Identified if repository is a monorepo
|
|
628
|
+
- [ ] If monorepo: Analyzed all component package.json files
|
|
629
|
+
- [ ] Identified build-time tools needed (tsx, typescript, etc.)
|
|
630
|
+
- [ ] Identified runtime dependencies needed
|
|
631
|
+
- [ ] Updated root package.json with consolidated dependencies
|
|
632
|
+
- [ ] User approved dependency consolidation
|
|
633
|
+
- [ ] Committed changes to git
|
|
634
|
+
- [ ] Ready to proceed to app spec creation
|
|
635
|
+
|
|
636
|
+
---
|
|
88
637
|
|
|
89
638
|
### Step 2: App Migration
|
|
90
639
|
|
|
@@ -144,19 +693,36 @@ Follow these steps to migrate the app:
|
|
|
144
693
|
|
|
145
694
|
#### 2.2 Environment Variables
|
|
146
695
|
|
|
147
|
-
1. **
|
|
148
|
-
|
|
696
|
+
1. **Collect environment variables:**
|
|
697
|
+
|
|
698
|
+
**If migrating from Vercel:**
|
|
699
|
+
- Read the `.env.<environment>` file from the migration folder (Step 1.1)
|
|
149
700
|
- Parse all variables from this file
|
|
150
|
-
- If no environment variables were pulled,
|
|
701
|
+
- If no environment variables were pulled, proceed with manual collection
|
|
702
|
+
|
|
703
|
+
**If deploying source code directly (no Vercel):**
|
|
704
|
+
- Check for `.env.example` or `.env.sample` file in project
|
|
705
|
+
- Read `.env.example` to understand required variables
|
|
706
|
+
- Ask user for values for each required variable
|
|
707
|
+
- Generate secure values where needed (e.g., `AUTH_SECRET`)
|
|
151
708
|
|
|
152
709
|
2. **Transform system variables:**
|
|
153
710
|
- Note: `VERCEL_URL`, `VERCEL_ENV`, any `VERCEL_GIT_*` and Vercel-specific system variables will NOT be available in App Platform
|
|
154
711
|
- Warn the user if the app depends on these variables
|
|
712
|
+
- Replace `VERCEL_URL` with App Platform URL (set after deployment)
|
|
713
|
+
- Replace `VERCEL_ENV` with `NODE_ENV=production`
|
|
155
714
|
|
|
156
715
|
3. **Prepare environment variables for App Platform:**
|
|
157
716
|
- Keep the same variable names (except for Vercel-specific ones)
|
|
158
|
-
- Mark sensitive variables (API keys, secrets, database passwords) as
|
|
159
|
-
-
|
|
717
|
+
- Mark sensitive variables (API keys, secrets, database passwords) as `type: SECRET` in app spec
|
|
718
|
+
- Generate secure random values where needed:
|
|
719
|
+
- `AUTH_SECRET`: `openssl rand -base64 32`
|
|
720
|
+
- `STRIPE_WEBHOOK_SECRET`: User provides or placeholder
|
|
721
|
+
- If unable to retrieve values, ask user or leave blank (app may have defaults)
|
|
722
|
+
|
|
723
|
+
4. **Database connection string:**
|
|
724
|
+
- If creating managed database in App Platform, use `${db.DATABASE_URL}` reference
|
|
725
|
+
- If using external database, ask user for connection string
|
|
160
726
|
|
|
161
727
|
#### 2.3 Component Type Detection
|
|
162
728
|
|
|
@@ -195,6 +761,296 @@ Determine the appropriate App Platform component type based on the app's charact
|
|
|
195
761
|
- Option A: Single web service (simplest - handles both static and API)
|
|
196
762
|
- Option B: Separate static site + web service components (more complex setup)
|
|
197
763
|
- **Recommend Option A** unless user specifically wants separation
|
|
764
|
+
- **See section 2.3.5 below for detailed multi-service architecture guidance**
|
|
765
|
+
|
|
766
|
+
#### 2.3.5 Multi-Service and Monorepo Applications
|
|
767
|
+
|
|
768
|
+
**App Platform supports deploying multiple components in a single app.** This is different from deploying multiple separate apps.
|
|
769
|
+
|
|
770
|
+
**One App with Multiple Components vs Multiple Apps:**
|
|
771
|
+
|
|
772
|
+
| Use One App (Multiple Components) | Use Multiple Apps |
|
|
773
|
+
|-----------------------------------|-------------------|
|
|
774
|
+
| Services in same repository | Services in different repositories |
|
|
775
|
+
| Deploy together on git push | Deploy independently |
|
|
776
|
+
| Shared database connection | Separate databases |
|
|
777
|
+
| Internal communication (fast, no public internet) | Public API communication |
|
|
778
|
+
| Examples: monorepo, microservices, frontend+API+worker | Examples: different products, different teams |
|
|
779
|
+
|
|
780
|
+
**Component Types in One App:**
|
|
781
|
+
- **Multiple web services** (e.g., frontend, API, admin panel)
|
|
782
|
+
- **Static sites + web services** (e.g., marketing site + API)
|
|
783
|
+
- **Workers** (background jobs, queue processors, continuous processes)
|
|
784
|
+
- **Jobs** (one-time tasks, pre-deploy hooks, post-deploy hooks)
|
|
785
|
+
- **Databases** (PostgreSQL, ValKey/Redis)
|
|
786
|
+
|
|
787
|
+
---
|
|
788
|
+
|
|
789
|
+
**Example 1: Monorepo with Frontend + API + Shared Database**
|
|
790
|
+
|
|
791
|
+
This is the most common multi-service scenario.
|
|
792
|
+
|
|
793
|
+
**Repository structure:**
|
|
794
|
+
```
|
|
795
|
+
monorepo/
|
|
796
|
+
├── apps/
|
|
797
|
+
│ ├── web/ # Next.js frontend
|
|
798
|
+
│ │ ├── package.json
|
|
799
|
+
│ │ └── src/
|
|
800
|
+
│ └── api/ # Express API
|
|
801
|
+
│ ├── package.json
|
|
802
|
+
│ └── src/
|
|
803
|
+
├── packages/
|
|
804
|
+
│ └── shared/ # Shared code
|
|
805
|
+
│ └── package.json
|
|
806
|
+
├── package.json # Root workspace config
|
|
807
|
+
└── pnpm-workspace.yaml # or package-lock.json, yarn.lock
|
|
808
|
+
```
|
|
809
|
+
|
|
810
|
+
**app-spec.yaml:**
|
|
811
|
+
```yaml
|
|
812
|
+
name: my-fullstack-app
|
|
813
|
+
region: nyc1
|
|
814
|
+
|
|
815
|
+
services:
|
|
816
|
+
# Frontend service
|
|
817
|
+
- name: web
|
|
818
|
+
github:
|
|
819
|
+
repo: owner/monorepo
|
|
820
|
+
branch: main
|
|
821
|
+
deploy_on_push: true
|
|
822
|
+
source_dir: /apps/web
|
|
823
|
+
build_command: "" # Auto-detect Next.js
|
|
824
|
+
run_command: "" # Auto-detect Next.js start
|
|
825
|
+
http_port: 8080
|
|
826
|
+
instance_count: 1
|
|
827
|
+
instance_size_slug: basic-xxs
|
|
828
|
+
routes:
|
|
829
|
+
- path: / # Frontend handles root and all non-API routes
|
|
830
|
+
envs:
|
|
831
|
+
- key: API_URL
|
|
832
|
+
value: ${api.PRIVATE_URL} # Internal URL to API service (fast, no public internet)
|
|
833
|
+
- key: DATABASE_URL
|
|
834
|
+
value: ${db.DATABASE_URL}
|
|
835
|
+
scope: RUN_AND_BUILD_TIME
|
|
836
|
+
- key: NODE_ENV
|
|
837
|
+
value: production
|
|
838
|
+
|
|
839
|
+
# API service
|
|
840
|
+
- name: api
|
|
841
|
+
github:
|
|
842
|
+
repo: owner/monorepo
|
|
843
|
+
branch: main
|
|
844
|
+
deploy_on_push: true
|
|
845
|
+
source_dir: /apps/api
|
|
846
|
+
build_command: "" # Auto-detect or specify if custom
|
|
847
|
+
run_command: "" # Auto-detect Express/Node
|
|
848
|
+
http_port: 8080
|
|
849
|
+
instance_count: 1
|
|
850
|
+
instance_size_slug: basic-xxs
|
|
851
|
+
routes:
|
|
852
|
+
- path: /api # API handles all /api/* routes
|
|
853
|
+
envs:
|
|
854
|
+
- key: DATABASE_URL
|
|
855
|
+
value: ${db.DATABASE_URL}
|
|
856
|
+
scope: RUN_AND_BUILD_TIME
|
|
857
|
+
- key: NODE_ENV
|
|
858
|
+
value: production
|
|
859
|
+
|
|
860
|
+
databases:
|
|
861
|
+
- name: db
|
|
862
|
+
engine: PG
|
|
863
|
+
version: "18"
|
|
864
|
+
production: false # Set to true for production tier with backups
|
|
865
|
+
```
|
|
866
|
+
|
|
867
|
+
**Key Points:**
|
|
868
|
+
1. Both services reference same repository, different `source_dir`
|
|
869
|
+
2. Services can reference each other with `${service-name.PRIVATE_URL}` (internal communication, fast)
|
|
870
|
+
3. Public routes are configured per service (`/` for web, `/api` for API)
|
|
871
|
+
4. Database is shared via `${db.DATABASE_URL}` reference
|
|
872
|
+
5. All services deploy together when code is pushed
|
|
873
|
+
6. Buildpack auto-detects framework in each service's directory
|
|
874
|
+
|
|
875
|
+
**Monorepo Package Manager Detection:**
|
|
876
|
+
- If `pnpm-workspace.yaml` exists → buildpack uses pnpm
|
|
877
|
+
- If root `package.json` has "workspaces" field → buildpack uses npm/yarn workspaces
|
|
878
|
+
- Buildpack automatically installs dependencies for each service
|
|
879
|
+
|
|
880
|
+
---
|
|
881
|
+
|
|
882
|
+
**Example 2: Adding Workers and Jobs for Background Tasks**
|
|
883
|
+
|
|
884
|
+
**Repository structure:**
|
|
885
|
+
```
|
|
886
|
+
app/
|
|
887
|
+
├── web/ # Frontend
|
|
888
|
+
├── api/ # API
|
|
889
|
+
├── worker/ # Background worker (continuous)
|
|
890
|
+
│ └── worker.js # Processes queue, runs continuously
|
|
891
|
+
└── jobs/
|
|
892
|
+
└── migrations/ # Database migrations (one-time)
|
|
893
|
+
└── migrate.js
|
|
894
|
+
```
|
|
895
|
+
|
|
896
|
+
**app-spec.yaml additions:**
|
|
897
|
+
```yaml
|
|
898
|
+
name: my-app-with-workers
|
|
899
|
+
region: nyc1
|
|
900
|
+
|
|
901
|
+
services:
|
|
902
|
+
# ... web and api services as above ...
|
|
903
|
+
|
|
904
|
+
workers:
|
|
905
|
+
# Background worker - runs continuously
|
|
906
|
+
- name: email-worker
|
|
907
|
+
github:
|
|
908
|
+
repo: owner/repo
|
|
909
|
+
branch: main
|
|
910
|
+
source_dir: /worker
|
|
911
|
+
build_command: ""
|
|
912
|
+
run_command: "node worker.js" # Continuous process
|
|
913
|
+
instance_count: 1
|
|
914
|
+
instance_size_slug: basic-xxs
|
|
915
|
+
envs:
|
|
916
|
+
- key: DATABASE_URL
|
|
917
|
+
value: ${db.DATABASE_URL}
|
|
918
|
+
- key: REDIS_URL
|
|
919
|
+
value: ${cache.DATABASE_URL}
|
|
920
|
+
- key: NODE_ENV
|
|
921
|
+
value: production
|
|
922
|
+
|
|
923
|
+
jobs:
|
|
924
|
+
# Pre-deploy job - runs before deployment
|
|
925
|
+
- name: db-migrate
|
|
926
|
+
kind: PRE_DEPLOY
|
|
927
|
+
github:
|
|
928
|
+
repo: owner/repo
|
|
929
|
+
branch: main
|
|
930
|
+
source_dir: /jobs/migrations
|
|
931
|
+
build_command: ""
|
|
932
|
+
run_command: "node migrate.js" # Runs once before deployment
|
|
933
|
+
instance_size_slug: basic-xxs
|
|
934
|
+
envs:
|
|
935
|
+
- key: DATABASE_URL
|
|
936
|
+
value: ${db.DATABASE_URL}
|
|
937
|
+
|
|
938
|
+
databases:
|
|
939
|
+
- name: db
|
|
940
|
+
engine: PG
|
|
941
|
+
version: "18"
|
|
942
|
+
- name: cache
|
|
943
|
+
engine: REDIS # ValKey (Redis fork)
|
|
944
|
+
version: "7"
|
|
945
|
+
```
|
|
946
|
+
|
|
947
|
+
**Worker vs Job:**
|
|
948
|
+
- **Worker**: Continuous process (e.g., queue processor, scheduled task runner)
|
|
949
|
+
- **Job**: Runs once per deployment (e.g., database migrations, cache warming)
|
|
950
|
+
- **Job kinds**:
|
|
951
|
+
- `PRE_DEPLOY`: Runs before new code is deployed (migrations)
|
|
952
|
+
- `POST_DEPLOY`: Runs after deployment succeeds (cache warming)
|
|
953
|
+
|
|
954
|
+
---
|
|
955
|
+
|
|
956
|
+
**Example 3: Separating Static Site from API Service**
|
|
957
|
+
|
|
958
|
+
Sometimes you want a separate static frontend (SPA) and API backend.
|
|
959
|
+
|
|
960
|
+
**app-spec.yaml:**
|
|
961
|
+
```yaml
|
|
962
|
+
name: spa-with-api
|
|
963
|
+
region: nyc1
|
|
964
|
+
|
|
965
|
+
static_sites:
|
|
966
|
+
# Static React/Vue/Angular SPA
|
|
967
|
+
- name: web
|
|
968
|
+
github:
|
|
969
|
+
repo: owner/repo
|
|
970
|
+
branch: main
|
|
971
|
+
source_dir: /frontend
|
|
972
|
+
build_command: "npm run build" # Or leave empty for auto-detect
|
|
973
|
+
output_dir: dist # Or build, out, public
|
|
974
|
+
routes:
|
|
975
|
+
- path: /
|
|
976
|
+
envs:
|
|
977
|
+
- key: VITE_API_URL # Or REACT_APP_API_URL, NEXT_PUBLIC_API_URL
|
|
978
|
+
value: ${api.PUBLIC_URL} # Public URL to API
|
|
979
|
+
|
|
980
|
+
services:
|
|
981
|
+
# API service
|
|
982
|
+
- name: api
|
|
983
|
+
github:
|
|
984
|
+
repo: owner/repo
|
|
985
|
+
branch: main
|
|
986
|
+
source_dir: /backend
|
|
987
|
+
build_command: ""
|
|
988
|
+
run_command: ""
|
|
989
|
+
http_port: 8080
|
|
990
|
+
routes:
|
|
991
|
+
- path: /api
|
|
992
|
+
envs:
|
|
993
|
+
- key: DATABASE_URL
|
|
994
|
+
value: ${db.DATABASE_URL}
|
|
995
|
+
|
|
996
|
+
databases:
|
|
997
|
+
- name: db
|
|
998
|
+
engine: PG
|
|
999
|
+
version: "18"
|
|
1000
|
+
```
|
|
1001
|
+
|
|
1002
|
+
**When to use this pattern:**
|
|
1003
|
+
- SPA that's 100% client-side rendered
|
|
1004
|
+
- Clear separation between frontend and backend
|
|
1005
|
+
- Frontend only needs static file hosting
|
|
1006
|
+
|
|
1007
|
+
---
|
|
1008
|
+
|
|
1009
|
+
**When to Use Multiple Apps vs One App with Multiple Components:**
|
|
1010
|
+
|
|
1011
|
+
**Use ONE app with multiple components when:**
|
|
1012
|
+
- ✅ All services are in the same repository (monorepo)
|
|
1013
|
+
- ✅ Services share the same database
|
|
1014
|
+
- ✅ Services need to deploy together (atomic deployments)
|
|
1015
|
+
- ✅ Services communicate internally (low latency requirements)
|
|
1016
|
+
- ✅ Simpler management (one dashboard, one app spec)
|
|
1017
|
+
|
|
1018
|
+
**Use MULTIPLE separate apps when:**
|
|
1019
|
+
- ✅ Services are in different repositories
|
|
1020
|
+
- ✅ Services need to deploy independently
|
|
1021
|
+
- ✅ Services have different teams/ownership
|
|
1022
|
+
- ✅ Services need independent scaling and resource management
|
|
1023
|
+
- ✅ Services are truly separate products/systems
|
|
1024
|
+
|
|
1025
|
+
---
|
|
1026
|
+
|
|
1027
|
+
**Deployment Behavior with Multiple Components:**
|
|
1028
|
+
- Git push triggers deployment of **ALL components** in the app
|
|
1029
|
+
- All components must build successfully before deployment
|
|
1030
|
+
- If **one component fails**, entire deployment fails (rollback to previous)
|
|
1031
|
+
- Components start simultaneously after successful build
|
|
1032
|
+
- Database migrations (PRE_DEPLOY jobs) run before services start
|
|
1033
|
+
|
|
1034
|
+
**Troubleshooting Multi-Component Deployments:**
|
|
1035
|
+
|
|
1036
|
+
If one component fails:
|
|
1037
|
+
1. Check which component failed in logs: `doctl apps logs <app-id> --type build`
|
|
1038
|
+
2. Fix the failing component's code or configuration
|
|
1039
|
+
3. Push fix - all components rebuild
|
|
1040
|
+
4. Consider deploying components in separate apps if you need independent deployments
|
|
1041
|
+
|
|
1042
|
+
**Internal Service Communication:**
|
|
1043
|
+
- Use `${service-name.PRIVATE_URL}` for fast internal communication (no public internet)
|
|
1044
|
+
- Example: Frontend calls `${api.PRIVATE_URL}/users` instead of public URL
|
|
1045
|
+
- Faster and more secure than public URLs
|
|
1046
|
+
- Private URLs are only accessible within the app's components
|
|
1047
|
+
|
|
1048
|
+
**Assistant Instructions:**
|
|
1049
|
+
- When detecting a monorepo, ask user: "I see this is a monorepo with multiple services. Would you like to deploy them as separate components in one app, or as a single service?"
|
|
1050
|
+
- Show the user which services you detected (by finding multiple package.json files)
|
|
1051
|
+
- Propose an app spec with multiple components
|
|
1052
|
+
- Explain that all services will deploy together
|
|
1053
|
+
- Confirm the routing strategy (which paths go to which services)
|
|
198
1054
|
|
|
199
1055
|
#### 2.4 Feature Translation
|
|
200
1056
|
|
|
@@ -242,119 +1098,249 @@ Determine the appropriate App Platform component type based on the app's charact
|
|
|
242
1098
|
|
|
243
1099
|
#### 2.5 Create App Platform App
|
|
244
1100
|
|
|
245
|
-
**Using
|
|
1101
|
+
**Using doctl CLI (Primary Method):**
|
|
246
1102
|
|
|
247
|
-
1. **
|
|
1103
|
+
1. **Create app spec YAML file** with configuration based on component type:
|
|
248
1104
|
|
|
249
|
-
**IMPORTANT: Only proceed with app creation after completing validation in step 2.1**
|
|
1105
|
+
**IMPORTANT: Only proceed with app creation after completing validation in step 2.1 and local testing in Step 0**
|
|
250
1106
|
|
|
251
1107
|
**For Static Sites:**
|
|
252
|
-
```
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
1108
|
+
```yaml
|
|
1109
|
+
name: <app-name>
|
|
1110
|
+
region: <region> # e.g., nyc1, sfo1, ams3
|
|
1111
|
+
services:
|
|
1112
|
+
- name: web
|
|
1113
|
+
github:
|
|
1114
|
+
repo: <owner>/<repo-name>
|
|
1115
|
+
branch: main # or from Vercel if migrating
|
|
1116
|
+
deploy_on_push: true
|
|
1117
|
+
source_dir: / # or path for monorepo
|
|
1118
|
+
build_command: "" # empty for buildpack auto-detection
|
|
1119
|
+
output_dir: "" # only if non-standard
|
|
1120
|
+
instance_count: 1
|
|
1121
|
+
instance_size_slug: basic-xxs
|
|
1122
|
+
envs:
|
|
1123
|
+
# Add environment variables here
|
|
262
1124
|
```
|
|
263
1125
|
|
|
264
1126
|
**For Web Services (Dynamic Sites):**
|
|
265
|
-
```
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
1127
|
+
```yaml
|
|
1128
|
+
name: <app-name>
|
|
1129
|
+
region: <region> # e.g., nyc1, sfo1, ams3
|
|
1130
|
+
services:
|
|
1131
|
+
- name: web
|
|
1132
|
+
github:
|
|
1133
|
+
repo: <owner>/<repo-name>
|
|
1134
|
+
branch: main # or from Vercel if migrating
|
|
1135
|
+
deploy_on_push: true
|
|
1136
|
+
source_dir: / # or path for monorepo
|
|
1137
|
+
build_command: "" # empty for buildpack auto-detection
|
|
1138
|
+
run_command: "" # empty for buildpack auto-detection
|
|
1139
|
+
http_port: 8080
|
|
1140
|
+
instance_count: 1
|
|
1141
|
+
instance_size_slug: basic-xxs
|
|
1142
|
+
envs:
|
|
1143
|
+
- key: NODE_ENV
|
|
1144
|
+
value: production
|
|
1145
|
+
scope: RUN_AND_BUILD_TIME
|
|
1146
|
+
# Add other environment variables here
|
|
1147
|
+
databases:
|
|
1148
|
+
- name: db
|
|
1149
|
+
engine: PG
|
|
1150
|
+
version: "18"
|
|
1151
|
+
production: false
|
|
276
1152
|
```
|
|
277
1153
|
|
|
278
|
-
2. **
|
|
1154
|
+
2. **Save the app spec to local filesystem:**
|
|
1155
|
+
- Save as `app-spec.yaml` in project root or migration folder
|
|
1156
|
+
- This allows the user to manually create the app if needed
|
|
279
1157
|
|
|
280
|
-
3. **
|
|
281
|
-
-
|
|
282
|
-
-
|
|
283
|
-
|
|
284
|
-
**Alternative using CLI:** Use `doctl apps create` with an app spec YAML/JSON file
|
|
1158
|
+
3. **Create app using doctl CLI:**
|
|
1159
|
+
- Run: `doctl apps create --spec app-spec.yaml`
|
|
1160
|
+
- Capture app ID from output
|
|
1161
|
+
- Monitor deployment: `doctl apps get <app-id>`
|
|
285
1162
|
|
|
286
1163
|
4. **Set up any required databases:**
|
|
287
1164
|
- If app uses Vercel Postgres → Create Managed PostgreSQL
|
|
288
1165
|
- If app uses Vercel KV → Create Managed ValKey (Redis fork)
|
|
289
1166
|
- Update connection strings in environment variables
|
|
290
1167
|
|
|
1168
|
+
**Database Configuration Details:**
|
|
1169
|
+
|
|
1170
|
+
**Adding Managed Databases in app spec:**
|
|
1171
|
+
|
|
1172
|
+
```yaml
|
|
1173
|
+
databases:
|
|
1174
|
+
# PostgreSQL database
|
|
1175
|
+
- name: db
|
|
1176
|
+
engine: PG
|
|
1177
|
+
version: "18" # Or "17", "16", "15", "14"
|
|
1178
|
+
production: false # false = dev tier ($15/mo), true = production tier ($25/mo+)
|
|
1179
|
+
cluster_name: my-db-cluster # optional - creates new cluster or references existing
|
|
1180
|
+
|
|
1181
|
+
# Redis/ValKey cache
|
|
1182
|
+
- name: cache
|
|
1183
|
+
engine: REDIS # ValKey (Redis fork, Redis 7.2 compatible)
|
|
1184
|
+
version: "7"
|
|
1185
|
+
production: false
|
|
1186
|
+
```
|
|
1187
|
+
|
|
1188
|
+
**Referencing databases in services:**
|
|
1189
|
+
|
|
1190
|
+
```yaml
|
|
1191
|
+
services:
|
|
1192
|
+
- name: web
|
|
1193
|
+
# ... other config ...
|
|
1194
|
+
envs:
|
|
1195
|
+
# Database URL is injected automatically
|
|
1196
|
+
- key: DATABASE_URL
|
|
1197
|
+
value: ${db.DATABASE_URL} # Format: postgresql://user:pass@host:port/dbname?sslmode=require
|
|
1198
|
+
scope: RUN_AND_BUILD_TIME # Available during build and runtime
|
|
1199
|
+
|
|
1200
|
+
# Redis URL
|
|
1201
|
+
- key: REDIS_URL
|
|
1202
|
+
value: ${cache.DATABASE_URL} # Format: redis://user:pass@host:port
|
|
1203
|
+
scope: RUN_TIME # Only available at runtime
|
|
1204
|
+
```
|
|
1205
|
+
|
|
1206
|
+
**Connection string formats:**
|
|
1207
|
+
- **PostgreSQL**: `postgresql://username:password@host:port/database?sslmode=require`
|
|
1208
|
+
- **Redis/ValKey**: `redis://username:password@host:port`
|
|
1209
|
+
- SSL/TLS is enforced for all connections to managed databases and cannot be disabled
|
|
1210
|
+
- Credentials are automatically generated and rotated
|
|
1211
|
+
|
|
1212
|
+
**Database tiers:**
|
|
1213
|
+
- **Development** (`production: false`): $15/month, 1 GB RAM, 10 GB disk, 1 node, daily backups
|
|
1214
|
+
- **Production** (`production: true`): Starting at $25/month, 2 GB RAM, 25 GB disk, automatic failover, point-in-time recovery
|
|
1215
|
+
|
|
1216
|
+
**Using external database (not managed by App Platform):**
|
|
1217
|
+
|
|
1218
|
+
If you want to use an existing external database:
|
|
1219
|
+
|
|
1220
|
+
```yaml
|
|
1221
|
+
services:
|
|
1222
|
+
- name: web
|
|
1223
|
+
envs:
|
|
1224
|
+
- key: DATABASE_URL
|
|
1225
|
+
value: "postgresql://external-host.com:5432/mydb?sslmode=require"
|
|
1226
|
+
type: SECRET # Mark as secret to encrypt in dashboard
|
|
1227
|
+
```
|
|
1228
|
+
|
|
1229
|
+
**Database migrations:**
|
|
1230
|
+
|
|
1231
|
+
Use PRE_DEPLOY jobs to run migrations before deployment:
|
|
1232
|
+
|
|
1233
|
+
```yaml
|
|
1234
|
+
jobs:
|
|
1235
|
+
- name: db-migrate
|
|
1236
|
+
kind: PRE_DEPLOY
|
|
1237
|
+
github:
|
|
1238
|
+
repo: owner/repo
|
|
1239
|
+
branch: main
|
|
1240
|
+
source_dir: /
|
|
1241
|
+
run_command: "npm run migrate" # or "pnpm migrate", "yarn migrate"
|
|
1242
|
+
instance_size_slug: basic-xxs
|
|
1243
|
+
envs:
|
|
1244
|
+
- key: DATABASE_URL
|
|
1245
|
+
value: ${db.DATABASE_URL}
|
|
1246
|
+
```
|
|
1247
|
+
|
|
1248
|
+
Common migration commands:
|
|
1249
|
+
- Prisma: `npx prisma migrate deploy`
|
|
1250
|
+
- Drizzle: `npm run db:push` or `npm run db:migrate`
|
|
1251
|
+
- TypeORM: `npm run typeorm migration:run`
|
|
1252
|
+
- Knex: `npm run knex migrate:latest`
|
|
1253
|
+
- Sequelize: `npx sequelize-cli db:migrate`
|
|
1254
|
+
|
|
1255
|
+
**Important notes:**
|
|
1256
|
+
- Database creation can take 10-15 minutes on first deployment
|
|
1257
|
+
- Databases persist across deployments and app deletions (must manually delete)
|
|
1258
|
+
- Connection pooling is recommended (use connection pool library)
|
|
1259
|
+
- **Data migration** from Vercel Postgres is a separate manual process (not automated by this guide)
|
|
1260
|
+
|
|
1261
|
+
**Data migration strategy (manual process):**
|
|
1262
|
+
1. Create new App Platform database
|
|
1263
|
+
2. Use `pg_dump` to export from Vercel Postgres
|
|
1264
|
+
3. Use `psql` or `pg_restore` to import to App Platform database
|
|
1265
|
+
4. Test thoroughly before switching DNS
|
|
1266
|
+
5. Keep Vercel database running during transition
|
|
1267
|
+
6. Consider using database migration tools like `pg_dump`/`pg_restore`, or managed migration services
|
|
1268
|
+
|
|
291
1269
|
#### 2.6 Configure Domains
|
|
292
1270
|
|
|
293
|
-
**Using
|
|
1271
|
+
**Using doctl CLI (Primary Method):**
|
|
294
1272
|
|
|
295
1273
|
1. **Add custom domains to the App Platform app:**
|
|
296
|
-
-
|
|
1274
|
+
- Run: `doctl apps create-domain <app-id> --domain <domain-name>`
|
|
1275
|
+
- For each domain that was in Vercel (if migrating), add it to App Platform
|
|
297
1276
|
- App Platform will provide DNS configuration details
|
|
298
1277
|
- Both apex domains (example.com) and subdomains (www.example.com) are supported
|
|
299
1278
|
- App Platform will automatically provision SSL certificates
|
|
300
1279
|
|
|
301
|
-
2. **
|
|
302
|
-
-
|
|
1280
|
+
2. **Get DNS configuration:**
|
|
1281
|
+
- Get default ingress: `doctl apps get <app-id> --format DefaultIngress`
|
|
1282
|
+
- Get domain configuration: `doctl apps get-domain <app-id> <domain-name>`
|
|
1283
|
+
|
|
1284
|
+
3. **Provide DNS update instructions to the user:**
|
|
1285
|
+
- Display these instructions as post deployment instruction
|
|
303
1286
|
- List each domain that needs to be updated
|
|
304
1287
|
- Ask if the user wants to manage domains through DigitalOcean or keep it self managed (outside of DigitalOcean)
|
|
305
|
-
- If the user wants to
|
|
306
|
-
|
|
1288
|
+
- If the user wants to manage domains through DigitalOcean, then display:
|
|
1289
|
+
|
|
307
1290
|
```md
|
|
308
1291
|
## Move DNS records to DigitalOcean
|
|
309
|
-
|
|
1292
|
+
|
|
310
1293
|
Update your DNS provider with our nameservers.
|
|
311
|
-
|
|
1294
|
+
|
|
312
1295
|
DigitalOcean Nameservers
|
|
313
1296
|
- ns1.digitalocean.com
|
|
314
1297
|
- ns2.digitalocean.com
|
|
315
1298
|
- ns3.digitalocean.com
|
|
316
1299
|
```
|
|
317
|
-
|
|
318
|
-
|
|
1300
|
+
|
|
1301
|
+
- If the user wants to keep it self managed:
|
|
1302
|
+
- Get the default_ingress using `doctl apps get <app-id> --format DefaultIngress`
|
|
1303
|
+
- Display:
|
|
1304
|
+
|
|
319
1305
|
```md
|
|
320
1306
|
Add a new CNAME record using the provided alias to point your domain to your DigitalOcean app.
|
|
321
|
-
|
|
1307
|
+
|
|
322
1308
|
## CNAME alias
|
|
323
|
-
|
|
324
|
-
|
|
1309
|
+
<default_ingress>
|
|
1310
|
+
|
|
325
1311
|
Check if CNAME flattening is supported for root domains. If your provider doesn't support this method, you can create an A record that points to your root domain.
|
|
326
|
-
|
|
1312
|
+
|
|
327
1313
|
## A Records
|
|
328
1314
|
- 162.159.140.98
|
|
329
1315
|
- 172.66.0.96
|
|
330
1316
|
```
|
|
331
|
-
|
|
1317
|
+
|
|
1318
|
+
- Note: default ingress is only available after a successful deployment
|
|
332
1319
|
|
|
333
|
-
|
|
1320
|
+
4. **Important notes for the user:**
|
|
334
1321
|
- DNS propagation can take up to 48 hours
|
|
335
1322
|
- Wildcard domains (*.example.com) are also supported if needed
|
|
336
1323
|
|
|
337
|
-
|
|
1324
|
+
#### 2.8 Assisted Deployment Troubleshooting
|
|
338
1325
|
|
|
339
|
-
|
|
1326
|
+
**If deployment fails, follow this assisted troubleshooting process:**
|
|
340
1327
|
|
|
341
|
-
|
|
1328
|
+
The AI assistant will analyze errors and suggest fixes for you to review and approve. This is not fully automatic - you remain in control.
|
|
342
1329
|
|
|
343
1330
|
1. **Check deployment status:**
|
|
344
|
-
- Use
|
|
1331
|
+
- Use `doctl apps get <app-id>` to get deployment status
|
|
345
1332
|
- Status will be either: ACTIVE, DEPLOYED (success) or FAILED, ERROR (failure)
|
|
346
1333
|
|
|
347
1334
|
2. **Fetch deployment logs immediately:**
|
|
348
|
-
-
|
|
349
|
-
-
|
|
350
|
-
-
|
|
351
|
-
- Ask the user to copy and paste the build and deploy error logs if REST api is not available for use
|
|
1335
|
+
- Get build logs: `doctl apps logs <app-id> --type build`
|
|
1336
|
+
- Get runtime logs: `doctl apps logs <app-id> --type run`
|
|
1337
|
+
- Get deployment logs: `doctl apps get-deployment <app-id> <deployment-id>`
|
|
352
1338
|
- Parse the error messages to identify the failure type
|
|
353
1339
|
|
|
354
|
-
3. **Analyze the error and
|
|
1340
|
+
3. **Analyze the error and suggest fixes:**
|
|
355
1341
|
|
|
356
1342
|
**For "command not found" or "script not found" errors:**
|
|
357
|
-
- **
|
|
1343
|
+
- **Suggested fix - prefer buildpack auto-detection:**
|
|
358
1344
|
- **First attempt:** Leave build/run commands empty to let buildpack auto-detect
|
|
359
1345
|
- This works for most standard frameworks (Next.js, React, Vue, etc.)
|
|
360
1346
|
- If this fails, then try checking package.json for custom scripts:
|
|
@@ -364,14 +1350,14 @@ Determine the appropriate App Platform component type based on the app's charact
|
|
|
364
1350
|
- Update the app with corrected configuration and redeploy
|
|
365
1351
|
|
|
366
1352
|
**For "no start command" or run command errors:**
|
|
367
|
-
- **
|
|
1353
|
+
- **Suggested fix - prefer buildpack auto-detection:**
|
|
368
1354
|
- **First attempt:** Leave run command empty to let buildpack auto-detect
|
|
369
1355
|
- Buildpack will use framework defaults or package.json "start" script
|
|
370
1356
|
- Only specify custom run command if buildpack auto-detection fails
|
|
371
1357
|
- Update run command and redeploy
|
|
372
1358
|
|
|
373
1359
|
**For "output directory not found" errors:**
|
|
374
|
-
- **
|
|
1360
|
+
- **Suggested fix:**
|
|
375
1361
|
- Check common output directories: `build`, `dist`, `out`, `public`, `.next`
|
|
376
1362
|
- **Check .gitignore in migration folder** for build output patterns
|
|
377
1363
|
- Look in build logs for "writing output to..." messages
|
|
@@ -379,20 +1365,20 @@ Determine the appropriate App Platform component type based on the app's charact
|
|
|
379
1365
|
|
|
380
1366
|
**For "module not found" or dependency errors:**
|
|
381
1367
|
- **Check migration folder for lockfile** (package-lock.json or yarn.lock)
|
|
382
|
-
- **
|
|
1368
|
+
- **Suggested fix options:**
|
|
383
1369
|
- If lockfile is in a subdirectory, update source_dir
|
|
384
1370
|
- If using private packages, check if registry auth env vars are needed
|
|
385
1371
|
- Add NODE_ENV=production if missing
|
|
386
1372
|
|
|
387
1373
|
**For port/health check failures (service starts but fails health check):**
|
|
388
1374
|
- Fetch runtime logs to see what port the app is listening on
|
|
389
|
-
- **
|
|
1375
|
+
- **Suggested fix:**
|
|
390
1376
|
- Check if app is hardcoded to wrong port
|
|
391
1377
|
- Ensure PORT environment variable is set
|
|
392
1378
|
- Update HTTP port configuration if needed
|
|
393
1379
|
|
|
394
1380
|
**For monorepo/source directory errors:**
|
|
395
|
-
- **
|
|
1381
|
+
- **Suggested fix:**
|
|
396
1382
|
- Check Vercel config for rootDirectory
|
|
397
1383
|
- **Search migration folder** for package.json in subdirectories
|
|
398
1384
|
- Look for workspace configuration files (lerna.json, nx.json, etc.)
|
|
@@ -400,14 +1386,15 @@ Determine the appropriate App Platform component type based on the app's charact
|
|
|
400
1386
|
- Deploy the mono repo under 1 app, where each repository service is a `service component` or `static site component` depending on the repository service. Ask the user for confirmation.
|
|
401
1387
|
|
|
402
1388
|
4. **Apply the fix and redeploy:**
|
|
403
|
-
-
|
|
404
|
-
-
|
|
1389
|
+
- Update app spec YAML with fixes
|
|
1390
|
+
- Update app using doctl: `doctl apps update <app-id> --spec app-spec.yaml`
|
|
1391
|
+
- Or update specific config: `doctl apps update <app-id> --env <key>=<value>`
|
|
405
1392
|
- Wait for deployment to complete and check status again
|
|
406
1393
|
|
|
407
1394
|
5. **Retry logic:**
|
|
408
|
-
- If first
|
|
409
|
-
- Maximum 3
|
|
410
|
-
- After 3 failed attempts, report to user with detailed error and
|
|
1395
|
+
- If first suggested fix doesn't work, analyze logs again and try alternative approach
|
|
1396
|
+
- Maximum 3 assisted troubleshooting attempts per app
|
|
1397
|
+
- After 3 failed attempts, report to user with detailed error analysis and request manual intervention
|
|
411
1398
|
|
|
412
1399
|
6. **Report fix applied:**
|
|
413
1400
|
- Tell the user what error was found
|
|
@@ -418,19 +1405,19 @@ Determine the appropriate App Platform component type based on the app's charact
|
|
|
418
1405
|
|
|
419
1406
|
After migrating the app:
|
|
420
1407
|
|
|
421
|
-
1. **Verify deployment succeeded** in App Platform (use
|
|
1408
|
+
1. **Verify deployment succeeded** in App Platform (use `doctl apps get <app-id>` to check status)
|
|
422
1409
|
- Wait for the deployment to complete (this may take several minutes)
|
|
423
1410
|
- Check deployment status: should be "ACTIVE" or "DEPLOYED"
|
|
424
1411
|
|
|
425
|
-
2. **If deployment FAILED,
|
|
426
|
-
- Follow the process in section 2.8 "
|
|
427
|
-
- Fetch logs, analyze errors,
|
|
428
|
-
- Retry up to 3 times with different
|
|
1412
|
+
2. **If deployment FAILED, begin assisted troubleshooting:**
|
|
1413
|
+
- Follow the process in section 2.8 "Assisted Deployment Troubleshooting"
|
|
1414
|
+
- Fetch logs, analyze errors, suggest fixes for user to review
|
|
1415
|
+
- Retry up to 3 times with different suggested approaches
|
|
429
1416
|
- **Continue with validation after:**
|
|
430
1417
|
- The app is successfully deployed, OR
|
|
431
|
-
- 3
|
|
1418
|
+
- 3 troubleshooting attempts have been made and user intervention is needed
|
|
432
1419
|
|
|
433
|
-
3. **If
|
|
1420
|
+
3. **If suggested fixes don't resolve the issue after 3 attempts:**
|
|
434
1421
|
- Present detailed error information to the user
|
|
435
1422
|
- Show what fixes were attempted
|
|
436
1423
|
- Ask user for manual configuration input:
|
|
@@ -451,6 +1438,200 @@ After migrating the app:
|
|
|
451
1438
|
- If auto-fixed, show what was corrected
|
|
452
1439
|
- If failed, show the errors and fixes that were attempted
|
|
453
1440
|
|
|
1441
|
+
6. **Provide rollback plan:**
|
|
1442
|
+
- Inform user how to rollback if issues arise
|
|
1443
|
+
- See section 3.1 below for detailed rollback instructions
|
|
1444
|
+
|
|
1445
|
+
#### 3.1 Rollback and Recovery Plan
|
|
1446
|
+
|
|
1447
|
+
**Before updating DNS (if migrating from Vercel):**
|
|
1448
|
+
|
|
1449
|
+
1. ✅ Test App Platform deployment thoroughly using the default `.ondigitalocean.app` URL
|
|
1450
|
+
2. ✅ Verify all functionality works (API endpoints, database, authentication, etc.)
|
|
1451
|
+
3. ✅ Keep Vercel app running during DNS propagation (24-48 hours)
|
|
1452
|
+
4. ✅ Monitor App Platform logs and metrics for errors
|
|
1453
|
+
5. ✅ Have rollback plan ready before updating DNS
|
|
1454
|
+
|
|
1455
|
+
---
|
|
1456
|
+
|
|
1457
|
+
**Rollback Option A: DNS Rollback (if you've already updated DNS)**
|
|
1458
|
+
|
|
1459
|
+
If you've migrated domains but need to roll back to Vercel:
|
|
1460
|
+
|
|
1461
|
+
```bash
|
|
1462
|
+
# 1. Identify which DNS records need to be changed back
|
|
1463
|
+
# For each domain, update DNS records:
|
|
1464
|
+
|
|
1465
|
+
# If using CNAME record:
|
|
1466
|
+
# Change: myapp.com -> CNAME -> my-app-abc123.ondigitalocean.app
|
|
1467
|
+
# Back to: myapp.com -> CNAME -> cname.vercel-dns.com
|
|
1468
|
+
|
|
1469
|
+
# If using A records:
|
|
1470
|
+
# Remove App Platform A records (162.159.140.98, 172.66.0.96)
|
|
1471
|
+
# Restore original Vercel A records (check your DNS provider's history)
|
|
1472
|
+
```
|
|
1473
|
+
|
|
1474
|
+
**Steps:**
|
|
1475
|
+
1. Log into your DNS provider (Cloudflare, Namecheap, etc.)
|
|
1476
|
+
2. Restore DNS records to point back to Vercel
|
|
1477
|
+
3. Wait for DNS propagation (can take up to 48 hours, but often faster)
|
|
1478
|
+
4. Monitor traffic shifting back to Vercel
|
|
1479
|
+
5. Keep App Platform app running until you're ready to delete it
|
|
1480
|
+
|
|
1481
|
+
**Timeline**: DNS propagation typically takes 15 minutes to 48 hours depending on TTL settings.
|
|
1482
|
+
|
|
1483
|
+
---
|
|
1484
|
+
|
|
1485
|
+
**Rollback Option B: App Platform Deployment Rollback**
|
|
1486
|
+
|
|
1487
|
+
If App Platform is working but a recent deployment introduced bugs:
|
|
1488
|
+
|
|
1489
|
+
```bash
|
|
1490
|
+
# 1. View deployment history
|
|
1491
|
+
doctl apps list-deployments <app-id>
|
|
1492
|
+
|
|
1493
|
+
# Output will show:
|
|
1494
|
+
# ID Status Created At
|
|
1495
|
+
# abc123 ACTIVE 2025-01-15 10:30:00
|
|
1496
|
+
# def456 ACTIVE 2025-01-14 08:15:00 <- previous working deployment
|
|
1497
|
+
# ghi789 ACTIVE 2025-01-13 14:20:00
|
|
1498
|
+
|
|
1499
|
+
# 2. Rollback to previous deployment
|
|
1500
|
+
doctl apps create-deployment <app-id> --deployment-id <previous-deployment-id>
|
|
1501
|
+
|
|
1502
|
+
# Example:
|
|
1503
|
+
# doctl apps create-deployment abc-123-app --deployment-id def456
|
|
1504
|
+
```
|
|
1505
|
+
|
|
1506
|
+
**When to use this:**
|
|
1507
|
+
- Recent code push broke the app
|
|
1508
|
+
- Need to quickly return to last known good state
|
|
1509
|
+
- Issue is with application code, not infrastructure
|
|
1510
|
+
|
|
1511
|
+
**Limitations:**
|
|
1512
|
+
- Only rolls back application code, not infrastructure changes (database schema, env vars)
|
|
1513
|
+
- Can only rollback to deployments that are still available (typically last 10 deployments)
|
|
1514
|
+
- Database changes are NOT rolled back automatically - handle separately
|
|
1515
|
+
|
|
1516
|
+
---
|
|
1517
|
+
|
|
1518
|
+
**Rollback Option C: Code Rollback via Git**
|
|
1519
|
+
|
|
1520
|
+
If you need to revert code changes:
|
|
1521
|
+
|
|
1522
|
+
```bash
|
|
1523
|
+
# 1. Identify the problematic commit
|
|
1524
|
+
git log --oneline
|
|
1525
|
+
|
|
1526
|
+
# 2. Revert the commit (creates new commit that undoes changes)
|
|
1527
|
+
git revert <commit-hash>
|
|
1528
|
+
|
|
1529
|
+
# 3. Push to main branch
|
|
1530
|
+
git push origin main
|
|
1531
|
+
|
|
1532
|
+
# App Platform will automatically deploy the reverted code
|
|
1533
|
+
```
|
|
1534
|
+
|
|
1535
|
+
**When to use this:**
|
|
1536
|
+
- Need to undo specific code changes
|
|
1537
|
+
- Want to maintain git history
|
|
1538
|
+
- Problem is in application code
|
|
1539
|
+
|
|
1540
|
+
**Alternative - Reset to previous commit** (more destructive):
|
|
1541
|
+
```bash
|
|
1542
|
+
# WARNING: This rewrites history
|
|
1543
|
+
git reset --hard <previous-commit-hash>
|
|
1544
|
+
git push origin main --force
|
|
1545
|
+
|
|
1546
|
+
# App Platform will deploy the previous state
|
|
1547
|
+
```
|
|
1548
|
+
|
|
1549
|
+
⚠️ **Use `--force` with caution** - only do this if you understand the implications.
|
|
1550
|
+
|
|
1551
|
+
---
|
|
1552
|
+
|
|
1553
|
+
**Rollback Option D: Full App Deletion and Vercel Restoration**
|
|
1554
|
+
|
|
1555
|
+
If App Platform isn't working and you need to fully abort the migration:
|
|
1556
|
+
|
|
1557
|
+
1. **Do NOT delete Vercel app yet** - keep it running
|
|
1558
|
+
2. Update DNS to point back to Vercel (see Option A above)
|
|
1559
|
+
3. Wait for DNS propagation
|
|
1560
|
+
4. Verify traffic is back on Vercel
|
|
1561
|
+
5. Once confirmed stable, delete App Platform app:
|
|
1562
|
+
```bash
|
|
1563
|
+
doctl apps delete <app-id>
|
|
1564
|
+
```
|
|
1565
|
+
6. Note: Databases must be deleted separately:
|
|
1566
|
+
```bash
|
|
1567
|
+
doctl databases delete <db-id>
|
|
1568
|
+
```
|
|
1569
|
+
|
|
1570
|
+
---
|
|
1571
|
+
|
|
1572
|
+
**Database Rollback Considerations:**
|
|
1573
|
+
|
|
1574
|
+
⚠️ **Database schemas and data are NOT automatically rolled back**
|
|
1575
|
+
|
|
1576
|
+
If you ran database migrations on App Platform:
|
|
1577
|
+
|
|
1578
|
+
**Option 1: Restore from backup**
|
|
1579
|
+
```bash
|
|
1580
|
+
# List database backups
|
|
1581
|
+
doctl databases backups list <db-id>
|
|
1582
|
+
|
|
1583
|
+
# Restore from backup
|
|
1584
|
+
doctl databases restore <db-id> --backup-id <backup-id>
|
|
1585
|
+
```
|
|
1586
|
+
|
|
1587
|
+
**Option 2: Run reverse migrations**
|
|
1588
|
+
- If using Prisma, Drizzle, TypeORM, etc., run down/reverse migrations
|
|
1589
|
+
- This requires having written reverse migration scripts
|
|
1590
|
+
|
|
1591
|
+
**Option 3: Manual database restoration**
|
|
1592
|
+
- If you have a pg_dump from before migration, restore it
|
|
1593
|
+
- This is why taking a backup before migration is critical
|
|
1594
|
+
|
|
1595
|
+
---
|
|
1596
|
+
|
|
1597
|
+
**Monitoring During Rollback:**
|
|
1598
|
+
|
|
1599
|
+
While rolling back, monitor:
|
|
1600
|
+
- **DNS propagation**: Use `dig myapp.com` or online DNS checkers
|
|
1601
|
+
- **Traffic**: Check which servers are receiving traffic
|
|
1602
|
+
- **Error rates**: Monitor both Vercel and App Platform
|
|
1603
|
+
- **User impact**: Communicate with users if necessary
|
|
1604
|
+
|
|
1605
|
+
---
|
|
1606
|
+
|
|
1607
|
+
**Best Practices to Minimize Rollback Risk:**
|
|
1608
|
+
|
|
1609
|
+
1. ✅ **Test thoroughly** before updating DNS
|
|
1610
|
+
2. ✅ **Use low TTL** on DNS records during migration (e.g., 300 seconds / 5 minutes)
|
|
1611
|
+
3. ✅ **Backup database** before running migrations
|
|
1612
|
+
4. ✅ **Deploy to App Platform dev environment first** (create a separate dev app)
|
|
1613
|
+
5. ✅ **Keep Vercel running** for at least 48 hours after DNS update
|
|
1614
|
+
6. ✅ **Monitor metrics** closely for first 24-48 hours
|
|
1615
|
+
7. ✅ **Have team available** during DNS cutover window
|
|
1616
|
+
8. ✅ **Communicate with users** about potential brief disruption
|
|
1617
|
+
|
|
1618
|
+
---
|
|
1619
|
+
|
|
1620
|
+
**When to Rollback:**
|
|
1621
|
+
|
|
1622
|
+
Consider rolling back if:
|
|
1623
|
+
- ❌ Critical functionality is broken
|
|
1624
|
+
- ❌ Performance is significantly degraded
|
|
1625
|
+
- ❌ Database connection issues persist
|
|
1626
|
+
- ❌ Authentication/authorization fails
|
|
1627
|
+
- ❌ Third-party integrations break
|
|
1628
|
+
- ❌ Error rate exceeds acceptable threshold
|
|
1629
|
+
|
|
1630
|
+
Don't rollback for:
|
|
1631
|
+
- ✅ Minor UI issues (can be fixed with quick patch)
|
|
1632
|
+
- ✅ Non-critical features not working (can be fixed iteratively)
|
|
1633
|
+
- ✅ Expected differences in platform behavior (document for users)
|
|
1634
|
+
|
|
454
1635
|
### Step 4: Migration Summary
|
|
455
1636
|
|
|
456
1637
|
After completing the migration, provide:
|
|
@@ -485,6 +1666,140 @@ After completing the migration, provide:
|
|
|
485
1666
|
- Optimization suggestions
|
|
486
1667
|
- Timeline: Remind user to keep Vercel running until DNS fully propagates
|
|
487
1668
|
|
|
1669
|
+
## App Platform Strengths and When to Use It
|
|
1670
|
+
|
|
1671
|
+
While this guide focuses on migration considerations and limitations, it's important to understand App Platform's advantages:
|
|
1672
|
+
|
|
1673
|
+
**Built-in Managed Features:**
|
|
1674
|
+
- ✅ **Managed databases** with automatic backups, point-in-time recovery, and automatic failover (PostgreSQL, Redis/ValKey)
|
|
1675
|
+
- ✅ **Automatic SSL certificates** for all custom domains with auto-renewal
|
|
1676
|
+
- ✅ **Built-in CDN** for global content delivery with automatic edge caching
|
|
1677
|
+
- ✅ **Native cron jobs** and background workers for scheduled tasks
|
|
1678
|
+
- ✅ **One-click rollbacks** to previous deployments (last 10 deployments available)
|
|
1679
|
+
- ✅ **Automatic health checks** and restarts for failing services
|
|
1680
|
+
- ✅ **Zero-downtime deployments** with automatic traffic shifting
|
|
1681
|
+
|
|
1682
|
+
**Developer Experience:**
|
|
1683
|
+
- ✅ **Buildpack auto-detection** - minimal configuration required for standard frameworks
|
|
1684
|
+
- ✅ **Git-based deployments** - push to deploy, no complex CI/CD setup needed
|
|
1685
|
+
- ✅ **Preview URLs** for every deployment (`.ondigitalocean.app` subdomains)
|
|
1686
|
+
- ✅ **Integrated logs and metrics** - no external logging service needed
|
|
1687
|
+
- ✅ **Simple, transparent pricing** - no surprise bills, predictable costs
|
|
1688
|
+
- ✅ **Multi-component apps** - deploy frontend, API, workers in one app
|
|
1689
|
+
- ✅ **Internal service communication** - fast, secure service-to-service calls
|
|
1690
|
+
|
|
1691
|
+
**Infrastructure & Operations:**
|
|
1692
|
+
- ✅ **Managed infrastructure** - no Kubernetes knowledge required
|
|
1693
|
+
- ✅ **Automatic scaling** (horizontal scaling for web services)
|
|
1694
|
+
- ✅ **Resource monitoring** built into dashboard
|
|
1695
|
+
- ✅ **Security updates** handled automatically by buildpacks
|
|
1696
|
+
- ✅ **Compliance** - SOC 2, GDPR, HIPAA available on higher tiers
|
|
1697
|
+
- ✅ **Multiple regions** - deploy closer to your users (NYC, SF, AMS, SGP, BLR, etc.)
|
|
1698
|
+
|
|
1699
|
+
**When App Platform is a Great Fit:**
|
|
1700
|
+
- ✅ You want **managed infrastructure** without Kubernetes complexity
|
|
1701
|
+
- ✅ Your app uses **standard frameworks** (Next.js, Express, Django, Rails, Go, etc.)
|
|
1702
|
+
- ✅ You value **operational simplicity** over fine-grained control
|
|
1703
|
+
- ✅ You need **cost predictability** (flat monthly pricing per service)
|
|
1704
|
+
- ✅ You want **database management** handled for you
|
|
1705
|
+
- ✅ You're building **monorepo** apps with multiple services
|
|
1706
|
+
- ✅ You prefer **convention over configuration**
|
|
1707
|
+
|
|
1708
|
+
**When to Consider Alternatives:**
|
|
1709
|
+
- ⚠️ You need edge computing with sub-10ms global latency
|
|
1710
|
+
- ⚠️ You heavily rely on Vercel Edge Functions or middleware
|
|
1711
|
+
- ⚠️ You need ISR (Incremental Static Regeneration)
|
|
1712
|
+
- ⚠️ You require custom infrastructure or bare metal
|
|
1713
|
+
- ⚠️ You need highly customized caching strategies
|
|
1714
|
+
- ⚠️ You want automatic PR preview deployments (requires GitHub Actions setup)
|
|
1715
|
+
|
|
1716
|
+
---
|
|
1717
|
+
|
|
1718
|
+
## Expected Outcomes and Success Criteria
|
|
1719
|
+
|
|
1720
|
+
**This guide works well for:**
|
|
1721
|
+
|
|
1722
|
+
✅ **Standard web applications:**
|
|
1723
|
+
- Next.js apps with API routes and database
|
|
1724
|
+
- React/Vue/Angular SPAs with backend APIs
|
|
1725
|
+
- Express/Fastify Node.js applications
|
|
1726
|
+
- Full-stack monorepo applications
|
|
1727
|
+
- Apps with straightforward build processes
|
|
1728
|
+
- Apps using standard framework conventions
|
|
1729
|
+
|
|
1730
|
+
✅ **Migration scenarios:**
|
|
1731
|
+
- Simple to moderate complexity apps
|
|
1732
|
+
- Apps with manageable environment variables (< 50 vars)
|
|
1733
|
+
- Standard database usage (PostgreSQL, Redis)
|
|
1734
|
+
- Apps without heavy Vercel-specific features
|
|
1735
|
+
- Teams comfortable with some manual configuration
|
|
1736
|
+
|
|
1737
|
+
**This guide may require additional work for:**
|
|
1738
|
+
|
|
1739
|
+
⚠️ **Complex architectures:**
|
|
1740
|
+
- Heavy monorepo setups with custom build orchestration
|
|
1741
|
+
- Apps with complex multi-stage builds
|
|
1742
|
+
- Apps with custom buildpacks or Docker requirements
|
|
1743
|
+
- Microservices with complex inter-service dependencies
|
|
1744
|
+
- Apps with extensive custom middleware
|
|
1745
|
+
|
|
1746
|
+
⚠️ **Vercel-heavy applications:**
|
|
1747
|
+
- Apps heavily dependent on Edge Functions
|
|
1748
|
+
- Apps using Vercel middleware extensively
|
|
1749
|
+
- Apps relying on ISR (Incremental Static Regeneration)
|
|
1750
|
+
- Apps with complex Vercel-specific rewrites/redirects
|
|
1751
|
+
- Apps using Vercel's built-in image optimization heavily
|
|
1752
|
+
|
|
1753
|
+
⚠️ **Special requirements:**
|
|
1754
|
+
- Real-time collaborative applications with WebSocket state management
|
|
1755
|
+
- Apps requiring GPU acceleration
|
|
1756
|
+
- Apps with proprietary build systems
|
|
1757
|
+
- Apps that need extensive custom caching logic
|
|
1758
|
+
- Apps requiring sub-10ms global edge latency
|
|
1759
|
+
|
|
1760
|
+
**This guide is NOT suitable for:**
|
|
1761
|
+
|
|
1762
|
+
❌ **Non-standard infrastructure:**
|
|
1763
|
+
- Custom infrastructure requirements (bare metal, GPU, specific hardware)
|
|
1764
|
+
- Apps that can't use buildpacks (custom base images, etc.)
|
|
1765
|
+
- Apps requiring Windows servers
|
|
1766
|
+
- Apps with licensed software that can't run in containers
|
|
1767
|
+
|
|
1768
|
+
❌ **Extreme edge cases:**
|
|
1769
|
+
- Real-time gaming backends with state synchronization
|
|
1770
|
+
- Video/audio processing requiring specialized hardware
|
|
1771
|
+
- Blockchain nodes or cryptocurrency mining
|
|
1772
|
+
- Applications requiring root access or kernel modules
|
|
1773
|
+
|
|
1774
|
+
**If your app falls into these categories**, consult DigitalOcean documentation or support for custom solutions, or consider using DigitalOcean Droplets/Kubernetes for more control.
|
|
1775
|
+
|
|
1776
|
+
---
|
|
1777
|
+
|
|
1778
|
+
**Realistic Expectations:**
|
|
1779
|
+
|
|
1780
|
+
**What this guide will help you achieve:**
|
|
1781
|
+
- 🎯 Deploy your app to App Platform in 30-60 minutes (simple apps)
|
|
1782
|
+
- 🎯 Automated error detection and fix suggestions (up to 3 attempts)
|
|
1783
|
+
- 🎯 Working app spec YAML file you can modify
|
|
1784
|
+
- 🎯 Clear understanding of what needs manual work
|
|
1785
|
+
- 🎯 Rollback plan if things go wrong
|
|
1786
|
+
|
|
1787
|
+
**What requires human intervention:**
|
|
1788
|
+
- 👤 Understanding your app's architecture
|
|
1789
|
+
- 👤 Making trade-off decisions (cost, features, performance)
|
|
1790
|
+
- 👤 Implementing code changes for unsupported features
|
|
1791
|
+
- 👤 Testing and validating functionality
|
|
1792
|
+
- 👤 Database data migration (separate manual process)
|
|
1793
|
+
- 👤 Monitoring production performance
|
|
1794
|
+
|
|
1795
|
+
**Success metrics:**
|
|
1796
|
+
- ✅ App builds successfully on first or second attempt
|
|
1797
|
+
- ✅ All critical functionality works on App Platform
|
|
1798
|
+
- ✅ Performance is acceptable (within 10-20% of Vercel)
|
|
1799
|
+
- ✅ Database connections work reliably
|
|
1800
|
+
- ✅ Environment variables are correctly configured
|
|
1801
|
+
- ✅ You understand how to deploy updates
|
|
1802
|
+
|
|
488
1803
|
## Special Considerations
|
|
489
1804
|
|
|
490
1805
|
### Preview Deployments
|
|
@@ -492,17 +1807,27 @@ After completing the migration, provide:
|
|
|
492
1807
|
- **Workaround:** Create a separate dev app with dev environment
|
|
493
1808
|
- Recommend using GitHub Actions for preview deployments
|
|
494
1809
|
|
|
495
|
-
###
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
**
|
|
499
|
-
-
|
|
1810
|
+
### CLI Tools vs MCP Servers
|
|
1811
|
+
|
|
1812
|
+
**Primary Method: CLI Tools (Recommended)**
|
|
1813
|
+
- **doctl CLI:** Primary method for App Platform operations
|
|
1814
|
+
- Create apps: `doctl apps create --spec app-spec.yaml`
|
|
1815
|
+
- Manage deployments: `doctl apps get <app-id>`
|
|
1816
|
+
- Configure domains: `doctl apps create-domain <app-id> --domain <domain>`
|
|
1817
|
+
- View logs: `doctl apps logs <app-id> --type build|run`
|
|
1818
|
+
- Update apps: `doctl apps update <app-id> --spec app-spec.yaml`
|
|
1819
|
+
- **gh CLI:** For GitHub repository operations
|
|
1820
|
+
- Create repo: `gh repo create <name> --private --source=. --push`
|
|
1821
|
+
- Fork repo: `gh repo fork <owner>/<repo>`
|
|
1822
|
+
- View repo: `gh repo view`
|
|
1823
|
+
- **Vercel CLI (if migrating from Vercel):** For environment variables and app details
|
|
1824
|
+
- Pull env vars: `vercel env pull .env.production --environment=production`
|
|
1825
|
+
- Inspect app: `vercel inspect <app-name>`
|
|
1826
|
+
|
|
1827
|
+
**Alternative Method: MCP Servers (Optional)**
|
|
500
1828
|
- **Vercel MCP server (Optional):** Project metadata where available
|
|
501
|
-
- **
|
|
502
|
-
|
|
503
|
-
**DigitalOcean:**
|
|
504
|
-
- **DigitalOcean MCP server (Primary):** App creation, deployment management, domain configuration
|
|
505
|
-
- **Fallback:** `doctl` CLI or REST API if MCP is unavailable
|
|
1829
|
+
- **DigitalOcean MCP server (Optional):** App Platform operations
|
|
1830
|
+
- **Note:** CLI tools are preferred - users don't need MCP servers
|
|
506
1831
|
|
|
507
1832
|
### Database Migration
|
|
508
1833
|
- Creating new databases is straightforward
|
|
@@ -618,34 +1943,64 @@ Throughout the migration:
|
|
|
618
1943
|
- Migration folders will be created at `./vercel-migration/<app-name>-migration/` for each app
|
|
619
1944
|
- App specs will be saved for each app as backup
|
|
620
1945
|
- App Platform buildpack documentation will be referenced for best practices
|
|
621
|
-
- **Explain
|
|
622
|
-
- **Show your work** - when
|
|
1946
|
+
- **Explain assisted troubleshooting** - let users know that if deployments fail, you will analyze logs and suggest fixes for them to review
|
|
1947
|
+
- **Show your work** - when fixes are suggested and applied, explain what error was found and what solution was proposed
|
|
623
1948
|
- **Confirm** before making changes that could affect production
|
|
624
|
-
- **Keep user informed** during
|
|
1949
|
+
- **Keep user informed** during retry attempts (e.g., "Deployment failed, analyzing logs and suggesting fix 1 of 3...")
|
|
625
1950
|
|
|
626
1951
|
## Final Checklist
|
|
627
1952
|
|
|
628
|
-
Before marking
|
|
629
|
-
|
|
630
|
-
- [ ]
|
|
631
|
-
- [ ]
|
|
632
|
-
- [ ]
|
|
633
|
-
- [ ]
|
|
634
|
-
- [ ]
|
|
1953
|
+
Before marking deployment complete:
|
|
1954
|
+
|
|
1955
|
+
- [ ] Local testing completed (Step 0) - dependencies install, build succeeds
|
|
1956
|
+
- [ ] Repository is set up and accessible (Step 1)
|
|
1957
|
+
- [ ] Database is created (if needed) and connection string is available
|
|
1958
|
+
- [ ] Environment variables are collected and prepared
|
|
1959
|
+
- [ ] App spec YAML file is created and validated
|
|
1960
|
+
- [ ] The app has been created in App Platform using `doctl apps create`
|
|
1961
|
+
- [ ] Deployment is successful (either on first try or after assisted troubleshooting)
|
|
1962
|
+
- [ ] Assisted troubleshooting was attempted if deployment failed
|
|
1963
|
+
- [ ] User has been informed of any fixes that were suggested and applied
|
|
1964
|
+
- [ ] Environment variables have been configured in App Platform
|
|
635
1965
|
- [ ] Build configurations match validated settings from repository inspection
|
|
636
|
-
- [ ] App spec has been saved to
|
|
637
|
-
- [ ] Custom domains have been added to the App Platform app
|
|
638
|
-
- [ ] User has received DNS update instructions for each domain
|
|
1966
|
+
- [ ] App spec has been saved to `app-spec.yaml` (or migration folder)
|
|
1967
|
+
- [ ] Custom domains have been added to the App Platform app (if applicable)
|
|
1968
|
+
- [ ] User has received DNS update instructions for each domain (if applicable)
|
|
639
1969
|
- [ ] User understands to test before updating DNS
|
|
640
1970
|
- [ ] User has been informed about unsupported features
|
|
641
1971
|
- [ ] User has testing instructions
|
|
642
1972
|
- [ ] User knows how to rollback if needed
|
|
643
|
-
- [ ] User knows to keep Vercel running until DNS propagates
|
|
1973
|
+
- [ ] If migrating from Vercel: User knows to keep Vercel running until DNS propagates
|
|
644
1974
|
- [ ] Summary includes the app's status (Success/Auto-Fixed/Failed) with details
|
|
645
1975
|
- [ ] If successful: provide app name, URL (default ingress), and dashboard URL (`https://cloud.digitalocean.com/apps/$app_id`)
|
|
646
1976
|
- [ ] If failed: tell the user to create a support ticket and link to DigitalOcean's documentation
|
|
647
|
-
- [ ] Remind user they can repeat this process for additional apps they want to
|
|
1977
|
+
- [ ] Remind user they can repeat this process for additional apps they want to deploy
|
|
1978
|
+
|
|
648
1979
|
---
|
|
649
1980
|
|
|
650
|
-
|
|
1981
|
+
## Key Points from This Update
|
|
1982
|
+
|
|
1983
|
+
1. **Multiple deployment scenarios supported:**
|
|
1984
|
+
- Migrating from existing Vercel deployment
|
|
1985
|
+
- Deploying source code directly (no Vercel required)
|
|
1986
|
+
- Deploying without repository access (create new repo or deploy from local)
|
|
1987
|
+
|
|
1988
|
+
2. **CLI tools are primary method:**
|
|
1989
|
+
- `doctl` for App Platform operations
|
|
1990
|
+
- `gh` CLI for GitHub repository operations
|
|
1991
|
+
- `vercel` CLI only if migrating from Vercel
|
|
1992
|
+
- MCP servers are optional, not required
|
|
1993
|
+
|
|
1994
|
+
3. **Local testing before deployment:**
|
|
1995
|
+
- Test build locally to catch issues early
|
|
1996
|
+
- Avoid waiting for deployment errors
|
|
1997
|
+
- Verify dependencies, build, and configuration
|
|
1998
|
+
|
|
1999
|
+
4. **Goal is to get app working on App Platform:**
|
|
2000
|
+
- Doesn't require existing Vercel deployment
|
|
2001
|
+
- Focus on making source code work on App Platform
|
|
2002
|
+
- Support users who don't want to give repo access
|
|
2003
|
+
|
|
2004
|
+
---
|
|
651
2005
|
|
|
2006
|
+
**Remember:** This is an AI-assisted deployment guide. Always prioritize user confirmation for critical decisions and be clear about what can and cannot be automated. The AI assistant provides suggestions and automates routine tasks, but the human user makes final decisions and validates results. The goal is to get the application working on App Platform through active collaboration, whether it's a migration from Vercel or a fresh deployment.
|