Skip to content

Split subgraph on deployment facts, not wholesale: manifest as a template in the lib repo, networks.json in the deploy repo #149

Description

@thedavidmeister

rainlanguage/rain.metadata.deploy#4 and #148 move the whole
subgraph/ directory — all 15 files — out of the library repo. That cut costs the
schema drift guard and it is not the cut the tooling wants.

The cut this issue proposes

Split on whether a file carries deployment facts, not on "the subgraph".

Stays in rain.metadatasubgraph.yaml (as a template, see below), schema.graphql,
src/metaBoard.ts, src/transaction.ts, tests/*, package.json,
docker-compose.yml. This is subgraph SOURCE. The repo runs graph codegen and
graph test and never graph build --network.

Moves to rain.metadata.deploynetworks.json, the Goldsky deploy workflow, and
the deploy-record test. At deploy time the workflow checks out the library repo's
subgraph source into a temp dir, drops networks.json beside it, runs
graph build --network <x> there, and deploys. The manifest mutation lands in the temp
copy and is never committed.

That direction is deploy → library, which the split allows. The current PRs need the
library's interface artifact path repointed at the deploy repo's concrete precisely
because they move the manifest the wrong way.

The template

subgraph.yaml's source: block keeps only abi: MetaBoard. No address, no
startBlock.

Measured, do not re-derive

Run on rain.metadata@main in the pinned rainix shell, baseline vs stub, both after
forge soldeer install:

  • The stub builds. With address and startBlock deleted from subgraph.yaml,
    subgraph-build completes for all five networks, exit 0, and the built manifest at
    subgraph/build/subgraph.yaml carries the real matic address. graph build --network
    fills both from networks.json.
  • graph codegen does not need them. It ran and printed "Types generated
    successfully" on the stubbed manifest before any graph build had filled anything.
  • graph build --network writes back into the SOURCE subgraph.yaml, not only
    build/.
    After the run the stub's own committed manifest carried both fields again.
    A stub does not stay stubbed in a tree that runs build.

That last point is why the template only works if the library repo never runs
graph build --network, and it is also a live latent bug today:

  • subgraph_networks iterates jq keys, so the order is alphabetical —
    arbitrum-one, base, base-sepolia, flare, matic.
  • Whichever network sorts LAST is what subgraph.yaml holds after every build.
  • matic sorts last today and matic is what is committed, so git status is clean by
    coincidence. Add a network sorting after matic and every subgraph-build leaves a
    dirty tree, and nothing checks.

So the committed inline address/startBlock are not a template default. They are a
residue of the last build. The template removes the residue rather than documenting it.

What this recovers

schema.graphql stays in the same tree as crates/metaboard/src/schema/metaboard.graphql,
so the consumer-snapshot drift check is local and per-PR: regenerate the snapshot from
the schema and git diff --exit-code, the same shape as rainix-copy-artifacts. No
token, no introspection, no cross-repo fetch.

That also replaces crates/cli/src/cli/schema_check.rs (948 lines of bespoke GraphQL
comparison) with a generator plus a diff. The snapshot is the entity-type projection of
schema.graphql, which is what schema_check's own check() already compares, so it is
derivable rather than hand-written.

Why this matters to consumers: cynic's build.rs registers the schema from the local
snapshot and checks the QueryFragment derives against THAT file at compile time. Drift
is invisible to the compiler — the crate builds against a stale snapshot, sends the
query, and the live subgraph rejects it at runtime as CynicClientError::GraphqlError,
surfacing through FetchAuthoringMetaV2WordError, which raindex propagates in its own
error enum. The queried surface is metaV1S(where: {metaHash|subject})
metaHash, meta, sender, id, metaBoard { address }, subject and
metaBoards(first, skip)address. Rename or retype any of those and every consumer's
meta fetch fails; adding fields breaks nothing.

Two verifications this work must run

  1. Matchstick on a stubbed manifest. graph test mocks chain state rather than
    connecting, so it should not need the address, but the repo's tests currently run
    against a full manifest and this was not testable locally (no docker). If graph test
    needs the address, say so and propose the alternative rather than putting the address
    back silently.
  2. network: in the template. The stub above kept network: matic hardcoded and the
    build passed because --network overrides it. Leaving a real network name in a
    template is the same misleading residue one level up. Test whether graph accepts a
    placeholder; if it does not, record why the name has to stay.

Consequences for the open PRs

Both #4 and #148 need reworking rather than amending — instead of moving 15 files out,
move one file plus two workflows.

Four of #4's five assertions survive in the deploy repo unchanged, because they work off
networks.json plus the deploy records: every frozen release indexed on every network,
one address per datasource across networks, every indexed network covered by
supportedNetworks(). networks.json carries the datasource names and addresses itself,
so no manifest is needed for those.

The fifth — the manifest's ABI path derived from the deploy candidate's artifactPath
moves to rain.metadata and becomes a pin against the interface, alongside the
MetaV1_2 event-signature pin that is already manifest-vs-interface.

Out of scope, stated so it is not mistaken for fixed

Three MetaBoard addresses are in play and nothing reconciles them under any cut:
networks.json says 0xfb8437Ae…, src/generated/candidate/MetaBoard.sol says
0x8fD50fF9…, and the one live subgraph indexes 0x59401c93… under the name
metadata-base, not metaboard-*. Separate work.

subgraph-deploy remains unexercisable without CI_GOLDSKY_TOKEN.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions