Skip to content

Commit cd9bcb0

Browse files
committed
feat: add integration tests with sekin deployment
- Add integration-test job to CI that deploys SEKAI from kiracore/sekin - Create ci-integration-test.yaml scenario testing 12 query operations - Add resolveAddress() to mapper for keys.parse, auth.account, gov.roles, gov.permissions, gov.role-assign, staking.validators, staking.validator - Resolver handles both key names and actual kira addresses
1 parent 3af7140 commit cd9bcb0

File tree

3 files changed

+223
-23
lines changed

3 files changed

+223
-23
lines changed

.github/workflows/ci.yml

Lines changed: 89 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,10 @@ jobs:
3434
- name: Run go vet
3535
run: go vet ./...
3636

37-
test:
38-
name: Test
37+
build:
38+
name: Build Check
3939
runs-on: ubuntu-latest
40+
needs: [lint]
4041
steps:
4142
- uses: actions/checkout@v4
4243

@@ -46,13 +47,20 @@ jobs:
4647
go-version: '1.21'
4748
cache: true
4849

49-
- name: Run tests
50-
run: go test -v -race ./...
50+
- name: Build
51+
run: |
52+
CGO_ENABLED=0 go build -o sekai-cli ./cmd/sekai-cli
53+
./sekai-cli --help
5154
52-
build:
53-
name: Build Check
55+
integration-test:
56+
name: Integration Tests
5457
runs-on: ubuntu-latest
55-
needs: [lint, test]
58+
needs: [lint]
59+
env:
60+
CONTAINER: sekin-sekai-1
61+
CHAIN_ID: testnet-1
62+
SEKAI_CONTAINER: sekin-sekai-1
63+
SEKAI_CHAIN_ID: testnet-1
5664
steps:
5765
- uses: actions/checkout@v4
5866

@@ -62,7 +70,78 @@ jobs:
6270
go-version: '1.21'
6371
cache: true
6472

