Skip to content

Commit 03608eb

Browse files
authored
Merge branch 'main' into export-chat-sessions
2 parents 33cde33 + 2233590 commit 03608eb

2,351 files changed

Lines changed: 7785 additions & 2062640 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/auto-merge.yml

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
name: Auto-Merge PRs
2+
3+
# Fires when a PR is opened/updated (to enable native auto-merge) and when a
4+
# check suite completes (to directly merge if every check went green and the
5+
# branch has no conflicts).
6+
on:
7+
pull_request:
8+
types: [opened, synchronize, reopened, ready_for_review]
9+
branches: [main]
10+
check_suite:
11+
types: [completed]
12+
13+
permissions:
14+
contents: write # needed to merge
15+
pull-requests: write # needed to update PR auto-merge flag
16+
17+
jobs:
18+
# ── 1. Enable GitHub's built-in auto-merge the moment a PR is opened / updated
19+
enable-auto-merge:
20+
name: Enable auto-merge on PR
21+
if: |
22+
github.event_name == 'pull_request' &&
23+
github.event.pull_request.draft == false
24+
runs-on: ubuntu-latest
25+
steps:
26+
- name: Enable squash auto-merge
27+
# continue-on-error so a repo without branch-protection rules doesn't
28+
# block the workflow; the merge-when-green job is the primary mechanism.
29+
continue-on-error: true
30+
env:
31+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
32+
run: |
33+
gh pr merge --auto --squash \
34+
--repo "${{ github.repository }}" \
35+
"${{ github.event.pull_request.number }}"
36+
37+
# ── 2. Directly merge when ALL check runs on the suite pass ──────────────
38+
merge-when-green:
39+
name: Merge PR when all checks pass
40+
if: |
41+
github.event_name == 'check_suite' &&
42+
github.event.check_suite.conclusion == 'success'
43+
runs-on: ubuntu-latest
44+
steps:
45+
- name: Merge passing, conflict-free PRs
46+
uses: actions/github-script@v7
47+
with:
48+
github-token: ${{ secrets.GITHUB_TOKEN }}
49+
script: |
50+
const headSha = context.payload.check_suite.head_sha;
51+
const prs = context.payload.check_suite.pull_requests ?? [];
52+
53+
if (prs.length === 0) {
54+
core.info('No open PRs linked to this check suite — nothing to do.');
55+
return;
56+
}
57+
58+
for (const pr of prs) {
59+
// Fetch the full PR object (includes mergeable + draft fields)
60+
const { data: pull } = await github.rest.pulls.get({
61+
owner: context.repo.owner,
62+
repo: context.repo.repo,
63+
pull_number: pr.number,
64+
});
65+
66+
if (pull.draft) {
67+
core.info(`PR #${pr.number} is a draft — skipping.`);
68+
continue;
69+
}
70+
71+
if (pull.state !== 'open') {
72+
core.info(`PR #${pr.number} is already closed — skipping.`);
73+
continue;
74+
}
75+
76+
// GitHub computes mergeability asynchronously; poll once if null.
77+
let mergeable = pull.mergeable;
78+
if (mergeable === null) {
79+
core.info(`PR #${pr.number}: mergeability not yet computed, waiting 6 s…`);
80+
await new Promise(r => setTimeout(r, 6000));
81+
const { data: refreshed } = await github.rest.pulls.get({
82+
owner: context.repo.owner,
83+
repo: context.repo.repo,
84+
pull_number: pr.number,
85+
});
86+
mergeable = refreshed.mergeable;
87+
}
88+
89+
if (mergeable === false) {
90+
core.info(`PR #${pr.number} has merge conflicts — skipping.`);
91+
continue;
92+
}
93+
94+
// Confirm every completed check run passed (or was neutral/skipped).
95+
const { data: { check_runs } } = await github.rest.checks.listForRef({
96+
owner: context.repo.owner,
97+
repo: context.repo.repo,
98+
ref: headSha,
99+
per_page: 100,
100+
});
101+
102+
const failing = check_runs.filter(r =>
103+
r.status === 'completed' &&
104+
!['success', 'skipped', 'neutral'].includes(r.conclusion)
105+
);
106+
107+
if (failing.length > 0) {
108+
core.info(
109+
`PR #${pr.number} has failing checks ` +
110+
`(${failing.map(r => r.name).join(', ')}) — skipping.`
111+
);
112+
continue;
113+
}
114+
115+
// Everything is green and conflict-free — merge!
116+
try {
117+
await github.rest.pulls.merge({
118+
owner: context.repo.owner,
119+
repo: context.repo.repo,
120+
pull_number: pr.number,
121+
merge_method: 'squash',
122+
commit_title: `${pull.title} (#${pr.number})`,
123+
commit_message: pull.body ?? '',
124+
});
125+
core.info(`✅ Auto-merged PR #${pr.number}: ${pull.title}`);
126+
} catch (err) {
127+
core.error(`Failed to merge PR #${pr.number}: ${err.message}`);
128+
}
129+
}
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
name: Deploy FiatBridge to Futurenet
2+
3+
on:
4+
push:
5+
branches:
6+
- 'release/**'
7+
paths:
8+
- 'stellar-contracts/**'
9+
- '.github/workflows/deploy-futurenet.yml'
10+
11+
permissions:
12+
contents: read
13+
deployments: write
14+
15+
jobs:
16+
deploy:
17+
name: Deploy to Futurenet
18+
runs-on: ubuntu-latest
19+
environment: futurenet
20+
21+
defaults:
22+
run:
23+
working-directory: stellar-contracts
24+
25+
steps:
26+
- name: Checkout repository
27+
uses: actions/checkout@v4
28+
29+
- name: Set up Rust
30+
uses: dtolnay/rust-toolchain@stable
31+
with:
32+
toolchain: stable
33+
targets: wasm32-unknown-unknown
34+
35+
- name: Install Soroban CLI
36+
run: |
37+
curl -s https://raw.githubusercontent.com/stellar/rs-soroban-sdk/master/soroban-env/install-soroban.sh | bash
38+
soroban --version
39+
40+
- name: Cache Cargo registry
41+
uses: actions/cache@v4
42+
with:
43+
path: |
44+
~/.cargo/registry
45+
~/.cargo/git
46+
stellar-contracts/target
47+
key: ${{ runner.os }}-cargo-${{ hashFiles('stellar-contracts/Cargo.lock') }}
48+
restore-keys: |
49+
${{ runner.os }}-cargo-
50+
51+
- name: Build contract
52+
run: cargo build --target wasm32-unknown-unknown --release
53+
54+
- name: Deploy to Futurenet
55+
id: deploy
56+
env:
57+
FUTURENET_ADMIN_SECRET_KEY: ${{ secrets.FUTURENET_ADMIN_SECRET_KEY }}
58+
FUTURENET_RPC_URL: https://rpc-futurenet.stellar.org
59+
FUTURENET_NETWORK_PASSPHRASE: 'Test SDF Future Network ; April 2020'
60+
OUTPUT_FILE: ./contract_id_futurenet.txt
61+
run: |
62+
chmod +x ../scripts/deploy_fiat_bridge_futurenet.sh
63+
../scripts/deploy_fiat_bridge_futurenet.sh
64+
65+
# Pass outputs to GitHub Actions context
66+
CONTRACT_ID=$(cat "$OUTPUT_FILE")
67+
echo "contract_id=$CONTRACT_ID" >> $GITHUB_OUTPUT
68+
69+
- name: Upload contract ID artifact
70+
if: success()
71+
uses: actions/upload-artifact@v4
72+
with:
73+
name: contract-deployment-${{ github.sha }}
74+
path: stellar-contracts/contract_id_futurenet.txt
75+
retention-days: 90
76+
77+
- name: Create deployment status
78+
if: always()
79+
uses: actions/github-script@v7
80+
with:
81+
script: |
82+
const status = '${{ job.status }}' === 'success' ? 'success' : 'failure';
83+
const conclusion = status === 'success' ? '✅ Deployment successful' : '❌ Deployment failed';
84+
85+
github.rest.repos.createDeployment({
86+
owner: context.repo.owner,
87+
repo: context.repo.repo,
88+
ref: context.ref,
89+
environment: 'futurenet',
90+
required_contexts: [],
91+
auto_merge: false,
92+
description: 'FiatBridge Smart Contract Deployment'
93+
})
94+
95+
- name: Post deployment summary
96+
if: success()
97+
run: |
98+
echo "## 🎉 Deployment Summary" >> $GITHUB_STEP_SUMMARY
99+
echo "" >> $GITHUB_STEP_SUMMARY
100+
echo "**Status:** ✅ Success" >> $GITHUB_STEP_SUMMARY
101+
echo "**Environment:** Futurenet" >> $GITHUB_STEP_SUMMARY
102+
echo "**Contract ID:** ${{ steps.deploy.outputs.contract_id }}" >> $GITHUB_STEP_SUMMARY
103+
echo "**Branch:** ${{ github.ref_name }}" >> $GITHUB_STEP_SUMMARY
104+
echo "**Commit:** ${{ github.sha }}" >> $GITHUB_STEP_SUMMARY
105+
106+
- name: Notify on failure
107+
if: failure()
108+
run: |
109+
echo "## ❌ Deployment Failed" >> $GITHUB_STEP_SUMMARY
110+
echo "" >> $GITHUB_STEP_SUMMARY
111+
echo "Environment: Futurenet" >> $GITHUB_STEP_SUMMARY
112+
echo "Branch: ${{ github.ref_name }}" >> $GITHUB_STEP_SUMMARY
113+
echo "Check the logs for details." >> $GITHUB_STEP_SUMMARY

