Merge pull request #122971 from pohly/apidiff

hack: add apidiff.sh
This commit is contained in:
Kubernetes Prow Robot 2024-04-24 09:47:12 -07:00 committed by GitHub
commit cc8063a911
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

154
hack/apidiff.sh Executable file
View File

@ -0,0 +1,154 @@
#!/usr/bin/env bash
# Copyright 2024 The Kubernetes Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# This script checks the coding style for the Go language files using
# golangci-lint. Which checks are enabled depends on command line flags. The
# default is a minimal set of checks that all existing code passes without
# issues.
usage () {
cat <<EOF >&2
Usage: $0 [-r <revision>] [directory]"
-r <revision>: only report issues in code added since that revision. Default is
the common base of origin/master and HEAD.
[package]: check directory instead of everything
EOF
exit 1
}
set -o errexit
set -o nounset
set -o pipefail
KUBE_ROOT=$(dirname "${BASH_SOURCE[0]}")/..
source "${KUBE_ROOT}/hack/lib/init.sh"
base="$(git merge-base origin/master HEAD)"
while getopts "r:" o; do
case "${o}" in
r)
base="${OPTARG}"
if [ ! "$base" ]; then
echo "ERROR: -${o} needs a non-empty parameter" >&2
echo >&2
usage
fi
;;
*)
usage
;;
esac
done
shift $((OPTIND - 1))
# Check specific directory or everything.
targets=("$@")
if [ ${#targets[@]} -eq 0 ]; then
# This lists all entries in the go.work file as absolute directory paths.
kube::util::read-array targets < <(
go list -f '{{.Dir}}' -m | while read -r d; do
# We need relative paths because we will invoke apidiff in
# different work trees.
d="$(realpath -s --relative-to="$(pwd)" "${d}")"
if [ "${d}" != "." ]; then
# sub-directories have to have a leading dot.
d="./${d}"
fi
echo "${d}"
done
)
fi
# Must be a something that git can resolve to a commit.
# "git rev-parse --verify" checks that and prints a detailed
# error.
base="$(git rev-parse --verify "$base")"
kube::golang::setup_env
kube::util::ensure-temp-dir
# Install apidiff and make sure it's found.
export GOBIN="${KUBE_TEMP}"
PATH="${GOBIN}:${PATH}"
echo "installing apidiff into ${GOBIN}"
go install golang.org/x/exp/cmd/apidiff@latest
cd "${KUBE_ROOT}"
# output_name targets a target directory and prints the base name of
# an output file for that target.
output_name () {
what="$1"
echo "${what}" | sed -e 's/[^a-zA-Z0-9_-]/_/g' -e 's/$/.out/'
}
# run invokes apidiff once per target and stores the output
# file(s) in the given directory.
run () {
out="$1"
mkdir -p "$out"
for d in "${targets[@]}"; do
apidiff -m -w "${out}/$(output_name "${d}")" "${d}"
done
}
# First the current code.
run "${KUBE_TEMP}/after"
WORKTREE="${KUBE_TEMP}/worktree"
# Create a copy of the repo with the base checked out.
git worktree add -f -d "${WORKTREE}" "${base}"
# Clean up the copy on exit.
kube::util::trap_add "git worktree remove -f ${WORKTREE}" EXIT
# Base ready for apidiff.
(
cd "${WORKTREE}"
run "${KUBE_TEMP}/before"
)
# Now produce a report. All changes get reported because exporting some API
# unnecessarily might also be good to know, but the final exit code will only
# be non-zero if there are incompatible changes.
#
# The report is Markdown-formatted and can be copied into a PR comment verbatim.
res=0
echo
compare () {
what="$1"
before="$2"
after="$3"
changes=$(apidiff -m "${before}" "${after}" 2>&1 | grep -v -e "^Ignoring internal package") || true
echo "## ${what}"
if [ -z "$changes" ]; then
echo "no changes"
else
echo "$changes"
echo
fi
incompatible=$(apidiff -incompatible -m "${before}" "${after}" 2>&1) || true
if [ -n "$incompatible" ]; then
res=1
fi
}
for d in "${targets[@]}"; do
compare "${d}" "${KUBE_TEMP}/before/$(output_name "${d}")" "${KUBE_TEMP}/after/$(output_name "${d}")"
done
exit "$res"