diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index 71c78d2..af6582b 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -17,20 +17,17 @@ jobs: python-version: ["3.13"] 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@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: path: language-sdk + - name: Parse testing SDK branch from PR body + id: parse + run: python language-sdk/ops/parse_sdk_branch.py + env: + PR_BODY: ${{ github.event.pull_request.body }} + - name: Checkout Testing SDK uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: @@ -67,22 +64,19 @@ jobs: 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" + steps: - name: Checkout Language SDK (this PR) uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: path: language-sdk + - name: Parse testing SDK branch from PR body + id: parse + run: python language-sdk/ops/parse_sdk_branch.py + env: + PR_BODY: ${{ github.event.pull_request.body }} + - name: Checkout Testing SDK uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: @@ -133,20 +127,20 @@ jobs: 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" \ @@ -156,10 +150,10 @@ jobs: --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 @@ -167,7 +161,7 @@ jobs: cat /tmp/response.json exit 1 fi - + echo "Getting durable executions..." aws lambda list-durable-executions-by-function \ --function-name "$QUALIFIED_FUNCTION_NAME" \ @@ -176,15 +170,13 @@ jobs: --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" - - diff --git a/.github/workflows/test-parser.yml b/.github/workflows/test-parser.yml new file mode 100644 index 0000000..3d45360 --- /dev/null +++ b/.github/workflows/test-parser.yml @@ -0,0 +1,21 @@ +name: Test Parser + +on: + pull_request: + paths: + - 'ops/parse_sdk_branch.py' + - 'ops/__tests__/**' + push: + branches: [ main ] + paths: + - 'ops/parse_sdk_branch.py' + - 'ops/__tests__/**' + +jobs: + test-parser: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + + - name: Run parser tests + run: python ops/__tests__/test_parse_sdk_branch.py diff --git a/ops/__tests__/test_parse_sdk_branch.py b/ops/__tests__/test_parse_sdk_branch.py new file mode 100755 index 0000000..cdae4bc --- /dev/null +++ b/ops/__tests__/test_parse_sdk_branch.py @@ -0,0 +1,84 @@ +#!/usr/bin/env python3 + +import os +import sys + +sys.path.insert(0, os.path.dirname(os.path.dirname(__file__))) + +from parse_sdk_branch import parse_sdk_branch + + +def test_parse_sdk_branch(): + test_cases = [ + # Basic cases + ("TESTING_SDK_BRANCH = feature/test", "feature/test"), + ("TESTING_SDK_BRANCH: feature/test", "feature/test"), + ("TESTING_SDK_BRANCH=feature/test", "feature/test"), + ("testing_sdk_branch: feature/test", "feature/test"), + # Complex PR body with backticks and contractions + ( + """Updated the script to safely parse the testing SDK branch from the PR body, handling case insensitivity and whitespace. + +The goal here is to fix the usage of backticks such as in `foo`, and contractions that we've been using such as `we've` + +``` +plus of course the usage of multiple backticks to include code +``` + +TESTING_SDK_BRANCH = main + +By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.""", + "main", + ), + # Edge cases with markdown and special characters + ( + """# PR Title + +Some `code` and we've got contractions here. + +```python +def test(): + return "test" +``` + +TESTING_SDK_BRANCH: feature/fix-backticks + +More text with `inline code` and don't forget contractions.""", + "feature/fix-backticks", + ), + # Multiple occurrences (should take first) + ( + """TESTING_SDK_BRANCH = first-branch + +Some text here. + +TESTING_SDK_BRANCH = second-branch""", + "first-branch", + ), + # Whitespace variations + (" TESTING_SDK_BRANCH = feature/spaces ", "feature/spaces"), + ("TESTING_SDK_BRANCH:feature/no-space", "feature/no-space"), + # Default cases + ("No branch specified", "main"), + ("", "main"), + ("Just some random text", "main"), + # Case with backticks in branch name + ("TESTING_SDK_BRANCH = feature/fix-`backticks`", "feature/fix-`backticks`"), + # Case with contractions in surrounding text + ( + "We've updated this and TESTING_SDK_BRANCH = feature/test and we're done", + "feature/test", + ), + ] + + for input_text, expected in test_cases: + result = parse_sdk_branch(input_text) + if result != expected: + return False + + return True + + +if __name__ == "__main__": + success = test_parse_sdk_branch() + sys.exit(0 if success else 1) diff --git a/ops/parse_sdk_branch.py b/ops/parse_sdk_branch.py new file mode 100755 index 0000000..1967085 --- /dev/null +++ b/ops/parse_sdk_branch.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python3 + +import os +import re + + +def parse_sdk_branch(pr_body: str, default_ref: str = "main") -> str: + """Parse PR body for TESTING_SDK_BRANCH and return the branch reference.""" + pattern = re.compile(r"(?i)TESTING_SDK_BRANCH\s*[:=]\s*(\S+)", re.MULTILINE) + + match = pattern.search(pr_body) + if match: + ref = match.group(1).strip() + if ref: + return ref + + return default_ref + + +def main(): + pr_body = os.environ.get("PR_BODY", "") + ref = parse_sdk_branch(pr_body) + + github_output = os.environ.get("GITHUB_OUTPUT") + if github_output: + with open(github_output, "a", encoding="utf-8") as f: + f.write(f"testing_ref={ref}\n") + + +if __name__ == "__main__": + main()