Skip to content

chore: cli 5.6.0 - #176

Merged
finalerock44 merged 10 commits into
productionfrom
promote/cli-5.6.0
Sep 17, 2026
Merged

finalerock44 merged 10 commits into
productionfrom
promote/cli-5.6.0

Conversation

@finalerock44

Copy link
Copy Markdown
Contributor

What & why

Type of change

  • fix — bug fix
  • feat — new feature
  • perf — performance improvement
  • refactor — code change that's neither a fix nor a feature
  • docs — documentation only
  • chore / ci / build / test — tooling, no user-facing change
  • Breaking change (title has ! or PR notes a BREAKING CHANGE:)

Checklist

  • PR title follows the Conventional Commits format (see comment above)
  • pnpm lint passes
  • pnpm typecheck passes
  • pnpm build passes
  • I have not bumped the version or edited CHANGELOG.md (release-please handles this)
  • I have signed the CLA (the bot will prompt on first contribution)
  • Docs / README.md / STYLE_GUIDE.md updated if behaviour or output changed

How to test

finalerock44 and others added 10 commits September 17, 2026 13:28
…164)

Sends the opt-in flag with the submission; the API derives the CI context
(repo + branch/PR + check name) from the run metadata and cancels the
previous run's still-queued tests.

The superseded run's own CLI, still polling, now exits 0 instead of failing
the build: any result carrying `superseded_by:` settles the verdict as
SUPERSEDED, even alongside a test that had already failed, because this run
no longer speaks for the commit. The failure is still printed and still in
tests[] under --json, where SUPERSEDED is a third value of an existing
documented field.

Sent as its own field rather than inside `config`, which is stamped onto
every result row and shipped to the runner — this is a submission directive,
not run configuration. Not exposed on the MCP tool: it has no CI metadata to
derive a context from, so the flag could only ever be a no-op there.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: dcd-cli-release-please[bot] <296541543+dcd-cli-release-please[bot]@users.noreply.github.com>
The link was built from this run's console URL with only the upload id
swapped, so it kept `&result=<id>` — a result of the run that was
superseded, not of the one that replaced it. Opening it deep-linked the
newer upload to a test it does not contain.

Found running the feature end to end on dev.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
* fix(cloud): drop the stale result id from the superseded-by link

The link was built from this run's console URL with only the upload id
swapped, so it kept `&result=<id>` — a result of the run that was
superseded, not of the one that replaced it. Opening it deep-linked the
newer upload to a test it does not contain.

Found running the feature end to end on dev.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* chore(dev): release 5.5.0-beta.6

* chore: ReleaseAs 5.6.0-beta.1

* ReleaseAs 5.6.0-beta.1

* ReleaseAs 5.6.0-beta.1

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: dcd-cli-release-please[bot] <296541543+dcd-cli-release-please[bot]@users.noreply.github.com>
ReleaseAs: 5.6.0-beta.1
…170)

#168 merged release-please's own `chore(dev): release 5.5.0-beta.6` as an
ordinary PR, so no v5.5.0-beta.6 tag or release was created. The manifest
then pointed at an untagged version, release-please lost its anchor,
rescanned the whole history and picked up the stale version pin from #137
— hence #167.

Roll manifest, package.json and CHANGELOG-beta.md back to the last real
release (v5.5.0-beta.5) and pin the next beta with a real footer.

Release-As: 5.6.0-beta.1
Co-authored-by: dcd-cli-release-please[bot] <296541543+dcd-cli-release-please[bot]@users.noreply.github.com>
* ci: publish to npm via trusted publishing

npm already has this repo + npm-publish.yml registered as the trusted
publisher, but nothing in CI asked for an OIDC claim, so publishes still
used NPM_TOKEN — which expired 90 days after it was last set and failed
5.6.0-beta.1 with a 404 on PUT.

Three things were missing, not one:

- `id-token: write` on the publish job, and again on the two jobs that call
  it: a reusable workflow cannot hold a permission its caller lacks, and
  release-please.yml grants only contents/pull-requests.
