The Atlas MikeOSS.Azure's docs, bound to the code — and to the migration that built it
108 documents
updating-mktplc.md

The runbook for publishing a new version of the Mike managed-application offer to the Azure Marketplace. The order is load-bearing: bump the bare numeric version in Partner Center, optionally sanity-build the image with local docker, then run scripts/release-images.ps1 (4 steps: refuse unpinned FROM tags, az acr build the backend into the public acrmikeoss with a Windows encoding workaround + run-status double-check, mirror PostgREST, docker scout CVE scan) BEFORE scripts/package-marketplace.ps1 (6 steps: compile main.bicep with v2→v1 ARM downconversion, JSON-parse, ARM-TTK, createUiDefinition lint, cert-policy lint, flat zip into dist/). Records that 1.0.2 was rejected on the "Outputs Must Not Contain Secrets" ARM-TTK rule, which is why the whole preflight harness now gates the zip, and includes the automated preflight checklist plus a manual pre-publish checklist of things the harness can't see. Follow this exact order whenever cutting and submitting a new marketplace release; release-images runs before package-marketplace.

Updating the Marketplace Listing

Steps to publish a new version of the Mike managed-application offer to the Azure Marketplace.

Replace 1.0.0 in the commands below with the version you set in Partner Center.

What changed since 1.0.2: the 1.0.2 submission was rejected on the ARM-TTK rule "Outputs Must Not Contain Secrets" (a securestring output that should have stayed inside Key Vault). The whole set of ARM-TTK / cert-policy / Bicep-linter checks Partner Center cares about are now enforced locally as a pre-flight harness — scripts/package-marketplace.ps1 won't produce a zip until they all pass. See docs/dev/marketplace-republish.md for the full background, and the Pre-flight (automated) section below for what's gated. Rejection rule: https://learn.microsoft.com/en-us/azure/azure-resource-manager/templates/test-toolkit#outputs-must-not-contain-secrets.


1. Bump the version in Partner Center

  1. Open the Marketplace offer in Partner Center.
  2. Navigate to Plan Overview → free → Technical Configuration.
  3. Increment the Version field using bare numeric format (e.g. 1.0.21.0.3). No v prefix.
  4. Note the exact version string — you'll pass it to both scripts below.

