Skip to content

feat(xtest): Allow selecting sdk versions for xtest#446

Merged
dmihalcik-virtru merged 14 commits into
mainfrom
DSPX-1115-sdkversions
May 15, 2026
Merged

feat(xtest): Allow selecting sdk versions for xtest#446
dmihalcik-virtru merged 14 commits into
mainfrom
DSPX-1115-sdkversions

Conversation

@dmihalcik-virtru
Copy link
Copy Markdown
Member

@dmihalcik-virtru dmihalcik-virtru commented May 4, 2026

Summary

  • Adds version-qualified SDK specifiers (go@main, go@v0.18.0, go@*) to --sdks, --sdks-encrypt, and --sdks-decrypt pytest options
  • Replaces the static sdk: [go, java, js] CI matrix with a dynamic per-sdk@version matrix, so each released or head version of each SDK gets its own test job
  • Skips round-trip test pairs where all SDKs involved are released artifacts when running non-dispatch CI, to avoid redundant old-vs-old coverage

Motivation

Version-qualified SDK selection

Previously the matrix ran one job per SDK type, always using whatever versions happened to be installed. This PR resolves each SDK to explicit versions (via otdf-sdk-mgr versions resolve) and parametrizes the matrix over sdk@version entries, making it possible to test multiple released versions of the same SDK in a single run and to pin exact versions in CI artifacts.

Skip released-only pairs

With multiple SDK versions in the matrix, the cross-product of (encrypt_sdk, decrypt_sdk) pairs grows quickly. Most of those new pairs are combinations of two already-shipped artifacts — they test code that hasn't changed and add no signal on a PR.

This is analogous to the existing --focus <sdk> mechanism, which skips pairs that don't include the focused SDK. The new --skip-released-pairs flag (set automatically in CI) skips any round-trip test where both encrypt_sdk and decrypt_sdk are semver-tagged releases (v\d+\.\d+\.\d+).

The flag is not set when:

  • The event is workflow_dispatch — the user explicitly requested a full run
  • The platform under test is itself a head build (e.g. main) — in that case, testing released SDKs against a new platform IS meaningful for backward-compatibility coverage (covers PRs and cron jobs from opentdf/platform)

Implementation

  • SDK.is_released() in tdfs.py — semver regex on the version string
  • --skip-released-pairs option + pytest_runtest_setup hook in conftest.py — auto-skips without touching individual test files
  • SKIP_RELEASED_PAIRS env var in the CI matrix job, gated on event type and platform head status

Summary by CodeRabbit

  • New Features

    • Added --skip-released-pairs to optionally skip tests for released SDK pairs.
    • Tests can target resolved SDK@version entries (SDK plus tag) at runtime.
  • Chores

    • CI test matrix now uses resolved SDK@version entries and produces clearer artifact names.
    • Test validators and parsing tightened; lint/type-tool configs updated.
    • Aggregate workflow now treats skipped test runs as workflow failures.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 4, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a27f67d2-e62e-4517-bcff-5e7fba1fb401

📥 Commits

Reviewing files that changed from the base of the PR and between 7bc0f72 and 84daa32.

📒 Files selected for processing (1)
  • xtest/pyproject.toml
✅ Files skipped from review due to trivial changes (1)
  • xtest/pyproject.toml

📝 Walkthrough

Walkthrough

Refactors SDK-spec parsing and release detection for xtests: adds typed SDK spec helpers and parsing in xtest/tdfs.py, validates CLI SDK specs and a --skip-released-pairs flag in xtest/conftest.py, updates the GitHub Actions xtest workflow to produce/consume a sdk-version matrix and adjust step conditions/artifact names, and tweaks lint/pyright config.

Changes

SDK Version Specification & Conditional Testing

