fix(setup): keep local authoring independent of publishing - #293
Conversation
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: eff50b3c-427f-453a-8f4a-49848ad02602
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: eff50b3c-427f-453a-8f4a-49848ad02602
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: eff50b3c-427f-453a-8f4a-49848ad02602
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: eff50b3c-427f-453a-8f4a-49848ad02602
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: eff50b3c-427f-453a-8f4a-49848ad02602
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: eff50b3c-427f-453a-8f4a-49848ad02602
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: eff50b3c-427f-453a-8f4a-49848ad02602
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: eff50b3c-427f-453a-8f4a-49848ad02602
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: eff50b3c-427f-453a-8f4a-49848ad02602
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: eff50b3c-427f-453a-8f4a-49848ad02602
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: eff50b3c-427f-453a-8f4a-49848ad02602
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: eff50b3c-427f-453a-8f4a-49848ad02602
Use the Copilot Studio client identity, the platform-reference ALM API version, and route-appropriate headers and multipart metadata. Accept the live publish response casing and cover the wire contract in focused tests. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: eff50b3c-427f-453a-8f4a-49848ad02602
Gaps found1. Native ALM API version applied inconsistently —
2. Schema mismatch is detected after canonical state is written — The prefetch calls 3.
4. It now raises 5. Stale fixtures / lost coverage (minor)
CC: nkemms |
|
Thanks for the detailed pass. I traced each item against the platform HTTP reference, live captures, and the current attach state model.
|
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: eff50b3c-427f-453a-8f4a-49848ad02602
Code Review — PR #293Mode: Lightweight (diff-based) review, cross-checked against full PR-branch file snapshots ( I largely arrive at the same conclusions as Apurva Banka (@apurvabanka)'s review above, and confirmed each of their points independently against the actual source (line numbers below refer to the PR branch). Two of these are BLOCKER-level, not just observations. [BLOCKER] 1. Canonical setup state can be persisted with an unvalidated/wrong schema name before the real validation runs
prefetched_changeset: dict[str, Any] | None = None
if not connection["agent"]["schemaName"]:
prefetched_changeset = client.fetch_components(normalized_agent_id)
connection["agent"]["schemaName"] = _validate_changeset_identity(
prefetched_changeset,
normalized_agent_id,
) # <-- no expected_schema_name passed here
canonical_state, existing_setup = _validate_setup_target(kit_root, connection)
...
if existing_setup is None or progress_recorded:
_record_canonical_setup_progress(kit_root, connection, canonical_state, existing_setup) # <-- writes .local/setup/config.json
progress_recorded = True
...
_validate_changeset_identity(
changeset,
normalized_agent_id,
expected_schema_name=expected_schema_name or schema_name, # <-- the real check, can raise here
)
Test coverage confirms this isn't just theoretical: Fix: pass [BLOCKER] 2.
|
Apurva Banka (apurvabanka)
left a comment
There was a problem hiding this comment.
Thanks for the thorough replies — I went back and verified each one against the code rather than just the diff.
Retracting my #2 (and the matching BLOCKER in the review below). You're right that it isn't reachable. I instrumented _validate_changeset_identity to confirm: when expected_schema_name is supplied, _confirm_dev_route uses it as the fallback, so schemaName is never empty and the prefetch branch never runs — the mismatch is caught on the first and only validation. When it isn't supplied, the prefetch runs but the second call resolves to the schema it just derived, so there's nothing to disagree with. The fix I proposed would have been a no-op.
I also confirmed the persisted schema_name on a rejected attach is the expected schema with a blocked step, not a foreign one — so no state poisoning. I saw the write happening before validation and wrongly inferred what was in it. Apologies for the noise.
Your answers on #3 (family identity moved to validate-agent / prod-to-dev / guarded import), #4 (fail-closed on authoritative component schema), and #5 (cassettes are immutable recordings; Accept omission matches the external request reference) all check out. Publish coverage is now in via 8db835fe — verified passing locally.
One optional nit: a one-line comment on get_realms / get_realm_configuration noting they intentionally stay on DEFAULT_API_VERSION because the almimportexport.http reference doesn't cover them and configure is live-proven on 2024-10-01. Two of us asked the same question independently, so the next reader probably will too. Not worth holding the merge for.
Approving. 🚀
|
Apurva Banka (@apurvabanka) I'll align the API versions to the newer value in a follow up PR. Thanks |
|
Thanks for the independent pass, RamananVr. These substantially overlap with Apurva Banka (@apurvabanka)'s earlier review; after your comment, Apurva instrumented the schema path and retracted that blocker—the persisted value is the expected schema, not a foreign one, so the proposed prefetch change would be inert. The API-version split will be aligned to |
Summary
Why
A newly created MOS agent can expose editable components before it has published Dev configuration. Test 31 reproduced setup incorrectly treating the missing published
/configureresource as a requirement to publish. Test 33 confirmed that unpublished attachment succeeds, but also exposed that the progress checklist conflated completed local materialization with overall runtime readiness.Runtime evidence
Tests
python -m pytest tests\scripts\test_setup_existing_da.py tests\scripts\test_setup_mos_starter.py tests\scripts\test_setup_alm_import.py tests\scripts\test_setup_alm_export.py tests\scripts\test_auth.py tests\scripts\test_da_command_degradation.py tests\setup\test_da_setup_router.py -q227 passed.