Before you spend time on a server-side az acr build (which uploads the build context to ACR's build agent), confirm the image builds cleanly locally:

docker build -t mike-backend:local-sanity .

This catches lockfile drift, missing pnpm-workspace.yaml allowlist entries, or Dockerfile/package-manager mismatches before they cost an Azure round-trip.

The Dockerfile uses pnpm (pinned via packageManager: pnpm@11.1.2 in each package.json and activated by corepack enable in each stage). It copies pnpm-lock.yaml, .npmrc, and pnpm-workspace.yaml into each builder, then runs pnpm install --frozen-lockfile. Install scripts are gated by the allowBuilds allowlist in each pnpm-workspace.yaml — if a new dependency needs to run install scripts (e.g. native bindings), add it there or the build will warn and skip.


3. Build and push the backend image to the public ACR

.\scripts\release-images.ps1 -Registry acrmikeoss -Version 1.0.0

Runs before package-marketplace.ps1 so the image tag referenced by createUiDefinition.json exists when a customer deploys.

What it does ([1/4][4/4]):

  1. Dockerfile FROM-tag pinning — refuses :latest and no-tag bases. Cert-policy requires reproducible images.
  2. az acr build — builds the backend container server-side in acrmikeoss (no local Docker required) and tags it backend:<Version>. Wrapped with a Windows-encoding workaround (PYTHONIOENCODING=utf-8 + chcp 65001) and a post-exit double-check against az acr task list-runs so that an encoding crash on the streaming-log path doesn't mask a build that succeeded server-side (see the 2026-05-18 incident on run cb5).
  3. PostgREST mirror — imports the pinned PostgREST tag from Docker Hub. Skip with -SkipPostgrest if the tag was already mirrored on a previous release.
  4. docker scout cves — scans the just-pushed image for Critical CVEs. Auto-skipped if Docker / Scout isn't available locally. Pass -SkipScan to bypass explicitly.

4. Build the marketplace template zip

.\scripts\package-marketplace.ps1 -Version 1.0.0

What it does ([1/6][6/6]):

  1. Compile infra/main.bicepmarketplace/mainTemplate.json (with the v2 → v1 ARM JSON downconversion needed by Partner Center).
  2. JSON parse all three marketplace files.
  3. ARM-TTK (scripts/preflight/arm-ttk.ps1) — full best-practice suite. Bootstraps Azure/arm-ttk on first run.
  4. createUiDefinition lint (scripts/preflight/ui-definition.ps1) — structural shape + cross-reference of every outputs.* expression to a defined control.
  5. Cert-policy lint (scripts/preflight/cert-policy.ps1) — schema URI, broader secret-name heuristic on outputs, nested-deployment scope, viewDefinition staleness.
  6. Zip — substitutes __VERSION__ in createUiDefinition.json and produces a flat zip in dist/ (Partner Center rejects nested archives).

Versions normalise to ARM's n.n.n.n contentVersion automatically (1.0.01.0.0.0; a leading v is also accepted).

Each step has a -SkipXxx escape hatch for local iteration. Do not pass any of them when producing a release artifact.


5. Upload the new package in Partner Center

  1. Still in Plan Overview → free → Technical Configuration.
  2. Remove the existing package file.
  3. Upload the new zip from the dist/ folder.
  4. Save.

6. Review and publish

  1. Click Review and publish on the offer.
  2. Confirm the version, plan, and package details.
  3. Submit to publish.

Pre-flight (automated)

The pipeline below runs unattended when you invoke release-images.ps1 then package-marketplace.ps1. Every box must be green before the zip is produced.

  • [ ] [1/4] Dockerfile FROM tags pinned (no :latest, no implicit tag)
  • [ ] [2/4] az acr build succeeded server-side (run-status double-check covers encoding-stream noise)
  • [ ] [3/4] PostgREST tag mirrored
  • [ ] [4/4] docker scout cves — 0 Critical findings
  • [ ] [1/6] Bicep build clean (stricter linter via bicepconfig.json; promotes outputs-should-not-contain-secrets, use-recent-api-versions, secure-params-in-nested-deploy to error)
  • [ ] [2/6] All JSON files parse
  • [ ] [3/6] ARM-TTK — Passed: N, Failed: 0
  • [ ] [4/6] createUiDefinition Structural OK, Cross-ref OK
  • [ ] [5/6] Cert-policy Schema URI / Output names / Nested-deploy scope / viewDefinition all OK
  • [ ] [6/6] Zip built (dist/mike-marketplace-<Version>.zip)

Pre-publish manual checklist

Things the harness can't see — eyeball before clicking Review and publish:

Repo hygiene

  • [ ] git status clean. Stray Bicep compile artifacts (e.g. infra/main.json) should be deleted — the proper output lives at marketplace/mainTemplate.json and is gitignored.
  • [ ] pnpm install runs clean in backend/ and frontend/ against the committed pnpm-lock.yaml (no pnpm install --no-frozen-lockfile drift).
  • [ ] Image reference in marketplace/createUiDefinition.json still points at acrmikeoss.azurecr.io and uses the __VERSION__ placeholder for the backend tag.

Partner Center listing

  • [ ] Listing logos (small/medium/large/wide/hero) present and current.
  • [ ] Screenshots reflect the current UI.
  • [ ] Support contact, privacy URL, and terms URL are all reachable on https:// only.
  • [ ] "What's new" field populated for this version.
  • [ ] Test-drive / hide-keys / lead-management settings unchanged unless intentional.

Marketplace cert policy (sanity)

  • [ ] No new top-level outputs whose name looks like a secret (password|secret|key|token|connectionString|sasToken|credential). The cert-policy lint covers this but is name-heuristic — a deliberate output named xyzPasswordLength (counting only) would slip past and look bad in a review.
  • [ ] No Microsoft.Resources/deployments resources added that bypass Bicep modules (raw deployments default to outer scope and risk leaking @secure() values).

When the harness flags something

scripts/preflight/*.ps1 errors point at the offending file / output / rule name. For ARM-TTK rule meanings, the canonical list is at https://github.com/Azure/arm-ttk/tree/master/arm-ttk/testcases. For cert-policy, https://learn.microsoft.com/en-us/legal/marketplace/certification-policies#300-azure-applications. For createUiDefinition control reference, https://learn.microsoft.com/en-us/azure/azure-resource-manager/managed-applications/create-uidefinition-overview.