Skip to content

X-Test

X-Test #3960

Workflow file for this run

name: X-Test
on:
pull_request:
workflow_dispatch:
inputs:
platform-ref:
required: false
type: string
default: main
description: "The branch or commit to use for the platform"
otdfctl-ref:
required: false
type: string
default: main
description: "The branch or commit to use for otdfctl"
js-ref:
required: false
type: string
default: main
description: "The branch or commit to use for the web-sdk"
java-ref:
required: false
type: string
default: main
description: "The branch or commit to use for the java-sdk"
focus-sdk:
required: false
type: string
default: all
description: "The SDK to focus on (go, js, java, all)"
workflow_call:
inputs:
platform-ref:
required: false
type: string
default: main
otdfctl-ref:
required: false
type: string
default: main
js-ref:
required: false
type: string
default: main
java-ref:
required: false
type: string
default: main
focus-sdk:
required: false
type: string
default: all
schedule:
- cron: "30 6 * * *" # 0630 UTC
- cron: "0 5 * * 1,3" # 500 UTC (Monday, Wednesday)
- cron: "0 18 * * 0" # 1800 UTC (Sunday)
jobs:
resolve-versions:
timeout-minutes: 10
runs-on: ubuntu-latest
permissions:
contents: read
outputs:
platform-tag-to-sha: ${{ steps.version-info.outputs.platform-tag-to-sha }}
platform-tag-list: ${{ steps.version-info.outputs.platform-tag-list }}
heads: ${{ steps.version-info.outputs.platform-heads }}
default-tags: ${{ steps.version-info.outputs.default-tags }}
go: ${{ steps.version-info.outputs.go-version-info }}
java: ${{ steps.version-info.outputs.java-version-info }}
js: ${{ steps.version-info.outputs.js-version-info }}
env:
PLATFORM_REF: "${{ inputs.platform-ref || 'main lts' }}"
JS_REF: "${{ inputs.js-ref }}"
OTDFCTL_REF: "${{ inputs.otdfctl-ref }}"
JAVA_REF: "${{ inputs.java-ref }}"
steps:
- name: Validate focus-sdk input
if: ${{ inputs.focus-sdk != '' }}
run: |-
if [[ ! "all go java js" =~ (^|[[:space:]])${{ inputs.focus-sdk }}($|[[:space:]]) ]]; then
echo "Invalid focus-sdk input: ${{ inputs.focus-sdk }}. Must be one of: all, go, java, js." >> "$GITHUB_STEP_SUMMARY"
exit 1
fi
- name: Default Versions depend on context
id: default-tags
run: |-
if [[ $CRON_NIGHTLY == 'true' ]]; then
echo "Running nightly tests"
echo "DEFAULT_TAGS=main latest" >> "$GITHUB_ENV"
elif [[ $CRON_MONDAY_WEDNESDAY == 'true' ]]; then
echo "Running Monday/Wednesday tests"
echo "DEFAULT_TAGS=main lts" >> "$GITHUB_ENV"
elif [[ $CRON_WEEKLY == 'true' ]]; then
echo "Running weekly tests"
echo "DEFAULT_TAGS=main latest lts" >> "$GITHUB_ENV"
else
echo "Running PR, Workflow Dispatch, or manual trigger"
echo "DEFAULT_TAGS=main" >> "$GITHUB_ENV"
fi
env:
CRON_NIGHTLY: ${{ github.event.schedule == '30 6 * * *' }}
CRON_MONDAY_WEDNESDAY: ${{ github.event.schedule == '0 5 * * 1,3' }}
CRON_WEEKLY: ${{ github.event.schedule == '0 18 * * 0' }}
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
path: otdf-sdk
persist-credentials: false
repository: opentdf/tests
sparse-checkout: xtest/sdk
- uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b
with:
python-version: "3.12"
- run: |-
pip install -r scripts/requirements.txt
working-directory: otdf-sdk/xtest/sdk
- id: version-info
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea #v7.0.1
with:
script: |
function htmlEscape(str) {
return str.replace(/&/g, "&")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;")
.replace(/'/g, "&#39;");
}
const { execSync } = require('child_process');
const path = require('path');
const workingDir = path.join(process.env.GITHUB_WORKSPACE, 'otdf-sdk/xtest/sdk');
const resolveVersionScript = path.join(workingDir, 'scripts/resolve-version.py');
const defaultTags = process.env.DEFAULT_TAGS || 'main';
core.setOutput('default-tags', defaultTags);
const refs = {
platform: process.env.PLATFORM_REF || defaultTags,
go: process.env.OTDFCTL_REF || defaultTags,
js: process.env.JS_REF || defaultTags,
java: process.env.JAVA_REF || defaultTags
};
const versionData = {};
for (const [sdkType, ref] of Object.entries(refs)) {
try {
const output = execSync(`python3 ${resolveVersionScript} ${sdkType} ${ref}`, { cwd: workingDir }).toString();
const ojson = JSON.parse(output);
if (!!ojson.err) {
throw new Error(ojson.err);
}
versionData[sdkType] = ojson;
} catch (error) {
console.error(`Error resolving version for ${sdkType}:`, error);
versionData[sdkType] = [{ tag: ref, err: error.message }];
}
}
core.setOutput('all', JSON.stringify(versionData));
core.summary.addHeading('Versions under Test', 3);
let errorCount = 0;
const table = [];
const th = (data) => ({ data, header: true });
table.push([th('Library'), th('Tag'), th('SHA'), th('Alias'), th('Error')]);
for (const [sdkType, refInfo] of Object.entries(versionData)) {
const tagList = [];
const tagToSha = {};
const headTags = [];
for (const { tag, head, sha, alias, err, release } of refInfo) {
const sdkRepoUrl = `https://github.com/opentdf/${encodeURIComponent(sdkType == 'js' ? 'web-sdk' : sdkType == 'go' ? 'otdfctl' : sdkType == 'java' ? 'java-sdk' : sdkType)}`;
const sdkLink = `<a href="${htmlEscape(sdkRepoUrl)}">${htmlEscape(sdkType)}</a>`;
const commitLink = sha ? `<a href="${htmlEscape(`${sdkRepoUrl}/commit/${encodeURIComponent(sha)}`)}">${htmlEscape(sha.substring(0, 7))}</a>` : ' . ';
const tagLink = (release && tag)
? `<a href="${htmlEscape(`${sdkRepoUrl}/releases/tag/${release}`)}">${htmlEscape(tag)}</a>`
: tag ? htmlEscape(tag) : 'N/A';
table.push([sdkLink, tagLink, commitLink, alias || 'N/A', err || 'N/A']);
if (err) {
errorCount += 1;
continue;
}
tagList.push(tag);
tagToSha[tag] = sha;
if (head) {
headTags.push(tag);
}
}
core.setOutput(`${sdkType}-tag-list`, JSON.stringify(tagList));
core.setOutput(`${sdkType}-tag-to-sha`, JSON.stringify(tagToSha));
core.setOutput(`${sdkType}-heads`, JSON.stringify(headTags));
core.setOutput(`${sdkType}-version-info`, JSON.stringify(refInfo));
}
core.summary.addTable(table);
core.summary.write();
if (errorCount > 0) {
throw new Error('Errors detected in version resolution. Failing the run.');
}
cross-client-test:
timeout-minutes: 60
runs-on: ubuntu-latest
needs: resolve-versions
permissions:
contents: read
packages: read
env:
FOCUS_SDK: "${{ inputs.focus-sdk || 'all' }}"
strategy:
fail-fast: false
matrix:
platform-tag: ${{ fromJSON(needs.resolve-versions.outputs.platform-tag-list) }}
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
repository: opentdf/tests
path: otdftests # use different name bc other repos might have tests directories
######## SPIN UP PLATFORM BACKEND #############
- name: Check out and start up platform with deps/containers
id: run-platform
uses: opentdf/platform/test/start-up-with-containers@main
with:
platform-ref: ${{ fromJSON(needs.resolve-versions.outputs.platform-tag-to-sha)[matrix.platform-tag] }}
ec-tdf-enabled: true
extra-keys: >-
[{
"kid": "golden-r1",
"alg": "rsa:2048",
"privateKey": "-----BEGIN PRIVATE KEY-----\nMIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDxAXgP2SjRPhKe\nO1OdLco7zsU+uMnvQFnTrc0W8eQ/vUGjP8HNABA3kKUeJZUGb4lyE5u62sBqD+Va\nOWh0tIRCIEPRC/tF3hTE5TeDJLJiY9N3R5P9OjWuFewnQFXIfTPqmrny1pYowfkd\nnbxBSzb/xTpk6K+yzkyrZdW1JvYdW/1CBGpo7qtfxflR3Cy13V15YDuVTD2rHUSj\nM2eYUU+b4HLoHvKZ87y18nwaOMOMMqbvp4xFoxckoE/XkuaHyH1UWI9HqCyFBrh+\nf24OPMP0N3qMCseXJc2CTBGSX4jKdB0WGqOpZdBxKWlKxLGlKAe9Ko1eYzUHdhhN\npBRmU4HzAgMBAAECggEAHRHhSoAWJU8Ibd+YEVBxoU8qiYs+iEZJz3eaUlcxAeMx\nJKDPHowQaLNgx0cfN5yChqkI0rwKE4EBWCWujM0tWtCLfY6la2MDPFCtpnrprWZ/\nHlca6aN40BvC1WU0M6+ucHDjVwA9MoNbKhBZocKRyr4ecgeDEd1CcDYjVetyKk4v\nTKIa7mvoNfRMT5dsmvUdRgtkvIaomLYoCVc7nK2d7C0WP/RaUWpJUUpZE+8lP3ze\no44HMMpeq+yyeXJhq6+PIErJfOChYJVjwOWCVJ99NRJ2RFU4kNu4gY2YcL6IRCV5\n6rfwsJwdKlLxTKVEZPCWVEa0TS+G4yQV8gu1LtvAwQKBgQD6Z5Hxw2R+bTFFyeOx\nMlDno8PvBlw4B3QrrWppk3f+m4261eSFdCMkZTZw81QjdGCJ/BTtMASaNWIWVyc1\nkslSg+ARPF5XEBEGpUmINRUotV9B7Wtq5Nid9xTlUoUPiuVVVU+eEvwTw8F/tgOu\nITwUM/uOYJdI16XfL4qtGxab0wKBgQD2ZCIbXK4BO5+8YC23YWymspTK/YShfoYA\nM8Ktxdp+xHGZoNzbx+mSd6vvvtWPhiayje2ppc82OsB+q6BYQOYTRowwdidWBETd\nM7/Q/QKg9Zn3kM+WA71KDtK3VIQBqZfYjevpTEqGjG9XN1apWZh80YeU3uhBuaSZ\nKns62AxNYQKBgAj8jpBOotymro4CoNlLJPwrNGzvnX+lRNYMczU2xaetjXiXFIx1\njo1P1JRZJzvegVhyY43fm0qtf8eteQrDKdZ8RR5ZPEmDmhjS9cCdpxS+7ZxAGQrN\nC7kflPBl9cCJC5H0bdcOd11+OQOMVLV7G9zdwLlrXgKPOrS30BJGVplhAoGAU+YM\n5xxL9AeFgPOPHZ6DDNBKckSZYRRgNLlrVRjGKdxiglmQWxZbppAxb9Wfitu3WZ2S\ni+31/RVMbtWqJ+MRdQbUvbu98UBK4re4XUWKG50F7JLW3NIxJoKdpeeVe6twFUFe\nT3a2+dHgJ+akD85+aiI+9KZil97K+YzJoWPn7IECgYB9O3ZiTlT3N3iuML+CCrv/\nEttS+1sWf1fdwq1Roosw3JWxuXC45KNn/lUsk0jvVJkMM/XDxG19E3NyltMWr2de\nj0o4TgFsOvXh6k1k7ftMwauFooAdIgkn9HPU7zwv7eAwWfOOxz57RvVnKKvcUq9F\nrELh+ivyqdpAYiJ1z4+0LA==\n-----END PRIVATE KEY-----\n",
"cert": "-----BEGIN CERTIFICATE-----\nMIIC/TCCAeWgAwIBAgIUDiCm76cjcg4Wd862cEzTzLqSzFswDQYJKoZIhvcNAQEL\nBQAwDjEMMAoGA1UEAwwDa2FzMB4XDTI0MTIxODIwMzUxNFoXDTI1MTIxODIwMzUx\nNFowDjEMMAoGA1UEAwwDa2FzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC\nAQEA8QF4D9ko0T4SnjtTnS3KO87FPrjJ70BZ063NFvHkP71Boz/BzQAQN5ClHiWV\nBm+JchObutrAag/lWjlodLSEQiBD0Qv7Rd4UxOU3gySyYmPTd0eT/To1rhXsJ0BV\nyH0z6pq58taWKMH5HZ28QUs2/8U6ZOivss5Mq2XVtSb2HVv9QgRqaO6rX8X5Udws\ntd1deWA7lUw9qx1EozNnmFFPm+By6B7ymfO8tfJ8GjjDjDKm76eMRaMXJKBP15Lm\nh8h9VFiPR6gshQa4fn9uDjzD9Dd6jArHlyXNgkwRkl+IynQdFhqjqWXQcSlpSsSx\npSgHvSqNXmM1B3YYTaQUZlOB8wIDAQABo1MwUTAdBgNVHQ4EFgQUVl6EWRsZE5kf\nXR6EC9LDStsR1howHwYDVR0jBBgwFoAUVl6EWRsZE5kfXR6EC9LDStsR1howDwYD\nVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAJysUw1bQkm+UdIWubPVo\nh/h1YoSHMEmwtphLflMDiJvm1GIjFM5zVgnpmkiI9DVCAs8vyhHe+UVCgiCAMqU9\nuu1jYxXY54v8nx+Ps3X1snylIs82JHKXT1AJaXECSi0DwIuF3hIyPUJpK9AJ/PqC\nOvhq3sMX5p0D3bmk8518rRwkSZ2a7jn5qvLa6P0g4Ph32j5UdRmgvsgh/jJk7PkK\nHuf86yZ4KbkgU6kMs4rTOLNIBmMJlm7R9xrGMVwK8X/NPZWV4fBNQZPIJw7svNzo\npe60OK4cT0G0/LHEOGxCLpmxjq2+xedKkrmq6PrRZquL386RyjkCZh6F5AWJCqB9\n4g==\n-----END CERTIFICATE-----\n"
}]
- name: Set up Python 3.12
uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b
with:
python-version: "3.12"
- uses: bufbuild/buf-setup-action@2211e06e8cf26d628cda2eea15c95f8c42b080b3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
- name: Set up JDK
uses: actions/setup-java@5896cecc08fd8a1fbdfaf517e29b571164b031f7
with:
java-version: "11"
distribution: "adopt"
server-id: github
- name: Set up Node 22
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af
with:
node-version: "22.x"
######### CHECKOUT JS CLI #############
- name: Configure js-sdk
uses: ./otdftests/xtest/setup-cli-tool
with:
path: otdftests/xtest/sdk
sdk: js
version-info: "${{ needs.resolve-versions.outputs.js }}"
######## SETUP THE JS CLI #############
- name: build and setup the web-sdk cli
id: build-web-sdk
run: |
make
working-directory: otdftests/xtest/sdk/js
######## CHECKOUT GO CLI #############
- name: Configure otdfctl
id: configure-go
uses: ./otdftests/xtest/setup-cli-tool
with:
path: otdftests/xtest/sdk
sdk: go
version-info: "${{ needs.resolve-versions.outputs.go }}"
- name: Resolve otdfctl heads
id: resolve-otdfctl-heads
run: |-
echo "OTDFCTL_HEADS=$OTDFCTL_HEADS" >> "$GITHUB_ENV"
env:
OTDFCTL_HEADS: ${{ steps.configure-go.outputs.heads }}
- name: Replace otdfctl go.mod packages, but only at head version of platform
if: env.FOCUS_SDK == 'go' && contains(fromJSON(needs.resolve-versions.outputs.heads), matrix.platform-tag)
run: |-
echo "Replacing go.mod packages..."
PLATFORM_DIR_ABS="$(pwd)/${{ steps.run-platform.outputs.platform-working-dir }}"
OTDFCTL_DIR_ABS="$(pwd)/otdftests/xtest/sdk/go/src/"
echo "PLATFORM_DIR_ABS: $PLATFORM_DIR_ABS"
echo "OTDFCTL_DIR_ABS: $OTDFCTL_DIR_ABS"
for head in $(echo "${OTDFCTL_HEADS}" | jq -r '.[]'); do
echo "Processing head: $head"
cd "${OTDFCTL_DIR_ABS}/$head"
for m in lib/fixtures lib/ocrypto protocol/go sdk; do
go mod edit -replace "github.com/opentdf/platform/$m=${PLATFORM_DIR_ABS}/$m"
done
go mod tidy
done
######## SETUP THE GO CLI #############
- name: Prepare go cli
run: |-
make
working-directory: otdftests/xtest/sdk/go
####### CHECKOUT JAVA SDK ##############
- name: Configure java-sdk
uses: ./otdftests/xtest/setup-cli-tool
with:
path: otdftests/xtest/sdk
sdk: java
version-info: "${{ needs.resolve-versions.outputs.java }}"
- name: pre-release protocol buffers for java-sdk
if: |
contains('["go", "java"]', env.FOCUS_SDK) && contains(fromJSON(needs.resolve-versions.outputs.heads), matrix.platform-tag)
run: |-
echo "Replacing .env files for java-sdk..."
echo "Platform tag: $platform_tag"
echo "Java version info: $java_version_info"
for row in $(echo "$java_version_info" | jq -c '.[]'); do
TAG=$(echo "$row" | jq -r '.tag')
HEAD=$(echo "$row" | jq -r '.head')
if [[ "$HEAD" == "true" ]]; then
echo "Creating .env file for tag: [$TAG]; pointing to [$platform_ref]"
echo "PLATFORM_BRANCH=$platform_tag" > "otdftests/xtest/sdk/java/${TAG}.env"
fi
done
env:
java_version_info: ${{ needs.resolve-versions.outputs.java }}
platform_ref: ${{ fromJSON(needs.resolve-versions.outputs.platform-tag-to-sha)[matrix.platform-tag] }}
platform_tag: ${{ matrix.platform-tag }}
####### SETUP JAVA CLI ##############
- name: Prepare java cli
run: |
make
env:
BUF_INPUT_HTTPS_USERNAME: opentdf-bot
BUF_INPUT_HTTPS_PASSWORD: ${{ secrets.PERSONAL_ACCESS_TOKEN_OPENTDF }}
working-directory: otdftests/xtest/sdk/java
######## Configure test environment #############
- name: Lookup current platform version
id: platform-version
run: |-
if ! go run ./service version; then
# NOTE: the version command was added in 0.4.37
echo "Error: Unable to get platform version; defaulting to tag: [$PLATFORM_TAG]"
echo "PLATFORM_VERSION=$PLATFORM_TAG" >> "$GITHUB_ENV"
exit
fi
# Older version commands output version to stderr; newer versions output to stdout
PLATFORM_VERSION=$(go run ./service version 2>&1)
echo "PLATFORM_VERSION=$PLATFORM_VERSION" >> "$GITHUB_ENV"
echo "## Platform version output: [$PLATFORM_VERSION]"
working-directory: ${{ steps.run-platform.outputs.platform-working-dir }}
env:
PLATFORM_TAG: ${{ matrix.platform-tag }}
- name: Install test dependencies
run: |-
pip install -r requirements.txt
working-directory: otdftests/xtest
- name: Validate xtest helper library (tests of the test harness and its utilities)
if: ${{ !inputs }}
run: |-
pytest test_nano.py test_self.py
working-directory: otdftests/xtest
######## RUN THE TESTS #############
- name: Run legacy decryption tests
run: |-
pytest -ra -v --focus "$FOCUS_SDK" test_legacy.py
working-directory: otdftests/xtest
env:
PLATFORM_DIR: "../../${{ steps.run-platform.outputs.platform-working-dir }}"
- name: Run all standard xtests
if: ${{ env.FOCUS_SDK == 'all' }}
run: |-
pytest -ra -v test_tdfs.py
working-directory: otdftests/xtest
env:
PLATFORM_DIR: "../../${{ steps.run-platform.outputs.platform-working-dir }}"
SCHEMA_FILE: "manifest.schema.json"
- name: Run xtests focusing on a specific SDK
if: ${{ env.FOCUS_SDK != 'all' }}
run: |-
pytest -ra -v --focus "$FOCUS_SDK" test_tdfs.py
working-directory: otdftests/xtest
env:
PLATFORM_DIR: "../../${{ steps.run-platform.outputs.platform-working-dir }}"
SCHEMA_FILE: "manifest.schema.json"
######## ATTRIBUTE BASED CONFIGURATION #############
- name: Does platform support multikas?
id: multikas
run: |-
if [[ $PLATFORM_TAG == main ]]; then
echo "Main supports multikas"
echo "supported=true" >> "$GITHUB_OUTPUT"
elif [[ $PLATFORM_VERSION =~ ^0\.[5-9]\.[0-9]+$ ]]; then
echo "Selected version [$PLATFORM_VERSION] supports multikas"
echo "supported=true" >> "$GITHUB_OUTPUT"
else
echo "At tag [$PLATFORM_TAG], [$PLATFORM_VERSION] probably does not support multikas"
echo "supported=false" >> "$GITHUB_OUTPUT"
fi
env:
PLATFORM_TAG: ${{ matrix.platform-tag }}
- name: Start additional kas
if: ${{ steps.multikas.outputs.supported == 'true' }}
uses: opentdf/platform/test/start-additional-kas@main
with:
ec-tdf-enabled: true
kas-port: 8181
kas-name: alpha
- name: Start additional kas
if: ${{ steps.multikas.outputs.supported == 'true' }}
uses: opentdf/platform/test/start-additional-kas@main
with:
ec-tdf-enabled: true
kas-port: 8282
kas-name: beta
- name: Start additional kas
if: ${{ steps.multikas.outputs.supported == 'true' }}
uses: opentdf/platform/test/start-additional-kas@main
with:
ec-tdf-enabled: true
kas-port: 8383
kas-name: gamma
- name: Start additional kas
if: ${{ steps.multikas.outputs.supported == 'true' }}
uses: opentdf/platform/test/start-additional-kas@main
with:
ec-tdf-enabled: true
kas-port: 8484
kas-name: delta
- name: Run attribute based configuration tests
if: ${{ steps.multikas.outputs.supported == 'true' }}
run: |-
pytest -ra -v --focus "$FOCUS_SDK" test_abac.py
working-directory: otdftests/xtest
env:
PLATFORM_DIR: "../../${{ steps.run-platform.outputs.platform-working-dir }}"