From 265bdc1a06f9f0935dc12c3e2edccc2d7e546efe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Gronowski?= Date: Wed, 17 Dec 2025 12:27:59 +0100 Subject: [PATCH] validate/module-replace: Ignore client diff if it only removes the replace rule MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The check is supposed to detect if we're missing replace rules (mostly for the actual code changes). When dropping the replace rules we're also updating the client/go.mod to use the yet-untagged `api` module version (but that's ok). For context, an example client diff for a commit that drops replace rules is: ```diff index d032891256..04cb6f3bee 100644 --- client/go.mod +++ client/go.mod @@ -10,7 +10,7 @@ require ( github.com/docker/go-connections v0.6.0 github.com/docker/go-units v0.5.0 github.com/google/go-cmp v0.7.0 - github.com/moby/moby/api v1.52.0 + github.com/moby/moby/api v1.52.1-0.20251216183007-8316b79e045e github.com/moby/term v0.5.2 github.com/opencontainers/go-digest v1.0.0 github.com/opencontainers/image-spec v1.1.1 @@ -32,5 +32,3 @@ require ( go.opentelemetry.io/otel/metric v1.35.0 // indirect golang.org/x/sys v0.33.0 // indirect ) - -replace github.com/moby/moby/api => ../api diff --git client/go.sum client/go.sum index 29b5ea6130..558c150354 100644 --- client/go.sum +++ client/go.sum @@ -29,6 +29,8 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= +github.com/moby/moby/api v1.52.1-0.20251216183007-8316b79e045e h1:OU/YmCsRJtfx4OhTt7DD8WANQ57eHSUkYrGFNnS5yxc= +github.com/moby/moby/api v1.52.1-0.20251216183007-8316b79e045e/go.mod h1:8mb+ReTlisw4pS6BRzCMts5M49W5M7bKt1cJy/YbAqc= github.com/moby/term v0.5.2 h1:6qk3FJAFDs6i/q3W/pQ97SX192qKfZgGjCQqfCJkgzQ= github.com/moby/term v0.5.2/go.mod h1:d3djjFCrjnB+fl8NJux+EJzu0msscUP+f8it8hPkFLc= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=' ']' ``` Signed-off-by: Paweł Gronowski Signed-off-by: Paweł Gronowski --- hack/validate/module-replace | 57 ++++++++++++++++++++++++++++++++---- 1 file changed, 51 insertions(+), 6 deletions(-) diff --git a/hack/validate/module-replace b/hack/validate/module-replace index 0216c53159..af4e1256d1 100755 --- a/hack/validate/module-replace +++ b/hack/validate/module-replace @@ -4,23 +4,62 @@ set -e SCRIPTDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" source "${SCRIPTDIR}/.validate" -api_files=$( - validate_diff --diff-filter=ACMR --name-only -- \ +# Leaves only actual changes, not the diff header +filter_diff() { + sed '1,4d' | grep -E '^[+-]' | grep -Ev '^(\+\+\+|\-\-\-)' +} + +api_diff=$( + validate_diff --diff-filter=ACMR -U0 -- \ 'api/' \ ':(exclude)api/README.md' \ ':(exclude)api/swagger.yaml' \ ':(exclude)api/docs/' \ + | filter_diff \ || true ) -client_files=$(validate_diff --diff-filter=ACMR --name-only -- 'client/' || true) +client_diff=$(validate_diff --diff-filter=ACMR -U0 -- 'client/' | filter_diff || true) has_errors=0 +echo "================================================" +echo "go.mod:" cat go.mod +echo "================================================" +# reads stdin and returns 1 or 0 if the replace rule for the module is present +# example input: +# - github.com/moby/moby/api v1.52.0 +# + github.com/moby/moby/api v1.52.1-0.20251217102041-b8093b76fb43 +# - +# -replace github.com/moby/moby/api => ../api +# +github.com/moby/moby/api v1.52.1-0.20251217102041-b8093b76fb43 h1:CTVB9ByfoOULdpH0GiDWwHK3B1jxwjoWtHiEGia1nRc= +# +github.com/moby/moby/api v1.52.1-0.20251217102041-b8093b76fb43/go.mod h1:8mb+ReTlisw4pS6BRzCMts5M49W5M7bKt1cJy/YbAqc= +only_removes_replace_rule_for_module() { + local module="$1" + input=$(cat | sed '/^[-+]$/d') # strip empty lines + + if ! grep -qE "^-replace ${module} => " <<< "${input}"; then + return 1 + fi + + # Check if ALL lines contain the module string + # The grep command checks if there's NO match for the module string, and + # then we negate the results + if grep -vqF "${module}" <<< "${input}"; then + return 1 + fi + + return 0 +} + +echo >&2 "================================================" +echo >&2 "api diff:" +echo >&2 "${api_diff}" +echo >&2 "================================================" # Check if changes to ./api require a replace rule in go.mod -if [ -n "${TEST_FORCE_VALIDATE:-}" ] || [ -n "${api_files}" ]; then +if [ -n "${TEST_FORCE_VALIDATE:-}" ] || [ -n "${api_diff}" ]; then echo "Detected changes in ./api directory, checking for replace rule..." if ! go list -mod=readonly -m -json github.com/moby/moby/api | jq -e '.Replace'; then echo >&2 "ERROR: Changes detected in ./api but go.mod is missing a replace rule for github.com/moby/moby/api" @@ -31,10 +70,16 @@ if [ -n "${TEST_FORCE_VALIDATE:-}" ] || [ -n "${api_files}" ]; then fi fi +echo >&2 "================================================" +echo >&2 "client diff:" +echo >&2 "${client_diff}" +echo >&2 "================================================" # Check if changes to ./client require a replace rule in go.mod -if [ -n "${TEST_FORCE_VALIDATE:-}" ] || [ -n "${client_files}" ]; then +if [ -n "${TEST_FORCE_VALIDATE:-}" ] || [ -n "${client_diff}" ]; then echo "Detected changes in ./client directory, checking for replace rule..." - if ! go list -mod=readonly -m -json github.com/moby/moby/client | jq -e '.Replace'; then + if only_removes_replace_rule_for_module "github.com/moby/moby/api" <<< "${client_diff}"; then + echo >&2 "✓ This seems to only remove the replace rule for github.com/moby/moby/api" + elif ! go list -mod=readonly -m -json github.com/moby/moby/client | jq -e '.Replace'; then echo >&2 "ERROR: Changes detected in ./client but go.mod is missing a replace rule for github.com/moby/moby/client" echo >&2 "Please run ./hack/vendor.sh replace" has_errors=1