65-
- name: Build
73+
- name: Build sekai-cli
74+
run: CGO_ENABLED=0 go build -o sekai-cli ./cmd/sekai-cli
75+
76+
- name: Clone sekin repository
77+
run: git clone --depth 1 https://github.com/kiracore/sekin.git /tmp/sekin
78+
79+
- name: Start SEKAI infrastructure
6680
run: |
67-
CGO_ENABLED=0 go build -o sekai-cli ./cmd/sekai-cli
68-
./sekai-cli --help
81+
cd /tmp/sekin
82+
docker compose up -d sekai syslog-ng
83+
echo "Waiting for containers to start..."
84+
sleep 10
85+
docker ps
86+
87+
- name: Initialize SEKAI network
88+
run: |
89+
# Run the spin-local-testnet script steps (except start which blocks)
90+
echo ">>> Step 1: Initialize sekaid"
91+
docker exec ${CONTAINER} /scaller init --chain-id "${CHAIN_ID}" --moniker "CI-Node"
92+
93+
echo ">>> Step 2: Add genesis key"
94+
docker exec ${CONTAINER} /scaller keys-add --name genesis
95+
96+
echo ">>> Step 3: Add genesis account"
97+
docker exec ${CONTAINER} /scaller add-genesis-account --name genesis --coins 300000000000000ukex
98+
99+
echo ">>> Step 4: Claim validator role"
100+
docker exec ${CONTAINER} /scaller gentx-claim --name genesis --moniker "CI-Validator"
101+
102+
echo ">>> Step 5: Start sekaid (background with auto-restart)"
103+
docker exec -d ${CONTAINER} /scaller start --restart always
104+
105+
echo "Waiting for node to start producing blocks..."
106+
sleep 30
107+
108+
- name: Wait for chain to be ready
109+
run: |
110+
echo "Checking chain status..."
111+
for i in {1..30}; do
112+
if docker exec ${CONTAINER} /sekaid status 2>/dev/null | grep -q '"catching_up":false'; then
113+
echo "Chain is ready and synced!"
114+
docker exec ${CONTAINER} /sekaid status
115+
exit 0
116+
fi
117+
echo "Attempt $i/30: Chain not ready yet, waiting..."
118+
sleep 5
119+
done
120+
echo "Chain did not become ready in time"
121+
docker exec ${CONTAINER} /sekaid status || true
122+
exit 1
123+
124+
- name: Run sekai-cli status check
125+
run: ./sekai-cli status
126+
127+
- name: Run scenario-based integration test
128+
run: ./sekai-cli scenario run examples/scenarios/ci-integration-test.yaml
129+
130+
- name: Run Go integration tests
131+
run: go test -v -timeout 30m ./test/integration/...
132+
133+
- name: Collect logs on failure
134+
if: failure()
135+
run: |
136+
echo "=== Docker containers ==="
137+
docker ps -a
138+
echo "=== SEKAI container logs ==="
139+
docker logs ${CONTAINER} 2>&1 | tail -200 || true
140+
echo "=== Syslog logs ==="
141+
docker logs sekin-syslog-ng-1 2>&1 | tail -100 || true
142+
143+
- name: Cleanup
144+
if: always()
145+
run: |
146+
cd /tmp/sekin
147+
docker compose down -v || true
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# CI Integration Test Scenario
2+
# This scenario tests basic sekai-cli functionality against a running SEKAI node
3+
name: ci-integration-test
4+
description: Integration tests for CI pipeline - verifies basic queries and transactions
5+
6+
steps:
7+
# === Status Checks ===
8+
- name: Check node status
9+
module: status
10+
action: status
11+
output: node_status
12+
13+
- name: Get network properties
14+
module: gov
15+
action: network-properties
16+
output: network_props
17+
18+
# === Key Management ===
19+
- name: List keys
20+
module: keys
21+
action: list
22+
output: keys_list
23+
24+
# === Bank Module Queries ===
25+
- name: Check genesis balance
26+
module: bank
27+
action: balances
28+
params:
29+
address: genesis
30+
output: genesis_balance
31+
32+
- name: Get total supply
33+
module: bank
34+
action: total-supply
35+
output: total_supply
36+
37+
# === Governance Queries ===
38+
- name: List all roles
39+
module: gov
40+
action: all-roles
41+
output: all_roles
42+
43+
- name: Get genesis permissions
44+
module: gov
45+
action: permissions
46+
params:
47+
address: genesis
48+
output: genesis_permissions
49+
50+
- name: List councilors
51+
module: gov
52+
action: councilors
53+
output: councilors
54+
55+
# === Token Module Queries ===
56+
- name: Get token rates
57+
module: tokens
58+
action: all-rates
59+
output: token_rates
60+
61+
- name: Get token black whites
62+
module: tokens
63+
action: token-black-whites
64+
output: token_black_whites
65+
66+
# === Staking Queries ===
67+
- name: List validators
68+
module: staking
69+
action: validators
70+
output: validators
71+
72+
# === Auth Module Queries ===
73+
- name: Get genesis account info
74+
module: auth
75+
action: account
76+
params:
77+
address: genesis
78+
output: genesis_account

pkg/scenarios/mapper.go

