SIGN IN SIGN UP

ELM migrations: pipelines rewiring + cutover review/approve + TSG doc (#1501)

* Add ELM GitHub token auth flow for migration create

- Add --github-token and ELM_GITHUB_TOKEN fallback

- Run GitHub device flow when token is not provided

- Keep target-owner-user-id optional for FF-off compatibility

- Add deviceFlowConfig endpoint fallback support

- Expand migration auth edge-case tests

- Update ELM docs for token/device-flow create behavior

* Improve ELM create conflict error messaging

- Translate generic 409 TF400898 during migration create into a clear active-migration message

- Keep non-conflict errors unchanged

- Add regression tests for conflict mapping and pass-through behavior

* Document 409 conflict error behavior for migration create

- Add troubleshooting entry in migrations.md

- Add pitfall row and dedicated 409 section in elm_migrations_tsg.md

* Harden device-flow response handling and fallback guidance

- Show PAT guidance when both device-flow config endpoints return 404

- Validate interval/expires_in as positive integers and fail with explicit invalid response errors

- Add regression tests for new fallback and validation behavior

* Handle device-flow 401/403 with generic guidance

- Map 401/403 to generic app/service-unavailable message

- Preserve PAT fallback guidance in message

- Add unit test coverage for HTTP 401 handling

* Use strict target repo validation and pre-check issue details

- Enforce target repository format as https://host/org/repo client-side

- Prefer PreCheckIssueType/validation issue messages from response body for CLI errors

- Keep non-TF400898 409 handling unchanged

- Add regression tests for new validation and error-detail extraction

* Mark ELM migrations command group as preview

Add is_preview for migrations command groups and align help/docs with preview and limited-availability messaging.

* ELM migrations: treat 'completed' equivalent to 'succeeded' for terminal status handling

* ELM migrations abandon: return success message instead of empty object

* ELM migrations: UX improvements for pause, cancel, list, abandon and resume error messages

* ELM migrations: add service-endpoint-id parameter for GitHub Enterprise Server migrations

* Add tests for service-endpoint-id parameter

* ELM device flow: copy user code to clipboard when available

* Fix: skip github token resolution when service-endpoint-id is provided

* ELM abandon: add optional remove-read-only flag

* ELM cutover: add review and approve CLI flow

* fix: always resolve github user token regardless of service endpoint

* Initial commit: Add README and hello.js

* Fix ELM style checks

* Add migration workflow guide for operators and repo owners

* Fix R0917: use keyword-only args in create_migration and _update_migration

* Revert "Add migration workflow guide for operators and repo owners"

This reverts commit ed0bb92eb79c66239a8115dbdd21b49e4519ff06.

* Remove ELM_Demo_Script.md

* Revert "Remove ELM_Demo_Script.md"

This reverts commit 16f0c060f98d5b4c654e62116eded32c2681e0f9.

* Remove ELM_Demo_Script.md

* Restore upstream README and remove stray E2E_TEST_REPORT to fix markdown lint

* Remove stray hello.js and docs gitlink accidentally added

* Skip GitHub device flow when --service-endpoint-id is provided

When a service connection is supplied via --service-endpoint-id, GitHub auth is handled server-side by the service endpoint. The CLI must not call /_apis/migrations/deviceFlowConfig, which fails (400) against GHES when the ELM GitHub App is not reachable from the caller's network.

- Gate _resolve_github_user_token on service_endpoint_id

- Reject --service-endpoint-id and --github-token together (ambiguous)

- Update help text to document precedence

- Add tests covering: SE-only, SE+token mutex, SE ignores env token, SE+whitespace token, SE+409 conflict message, SE+all optional fields

* fix(migration): send DateTimeOffset.MinValue sentinel to clear scheduled cutover date

The ELM service silently ignores 'null' for scheduledCutoverDate and only treats DateTimeOffset.MinValue ('0001-01-01T00:00:00+00:00') as the clear sentinel. Previously, 'az devops migrations cutover cancel' returned 200 OK but the server left the field set, leading users to believe the cancel had taken effect when it had not.

Verified empirically via 'az devops invoke' against a live stuck migration: sending the MinValue sentinel cleared scheduledCutoverDate to null in the response, while sending null was a silent no-op.

Updated unit test to assert the sentinel value is sent.

* chore(migration): sanitize internal identifiers from ELM help/docs/tests

Replace specific pool names and aliases with generic placeholders in customer-facing help text, docs, and test fixtures.

* fix(migration): block cutover cancel once stage is Cutover

Clearing scheduledCutoverDate after the worker has entered the Cutover stage puts the migration into a state that requires server-side recovery (the post-cutover drain uses the field as a 'final sync ran' marker). Tracked service-side as Bug 2394803.

Guard the dangerous case client-side until the service-side reject ships, so customers running 'az devops migrations cutover cancel' against an in-progress cutover get a clear error instead of corrupting the migration state.

* Add ELM pipeline rewiring CLI commands

* ELM pipelines: address code-review feedback

- Treat 404 as plain 'not found' (drop feature_not_enabled_message plumbing).
- Repository-mapping DTO now uses camelCase (sourceRepositoryId / targetRepository).
- Remove obsolete 404-feature-disabled test; simplify the remaining 404 test.

* ELM pipelines: camelCase top-level payload keys; fix acknowledge example wording

* ELM pipelines: typed exit-code exceptions, api-version bump, failed-migration hint

* ELM migrations create: add --enable-boards-github-connection opt-in flag

* ELM migrations create: add --enable-auto-discover-pipelines and --pipeline-service-connection-id opt-in flags

Adds two server-contract opt-in flags to `migrations create` for pipeline rewiring:

- `--enable-auto-discover-pipelines` sets configOptions.enableAutoDiscoverPipelines=true so the server walks the source repo and creates clone definitions for every pipeline referencing it at cutover.
- `--pipeline-service-connection-id` pre-attaches the project-scoped GitHub service connection used by all rewired pipelines. Required for full auto-discovery; optional in manual mode (subsequent `pipelines submit` calls only need `--pipeline-ids`).

* ELM pipelines submit: relax mandatory --service-connection-id

Per the design doc (Tfs/.../az-cli-pipelines-design.md), pipelines submit
in manual mode should accept --pipeline-ids alone when a service connection
was already attached via:
  - migrations create --pipeline-service-connection-id, or
  - pipelines update --service-connection-id

Previously the CLI hard-rejected submit without --service-connection-id,
contradicting the documented workflow. The check is removed; the server is
now the source of truth and returns a meaningful 400 when no SC is in
context. --service-connection-id remains accepted and is included in the
payload only when supplied. Help text updated to reflect optional usage.

* fix(elm): allow --service-endpoint-id and user PAT together

Service endpoint (sync credential) and gitHubUserToken (user-identity verification) are independent. Drop the either/or gate and stop forcing github_token=None when SE is provided. The CLI now forwards an explicit --github-token or ELM_GITHUB_TOKEN env var alongside --service-endpoint-id, but does NOT trigger device flow on the SE path so non-interactive flows aren't broken. Required for FF Git.EnterpriseLiveMigration.RequireGitHubUserToken.

* chore: gitignore ELM dev-session scratch helpers and fixtures

* gitignore: exclude docs/ (lives in separate Proxima docs repo)

* ELM CLI: friendlier errors based on server probe results

- create_migration: --pipeline-service-connection-id is dropped with a
  warning (server discards it; SC is a submit-time concept).
- _send_request: translate 400 'EnsureBranchExists' -> 'run submit first'.
- delete_pipeline_rewiring: translate 409 -> 'not in terminal stage'.
- Update test to assert SC is dropped + warning emitted.

* Revert SC-drop from 207bf95: design says CLI must send pipelineServiceConnectionId

Probe showed server bug (field accepted but not pre-attached for later
submit), but design contract requires the field. Keep CLI honoring the
design so customers benefit automatically when the server side is fixed.
The EnsureBranchExists and 409-delete translations from 207bf95 are kept.

* ELM CLI: confirm-prompt on pipelines acknowledge + name fallback in table

- pipelines acknowledge now requires confirmation (use -y to skip) since the server has no revoke API; recovery requires migration abandon+recreate.

- _transform_pipeline_entry_row falls back to yamlFilename when server returns name=null (pending server-side hydration UX fix).

- --acknowledge-ids / --pipeline-ids (acknowledge) help text documents irrevocability.

* Wire cutover --pipelines-verified and migrations list --include-all

approve_cutover now accepts --pipelines-verified and posts pipelinesVerified:true; accept-failures is optional with a clear error when neither flag is given. list_migrations wires --include-all (includeInactiveMigrations) with --include-inactive kept as deprecated alias. Removes the dead 'pipelines acknowledge' command in favor of the cutover-level verification flow. Adds/updates unit tests (110 passing).

* Enumerate supported --skip-validation policy names in migrations create help

* Fix lint: group knack imports, signature indentation, suppress false-positive membership warning

* Remove dead pipeline acknowledge surface (acknowledge moves to cutover --pipelines-verified)

* docs: remove stray 1.0.3 snapshot dir; refresh TSG wheel version to 1.0.5

* scope: limit PR to ELM changes (restore .gitignore and stray 1.0.3 snapshot to upstream)

* docs(elm tsg): install latest CLI + extension instead of wheel file

* docs(elm tsg): document cutover review/approve, pipelines rewiring, new create flags, include-all; fix stages/statuses

* fix(elm): treat readyForCutover/reviewForCutover as active stages

Complete _ACTIVE_STAGES so the stage-only fallback in _is_migration_active recognizes every in-flight stage, not just a subset. readyForCutover and reviewForCutover are cutover-gate stages where the migration is still active; terminal detection remains status-based and is unaffected. Adds a unit test covering all in-progress stages.

* docs(elm): clarify migrations abandon does not delete the record

* fix(elm): block migrations create auto-discover without pipeline service connection

* docs(elm): remove internal tracking reference from cancel_cutover comment

---------

Co-authored-by: Bhuvan Shah <bhuvanshah@microsoft.com>
Co-authored-by: Demo User <demo@microsoft.com>
B
bhuvanshahMSFT committed
afbde986cef3fb686dc5b5c7adb805b2818781af
Parent: 20205e6
Committed by GitHub <noreply@github.com> on 6/15/2026, 11:20:16 AM