Skip to content

fix(ci): repair publishing and Cognitive service test credentials - #2691

Merged
Rana Singh (ranadeepsingh) merged 6 commits into
microsoft:masterfrom
ranadeepsingh:fix/master-ci-234106471
Sep 4, 2026
Merged

fix(ci): repair publishing and Cognitive service test credentials#2691
Rana Singh (ranadeepsingh) merged 6 commits into
microsoft:masterfrom
ranadeepsingh:fix/master-ci-234106471

Conversation

@ranadeepsingh

@ranadeepsingh Rana Singh (ranadeepsingh) commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

What changed

  • Validate restored SBT dependencies with the existing bounded retry and cache-eviction helper before Python artifact packaging.
  • Run ordinary Cognitive, Face, Form, Vision, Text, Translator, Speech, notebook, and website tests against the API-key-enabled mmlspark-cs-central resource in centralus.
  • Preserve explicit .setSubscriptionKey(...) and .setLocation(...) calls so test configurations remain reusable examples.
  • Use a dedicated cognitive-api-key-central Key Vault secret without changing existing eastus secrets.
  • Restore explicit subscription-key authentication for custom Language tests on the dedicated East US authoring resource; retain Microsoft Entra authentication only for the website Translator path, whose specialized resource still disables local authentication.
  • Pair AI Foundry tests with the verified openai-api-key-3 / synapseml-openai-3 resource.
  • Replace the unavailable custom Speech deployment fixture with deterministic endpoint-ID configuration coverage.
  • Rewrite executable website Python samples only in the transient CI copy, leaving checked-in Python and Scala examples unchanged, and make markdown writes failure-safe.

Root cause

Azure Pipelines build 234106471 had 15 failing jobs:

  1. The publishing job restored incomplete or poisoned SBT, Ivy, and Coursier metadata, then attempted packagePython before validating the restored dependencies.
  2. Fourteen Cognitive service jobs used keys for resources on which Azure Policy had enforced disableLocalAuth=true, producing HTTP 401 and 403 responses.

The blocked shared resource was mmlspark-cs in resource group marhamil-mmlspark, region eastus. This PR does not weaken that policy. Ordinary tests instead use mmlspark-cs-central, whose local authentication is enabled, with the matching centralus endpoint. The central key returns HTTP 401 against the old eastus endpoint, so key and region are changed together.

Compatibility and security

  • No public production JVM signature, serialized parameter, generated wrapper, REST diagnostic, Speech authentication, or Databricks utility changes remain in the final patch.
  • Credentials are loaded from Key Vault or environment overrides and are not committed or printed.
  • Existing shared eastus secrets remain unchanged to avoid affecting unrelated consumers.
  • The CI identity has only the Cognitive Services User role on mmlspark-cs-central; the temporary Face Contributor role used for diagnosis was removed.
  • Custom Language coverage uses its matching Key Vault key after re-enabling local authentication on a resource already exempt from the enforcing policy; Document Translator coverage retains Entra authentication because its specialized resource still rejects keys.

Evidence

  • Build 234137720 passed all eight publishing tasks on the cache-recovery commit.
  • The superseded broad-Entra head passed all 65 Azure jobs in build 234253942. That run established the original failure classification but is not evidence for the new head.
  • Representative live validation with the central key passed 44 tests across Face identification, Vision OCR, Form layout, Text language detection, Translator, and REST Speech.
  • Cognitive test compilation and main/test Scalastyle passed with JDK 11.
  • The deterministic Speech endpoint-ID regression passed.
  • All 134 Python CI tests passed.
  • Black 22.3.0 left all 202 checked Python files unchanged.
  • Previous-head build 234337123 executed all 65 jobs at merge SHA af6dc5208e490ab9ccc98314e1288f7127c29330: 64 succeeded, and UnitTests lightgbm4 succeeded with issues only because three non-gating Azure cache restores hit an external SSL error. The build published 3,435 tests with 3,413 passed, 22 not applicable, and zero failed.
  • Live custom Language validation passed all 8 tests across custom entity recognition and multi-label classification using .setSubscriptionKey(languageApiKey) against the matching East US resource.
  • The local legacy Speech SDK live tests are blocked before authentication by native azure-c-shared platform initialization error 2153; REST Speech with the same central key succeeds. Hosted Azure validation is required for that SDK path.

Current exact head: c8c5ddde6b29c683a6a8c92e742aca9f05882098

Status: exact-head automated review and the 65-job Azure pipeline are pending after restoring custom Language key authentication.

## Summary
Revalidate restored SBT dependencies with the existing bounded retry helper before artifact packaging starts, and add a pipeline contract regression that locks recovery ahead of the first publishing SBT command.

## Prompting Intent
Triage Azure Pipelines run 234106471 on master, separate repository-actionable failures from external live-service failures, and fix the pipeline without weakening service assertions or hiding missing evidence.

## Linked Sources
- Failed build: https://msdata.visualstudio.com/A365/_build/results?buildId=234106471&view=results
- Existing cache hardening: microsoft@7c72c49

## Rationale
The cache task reported three exact hits, but packagePython repeatedly failed to resolve hadoop-bare-naked-local-fs, proving that an exact Azure cache restore does not guarantee usable local state. Azure task retries reused that state unchanged. Running sbt_retry.sh update once before packaging validates the cache and selectively evicts unresolved coordinates. This avoids retrying publishBlob uploads and avoids imposing an extra validation process on every SBT job. The unrelated 401/403 live-service failures remain visible because the test resources have local authentication disabled; skipping them would create a false green.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 476d113f-dd35-40c6-bc79-005dcccd7b79
Copilot AI lite review requested due to automatic review settings September 2, 2026 10:26
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
There may be pipelines that require an authorized user to comment /azp run to run.

@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown

Hey Rana Singh (@ranadeepsingh) 👋!
Thank you so much for contributing to our repository 🙌.
Someone from SynapseML Team will be reviewing this pull request soon.

We use semantic commit messages to streamline the release process.
Before your pull request can be merged, you should make sure your first commit and PR title start with a semantic prefix.
This helps us to create release messages and credit you for your hard work!

Examples of commit messages with semantic prefixes:

  • fix: Fix LightGBM crashes with empty partitions
  • feat: Make HTTP on Spark back-offs configurable
  • docs: Update Spark Serving usage
  • build: Add codecov support
  • perf: improve LightGBM memory usage
  • refactor: make python code generation rely on classes
  • style: Remove nulls from CNTKModel
  • test: Add test coverage for CNTKModel

To test your commit locally, please follow our guild on building from source.
Check out the developer guide for additional guidance on testing your change.

@ranadeepsingh

Copy link
Copy Markdown
Collaborator Author

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟢 Approval recommended

The change is small, targeted, and backed by a concrete contract test that enforces the intended publish-step ordering.

Review tier: Lite
Findings: None

What changed in this PR

This PR hardens the Azure Pipelines publish step against “poisoned” restored SBT/Ivy/Coursier caches by running the existing sbt_retry.sh dependency recovery/eviction flow before packagePython, and adds a regression test to enforce the ordering contract.

Changes:

  • Run SBT_SETUP_MAX_STAGGER_SECONDS=0 bash tools/ci/sbt_retry.sh update in templates/publish.yml before sbt packagePython.
  • Add a pipeline contract test to ensure dependency recovery precedes both packagePython and publishBlob.
File Description
tools/​ci/​tests/​test_pipeline_yaml.py Adds a regression contract asserting the publish template runs cache recovery before packaging and blob publish.
templates/​publish.yml Inserts a pre-packaging dependency recovery step using the existing SBT retry/eviction helper.

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

## Summary
Migrate Cognitive Services, website samples, and the failing Databricks Forms
notebook from disabled local-key authentication to short-lived Microsoft Entra
tokens. Add Speech SDK AAD support and redact notebook request and response
bodies from retry diagnostics.