Lines changed: 56 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ func NewActionMapper(client sdk.Client) *ActionMapper {
7272
// resolveAddress resolves a key name to an address if needed.
7373
// If the input looks like a bech32 address (starts with "kira"), it's returned as-is.
7474
// Otherwise, it tries to resolve it as a key name.
75+
// TODO: Handle Ethereum addresses (0x...) for torii bridge integration.
76+
// TODO: Handle custom bech32 prefixes for minted tokens.
7577
func (m *ActionMapper) resolveAddress(ctx context.Context, nameOrAddress string) (string, error) {
7678
// If it looks like an address, return as-is
7779
if strings.HasPrefix(nameOrAddress, "kira") {
@@ -280,10 +282,14 @@ func (m *ActionMapper) executeKeys(ctx context.Context, action string, params ma
280282
return nil, nil, err
281283

282284
case "parse":
283-
address := params["address"]
284-
if address == "" {
285+
addrParam := params["address"]
286+
if addrParam == "" {
285287
return nil, nil, fmt.Errorf("keys.parse requires 'address' parameter")
286288
}
289+
address, err := m.resolveAddress(ctx, addrParam)
290+
if err != nil {
291+
return nil, nil, fmt.Errorf("failed to resolve address: %w", err)
292+
}
287293
result, err := m.keysMod.Parse(ctx, address)
288294
return result, nil, err
289295

@@ -427,10 +433,14 @@ func (m *ActionMapper) executeAuth(ctx context.Context, action string, params ma
427433

428434
switch action {
429435
case "account":
430-
address := params["address"]
431-
if address == "" {
436+
addrParam := params["address"]
437+
if addrParam == "" {
432438
return nil, nil, fmt.Errorf("auth.account requires 'address' parameter")
433439
}
440+
address, err := m.resolveAddress(ctx, addrParam)
441+
if err != nil {
442+
return nil, nil, fmt.Errorf("failed to resolve address: %w", err)
443+
}
434444
result, err := m.authMod.Account(ctx, address)
435445
return result, nil, err
436446

@@ -510,18 +520,26 @@ func (m *ActionMapper) executeGov(ctx context.Context, action string, params map
510520
return result, nil, err
511521

512522
case "roles":
513-
address := params["address"]
514-
if address == "" {
523+
addrParam := params["address"]
524+
if addrParam == "" {
515525
return nil, nil, fmt.Errorf("gov.roles requires 'address' parameter")
516526
}
527+
address, err := m.resolveAddress(ctx, addrParam)
528+
if err != nil {
529+
return nil, nil, fmt.Errorf("failed to resolve address: %w", err)
530+
}
517531
result, err := m.govMod.Roles(ctx, address)
518532
return result, nil, err
519533

520534
case "permissions":
521-
address := params["address"]
522-
if address == "" {
535+
addrParam := params["address"]
536+
if addrParam == "" {
523537
return nil, nil, fmt.Errorf("gov.permissions requires 'address' parameter")
524538
}
539+
address, err := m.resolveAddress(ctx, addrParam)
540+
if err != nil {
541+
return nil, nil, fmt.Errorf("failed to resolve address: %w", err)
542+
}
525543
result, err := m.govMod.Permissions(ctx, address)
526544
return result, nil, err
527545

@@ -586,13 +604,19 @@ func (m *ActionMapper) executeGov(ctx context.Context, action string, params map
586604

587605
case "role-assign", "assign-role":
588606
from := params["from"]
589-
address := params["address"]
607+
addrParam := params["address"]
590608
roleStr := params["role"]
591609

592-
if from == "" || address == "" || roleStr == "" {
610+
if from == "" || addrParam == "" || roleStr == "" {
593611
return nil, nil, fmt.Errorf("gov.role-assign requires 'from', 'address', and 'role' parameters")
594612
}
595613

614+
// Resolve address (could be key name or actual address)
615+
address, err := m.resolveAddress(ctx, addrParam)
616+
if err != nil {
617+
return nil, nil, fmt.Errorf("failed to resolve address: %w", err)
618+
}
619+
596620
// Parse role ID as int
597621
roleID, err := strconv.Atoi(roleStr)
598622
if err != nil {
@@ -1489,8 +1513,17 @@ func (m *ActionMapper) executeStaking(ctx context.Context, action string, params
14891513

14901514
switch action {
14911515
case "validators":
1516+
// Resolve address if provided
1517+
var address string
1518+
if addrParam := params["address"]; addrParam != "" {
1519+
var err error
1520+
address, err = m.resolveAddress(ctx, addrParam)
1521+
if err != nil {
1522+
return nil, nil, fmt.Errorf("failed to resolve address: %w", err)
1523+
}
1524+
}
14921525
opts := &staking.ValidatorQueryOpts{
1493-
Address: params["address"],
1526+
Address: address,
14941527
ValAddr: params["val_address"],
14951528
Moniker: params["moniker"],
14961529
Status: params["status"],
@@ -1499,14 +1532,24 @@ func (m *ActionMapper) executeStaking(ctx context.Context, action string, params
14991532
return result, nil, err
15001533

15011534
case "validator":
1502-
address := params["address"]
1535+
addrParam := params["address"]
15031536
valAddr := params["val_address"]
15041537
moniker := params["moniker"]
15051538

1506-
if address == "" && valAddr == "" && moniker == "" {
1539+
if addrParam == "" && valAddr == "" && moniker == "" {
15071540
return nil, nil, fmt.Errorf("staking.validator requires 'address', 'val_address', or 'moniker' parameter")
15081541
}
15091542

1543+
// Resolve address if provided
1544+
var address string
1545+
if addrParam != "" {
1546+
var err error
1547+
address, err = m.resolveAddress(ctx, addrParam)
1548+
if err != nil {
1549+
return nil, nil, fmt.Errorf("failed to resolve address: %w", err)
1550+
}
1551+
}
1552+
15101553
opts := &staking.ValidatorQueryOpts{
15111554
Address: address,
15121555
ValAddr: valAddr,

0 commit comments

Comments
 (0)