Skip to content

Gap-8: App Service Migrate (F → A) — Beanstalk + Heroku + App Engine migration guides - #1633

Merged
JasonYeMSFT (JasonYeMSFT) merged 4 commits into
mainfrom
pass-equity-gap-8
May 4, 2026
Merged

Gap-8: App Service Migrate (F → A) — Beanstalk + Heroku + App Engine migration guides#1633
JasonYeMSFT (JasonYeMSFT) merged 4 commits into
mainfrom
pass-equity-gap-8

Conversation

@paulyuk

Copy link
Copy Markdown
Member

Closes #1616 | Parent: #1608

What

Add cross-cloud migration support for App Service — previously zero coverage (grade F).

Files Added (6 migration references)

  • beanstalk-to-app-service.md — AWS Elastic Beanstalk → App Service
  • heroku-to-app-service.md — Heroku → App Service
  • app-engine-to-app-service.md — Google App Engine → App Service
  • assessment.md — PaaS-to-PaaS assessment report template
  • code-migration.md — Code conversion guidance
  • global-rules.md — Migration rules

Tests Updated

  • 11 new trigger test cases for Beanstalk, Heroku, and App Engine migration prompts
  • Snapshots regenerated for expanded SKILL.md description
  • All 43 tests passing ✅

Critical Path

⚠️ This PR modifies azure-cloud-migrate/SKILL.mdGap-9 (Container Apps Migrate) depends on this PR merging first since it also needs SKILL.md trigger changes.

Starting assessment — domain experts should review and modify scenarios.

…Engine (Gap-8)

Add cross-cloud migration support for App Service:
- beanstalk-to-app-service.md — AWS Elastic Beanstalk migration
- heroku-to-app-service.md — Heroku migration
- app-engine-to-app-service.md — Google App Engine migration
- assessment.md — PaaS-to-PaaS assessment template
- code-migration.md — Code conversion guidance
- global-rules.md — Migration rules

Updated SKILL.md with new triggers (Beanstalk, Heroku, App Engine, Cloud Run, ECS)
Updated trigger tests with 11 new routing test cases
Updated snapshots for expanded keyword set

Closes #1616
Parent: #1608

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds App Service cross-cloud migration coverage (Beanstalk/Heroku/App Engine) to the azure-cloud-migrate skill, along with updated triggers/tests and references.

Changes:

  • Added App Service migration reference guides (assessment, code-migration, global rules, and source-specific mappings).
  • Expanded trigger tests to cover Beanstalk/Heroku/App Engine prompts and regenerated snapshots.
  • Updated SKILL.md description/version and scenario table to include App Service migrations.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
tests/azure-cloud-migrate/triggers.test.ts Adds new “should trigger” prompt sets for App Service migration scenarios.
tests/azure-cloud-migrate/snapshots/triggers.test.ts.snap Updates expected keyword extraction/snapshot due to SKILL metadata changes.
plugin/skills/azure-cloud-migrate/SKILL.md Updates skill description/version and adds App Service scenarios + links.
plugin/skills/azure-cloud-migrate/references/services/app-service/global-rules.md Introduces App Service migration guardrails and identity-first rules.
plugin/skills/azure-cloud-migrate/references/services/app-service/assessment.md Adds an App Service-focused assessment template/phase guidance.
plugin/skills/azure-cloud-migrate/references/services/app-service/code-migration.md Adds code conversion guidance and patterns for App Service.
plugin/skills/azure-cloud-migrate/references/services/app-service/beanstalk-to-app-service.md Adds Beanstalk → App Service mapping and examples.
plugin/skills/azure-cloud-migrate/references/services/app-service/heroku-to-app-service.md Adds Heroku → App Service mapping and CI/CD guidance.
plugin/skills/azure-cloud-migrate/references/services/app-service/app-engine-to-app-service.md Adds App Engine → App Service mapping and examples.

Comment thread plugin/skills/azure-cloud-migrate/SKILL.md Outdated
Comment thread plugin/skills/azure-cloud-migrate/SKILL.md Outdated
Comment thread plugin/skills/azure-cloud-migrate/references/services/app-service/global-rules.md Outdated
@github-actions

