Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ hack/verify-go-modules.sh: compare dependency versions #3312

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
83 changes: 83 additions & 0 deletions hack/verify-go-modules.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@
# limitations under the License.

# This script verifies all go modules in the repository.
# go.mod and go.sum files are checked that both have been
# committed. Versions of dependencies they declare are
# checked to be in line with dependencies in k8s.io/kubernetes,
# and a warning message is printed if they differ in v<Maj>.<Min>.

set -o errexit
set -o nounset
Expand All @@ -24,14 +28,93 @@ REPO_ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)

mapfile -t DIRS < <(find "${REPO_ROOT}" -name go.mod -print0 | xargs -0 dirname)

# list_deps lists dependencies of the supplied go.mod file (dependencies
# with version "v0.0.0" are skipped). The output is a json dictionary in the
# format `{"<Dependency>": "<Version>", ...}`.
function list_deps {
gomod_file="${1}"
go mod edit -json "${gomod_file}" \
| jq -r '
(
[ .Require[]
| select(.Version != "v0.0.0")
| { (.Path): .Version } ]
| add
)
'
}

# diff_version_deps lists common dependencies of the two supplied go.mod files
# whose respective versions differ (up to v<Maj>.<Min>). The output is a json
# dictionary in the format:
# `{"<Dependency>": {
# "has": "<Dependency version of the first file>",
# "wants": "<Dependency version of the second file>"
# }, ...}`
function diff_version_deps {
has_deps="${1}"
wants_deps="${2}"
jq -s '
# Extracts v<Maj>.<Min> from a semantic version string.
def major_minor_semver: capture("v(?<major>\\d+)\\.(?<minor>\\d+)")
| "v" + .major + "." + .minor;

map(to_entries) # Convert both input dicts into two separate arrays.
| add # Concatenate those two arrays into a single one.
| group_by(.key) # Group items by `.key`.
| map( # Map each selected item into { "<Dep>": {"has": "<Version0>", "wants": "<Version1>"} }.
select(
# If grouping resulted in two items, it means both arrays have this dependency.
length == 2
# Compare the v<Maj>.<Min> of both items.
and (.[0].value | major_minor_semver) != (.[1].value | major_minor_semver)
)
| { (.[0].key): { "has": .[0].value, "wants": .[1].value } }
)
| add // empty
' "${has_deps}" "${wants_deps}"
}

# print_diff_version_deps prints the output of diff_version_deps as a
# human-readable multi-line text.
function print_diff_version_deps {
jq -r "to_entries | map(\"Warning: version mismatch: has \(.key)@\(.value.has), but \(.value.wants) expected\") | join(\"\\n\")"
}

# Compares versions of dependencies in the supplied go.mod to
# makes sure they are in line with the ones declared in
# k8s.io/kubernetes module and prints the result.
function compare_mod_versions {
gomod_file="${1}"
echo "Verifying dependency versions in ${gomod_file} against ${k8s_gomod}"
deps="$(list_deps ${gomod_file})"

diff_version_deps <(echo "${deps}") <(echo "${k8s_deps}") \
| print_diff_version_deps "${gomod_file}"
}

function gomod_filepath_for {
mod="${1}"
go list -m -json "${mod}" | jq -r .GoMod
}

k8s_gomod="$(gomod_filepath_for k8s.io/kubernetes)"
k8s_deps="$(list_deps ${k8s_gomod})"

for dir in "${DIRS[@]}"; do
(
cd "$dir"
echo "Verifying ${dir}"

if ! git diff --quiet HEAD -- go.mod go.sum; then
echo "go module files are out of date"
git diff HEAD -- go.mod go.sum
exit 1
fi

compare_mod_versions "${dir}/go.mod"
)
done

compare_mod_versions "$(gomod_filepath_for github.com/kcp-dev/client-go)"
compare_mod_versions "$(gomod_filepath_for github.com/kcp-dev/apimachinery/v2)"