📋 Shared Instructions: shared-instructions.md — Cross-cutting concerns. Always confirm before deploy.
DeployBuilds and deploys the app in the current directory.
Before any deploy, sync source control first: stage all changes, create a commit, and push to remote.
Workflow
- Memory Bank → 2. Verify Project + Env → 3. Pick Path → 4. Shared Connection Policy Preflight → 5. Build Verification → 6. Git Sync (Add + Commit + Push) → 7. Confirm + Deploy → 8. Update Memory Bank
Step 1: Check Memory Bank
Read memory-bank.md for app slug, GUID, and environment.
Step 2: Verify Project + Env
test -f ms.config.json || { echo "Not in a Microsoft App workspace."; exit 1; }
git rev-parse --is-inside-work-tree >/dev/null 2>&1 || { echo "Not in a git repository."; exit 1; }
BIN=ms
$BIN auth status # must report the expected UPN
If auth is stale or the wrong account, stop and have the user run $BIN auth login.
Step 3: Pick a Deploy Path
Ask the user which path:
| Path | When |
|---|---|
Standard deploy (ms app deploy [--commit <sha>]) |
Default. Use for normal release flow. --commit defaults to git rev-parse HEAD. |
Traced deploy (ms app build + ms app build-status + ms app deploy) |
Use when the user needs explicit build-id tracking before deploy. |
ms app build -c <sha> + ms app build-status -o <build-id> is a third (older) two-step variant for the cloud-built path. The build subcommand is marked deprecated in the CLI source but still works; use it only when the user wants an explicit build-id to track. Otherwise, ms app deploy is the single-step replacement.
Step 4: Shared Connection Policy Preflight
ms app deploy validates that every shared connection reference declares allowedActions,
and fails the deploy when one doesn't. Catch it here — before spending a build and a push on a
deploy that can't succeed.
node -e '
const fs = require("fs");
const refs = JSON.parse(fs.readFileSync("ms.config.json", "utf8")).connectionReferences || {};
const ok = (a) => Array.isArray(a) && a.length > 0 &&
a.every((x) => typeof x === "string" && /\S/.test(x));
let bad = 0;
for (const [name, r] of Object.entries(refs)) {
if (!String(r.sharedConnectionId || "").trim()) continue;
const t = Object.entries(r.dataSets || {}).flatMap(([d, s]) =>
Object.entries(s.dataSources || {}).map(([k, v]) => [d + "/" + k, v]));
if (r.allowedActions !== undefined && !ok(r.allowedActions)) {
bad++;
console.log("INVALID connector-level allowedActions: " + name);
}
if (t.length) {
for (const [p, v] of t) if (!ok(v.allowedActions)) { bad++; console.log("MISSING per-table allowedActions: " + name + " -> " + p); }
} else if (r.allowedActions === undefined) { bad++; console.log("MISSING connector-level allowedActions: " + name); }
}
if (bad) { console.log(bad + " issue(s): fix before deploy"); process.exitCode = 1; } else console.log("OK: all shared references declare allowedActions");
'
This mirrors the CLI's own validation and works in bash and PowerShell alike (Node 22+ is a
project prerequisite; jq is not).
Any MISSING or INVALID line means the deploy will fail. Stop and fix it rather than proceeding:
per-table→ the reference has dataset tables. Every table needs its own non-empty list from"get"/"post"/"patch"/"delete".connector-level→ no dataset tables. Declare Action IDs fromms connector list-actions --connector <api-id> --json.
Infer the least-privilege set from what src/ actually calls, propose it, and confirm with the
user before writing. Do not grant everything to get past the gate, and do not delete
sharedConnectionId. See allowed-actions.md.
OK means every shared reference is covered — continue.
Step 5: Build Verification
npm run build
Failure handling per shared-instructions.md:
- TS6133 (unused import): remove and retry once.
- Other TS errors: report file:line, STOP.
- Module not found:
npm installand retry once. - Other non-zero exit: report verbatim, STOP.
Verify the build output directory (./dist by default, or whatever --build-path resolved to during ms app create) is populated before continuing.
Step 6: Git Sync (Add + Commit + Push)
Deploy must use a pushed commit. Always sync local changes first.
if [ -n "$(git status --porcelain)" ]; then
git add -A
git commit -m "$COMMIT_MESSAGE"
fi
# Ensure the deployment commit exists on remote.
git push -u origin HEAD
DEPLOY_SHA="$(git rev-parse HEAD)"
If there are local changes, ask for a commit message before running git commit. If the user does not provide one, use:
chore: prepare deploy
If git commit reports "nothing to commit", continue to push/verify the current HEAD.
Step 7: Confirm + Deploy
Always ask explicitly before deploy — there is no baseline-deploy exemption in this plugin:
"Ready to deploy
<app-name>to<environment-name>(<env-id>)? This will update the live app."
Wait for explicit user yes.
Standard deploy:
$BIN app deploy --commit "$DEPLOY_SHA"
Traced deploy with build-id traceability:
$BIN app build -c "$DEPLOY_SHA" # returns a build-id
$BIN app build-status -o "$BUILD_ID" # polls until terminal state
$BIN app deploy --commit "$DEPLOY_SHA" # promote the built commit
Capture and surface any URLs / build IDs from the output.
After a successful deploy, offer to open the live app:
$BIN app play # opens the live URL in the browser
$BIN app play --no-browser # print URL only
If the user wants to verify the code before making it live, remind them they can preview without deploying:
$BIN app play --mode preview # opens the latest code on main (no deploy needed)
Step 8: Update Memory Bank
If memory-bank.md exists:
- Update "Last deployed" timestamp.
- Record the deploy path used (standard / traced).
- Capture the commit SHA at deploy time.
If no memory bank exists, create one per memory-bank.md so subsequent skills have context.
Failure Recovery
| Error | Fix |
|---|---|
ms app deploy: 401 / token expired |
$BIN auth login and retry. |
ms app deploy: Invalid ms.config.json for shared connection policy enforcement |
A shared connection reference is missing allowedActions. The listed issues name the reference (and dataset/table) at fault. Declare them per allowed-actions.md and retry. Never remove sharedConnectionId to bypass this. |
ms app deploy: env mismatch |
Active CLI env doesn't match ms.config.json. Either re-create/redeploy against the matching environment, or update ms.config.json. |
git push: no upstream configured |
Run git push -u origin HEAD, then retry deploy. |
git commit: author identity unknown |
Configure Git identity (git config --global user.name / git config --global user.email) and retry commit. |
ms app deploy: commit not in remote |
Ensure Step 6 (Git Sync) completed and push succeeded, then retry. |
ms app build-status: 404 |
Build was submitted to a different cluster than you're querying. Verify the --cloud value matches the cluster used at build time. |
ms app deploy: 403 / not authorized on environment |
The account lacks Maker permissions in the target env. Confirm with $BIN app list --json — if the app doesn't appear, you're not authorized. |