diff --git a/.github/workflows/mixed-version-compatibility-review.yml b/.github/workflows/mixed-version-compatibility-review.yml new file mode 100644 index 000000000000..548d4b530737 --- /dev/null +++ b/.github/workflows/mixed-version-compatibility-review.yml @@ -0,0 +1,104 @@ +name: Mixed Version Compatibility Review + +permissions: + contents: read + pull-requests: read + +on: + merge_group: + pull_request: + types: [ opened, synchronize, reopened, labeled, unlabeled ] + branches: + - master + +jobs: + mixed-version-compatibility-check: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Check for mixed version compatibility risks + id: compatibility-check + run: | + git fetch origin ${{ github.base_ref }} --depth 1 + + # Define the specific base class files that are risky for mixed versions + BASE_CLASS_FILES="core/aws-core/src/main/java/software/amazon/awssdk/awscore/AwsRequest.java + core/aws-core/src/main/java/software/amazon/awssdk/awscore/AwsResponse.java + core/aws-core/src/main/java/software/amazon/awssdk/awscore/AwsResponseMetadata.java + core/aws-core/src/main/java/software/amazon/awssdk/awscore/exception/AwsServiceException.java + core/sdk-core/src/main/java/software/amazon/awssdk/core/SdkPojo.java" + + # Check if any of the base class files were modified + CHANGED_BASE_FILES=$(git diff --name-only remotes/origin/${{ github.base_ref }} -- $BASE_CLASS_FILES || true) + + if [ -z "$CHANGED_BASE_FILES" ]; then + echo "No base class changes detected." + echo "has_risk=false" >> $GITHUB_OUTPUT + exit 0 + fi + + echo "Base class changes detected in:" + echo "$CHANGED_BASE_FILES" + + # Look for new public methods in the changed base class files + # Filter out obvious false positives: comments, string literals, javadoc + NEW_METHODS=$(git diff remotes/origin/${{ github.base_ref }} -- $BASE_CLASS_FILES | \ + + grep '^+.*public.*(' | \ # Find lines with new public methods + grep -v '^+[[:space:]]*//.*' | \ # Line comments + grep -v '^+[[:space:]]*\*.*' | \ # Javadoc lines + grep -v '^+[[:space:]]*/\*.*' || true # Block comments + + if [ -n "$NEW_METHODS" ]; then + echo "::warning::New public methods detected in base classes:" + echo "$NEW_METHODS" | while read line; do + echo "::warning::$line" + done + echo "has_risk=true" >> $GITHUB_OUTPUT + echo "risk_type=new_methods" >> $GITHUB_OUTPUT + else + echo "::warning::Base class files modified but no new public methods detected" + echo "has_risk=true" >> $GITHUB_OUTPUT + echo "risk_type=other_changes" >> $GITHUB_OUTPUT + fi + + - name: Fail if compatibility risks found without approval + if: ${{ steps.compatibility-check.outputs.has_risk == 'true' && !contains(github.event.pull_request.labels.*.name, 'mixed-version-compatibility-reviewed') }} + run: | + # Define the base class files + BASE_CLASS_FILES="core/aws-core/src/main/java/software/amazon/awssdk/awscore/AwsRequest.java + core/aws-core/src/main/java/software/amazon/awssdk/awscore/AwsResponse.java + core/aws-core/src/main/java/software/amazon/awssdk/awscore/AwsResponseMetadata.java + core/aws-core/src/main/java/software/amazon/awssdk/awscore/exception/AwsServiceException.java + core/sdk-core/src/main/java/software/amazon/awssdk/core/SdkPojo.java" + + # Extract class names from the actually changed files + CHANGED_BASE_FILES=$(git diff --name-only remotes/origin/${{ github.base_ref }} -- $BASE_CLASS_FILES || true) + CHANGED_CLASS_NAMES=$(echo "$CHANGED_BASE_FILES" | sed 's|.*/||' | sed 's|\.java||' | paste -sd ',' - | sed 's/,/, /g') + + echo "::error::Mixed version compatibility risk detected!" + echo "::error::Changes were made to base classes that generated service code implements:" + echo "::error::- $CHANGED_CLASS_NAMES" + echo "::error::" + echo "::error::This may break customers using mixed SDK versions if:" + echo "::error::- New methods are added with UnsupportedOperationException defaults" + echo "::error::- Core behavior changes invoke existing methods in new ways" + echo "::error::- Interface contracts change in subtle ways" + echo "::error::" + echo "::error::Please review with the team for mixed version impact and add" + echo "::error::'mixed-version-compatibility-reviewed' label after approval." + echo "::error::" + echo "::error::If this introduces compatibility issues, consider:" + echo "::error::- Bumping minor version" + echo "::error::- Documenting compatibility impact in release notes" + echo "::error::- Ensuring older service modules can handle the changes" + exit 1 + + - name: Success message when approved + if: ${{ steps.compatibility-check.outputs.has_risk == 'true' && contains(github.event.pull_request.labels.*.name, 'mixed-version-compatibility-reviewed') }} + run: | + echo "✅ Mixed version compatibility risk detected but approved for merge" + echo "Base class changes have been reviewed and approved by the team" \ No newline at end of file