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
39 changes: 37 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,9 @@ jobs:
exit 1
fi

- name: Test validate-deployment script (mocked CLI)
run: bash scripts/validate-deployment.test.sh

stellar-kani:
needs: changes
if: needs.changes.outputs.stellar == 'true'
Expand Down Expand Up @@ -350,7 +353,6 @@ jobs:
defaults:
run:
working-directory: stellar
continue-on-error: true
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

Expand Down Expand Up @@ -388,16 +390,48 @@ jobs:
RPC_URL: https://rpc-futurenet.stellar.org
IDENTITY_NAME: wraith-dryrun-ci
run: |
set -euo pipefail
./scripts/deploy-dryrun.sh 2>&1 | tee deploy-dryrun-output.txt
exit_code=${PIPESTATUS[0]}
if [ $exit_code -ne 0 ]; then
echo "::error::Deploy dry-run script failed with exit code $exit_code"
exit $exit_code
fi

- name: Validate deployment output
run: |
chmod +x ./scripts/validate-deployment.sh
./scripts/validate-deployment.sh deploy-dryrun-output.txt futurenet

- name: Parse and save contract IDs
run: |
cat deploy-dryrun-output.txt | grep -E '(stealth-announcer|stealth-registry|stealth-sender|wraith-names)\s' | \
awk '{print $1, $2}' > contract-ids.txt || true
awk '{print $1, $2}' > contract-ids.txt

# Verify contract-ids.txt is not empty
if [ ! -s contract-ids.txt ]; then
echo "::error::contract-ids.txt is empty - failed to parse contract IDs"
exit 1
fi

# Count lines to verify all 4 contracts are present
contract_count=$(wc -l < contract-ids.txt)
if [ "$contract_count" -ne 4 ]; then
echo "::error::Expected 4 contract IDs, found $contract_count"
cat contract-ids.txt
exit 1
fi

echo "### Deploy Dry-Run Results" >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
cat deploy-dryrun-output.txt >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY

echo "" >> $GITHUB_STEP_SUMMARY
echo "### Contract Manifest" >> $GITHUB_STEP_SUMMARY
echo '```json' >> $GITHUB_STEP_SUMMARY
cat deploy-dryrun-output-manifest.json >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY

- name: Upload dry-run output
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
Expand All @@ -406,6 +440,7 @@ jobs:
name: deploy-dryrun-results
path: |
stellar/deploy-dryrun-output.txt
stellar/deploy-dryrun-output-manifest.json
stellar/contract-ids.txt

stellar-chaos-nightly:
Expand Down
144 changes: 144 additions & 0 deletions stellar/scripts/VALIDATION_README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
# Stellar Deployment Validation

## Overview

This directory contains scripts for validating Stellar contract deployments to ensure they complete successfully and produce valid contract IDs.

## Scripts

### `deploy-dryrun.sh`
The main deployment script that deploys all Wraith Protocol Stellar contracts to futurenet and runs smoke tests.

### `validate-deployment.sh`
Validation script that ensures deployment output meets requirements:
- All required contract IDs are present (stealth-announcer, stealth-registry, stealth-sender, wraith-names)
- Contract IDs are valid Stellar addresses (start with 'C', 56 characters, valid base32)
- Contract IDs match the expected network (via stellar.expert URLs)
- **Contract IDs exist on the target network (via RPC query)**
- Deployment completed successfully
- Generates a JSON manifest with validated contract IDs

**Usage:**
```bash
./validate-deployment.sh <output-file> <network>
```

**Example:**
```bash
./validate-deployment.sh deploy-dryrun-output.txt futurenet
```

**Environment Variables:**
- `RPC_URL`: Override the default RPC URL for the network

**Exit Codes:**
- 0: All validations passed
- 1: Validation failed

**Outputs:**
- `<output-file>-manifest.json`: JSON manifest with contract IDs and validation status (always written prior to exit on both success and failure paths)

**RPC Verification:**
The script queries the Stellar RPC for each contract using `stellar contract info wasm-hash` to verify that the contract actually exists on the specified network. This ensures the deployment was successful and the contracts are accessible.

### `validate-deployment.test.sh`
Unit tests for the validation script covering:
- Valid deployment output
- Missing contract IDs
- Invalid contract ID formats
- Wrong network detection
- Smoke test failures
- Early failure (missing output file) generating failed manifest and preserving exit code
- Late failure (RPC lookup failure) generating failed manifest and preserving exit code
- Unexpected error/panic line with success marker generating failed manifest and preserving non-zero exit code

**Usage:**
```bash
./validate-deployment.test.sh
```

## CI Integration

The validation is integrated into the `.github/workflows/ci.yml` workflow in the `stellar-deploy-dryrun` job:

1. **Removed `continue-on-error: true`** - Job now fails on errors
2. **Removed `|| true` from parsing** - Parsing failures now fail the job
3. **Added exit code checking** - Deploy script failures are caught and reported
4. **Added validation step** - Runs `validate-deployment.sh` to verify output
5. **Added contract count verification** - Ensures all 4 contracts are present
6. **Added manifest artifact** - Uploads JSON manifest with validated IDs

## Validation Requirements

### Contract ID Format
- Must start with 'C'
- Must be exactly 56 characters long
- Must contain only valid base32 characters (A-Z, 2-7)

### Required Contracts
1. stealth-announcer
2. stealth-registry
3. stealth-sender
4. wraith-names

### Network Validation
Contract IDs are verified against the expected network by:
1. Checking stellar.expert URLs in the deployment output
2. **Querying the RPC endpoint to verify each contract exists on-chain**

The RPC verification uses `stellar contract info wasm-hash` which:
- Queries the network's RPC endpoint
- Retrieves the WASM hash for the contract
- Fails if the contract doesn't exist on the specified network

## Artifacts

The following artifacts are uploaded on every run (success or failure):
- `deploy-dryrun-output.txt` - Full deployment output
- `deploy-dryrun-output-manifest.json` - JSON manifest with validated IDs
- `contract-ids.txt` - Parsed contract IDs (legacy format)

## Example Manifest

```json
{
"network": "futurenet",
"timestamp": "2026-09-27T12:34:56Z",
"contracts": {
"stealth-announcer": "CABCDEFGHIJKLMNOPQRSTUVWXYZ234567ABCDEFGHIJKLMNOPQRS",
"stealth-registry": "CBCDEFGHIJKLMNOPQRSTUVWXYZ234567ABCDEFGHIJKLMNOPQRST",
"stealth-sender": "CCDEFGHIJKLMNOPQRSTUVWXYZ234567ABCDEFGHIJKLMNOPQRSTU",
"wraith-names": "CDEFGHIJKLMNOPQRSTUVWXYZ234567ABCDEFGHIJKLMNOPQRSTUV"
},
"validation": {
"status": "passed",
"required_contracts": 4,
"found_contracts": 4
}
}
```

## Troubleshooting

### Validation Fails with "Missing contract ID"
Check the deployment output to ensure the contract was deployed successfully. Look for error messages in the deploy step.

### Validation Fails with "Invalid format"
The contract ID doesn't match Stellar's address format. This usually indicates a parsing error or corrupted output.

### Validation Fails with "Network mismatch"
The deployment was made to a different network than expected. Verify the `RPC_URL` and `NETWORK` environment variables.

### Validation Fails with "Contract ID does not exist on network"
The contract ID is valid but doesn't exist on the specified network. This indicates:
- The deployment may have failed silently
- The wrong network was specified for validation
- The RPC endpoint is not in sync

Check the deployment output for errors and verify the RPC_URL matches the deployment network.

### Smoke tests failed
Check the deployment output for specific test failures. Common causes:
- Network connectivity issues
- Insufficient account balance
- Contract initialization errors
Loading