Skip to content

ci: dispatchable explorer verification for a deployment that already exists - #128

Merged
thedavidmeister merged 1 commit into
mainfrom
2026-08-16-manual-sol-verify
Aug 16, 2026
Merged

ci: dispatchable explorer verification for a deployment that already exists#128
thedavidmeister merged 1 commit into
mainfrom
2026-08-16-manual-sol-verify

Conversation

@thedavidmeister

Copy link
Copy Markdown
Contributor

Adds Manual sol verify: a workflow_dispatch that submits the source of a registry that is already on chain to every supported explorer.

Blocked by rainlanguage/rainix#312 — this is the caller; the reusable it pins at @main lands there first.

Why this exists separately from the deploy

manual-sol-artifacts.yaml submits source only for what its own run broadcast, and the broadcast is idempotent by construction: LibRainDeploy.deployToNetworks skips any network that already has code at the expected address. So once a deploy has landed, re-dispatching it broadcasts nothing, --verify has nothing to submit, and the run is green having verified nothing — a false success, not a repair.

That is the state this repo was in. Both registries broadcast to all five networks on 2026-08-15 and then died on the first explorer with Invalid API Key (#err2): https://github.com/rainlanguage/rain.deploy/actions/runs/31874483065 and https://github.com/rainlanguage/rain.deploy/actions/runs/31874687768. base, base_sepolia, flare and polygon were never attempted at all.

Confirmed the re-dispatch route is a dead end rather than assuming it: script/Deploy.sol:Deploy run against all five networks now logs - Code already exists at expected address, skipping deployment on every one and records no transactions.

Shape

contract and address are dispatch inputs rather than a suite choice with the values baked in, because the addresses and artifact paths already have exactly one home — the candidate declarations in RegistryDeploySuites and the generated snapshots they read — and a second copy in a workflow is a pin that can go stale silently. The deploy prints the pair it wants on its manual verification command: line for every network, whether it deployed there or skipped it, so the values come from a run rather than from memory.

networks defaults to LibRainDeploy.supportedNetworks() in foundry's spelling. Foundry's chain names are not the [rpc_endpoints] aliases: base-sepolia is a chain name and base_sepolia is rejected outright by forge verify-contract --chain, which is worth knowing because the manual verification command: line the deploy prints uses the alias and is therefore not directly runnable for that one network.

It never broadcasts and never reads DEPLOYMENT_KEY.

QA

  • Discriminating tests: n/a — a workflow caller has no unit-testable surface. Exercised end to end instead, against the real explorers, at https://github.com/rainlanguage/rain.deploy/actions/runs/31949208775: the same uses:/with:/secrets: inherit call this file makes, over both registries and all five networks. Result: AddressRegistry and MigrationRegistry verified on arbiscan, basescan, sepolia.basescan, flare-explorer and polygonscan.
  • Mutations applied: n/a — the diff is one workflow file with no branch a mutation could survive. The input shape was instead falsified against the alternative: a suite choice was tried first and rejected because it can only work by copying the deployed addresses into the workflow, giving this repo's most load-bearing constants a second home.
  • Oracle: the explorers, not the run. Verified is read back from the explorer itself — https://basescan.org/address/0x25aC2b82915f191dbE64e65BAeDDD68b97b68fe1, https://polygonscan.com/address/0x6E3aE74aDCd6CF28A1b2F685D5E709ffE44D429D and https://flare-explorer.flare.network/api?module=contract&action=getsourcecode — and the --watch responses quoted in the run are the explorer's own words.
  • Category check: covers the category rather than the incident. Nothing here is specific to Invalid API Key; it is the repair path for any contract that is on chain and unverified, including a network added after a deploy, an explorer that was down, and a rate-limited submission.

…exists

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@thedavidmeister thedavidmeister self-assigned this Aug 16, 2026
@coderabbitai

coderabbitai Bot commented Aug 16, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@thedavidmeister, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 47 minutes

Limit details: You’ve used all 1 included review currently available under your plan.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 87b4e966-45c6-4d60-ae10-37a0a59b2308

📥 Commits

Reviewing files that changed from the base of the PR and between 369cfe9 and 0b3d8e4.

📒 Files selected for processing (1)
  • .github/workflows/manual-sol-verify.yaml

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@thedavidmeister

Copy link
Copy Markdown
Contributor Author

Reviewed 0b3d8e4: ready. Read the diff.

One new workflow_dispatch-only workflow, calling rainix's verify reusable. It never broadcasts and never reads DEPLOYMENT_KEYforge verify-contract talks to the explorer API and nothing else — so it is safe to re-run and is a no-op against an explorer that already holds the source.

The header states the reason this exists, and it is the thing established empirically today: manual-sol-artifacts.yaml submits source only for what its own run broadcast, and the broadcast is idempotent, so a re-dispatch against networks that already hold the code broadcasts nothing, leaves --verify an empty queue, and goes green having verified nothing. That is exactly how both deploys ended up unverified for a day.

The networks input default carries the base-sepolia spelling rather than the [rpc_endpoints] alias base_sepolia, which clap rejects outright — the same defect that makes the command deployToNetworks prints for humans un-runnable for that one network.

CI: test and legal green. rainix / static fails at agent-context-capCLAUDE.md at 24227 bytes against the 4096 cap. Repo-wide and pre-existing: main's own tip fails the identical step, and this PR's whole diff is one new YAML file. A separate PR is cutting it.

One residual, not blocking: the networks default restates LibRainDeploy.supportedNetworks() in a third spelling, and the comment saying it has to move when that does is the only thing binding them. Same shape as the drift #112 closed for [rpc_endpoints] and [etherscan], and nothing tests this one.

Note this pins @main on a reusable that has not merged yet — rainlanguage/rainix#312 is still open. uses: resolves at dispatch time, not at merge time, so this is inert until then; a dispatch before 312 lands fails with an unresolved-workflow error and nothing else.

@thedavidmeister
thedavidmeister merged commit b98107c into main Aug 16, 2026
3 of 4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant