DX | 06-07-2026 | Release#169
Conversation
…api_version header
Add a self-contained pytest integration suite under tests/integration that creates a fresh stack per run, exercises every SDK resource method (positive, negative, and edge cases) against the live CMA API, and tears the stack down. - framework/: dynamic stack setup/teardown, request+cURL capture, response/error validators, tracked assertions, and a custom dashboard HTML report - api/: 30 resource files with full method coverage - data/: complex content-type schemas (modular blocks, groups, references, JSON RTE) and entry payloads - strict, bug-catching assertions; genuine SDK/environment issues tracked via xfail - timestamped HTML report + cURL log written to repo root (gitignored) Also: update AGENTS.md to document the sanity suite + env vars, add pytest/pytest-order to requirements, gitignore secrets/reports/docs.
Cover the asset scanning feature (DAM/AM 2.0) against both the normal org and the AM 2.0 (DAM-enabled) org: - normal-org scan tests (test_06_asset): upload returns _asset_scan_status 'pending'; field absent unless include_asset_scan_status=true; clean file scans 'clean'; EICAR test file scans 'quarantined'; listing includes status - test_31_am_assets: AM-org assets get 'am'-prefixed UIDs, full CRUD round-trip, the same scan lifecycle, publish() with the api_version: 3.2 header (publish- only; 404 on fetch) - framework: am_stack fixture (stack in AM_ORG_UID; whole suite skips when unset), runtime-generated EICAR fixture (base64-encoded so the signature is not committed raw), wait_for_scan() polling helper, and api_version header reset for per-test isolation Note: the correct query param is include_asset_scan_status (the response field is _asset_scan_status); verified live.
Asset.update() forced Content-Type: multipart/form-data while sending a JSON body, and Asset.replace() set a bare multipart/form-data header (no boundary) while passing files=. Both made the CMA API reject the request with 422 'Please send a valid multipart/form-data payload', and both leaked the wrong Content-Type onto subsequent requests on the shared client. - update(): send the JSON body as application/json (matches the JS SDK and the live API, which returns 200) - replace(): let the HTTP layer build the multipart body with a proper boundary Bump version to 1.10.1 and update the asset update unit test accordingly.
- taxonomy/terms/global-field delete: drop Content-Type on the body-less DELETE (the SDK merges application/json, which the API rejects 400/500; the JS SDK omits it) — these now pass instead of xfail - bulk update_workflow: provide a real target stage uid + notify field - branch delete: poll-retry the transient 'branch not valid' (905) while the branch finishes async provisioning - asset update/replace: flip from xfail to passing (fixed in the SDK, v1.10.1) - capture/setup: retry transient network errors (ReadTimeout/ConnectionError) 2x with backoff and bump the client timeout to 120s so dev11 blips don't fail the run
- assets.py replace(): use per-request header copy (no Content-Type) instead of mutating shared client headers dict; wrap file open in context manager to prevent FD leak - assets.py update(): use per-request header copy with explicit Content-Type: application/json, robust against prior upload/replace calls - capture.py retry: close old FD before reopening on transient retry; use tuple(val[2:]) to handle both 2-tuple and 3-tuple file specs without crashing on missing index - setup.py: remove references to non-existent .env.example in docstring and runtime error message - test_assets_unit.py: fix scan-status unit tests to use correct query param name (include_asset_scan_status) and lowercase string value (true), matching the integration suite and CMA API wire format
_api_client._call_request merges self.headers into every request via headers.update(self.headers), which overwrites any per-request copy before the request is sent. The only effective way to suppress Content-Type for multipart uploads is to temporarily pop it from the shared dict and restore it in a finally block. Also retains the with-open() fix so the file handle is always closed after the request.
…roval publish_request_approval calls GET /workflow which returns 401 when the entry has no active workflow state. wf_entry is class-scoped so TestWorkflowPublishRules gets a fresh entry that was never assigned to a stage (TestWorkflowStagesAndTasks sets a different instance). Fix: call set_workflow_stage inside the test to activate the entry's workflow state before querying. Removes the xfail marker.
…e reason GET /workflow (publish approval state) and POST /workflow (set stage) are separate ACL checks. The test account has set-stage permission but not get-approval permission on DEV11, causing 401 regardless of workflow state. The set_workflow_stage setup step is kept — it is still correct hygiene. Unblock: grant Workflow > Publish Approval to Owner role in the test org.
feat: add asset scanning unit tests for _asset_scan_status param and api_version header
🔒 Security Scan Results
⏱️ SLA Breach Summary
ℹ️ Vulnerabilities Without Available Fixes (Informational Only)The following vulnerabilities were detected but do not have fixes available (no upgrade or patch). These are excluded from failure thresholds:
✅ BUILD PASSED - All security checks passed |
chore: back-merge main into development
🔒 Security Scan Results
⏱️ SLA Breach Summary
ℹ️ Vulnerabilities Without Available Fixes (Informational Only)The following vulnerabilities were detected but do not have fixes available (no upgrade or patch). These are excluded from failure thresholds:
✅ BUILD PASSED - All security checks passed |
…-rewrite test(integration): dynamic-stack CMA SDK sanity suite + AM 2.0 coverage + asset Content-Type fix (v1.10.1)
🔒 Security Scan Results
⏱️ SLA Breach Summary
ℹ️ Vulnerabilities Without Available Fixes (Informational Only)The following vulnerabilities were detected but do not have fixes available (no upgrade or patch). These are excluded from failure thresholds:
✅ BUILD PASSED - All security checks passed |
-Asset scanning tests added.
-e2e sanity tests added.
-Fixed Asset.update() to send the JSON body with Content-Type: application/json instead of an invalid bare multipart/form-data, which the API rejected with 422.
Fixed Asset.replace() to let the HTTP layer set multipart/form-data with a proper boundary (a bare multipart/form-data header without a boundary previously caused a 422). Both fixes also remove a side effect that leaked the wrong Content-Type onto subsequent requests.