hack: backport apidiff.sh

This makes the script identical to current
master (f3cbd79db7). This is needed
because pull-kubernetes-apidiff-client-go is the same for all
branches and assumes that the script automatically determines
the diff based on Prow env variables.
This commit is contained in:
Patrick Ohly 2025-01-15 14:51:48 +01:00
parent e616858316
commit 9ade604a07

View File

@ -14,10 +14,9 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
# This script checks the coding style for the Go language files using # This script analyzes API changes between specified revisions this repository.
# golangci-lint. Which checks are enabled depends on command line flags. The # It uses the apidiff tool to detect differences, reports incompatible changes, and optionally
# default is a minimal set of checks that all existing code passes without # builds downstream projects to assess the impact of those changes.
# issues.
usage () { usage () {
cat <<EOF >&2 cat <<EOF >&2
@ -79,36 +78,26 @@ while getopts "r:t:b:" o; do
done done
shift $((OPTIND - 1)) shift $((OPTIND - 1))
# Check specific directory or everything. # default from prow env if unset from args
targets=("$@") # https://docs.prow.k8s.io/docs/jobs/#job-environment-variables
if [ ${#targets[@]} -eq 0 ]; then # TODO: handle batch PR testing
# This lists all entries in the go.work file as absolute directory paths.
kube::util::read-array targets < <(go list -f '{{.Dir}}' -m) if [[ -z "${target:-}" && -n "${PULL_PULL_SHA:-}" ]]; then
target="${PULL_PULL_SHA}"
fi fi
# target must be a something that git can resolve to a commit.
# Sanitize paths:
# - We need relative paths because we will invoke apidiff in
# different work trees.
# - Must start with a dot.
for (( i=0; i<${#targets[@]}; i++ )); do
d="${targets[i]}"
d=$(realpath -s --relative-to="$(pwd)" "${d}")
if [ "${d}" != "." ]; then
# sub-directories have to have a leading dot.
d="./${d}"
fi
targets[i]="${d}"
done
# Must be a something that git can resolve to a commit.
# "git rev-parse --verify" checks that and prints a detailed # "git rev-parse --verify" checks that and prints a detailed
# error. # error.
if [ -n "${target}" ]; then if [[ -n "${target}" ]]; then
target="$(git rev-parse --verify "${target}")" target="$(git rev-parse --verify "${target}")"
fi fi
# Determine defaults. if [[ -z "${base}" && -n "${PULL_BASE_SHA:-}" && -n "${PULL_PULL_SHA:-}" ]]; then
if [ -z "${base}" ]; then if ! base="$(git merge-base "${PULL_BASE_SHA}" "${PULL_PULL_SHA}")"; then
echo >&2 "Failed to detect base revision correctly with prow environment variables."
exit 1
fi
elif [[ -z "${base}" ]]; then
if ! base="$(git merge-base origin/master "${target:-HEAD}")"; then if ! base="$(git merge-base origin/master "${target:-HEAD}")"; then
echo >&2 "Could not determine default base revision. -r must be used explicitly." echo >&2 "Could not determine default base revision. -r must be used explicitly."
exit 1 exit 1
@ -116,6 +105,20 @@ if [ -z "${base}" ]; then
fi fi
base="$(git rev-parse --verify "${base}")" base="$(git rev-parse --verify "${base}")"
# Check specific directory or everything.
targets=("$@")
if [ ${#targets[@]} -eq 0 ]; then
shopt -s globstar
# Modules are discovered by looking for go.mod rather than asking go
# to ensure that modules that aren't part of the workspace and/or are
# not dependencies are checked too.
# . and staging are listed explicitly here to avoid _output
for module in ./go.mod ./staging/**/go.mod; do
module="${module%/go.mod}"
targets+=("$module")
done
fi
# Give some information about what's happening. Failures from "git describe" are ignored # Give some information about what's happening. Failures from "git describe" are ignored
# silently, that's optional information. # silently, that's optional information.
describe () { describe () {
@ -156,8 +159,18 @@ run () {
out="$1" out="$1"
mkdir -p "$out" mkdir -p "$out"
for d in "${targets[@]}"; do for d in "${targets[@]}"; do
apidiff -m -w "${out}/$(output_name "${d}")" "${d}" if ! [ -d "${d}" ]; then
echo "module ${d} does not exist, skipping ..."
continue
fi
# cd to the path for modules that are intree but not part of the go workspace
# per example staging/src/k8s.io/code-generator/examples
(
cd "${d}"
apidiff -m -w "${out}/$(output_name "${d}")" .
) &
done done
wait
} }
# inWorktree checks out a specific revision, then invokes the given # inWorktree checks out a specific revision, then invokes the given
@ -204,12 +217,16 @@ inWorktree "${KUBE_TEMP}/base" "${base}" run "${KUBE_TEMP}/before"
# be non-zero if there are incompatible changes. # be non-zero if there are incompatible changes.
# #
# The report is Markdown-formatted and can be copied into a PR comment verbatim. # The report is Markdown-formatted and can be copied into a PR comment verbatim.
res=0 failures=()
echo echo
compare () { compare () {
what="$1" what="$1"
before="$2" before="$2"
after="$3" after="$3"
if [ ! -f "${before}" ] || [ ! -f "${after}" ]; then
echo "can not compare changes, module didn't exist before or after"
return
fi
changes=$(apidiff -m "${before}" "${after}" 2>&1 | grep -v -e "^Ignoring internal package") || true changes=$(apidiff -m "${before}" "${after}" 2>&1 | grep -v -e "^Ignoring internal package") || true
echo "## ${what}" echo "## ${what}"
if [ -z "$changes" ]; then if [ -z "$changes" ]; then
@ -218,9 +235,9 @@ compare () {
echo "$changes" echo "$changes"
echo echo
fi fi
incompatible=$(apidiff -incompatible -m "${before}" "${after}" 2>&1) || true incompatible=$(apidiff -incompatible -m "${before}" "${after}" 2>&1 | grep -v -e "^Ignoring internal package") || true
if [ -n "$incompatible" ]; then if [ -n "$incompatible" ]; then
res=1 failures+=("${what}")
fi fi
} }
@ -257,7 +274,11 @@ tryBuild () {
) )
} }
if [ $res -ne 0 ]; then res=0
if [ ${#failures[@]} -gt 0 ]; then
res=1
echo "Detected incompatible changes on modules:"
printf '%s\n' "${failures[@]}"
cat <<EOF cat <<EOF
Some notes about API differences: Some notes about API differences: