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
12 changes: 6 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ name: Community Tests
on:
workflow_call:
inputs:
remotes:
description: 'RPC endpoint(s), comma-separated'
remote:
description: 'RPC endpoint'
required: true
type: string
chain_id:
Expand All @@ -26,8 +26,8 @@ on:

workflow_dispatch:
inputs:
remotes:
description: 'RPC endpoint(s), comma-separated'
remote:
description: 'RPC endpoint'
required: true
type: string
chain_id:
Expand Down Expand Up @@ -55,7 +55,7 @@ jobs:
- name: Run one-shot tests
run: |
make tests-one-shot \
REMOTES="${{ inputs.remotes }}" \
REMOTE="${{ inputs.remote }}" \
CHAINID="${{ inputs.chain_id }}" \
FUNDER_SCRIPT="${{ inputs.funder_script }}"

Expand All @@ -68,6 +68,6 @@ jobs:
- name: Run repeatable tests
run: |
make tests-repeatable \
REMOTES="${{ inputs.remotes }}" \
REMOTE="${{ inputs.remote }}" \
CHAINID="${{ inputs.chain_id }}" \
FUNDER_SCRIPT="${{ inputs.funder_script }}"
6 changes: 3 additions & 3 deletions .github/workflows/test-13.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
name: test-13

# Network-specific workflow for test-13.
# Calls the generic ci.yml with the right remotes, chain_id and funder_script.
# Calls the generic ci.yml with the right remote, chain_id and funder_script.
#
# Optional repository variables:
# vars.REMOTES_TEST13 — RPC endpoint(s), comma-separated (default: rpc.test-13-aeddi-1.gnoland.network)
# vars.REMOTE_TEST13 — RPC endpoint (default: rpc.test-13-aeddi-1.gnoland.network)
# vars.CHAINID_TEST13 — chain ID (default: test-13)

on:
Expand All @@ -24,7 +24,7 @@ jobs:
run:
uses: ./.github/workflows/ci.yml
with:
remotes: ${{ vars.REMOTES_TEST13 || 'https://rpc.test-13-aeddi-1.gnoland.network,https://rpc.test-13-gfanton-1.gnoland.network,https://rpc.test-13-moul-1.gnoland.network' }}
remote: ${{ vars.REMOTE_TEST13 || 'https://rpc.test-13-aeddi-1.gnoland.network' }}
chain_id: ${{ vars.CHAINID_TEST13 || 'test-13' }}
funder_script: ./funders/test-13.sh
test_type: ${{ inputs.test_type || 'both' }}
18 changes: 9 additions & 9 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,40 +1,40 @@
.PHONY: tests-one-shot tests-repeatable help

REMOTES ?=
REMOTE ?=
CHAINID ?=
FUNDER_SCRIPT ?=