Layer / File(s) Summary
Data shapes & guards
xtest/tdfs.py
Adds is_sdk_type(), annotates SDK.version, adds SDK.is_released() and parse_sdk_spec(spec) -> list[SDK].
Version enumeration
xtest/tdfs.py
Refactors all_versions_of() to a list-comprehension and integrates with parse_sdk_spec() to support "<sdk>", "<sdk>@*", and "<sdk>@<version>".
CLI validation
xtest/conftest.py
Adds sdk_spec_type(v: str) validator; updates --sdks, --sdks-decrypt, --sdks-encrypt to use it and raise pytest.UsageError on parse errors.
Param generation & setup hook
xtest/conftest.py
pytest_generate_tests() now resolves SDK lists by calling tdfs.parse_sdk_spec(); adds pytest_runtest_setup() to skip tests when both encrypt/decrypt SDKs are released and --skip-released-pairs is set.
CI: resolve-versions output
.github/workflows/xtest.yml
resolve-versions step builds sdk-version-list (skips platform, excludes errored entries) and sets it as job output.
CI: matrix & envs
.github/workflows/xtest.yml
xct job matrix switches from sdk to sdk-version using sdk-version-list; ENCRYPT_SDK and related envs use matrix.sdk-version. SKIP_RELEASED_PAIRS added and computed.
CI: conditional steps & artifacts
.github/workflows/xtest.yml
Step conditions changed to startsWith(matrix.sdk-version, 'go@') / java@; pytest steps conditionally append --skip-released-pairs; artifact names sanitized from ENCRYPT_SDK and include sdk-version and platform-tag; aggregator treats skipped as failure.
Tooling config
xtest/pyproject.toml
Ruff enables PERF rules; Pyright venv settings added (venvPath=".", venv=".venv").
Small refactor (no behavior change)
xtest/audit_logs.py
Replaced several for/append constructions with context.extend([...]) list comprehensions in _raise_assertion_error.

Sequence Diagram

sequenceDiagram
    actor Dev as Developer
    participant GHA as GitHub Actions
    participant RV as resolve-versions
    participant Parser as tdfs.parse_sdk_spec
    participant XCT as xct (matrix)
    participant Pytest as pytest
    participant Hook as pytest_runtest_setup

    Dev->>GHA: push / trigger workflow
    GHA->>RV: run version resolution
    RV->>Parser: build sdkVersionList from resolved tags
    Parser-->>RV: SDK strings like "go@v1.2.3"
    RV->>GHA: set job output sdk-version-list (JSON)
    GHA->>XCT: expand matrix from sdk-version-list
    XCT->>Pytest: invoke pytest with matrix.sdk-version envs
    Pytest->>Parser: parse CLI --sdks* via parse_sdk_spec()
    Parser-->>Pytest: resolved SDK parameter sets
    Pytest->>Hook: for each test, run pytest_runtest_setup
    Hook->>Hook: if both SDKs .is_released() && skip flag -> skip test
    alt skipped
        Hook-->>Pytest: test skipped
    else
        Hook-->>Pytest: test runs
    end
Loading

Estimated Code Review Effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Suggested Reviewers

  • pflynn-virtru
  • alkalescent

Poem

🐰 Specs now hop in tidy rows,
parsing tags where each version grows,
released pairs step softly by,
CI matrices march, artifacts fly,
a rabbit cheers the tests that know.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 22.22% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main feature: adding version-qualified SDK selection to xtest, which is the core purpose of this PR.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch DSPX-1115-sdkversions

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces support for version-qualified SDK specifiers (e.g., 'go:main', 'go:*') in the test suite. Key changes include the addition of sdk_spec_type for CLI option validation in conftest.py, a new parse_sdk_spec utility in tdfs.py, and updates to pyright configuration. Feedback focuses on improving consistency by using the is_sdk_type helper and replacing assert statements with ValueError to ensure robust runtime validation.

Comment thread xtest/conftest.py Outdated
Comment thread xtest/tdfs.py Outdated
Comment thread xtest/tdfs.py Outdated
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 4, 2026

X-Test Failure Report

1 similar comment
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 4, 2026

X-Test Failure Report

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 5, 2026

X-Test Failure Report

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 5, 2026

X-Test Failure Report

dmihalcik-virtru and others added 11 commits May 5, 2026 09:45
- Add `tdfs.parse_sdk_spec()` supporting `go`, `go:*`, `go:main`,
  `go:v0.18.0` specifiers
