Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions .github/workflows/pages.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Deploys the reDeploy marketing site (apps/website, Vite static build) to GitHub
# Pages on every push to main. Uses the Actions-based Pages deployment (not classic
# branch-deploy) because the artifact is a build output, not a checked-in folder.
# Custom domain: redeploy.thesolidchain.com (configured in the repo's Pages settings;
# apps/website/public/CNAME travels with the artifact for good measure).
name: pages

on:
push:
branches: [main]
paths:
- "apps/website/**"
- ".github/workflows/pages.yml"
workflow_dispatch:

permissions:
contents: read
pages: write
id-token: write

concurrency:
group: pages
cancel-in-progress: false

jobs:
deploy:
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup
- run: pnpm --filter @redeploy/website build
- uses: actions/configure-pages@v5
- uses: actions/upload-pages-artifact@v3
with:
path: apps/website/dist
- id: deployment
uses: actions/deploy-pages@v4
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2026 Roberto Cano

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
182 changes: 107 additions & 75 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,89 +1,121 @@
# reDeploy
# reDeploy `^^`

reDeploy is a **deployment system built on top of Hardhat Ignition**. It lets you declaratively define
contract deployments (constructor args, inter-contract links, ordering), deploy them **idempotently and
resumably** (a contract already deployed is never re-deployed), apply **resumable post-deployment
configuration**, **verify** both source and on-chain configuration, and **read** existing deployment state from
external systems. A **visual studio** (drag-and-drop) authors the connection/config graph and inspects live
deployments. reDeploy reuses Hardhat Ignition's module engine, journal, and resume semantics wherever possible
rather than reinventing them.
> **Declarative, idempotent, verifiable smart-contract deployments** — built on
> [Hardhat Ignition](https://hardhat.org/ignition). One spec. One graph. One truth.
>
> **Website:** [redeploy.thesolidchain.com](https://redeploy.thesolidchain.com) · a product of **The Solid Chain**

Built for smart-contract teams deploying multi-contract systems across chains who need reproducible, resumable,
verifiable deployments and a visual way to wire and inspect them.
reDeploy lets you declaratively define contract deployments (constructor args, inter-contract links,
ordering), deploy them **idempotently and resumably** — a contract already deployed is never re-deployed, and
an interrupted run picks up exactly where it stopped — apply **resumable post-deployment configuration**,
**verify** both source and on-chain configuration, and **read** deployment state back through a typed API.
A **visual studio** (drag-and-drop) authors the connection/config graph and inspects live deployments.
reDeploy reuses Hardhat Ignition's module engine, journal, and resume semantics wherever possible rather than
reinventing them.

Built for smart-contract teams deploying multi-contract systems across chains who need reproducible,
resumable, verifiable deployments — and a visual way to wire and inspect them.

## Highlights

- **Declarative spec** — contracts, args, `ref`s between them, and explicit ordering in one JSON document.
Args can be literals, per-network **params**, safe **expressions** (`keccak256`, CREATE2 addresses,
arithmetic), async **resolvers**, or values **read live** from already-deployed contracts.
- **Idempotent & resumable** — the Ignition journal is the source of truth. Re-running a deploy skips what's
on-chain, creates only what's missing, and resumes interrupted runs. Safe to run in CI.
- **Post-deploy configuration** — roles, wiring, setters declared as steps (`set` / `grantRole` / `wire`),
applied like migrations: journaled, resumable, re-runnable.
- **Two-layer verification** — source on Etherscan & Sourcify, plus on-chain assertion that the *live
configuration* still matches the declared spec. Drift is a diff, not an incident.
- **Multi-network** — one spec, many networks: per-network parameters, per-network journals, network
selection end-to-end from studio to server.
- **Visual studio** — drag-and-drop authoring over the same engine: simulate the plan, deploy for real,
inspect any live deployment. Emits the same spec files you'd write by hand.

## Quick start

```sh
git clone https://github.com/robercano/reDeploy && cd reDeploy
pnpm install
cp .env.example .env # fill in what you need; never commit .env

# terminal 1 — a local chain
anvil

# terminal 2 — the deploy server
pnpm --filter @redeploy/deploy-server dev

# terminal 3 — the studio (proxies /api to the deploy server)
pnpm --filter @redeploy/studio dev # → http://localhost:5173
```

Prefer the terminal? The `redeploy` CLI wraps the same libraries:

```sh
redeploy simulate --spec protocol.spec.json # plan only, nothing on-chain
redeploy deploy --spec protocol.spec.json # idempotent, resumable
redeploy apply-config --spec protocol.spec.json # post-deploy steps
redeploy verify --source --config # both verification layers
redeploy status # read the journal back
```

Full local walkthrough (Anvil, `.env`, SSE endpoints, real deploy):
**[`docs/RUNBOOK-anvil-deploy.md`](docs/RUNBOOK-anvil-deploy.md)**.

## Packages & apps
- **`packages/core`** — `@redeploy/core`: deployment engine over Ignition — declarative spec, dependency
resolution/ordering, idempotent journal-based resume, plan-only simulate.
- **`packages/config`** — `@redeploy/config`: post-deployment configuration — declarative steps, resumable
partial configuration, config-state idempotency.
- **`packages/verify`** — `@redeploy/verify`: source/bytecode verification (Etherscan/Sourcify) + on-chain
assertion that live configuration matches the declared spec.
- **`packages/reader`** — `@redeploy/reader`: read-only library exposing deployment + config state via a typed
API to external systems.
- **`apps/studio`** — `@redeploy/studio`: visual tool (React + React Flow) for drag-and-drop authoring of
connections/config (emits spec files) and a deployment inspector.
- **`apps/deploy-server`** — `@redeploy/deploy-server`: HTTP server (node:http, no framework) exposing
deployment **simulate** (plan-only) and **real deploy** over `@redeploy/core` (+ `@redeploy/reader`),
consumed by the studio.
- **`contracts/`** — Foundry project: sample interconnected Solidity contracts used as deployment fixtures.

| Module | Package | What it does |
| --- | --- | --- |
| `packages/core` | `@redeploy/core` | Deployment engine over Ignition — declarative spec, dependency resolution/ordering, idempotent journal-based resume, plan-only simulate. |
| `packages/config` | `@redeploy/config` | Post-deployment configuration — declarative steps, resumable partial configuration, args read live from deployed contracts. |
| `packages/verify` | `@redeploy/verify` | Source/bytecode verification (Etherscan/Sourcify) + on-chain assertion that live configuration matches the declared spec. |
| `packages/reader` | `@redeploy/reader` | Read-only typed API over deployment + config state — snapshots and per-network address-book export for external systems. |
| `apps/cli` | `@redeploy/cli` | The `redeploy` command — deploy/simulate/apply-config/verify/status/snapshot over the libraries. |
| `apps/studio` | `@redeploy/studio` | Visual tool (React + React Flow) for drag-and-drop authoring of connections/config (emits spec files) and a deployment inspector. |
| `apps/deploy-server` | `@redeploy/deploy-server` | Minimal `node:http` server exposing simulate (plan-only), real deploy, deployment state, and network discovery to the studio and other clients. |
| `apps/website` | `@redeploy/website` | The public one-page site served at redeploy.thesolidchain.com. |
| `contracts/` | — | Foundry project: sample interconnected Solidity contracts used as deployment fixtures. |

## Deploy server
`apps/deploy-server` is a minimal `node:http` server (no framework) that exposes deployment simulation and
execution as an HTTP API for the studio (and any other client). It listens on `127.0.0.1:8787` by default
(override with the `PORT` / `HOST` env vars; `HOST` stays loopback unless explicitly overridden). It loads a
repo-root `.env` on startup — real `process.env` values always take precedence over the file.

Endpoints:
`apps/deploy-server` is a minimal `node:http` server (no framework) listening on `127.0.0.1:8787` by default
(`PORT` / `HOST` env overrides; `HOST` stays loopback unless explicitly overridden). It loads a repo-root
`.env` on startup — real `process.env` values take precedence.

- **`GET /health`** → `{ "status": "ok" }`.
- **`GET /api/deployment`** → read-only JSON `DeploymentView` (`{ contracts, configSteps, warnings }`), built
from the on-disk Ignition journal. Returns the empty view (`{contracts:[],configSteps:[],warnings:[]}`) for a
never-deployed directory, or `500 { "error": "Failed to read deployment state" }` on other read failures. The
deployment directory is resolved **strictly from server env** — never from client input — as a deliberate
security boundary against path traversal.
- **`POST /api/simulate`** — plan-only, no chain writes. Body is a `DeploymentSpec` JSON document. Response is
`Content-Type: text/event-stream` (SSE): zero or more `event: step` frames (one per planned step, each
augmented with `address: null`), followed by a terminal `event: done` frame — `{success:true}` on success, or
`{success:false, errors:[...]}` on failure.
- **`POST /api/deploy`** — a **real** deploy that broadcasts transactions on-chain. Body is a `DeploymentSpec`
JSON document. Response is SSE: an `event: progress` frame (`{phase:"deploying"}`), then a terminal
`event: done` frame — `{success:true, deployment: DeploymentView | null, warning?}` on success, or
`{success:false, errors:[{code?, message}]}` on failure.

Environment variables read by the deploy path (values are never echoed in responses or logs):
- `RPC_URL` — JSON-RPC endpoint. Defaults to `http://127.0.0.1:8545` (Anvil's default).
- `FOUNDRY_OUT` — Foundry artifacts directory. Defaults to `<repo>/contracts/out`.
- `DEPLOYER_PRIVATE_KEY` — required for real deploys (`POST /api/deploy`); accepted with or without a `0x`
prefix. Missing → a terminal `done{success:false}` SSE error, not a crash.
- `DEPLOYMENT_DIR` — where the Ignition journal is persisted. Defaults to an OS-temp directory
(`redeploy-deployments/default`). Successful real deploys also persist a snapshot under
`<DEPLOYMENT_DIR>/snapshots/<takenAt>.json`.
- **`GET /api/deployment`** → read-only `DeploymentView` (`{ contracts, configSteps, warnings }`) built from
the on-disk Ignition journal. The deployment directory is resolved **strictly from server env** — never from
client input — as a deliberate boundary against path traversal.
- **`GET /api/networks`** → the configured network registry for multi-network deploys.
- **`POST /api/simulate`** → plan-only, no chain writes. SSE stream: `step` frames, then a terminal `done`.
- **`POST /api/deploy`** → a **real** deploy that broadcasts on-chain. SSE stream: `progress`, then a
terminal `done` with the resulting `DeploymentView`. Secrets are never echoed in responses or logs.

Environment variables for the deploy path: `RPC_URL` (defaults to Anvil's `http://127.0.0.1:8545`),
`FOUNDRY_OUT` (defaults to `contracts/out`), `DEPLOYER_PRIVATE_KEY` (required for real deploys — use a
throwaway key locally, a keystore/hardware wallet for anything real), `DEPLOYMENT_DIR` (journal + snapshot
location). See [`.env.example`](.env.example).

## Studio deploy flow
The studio (`apps/studio`, Vite dev server on `:5173`) proxies `/api` requests to the deploy-server at
`http://127.0.0.1:8787` (override via `VITE_DEPLOY_SERVER_URL`). **Both dev servers must be running** for the
studio's deploy flow to work.

Toolbar actions:
- **`Deploy (simulate)`** — POSTs the current spec to `/api/simulate` for a plan-only preview (shows
`Simulating…` while in flight). No chain writes.
- **`Plan`** — a local, synchronous dry-run diff (create/skip/change) against the last known deployment state;
no network call.
- **`Deploy (real)`** — opens a confirmation modal (red/danger styling, since it's irreversible) and, once
confirmed, POSTs to `/api/deploy` to broadcast on-chain (shows `Deploying…` while in flight).

The read-only **Inspector** renders the resulting `DeploymentView` as a React Flow canvas: each contract node
shows its Deploy ID, contract name, deployed address (blue monospace) or "(not deployed)", and constructor
args; a right-side panel lists config steps with completed/pending badges; a context badge reads
"Real deployment (broadcast on-chain)" or "Simulated plan (dry run)" depending on the source of the view.

For the full step-by-step local walkthrough against Anvil (start Anvil, configure `.env`, run both dev
servers, deploy, and curl the SSE endpoints directly), see
**[`docs/RUNBOOK-anvil-deploy.md`](docs/RUNBOOK-anvil-deploy.md)**.

## Contributor tooling (orchestrator harness)
This repo is developed using an orchestrated multi-agent Claude Code setup (a lead orchestrator that scopes
work to worktree-isolated implementers, gated by adversarial reviewers). If you're contributing to reDeploy (or
adapting its `.claude/` harness for another project), see:
The studio (`:5173`) proxies `/api` to the deploy server (`:8787`, override `VITE_DEPLOY_SERVER_URL`); both
dev servers must run for the deploy flow. Toolbar: **Deploy (simulate)** for a plan-only preview,
**Plan** for a local create/skip/change diff, **Deploy (real)** for a confirmed on-chain broadcast — results
render in the read-only Inspector (React Flow canvas with addresses, args, and config-step status).

## Contributing & the orchestrator harness

This repo is developed with an orchestrated multi-agent Claude Code setup — a lead orchestrator scoping work
to worktree-isolated implementers, gated by adversarial reviewers and CI. If you're contributing (or adapting
the `.claude/` harness for your own project):

- **[`docs/GETTING_STARTED.md`](docs/GETTING_STARTED.md)** — harness setup, step by step.
- **[`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md)** — the orchestrator/implementer/reviewer mental model.
- **[`docs/USAGE.md`](docs/USAGE.md)** — how to drive the orchestrator day to day.

Gates for every module (build · lint · typecheck · test · coverage ≥ 80%) run locally via
`.claude/scripts/gate.sh` and in CI on every PR.

## License

[MIT](LICENSE) © 2026 Roberto Cano · The Solid Chain
3 changes: 2 additions & 1 deletion apps/cli/package.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
{
"name": "@redeploy/cli",
"version": "0.0.0",
"license": "MIT",
"private": true,
"type": "module",
"description": "Thin command-line entry point for reDeploy: deploy/simulate (core), apply-config (config), verify (verify), status/snapshot (reader). Wraps existing library APIs no reimplemented business logic.",
"description": "Thin command-line entry point for reDeploy: deploy/simulate (core), apply-config (config), verify (verify), status/snapshot (reader). Wraps existing library APIs \u2014 no reimplemented business logic.",
"bin": {
"redeploy": "dist/index.js"
},
Expand Down
1 change: 1 addition & 0 deletions apps/deploy-server/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"name": "@redeploy/deploy-server",
"version": "0.0.0",
"license": "MIT",
"private": true,
"type": "module",
"description": "HTTP deploy server: exposes deployment simulation and execution as an API. Built on node:http, no framework deps.",
Expand Down
1 change: 1 addition & 0 deletions apps/studio/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"name": "@redeploy/studio",
"version": "0.0.0",
"license": "MIT",
"private": true,
"type": "module",
"description": "Visual tool: drag-and-drop authoring of contract connections and configuration (emits spec files) plus a deployment inspector. React + React Flow.",
Expand Down
1 change: 1 addition & 0 deletions apps/website/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"name": "@redeploy/website",
"version": "0.0.0",
"license": "MIT",
"private": true,
"type": "module",
"description": "Public marketing site for reDeploy: sells its benefits and showcases Studio features. Static Vite build, no backend.",
Expand Down
1 change: 1 addition & 0 deletions apps/website/public/CNAME
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
redeploy.thesolidchain.com
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"name": "redeploy",
"version": "0.0.0",
"license": "MIT",
"private": true,
"description": "Hardhat Ignition-based deployment system: declarative deploy/config, idempotent resume, verification, reader library, and a visual authoring/inspection studio.",
"type": "module",
Expand All @@ -23,6 +24,8 @@
"solhint": "^5.2.0"
},
"pnpm": {
"onlyBuiltDependencies": ["esbuild"]
"onlyBuiltDependencies": [
"esbuild"
]
}
}
1 change: 1 addition & 0 deletions packages/config/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"name": "@redeploy/config",
"version": "0.0.0",
"license": "MIT",
"private": true,
"type": "module",
"description": "Post-deployment configuration: declarative config steps, resumable partial configuration, config-state idempotency.",
Expand Down
1 change: 1 addition & 0 deletions packages/core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"name": "@redeploy/core",
"version": "0.0.0",
"license": "MIT",
"private": true,
"type": "module",
"description": "Deployment engine on top of Hardhat Ignition: declarative deployment spec, dependency resolution and ordering, idempotent journal-based resume.",
Expand Down
1 change: 1 addition & 0 deletions packages/reader/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"name": "@redeploy/reader",
"version": "0.0.0",
"license": "MIT",
"private": true,
"type": "module",
"description": "Read-only library to load deployment and configuration state and expose a typed API to external systems.",
Expand Down
1 change: 1 addition & 0 deletions packages/verify/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"name": "@redeploy/verify",
"version": "0.0.0",
"license": "MIT",
"private": true,
"type": "module",
"description": "Verification: source/bytecode verification (Etherscan/Sourcify) and on-chain assertion that live configuration matches the declared spec.",
Expand Down
Loading