Skip to content

build: pin javadoc copyright footer to avoid 1980 year #1064

build: pin javadoc copyright footer to avoid 1980 year

build: pin javadoc copyright footer to avoid 1980 year #1064

name: Conformance Tests
# Full-integration conformance run: builds the SDK + Java handlers, installs the
# pinned language-agnostic runner from PyPI, then deploys + invokes + validates
# one SAM stack per suite. Suites are discovered from the module's
# template_<suite>.yaml files (see conformance-tests/scripts/discover_suites.py)
# and each runs as its own parallel matrix job, so adding a suite only requires
# shipping its template + handlers under conformance-tests/.
on:
push:
branches: [main]
pull_request:
branches: [main]
paths:
- "sdk/**"
- "pom.xml"
- "conformance-tests/**"
- ".github/workflows/conformance-tests.yml"
workflow_dispatch:
concurrency:
# Runs share fixed per-suite stack names, so serialize the whole workflow
# with multiple pending runs to avoid concurrent CloudFormation updates on the
# same stack -- mirrors e2e-tests.yml.
group: conformance-tests
cancel-in-progress: false
queue: max
permissions:
contents: read
id-token: write # Required for AWS OIDC credentials
jobs:
discover_suites:
name: discover conformance suites
# 1. Run for non-PR events, such as scheduled runs and manual invocations
# 2. For PRs, run only same-repo branches from non-Dependabot actors; forked PRs or Dependabot should not access secrets.
# Skipping this job also skips the `conformance` matrix, which needs its output.
if: github.event_name != 'pull_request' || (github.actor != 'dependabot[bot]' && github.event.pull_request.head.repo.full_name == github.repository)
# Job is already gated to same-repo, non-Dependabot actors above, so fork
# code never runs here; use the plain CodeBuild runner label.
runs-on: ${{ format('codebuild-github-actions-runner-{0}-{1}', github.run_id, github.run_attempt) }}
outputs:
suites: ${{ steps.discover.outputs.suites }}
steps:
- name: Checkout repository
uses: actions/checkout@v7
- name: Discover suites from templates
id: discover
working-directory: conformance-tests
run: echo "suites=$(python3 scripts/discover_suites.py)" >> "$GITHUB_OUTPUT"
conformance:
name: conformance (${{ matrix.suite }})
needs: discover_suites
# discover_suites (its `needs`) is gated to same-repo, non-Dependabot actors,
# which also gates this matrix; use the plain CodeBuild runner label.
runs-on: ${{ format('codebuild-github-actions-runner-{0}-{1}', github.run_id, github.run_attempt) }}
env:
AWS_REGION: us-west-2
# The runner image ships /etc/pip.conf with `[global] target =
# /tmp/opt/python/site-packages` on PYTHONPATH; ignore both so the uv venv
# and the conformance runner install stay isolated.
PIP_CONFIG_FILE: /dev/null
PYTHONPATH: ""
strategy:
fail-fast: false
matrix:
suite: ${{ fromJSON(needs.discover_suites.outputs.suites) }}
defaults:
run:
working-directory: conformance-tests
steps:
- name: Checkout repository
uses: actions/checkout@v7
- name: Setup Java 21
uses: actions/setup-java@v6
with:
distribution: corretto
java-version: 21
cache: maven
- name: Setup AWS SAM CLI
uses: aws-actions/setup-sam@v3
with:
use-installer: true
- name: Build SDK and conformance handlers
working-directory: .
run: mvn -B -q -Dmaven.test.skip=true install --file pom.xml
- name: Setup Python
# The runner image is Amazon Linux; actions/setup-python only ships Ubuntu
# builds, so uv provides the Python 3.14 interpreter and activates a venv.
uses: astral-sh/setup-uv@07a047e608db84b3d8c06cd9a7c7dcc9c355c18e # v10.3.2
with:
python-version: "3.14"
activate-environment: true
- name: Install conformance runner
run: uv pip install "git+https://github.com/aws/aws-durable-execution-conformance-tests.git@main#subdirectory=packages/aws-durable-execution-conformance-tests"
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@e1253824e5c10ff9df46874f81ed3ec929e19cfd # v6.3.0
with:
# SAM-capable deploy role (has CloudFormation/S3/IAM), same role the
# SAM-based e2e tests assume.
role-to-assume: "${{ secrets.TEST_ROLE_ARN }}"
role-session-name: java-sdk-conformance-test
aws-region: ${{ env.AWS_REGION }}
allowed-account-ids: ${{ secrets.TEST_ACCOUNT_ID }}
- name: Inject Lambda execution role into template
env:
ROLE_ARN: ${{ secrets.TEST_LAMBDA_EXECUTION_ROLE_ARN }}
run: |
if [ -z "$ROLE_ARN" ]; then
echo "TEST_LAMBDA_EXECUTION_ROLE_ARN not set; template will create its own role."
exit 0
fi
# Point every function at the pre-existing execution role and drop the
# self-created DurableFunctionRole. Mutates only the CI checkout; the
# checked-in template stays self-contained for local runs.
python3 scripts/inject_execution_role.py \
--template template_${{ matrix.suite }}.yaml \
--role-arn "$ROLE_ARN"
- name: Compute stack-safe suite slug
run: |
# CloudFormation stack names allow only [a-zA-Z][-a-zA-Z0-9]*;
# suite names like wait_for_condition contain underscores.
echo "SUITE_SLUG=$(echo '${{ matrix.suite }}' | tr '_' '-')" >> "$GITHUB_ENV"
- name: Run conformance suite
run: |
# Stable per-suite stack name (no run-id suffix) + --no-cleanup:
# each run updates the same stack in place instead of creating and
# deleting a fresh one, which is faster and keeps resources warm.
python -m aws_durable_execution_conformance_tests.app \
--template template_${{ matrix.suite }}.yaml \
--language java \
--suite ${{ matrix.suite }} \
--name conformance-java-${SUITE_SLUG} \
--no-cleanup \
--region ${{ env.AWS_REGION }} \
--history-dir history-${{ matrix.suite }} \
--report console junit \
--report-file report-${{ matrix.suite }}
- name: Diagnose Logs Insights query
if: failure() && (matrix.suite == 'step' || matrix.suite == 'child')
run: |
if [[ "${{ matrix.suite }}" == "step" ]]; then
logical_id=StepLogging
test_id=1-7
else
logical_id=ChildPrintOnly
test_id=3-17
fi
physical_id=$(aws cloudformation describe-stack-resource \
--stack-name "conformance-tests-conformance-java-${SUITE_SLUG}" \
--logical-resource-id "$logical_id" \
--query "StackResourceDetail.PhysicalResourceId" \
--output text)
account_id=$(aws sts get-caller-identity --query Account --output text)
execution_name=$(jq -r '.Events[] | select(.EventType == "ExecutionStarted") | .Name' \
"history-${{ matrix.suite }}/${test_id}.json")
execution_id=$(jq -r '.Events[] | select(.EventType == "ExecutionStarted") | .Id' \
"history-${{ matrix.suite }}/${test_id}.json")
execution_arn="arn:aws:lambda:${AWS_REGION}:${account_id}:function:${physical_id}:\$LATEST/durable-execution/${execution_name}/${execution_id}"
log_group="/aws/lambda/${physical_id}"
start_time=$(date --date="10 minutes ago" +%s)
end_time=$(date +%s)
run_query() {
local label="$1"
local query="$2"
local query_id
local result
local status
query_id=$(aws logs start-query \
--log-group-name "$log_group" \
--start-time "$start_time" \
--end-time "$end_time" \
--query-string "$query" \
--query queryId \
--output text)
for _ in {1..20}; do
result=$(aws logs get-query-results --query-id "$query_id")
status=$(jq -r .status <<<"$result")
[[ "$status" == "Complete" ]] && break
sleep 0.5
done
jq -c --arg label "$label" '{
label: $label,
status: .status,
rows: (.results | length),
messages: [.results[] | map({key: .field, value: .value}) | from_entries | .["@message"]]
}' <<<"$result"
}
run_query "runner" \
"fields @timestamp, @message | filter coalesce(durableExecutionArn, executionArn) like \"${execution_arn}\""
run_query "equality" \
"fields @timestamp, @message | filter durableExecutionArn = \"${execution_arn}\" or executionArn = \"${execution_arn}\""
- name: Upload conformance report
if: always()
uses: actions/upload-artifact@v7
with:
name: conformance-report-${{ matrix.suite }}
path: |
conformance-tests/report-${{ matrix.suite }}.xml
conformance-tests/history-${{ matrix.suite }}/
if-no-files-found: warn