-
Notifications
You must be signed in to change notification settings - Fork 216
chore: Add API Breakage Checking GitHub Action #3753
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 31 commits
Commits
Show all changes
40 commits
Select commit
Hold shift + click to select a range
05794ac
Add API Checkers
rozaychen 8e7a11a
Add Test API Dumps Files
rozaychen ca82873
Merge branch 'main' of https://github.com/rozaychen/amplify-swift
rozaychen bacf67c
Update apiBreakTest.yml
rozaychen 0e45bdb
Add Test
rozaychen 45bfa5b
Revert "Add Test"
rozaychen b842214
Update apiBreakTest.yml
rozaychen a916b78
Update check_api_breakage.sh
rozaychen bdb9b74
Update apiBreakTest.yml
rozaychen b10d30f
Update apiBreakTest.yml
rozaychen ce3b1b8
Update apiBreakTest.yml
rozaychen b9420f3
Update apiBreakTest.yml
rozaychen c89c0dd
Update apiBreakTest.yml
rozaychen b1df401
Update apiBreakTest.yml
rozaychen 59db256
Merge pull request #3751 from rozaychen/main
rozaychen 0cac0c3
Update apiBreakTest.yml
rozaychen 213b0ab
Update API dumps for new version
github-actions[bot] 32ea7de
Update APIDigesterCheck.yml
rozaychen 3d17366
Update apiBreakTest.yml
rozaychen c13b808
Update APIDigesterCheck.yml
rozaychen be150ed
Update API dumps for new version
github-actions[bot] ee20d60
Update APIDigesterCheck.yml
rozaychen 6faf7d6
Update API dumps for new version
github-actions[bot] df113d5
Auto-send Slack Message when Check Failed
rozaychen 2bff924
Update API dumps for new version
github-actions[bot] 26220b3
Use aws-amplify-ops for committing
rozaychen c0ffb41
Update API dumps for new version
aws-amplify-ops c7db8f2
Update apiBreakTest.yml
rozaychen 8668033
Update CODEOWNERS
rozaychen 3d6a9ba
Update apiBreakTest.yml to remove review adding function
rozaychen 2895f35
Enabling Configurable Exceptions
rozaychen 1c0d802
Update CODEOWNERS
rozaychen 4d45785
Rename APIDigesterCheck.yml to api_digester_check.yml
rozaychen 6d6ad03
Update api_digester_check.yml
rozaychen 0659b85
Update api_digester_check.yml
rozaychen a640f08
Update and rename apiBreakTest.yml to api-breaking-changes-detection.yml
rozaychen e6c0aad
Rename check_api_breakage.sh to CircleciScripts/check_api_breakage.sh
rozaychen c3e9044
Update api-breaking-changes-detection.yml
rozaychen 421d7a4
Update API dumps for new version
aws-amplify-ops 2c8441f
Merge branch 'main' into feat/api-breakage-checker
rozaychen File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
name: Swift API Digester Functionality Check | ||
rozaychen marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
on: | ||
schedule: | ||
- cron: '0 0 * * *' # This will run the action every night at midnight | ||
rozaychen marked this conversation as resolved.
Show resolved
Hide resolved
|
||
workflow_dispatch: # Allows manual triggering | ||
|
||
jobs: | ||
check-swift-api-digester: | ||
runs-on: macos-latest | ||
|
||
steps: | ||
- name: Checkout repository | ||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 #v4.1.1 | ||
with: | ||
fetch-depth: 0 | ||
rozaychen marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
|
||
- name: Check API Digester | ||
shell: bash | ||
env: | ||
WEBHOOK_URL: ${{ secrets.SLACK_API_CHECKER_WEBHOOK_URL }} | ||
run: | | ||
TEMP_DIR=$(mktemp -d) | ||
echo "Temporary directory created at $TEMP_DIR" | ||
SDK_PATH=$(xcrun --sdk macosx --show-sdk-path) | ||
echo "SDK Path: $SDK_PATH" | ||
|
||
# Run swift-api-digester | ||
swift api-digester -sdk "$SDK_PATH" -diagnose-sdk --input-paths api-dump-test/A.json --input-paths api-dump-test/B.json >> "$TEMP_DIR/api-digester-output.txt" 2>&1 | ||
|
||
# Display the output | ||
cat "$TEMP_DIR/api-digester-output.txt" | ||
|
||
if diff "$TEMP_DIR/api-digester-output.txt" api-dump-test/expected-result.txt; then | ||
echo "The output matches the expected result." | ||
else | ||
echo "The output does not match the expected result." | ||
rozaychen marked this conversation as resolved.
Show resolved
Hide resolved
|
||
WORKFLOW_URL="https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" | ||
echo "$WORKFLOW_URL" | xargs -I {} curl -s POST "$WEBHOOK_URL" -H "Content-Type:application/json" --data '{"WORKFLOW_URL":"{}"}' | ||
exit 1 | ||
fi |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,216 @@ | ||
name: Public Interface Breakage Detection | ||
rozaychen marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
on: | ||
pull_request: | ||
|
||
permissions: | ||
contents: write | ||
pull-requests: write | ||
|
||
jobs: | ||
buildAndCheckAPIBreakage: | ||
rozaychen marked this conversation as resolved.
Show resolved
Hide resolved
|
||
name: Build and Check API Breakage | ||
runs-on: macos-latest | ||
|
||
steps: | ||
- name: Checkout repository | ||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 #v4.1.1 | ||
with: | ||
fetch-depth: 0 | ||
rozaychen marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
|
||
- name: Setup and Run Swift API Diff | ||
env: | ||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
run: | | ||
# Define the list of exceptions to filter out | ||
exceptions=( | ||
'has been added as a new enum case$' | ||
'is now with @_spi$' | ||
) | ||
|
||
# Define the mandatory patterns to filter out | ||
mandatory_patterns=( | ||
'^/\*' | ||
'^$' | ||
) | ||
|
||
# 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 | ||
rozaychen marked this conversation as resolved.
Show resolved
Hide resolved
rozaychen marked this conversation as resolved.
Show resolved
Hide resolved
|
||
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 | ||
|
||
# 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 | ||
echo -e "$api_diff_output" >> $GITHUB_ENV | ||
echo "EOF" >> $GITHUB_ENV | ||
else | ||
echo "### ✅ No Public API Breaking Change detected" >> $GITHUB_ENV | ||
echo "EOF" >> $GITHUB_ENV | ||
fi | ||
|
||
# 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 | ||
git commit -m "Update API dumps for new version" | ||
git push origin HEAD:${{ github.head_ref }} | ||
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 | ||
|
||
- name: Comment on PR with API Diff | ||
uses: actions/github-script@v6 | ||
rozaychen marked this conversation as resolved.
Show resolved
Hide resolved
|
||
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."); | ||
} | ||
|
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.