Files
dingtalk-workspace-cli/scripts/ci/changed-test-packages.sh
T

137 lines
4.1 KiB
Bash
Executable File

#!/bin/sh
# Copyright 2026 Alibaba Group
# Licensed under the Apache License, Version 2.0 (the "License");
set -eu
ROOT="$(CDPATH= cd -- "$(dirname -- "$0")/../.." && pwd)"
usage() {
printf '%s\n' "usage: $0 <changed|list> BASE_REF HEAD_REF" >&2
exit 2
}
[ "${1:-}" = changed ] || [ "${1:-}" = list ] || usage
[ "$#" -eq 3 ] || usage
MODE="$1"
BASE_REF="$2"
HEAD_REF="$3"
cd "$ROOT"
git rev-parse --verify --quiet "${BASE_REF}^{commit}" >/dev/null || {
printf 'changed test package base is not a commit: %s\n' "$BASE_REF" >&2
exit 2
}
git rev-parse --verify --quiet "${HEAD_REF}^{commit}" >/dev/null || {
printf 'changed test package head is not a commit: %s\n' "$HEAD_REF" >&2
exit 2
}
resolved_head="$(git rev-parse "${HEAD_REF}^{commit}")"
current_head="$(git rev-parse HEAD)"
[ "$current_head" = "$resolved_head" ] || {
printf 'changed test package head does not match the checked-out revision: expected %s, got %s\n' \
"$resolved_head" "$current_head" >&2
exit 2
}
git diff --quiet HEAD -- && git diff --cached --quiet HEAD -- || {
printf '%s\n' 'changed test package planning requires a clean tracked worktree' >&2
exit 2
}
workdir="$(mktemp -d "${TMPDIR:-/tmp}/dws-changed-packages.XXXXXX")"
trap 'rm -rf "$workdir"' EXIT HUP INT TERM
files="$workdir/files"
changed_packages="$workdir/changed-packages"
impacted_packages="$workdir/impacted-packages"
all_packages="$workdir/all-packages"
package_dependencies="$workdir/package-dependencies"
embed_owners="$workdir/embed-owners"
: > "$changed_packages"
: > "$impacted_packages"
git diff --no-ext-diff --find-renames --name-only \
--diff-filter=ACMRD "$BASE_REF" "$HEAD_REF" > "$files"
if ! go list ./... > "$all_packages"; then
printf '%s\n' 'failed to resolve the module package graph' >&2
exit 1
fi
if ! go list -f \
'{{- $import := .ImportPath -}}{{- $dir := .Dir -}}{{- range .EmbedFiles }}{{$import}}|{{$dir}}|{{.}}{{"\n"}}{{- end -}}{{- range .TestEmbedFiles }}{{$import}}|{{$dir}}|{{.}}{{"\n"}}{{- end -}}{{- range .XTestEmbedFiles }}{{$import}}|{{$dir}}|{{.}}{{"\n"}}{{- end -}}' \
./... > "$embed_owners"; then
printf '%s\n' 'failed to resolve embedded file ownership' >&2
exit 1
fi
while IFS= read -r file; do
[ -n "$file" ] || continue
case "$file" in
CHANGELOG.md|README.md|README_zh.md|CONTRIBUTING.md|SECURITY.md|\
CODE_OF_CONDUCT.md|LICENSE|NOTICE|docs/*|\
.github/PULL_REQUEST_TEMPLATE.md|.github/ISSUE_TEMPLATE/*)
continue
;;
esac
directory="$(dirname "$file")"
if [ "$directory" = . ]; then
pattern=.
else
pattern="./$directory"
fi
if [ -d "$directory" ]; then
has_go_files=false
for go_file in "$directory"/*.go; do
if [ -f "$go_file" ]; then
has_go_files=true
break
fi
done
if [ "$has_go_files" = true ]; then
if ! package="$(go list -f '{{.ImportPath}}' "$pattern")"; then
printf 'failed to resolve changed Go package: %s\n' "$directory" >&2
exit 1
fi
printf '%s\n' "$package" >> "$changed_packages"
continue
fi
fi
embedded_owner_found=false
while IFS='|' read -r package package_dir embedded_file; do
[ -n "$package" ] || continue
case "$package_dir" in
"$ROOT") embedded_path="$embedded_file" ;;
"$ROOT"/*)
embedded_path="${package_dir#"$ROOT"/}/$embedded_file"
;;
*) continue ;;
esac
if [ "$embedded_path" = "$file" ]; then
printf '%s\n' "$package" >> "$changed_packages"
embedded_owner_found=true
fi
done < "$embed_owners"
[ "$embedded_owner_found" = true ] || continue
done < "$files"
LC_ALL=C sort -u "$changed_packages" -o "$changed_packages"
if [ "$MODE" = changed ] || [ ! -s "$changed_packages" ]; then
cat "$changed_packages"
exit 0
fi
while IFS= read -r package; do
if ! go list -deps -test "$package" > "$package_dependencies"; then
printf 'failed to resolve dependencies for Go package: %s\n' "$package" >&2
exit 1
fi
if grep -Fxf "$changed_packages" "$package_dependencies" >/dev/null; then
printf '%s\n' "$package"
fi
done < "$all_packages" > "$impacted_packages"
cat "$changed_packages" >> "$impacted_packages"
LC_ALL=C sort -u "$impacted_packages"