Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[EPIC] E2E DevOps #911

Open
wants to merge 13 commits into
base: staging
Choose a base branch
from
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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules
.env
5 changes: 4 additions & 1 deletion .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,7 @@ yarn-error.log*

# Files generated by next-on-netlify command
/out_publish/
/out_functions/
/out_functions/

tests/
synpress.config.js
61 changes: 57 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,29 +1,49 @@
name: CI

on: [push, pull_request]
on:
push:
pull_request:
branches:
- main
- e2e-devops

env:
NEXT_PUBLIC_GRAPH_ENDPOINT_MAINNET: 'https://api.thegraph.com/subgraphs/name/alextheboredape/aelin-mainnet'
NEXT_PUBLIC_GRAPH_ENDPOINT_OPTIMISM: 'https://api.thegraph.com/subgraphs/name/alextheboredape/aelin-optimism'
NEXT_PUBLIC_GRAPH_ENDPOINT_GOERLI: 'https://api.thegraph.com/subgraphs/name/alextheboredape/aelin-goerli'
NEXT_PUBLIC_GRAPH_ENDPOINT_ARBITRUM: 'https://api.thegraph.com/subgraphs/name/alextheboredape/aelin-arbitrum'
NEXT_PUBLIC_GRAPH_ENDPOINT_POLYGON: 'https://api.thegraph.com/subgraphs/name/alextheboredape/aelin-polygon'
NEXT_PUBLIC_REACT_APP_DEFAULT_CHAIN_ID: 1

jobs:
build:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3

- name: Set yarn cache directory
run: yarn config set cache-folder .yarn-cache
continue-on-error: true

- name: Use Node.js 16
uses: actions/setup-node@v2
uses: actions/setup-node@v3
with:
node-version: '16'
node-version: '16.x'

- name: Install yarn
run: npm install -g yarn

- uses: actions/cache@v3
with:
path: |
.yarn-cache
node_modules
key: ${{ runner.os }}-yarn-v1-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-v1-
continue-on-error: true

- name: Installing dependencies
run: yarn --prefer-offline

Expand All @@ -32,3 +52,36 @@ jobs:

- name: Running Tests
run: yarn test

e2e:
needs: build
runs-on: ubuntu-latest

steps:
- name: Chown workspace
run: chown -R $(whoami) .

- name: Checkout
uses: actions/checkout@v3

- name: Set up QEMU
uses: docker/setup-qemu-action@v2

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2

- name: Cache Docker layers
uses: actions/cache@v3
with:
path: /tmp/.buildx-cache
key: ${{ runner.os }}-buildx-${{ github.sha }}
restore-keys: |
${{ runner.os }}-buildx-
- name: Run e2e tests
run: |
docker-compose -f ./ci/docker-compose.ci.yaml up --build --exit-code-from aelin-ui
env:
COMPOSE_DOCKER_CLI_BUILD: 1
DOCKER_BUILDKIT: 1
DOCKER_DEFAULT_PLATFORM: linux/amd64
NGROK_AUTH: ${{ secrets.NGROK_AUTH }}
10 changes: 10 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
FROM alpine:3.14

RUN apk update && apk add bash

WORKDIR /app

COPY ./ci/add-envs.sh ./


ENTRYPOINT ["/bin/bash", "-c"]
84 changes: 68 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,31 +1,83 @@
# Aelin Frontend v2
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you create a TESTING.md file to add this? I don't think it's necessary to run the entire protocol locally for development reasons. I don't think it's worth adding so much complexity to just run the app.

Copy link
Collaborator Author

@0xlinus 0xlinus Mar 3, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree. But if there's gonna be a pool/deal creation or interaction, then we should use this. Otherwise will be continue to pollute Goerli. Also we tend to always use small token values bc of balance limitations which ended up creating bugs in the past. So:

  • If it's just to display data => no need to use the whole app
  • Need to create a pool/deal, or invest, vest etc => I'd definitely push to use this

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It adds too much complexity to run the dapp IMO. I would move this to TESTING.md, which is what it was created for. I don't want new contributors to struggle w/this when the steps are now pretty simple.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still think that we should go this way:

  • If it's just to display data => no need to use the whole app
  • Need to create a pool/deal, or invest, vest etc => I'd definitely push to use this

We can discuss this later in standies

PS: running 2 commands is adding too much complexity?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it not only adds two commands, but requires installing and managing docker and docker compose. Having been developed with the docker stack, it has disadvantages compared to the previous approach. For instance: slower nextjs fast refresh, need to prune your images/container because it uses huge disk space, slower startup time...

# Aelin UI - Local Dev Environment

### Run this application with Node 14
## How it works

1. Copy `.env.example` as `.env.local`
To be able to run Aelin and all its components locally we'll need:

```
$ cp .env.example .env.local
```
1. **Blockchain node** with the latest Aelin contracts deployed
2. **Graph node** with the latest Aelin subgraphs deployed
3. **Aelin UI app** running

2. Install dependencies
### Blockchain