## Prompting Intent
Triage and fix every actionable failure in Azure Pipelines run 234106471 on
master. Follow the SynapseML PR loop, preserve key-based public behavior and JVM
compatibility, avoid credential exposure, and prove the replacement
authentication path.

## Linked Sources
- Failed pipeline: https://msdata.visualstudio.com/A365/_build/results?buildId=234106471&view=results
- Pull request: microsoft#2691
- Azure Policy evidence: affected Cognitive Services accounts enforce
  disableLocalAuth=true

## Rationale
Azure Policy prevents restoring local keys, so the tests now use the pipeline
service connection and resource-scoped Cognitive Services User assignments.
Shared helpers keep resource routing consistent. Speech retains subscription-key
fallback because its SDK requires a service-specific AAD credential format.
Databricks receives a fresh token only for the affected notebook, and body
redaction prevents retry logs from printing it.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 476d113f-dd35-40c6-bc79-005dcccd7b79
Copilot AI review requested due to automatic review settings September 2, 2026 17:57
@ranadeepsingh Rana Singh (ranadeepsingh) changed the title fix(ci): repair poisoned SBT caches before publishing fix(ci): repair master publishing and Cognitive test authentication Sep 2, 2026
@ranadeepsingh

Copy link
Copy Markdown
Collaborator Author

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

A couple of verified issues in changed code paths can lead to corrupted CI artifacts on exceptions and to error-reporting failures masking the real HTTP failure context.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review tier: Lite
Findings: 1 Medium severity

New issues introduced by this change (1)
Severity Finding
Medium severity core/​src/​main/​scala/​com/​microsoft/​azure/​synapse/​ml/​io/​http/​RESTHelpers.scala — In the non-redacted path, requestBodyOpt uses Try(...).get, so if reading the request entity…
Suppressed comments (1)

website/doctest.py:133

  • add_python_helper_to_markdown truncates the markdown file before applying transformations. If use_aad_for_ci_samples or the regex replacement raises, the file will be left empty/corrupted, which can mask the real failure and make CI harder to debug. Prefer writing the updated content first, then truncating after a successful write (and rely on the context manager instead of calling close() explicitly).
    with io.open(os.path.join(folder, md), "r+", encoding="utf-8") as f:
        content = f.read()
        f.truncate(0)
        content = use_aad_for_ci_samples(content, md)
        content = re.sub("<!--pytest-codeblocks:cont-->", replacement, content)
        f.seek(0, 0)
        f.write(content)
        f.close()

Comment thread core/src/main/scala/com/microsoft/azure/synapse/ml/io/http/RESTHelpers.scala Outdated
## Summary
Complete the Entra migration for the remaining website, AI Foundry, Face-adjacent, and Speech validation paths. Preserve HTTP diagnostics when request bodies are unreadable, make documentation updates failure-safe, retire the obsolete key-only custom Speech fixture in favor of deterministic endpoint configuration coverage, and apply the pinned notebook formatting.

## Prompting Intent
The engineer asked to triage and fix every failure from the latest master CI/CD run using the full SynapseML PR loop, then keep iterating on exact-head validation and automated review findings until the change is merge-ready without exposing credentials or weakening meaningful coverage.

## Linked Sources
- Original Azure Pipelines failure: https://msdata.visualstudio.com/A365/_build/results?buildId=234106471&view=results
- First exact-head validation: https://msdata.visualstudio.com/A365/_build/results?buildId=234189609&view=results
- Pull request: microsoft#2691
- REST diagnostics review finding: microsoft#2691 (comment)