- npm >= 11.5.1 to do the exchange. Node 22 ships npm 10.9, so the publish
  job moves to Node 24 (npm 11.19).
- `npm publish` rather than `pnpm publish`: pnpm only gained the exchange in
  v11 and this repo pins 10.17. pnpm still installs and builds.

NPM_TOKEN is now unused and can be deleted once a release has gone out
this way.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix: point repository.url at the source repo

It was https://devicecloud.dev — the marketing site, not a git remote.

Trusted publishing auto-enables provenance (npm's oidc.js sets it whenever
the provenance config is at its default, the OIDC claim says the repo is
public and the package is public — all true here), and the registry checks
the generated provenance, which names GITHUB_SERVER_URL/GITHUB_REPOSITORY,
against this field. A mismatch is a 422 at publish time; a dry run never
sends provenance, so it would not have shown up until the real upload.

homepage keeps pointing at devicecloud.dev.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
* chore: seed 5.0.0 production release

History was squashed into the initial commit of this repo, so release-please
has no user-facing commits to build a changelog from. This forces the first
stable release of the 5.x line off the current dev tip and resets the prod
manifest baseline to the prior npm `latest` (4.4.9) so Release-As produces a
clean forward 5.0.0 instead of a no-op.

Release-As: 5.0.0

* chore: promote v5 (#56)

* fix(upgrade): compare prerelease versions per SemVer

`isOutdated` stripped the prerelease suffix before comparing, so
beta-to-beta bumps like 5.0.0-beta.0 -> 5.0.0-beta.1 both collapsed to
[5,0,0], compared equal, and `dcd upgrade` reported "Already on the
latest version". Same nudge in cloud.ts was affected.

Replace the naive major.minor.patch compare with a SemVer 2.0.0
`compareSemver` helper that handles prerelease precedence (a prerelease
ranks below its final release; identifiers compare dot-by-dot, numeric
numerically and below alphanumeric). Add unit coverage for the
regression and related cases.

* fix: suppress refresh countdown in quiet mode

When --quiet is passed (geared at CI), the live results footer no longer
renders the "next refresh in Ns" / "refreshing…" countdown. The realtime
connection indicator is still shown.

* feat(cloud): warn on deprecated iOS 16 (removal 2026-08-23)

* feat(cloud): drop legacy Maestro removed-versions block; soft-warn on deprecated 1.39.5/1.41.0

* fix(installer): make beta opt-in, add stable/beta channels

The install scripts resolved the version from /latest.json, which (until a
stable release exists) synthesized the newest prerelease — so the default
`curl … | sh` was silently installing betas.

Pair the proxy's new channel support (get.devicecloud.dev now serves stable
on /latest.json and prereleases on ?channel=beta) with explicit opt-ins:

- DCD_BETA — request the beta channel (latest prerelease).
- DCD_VERSION — already pins an exact version; documented for rollback.
- Default (no opt-in) installs the latest *stable* only. When no stable
  release exists yet, the installer errors with guidance pointing at
  DCD_BETA / DCD_VERSION instead of falling back to a beta.

The manifest fetch is separated from parsing so a transient network/proxy
failure (curl -f non-zero) is reported differently from a channel that has
no release yet (HTTP 200 with "version": null).

* chore: add open-source contribution governance

Scaffolding to open dcd-cli to external contributors:

- LICENSE (MIT), CONTRIBUTING, CODE_OF_CONDUCT, SECURITY, CLA templates
- CODEOWNERS, PR template, issue forms + config, dependabot, .editorconfig
- pr-title-lint workflow: Conventional Commits on PR title (squash-merge model,
  types kept in sync with release-please changelog-sections)
- cla workflow: CLA Assistant Lite
- release-please: use a GitHub App token (falls back to GITHUB_TOKEN until the
  App secrets exist) so Release PRs trigger required checks under branch protection
- cli-ci: also run on production so the dev->production promotion PR is gated