.github/workflows/frontend.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,3 +56,7 @@ jobs:
5656
GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY || 'PLACEHOLDER' }}
5757
PAYSTACK_SECRET_KEY: ${{ secrets.PAYSTACK_SECRET_KEY || 'PLACEHOLDER' }}
5858
PAYOUT_PROVIDER: ${{ secrets.PAYOUT_PROVIDER || 'paystack' }}
59+
60+
- name: Unit tests with coverage
61+
run: npm run test:coverage
62+
# Fails the pipeline if coverage thresholds (stmt 70%, branch 65%, fn 70%) are not met

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,5 @@ stellar-contracts/target/
1010
# Contract build artifacts
1111
*.wasm
1212

13+
issue.md
14+
pr.md

.vscode/settings.json

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
11
{
2-
"rust-analyzer.linkedProjects": [
3-
"stellar-contracts/Cargo.toml"
4-
]
2+
"rust-analyzer.linkedProjects": ["stellar-contracts/Cargo.toml"]
53
}

CONTRIBUTING.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Contributing
22

3-
Thank you for taking the time to contribute. This document covers everything you need to open your first pull request.
3+
This document covers everything you need to open your first pull request.
44

55
---
66

IMPLEMENTATION_SUMMARY.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ Automated verification script that checks:
104104
**Persist and validate nonce per operator**
105105

106106
- Nonces stored in instance storage with `DataKey::OperatorNonce(Address)`
107-
- Each operator has independent nonce counter
107+
- Each operator has independent nonce counters
108108
- Nonces persist across operator deactivation/reactivation
109109
- Validation occurs before any state changes
110110

0 commit comments

Comments
 (0)