Skip to content

Commit 56fe2a9

Browse files
committed
fix(e2e): fail loudly on image-load errors; verify imports; move changelog entry
Review follow-ups: - Drop '|| true' at every CI-active kind_load_image call site (upgrade-chain.sh, framework.sh x3) — under set -euo pipefail a failed load now aborts the run instead of resurrecting the silent-failure path this PR exists to kill. - Convert the release-image load in test_upgrade_comprehensive.sh off raw 'kind load docker-image'; no raw kind-load calls remain in e2e/. - kind_load_image: capture and surface ctr's stderr on failure, and verify the image is actually present in containerd after import (a truncated stream can 'succeed' without importing what we think it did). - Move the changelog entry from Improvements to Bug Fixes, matching #319. Re-validated: full hardfork upgrade e2e 5/5 with the presence check live on all three image loads. Signed-off-by: puneetmahajan <59960662+puneet2019@users.noreply.github.com>
1 parent 9265172 commit 56fe2a9

5 files changed

Lines changed: 26 additions & 18 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
6464
- (types,utils) [#320](https://github.com/mocachain/moca/pull/320) Delete dead ethermint-era files orphaned by the `rpc/`/`x/evm`/`x/erc20` removals: `types/{block,gasmeter,int,protocol,validation,constant}.go`, `types/openapiutil/`, and `utils/eth/eth.go` — every exported symbol verified unreferenced across the repo and all known external consumers (moca-storage-provider, moca-go-sdk, moca-challenger). Externally-used files (`chain_id.go``ParseChainID` is production code in the storage provider's signer — `grn.go`, `s3util`, `resource`, `common`) are untouched.
6565
- (client) [#321](https://github.com/mocachain/moca/pull/321) Delete the dead `client/testnet.go` (579 LOC): an unreferenced near-duplicate of `cmd/mocad/cmd/testnet.go`, which is what the `mocad testnet` command actually wires.
6666
- (e2e) [#324](https://github.com/mocachain/moca/pull/324) Fix the hardfork-upgrade e2e flake ("Chain did not reach height N within 240s"): the new-binary image load into kind could fail silently (`kind load ... || true`) and readiness accepted a single healthy pod as "chain resumed" while 2/3 quorum was still absent. Load images via `docker save | ctr import` with verification (`kind_load_image`), and gate post-restart on every validator's own RPC plus the EVM JSON-RPC (`wait_for_all_validator_rpcs`, `wait_for_evm_rpc_ready`); also delete stale kind clusters on fresh builds so containerd can't serve an old image SHA under the new tag.
67+
6768
- (contracts) [#314](https://github.com/mocachain/moca/pull/314) Slim `contracts/` to what moca actually uses (mirroring cosmos/evm's top-level `contracts/` convention): delete the four ERC20 test doubles (`MinterBurnerDecimals`, `Burnable`, `DirectBalanceManipulation`, `MaliciousDelayed`) — dead since the `x/erc20` removal (#221), available upstream where still needed — plus their `.sol` sources, artifacts, and npm manifest. The moca-specific `ERC721NonTransferable` (bucket/object/group NFT facade the storage keeper mints/burns through) stays put, now pinned by a guard test covering its ABI surface, fixed token/hub addresses, and its intentionally bytecode-less (ABI-only) nature. Slither retargets to `solidity/`; the now-subjectless solhint workflow and broken `lint-contracts` Make targets are removed.
6869

6970
### State Machine Breaking

e2e/kind/framework/framework.sh

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ fw_start_chain() {
134134
fi
135135
else
136136
log_info "FW_SKIP_BUILD=true, loading pre-built images into Kind..."
137-
kind_load_image "${DOCKER_IMAGE}:${DOCKER_TAG}" || true
137+
kind_load_image "${DOCKER_IMAGE}:${DOCKER_TAG}"
138138
fi
139139

140140
# Deploy chain
@@ -162,8 +162,8 @@ fw_start_chain_from_version() {
162162
OLD_VERSION="${old_version}" bash "${SCRIPTS_DIR}/build-images.sh"
163163
else
164164
log_info "FW_SKIP_BUILD=true, loading pre-built images into Kind..."
165-
kind_load_image "${DOCKER_IMAGE}:${DOCKER_TAG}" || true
166-
kind_load_image "${DOCKER_IMAGE}:${old_version}" || true
165+
kind_load_image "${DOCKER_IMAGE}:${DOCKER_TAG}"
166+
kind_load_image "${DOCKER_IMAGE}:${old_version}"
167167
fi
168168

169169
# Deploy with old version

e2e/kind/scripts/lib.sh

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -123,11 +123,18 @@ kind_load_image() {
123123
log_error "Kind control-plane container '$node' not running"
124124
return 1
125125
fi
126-
docker save "$image" | docker exec -i "$node" \
127-
ctr --namespace=k8s.io images import - >/dev/null 2>&1 || {
128-
log_error "Failed to load image $image into Kind"
126+
local import_out
127+
if ! import_out=$(docker save "$image" | docker exec -i "$node" \
128+
ctr --namespace=k8s.io images import - 2>&1); then
129+
log_error "Failed to load image $image into Kind: ${import_out}"
129130
return 1
130-
}
131+
fi
132+
# Verify the image is actually present in containerd — a truncated stream
133+
# can "succeed" without importing what we think it did.
134+
if ! docker exec "$node" ctr --namespace=k8s.io images ls -q 2>/dev/null | grep -qF "${image}"; then
135+
log_error "Image $image not present in Kind containerd after import (got: ${import_out})"
136+
return 1
137+
fi
131138
log_success "Image $image loaded into Kind cluster"
132139
}
133140

e2e/kind/scripts/upgrade-chain.sh

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,15 @@ _upgrade_governance() {
3838
mocad query auth module-account gov \
3939
--node tcp://localhost:26657 \
4040
--home /root/.mocad \
41-
--output json 2>/dev/null | jq -r '.account.base_account.address // .account.value.address // empty' 2>/dev/null) || true
41+
--output json 2>/dev/null | jq -r '.account.base_account.address // .account.value.address // empty' 2>/dev/null)
4242

4343
if [ -z "$gov_authority" ]; then
4444
log_warn "Could not query gov module address, trying alternative..."
4545
gov_authority=$(kubectl exec -n "${K8S_NAMESPACE}" validator-0-0 -c mocad -- \
4646
mocad query auth module-accounts \
4747
--node tcp://localhost:26657 \
4848
--home /root/.mocad \
49-
--output json 2>/dev/null | jq -r '.accounts[] | select(.name=="gov") | .base_account.address // .value.address // empty' 2>/dev/null) || true
49+
--output json 2>/dev/null | jq -r '.accounts[] | select(.name=="gov") | .base_account.address // .value.address // empty' 2>/dev/null)
5050
fi
5151

5252
if [ -z "$gov_authority" ]; then
@@ -80,7 +80,7 @@ PROPOSAL_EOF
8080

8181
# Write proposal file into the pod
8282
echo "$proposal_json" | kubectl exec -i -n "${K8S_NAMESPACE}" validator-0-0 -c mocad -- \
83-
bash -c "cat > /tmp/upgrade-proposal.json" || true
83+
bash -c "cat > /tmp/upgrade-proposal.json"
8484

8585
# Submit proposal via sync broadcast + wait for inclusion
8686
local submit_out="" submit_hash=""
@@ -110,9 +110,9 @@ PROPOSAL_EOF
110110
--node tcp://localhost:26657 \
111111
--chain-id "${CHAIN_ID}" \
112112
--home /root/.mocad \
113-
--output json 2>&1) || true
113+
--output json 2>&1)
114114

115-
proposal_id=$(echo "$query_out" | jq -r '.proposals[-1].id // .proposals[-1].proposal_id // empty' 2>/dev/null) || true
115+
proposal_id=$(echo "$query_out" | jq -r '.proposals[-1].id // .proposals[-1].proposal_id // empty' 2>/dev/null)
116116

117117
if [ -z "$proposal_id" ]; then
118118
log_error "Could not find upgrade proposal"
@@ -206,9 +206,9 @@ _wait_for_upgrade_halt() {
206206
# Chain halts but doesn't exit — scale down, replace binary, scale back up
207207
log_info "Scaling down validators..."
208208
for ((i = 0; i < NUM_VALIDATORS; i++)); do
209-
kubectl scale statefulset "validator-${i}" --replicas=0 -n "${K8S_NAMESPACE}" 2>/dev/null || true
209+
kubectl scale statefulset "validator-${i}" --replicas=0 -n "${K8S_NAMESPACE}" 2>/dev/null
210210
done
211-
kubectl wait --for=delete pod -l app=validator -n "${K8S_NAMESPACE}" --timeout=60s 2>/dev/null || true
211+
kubectl wait --for=delete pod -l app=validator -n "${K8S_NAMESPACE}" --timeout=60s 2>/dev/null
212212
log_info "All validators stopped"
213213

214214
# Update all validator StatefulSets to use the new image, then scale back up
@@ -220,7 +220,7 @@ _update_validator_images() {
220220

221221
# Load new image into Kind if not already loaded (docker save | ctr import
222222
# — see kind_load_image in lib.sh; avoids buildx desktop-linux quirks)
223-
kind_load_image "${NEW_DOCKER_IMAGE}" || true
223+
kind_load_image "${NEW_DOCKER_IMAGE}"
224224

225225
# Patch each validator StatefulSet with the new image
226226
for ((i = 0; i < NUM_VALIDATORS; i++)); do
@@ -236,7 +236,7 @@ _update_validator_images() {
236236
# Scale validators back up with new image
237237
log_info "Starting validators with new image..."
238238
for ((i = 0; i < NUM_VALIDATORS; i++)); do
239-
kubectl scale statefulset "validator-${i}" --replicas=1 -n "${K8S_NAMESPACE}" 2>/dev/null || true
239+
kubectl scale statefulset "validator-${i}" --replicas=1 -n "${K8S_NAMESPACE}" 2>/dev/null
240240
done
241241

242242
# Wait for all validators to come back up
@@ -246,7 +246,7 @@ _update_validator_images() {
246246
kubectl wait --for=condition=ready "pod/validator-${i}-0" \
247247
-n "${K8S_NAMESPACE}" --timeout=180s 2>/dev/null || {
248248
log_error "Validator-${i} failed to restart"
249-
kubectl logs -n "${K8S_NAMESPACE}" "validator-${i}-0" --tail=50 2>/dev/null || true
249+
kubectl logs -n "${K8S_NAMESPACE}" "validator-${i}-0" --tail=50 2>/dev/null
250250
return 1
251251
}
252252
done

e2e/kind/tests/test_upgrade_comprehensive.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ if [ -n "$RELEASE_TAG" ] && [ -z "$RELEASE_IMAGE" ]; then
191191
log_info "Pulling release image: ${_GHCR_IMAGE}..."
192192
docker pull "$_GHCR_IMAGE" 2>&1
193193
echo "FROM ${_GHCR_IMAGE}" | docker build -t "$RELEASE_IMAGE" - 2>&1
194-
kind load docker-image "$RELEASE_IMAGE" --name "${KIND_CLUSTER_NAME}" 2>&1
194+
kind_load_image "$RELEASE_IMAGE"
195195
fi
196196

197197
# Get validator operator addresses indexed by validator-N pod number.

0 commit comments

Comments
 (0)