validate/module-replace: Ignore client diff if it only removes the replace rule

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 <pawel.gronowski@docker.com>

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
This commit is contained in:
Paweł Gronowski
2025-12-17 12:27:59 +01:00
parent b8093b76fb
commit 265bdc1a06

View File

@@ -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