## Rationale
Rewrite authentication independently from fluent setter adjacency so all executable Python samples move to the correct Entra endpoint shape, and route the one-off AI Foundry stage through the shared test helper. The legacy custom Speech endpoint has no discoverable policy-compliant owning resource, so replace its brittle key-backed cloud assertion with a deterministic check that SynapseML applies the endpoint ID to the Speech SDK while retaining the suite's live Entra recognition coverage. Render diagnostics and transformed markdown defensively so secondary read or transformation failures cannot hide the original error or truncate source files.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 476d113f-dd35-40c6-bc79-005dcccd7b79
Copilot AI review requested due to automatic review settings September 2, 2026 20:42
@ranadeepsingh

Copy link
Copy Markdown
Collaborator Author

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

The Speech SDK AAD path currently passes a formatted aad#resourceId#token string into SpeechConfig.setAuthorizationToken, which is likely invalid for the underlying SDK and risks breaking runtime authentication.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review tier: Lite
Findings: 1 High severity

New issues introduced by this change (1)
Severity Finding
High severity cognitive/​src/​main/​scala/​com/​microsoft/​azure/​synapse/​ml/​services/​speech/​SpeechToTextSDK.scalaSpeechConfig.setAuthorizationToken expects the raw Entra access token (JWT). Here the code passes…
Issues resolved since last review (1)
Severity Finding
Medium severity core/​src/​main/​scala/​com/​microsoft/​azure/​synapse/​ml/​io/​http/​RESTHelpers.scala — In the non-redacted path, requestBodyOpt uses Try(...).get, so if reading the request entity… View resolved comment

## Summary
Move the IdentifyFacesSuite fixture from subscription-exhausted PersonGroup storage to LargePersonGroup while preserving the live end-to-end identification assertions. Restrict stale fixture cleanup to timestamped test-owned groups and apply the formatter output required by the hosted Style job.

## Prompting Intent
The engineer asked to triage and fix every actionable failure from the latest master CI validation using the SynapseML PR loop, preserve meaningful service coverage, and distinguish product defects from hosted-agent infrastructure faults.

## Linked Sources
- Original failed build: https://msdata.visualstudio.com/A365/_build/results?buildId=234106471&view=results
- Exact-head validation: https://msdata.visualstudio.com/A365/_build/results?buildId=234213031&view=results
- Pull request: microsoft#2691
- Face service quotas: https://learn.microsoft.com/en-us/azure/ai-services/face/identity-quotas-limits

## Rationale
Direct AAD probes showed that standard PersonGroup person creation returns subscription-level QuotaExceeded even for an empty new group, while LargePersonGroup creation, person enrollment, training, and identification succeed on the same S0 resource. Using the transformer's existing largePersonGroupId support retains real service validation without deleting data in other resources, requesting unnecessary capacity, or weakening the test to a mock or skip. The Python change follows the exact hosted formatter diff rather than changing pipeline tooling.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 476d113f-dd35-40c6-bc79-005dcccd7b79
Copilot AI review requested due to automatic review settings September 2, 2026 22:52
@ranadeepsingh

Copy link
Copy Markdown
Collaborator Author

/azp run

Copilot AI review requested due to automatic review settings September 3, 2026 09:16
@ranadeepsingh Rana Singh (ranadeepsingh) changed the title fix(ci): repair master publishing and Cognitive test authentication fix(ci): repair publishing and Cognitive service test credentials Sep 3, 2026
@ranadeepsingh

Copy link
Copy Markdown
Collaborator Author

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

It changes CI publishing flow and live credential/region routing across many suites, which is high-impact and best confirmed with end-to-end CI evidence before approval.

Review tier: Lite
Findings: None

@ranadeepsingh

Copy link
Copy Markdown
Collaborator Author

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

@ranadeepsingh

Copy link
Copy Markdown
Collaborator Author

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

@codecov-commenter

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 87.41%. Comparing base (1db3c40) to head (a72e15a).

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #2691      +/-   ##
==========================================
+ Coverage   86.89%   87.41%   +0.52%     
==========================================
  Files         341      341              
  Lines       20742    20742              
  Branches     2166     2166              
==========================================
+ Hits        18023    18132     +109     
+ Misses       2719     2610     -109     

see 13 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@ranadeepsingh

Copy link
Copy Markdown
Collaborator Author

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

@ranadeepsingh

Copy link
Copy Markdown
Collaborator Author

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

@ranadeepsingh

Copy link
Copy Markdown
Collaborator Author

Final readiness evidence

  • Head: a72e15a773722dad9c0799907fd89491bfd23ea0
  • Merge SHA: af6dc5208e490ab9ccc98314e1288f7127c29330
  • Target: master at 1db3c40b1a7397f4801ab6077dfa282da9781ac4; 5 commits ahead, 0 behind
  • Review: exact-head Copilot review complete; 0 unresolved threads and 0 suppressed current-head findings
  • Required checks: 0 failed, 0 pending, 0 missing
  • Azure build 234337123: all 65 jobs executed; 64 succeeded and UnitTests lightgbm4 succeeded with issues only because three non-gating Cache@2 restores hit an external SSL error. Published tests: 3,435 total, 3,413 passed, 22 not applicable, 0 failed.
  • Readiness snapshot: complete=true

Remaining blocker: repository-required human approval (REVIEW_REQUIRED).

## Summary
Restore subscription-key authentication for the custom entity recognition and multi-label classification transformer tests, and remove the test-only AAD token helper that is no longer used.

## Prompting Intent
The engineer asked why the dedicated mmlspark-cs-language resource was used and required reusable transformer examples to configure .setSubscriptionKey(languageApiKey) rather than replacing key authentication with AAD.

## Linked Sources
- Pipeline failure: https://msdata.visualstudio.com/A365/_build/results?buildId=234106471&view=results
- Pull request: microsoft#2691
- Language resource setup: https://learn.microsoft.com/azure/ai-services/language-service/custom-named-entity-recognition/how-to/create-project
- Regional support: https://learn.microsoft.com/azure/ai-services/language-service/concepts/regional-support

## Rationale
The two custom projects and trained deployments are owned by the dedicated East US Language resource. Central US is prediction-only for these features, and the existing multi-service resource rejects Language authoring requests, so it cannot replace the authoring resource. Re-enabling local authentication under the resource's existing policy exemption preserves the explicit key-based examples and avoids an unnecessary AAD-only test dependency.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 476d113f-dd35-40c6-bc79-005dcccd7b79
Copilot AI review requested due to automatic review settings September 4, 2026 00:43
@ranadeepsingh

Copy link
Copy Markdown
Collaborator Author

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟢 Approval recommended

The changes are cohesive, limited to CI/templates/tests/docs, and the new CI-specific rewrite and pipeline ordering are covered by targeted unit tests.

Review tier: Lite
Findings: None

@ranadeepsingh
Rana Singh (ranadeepsingh) merged commit 2581574 into microsoft:master Sep 4, 2026
16 of 80 checks passed
Rana Singh (ranadeepsingh) added a commit to ranadeepsingh/SynapseML that referenced this pull request Sep 4, 2026
## Summary

Require the trusted Azure Pipelines trigger helper and completeness summary to accept only the exact current-head safe verdict. Align the maintainer workflow documentation and mocked trigger behavior with that fail-closed rule.

## Prompting Intent

The engineer asked for Copilot review to determine whether /azp run is safe before maintainers authorize credential-bearing Azure Pipelines. The current-head review found that a missing machine-readable verdict could still pass the trusted helper, so this change closes that authorization gap without allowing maintainer SHA confirmation to substitute for safety evidence.

## Linked Sources

- Copilot review: microsoft#2692 (review)
- High-severity finding: microsoft#2692 (comment)
- Follow-up to PR microsoft#2691: microsoft#2691

## Rationale

Requiring the exact safe marker is simpler and safer than treating an absent marker as implicit approval. The separate maintainer SHA attestation remains necessary but cannot establish facts the review did not emit; instruction-changing bootstrap PRs continue to require independent review and manual authorization.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 476d113f-dd35-40c6-bc79-005dcccd7b79
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants