Skip to content

Test outdated

Test outdated #13

name: Public Interface Breakage Detection
on:
pull_request:
permissions:
contents: write
pull-requests: write
jobs:
buildAndCheckAPIBreakage:
name: Build and Check API Breakage
runs-on: macos-latest
steps:
- name: Checkout repository
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 #v4.1.1
with:
ref: ${{ github.head_ref }} # Checkout the PR branch
fetch-depth: 1
- name: Fetch the branchs
run: |
git fetch origin ${{ github.sha }}
- name: Check if branch is up-to-date with reference branch
id: check-up-to-date
run: |
git fetch origin ${{ github.event.pull_request.base.ref }}
if git merge-base --is-ancestor origin/${{ github.event.pull_request.base.ref }} HEAD; then
echo "is_up_to_date=true" >> $GITHUB_ENV
else
echo "is_up_to_date=false" >> $GITHUB_ENV
fi
- name: Setup and Run Swift API Diff
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
# Define the mandatory patterns to filter out
mandatory_patterns=(
'^/\*'
'^$'
)
# Define the list of exceptions to filter out
exceptions=(
'has been added as a new enum case$'
'is now with @_spi$'
)
# Function to apply patterns with grep
apply_patterns() {
local input="$1"
local output="$input"
# Apply mandatory patterns
for pattern in "${mandatory_patterns[@]}"; do
output=$(echo "$output" | grep -v "$pattern")
done
# Apply exceptions
for exception in "${exceptions[@]}"; do
output=$(echo "$output" | grep -v "$exception")
done
echo "$output"
}
echo "Swift version: $(swift --version)"
echo "Swift package manager version: $(swift package --version)"
swift package resolve
# Ensure we are in the correct directory
cd $GITHUB_WORKSPACE
# Run swift-api-diff commands here directly
NEW_API_DIR=$(mktemp -d)
OLD_API_DIR=$(mktemp -d)
SDK_PATH=$(xcrun --show-sdk-path)
# Get all library module names
modules=$(swift package dump-package | jq -r '.products | map(select(.name == "Amplify" or .name == "CoreMLPredictionsPlugin" or .name == "AWSDataStorePlugin" or .name == "AWSPluginsCore")) | map(.name) | .[]')
echo "Modules: $modules"
echo "Fetching old version..."
git checkout ${{ github.event.pull_request.base.sha }}
built=false
for module in $modules; do
# If file doesn't exits in the old directory
if [ ! -f api-dump/${module}.json ]; then
echo "Old API file does not exist in the base branch. Generating it..."
# Check if the project has been built
if ! $built; then
echo "Building project..."
swift build > /dev/null 2>&1 || { echo "Failed to build project"; exit 1; }
built=true
fi
# Generate the API file using api-digester
swift api-digester -sdk "$SDK_PATH" -dump-sdk -module "$module" -o "$OLD_API_DIR/${module}.json" -I .build/debug || { echo "Failed to dump new SDK for module $module"; exit 1; }
else
# Use the api-dump/${module}.json file from the base branch directly
cp "api-dump/${module}.json" "$OLD_API_DIR/${module}.json"
fi
done
echo "Fetching new version..."
git checkout ${{ github.sha }}
git log -1 # Print the commit info for debugging
swift build> /dev/null 2>&1 || { echo "Failed to build new version"; exit 1; }
for module in $modules; do
swift api-digester -sdk "$SDK_PATH" -dump-sdk -module "$module" -o "$NEW_API_DIR/${module}.json" -I .build/debug || { echo "Failed to dump new SDK for module $module"; exit 1; }
done
# Checkout to the branch associated with the pull request
git stash --include-untracked
git checkout ${{ github.head_ref }}
if [ ! -d "api-dump" ]; then
echo "api-dump folder does not exist. Creating it..."
mkdir -p "api-dump"
fi
# Update the api-dump folder of the new version by making a commit if there are changes
for module in $modules; do
if [ ! -f api-dump/${module}.json ]; then
echo "API file does not exist in api-dump folder. Creating it..."
echo "{}" > "api-dump/${module}.json"
fi
if ! diff "$NEW_API_DIR/${module}.json" "api-dump/${module}.json" > /dev/null; then
echo "Updating API Dumps..."
mv "$NEW_API_DIR/${module}.json" "api-dump/${module}.json"
fi
done
git config --global user.name "aws-amplify-ops"
git config --global user.email "aws-amplify@amazon.com"
git add api-dump/*.json
if ! git diff --cached --quiet --exit-code; then
# Get the file names that have changes
changed_files=$(git diff --cached --name-only)
push_changes=false
for file in $changed_files; do
if [[ $file == api-dump/* ]]; then
# Get the number of lines in the file
total_lines=$(wc -l < "$file")
# Get the line numbers of the changes
changed_lines=$(git diff --cached -U0 "$file" | grep -o '@@ [^ ]* [^ ]* @@' | awk '{print $3}' | cut -d ',' -f1 | sed 's/[^0-9]//g')
echo "Changed lines in $file: $changed_lines"
# Check if any change is not within the last 10 lines
for line in $changed_lines; do
if [ "$line" -le "$((total_lines - 10))" ]; then
push_changes=true
break
fi
done
# If any file should be pushed, break out of the loop
if [ "$push_changes" = true ]; then
break
fi
fi
done
if [ "$push_changes" = true ]; then
if [ "$is_up_to_date" = "true" ]; then
git commit -m "Update API dumps for new version"
git push origin HEAD:${{ github.head_ref }}
else
echo "Branch is not up-to-date with main. Skipping
else
echo "No changes to commit in the api-dump folder."
fi
else
echo "No changes to commit in the api-dump folder."
fi
git stash pop || true
# Compare APIs for each module and capture the output
api_diff_output=""
for module in $modules; do
swift api-digester -sdk "$SDK_PATH" -diagnose-sdk --input-paths "$OLD_API_DIR/${module}.json" --input-paths "$NEW_API_DIR/${module}.json" >> "api-diff-report-${module}.txt" 2>&1
module_diff_output=$(apply_patterns "$(cat "api-diff-report-${module}.txt")")
if [ -n "$module_diff_output" ]; then
api_diff_output="${api_diff_output}\n**Module: ${module}**\n${module_diff_output}\n"
# Check if there are lines containing "has been renamed to Func"
if echo "$module_diff_output" | grep -q 'has been renamed to Func'; then
# Capture the line containing "has been renamed to Func"
renamed_line=$(echo "$module_diff_output" | grep 'has been renamed to Func')
# Append a message to the module_diff_output
api_diff_output="${api_diff_output}👉🏻 _Note: If you're just adding optional parameters to existing methods, neglect the line:_\n_${renamed_line}_\n"
fi
fi
done
echo "API_DIFF_OUTPUT<<EOF" >> $GITHUB_ENV
if [ -n "$api_diff_output" ]; then
echo "### 💔 Public API Breaking Change detected:" >> $GITHUB_ENV
if [ "$is_up_to_date" = "false" ]; then
api_diff_output="${api_diff_output}❗️ _Warning: Your branch is not up to date with the reference branch. Please ensure your branch is updated to avoid potential conflicts and ensure accurate API change detection._"
echo -e "$api_diff_output" >> $GITHUB_ENV
echo "EOF" >> $GITHUB_ENV
exit 1
fi
echo -e "$api_diff_output" >> $GITHUB_ENV
echo "EOF" >> $GITHUB_ENV
else
echo "### ✅ No Public API Breaking Change detected" >> $GITHUB_ENV
if [ "$is_up_to_date" = "false" ] && [ "$push_changes" = true ]; then
echo "❗️ _Warning: Your branch is not up to date with the reference branch. The API file can not successfully updated."
echo "EOF" >> $GITHUB_ENV
exit 1
fi
echo "EOF" >> $GITHUB_ENV
fi
- name: Comment on PR with API Diff
uses: actions/github-script@v6
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const apiDiffOutput = process.env.API_DIFF_OUTPUT;
const issueNumber = context.payload.pull_request.number;
const owner = context.repo.owner;
const repo = context.repo.repo;
if (apiDiffOutput && apiDiffOutput.trim().length > 0) {
github.rest.issues.createComment({
owner: owner,
repo: repo,
issue_number: issueNumber,
body: `## API Breakage Report\n${apiDiffOutput}\n`
});
} else {
console.log("No API diff output found.");
}