Merge pull request #124552 from pohly/apidiff
hack/apidiff.sh: compare between two revisions, usability enhancements
This commit is contained in:
		
							
								
								
									
										110
									
								
								hack/apidiff.sh
									
									
									
									
									
								
							
							
						
						
									
										110
									
								
								hack/apidiff.sh
									
									
									
									
									
								
							| @@ -21,10 +21,12 @@ | |||||||
|  |  | ||||||
| usage () { | usage () { | ||||||
|   cat <<EOF >&2 |   cat <<EOF >&2 | ||||||
| Usage: $0 [-r <revision>] [directory]" | Usage: $0 [-r <revision>] [directory ...]" | ||||||
|    -r <revision>: only report issues in code added since that revision. Default is |    -t <revision>: Report changes in code up to and including this revision. | ||||||
|       the common base of origin/master and HEAD. |                   Default is the current working tree instead of a revision. | ||||||
|    [package]: check directory instead of everything |    -r <revision>: Report change in code added since this revision. Default is | ||||||
|  |                   the common base of origin/master and HEAD. | ||||||
|  |    [directory]:   Check one or more specific directory instead of everything. | ||||||
| EOF | EOF | ||||||
|   exit 1 |   exit 1 | ||||||
| } | } | ||||||
| @@ -37,7 +39,8 @@ KUBE_ROOT=$(dirname "${BASH_SOURCE[0]}")/.. | |||||||
| source "${KUBE_ROOT}/hack/lib/init.sh" | source "${KUBE_ROOT}/hack/lib/init.sh" | ||||||
|  |  | ||||||
| base= | base= | ||||||
| while getopts "r:" o; do | target= | ||||||
|  | while getopts "r:t:" o; do | ||||||
|     case "${o}" in |     case "${o}" in | ||||||
|         r) |         r) | ||||||
|             base="${OPTARG}" |             base="${OPTARG}" | ||||||
| @@ -47,6 +50,14 @@ while getopts "r:" o; do | |||||||
|                 usage |                 usage | ||||||
|             fi |             fi | ||||||
|             ;; |             ;; | ||||||
|  |        t) | ||||||
|  |             target="${OPTARG}" | ||||||
|  |             if [ ! "$target" ]; then | ||||||
|  |                 echo "ERROR: -${o} needs a non-empty parameter" >&2 | ||||||
|  |                 echo >&2 | ||||||
|  |                 usage | ||||||
|  |             fi | ||||||
|  |             ;; | ||||||
|         *) |         *) | ||||||
|             usage |             usage | ||||||
|             ;; |             ;; | ||||||
| @@ -58,36 +69,51 @@ shift $((OPTIND - 1)) | |||||||
| targets=("$@") | targets=("$@") | ||||||
| if [ ${#targets[@]} -eq 0 ]; then | if [ ${#targets[@]} -eq 0 ]; then | ||||||
|     # This lists all entries in the go.work file as absolute directory paths. |     # This lists all entries in the go.work file as absolute directory paths. | ||||||
|     kube::util::read-array targets < <( |     kube::util::read-array targets < <(go list -f '{{.Dir}}' -m) | ||||||
|         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 | fi | ||||||
|  |  | ||||||
| # Default if -r was not given. | # Sanitize paths: | ||||||
| if [ -z "${base}" ]; then | # - We need relative paths because we will invoke apidiff in | ||||||
|     if ! base="$(git merge-base origin/master HEAD)"; then | #   different work trees. | ||||||
|         echo >&2 "Could not determine default base revision. -r must be used explicitly." | # - Must start with a dot. | ||||||
|         exit 1 | 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 |     fi | ||||||
| fi |     targets[i]="${d}" | ||||||
|  | done | ||||||
|  |  | ||||||
| # Must be a something that git can resolve to a commit. | # 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. | ||||||
| base="$(git rev-parse --verify "$base")" | if [ -n "${target}" ]; then | ||||||
|  |     target="$(git rev-parse --verify "${target}")" | ||||||
|  | fi | ||||||
|  |  | ||||||
|  | # Determine defaults. | ||||||
|  | if [ -z "${base}" ]; then | ||||||
|  |     if ! base="$(git merge-base origin/master "${target:-HEAD}")"; then | ||||||
|  |         echo >&2 "Could not determine default base revision. -r must be used explicitly." | ||||||
|  |         exit 1 | ||||||
|  |     fi | ||||||
|  | fi | ||||||
|  | base="$(git rev-parse --verify "${base}")" | ||||||
|  |  | ||||||
| # 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. | ||||||
| echo "Checking for API changes since ${base}$(if descr=$(git describe --tags "${base}" 2>/dev/null); then echo " = ${descr}"; fi)." | describe () { | ||||||
|  |     local rev="$1" | ||||||
|  |     local descr | ||||||
|  |     echo -n "$rev" | ||||||
|  |     if descr=$(git describe --tags "${rev}" 2>/dev/null); then | ||||||
|  |         echo -n " (= ${descr})" | ||||||
|  |     fi | ||||||
|  |     echo | ||||||
|  | } | ||||||
|  | echo "Checking $(if [ -n "${target}" ]; then describe "${target}"; else echo "current working tree"; fi) for API changes since $(describe "${base}")." | ||||||
|  |  | ||||||
| kube::golang::setup_env | kube::golang::setup_env | ||||||
| kube::util::ensure-temp-dir | kube::util::ensure-temp-dir | ||||||
| @@ -118,21 +144,31 @@ run () { | |||||||
|     done |     done | ||||||
| } | } | ||||||
|  |  | ||||||
| # First the current code. | # runWorktree checks out a specific revision, then invokes run there. | ||||||
| run "${KUBE_TEMP}/after" | runWorktree () { | ||||||
|  |     local out="$1" | ||||||
|  |     local worktree="$2" | ||||||
|  |     local rev="$3" | ||||||
|  |  | ||||||
| WORKTREE="${KUBE_TEMP}/worktree" |     # Create a copy of the repo with the specific revision checked out. | ||||||
|  |     git worktree add -f -d "${worktree}" "${rev}" | ||||||
|  |     # Clean up the copy on exit. | ||||||
|  |     kube::util::trap_add "git worktree remove -f ${worktree}" EXIT | ||||||
|  |  | ||||||
| # Create a copy of the repo with the base checked out. |     # Ready for apidiff. | ||||||
| git worktree add -f -d "${WORKTREE}" "${base}" |     ( | ||||||
| # Clean up the copy on exit. |         cd "${worktree}" | ||||||
| kube::util::trap_add "git worktree remove -f ${WORKTREE}" EXIT |         run "${out}" | ||||||
|  |     ) | ||||||
|  | } | ||||||
|  |  | ||||||
| # Base ready for apidiff. | # Dump old and new api state. | ||||||
| ( | if [ -z "${target}" ]; then | ||||||
|     cd "${WORKTREE}" |     run "${KUBE_TEMP}/after" | ||||||
|     run "${KUBE_TEMP}/before" | else | ||||||
| ) |     runWorktree "${KUBE_TEMP}/after" "${KUBE_TEMP}/target" "${target}" | ||||||
|  | fi | ||||||
|  | runWorktree "${KUBE_TEMP}/before" "${KUBE_TEMP}/base" "${base}" | ||||||
|  |  | ||||||
| # Now produce a report. All changes get reported because exporting some API | # 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 | # unnecessarily might also be good to know, but the final exit code will only | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Kubernetes Prow Robot
					Kubernetes Prow Robot