github-actions Bot commented Apr 1, 2026

Copy link
Copy Markdown
Contributor
Details# 🔍 Token Analysis Report

@github-copilot-for-azure/scripts@1.0.0 tokens
node --import tsx src/tokens/cli.ts compare --base origin/main --head HEAD --markdown

fatal: path 'plugin/skills/azure-cloud-migrate/references/services/app-service/app-engine-to-app-service.md' exists on disk, but not in 'origin/main'
fatal: path 'plugin/skills/azure-cloud-migrate/references/services/app-service/assessment.md' exists on disk, but not in 'origin/main'
fatal: path 'plugin/skills/azure-cloud-migrate/references/services/app-service/beanstalk-to-app-service.md' exists on disk, but not in 'origin/main'
fatal: path 'plugin/skills/azure-cloud-migrate/references/services/app-service/code-migration.md' exists on disk, but not in 'origin/main'
fatal: path 'plugin/skills/azure-cloud-migrate/references/services/app-service/global-rules.md' exists on disk, but not in 'origin/main'
fatal: path 'plugin/skills/azure-cloud-migrate/references/services/app-service/heroku-to-app-service.md' exists on disk, but not in 'origin/main'

📊 Token Change Report

Comparing origin/mainHEAD

Summary

Metric Value
📈 Total Change +8,869 tokens (+1046%)
Before 848 tokens
After 9,717 tokens
Files Changed 7

Changed Files

File Before After Change
plugin/skills/azure-cloud-migrate/references/services/app-service/heroku-to-app-service.md - 1,924 +1924
plugin/skills/azure-cloud-migrate/references/services/app-service/app-engine-to-app-service.md - 1,822 +1822
plugin/skills/azure-cloud-migrate/references/services/app-service/beanstalk-to-app-service.md - 1,624 +1624
plugin/skills/azure-cloud-migrate/references/services/app-service/assessment.md - 1,328 +1328
plugin/skills/azure-cloud-migrate/references/services/app-service/code-migration.md - 1,257 +1257
plugin/skills/azure-cloud-migrate/references/services/app-service/global-rules.md - 724 +724
plugin/skills/azure-cloud-migrate/SKILL.md 848 1,038 +190 (+22%)

@github-copilot-for-azure/scripts@1.0.0 tokens
node --import tsx src/tokens/cli.ts check --markdown

📊 Token Limit Check Report

Checked: 590 files
Exceeded: 90 files

⚠️ Files Exceeding Token Limits

File Tokens Limit Over By
.github/skills/analyze-skill-issues/SKILL.md 2109 500 +1609
.github/skills/analyze-test-run/SKILL.md 2471 500 +1971
.github/skills/file-test-bug/SKILL.md 628 500 +128
.github/skills/sensei/README.md 3531 2000 +1531
.github/skills/sensei/SKILL.md 3026 500 +2526
.github/skills/sensei/references/EXAMPLES.md 3701 2000 +1701
.github/skills/sensei/references/LOOP.md 4181 2000 +2181
.github/skills/sensei/references/SCORING.md 4299 2000 +2299
.github/skills/skill-authoring/SKILL.md 839 500 +339
plugin/skills/airunway-aks-setup/SKILL.md 1025 500 +525
plugin/skills/appinsights-instrumentation/SKILL.md 911 500 +411
plugin/skills/azure-ai/SKILL.md 820 500 +320
plugin/skills/azure-aigateway/SKILL.md 1261 500 +761
plugin/skills/azure-aigateway/references/policies.md 2342 2000 +342
plugin/skills/azure-cloud-migrate/SKILL.md 1038 500 +538
plugin/skills/azure-cloud-migrate/references/services/container-apps/cloudrun-deployment-guide.md 2029 2000 +29
plugin/skills/azure-cloud-migrate/references/services/container-apps/deployment-guide.md 2458 2000 +458
plugin/skills/azure-cloud-migrate/references/services/container-apps/fargate-deployment-guide.md 2587 2000 +587
plugin/skills/azure-cloud-migrate/references/services/functions/lambda-to-functions.md 2600 2000 +600
plugin/skills/azure-cloud-migrate/references/services/functions/runtimes/javascript.md 2181 2000 +181
plugin/skills/azure-compliance/SKILL.md 1188 500 +688
plugin/skills/azure-compute/SKILL.md 1090 500 +590
plugin/skills/azure-compute/workflows/vm-recommender/vm-recommender.md 2631 2000 +631
plugin/skills/azure-compute/workflows/vm-troubleshooter/vm-troubleshooter.md 2509 2000 +509
plugin/skills/azure-cost/SKILL.md 1980 500 +1480
plugin/skills/azure-deploy/SKILL.md 1645 500 +1145
plugin/skills/azure-deploy/references/pre-deploy-checklist.md 4692 2000 +2692
plugin/skills/azure-deploy/references/recipes/azd/errors.md 4004 2000 +2004
plugin/skills/azure-deploy/references/troubleshooting.md 2038 2000 +38
plugin/skills/azure-diagnostics/SKILL.md 1423 500 +923
plugin/skills/azure-enterprise-infra-planner/SKILL.md 1002 500 +502
plugin/skills/azure-enterprise-infra-planner/references/constraints/compute-apps.md 2022 2000 +22
plugin/skills/azure-hosted-copilot-sdk/SKILL.md 1263 500 +763
plugin/skills/azure-kubernetes/SKILL.md 2606 500 +2106
plugin/skills/azure-kubernetes/azure-kubernetes-automatic-readiness/SKILL.md 3609 500 +3109
plugin/skills/azure-kusto/SKILL.md 2152 500 +1652
plugin/skills/azure-messaging/SKILL.md 821 500 +321
plugin/skills/azure-prepare/SKILL.md 3359 500 +2859
plugin/skills/azure-prepare/references/aspire.md 4617 2000 +2617
plugin/skills/azure-prepare/references/plan-template.md 2617 2000 +617
plugin/skills/azure-prepare/references/recipes/azd/aspire.md 2275 2000 +275
plugin/skills/azure-prepare/references/recipes/azd/terraform.md 3555 2000 +1555
plugin/skills/azure-prepare/references/research.md 2274 2000 +274
plugin/skills/azure-prepare/references/resources-limits-quotas.md 3322 2000 +1322
plugin/skills/azure-prepare/references/security.md 2147 2000 +147
plugin/skills/azure-prepare/references/services/functions/bicep.md 3127 2000 +1127
plugin/skills/azure-prepare/references/services/functions/templates/recipes/composition.md 2813 2000 +813
plugin/skills/azure-prepare/references/services/functions/terraform.md 3404 2000 +1404
plugin/skills/azure-prepare/references/services/sql-database/bicep.md 2037 2000 +37
plugin/skills/azure-quotas/SKILL.md 2821 500 +2321
plugin/skills/azure-quotas/references/commands.md 2644 2000 +644
plugin/skills/azure-resource-lookup/SKILL.md 1394 500 +894
plugin/skills/azure-resource-visualizer/SKILL.md 2122 500 +1622
plugin/skills/azure-storage/SKILL.md 1228 500 +728
plugin/skills/azure-upgrade/SKILL.md 1249 500 +749
plugin/skills/azure-upgrade/references/languages/java/INSTRUCTION.md 2724 2000 +724
plugin/skills/azure-upgrade/references/languages/java/package-specific/com.microsoft.azure.management.md 2215 2000 +215
plugin/skills/azure-upgrade/references/languages/java/templates/PLAN_TEMPLATE.md 2411 2000 +411
plugin/skills/azure-upgrade/references/languages/java/templates/PROGRESS_TEMPLATE.md 2315 2000 +315
plugin/skills/azure-upgrade/references/languages/java/templates/SUMMARY_TEMPLATE.md 2190 2000 +190
plugin/skills/azure-upgrade/references/services/functions/automation.md 3463 2000 +1463
plugin/skills/azure-upgrade/references/services/functions/consumption-to-flex.md 2773 2000 +773
plugin/skills/azure-validate/SKILL.md 950 500 +450
plugin/skills/entra-agent-id/SKILL.md 4001 500 +3501
plugin/skills/entra-app-registration/SKILL.md 2070 500 +1570
plugin/skills/entra-app-registration/references/api-permissions.md 2545 2000 +545
plugin/skills/entra-app-registration/references/cli-commands.md 2211 2000 +211
plugin/skills/entra-app-registration/references/console-app-example.md 2752 2000 +752
plugin/skills/entra-app-registration/references/oauth-flows.md 2375 2000 +375
plugin/skills/microsoft-foundry/SKILL.md 3840 500 +3340
plugin/skills/microsoft-foundry/foundry-agent/create/create.md 4315 2000 +2315
plugin/skills/microsoft-foundry/foundry-agent/create/references/toolbox.md 2851 2000 +851
plugin/skills/microsoft-foundry/foundry-agent/deploy/deploy.md 6133 2000 +4133
plugin/skills/microsoft-foundry/foundry-agent/eval-datasets/eval-datasets.md 2494 2000 +494
plugin/skills/microsoft-foundry/foundry-agent/eval-datasets/references/generate-seed-dataset.md 2088 2000 +88
plugin/skills/microsoft-foundry/foundry-agent/eval-datasets/references/trace-to-dataset.md 4325 2000 +2325
plugin/skills/microsoft-foundry/foundry-agent/invoke/invoke.md 2084 2000 +84
plugin/skills/microsoft-foundry/foundry-agent/observe/observe.md 2941 2000 +941
plugin/skills/microsoft-foundry/foundry-agent/observe/references/continuous-eval.md 3860 2000 +1860
plugin/skills/microsoft-foundry/foundry-agent/trace/references/kql-templates.md 2701 2000 +701
plugin/skills/microsoft-foundry/models/deploy-model/SKILL.md 1640 500 +1140
plugin/skills/microsoft-foundry/models/deploy-model/capacity/SKILL.md 1739 500 +1239
plugin/skills/microsoft-foundry/models/deploy-model/customize/SKILL.md 2235 500 +1735
plugin/skills/microsoft-foundry/models/deploy-model/customize/references/customize-workflow.md 3335 2000 +1335
plugin/skills/microsoft-foundry/models/deploy-model/preset/SKILL.md 1226 500 +726
plugin/skills/microsoft-foundry/models/deploy-model/preset/references/preset-workflow.md 5534 2000 +3534
plugin/skills/microsoft-foundry/quota/quota.md 2288 2000 +288
plugin/skills/microsoft-foundry/quota/references/capacity-planning.md 2080 2000 +80
plugin/skills/microsoft-foundry/references/agent-metadata-contract.md 2373 2000 +373
plugin/skills/microsoft-foundry/references/sdk/foundry-sdk-py.md 2162 2000 +162

Consider moving content to references/ subdirectories.


Automated token analysis. See skill authoring guidelines for best practices.

@jongio Jon Gallant (jongio) left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CI is red - the snapshot header uses the old goo.gl/fbAQLP URL instead of jestjs.io/docs/snapshot-testing that every other snapshot in the repo uses. That's the only test suite failure and it's an easy fix (regenerate with the repo's Jest version).

Beyond CI, the reference docs have several technical accuracy issues that would cause the AI agent to generate incorrect migration guidance - broken Bicep, wrong service attributions, deprecated npm flags, and some misleading feature mappings. Details in inline comments.

The overall structure and approach is solid - matching the existing functions/ migration pattern with per-source-platform docs makes sense.

Comment thread tests/azure-cloud-migrate/__snapshots__/triggers.test.ts.snap Outdated
Comment thread plugin/skills/azure-cloud-migrate/SKILL.md Outdated
Comment thread plugin/skills/azure-cloud-migrate/references/services/app-service/global-rules.md Outdated
Comment thread tests/azure-cloud-migrate/triggers.test.ts
@kvenkatrajan

Copy link
Copy Markdown
Collaborator

Andrew Westgarth (@apwestgarth) - another one please

@paulyuk

Copy link
Copy Markdown
Member Author

📌 Follow-up enhancement filed: #2148

After this PR ships, we plan to refactor App Service templates to use a dynamic MCP tool pattern (analogous to Manvir Kaur (@manvkaur)'s Functions work in #1949), which would replace ~1,995 lines of hardcoded templates with runtime fetches from Azure-Samples + 3-tier fallback. This is intentionally not blocking this PR — we want to ship the proven, hand-curated templates now and layer the optimization after.

Paul Yu (paulyufan) and others added 2 commits May 3, 2026 10:15
# Conflicts:
#	plugin/skills/azure-cloud-migrate/SKILL.md
#	tests/azure-cloud-migrate/__snapshots__/triggers.test.ts.snap
#	tests/azure-cloud-migrate/triggers.test.ts
CI fix:
- Snapshot file regenerated with correct Jest header (jestjs.io/docs/snapshot-testing)
  after merge with main; resolves the test suite failure flagged at line 1.

SKILL.md / triggers:
- Description now matches scenario table (no orphan triggers); merged App Service
  + Container Apps trigger phrases under 60-word limit.
- triggers.test.ts: split should-trigger groups by source platform; added
  near-miss negative cases (e.g., 'What is Elastic Beanstalk?') with note that
  keyword matching cannot distinguish 'Deploy to Heroku' from 'Migrate from
  Heroku' (intent-level routing).

Tool references:
- Fixed 4 mis-named tool references: 'mcp_azure_mcp_get_bestpractices' →
  'mcp_azure_mcp_get_azure_bestpractices' across global-rules.md,
  assessment.md, and code-migration.md (caught by mcp-tool-references test).

Beanstalk:
- Split Python 3.11/3.12 into separate rows so version-pinned apps don't
  get force-upgraded during migration.
- Clarified sysvinit migration target: WebJobs (continuous) or Functions —
  Always On is not equivalent (it just prevents idle unload).
- Reworded RDS Proxy → 'Azure Database for PostgreSQL Flexible Server
  (built-in PgBouncer)' since PgBouncer is a Postgres feature, not App Service.

Heroku:
- Removed inaccurate '60 min/day' Free SKU limit; F1 uses CPU-minute quota.
- Added required 'permissions: id-token: write, contents: read' block to
  GitHub Actions OIDC example so azure/login@v2 doesn't 403.
- Reworded NODE_ENV/RAILS_ENV mapping — clarified it's an App Setting that
  controls runtime behavior, NOT confused with WEBSITES_NODE_DEFAULT_VERSION
  which controls the Node.js engine version.

App Engine:
- Removed misleading GOOGLE_CLOUD_PROJECT → AZURE_SUBSCRIPTION_ID mapping.
  GCP project IDs identify a runtime environment; Azure subscription IDs
  are tooling/billing context, not runtime equivalent.

Code migration:
- 'npm ci --production' → 'npm ci --omit=dev' (deprecated in npm 9+).
- Wrapped top-level await example in async function main() so the snippet
  runs as shown in CommonJS / standard Node entrypoints.

Global rules:
- Fixed misleading 'managed identity for telemetry ingestion' — App Insights
  ingestion uses APPLICATIONINSIGHTS_CONNECTION_STRING; managed identity is
  for management-plane access (querying, configuring), not ingestion.
- Switched runtime stack link from Node.js-specific page to overview page
  (overview-supported-languages).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@paulyuk

Copy link
Copy Markdown
Member Author

Review Feedback Addressed

Latest commit (25adde8) addresses all 16 active review threads + merges main. Verified each one against current code.

CI / Build

  • Snapshot header — File regenerated via npm test -u after merge; now uses correct https://jestjs.io/docs/snapshot-testing URL. Test suite no longer fails.
  • Tool name fix — 4 references to mcp_azure_mcp_get_bestpractices corrected to mcp_azure_mcp_get_azure_bestpractices across global-rules.md, assessment.md, code-migration.md (caught by mcp-tool-references test).

Beanstalk → App Service

  • Python 3.11/3.12 — Split into separate rows so version-pinned apps don't get force-upgraded
  • services (sysvinit) — Now maps to WebJobs (continuous) or Functions, with explicit note that Always On is NOT a replacement
  • PgBouncer — Reworded to "Azure Database for PostgreSQL Flexible Server (built-in PgBouncer)" since it's a Postgres feature

Heroku → App Service

  • F1 limits — Removed inaccurate "60 min/day"; clarified F1 uses CPU-minute quota with link to official limits page
  • OIDC permissions — Added required permissions: id-token: write, contents: read block + warning explaining the 403 failure mode
  • NODE_ENV vs WEBSITES_NODE_DEFAULT_VERSION — Reworded to clarify they serve different purposes (runtime behavior vs Node engine version)

App Engine → App Service

  • GOOGLE_CLOUD_PROJECT mapping — Removed the misleading AZURE_SUBSCRIPTION_ID mapping; replaced with explanation that GCP project IDs are runtime, Azure subscriptions are tooling/billing context

Code migration

  • npm ci --omit=dev — Replaced deprecated --production flag (npm 9+)
  • Top-level await — Wrapped MI database example in async function main() so it runs in CommonJS

Global rules

  • Application Insights ingestion — Fixed misleading "managed identity for telemetry ingestion"; clarified ingestion uses APPLICATIONINSIGHTS_CONNECTION_STRING, MI is for management plane
  • Runtime stack link — Switched from Node-specific page to overview-supported-languages

SKILL.md / triggers

  • Description matches scenarios — Merged App Service + Container Apps trigger phrases (under 60-word limit) so no orphan triggers
  • Near-miss negative tests — Added "What is Elastic Beanstalk?", "Set up monitoring for my Fargate cluster", "Write a Dockerfile for App Engine" with note that keyword matching cannot distinguish "Deploy to Heroku" from "Migrate from Heroku" (intent-level routing handled at agent level)

Merge conflict resolved

  • SKILL.md (description, version, rules, scenarios), triggers.test.ts, triggers.test.ts.snap — all resolved keeping App Service + Container Apps scenarios from both branches

Local test run

SKIP_INTEGRATION_TESTS=true npm test -- --testPathPatterns="azure-cloud-migrate|mcp-tool-references" — all 3 test suites PASS:

  • ✅ azure-cloud-migrate/unit.test.ts
  • ✅ azure-cloud-migrate/triggers.test.ts
  • ✅ mcp-tool-references/unit.test.ts

(Pre-existing TS error in agent-runner.ts unrelated to these changes blocks integration tests across many skills.)

Jon Gallant (@jongio) Andrew Westgarth (@apwestgarth) Sai Koumudi Kaluvakolanu (@saikoumudi) — ready for re-review. CC @microsoft/ghcp4a.

Local Jest regenerated the file with the legacy goo.gl URL, but the CI's
newer Jest version validates the snapshot guide URL strictly. Updated to
https://jestjs.io/docs/snapshot-testing per CI's expected value.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@paulyuk

Copy link
Copy Markdown
Member Author

Review thread audit complete ✅

Just finished a full audit of every review thread on this PR. All 16/16 threads are now resolved.

  • 4 active threads → replied with commit reference + permalink to fix, then marked resolved
  • 12 outdated threads (line moved due to subsequent edits) → marked resolved

Thread-by-thread reply trail is in the conversation above; each reply links to the exact line in the current branch where the fix lives.

Jon Gallant (@jongio) Andrew Westgarth (@apwestgarth) — your earlier CHANGES_REQUESTED review on this PR is the only thing blocking merge now. CI ✅ green, merge ✅ clean, threads ✅ all resolved. Could you re-review and either approve or dismiss the stale CHANGES_REQUESTED?

@jongio Jon Gallant (jongio) left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addresses my previous feedback. All 10 items fixed - snapshot header, OIDC permissions block, sysvinit/Always On clarification, PgBouncer attribution, Python version split, npm ci flag, NODE_ENV distinction, runtimes link, near-miss negatives, and trigger/scenario alignment. Clean fixes, no new issues. CI green.

@JasonYeMSFT
JasonYeMSFT (JasonYeMSFT) merged commit 220512a into main May 4, 2026
12 checks passed
@JasonYeMSFT
JasonYeMSFT (JasonYeMSFT) deleted the pass-equity-gap-8 branch May 4, 2026 17:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Gap-8: App Service Migrate (F → A) — Beanstalk + Heroku + App Engine migration guides

7 participants