* chore: drop CODEOWNERS

Low value for a small maintainer team where anyone can review anything; the
branch ruleset's approval requirement covers review without it.

* fix(ci): keep dependabot and fork PRs green (#46)

* fix(ci): keep dependabot and fork PRs green

Dependabot/fork PRs run without repo secrets, so three jobs failed on them:

- lint-and-test: HAS_PRIVATE_ACCESS was true for dependabot (same-repo head),
  so it tried to clone the private mock-api with an empty DCD_SSH_DEPLOY_KEY.
  Now excludes dependabot[bot], same as forks (skips mock-api + integration).
- claude-code-review: skips dependabot/fork PRs (no CLAUDE_CODE_OAUTH_TOKEN).
- cla: skips its action step until PERSONAL_ACCESS_TOKEN is configured so the
  check is green instead of 'Branch cla-signatures not found'; also fixes two
  invalid input names (custom-*-prompt -> custom-*-prcomment).

* ci: group all github-actions bumps into one weekly PR

Wildcard pattern so major action bumps join the group too, instead of one
PR per action.

* ci: power CLA via the shared automation GitHub App (#49)

* ci: power CLA via the shared automation GitHub App

Mint the CLA token from the same GitHub App release-please uses, instead of a
personal PAT (no expiry, signature commits show as the bot). Rename the App
secrets RELEASE_PLEASE_APP_* -> BOT_APP_* since one App now serves both
workflows. CLA self-skips until BOT_APP_ID is set.

Carries only the app-token delta — the dependabot/fork CI fixes and actions
grouping already landed on dev via #46.

* ci: allowlist internal maintainers (riglar, finalerock44) in CLA

* docs: set legal entity to Moropo Ltd t/a DeviceCloud (#50)

Fill the CLA party placeholder and the LICENSE/README copyright holder with the
registered entity. CLA still pending legal review.

* ci: bump the actions group across 1 directory with 6 updates (#47)

Bumps the actions group with 6 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [actions/create-github-app-token](https://github.com/actions/create-github-app-token) | `2` | `3` |
| [actions/checkout](https://github.com/actions/checkout) | `4` | `7` |
| [pnpm/action-setup](https://github.com/pnpm/action-setup) | `4` | `6` |
| [actions/setup-node](https://github.com/actions/setup-node) | `5` | `6` |
| [amannn/action-semantic-pull-request](https://github.com/amannn/action-semantic-pull-request) | `5` | `6` |
| [googleapis/release-please-action](https://github.com/googleapis/release-please-action) | `4` | `5` |



Updates `actions/create-github-app-token` from 2 to 3
- [Release notes](https://github.com/actions/create-github-app-token/releases)
- [Changelog](https://github.com/actions/create-github-app-token/blob/main/CHANGELOG.md)
- [Commits](actions/create-github-app-token@v2...v3)

Updates `actions/checkout` from 4 to 7
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](actions/checkout@v4...v7)

Updates `pnpm/action-setup` from 4 to 6
- [Release notes](https://github.com/pnpm/action-setup/releases)
- [Commits](pnpm/action-setup@v4...v6)

Updates `actions/setup-node` from 5 to 6
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](actions/setup-node@v5...v6)

Updates `amannn/action-semantic-pull-request` from 5 to 6
- [Release notes](https://github.com/amannn/action-semantic-pull-request/releases)
- [Changelog](https://github.com/amannn/action-semantic-pull-request/blob/main/CHANGELOG.md)
- [Commits](amannn/action-semantic-pull-request@v5...v6)

Updates `googleapis/release-please-action` from 4 to 5
- [Release notes](https://github.com/googleapis/release-please-action/releases)
- [Changelog](https://github.com/googleapis/release-please-action/blob/main/CHANGELOG.md)
- [Commits](googleapis/release-please-action@v4...v5)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: actions/create-github-app-token
  dependency-version: '3'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: actions/setup-node
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: amannn/action-semantic-pull-request
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: googleapis/release-please-action
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: pnpm/action-setup
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: finalerock44 <77282157+finalerock44@users.noreply.github.com>

* fix: v5 release blockers — installer, binary version, repeated flags,… (#51)

fix: v5 release blockers — installer, binary version, repeated flags, upgrade, CI output

- install.ps1: fix PS 5.1 parse error (`$asset:` -> `${asset}`) that made
  `irm | iex` a no-op on stock Windows; decode the octet-stream SHA256SUMS
  (Byte[] under -UseBasicParsing) to text before splitting.
- build/version: stamp the version into the bun-compiled binary via
  `bun --define __DCD_CLI_VERSION__` (the compiled binary can't read
  package.json), so `dcd --version` no longer reports 0.0.0. npm/tsx path
  still falls back to reading package.json. Adds src/global.d.ts.
- cloud: collect repeated `-e/--env`, `-m/--metadata`, `--include-tags`,
  `--exclude-tags`, `--exclude-flows` from rawArgs (citty/parseArgs kept only
  the last occurrence, silently dropping earlier values); echo the collected
  values too.
- upgrade: query the beta channel for prerelease installs and distinguish
  "no newer release on this channel" from a real network failure, replacing
  the misleading "Could not reach the update manifest" error during the beta.
- progress/polling: make the realtime status indicator TTY-aware — in
  non-interactive/CI output, print one line per state change instead of
  flooding logs with a per-frame spinner (not suppressed by --quiet/--json-file).
- methods: downgrade primary-Backblaze-upload failure warnings to debug-only;
  the Supabase fallback recovers and validateUploadResults raises the only
  user-facing error (when every strategy fails).
- list/status: build console links from the env the CLI targets
  (resolveFrontendUrl) instead of the API's hardcoded-prod consoleUrl.
- cloud: validate a local --app-file exists during --dry-run.

* chore(dev): release 5.0.0-beta.2 (#36)

Co-authored-by: dcd-cli-release-please[bot] <296541543+dcd-cli-release-please[bot]@users.noreply.github.com>

* fix: stop CLA locking release PRs (breaks release pipeline) (#52)

The CLA Assistant action defaults lock-pullrequest-aftermerge=true, so merging
a release-please PR locked it; release-please then failed trying to comment on
the locked PR, killing the Release job before npm publish + binary upload ran
(seen on v5.0.0-beta.2). Set lock-pullrequest-aftermerge=false.

Also skip release-please PRs in claude-code-review (version bumps — nothing to
review, and it must never block a release).

* feat(live): add a beta warning to `dcd live start` (#54)

Prints a beta notice (billed at $0.03/min, contact support to enroll) before
starting a session. The API's new enrollment gate returns a 403 whose
"contact support" message the CLI already surfaces verbatim on a non-enrolled
org.

* chore(dev): release 5.0.0-beta.3 (#53)

Co-authored-by: dcd-cli-release-please[bot] <296541543+dcd-cli-release-please[bot]@users.noreply.github.com>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Tom Riglar <tom.riglar@moropo.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: dcd-cli-release-please[bot] <296541543+dcd-cli-release-please[bot]@users.noreply.github.com>

* chore(production): release 5.0.0 (#33)

Co-authored-by: dcd-cli-release-please[bot] <296541543+dcd-cli-release-please[bot]@users.noreply.github.com>

* chore: release 5.1.0 (#65)

Promote the DB-driven notices feature (CLI render via ui, console banner, API block enforcement, CI identity forwarding) from dev to stable.

Release-As: 5.1.0

* chore(production): release 5.1.0 (#68)

Co-authored-by: dcd-cli-release-please[bot] <296541543+dcd-cli-release-please[bot]@users.noreply.github.com>

* chore: release 5.1.1 (#73)

Promote from dev to stable:

* fix: recover cleanly when the stored session is dead (#72) — `dcd login`
  now mints a dedicated Supabase session for the CLI rather than reusing the
  browser's refresh-token family, and a dead stored session recovers instead
  of hard-failing.
* deps: bump the minor-and-patch group (9 updates) (#71) and
  eslint-plugin-unicorn 68 -> 69 (#70).

Carries only the source delta — package.json version, CHANGELOG.md and the
release-please manifests stay as release-please left them on production.

Release-As: 5.1.1

* chore: release 5.2.0 (#83)

Promote from dev to stable:

* feat(cloud): upload-level device matrix (#1105) — one `dcd cloud` upload
  carries N device configs via repeatable `--ios-device-matrix <device>:<version>`
  / `--android-device-matrix <device>:<apiLevel>[:play]`, fanning out into one
  result row per (flow × config). Each flag names exactly one validated cell;
  there is no cross-product. Sequential flows form N independent depends_on
  chains, one per device. Adds a pre-submit cell-count + cost preview and a
  `device` object on each `--json` `tests[]` entry.
* fix(cloud): refuse a device matrix on an API that cannot honour it — an older
  API silently strips the unknown field and runs one device, exiting 0; the CLI
  now fails loudly instead of under-testing in silence.
* test: run the integration suite via execFile argv rather than a shell,
  clearing the whole js/shell-command-injection-from-environment class.

REQUIRES the dcd API carrying #1105 to be on production first. Without it the
matrix flags cannot be honoured (the CLI refuses, by design).

Carries only the source delta — package.json version, CHANGELOG.md and the
release-please manifests stay as release-please left them on production.

Release-As: 5.2.0

* chore(production): release 5.2.0 (#74)

Co-authored-by: dcd-cli-release-please[bot] <296541543+dcd-cli-release-please[bot]@users.noreply.github.com>

* chore: release 5.3.0 (#108)

Promote from dev to stable:

* feat: client-side envelope encryption of app binaries, flow zips and env vars
  (#94, #101) — opt-in via `--encrypt` / `DCD_ENCRYPT_BINARIES=1` and off by
  default, so uploads stay byte-identical unless asked for. Per-upload DEK,
  chunked AES-256-GCM container, X25519 sealed-box DEK wrap; encrypted binaries
  dedup on the plaintext hash so re-uploads still hit the cache.
* feat(artifacts): prefer server-assembled bundle delivery for downloads (#93) —
  falls back to the inline endpoint on 501, so it degrades cleanly against an
  API that has not shipped bundles.
* feat(device): add Android API level 37 (Android 17) (#107) — the flag enum
  accepts 37, but the device/API-level pair is validated against the
  compatibility matrix the *target* API serves, and production still tops out at
  36, so 37 is refused client-side until the platform gate flips.
* refactor(cloud): remove the enterprise-only --mitmHost / --mitmPath flags
  (#102). The submitted config payload for runs that never passed them is
  byte-identical.
* fix(deps) / deps: clear every outstanding pnpm audit advisory (#89, #92, #95,
  #100, #106), bump chalk 5 -> 6, and regenerate the schema types from the
  current API swagger (#105).

No platform prerequisite this time: the envelope decrypt half (dcd api +
simulators) is already on production with both env KEK public keys pinned,
bundle delivery has a 501 fallback, and API 37 is gated server-side.

Carries only the source delta — package.json version, CHANGELOG.md and the
release-please manifests stay as release-please left them on production.

Release-As: 5.3.0

* chore(production): release 5.3.0 (#109)

Co-authored-by: dcd-cli-release-please[bot] <296541543+dcd-cli-release-please[bot]@users.noreply.github.com>

* chore: release 5.3.1 (#119)

Promote from dev to stable:

* fix(cloud): exclude config-shaped files from flow discovery (#114, closes
  dcd-cli#99) — a `config.yaml` sitting in a flows folder was picked up as a
  flow and blew up `processDependencies` with "Expected an array of steps".
  Detection is by shape, not filename, so several named configs can coexist in
  one folder. A flow merely *missing* its `---` separator still errors loudly
  rather than being silently dropped.
* fix(cloud): reject malformed executionOrder instead of silently running in
  parallel (#117, closes dcd-cli#110) — the config was `yaml.load`ed and
  straight-cast, so an `executionOrder` in the wrong shape was ignored and every
  flow ran in parallel. A zod schema (`src/services/workspace-config.schema.ts`)
  is now the single source of truth, with `IWorkspaceConfig` inferred from it so
  the compile-time and runtime views cannot drift.
* deps: bump the minor-and-patch group with 5 updates (#112), plus
  eslint-plugin-unicorn 72 -> 73 and pnpm/action-setup 6.0.9 -> 6.0.10.

Behaviour changes users will notice:

* A malformed `executionOrder` is now a hard error with a targeted message
  showing found-vs-expected. Anyone whose config was mis-shaped has been running
  flows in parallel without knowing; after this they get a clear failure instead.
  That is the point of the fix, but it is the one change that can turn a
  previously-green pipeline red.
* Unrecognised top-level config keys emit a warning (with a did-you-mean for
  near-misses). Keys are preserved, not stripped — the config is forwarded to
  the API as `fields.workspaceConfig`, so stripping would silently alter the
  payload.
* Config warnings go to stderr, so `--json` stdout stays parseable and the MCP
  server's JSON-RPC stdout channel stays clean.

No platform prerequisite: both fixes are client-side (flow discovery and config
validation). The submitted payload for an already-valid config is unchanged.

Carries only the source delta — package.json version, CHANGELOG.md and the
release-please manifests stay as release-please left them on production.

Release-As: 5.3.1

* chore: promote the grouped deps bump into 5.3.1 (#123)

* chore: promote the grouped deps bump into 5.3.1

Promote from dev to stable, picking up the one change that landed after the
5.3.1 promotion (#119) and so missed the pending release PR (#120):

* deps: bump the minor-and-patch group with 6 updates (#121) —
  @supabase/supabase-js 2.112.2 -> 2.112.3, js-yaml 5.2.3 -> 5.3.0,
  @types/node 26.1.2 -> 26.2.0, eslint 10.8.0 -> 10.8.1, tsx 4.23.11 ->
  4.23.12, typescript-eslint 8.66.0 -> 8.67.0.

Carries only `pnpm-lock.yaml`. Dependabot left `package.json` untouched — every
range already admitted the new versions — so this changes nothing for npm
consumers, who resolve from those ranges. It matters only for the bun-compiled
standalone binaries, which bake in the locked versions.

`Release-As: 5.3.1` keeps the pending release PR (#120) on 5.3.1 rather than
rolling it to 5.3.2. Release-please regenerates the 5.3.1 section from this
commit's bullet alongside #119's three, so the changelog ends up carrying all
four entries.

Verified locally, because CI cannot check this branch: `pnpm install
--frozen-lockfile` (the lockfile agrees with production's package.json), `pnpm
lint` (0 errors, the same 32 pre-existing warnings — the eslint 10.8.1 and
typescript-eslint 8.67.0 bumps add no findings), `pnpm typecheck`, `pnpm build`,
and `pnpm audit --audit-level moderate` (no known vulnerabilities). The
integration tests did NOT run: dcd#1036 deleted `mock-api/`, which is also what
fails CI's `lint-and-test`, at a step that runs before the linter.

Release-As: 5.3.1

* ci: stop reaching into the private dcd repo for the mock-api

`lint-and-test` has failed on every same-repo PR since dcd#1036 deleted
`mock-api/` from the private devicecloud-dev/dcd repo this morning. CI checked
that directory out over an SSH deploy key and ran `pnpm install` in it; the
sparse-checkout now matches nothing, so the job dies at that step — before the
linter — and takes #120, #122 and #123 down with it.

Rather than re-point at a mock, this removes the linkage. dcd-cli is PUBLIC and
was holding `DCD_SSH_DEPLOY_KEY`, a credential granting read access to the
private repo, and pulling the API's `swagger.json` onto the runner on every
same-repo PR. Deleting the checkout drops both.

* The `Checkout dcd (mock-api)` and `Install Mock API dependencies` steps are
  gone, along with the `HAS_PRIVATE_ACCESS` gate that existed only to keep them
  off fork and Dependabot PRs. Every PR now takes the same path, so forks stop
  being second-class.
* CI runs `pnpm test:unit` — a new script that is the existing runner with
  `--unit`. `test/unit/*` is pure and needs no backend, so unit coverage is kept
  rather than dropped along with the integration suite.
* `scripts/test-runner.mjs` no longer defaults `MOCK_API_DIR` to
  `../../dcd/mock-api`. With no mock available it degrades to the unit suite and
  says so, instead of the bare ENOENT it throws today. Set `MOCK_API_DIR` and
  the integration specs run exactly as before.

`DCD_SSH_DEPLOY_KEY` can now be deleted from the repo's secrets — nothing reads
it. That is a separate manual step, not something this commit can do.

Two things are genuinely lost, both worth stating plainly rather than
discovering later:

* `test/integration/*` no longer runs anywhere automatically.
* With it goes the CLI<->swagger contract-drift check. Drift used to surface as
  a Prism 422 — that is how the `googlePlay` multipart break and the `tempPath`
  missing-example break were both caught. Nothing replaces it yet.

Verified locally: `pnpm test:unit` and a bare `pnpm test` both run the unit
suite only and print the notice; 81 pass and the 7 `flow-paths` failures are
Windows-only, asserting POSIX paths against win32 `path`. The same specs ran
green on ubuntu in the last full CI run (job 94750122384, 2026-08-14), which is
the platform CI uses. `pnpm lint`, `pnpm typecheck`, `pnpm build` and `pnpm
audit --audit-level moderate` are all clean.

* chore: promote the #124 docs into 5.3.1 (#125)

Promote from dev to stable, carrying the documentation half of #124 that the
5.3.1 promotions dropped.

`ci: stop reaching into the private dcd repo for the mock-api` (#124) touched six
files on dev. The promote PR (#123) carried four of them — `cli-ci.yml`,
`scripts/test-runner.mjs`, the `test:unit` script in `package.json`, and eight of
the ten changed `CLAUDE.md` lines — and dropped `CONTRIBUTING.md` and `README.md`
entirely. Production therefore ships the new CI shape while its docs still
describe the old one:

* `CONTRIBUTING.md` told contributors `pnpm test` boots a mock API, and that
  integration tests are "automatically skipped" on fork PRs only. Neither is
  true: CI runs no integration tests on any PR, and there is no default mock. It
  also omitted `pnpm test:unit` from the pre-push checklist, though it is now a
  required check.
* `README.md`'s dev-scripts block still showed
  `pnpm test  # build + boot mock API + integration/unit tests`.
* `CLAUDE.md`'s Contributing section still described the `DCD_SSH_DEPLOY_KEY`
  mock-api checkout, which no longer exists.

`README.md` is the one with reach beyond this repo: npm always includes it in the
tarball regardless of the `files` field, so the stale snippet would render on the
npmjs.com page for 5.3.1.

Docs only — no source, workflow, script or lockfile change. The three files are
now byte-identical to `dev`, leaving release plumbing (both manifests,
`CHANGELOG.md`, `package.json` version) as the only remaining divergence, which
is release-please's to own.

`Release-As: 5.3.1` keeps the pending release PR (#120) on 5.3.1 rather than
rolling it to 5.3.2.

Release-As: 5.3.1

* chore(production): release 5.3.1 (#120)

Co-authored-by: dcd-cli-release-please[bot] <296541543+dcd-cli-release-please[bot]@users.noreply.github.com>

* chore: release 5.4.0 (#128)

Promote from dev to stable:

* feat: remove iOS 16 (#126) — the platform removed iOS 16 on 2026-08-24, so
  `--ios-version 16` now fails against the API regardless of CLI version.
  Dropping '16' from `EiOSVersions` moves that rejection client-side with a
  better message ("Expected one of: 18, 17, 26") instead of a round trip to a
  400. `--help` follows automatically, since the option list is derived from
  the enum. Defaults were already iphone-14 / 17 and are unaffected — iPhone 14
  keeps iOS 17 and 18.

`src/types/generated/schema.types.ts` is regenerated against the post-removal
API swagger; alongside narrowing `iOSVersion` it picks up the API-side drift
that had accumulated since the artifact was last built on 2026-08-06.

No platform prerequisite in the other direction: the API is already serving the
reduced matrix, verified end-to-end on dev (a 5.3.1 CLI targeting iOS 16 is
refused by the fetched compatibility data, and a per-flow override reaches the
server-side gate).

`Release-As: 5.4.0` because the promotion commit is a `chore:` and would
otherwise cut no release at all. It is 5.4.0 rather than 6.0.0 deliberately:
#126 carried a `!` in its PR title, which is what put the beta line on a
6.0.0-beta.2 release PR before #127 re-pinned it. Removing a version the
platform no longer serves takes away nothing that still worked, so it is not a
major. The `!` does not reach production anyway — promotions are squash-merged,
so it lives only in dev's history.

Carries only the source delta — package.json version, CHANGELOG.md and the
release-please manifests stay as release-please left them on production.

Release-As: 5.4.0

* chore(production): release 5.4.0 (#129)

Co-authored-by: dcd-cli-release-please[bot] <296541543+dcd-cli-release-please[bot]@users.noreply.github.com>

* chore: release 5.4.1 (#145)

Promote from dev to stable: iOS 27 in the `--ios-version` enum (#131/#134 —
the iPhone 17 devices were already dropped), bplist-parser 0.5 named exports
(#143), the CLA action fork (#135/#136) and the grouped dependency bumps.

`Release-As: 5.4.1` because the promotion commit is a `chore:` and would
otherwise cut no release at all. 5.4.1 rather than the 5.5.0 the iOS 27 `feat:`
would roll, so the stable line matches the beta line already published as
5.4.1-beta.1.

Carries only the source delta — package.json version, CHANGELOG.md and the
release-please manifests stay as release-please left them on production.

Release-As: 5.4.1

* chore: promote the notices targeting change into 5.4.1

Second promotion commit for 5.4.1: #145 carried dev as of this morning, and the
notices change (#147) landed on dev after it. Source delta only; package.json
version, CHANGELOG.md and the release-please manifests stay as production has
them so release-please re-renders #146 with this entry added.

* feat(notices): expose platform, device and Maestro version to notice targeting; include notices in --json output (#147)

Release-As: 5.4.1

* chore(production): release 5.4.1

* chore: pin the 5.5.0 promotion

package.json tracks production's stable line from here; release-please
bumps it to 5.5.0 when the Release PR lands.

Release-As: 5.5.0

* chore(production): release 5.5.0

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Tom Riglar <tom.riglar@moropo.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: dcd-cli-release-please[bot] <296541543+dcd-cli-release-please[bot]@users.noreply.github.com>
Merge branch off production rather than promoting dev directly: dev's
ruleset squashes, and a squashed back-merge leaves the histories unlinked,
which is what kept #173 conflicting.

Tree is dev's. Only package.json's version collided — took dev's; the stable
manifest stays production's 5.5.0. No Release-As footer: the --cancel-previous
feat since v5.5.0 computes 5.6.0 on its own.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@finalerock44 finalerock44 self-assigned this Sep 17, 2026
@claude

claude Bot commented Sep 17, 2026

Copy link
Copy Markdown

Code review

No issues found. Checked for bugs and CLAUDE.md compliance.

@finalerock44
finalerock44 merged commit 147cd8c into production Sep 17, 2026
5 checks passed
@finalerock44
finalerock44 deleted the promote/cli-5.6.0 branch September 17, 2026 16:52
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.

1 participant