We'll use **Anvil** for this, which is a ganache-style blockchain node implemented by **Foundry**. There's a script that will run before everything else, which will deploy all contracts and deps needed.

### Graph node

A simple graph node as shown [here](https://thegraph.academy/developers/local-development/)

### Aelin UI

The one in this repo.

## Steps

First run `yarn` and install all deps (check that there are no errors)

### 1 - Start Anvil + Subgraph + Deploy Contracts

```sh
. ./start-local.sh
```
$ yarn
```

3. Auto generate generate contracts types, subgraph types & queries SDK
### 3 - Use generated envs

You'll need new envs containing contracts, private keys (test net dont worry!), etc.
Run this command and then change `.env.generated` to `.env`

First you'll have to wait until all contracts are deployed and env variables are generated. Check `docker-compose` logs and wait until you start to see a lot of activity.

After that's done you're safe to export the generated envs:

```sh
docker cp anvil:/usr/share/envs/.env.generated ./.env.generated
```
$ yarn postinstall

### 3 - Start UI

```sh
yarn dev
```

- NOTE: `postinstall` will generates an sdk file in `CODEGEN_OUTPUT_FILE` environment variable (default value: `types/generated/queries.ts` ) with all queries uses in the App.
### 4 - Run E2E test?

4. Run application as dev mode
> step 3 required!

```sh
yarn e2e:local
```
$ yarn dev
```

5. Open `http://localhost:3000`
## Metamask config

**Network**

You'll need to add the local blockchain we've just started.

![image](https://user-images.githubusercontent.com/99757679/217300010-2c434eab-b803-47b9-ad99-fed875a45223.png)

**Account**

Import a test account using the private key located in the `env.generated`

**IMPORTANT**

EVERY TIME your (re)start `docker-compose`, remember to reset Metamask account, otherwise you'll see an error due to block height miss match.

![image](https://user-images.githubusercontent.com/99757679/217300243-1ef40d2d-72e7-4a1e-b113-716625dbb0cd.png)

## Requirements

```sh
docker
docker-compose
```
12 changes: 12 additions & 0 deletions ci/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
FROM synthetixio/docker-e2e:18.13-ubuntu as base

RUN apt install git

WORKDIR /app

COPY . .

RUN echo "NEXT_PUBLIC_GRAPH_ENDPOINT_GOERLI=https://api.thegraph.com/subgraphs/name/alextheboredape/aelin-goerli" > .env
RUN echo "NEXT_PUBLIC_GRAPH_ENDPOINT_OPTIMISM=https://api.thegraph.com/subgraphs/name/alextheboredape/aelin-optimism" > .env

RUN yarn install --frozen-lockfile
32 changes: 32 additions & 0 deletions ci/Dockerfile-anvil
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
FROM alpine:3.16 AS builder
WORKDIR /opt
RUN apk add clang lld curl build-base linux-headers git \
&& curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > rustup.sh \
&& chmod +x ./rustup.sh \
&& ./rustup.sh -y
RUN git clone https://github.com/foundry-rs/foundry.git
# && cd foundry \
# && git reset --hard b554ab1fec09087fa3a35c6728968edca6debcf2
WORKDIR /opt/foundry
RUN source $HOME/.profile && cargo build --release \
&& strip /opt/foundry/target/release/forge \
&& strip /opt/foundry/target/release/cast \
&& strip /opt/foundry/target/release/anvil

FROM alpine:3.16 AS client
ENV GLIBC_KEY=https://alpine-pkgs.sgerrand.com/sgerrand.rsa.pub
ENV GLIBC_KEY_FILE=/etc/apk/keys/sgerrand.rsa.pub
ENV GLIBC_RELEASE=https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.35-r0/glibc-2.35-r0.apk

RUN apk add linux-headers gcompat git
RUN wget -q -O ${GLIBC_KEY_FILE} ${GLIBC_KEY} \
&& wget -O glibc.apk ${GLIBC_RELEASE} \
&& apk add glibc.apk --force
COPY --from=builder /opt/foundry/target/release/forge /usr/local/bin/forge
COPY --from=builder /opt/foundry/target/release/cast /usr/local/bin/cast
COPY --from=builder /opt/foundry/target/release/anvil /usr/local/bin/anvil
RUN adduser -Du 1000 foundry

EXPOSE 8545

ENTRYPOINT ["/bin/sh", "-c"]
38 changes: 38 additions & 0 deletions ci/Dockerfile-vercel
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Install all deps
FROM node:16-alpine AS deps
RUN apk add --no-cache libc6-compat git
WORKDIR /app
COPY package.json yarn-lock.json* ./
COPY . .
RUN yarn install --frozen-lockfile

# Build app
FROM node:16-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN yarn build

# Run
FROM node:16-alpine AS runner
WORKDIR /app
ENV NODE_ENV production
ENV NEXT_TELEMETRY_DISABLED 1

RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs

COPY --from=builder /app/next.config.js ./
COPY --from=builder /app/public ./public
COPY --from=builder /app/package.json ./package.json
COPY --from=builder /app/.env ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static

USER nextjs

EXPOSE 3000

ENV PORT 3000

ENTRYPOINT [ "/bin/sh", "-c" ]
61 changes: 61 additions & 0 deletions ci/add-envs.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#!/bin/bash

file_path="/usr/share/envs/.env.linuz"

while [ ! -f $file_path ]
do
echo "Waiting for file $file_path to exist..."
sleep 1
done

echo "Exporting ENVs for Aelin UI..."


NEXT_PUBLIC_ANVIL="http://0.0.0.0:8545";

[[ $1 == ci ]] && NEXT_PUBLIC_ANVIL="http://anvil:8545";

NEXT_PUBLIC_AELIN_POOL_FACTORY=$(grep AelinPoolFactory_address /usr/share/envs/.env.linuz | tail -1 | awk -F "=" '{print $2}')
NEXT_PUBLIC_AELIN_DEAL_FACTORY=$(grep AelinUpFrontDealFactory_address /usr/share/envs/.env.linuz | tail -1 | awk -F "=" '{print $2}')
NEXT_PUBLIC_UNI=$(grep UNI_address /usr/share/envs/.env.linuz | tail -1 | awk -F "=" '{print $2}')
NEXT_PUBLIC_USDC=$(grep USDC_address /usr/share/envs/.env.linuz | tail -1 | awk -F "=" '{print $2}')
NEXT_PUBLIC_WETH=$(grep WETH_address /usr/share/envs/.env.linuz | tail -1 | awk -F "=" '{print $2}')

echo "
CODEGEN_OUTPUT_FILE=types/generated/queries.ts
NEXT_PUBLIC_AELIN_VOUCHER_ENS_ADDRESS=aelincouncil.eth
NEXT_PUBLIC_GRAPH_ENDPOINT_MAINNET=https://api.thegraph.com/subgraphs/name/alextheboredape/aelin-mainnet
NEXT_PUBLIC_GRAPH_ENDPOINT_OPTIMISM=https://api.thegraph.com/subgraphs/name/alextheboredape/aelin-optimism
NEXT_PUBLIC_GRAPH_ENDPOINT_ARBITRUM=https://api.thegraph.com/subgraphs/name/alextheboredape/aelin-arbitrum
NEXT_PUBLIC_GRAPH_ENDPOINT_POLYGON=https://api.thegraph.com/subgraphs/name/alextheboredape/aelin-polygon
NEXT_PUBLIC_IPFS_GATEWAY_BASE_URL=https://w3s.link/ipfs
NEXT_PUBLIC_MAINTENANCE_MESSAGE_SUBTITLE=undefined
NEXT_PUBLIC_MAINTENANCE_MESSAGE_TITLE=undefined
NEXT_PUBLIC_MAINTENANCE_MODE=false
QUIXOTIC_API_TOKEN=ask
SIMPLEHASH_API_KEY=ask
STRATOS_API_TOKEN=ask
NEXT_PUBLIC_ARBITRUM_TOKEN_PROVIDER=ask
NEXT_PUBLIC_GOERLI_TOKEN_PROVIDER=ask
NEXT_PUBLIC_OPTIMISM_TOKEN_PROVIDER=ask
NEXT_PUBLIC_POLYGON_TOKEN_PROVIDER=ask
NEXT_PUBLIC_MAINNET_TOKEN_PROVIDER=EW9N4oDCQJ58k_9wF-wG8pkq7amdPnqD
NEXT_PUBLIC_WEB3_STORAGE_TOKEN_KEY=ask
NEXT_PUBLIC_APP_NAME=Aelin
NEXT_PUBLIC_APP_ENV=development
NEXT_PUBLIC_REACT_APP_DEFAULT_CHAIN_ID=5
NEXT_PUBLIC_APP_URL=https://app.aelin.xyz
NEXT_PUBLIC_APP_NAME=aelin
[email protected]
NEXT_PUBLIC_GRAPH_ENDPOINT_GOERLI=http://0.0.0.0:8000/subgraphs/name/aelinprotocol/e2e-subgraph
NEXT_PUBLIC_ETH_GAS_STATION_API_URL=https://ethgasstation.info/json/ethgasAPI.json
NEXT_PUBLIC_GAS_NOW_API_URL=https://etherchain.org/api/gasnow
NEXT_PUBLIC_AELIN_POOL_FACTORY=${NEXT_PUBLIC_AELIN_POOL_FACTORY}
NEXT_PUBLIC_AELIN_DEAL_FACTORY=${NEXT_PUBLIC_AELIN_DEAL_FACTORY}
NEXT_PUBLIC_UNI=${NEXT_PUBLIC_UNI}
NEXT_PUBLIC_USDC=${NEXT_PUBLIC_USDC}
NEXT_PUBLIC_WETH=${NEXT_PUBLIC_WETH}
NEXT_PUBLIC_ANVIL=${NEXT_PUBLIC_ANVIL}
PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80
NETWORK_NAME=goerli
" >> .env
Loading