Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 4 additions & 1 deletion .github/workflows/all_plugins.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,9 @@ jobs:
- name: "Bootstrap Workspace"
run: melos bootstrap

- name: "Test scoped analysis selection"
run: bash ./.github/workflows/scripts/test-analyze-changed-packages.sh

- name: "Flutter Analyze"
run: melos run analyze
run: bash ./.github/workflows/scripts/analyze-changed-packages.sh

43 changes: 43 additions & 0 deletions .github/workflows/scripts/analyze-changed-packages.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#!/usr/bin/env bash
# Scope pull-request analysis to the affected plugin families. Pushes to main
# and changes outside packages/ still analyze the entire workspace.
set -euo pipefail

if [[ "${GITHUB_EVENT_NAME:-}" != "pull_request" ]]; then
exec melos run analyze
fi

if [[ -z "${GITHUB_BASE_REF:-}" ]]; then
echo 'GITHUB_BASE_REF is required for pull requests' >&2
exit 1
fi

changed_files="$(git diff --name-only "origin/${GITHUB_BASE_REF}...HEAD")"
packages=()
while IFS= read -r file; do
[[ -z "$file" ]] && continue
case "$file" in
packages/*/*)
family="${file#packages/}"
packages+=("${family%%/*}")
;;
*)
# Workspace configuration or CI changes may affect every package.
echo "Workspace file changed: $file. Analyzing all packages."
exec melos run analyze
;;
esac
done <<< "$changed_files"

if (( ${#packages[@]} == 0 )); then
echo 'No package changes to analyze.'
exit 0
fi

# Analyze every package in the changed plugin families, including their
# platform interfaces and examples, to catch issues across package boundaries.
while IFS= read -r family; do
[[ -z "$family" ]] && continue
echo "Analyzing ${family} packages"
melos exec -c 5 --scope="*${family}*" -- dart analyze . --fatal-infos
done < <(printf '%s\n' "${packages[@]}" | sort -u)
72 changes: 72 additions & 0 deletions .github/workflows/scripts/test-analyze-changed-packages.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT="$(cd "$(dirname "$0")" && pwd)/analyze-changed-packages.sh"
work="$(mktemp -d)"
trap 'rm -rf "$work"' EXIT
mkdir -p "$work/bin" "$work/repo"
cat > "$work/bin/melos" <<'MOCK'
#!/usr/bin/env bash
printf '%s\n' "$*" >> "$MELOS_CALLS"
MOCK
chmod +x "$work/bin/melos"
export PATH="$work/bin:$PATH"
export MELOS_CALLS="$work/calls"
cd "$work/repo"
git init -q -b main
git config user.email test@example.com
git config user.name Test
mkdir -p packages/share_plus/share_plus packages/device_info_plus/device_info_plus
printf 'old\n' > packages/share_plus/share_plus/foo.dart
printf 'old\n' > packages/device_info_plus/device_info_plus/foo.dart
git add .
git commit -qm base
git remote add origin .
git fetch -q origin main
git checkout -q -b feature
export GITHUB_EVENT_NAME=pull_request GITHUB_BASE_REF=main

assert_calls() {
local expected="$1"
local actual="$(cat "$MELOS_CALLS" 2>/dev/null || true)"
if [[ "$actual" != "$expected" ]]; then
printf 'Expected: %s\nActual: %s\n' "$expected" "$actual" >&2
exit 1
fi
}

# A single plugin family is analyzed; unrelated packages are skipped.
printf 'new\n' > packages/share_plus/share_plus/foo.dart
git add . && git commit -qm single
: > "$MELOS_CALLS"
bash "$SCRIPT"
assert_calls 'exec -c 5 --scope=*share_plus* -- dart analyze . --fatal-infos'

# Two plugin families produce exactly two invocations, sorted, without repeats.
printf 'newer\n' > packages/share_plus/share_plus/foo.dart
printf 'new\n' > packages/device_info_plus/device_info_plus/foo.dart
git add . && git commit -qm multiple
: > "$MELOS_CALLS"
bash "$SCRIPT"
assert_calls $'exec -c 5 --scope=*device_info_plus* -- dart analyze . --fatal-infos\nexec -c 5 --scope=*share_plus* -- dart analyze . --fatal-infos'

# A workspace config change requires complete analysis.
printf 'config\n' > analysis_options.yaml
git add . && git commit -qm global
: > "$MELOS_CALLS"
bash "$SCRIPT"
assert_calls 'run analyze'

# The push path retains complete analysis.
: > "$MELOS_CALLS"
GITHUB_EVENT_NAME=push bash "$SCRIPT"
assert_calls 'run analyze'

# Missing base is an error and cannot quietly pass CI.
: > "$MELOS_CALLS"
if GITHUB_BASE_REF='' bash "$SCRIPT" 2>/dev/null; then
echo 'Missing base incorrectly succeeded' >&2
exit 1
fi
assert_calls ''

echo 'PASS: scoped analysis, multi-family, workspace changes, pushes, and missing base'
Loading