- Update `--sdks`, `--sdks-encrypt`, `--sdks-decrypt` CLI options to
  accept version-qualified values via new `sdk_spec_type` validator
- Replace `defaulted_list_opt`/`all_versions_of` expansion in
  `pytest_generate_tests` with `sdk_specs_opt` + `parse_sdk_spec`
- Emit `sdk-version-list` (e.g. `["go:main","java:latest"]`) from
  `resolve-versions` job and drive `xct` matrix from it instead of a
  hardcoded `["go","java","js"]`; each SDK version now gets its own
  matrix cell
- Replace `env.FOCUS_SDK == 'go'/'java'` step conditions with
  `startsWith(matrix.sdk-version, 'go:')` / `'java:'`
- Update artifact names to include the full `sdk-version` specifier

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Colons are not allowed in GitHub Actions artifact names and are
problematic in file names; '@' is the idiomatic version separator
(npm, Go module proxy, etc.).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Fail xtest capstone when xct matrix is skipped (empty sdk-version-list
  would previously produce a green run with zero tests executed)
- Correct --sdks help text examples from ':' to '@' separator
- Reject empty version strings (e.g. 'go@') and whitespace-only input
  in sdk_spec_type at argument-parse time with a clear error message
- Wrap e_sdks/d_sdks comprehensions in pytest_generate_tests to convert
  FileNotFoundError/ValueError into pytest.UsageError

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add SDK.is_released() to detect semver-tagged versions, a
--skip-released-pairs pytest flag, and a pytest_runtest_setup hook that
automatically skips any round-trip test where both encrypt_sdk and
decrypt_sdk are released artifacts. The workflow sets SKIP_RELEASED_PAIRS
on all non-workflow_dispatch triggers so PR runs skip redundant
old-vs-old pairs without requiring changes to individual test files.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
If the platform under test is a head build (e.g. main), all SDK pairs
are meaningful for backward-compat coverage, so --skip-released-pairs
must not fire. Only skip when both the platform tag is a released
artifact and the event is not a workflow_dispatch.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@dmihalcik-virtru dmihalcik-virtru force-pushed the DSPX-1115-sdkversions branch from 5b25db8 to 404c3ff Compare May 5, 2026 13:45
@dmihalcik-virtru dmihalcik-virtru changed the title feat(xtest): DSPX-1115 Allow selecting sdk versions for xtest feat(xtest): Allow selecting sdk versions for xtest May 5, 2026
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 5, 2026

X-Test Failure Report

@dmihalcik-virtru dmihalcik-virtru marked this pull request as ready for review May 5, 2026 15:12
@dmihalcik-virtru dmihalcik-virtru requested review from a team as code owners May 5, 2026 15:12
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/xtest.yml:
- Around line 717-725: Sanitize matrix.sdk-version before using it in artifact
names: update the two upload-artifact steps (the test-results upload and the
"Upload audit logs on failure" step) so the name interpolation uses a sanitized
value like replace(matrix.sdk-version, '/', '-') (e.g., ${{
replace(matrix.sdk-version, '/', '-') }}-${{ matrix.platform-tag }}), ensuring
any forward slashes are replaced (or otherwise removed) so artifact names are
valid for actions/upload-artifact.

In `@xtest/tdfs.py`:
- Around line 387-388: is_released currently only recognizes versions starting
with "v", so expand the detection to match tags like "sdk/0.9.0", bare semver
"0.9.0" and semver with prerelease/build metadata "0.9.0-beta.84". Update the
is_released method (refer to is_released and self.version) to use a broader
regex that optionally allows "v" or "sdk/" prefixes and accepts semver with
optional prerelease/build suffixes (for example by matching
(?:v|sdk/)?\d+\.\d+\.\d+(?:[-+].+)? across the string) so --skip-released-pairs
correctly identifies released JS versions.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 062f64a9-22a1-490d-a6b3-d442fed86167

📥 Commits

Reviewing files that changed from the base of the PR and between 7e76234 and 404c3ff.

📒 Files selected for processing (4)
  • .github/workflows/xtest.yml
  • xtest/conftest.py
  • xtest/pyproject.toml
  • xtest/tdfs.py