# Contributor subdirectories are detected automatically under tests/.
CONTRIB_DIRS := $(patsubst %/Makefile,%,$(wildcard tests/*/Makefile))

## tests-one-shot : fund accounts then run one-shot tests (REMOTES, CHAINID, FUNDER_SCRIPT)
## tests-one-shot : fund accounts then run one-shot tests (REMOTE, CHAINID, FUNDER_SCRIPT)
tests-one-shot:
@for dir in $(CONTRIB_DIRS); do \
echo ""; \
echo "==> $$dir — funding (one-shot)"; \
ARGS=$$($(MAKE) -C $$dir list-funding-one-shot --no-print-directory \
REMOTES=$(REMOTES) CHAINID=$(CHAINID)); \
REMOTE=$(REMOTE) CHAINID=$(CHAINID)); \
if [ -n "$$ARGS" ]; then \
REMOTES=$(REMOTES) CHAINID=$(CHAINID) $(FUNDER_SCRIPT) $$ARGS || exit 1; \
REMOTE=$(REMOTE) CHAINID=$(CHAINID) $(FUNDER_SCRIPT) $$ARGS || exit 1; \
fi; \
echo "==> $$dir — tests (one-shot)"; \
$(MAKE) -C $$dir tests-one-shot --no-print-directory \
REMOTES=$(REMOTES) CHAINID=$(CHAINID) || exit 1; \
REMOTE=$(REMOTE) CHAINID=$(CHAINID) || exit 1; \
done

## tests-repeatable : fund accounts then run repeatable tests (REMOTES, CHAINID, FUNDER_SCRIPT)
## tests-repeatable : fund accounts then run repeatable tests (REMOTE, CHAINID, FUNDER_SCRIPT)
tests-repeatable:
@for dir in $(CONTRIB_DIRS); do \
echo ""; \
echo "==> $$dir — funding (repeatable)"; \
ARGS=$$($(MAKE) -C $$dir list-funding-repeatable --no-print-directory \
REMOTES=$(REMOTES) CHAINID=$(CHAINID)); \
REMOTE=$(REMOTE) CHAINID=$(CHAINID)); \
if [ -n "$$ARGS" ]; then \
REMOTES=$(REMOTES) CHAINID=$(CHAINID) $(FUNDER_SCRIPT) $$ARGS || exit 1; \
REMOTE=$(REMOTE) CHAINID=$(CHAINID) $(FUNDER_SCRIPT) $$ARGS || exit 1; \
fi; \
echo "==> $$dir — tests (repeatable)"; \
$(MAKE) -C $$dir tests-repeatable --no-print-directory \
REMOTES=$(REMOTES) CHAINID=$(CHAINID) || exit 1; \
REMOTE=$(REMOTE) CHAINID=$(CHAINID) || exit 1; \
done

## help : show available targets
Expand Down
144 changes: 109 additions & 35 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ Every contributor subdirectory must expose these four rules:
| `tests-one-shot` | Runs tests that deploy on-chain state (realm deploys...) |
| `tests-repeatable` | Runs tests that can be re-executed safely |

All rules accept `REMOTES` (comma-separated RPC list) and `CHAINID` variables.
All rules accept `REMOTE` (single RPC endpoint) and `CHAINID` variables.

Before each run, the root Makefile calls `list-funding-*`, passes the returned
addresses to the funder script (test1), then runs the tests.
Expand All @@ -44,41 +44,33 @@ Run `make help` from any directory to list available targets.

## Running tests

Against test-13 with 3 validator nodes:
Against test-13:

```sh
make tests-one-shot \
REMOTES=https://rpc.test-13-aeddi-1.gnoland.network,https://rpc.test-13-gfanton-1.gnoland.network,https://rpc.test-13-moul-1.gnoland.network \
REMOTE=https://rpc.test-13-aeddi-1.gnoland.network \
CHAINID=test-13 \
FUNDER_SCRIPT=./funders/test-13.sh
```

Against a single custom RPC:

```sh
make tests-one-shot REMOTES=https://rpc.test12.testnets.gno.land CHAINID=test12
make tests-one-shot REMOTE=https://rpc.test12.testnets.gno.land CHAINID=test12
```

Against multiple validator nodes (stress tests will hit each one):
With a custom funder:

```sh
make tests-one-shot \
REMOTES=https://rpc1.gnoland.network,https://rpc2.gnoland.network,https://rpc3.gnoland.network \
CHAINID=test-13
```

With a custom funder script:

```sh
make tests-one-shot FUNDER_SCRIPT=./funders/test-13.sh REMOTES=... CHAINID=test-13
make tests-one-shot FUNDER_SCRIPT=./funders/test-13.sh REMOTE=... CHAINID=test-13
```

Directly from a contributor subdirectory:

```sh
cd tests/samourai-crew
make help
make tests-one-shot REMOTES=https://rpc.test12.testnets.gno.land CHAINID=test12
make tests-one-shot REMOTE=https://rpc.test12.testnets.gno.land CHAINID=test12
```

## Adding your own tests
Expand All @@ -100,44 +92,126 @@ gnokey add my-test-account -recover

### 3. Edit the Makefile

Declare your test account address and funding amounts:
Implement `list-funding-one-shot` and `list-funding-repeatable` so they print
space-separated `address amount` pairs — one pair per account that needs funding:

```makefile
ADDR_1 := g1your_address_here

FUND_AMOUNT_ONE_SHOT := 30000000ugnot # ~30 transactions at 1M ugnot each
FUND_AMOUNT_REPEATABLE := 10000000ugnot

list-funding-one-shot:
@echo "$(ADDR_1) $(FUND_AMOUNT_ONE_SHOT)"

list-funding-repeatable:
@echo "$(ADDR_1) $(FUND_AMOUNT_REPEATABLE)"
```text
g1abc... 30000000ugnot
g1def... 10000000ugnot
```

**Multiple wallets:** declare all addresses in `list-funding-*` as space-separated
`address amount` pairs. The funder will fund each one before the tests run.
Multiple pairs on a single line or across lines are both accepted. If you have no
tests of a given type, return an empty string (the funder skips it cleanly).

How you store and supply the addresses and mnemonics is up to you — Makefile
variables, a sourced env file, a helper script, or anything else. What matters is
that `list-funding-*` produces the right output and that `tests-one-shot` /
`tests-repeatable` inject the credentials the container needs.

### 4. Write your Dockerfile

Your `Dockerfile` must:

- Accept `one-shot` or `repeatable` as a command argument
- Contain your test account mnemonic (testnet key, no real value)
- Read `REMOTES` and `CHAINID` from env
- Read `REMOTE`, `CHAINID`, and any account variables from env (injected via `docker run -e`)
- Sign the network CLA if required (see `samourai-crew/run_tests.sh` for an example)

**Do not hardcode mnemonics in the Dockerfile.** Define them in your Makefile and pass
them at runtime via `docker run -e` (see step 3). This way addresses and mnemonics stay
in one place and the Dockerfile contains only logic, not secrets.

The image can use **any language** (shell, Go, Python, etc.). See `samourai-crew/` for a shell-based example.

### 5. What your container receives at runtime

| Variable | Description |
| --------- | --------------------------------------------------- |
| `REMOTES` | Comma-separated list of RPC endpoints |
| `CHAINID` | Chain ID |
| Variable | Source | Description |
| ------------- | ----------------- | ---------------------------------------------------- |
| `REMOTE` | root Makefile | Single RPC endpoint |
| `CHAINID` | root Makefile | Chain ID |
| `MY_ADDR` | your Makefile | Your testnet account address (name it as you like) |
| `MY_MNEMONIC` | your Makefile | Your testnet mnemonic (name it as you like) |

`MY_ADDR` and `MY_MNEMONIC` are examples — use whatever variable names and injection mechanism fit your setup.

**Reading REMOTE inside your container:**
CI passes the RPC endpoint as `REMOTE`. Your container's entrypoint reads it directly.

Example in shell:

```sh
REMOTE="${REMOTE:-http://127.0.0.1:26657}"
```

See `tests/samourai-crew/` for a complete shell-based implementation.

The funding has already been done by the time your container starts.

## Adding a new network to CI

To wire a new chain into CI, you need two files.

### 1. Create a funder script

```sh
cp funders/_template.sh funders/my-chain.sh
```

Edit `funders/my-chain.sh` and set the three defaults:

```sh
REMOTE="${REMOTE:-https://rpc.my-chain.example.com}"
CHAINID="${CHAINID:-my-chain-id}"
FUNDER_MNEMONIC="${FUNDER_MNEMONIC:-source bonus chronic canvas draft south burst lottery vacant surface solve popular case indicate oppose farm nothing bullet exhibit title speed wink action roast}"
```

The last line is the public test1 mnemonic — replace it if your network uses a different funded account.

### 2. Create a workflow file

```sh
cp .github/workflows/test-13.yml .github/workflows/my-chain.yml
```

Edit `.github/workflows/my-chain.yml`:

```yaml
name: my-chain

on:
push:
branches: [main]
pull_request:
branches: [main]
workflow_dispatch:
inputs:
test_type:
description: 'Test type'
type: choice
default: both
options: [one-shot, repeatable, both]

jobs:
run:
uses: ./.github/workflows/ci.yml
with:
remote: ${{ vars.REMOTE_MY_CHAIN || 'https://rpc.my-chain.example.com' }}
chain_id: ${{ vars.CHAINID_MY_CHAIN || 'my-chain-id' }}
funder_script: ./funders/my-chain.sh
test_type: ${{ inputs.test_type || 'both' }}
```

### 3. (Optional) Override the RPC via repository variable

If the network RPC changes without a code update, set a repository variable in
**GitHub → Settings → Secrets and variables → Actions → Variables**:

| Variable | Example value |
| ------------------ | --------------------------------------- |
| `REMOTE_MY_CHAIN` | `https://rpc.my-chain.example.com` |
| `CHAINID_MY_CHAIN` | `my-chain-id` |

The workflow reads these at runtime and falls back to the hardcoded defaults if not set.

## Current contributors

| Directory | Description |
Expand Down
50 changes: 17 additions & 33 deletions _template/Makefile
Original file line number Diff line number Diff line change
@@ -1,43 +1,27 @@
.PHONY: list-funding-one-shot list-funding-repeatable tests-one-shot tests-repeatable build help
.PHONY: list-funding-one-shot list-funding-repeatable tests-one-shot tests-repeatable help

# Override REMOTES and CHAINID to target a live network:
# make tests-one-shot REMOTES=https://rpc.test-13-aeddi-1.gnoland.network CHAINID=test-13
REMOTES ?=
CHAINID ?= test
IMAGE := $(shell basename $(CURDIR))

# TODO: replace with your testnet account address(es)
ADDR_1 := TODO_REPLACE_ADDR_1

# Funding amounts — adjust to match your tests' gas needs (~1M ugnot per tx)
FUND_AMOUNT_ONE_SHOT := 30000000ugnot
FUND_AMOUNT_REPEATABLE := 10000000ugnot
REMOTE ?=
CHAINID ?=

## list-funding-one-shot : print address/amount pairs to fund before one-shot tests
list-funding-one-shot:
@echo "$(ADDR_1) $(FUND_AMOUNT_ONE_SHOT)"
@# Example: @echo "g1_addr1 30000000ugnot g1_addr2 10000000ugnot"
@echo "not implemented" >&2 && exit 1

## list-funding-repeatable : print address/amount pairs to fund before repeatable tests
list-funding-repeatable:
@echo "$(ADDR_1) $(FUND_AMOUNT_REPEATABLE)"

## build : build the Docker test image
build:
docker build -t $(IMAGE) .

## tests-one-shot : run one-shot tests (REMOTES, CHAINID)
tests-one-shot: build
docker run --rm \
-e REMOTES=$(REMOTES) \
-e CHAINID=$(CHAINID) \
$(IMAGE) one-shot

## tests-repeatable : run repeatable tests (REMOTES, CHAINID)
tests-repeatable: build
docker run --rm \
-e REMOTES=$(REMOTES) \
-e CHAINID=$(CHAINID) \
$(IMAGE) repeatable
@# Example: @echo "g1_addr1 10000000ugnot"
@echo "not implemented" >&2 && exit 1

## tests-one-shot : run one-shot tests (REMOTE, CHAINID)
tests-one-shot:
@# Run one-shot tests (only bash and Docker allowed as deps) or no-op if none exist.
@echo "not implemented" >&2 && exit 1

## tests-repeatable : run repeatable tests (REMOTE, CHAINID)
tests-repeatable:
@# Run repeatable tests (only bash and Docker allowed as deps) or no-op if none exist.
@echo "not implemented" >&2 && exit 1

## help : show available targets
help:
Expand Down
9 changes: 3 additions & 6 deletions funders/_template.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,9 @@
# FUNDER_SCRIPT=./funders/test-14.sh make tests-one-shot CHAINID=test-14
#
# To override any default at call time:
# REMOTES=https://my-rpc.example.com FUNDER_SCRIPT=./funders/test-14.sh make tests-one-shot CHAINID=test-14
# REMOTE=https://my-rpc.example.com FUNDER_SCRIPT=./funders/test-14.sh make tests-one-shot CHAINID=test-14

# One or more RPC endpoints, comma-separated.
# The first one is used for single-endpoint operations (funding, queries).
# All of them are distributed across sybil stress wallets when running multi-RPC tests.
REMOTES="${REMOTES:-https://rpc.your-network.example.com}"
REMOTE="${REMOTE:-https://rpc.your-network.example.com}"

# Chain ID of the target network.
CHAINID="${CHAINID:-your-chain-id}"
Expand All @@ -23,7 +20,7 @@ CHAINID="${CHAINID:-your-chain-id}"
# Defaults to the public test1 mnemonic — replace with your own if needed.
FUNDER_MNEMONIC="${FUNDER_MNEMONIC:-source bonus chronic canvas draft south burst lottery vacant surface solve popular case indicate oppose farm nothing bullet exhibit title speed wink action roast}"

export REMOTES CHAINID FUNDER_MNEMONIC
export REMOTE CHAINID FUNDER_MNEMONIC

FUNDERS_DIR="$(cd "$(dirname "$0")" && pwd)"
exec "$FUNDERS_DIR/gnokey-send.sh" "$@"
Loading
Loading