Skip to content
Open
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
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 1 addition & 1 deletion .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,6 @@
}
}
},
"postCreateCommand": "cd /workspaces/Harvest-Finance/harvest-finance/backend && npm install",
"postCreateCommand": "cd /workspace/backend && npm install",
"remoteUser": "node"
}
38 changes: 24 additions & 14 deletions .github/workflows/cd.yml
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
name: CD

on:
push:
branches:
- main # → production
- develop # → staging
workflow_run:
workflows: ["CI"]
types: [completed]

concurrency:
group: cd-${{ github.ref }}
group: cd-${{ github.event.workflow_run.head_branch }}
cancel-in-progress: false

env:
Expand All @@ -19,13 +18,16 @@ jobs:
detect-environment:
name: Detect Target Environment
runs-on: ubuntu-latest
if: >-
github.event.workflow_run.conclusion == 'success' &&
(github.event.workflow_run.head_branch == 'main' || github.event.workflow_run.head_branch == 'develop')
outputs:
environment: ${{ steps.env.outputs.environment }}
image_tag: ${{ steps.env.outputs.image_tag }}
steps:
- id: env
run: |
if [[ "${{ github.ref }}" == "refs/heads/main" ]]; then
if [[ "${{ github.event.workflow_run.head_branch }}" == "main" ]]; then
echo "environment=production" >> "$GITHUB_OUTPUT"
echo "image_tag=latest" >> "$GITHUB_OUTPUT"
else
Expand Down Expand Up @@ -57,8 +59,8 @@ jobs:
- name: Build & push backend
uses: docker/build-push-action@v6
with:
context: harvest-finance/backend
file: harvest-finance/backend/Dockerfile
context: backend
file: backend/Dockerfile
push: true
tags: |
${{ env.IMAGE_BACKEND }}:${{ github.sha }}
Expand All @@ -71,8 +73,8 @@ jobs:
- name: Build & push frontend
uses: docker/build-push-action@v6
with:
context: harvest-finance/frontend
file: harvest-finance/frontend/Dockerfile
context: frontend
file: frontend/Dockerfile
push: true
tags: |
${{ env.IMAGE_FRONTEND }}:${{ github.sha }}
Expand All @@ -95,6 +97,9 @@ jobs:

- name: Deploy to staging via SSH
uses: appleboy/ssh-action@v1
env:
DATABASE_URL: ${{ secrets.DATABASE_URL }}
DIRECT_URL: ${{ secrets.DIRECT_URL }}
with:
host: ${{ secrets.STAGING_HOST }}
username: ${{ secrets.STAGING_USER }}
Expand All @@ -103,9 +108,11 @@ jobs:
cd /opt/harvest-finance
export IMAGE_TAG=${{ github.sha }}
export REGISTRY=${{ env.REGISTRY }}
export DATABASE_URL="$DATABASE_URL"
export DIRECT_URL="$DIRECT_URL"
docker compose -f docker-compose.staging.yml pull
docker compose -f docker-compose.staging.yml up -d --remove-orphans
docker system prune -f
docker compose -f docker-compose.staging.yml exec backend npm run migration:run

deploy-production:
name: Deploy → Production
Expand All @@ -120,6 +127,9 @@ jobs:

- name: Deploy to production via SSH
uses: appleboy/ssh-action@v1
env:
DATABASE_URL: ${{ secrets.DATABASE_URL }}
DIRECT_URL: ${{ secrets.DIRECT_URL }}
with:
host: ${{ secrets.PROD_HOST }}
username: ${{ secrets.PROD_USER }}
Expand All @@ -128,12 +138,12 @@ jobs:
cd /opt/harvest-finance
export IMAGE_TAG=${{ github.sha }}
export REGISTRY=${{ env.REGISTRY }}
export DATABASE_URL="$DATABASE_URL"
export DIRECT_URL="$DIRECT_URL"
# Rolling update — zero downtime
docker compose -f docker-compose.prod.yml pull
docker compose -f docker-compose.prod.yml up -d --remove-orphans --scale backend=2
sleep 10
docker compose -f docker-compose.prod.yml up -d --remove-orphans
docker system prune -f
docker compose -f docker-compose.prod.yml exec backend npm run migration:run

- name: Notify Slack on success
if: success()
Expand Down
90 changes: 46 additions & 44 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: CI

on:
push:
branches: [main, develop, "feat/**", "fix/**"]
branches: [main, develop]
pull_request:
branches: [main, develop]

Expand All @@ -11,7 +11,7 @@ concurrency:
cancel-in-progress: true

env:
NODE_VERSION: "20"
NODE_VERSION: "22"

jobs:
# ── Backend ──────────────────────────────────────────────────────────────────
Expand All @@ -20,25 +20,25 @@ jobs:
runs-on: ubuntu-latest
defaults:
run:
working-directory: harvest-finance/backend
working-directory: backend
steps:
- uses: actions/checkout@v4

- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: npm
cache-dependency-path: harvest-finance/backend/package-lock.json
cache-dependency-path: backend/package-lock.json

- run: npm ci || true
- run: npm run lint || true
- run: npm ci
- run: npm run lint

backend-test:
name: Backend — Unit + Integration Tests
runs-on: ubuntu-latest
defaults:
run:
working-directory: harvest-finance/backend
working-directory: backend

services:
postgres:
Expand Down Expand Up @@ -84,17 +84,17 @@ jobs:
with:
node-version: ${{ env.NODE_VERSION }}
cache: npm
cache-dependency-path: harvest-finance/backend/package-lock.json
cache-dependency-path: backend/package-lock.json

- run: npm ci
- run: npm run build
- run: npm test -- --forceExit --passWithNoTests || true
- run: npm test -- --forceExit
- name: Upload coverage
uses: actions/upload-artifact@v4
if: always()
with:
name: backend-coverage
path: harvest-finance/backend/coverage/
path: backend/coverage/

backend-build:
name: Backend — Docker Build
Expand All @@ -105,10 +105,9 @@ jobs:
- uses: docker/setup-buildx-action@v3
- name: Build backend image
uses: docker/build-push-action@v6
continue-on-error: true
with:
context: harvest-finance/backend
file: harvest-finance/backend/Dockerfile
context: backend
file: backend/Dockerfile
push: false
tags: harvest-finance-backend:${{ github.sha }}
cache-from: type=gha
Expand All @@ -120,15 +119,15 @@ jobs:
runs-on: ubuntu-latest
defaults:
run:
working-directory: harvest-finance/frontend
working-directory: frontend
steps:
- uses: actions/checkout@v4

- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: npm
cache-dependency-path: harvest-finance/frontend/package-lock.json
cache-dependency-path: frontend/package-lock.json

- run: npm ci
- run: npm run lint
Expand All @@ -138,27 +137,27 @@ jobs:
runs-on: ubuntu-latest
defaults:
run:
working-directory: harvest-finance/frontend
working-directory: frontend
steps:
- uses: actions/checkout@v4

- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: npm
cache-dependency-path: harvest-finance/frontend/package-lock.json
cache-dependency-path: frontend/package-lock.json

- run: npm ci
- run: npm test -- --passWithNoTests
- run: npm run test:vitest -- --run --passWithNoTests
- run: npm test
- run: npm run test:vitest -- --run

frontend-build:
name: Frontend — Next.js Build
runs-on: ubuntu-latest
needs: [frontend-lint, frontend-test]
defaults:
run:
working-directory: harvest-finance/frontend
working-directory: frontend
env:
NEXT_PUBLIC_API_URL: https://api.harvestfinance.io
steps:
Expand All @@ -168,15 +167,15 @@ jobs:
with:
node-version: ${{ env.NODE_VERSION }}
cache: npm
cache-dependency-path: harvest-finance/frontend/package-lock.json
cache-dependency-path: frontend/package-lock.json

- run: npm ci || true
- run: npm run build || true
- run: npm ci
- run: npm run build
- name: Upload build artifact
uses: actions/upload-artifact@v4
with:
name: frontend-build-${{ github.sha }}
path: harvest-finance/frontend/.next/
path: frontend/.next/
retention-days: 3

# ── Smart Contracts ───────────────────────────────────────────────────────────
Expand All @@ -194,40 +193,42 @@ jobs:
version: nightly

- name: Run forge tests
working-directory: contracts
run: forge test -vvv || true
working-directory: contracts-legacy
run: forge test -vvv --skip "test/VaultMainnetFork.t.sol"

- name: Forge coverage
working-directory: contracts
run: forge coverage --report lcov || true
working-directory: contracts-legacy
run: forge coverage --report lcov

- name: Upload coverage
uses: actions/upload-artifact@v4
with:
name: contracts-coverage
path: contracts/lcov.info
path: contracts-legacy/lcov.info

# ── Smart Contract Fork Tests ─────────────────────────────────────────────────
contracts-fork-test:
name: Contracts — Mainnet Fork Tests
# ── Soroban Contracts ────────────────────────────────────────────────────────
contracts-soroban:
name: Contracts — Soroban Build & Test
runs-on: ubuntu-latest
# Only run on main/develop pushes (not every feature PR) to conserve RPC calls
if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/develop')
defaults:
run:
working-directory: contracts-soroban/vault
steps:
- uses: actions/checkout@v4
with:
submodules: recursive

- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
version: nightly
components: rustfmt, clippy

- name: Run mainnet fork tests
working-directory: contracts
env:
ETH_RPC_URL: ${{ secrets.ETH_RPC_URL }}
run: make test-fork
- name: Cargo check
run: cargo check

- name: Cargo test
run: cargo test

- name: Cargo clippy
run: cargo clippy -- -D warnings

# ── All-green gate ────────────────────────────────────────────────────────────
all-checks:
Expand All @@ -237,5 +238,6 @@ jobs:
- backend-build
- frontend-build
- contracts-test
- contracts-soroban
steps:
- run: echo "CI passed ✓"
2 changes: 1 addition & 1 deletion .github/workflows/security.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
dir: [harvest-finance/backend, harvest-finance/frontend]
dir: [backend, frontend]
defaults:
run:
working-directory: ${{ matrix.dir }}
Expand Down
5 changes: 3 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# compiled output
/dist
/node_modules
dist/
node_modules/
target/

# Logs
logs
Expand Down
4 changes: 2 additions & 2 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[submodule "contracts/lib/forge-std"]
path = contracts/lib/forge-std
path = contracts-legacy/lib/forge-std
url = https://github.com/foundry-rs/forge-std
[submodule "contracts/lib/openzeppelin-contracts"]
path = contracts/lib/openzeppelin-contracts
path = contracts-legacy/lib/openzeppelin-contracts
url = https://github.com/OpenZeppelin/openzeppelin-contracts
Loading
Loading