Comment thread .github/workflows/xtest.yml Outdated
Comment thread xtest/tdfs.py Outdated
…rtifact names

- Broaden `SDK.is_released()` regex to recognize JS-style tags (`sdk/0.9.0`,
  `0.9.0-beta.84`) in addition to `v`-prefixed semver; use `fullmatch` to
  avoid partial matches so `--skip-released-pairs` correctly prunes JS pairs
- Sanitize `matrix.sdk-version` before using it in artifact names: JS tags
  like `sdk/0.9.0` produce names with `/` which `actions/upload-artifact`
  rejects; new step outputs a `/`→`-` sanitized value used by both upload steps

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@xtest/tdfs.py`:
- Around line 387-392: The current is_released() regex rejects semver strings
that include both prerelease and build metadata (e.g. "0.18.0-rc.1+build.7");
update the pattern in is_released to allow an optional prerelease group and an
optional build metadata group separately (for example replace the existing final
part with something like (?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?), keeping the
existing optional "sdk/" and "v" prefixes and using re.fullmatch against
self.version.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 990144b1-809b-45c0-a49a-d13463240507

📥 Commits

Reviewing files that changed from the base of the PR and between 404c3ff and 7bc0f72.

📒 Files selected for processing (4)
  • .github/workflows/xtest.yml
  • xtest/audit_logs.py
  • xtest/pyproject.toml
  • xtest/tdfs.py
✅ Files skipped from review due to trivial changes (2)
  • xtest/audit_logs.py
  • xtest/pyproject.toml

Comment thread xtest/tdfs.py
Comment on lines +387 to +392
def is_released(self) -> bool:
return bool(
re.fullmatch(
r"(?:sdk/)?v?\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?", self.version
)
)
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot May 5, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Allow prerelease and build metadata in is_released().

This regex rejects valid semver tags like 0.18.0-rc.1+build.7, so pytest_runtest_setup() will treat those SDKs as unreleased and keep running released-only pairs unnecessarily. Split prerelease and build into separate optional groups.

Suggested fix
     def is_released(self) -> bool:
         return bool(
             re.fullmatch(
-                r"(?:sdk/)?v?\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?", self.version
+                r"(?:sdk/)?v?\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?",
+                self.version,
             )
         )
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@xtest/tdfs.py` around lines 387 - 392, The current is_released() regex
rejects semver strings that include both prerelease and build metadata (e.g.
"0.18.0-rc.1+build.7"); update the pattern in is_released to allow an optional
prerelease group and an optional build metadata group separately (for example
replace the existing final part with something like
(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?), keeping the existing optional "sdk/"
and "v" prefixes and using re.fullmatch against self.version.

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.

prereleased and build-tagged SDKs are not released, hence the intentional regex rejection

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@jakedoublev, that makes complete sense — prerelease (-rc.1) and build-tagged (+build.7) versions are not stable releases, so intentionally excluding them from is_released() is the right design. My suggestion was incorrect. Thanks for the clarification!


✏️ Learnings added
Learnt from: jakedoublev
Repo: opentdf/tests PR: 446
File: xtest/tdfs.py:387-392
Timestamp: 2026-05-05T21:39:53.321Z
Learning: In `xtest/tdfs.py`, the `SDK.is_released()` method intentionally rejects prerelease (e.g., `-rc.1`) and build-metadata (e.g., `+build.7`) tagged versions. Only clean semver tags (e.g., `v0.18.0`) or those with an optional combined suffix are considered "released." Do not suggest expanding the regex to accept prerelease/build metadata tags as released artifacts.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

Comment thread .github/workflows/xtest.yml
Comment thread .github/workflows/xtest.yml
@github-actions
Copy link
Copy Markdown

X-Test Failure Report

@sonarqubecloud
Copy link
Copy Markdown

@github-actions
Copy link
Copy Markdown

X-Test Failure Report

@dmihalcik-virtru dmihalcik-virtru merged commit 9b5ad38 into main May 15, 2026
26 of 40 checks passed
@dmihalcik-virtru dmihalcik-virtru deleted the DSPX-1115-sdkversions branch May 15, 2026 02:20
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.

2 participants