diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index a735b26..8f47f48 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -6,6 +6,7 @@ on: permissions: contents: read + id-token: write jobs: integration-tests: @@ -19,9 +20,8 @@ jobs: - name: Parse testing SDK branch from PR body id: parse run: | - BODY="${{ github.event.pull_request.body }}" # Look for a line like: TESTING_SDK_BRANCH: feature/foo - REF=$(printf "%s\n" "$BODY" | sed -n 's/^TESTING_SDK_BRANCH:[[:space:]]*//p' | head -n1) + REF=$(printf '%s\n' '${{ github.event.pull_request.body }}' | sed -n 's/^TESTING_SDK_BRANCH:[[:space:]]*//p' | head -n1) if [ -z "$REF" ]; then REF="main"; fi echo "testing_ref=$REF" >> "$GITHUB_OUTPUT" echo "Using testing SDK branch: $REF" @@ -60,3 +60,131 @@ jobs: hatch run test:cov hatch run test:examples hatch build + + e2e-tests: + needs: integration-tests + runs-on: ubuntu-latest + if: github.event_name == 'pull_request' + env: + AWS_REGION: us-west-2 + + steps: + - name: Parse testing SDK branch from PR body + id: parse + run: | + # Look for a line like: TESTING_SDK_BRANCH: feature/foo + REF=$(printf '%s\n' '${{ github.event.pull_request.body }}' | sed -n 's/^TESTING_SDK_BRANCH:[[:space:]]*//p' | head -n1) + if [ -z "$REF" ]; then REF="main"; fi + echo "testing_ref=$REF" >> "$GITHUB_OUTPUT" + echo "Using testing SDK branch: $REF" + + - name: Checkout Language SDK (this PR) + uses: actions/checkout@v5 + with: + path: language-sdk + + - name: Checkout Testing SDK + uses: actions/checkout@v5 + with: + repository: aws/aws-durable-execution-sdk-python-testing + ref: ${{ steps.parse.outputs.testing_ref }} + token: ${{ secrets.CROSS_REPO_PAT }} + path: testing-sdk + + - name: Set up Python 3.13 + uses: actions/setup-python@v6 + with: + python-version: '3.13' + + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: "${{ secrets.ACTIONS_INTEGRATION_ROLE_NAME }}" + role-session-name: languageSDKIntegrationTest + aws-region: ${{ env.AWS_REGION }} + + - name: Install custom Lambda model + working-directory: testing-sdk + run: | + aws configure add-model --service-model file://.github/model/lambda.json --service-name lambda + + - name: Install Hatch and setup Testing SDK + working-directory: testing-sdk + env: + AWS_DURABLE_SDK_URL: file://${{ github.workspace }}/language-sdk + run: | + pip install hatch + python -m pip install -e . + + - name: Get integration examples + id: get-examples + working-directory: testing-sdk/examples + run: | + echo "examples=$(jq -c '.examples | map(select(.integration == true)) | .[0:2]' examples-catalog.json)" >> $GITHUB_OUTPUT + + - name: Deploy and test examples + working-directory: testing-sdk + env: + AWS_DURABLE_SDK_URL: file://${{ github.workspace }}/language-sdk + AWS_ACCOUNT_ID: ${{ secrets.AWS_ACCOUNT_ID }} + LAMBDA_ENDPOINT: ${{ secrets.LAMBDA_ENDPOINT }} + INVOKE_ACCOUNT_ID: ${{ secrets.INVOKE_ACCOUNT_ID }} + KMS_KEY_ARN: ${{ secrets.KMS_KEY_ARN }} + run: | + echo "Building examples..." + hatch run examples:build + + # Get first integration example for testing + EXAMPLE_NAME=$(echo '${{ steps.get-examples.outputs.examples }}' | jq -r '.[0].name') + EXAMPLE_NAME_CLEAN=$(echo "$EXAMPLE_NAME" | sed 's/ //g') + FUNCTION_NAME="${EXAMPLE_NAME_CLEAN}-LanguageSDK-PR-${{ github.event.number }}" + + echo "Deploying example: $EXAMPLE_NAME as $FUNCTION_NAME" + hatch run examples:deploy "$EXAMPLE_NAME" --function-name "$FUNCTION_NAME" + + QUALIFIED_FUNCTION_NAME="$FUNCTION_NAME:\$LATEST" + + echo "Waiting for function to be ready..." + aws lambda wait function-active --function-name "$FUNCTION_NAME" --endpoint-url "$LAMBDA_ENDPOINT" --region "${{ env.AWS_REGION }}" + + echo "Invoking Lambda function: $QUALIFIED_FUNCTION_NAME" + aws lambda invoke \ + --function-name "$QUALIFIED_FUNCTION_NAME" \ + --cli-binary-format raw-in-base64-out \ + --payload '{"name": "World"}' \ + --region "${{ env.AWS_REGION }}" \ + --endpoint-url "$LAMBDA_ENDPOINT" \ + /tmp/response.json \ + > /tmp/invoke_response.json + + echo "Response:" + cat /tmp/response.json + + # Check for function errors + FUNCTION_ERROR=$(jq -r '.FunctionError // empty' /tmp/invoke_response.json) + if [ -n "$FUNCTION_ERROR" ]; then + echo "ERROR: Lambda function failed with error: $FUNCTION_ERROR" + cat /tmp/response.json + exit 1 + fi + + echo "Getting durable executions..." + aws lambda list-durable-executions-by-function \ + --function-name "$QUALIFIED_FUNCTION_NAME" \ + --statuses SUCCEEDED \ + --region "${{ env.AWS_REGION }}" \ + --endpoint-url "$LAMBDA_ENDPOINT" \ + --cli-binary-format raw-in-base64-out \ + > /tmp/executions.json + + echo "Durable Executions:" + cat /tmp/executions.json + + # Cleanup + echo "Cleaning up function: $FUNCTION_NAME" + aws lambda delete-function \ + --function-name "$FUNCTION_NAME" \ + --endpoint-url "$LAMBDA_ENDPOINT" \ + --region "${{ env.AWS_REGION }}" || echo "Function cleanup failed or already deleted" + +