refactor: 각 어댑터터별 리펙토링 진행

This commit is contained in:
DongHyeonka
2026-08-24 18:26:40 +09:00
parent e98b56eb03
commit 0137263441
439 changed files with 31935 additions and 4719 deletions
+89 -6
View File
@@ -27,8 +27,15 @@ readonly MATRIX="${REPO_ROOT}/.github/ci-gate-matrix.yml"
# Deliberately a literal: a gate silently appearing or disappearing is the drift this lint exists to
# catch, so growing the matrix is an explicit edit here. 38 as of the HTTP Client platform hardening,
# which registered httpclient-spring62-runtime as a delegated-pending control — the 6.2 *runtime*
# claim, distinct from the API-surface scan that was standing in for it.
readonly EXPECTED_GATE_COUNT=38
# claim, distinct from the API-surface scan that was standing in for it. 40 after the Gradle
# convention wave registered documented-leaf-count and declared-dependency-absence, then 46 after
# the final qualification wave registered the four notification/runbook gates that existed but ran
# nowhere and the two API-surface gates the convention had already wired into check. 48 once the
# Compose runtime matrix and the GraphQL runtime JWT claim were registered as delegated-pending —
# both are real and neither runs in CI. 49 once the messaging broker certification lane registered
# its evidence gate — the first control in this repository whose subject is not "did the tests pass"
# but "is the committed evidence what the run produced".
readonly EXPECTED_GATE_COUNT=49
if [[ ! -f "${MATRIX}" ]]; then
printf '::error::gate-matrix-lint: missing %s\n' "${MATRIX}" >&2
@@ -135,6 +142,25 @@ gradle_custom_task_is_registered_in_build_file() {
return 0
fi
# A lane declared through the `ca.strict-test-lane` convention. The convention exists because the
# five lines every lane used to repeat were copied per lane and per leaf, and two copies had
# already lost `failOnNoDiscoveredTests`; registering through it is still registering, so this lint
# has to recognise the declaration or it reports every converted lane as missing.
if grep -qsE -- "lane\\(['\"]${task_name}['\"]\\)" "${build_file}"; then
return 0
fi
# An API surface gate declared through the `ca.api-surface` convention, which derives every task
# name from one label so a leaf cannot verify one surface while telling the reader about another.
# The name is computed, so there is no literal `tasks.register('verifyMongoApiSurface')` anywhere;
# what the build file says is `apiSurface { label = 'Mongo' }`.
if [[ "${task_name}" =~ ^verify(.+)ApiSurface$ ]]; then
local surface_label="${BASH_REMATCH[1]}"
if grep -qsE -- "label[[:space:]]*=[[:space:]]*['\"]${surface_label}['\"]" "${build_file}"; then
return 0
fi
fi
awk -v required_task="${task_name}" '
index($0, "registerStrictQualificationTest(") > 0 { inside_registration=1 }
inside_registration && /^[[:space:]]*name:[[:space:]]*/ {
@@ -159,14 +185,64 @@ gradle_custom_task_is_registered_in_build_file() {
' "${build_file}"
}
# Every `dependsOn ... named('x')` in the build, collected once.
#
# This used to be one recursive grep per gate. That was affordable at 38 gates and stopped being so
# at 48: the whole lint crossed the ten-second budget its own contract test asserts, and the first
# symptom was that test failing rather than anything about gate coverage. One pass, then membership
# tests against the result.
CHECK_WIRING_CACHE=""
load_check_wiring() {
[[ -n "${CHECK_WIRING_CACHE}" ]] && return 0
CHECK_WIRING_CACHE="$(grep -RhoE -- "dependsOn[^\n]*named\((['\"])[A-Za-z0-9_.-]+\1\)" \
"${REPO_ROOT}/src" --include='build.gradle' --include='ca.*.gradle' 2>/dev/null \
| grep -oE "(['\"])[A-Za-z0-9_.-]+\1" | tr -d "\"'" | sort -u)"
# A build with no such wiring at all would leave this empty and make every membership test pass by
# vacuity, so an empty result is a marker rather than an answer.
[[ -z "${CHECK_WIRING_CACHE}" ]] && CHECK_WIRING_CACHE="<none>"
return 0
}
gradle_custom_task_wired_into_check() {
local task_name="$1"
load_check_wiring
if printf '%s\n' "${CHECK_WIRING_CACHE}" | grep -qxF -- "${task_name}"; then
return 0
fi
# `ca.api-surface` wires check as `dependsOn tasks.named(verifyName())`, where verifyName() is
# derived from the leaf's label. The declaration that makes the gate real is the label, so that is
# what proves the wiring — the convention has exactly one check wiring and it is unconditional.
if [[ "${task_name}" =~ ^verify(.+)ApiSurface$ ]]; then
local surface_label="${BASH_REMATCH[1]}"
if grep -RqsE -- "label[[:space:]]*=[[:space:]]*['\"]${surface_label}['\"]" "${REPO_ROOT}/src" \
--include='build.gradle' \
&& grep -qsE -- "dependsOn tasks\.named\(verifyName\(\)\)" \
"${REPO_ROOT}/src/build-logic/src/main/groovy/ca.api-surface.gradle"; then
return 0
fi
fi
return 1
}
# The build files, found once rather than once per gate. Same reason as the wiring cache above: the
# per-gate `find` was a fixed cost multiplied by a number that grew.
GRADLE_FILE_CACHE=""
load_gradle_files() {
[[ -n "${GRADLE_FILE_CACHE}" ]] && return 0
GRADLE_FILE_CACHE="$(find "${REPO_ROOT}/src" -type f -name '*.gradle' | sort)"
return 0
}
gradle_custom_task_is_registered() {
local task_name="$1"
local build_file
while IFS= read -r -d '' build_file; do
load_gradle_files
while IFS= read -r build_file; do
[[ -z "${build_file}" ]] && continue
if gradle_custom_task_is_registered_in_build_file "${task_name}" "${build_file}"; then
return 0
fi
done < <(find "${REPO_ROOT}/src" -type f -name '*.gradle' -print0)
done <<< "${GRADLE_FILE_CACHE}"
return 1
}
@@ -325,9 +401,16 @@ while IFS=$'\t' read -r id blocking mechanism ref workflow job execution; do
failures+=("gate '${id}' expects Gradle check in job '${job}'")
continue
fi
# Build files *and* convention plugins. A gate can now be wired into check from an included
# build's convention rather than from a leaf's build.gradle, and a lint that only reads
# build.gradle would call such a gate unwired while it runs on every leaf — a false failure
# that teaches the next author to delete the matrix row instead of trusting it.
#
# A convention that derives the task name from a label wires check by that derived name, so
# there is no literal to grep for either; `gradle_custom_task_wired_into_check` handles both
# the literal and the derived form.
if [[ "${mechanism}" == "gradle-custom-task" ]] \
&& ! grep -RqsE -- "dependsOn.*named\\(['\"]${ref}['\"]\\)" "${REPO_ROOT}/src" \
--include='build.gradle'; then
&& ! gradle_custom_task_wired_into_check "${ref}"; then
failures+=("gate '${id}' task '${ref}' exists but is not wired into Gradle check")
continue
fi
+3 -2
View File
@@ -27,11 +27,12 @@ readonly EXPECTED_WORKFLOW_LOCK=(
'3be84c9f15fa3b2ac5a085f8d725ec6d05e7007ae0b433da9e79b3bf340d57ea .github/workflows/jpa-next-hibernate8.yml'
'a2b74bfb3af12d6d03cd2ea8a5e48490dd131afb89b79694d498c5798387ac53 .github/workflows/jpa-next-jpa4.yml'
'cd955ef4af895df477896dad9577810f010b2beea8570b09b008f9e94e928bd0 .github/workflows/jpa-next-postgresql19.yml'
'b56b548a867b74eaeccb42e7df4f4e52cf7ce657ab27f91e2c8d7ea9944d64af .github/workflows/jpa-nightly.yml'
'21e065880ef5d4c4ff973f52d8107ef08398ebaf9518ec6b2fd82d49c5d822c6 .github/workflows/jpa-nightly.yml'
'04851f44ba94533bfbc8fabe2b3a2b408726a9996e86ed3864986d1499d16b50 .github/workflows/jpa-pr.yml'
'59cb3a0ffc687a15eefe96bc5e3a70d42be78e1cc85d2e7f7880dac6124ca4c7 .github/workflows/jpa-r2-evidence.yml'
'4748f2ba0a0b77dc1a858ebcfa7db6e41627d97843df5f0aa978bc2facccaad2 .github/workflows/jpa-release.yml'
'cf4f80134197dd6d7dc177f0d21294a6b9ffe8709be67d05089f7ff0ce6c9429 .github/workflows/jpa-release.yml'
'5be7e931db749029d89787da042d6d7cf8e683d60698bd8a2993c29db26355fb .github/workflows/link-check.yml'
'8adafc59a2d87a6c65ef94b4726d7d036ac81b150ed3d301578308e6f9a3523f .github/workflows/messaging-certification.yml'
'4e4ccfa267ecd63b9369803d49f2dbdb2fa899517ad4cf23ab11d29104557a91 .github/workflows/notification-platform.yml'
'64245586cd5936f1a5647b57f2cd9acd316f96fd75f713b1890decb812e7d5fe .github/workflows/object-storage-qualification.yml'
'cbc104ea486c746229895e804e3be7716e056a02cce0588c537bce9f442f8b38 .github/workflows/redis-sdk-topology.yml'