Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
c2e4009
Setup periphery.yml
RafaelKayumov Jul 30, 2025
3210c1b
Adjust periphery.yml for local runs
RafaelKayumov Jul 30, 2025
0a9b0d2
Add baseline feature to ignore the snapshot of existing issues
RafaelKayumov Jul 30, 2025
f487cfe
git ignore Periphery install
RafaelKayumov Jul 30, 2025
d1f2151
Setup periphery run script
RafaelKayumov Jul 30, 2025
dcf8ac3
Move baseline json to Scripts/Periphery folder from root
RafaelKayumov Jul 30, 2025
b20a7a3
Add Periphery step in buildkite pipeline
RafaelKayumov Jul 30, 2025
75c27e7
Specify debug build config in build_for_testing lane
RafaelKayumov Jul 30, 2025
ffff651
Add skip job type check for Periphery
RafaelKayumov Jul 30, 2025
a2f2593
Add gh commit status for periphery
RafaelKayumov Jul 30, 2025
b6eef1c
Update artifact download
RafaelKayumov Jul 30, 2025
758a187
include Xcode Index Store in the build-products.tar artifact
RafaelKayumov Jul 30, 2025
ad13050
Exclude test targets
RafaelKayumov Jul 31, 2025
5f760a8
Remove unnecessary chmod
RafaelKayumov Jul 31, 2025
a3ded2e
Re-generate baseline
RafaelKayumov Aug 1, 2025
4b08069
Use quotes for path and version
RafaelKayumov Aug 6, 2025
7916cc4
Delete -xcconfig override from run_tests call
RafaelKayumov Aug 6, 2025
5f1c6f0
Add Periphery errors as Buildkite annotation
AliSoftware Aug 6, 2025
55fa528
Refactor setup-and-run-periphery.sh
AliSoftware Aug 6, 2025
0203b2f
🚧 TO REVERT: Introduce violations on purpose
AliSoftware Aug 6, 2025
92b4934
Revert "🚧 TO REVERT: Introduce violations on purpose"
AliSoftware Aug 6, 2025
147232e
Integrate periphery: add fancier reporting (#15984)
AliSoftware Aug 6, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .buildkite/commands/build-for-testing.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,5 @@ echo "--- :hammer_and_wrench: Building"
bundle exec fastlane build_for_testing

echo "--- :arrow_up: Upload Build Products"
tar -cf build-products.tar DerivedData/Build/Products/
tar -cf build-products.tar DerivedData/Build/Products/ DerivedData/Index.noindex/DataStore/
buildkite-agent artifact upload build-products.tar
44 changes: 44 additions & 0 deletions .buildkite/commands/run-periphery.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#!/bin/bash -eu

if .buildkite/commands/should-skip-job.sh --job-type validation; then
exit 0
fi

### Prepare

echo '--- 📦 Downloading Build Artifacts'
buildkite-agent artifact download build-products.tar .
tar -xf build-products.tar

### Run the Tests

PERIPHERY_OUTPUT_FILE="periphery-errors.txt"

echo '+++ :zombie: Detecting unused code'
set +e
# This is the script in the root.
./Scripts/Periphery/setup-and-run-periphery.sh \
--strict --quiet --skip-build --index-store-path 'DerivedData/Index.noindex/DataStore/' \
--write-results "$PERIPHERY_OUTPUT_FILE"
TESTS_EXIT_STATUS=$?
set -e

# Handle the result of the periphery scan
if [[ "$TESTS_EXIT_STATUS" -ne 0 ]]; then
echo '😱 Unused code detected!'
echo ''
echo '💡 You can run Periphery locally by calling `setup-and-run-periphery.sh` from `./Scripts/Periphery/` in the repo.'
echo ''
echo 'If you think there is a false positive violation, please check the known issues of Periphery at https://github.com/peripheryapp/periphery/issues.'
echo 'If you think a violation is valid but it should be surpressed for any reason, please apply the `// periphery: ignore - {your-reason-here}` comment.'
echo ''
# Add the periphery errors as a Buildkite annotation
(echo "### Periphery found unused code"; echo ''; echo '```'; cat "$PERIPHERY_OUTPUT_FILE"; echo ''; echo '```') \
| buildkite-agent annotate --context periphery --style error
else
echo '😊 No unused code found.'
buildkite-agent annotate --context periphery --style success 'No unused code found by Periphery :tada:'
fi

echo '--- 🚦 Report Exit code'
exit $TESTS_EXIT_STATUS
8 changes: 8 additions & 0 deletions .buildkite/pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,14 @@ steps:
agents:
queue: linter

- label: "🧟 Detect unused code"
command: ".buildkite/commands/run-periphery.sh"
depends_on: build
plugins: [$CI_TOOLKIT]
notify:
- github_commit_status:
context: Periphery - Detect unused code

- label: 🧹 Lint Translations
command: gplint /workdir/WooCommerce/Resources/AppStoreStrings.pot
plugins:
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,6 @@ WooCommerce/WooCommerceScreenshots/Mocks/vendor/
Modules/.build
Modules/.swiftpm/configuration/registries.json
Modules/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata

# Periphery install
vendor/Periphery/
68 changes: 68 additions & 0 deletions .periphery.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# This option tells Periphery to not report any Swift code as unused if it's accessible from Objective-C. This includes any class that inherits from NSObject, and any method or property marked with the @objc or @objcMembers attribute.
# Woocommerce-ios, is a mixed Swift and Objective-C project. Swift code is often called from Objective-C and vice-versa. Without this flag, Periphery would incorrectly flag Swift code that is only used by Objective-C parts of the app as "unused," which would be a false positive. Setting this to true is essential for getting accurate results in a mixed-language codebase.
retain_objc_accessible: true

# This option prevents Periphery from flagging unused parameters in protocol method implementations.
# Often, a protocol will define a method with parameters that are needed by some, but not all, conforming types. If a specific implementation doesn't need to use a parameter, Swift still requires that the method signature matches the protocol exactly. Periphery would normally see this unused parameter and flag it. However, removing it would cause a compile error because the method signature would no longer match the protocol. This flag tells Periphery to ignore these cases, avoiding false positives.
retain_unused_protocol_func_params: true

# This option retains all code within a previews struct that conforms to SwiftUI's PreviewProvider protocol.
# SwiftUI Previews are a powerful feature for UI development in Xcode. The code you write for previews is often not directly called from your main application target; it's used by Xcode's canvas. Periphery would see this and incorrectly mark the preview code as unused. This flag correctly tells Periphery to always keep preview provider code, which is the desired behavior.
retain_swift_ui_previews: true

# This option disables the check for public declarations that are only used within their own module.
# Normally, Periphery would suggest changing public to internal or private in these cases to reduce the public API surface of a module.
disable_redundant_public_analysis: false

# By default, Periphery will scan all targets in your project, including test targets.
# This can lead to false positives, as test code is not part of the main application.
# This option tells Periphery to exclude all test targets from the scan, ensuring that only the application code is analyzed.
exclude_tests: true

schemes:
- WooCommerce

project: WooCommerce.xcworkspace

# Used for local run by `periphery scan`
# This will not conflict with CI build configuration because of build skipping by `--skip-build` and `--index-store-path`
build_arguments:
- -xcconfig
- config/WooCommerce.debug.xcconfig

# A baseline is used to manage the large number of warnings from a mature codebase.
# It contains a snapshot of all "existing/acceptable" warnings. Periphery will ignore all
# warnings in this file, allowing you to focus on new issues in pull requests.
#
# After fixing existing warnings, regenerate this file with:
# periphery scan --write-baseline Scripts/Periphery/periphery_baseline.json
baseline: Scripts/Periphery/periphery_baseline.json

exclude_targets:
- GenerateCredentials
- WooCommerceScreenshots
- WordPressAuthenticator
- WordPressAuthenticatorTests
- WooCommerceTests
- WooCommerceUITests
- NotificationExtension
- StoreWidgetsExtension
- WatchWidgetsExtension
- "Woo Watch App"
- Fakes
- XcodeTarget_WooCommerceTests
- XcodeTarget_WooCommerceUITests
- XcodeTarget_WordPressAuthenticatorTests

index_exclude:
- Pods/*
- vendor/**
- BuildTools/.build/**
- "**/Tests/*"
- "**/Test*/*"
- "docs/*"
- "fastlane/*"
- "config/*"
- "**/*.xib"
- "**/*.storyboard"
- "**/*.generated.swift"
1 change: 1 addition & 0 deletions Scripts/Periphery/periphery_baseline.json

Large diffs are not rendered by default.

55 changes: 55 additions & 0 deletions Scripts/Periphery/setup-and-run-periphery.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#!/bin/bash

# Define the Periphery version
PERIPHERY_VERSION="3.2.0"

# Define the path to the periphery executable
REPO_ROOT="$(git rev-parse --show-toplevel)"
PERIPHERY_FOLDER_PATH="${REPO_ROOT}/vendor/Periphery"
PERIPHERY_PATH="${PERIPHERY_FOLDER_PATH}/periphery"

# Function to compare versions
version_gt() { test "$(printf '%s\n' "$@" | sort -V | head -n 1)" != "$1"; }

# Function to update and run Periphery
update_periphery() {
echo "Downloading version $PERIPHERY_VERSION..."
# Download the zip file
curl -L "https://github.com/peripheryapp/periphery/releases/download/${PERIPHERY_VERSION}/periphery-${PERIPHERY_VERSION}.zip" -o "periphery.zip"

# Create target directory if it doesn't exist
mkdir -p "$PERIPHERY_FOLDER_PATH"

# Unzip the contents directly into the target directory, overwriting files
unzip -o periphery.zip -d "$PERIPHERY_FOLDER_PATH"

# Clean up the zip file
rm periphery.zip

# Make sure the executable is executable
chmod +x "$PERIPHERY_PATH"

echo "Download and setup complete."
}

# Check if the executable exists and is executable
if [ -x "$PERIPHERY_PATH" ]; then
echo "Executable found. Checking version..."
# Get the current installed version
CURRENT_VERSION=$("$PERIPHERY_PATH" version)

# Compare the current version with the desired version
if version_gt "$PERIPHERY_VERSION" "$CURRENT_VERSION"; then
echo "Current version ($CURRENT_VERSION) is older than $PERIPHERY_VERSION. Updating..."
update_periphery
else
echo "Current version ($CURRENT_VERSION) is up-to-date."
fi
else
echo "Executable not found. Downloading..."
update_periphery
fi

echo "Running periphery scan..."
# Run periphery scan with additional arguments
"$PERIPHERY_PATH" scan --disable-update-check --relative-results "$@"