mirror of
https://github.com/luxfi/explorer.git
synced 2026-09-24 00:25:12 +00:00
`ChainConfig.Enabled` existed on the struct, was written in every chains.yaml
we ship, and was consulted by nothing. Only `Graph.Enabled` and the subgraph
flag were ever read (supervisor.go). So `enabled: false` registered the chain,
spawned its indexer and polled its RPC exactly like `enabled: true` — a switch
that looked like a switch and was wired to nothing.
Found by using it. lux-mainnet's config lists spc, which is a sovereign L1 and
has never been a chain on that network. Setting `enabled: false` and rolling
the config changed nothing: the pod still logged
[registry] added chain spc (…/v1/bc/spc/rpc) source=config
[spc/amm] [indexer] starting
[evm] Failed to get latest block: http status 404
at 1,800 errors an hour, against a chain that was already switched off.
Honoured in ChainRegistry.Add, which is the single door — config, env, mDNS
and the admin API all arrive there — so this is the whole of what the field
means, in one place. A disabled chain is not registered, so it does not index,
mounts no routes, and does not reach the SPA's chain list (which reads
registry.List()).
Enabled is now *bool because absent must not mean off. Every config written
while the field was inert says `enabled: true` out of convention; a plain bool
would read a future config that simply omits the key as false and make that
chain vanish with no error and no log. Nil is no opinion; only an explicit
`enabled: false` disables.
Tests: registration gated in all three states (true / false / absent), a
disabled chain proven not to reach the supervisor or the chain list, and
LoadConfig proven to decode into the pointer — a wrong yaml tag would leave it
nil and silently re-enable everything it disables. Verified by defeating the
check: the false and supervisor cases fail, the absent case still passes.
Also: the Dockerfile now runs vet + tests in the builder stage. This repo has
exactly one workflow, release.yml, which builds on a v* tag; nothing ran the
test files at all. Putting them where cgo and sqlite-dev already exist costs
no new job, no new runner dependency, and means a release that fails them
never becomes an image.
Co-authored-by: Hanzo Dev <[email protected]>
64 lines
2.7 KiB
Docker
64 lines
2.7 KiB
Docker
# Lux Explorer data-layer image (v1.3.0+).
|
|
#
|
|
# As of v1.3.0 the Go binary is API-only — it serves /v1/* (indexer +
|
|
# blockscout-compat REST), /health, /envs.js, and per-host brand SVGs.
|
|
# Every other path returns 404 and the IngressRoute routes it to the
|
|
# per-brand Blockscout FE Deployment (ghcr.io/{brand-org}/explore-{env}).
|
|
# Built from luxfi/explore via Dockerfile.branded — see ~/work/lux/explore.
|
|
|
|
ARG GO_VERSION=1.26
|
|
|
|
# ---- Stage 1: build the unified FE + indexer + graph binary ----
|
|
# graph + indexer are consumed as Go modules pinned in go.mod (luxfi/graph
|
|
# v1.2.3, luxfi/indexer v1.4.5), NOT cloned as siblings — explorer has no
|
|
# replace directive, so under -mod=mod the module cache is authoritative.
|
|
FROM golang:${GO_VERSION}-alpine AS builder
|
|
ARG VERSION=dev
|
|
RUN apk add --no-cache gcc musl-dev sqlite-dev git
|
|
|
|
# luxfi/* modules are private and may be re-tagged; resolve them direct
|
|
# (not via proxy/sumdb) and skip checksum-db cross-checks, exactly as the
|
|
# node image does. The default GITHUB_TOKEN is repo-scoped; a cross-org PAT
|
|
# is injected as the BuildKit secret `ghtok` by docker.yml.
|
|
ENV GOPRIVATE=github.com/lux-private/*,github.com/hanzoai/*
|
|
ENV GONOSUMCHECK=github.com/luxfi/*
|
|
ENV GONOSUMDB=github.com/lux-private/*
|
|
ENV GONOPROXY=github.com/lux-private/*
|
|
ENV GOFLAGS=-mod=mod
|
|
|
|
WORKDIR /src
|
|
COPY go.mod go.sum ./
|
|
# Configure git auth once so both `go mod download` here and the implicit
|
|
# fetch during `go build` can reach private luxfi/* modules.
|
|
RUN --mount=type=secret,id=ghtok,required=false \
|
|
if [ -s /run/secrets/ghtok ]; then \
|
|
git config --global url."https://x-access-token:$(cat /run/secrets/ghtok)@github.com/".insteadOf "https://github.com/"; \
|
|
fi && \
|
|
go mod download
|
|
|
|
COPY . .
|
|
# Tests run here, in the one place that already has cgo + sqlite-dev, so a
|
|
# release that fails them never becomes an image. Nothing else in this repo
|
|
# runs them: .hanzo/workflows/release.yml builds on a v* tag and there is no
|
|
# other workflow, so a test file added to this repo was, until now, never
|
|
# executed by anything but a developer's laptop.
|
|
RUN CGO_ENABLED=1 CGO_CFLAGS="-D_LARGEFILE64_SOURCE" go vet ./... && \
|
|
CGO_ENABLED=1 CGO_CFLAGS="-D_LARGEFILE64_SOURCE" go test ./...
|
|
RUN CGO_ENABLED=1 CGO_CFLAGS="-D_LARGEFILE64_SOURCE" \
|
|
go build -trimpath \
|
|
-ldflags="-s -w -X main.version=${VERSION}" \
|
|
-o /out/explorer .
|
|
|
|
# ---- Stage 2: runtime ----
|
|
FROM alpine:3.21
|
|
RUN apk add --no-cache ca-certificates sqlite-libs wget
|
|
COPY --from=builder /out/explorer /usr/local/bin/explorer
|
|
RUN adduser -D -u 65532 explorer
|
|
USER explorer
|
|
VOLUME /data
|
|
ENV DATA_DIR=/data HTTP_ADDR=:8090
|
|
EXPOSE 8090
|
|
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s \
|
|
CMD wget -qO- http://localhost:8090/health || exit 1
|
|
ENTRYPOINT ["explorer"]
|