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

🪚 Adding E2E test infrastructure #23

Merged
merged 18 commits into from
Nov 17, 2023
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
14 changes: 14 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# CI/CD files
.changeset
.github
.husky

# Dependencies & deployments
node_modules
deployments

# Metadata
*.md

# Docker files
docker-compose.templates.yaml
5 changes: 5 additions & 0 deletions .github/workflows/reusable-test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,8 @@ jobs:

- name: Test
run: yarn test
# Since we're running the E2E tests in docker, we'll need to reinstall
# the node modules. This is a temporary solution to bridge us between
# non-containerized and containerized development
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
83 changes: 83 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# .-.-. .-.-. .-.-. .-.-. .-.-. .-.-. .-.-. .-.-
# / / \ \ / / \ \ / / \ \ / / \ \ / / \ \ / / \ \ / / \ \ / / \
# `-' `-`-' `-`-' `-`-' `-`-' `-`-' `-`-' `-`-'
#
# Base node image with project dependencies
#
# .-.-. .-.-. .-.-. .-.-. .-.-. .-.-. .-.-. .-.-
# / / \ \ / / \ \ / / \ \ / / \ \ / / \ \ / / \ \ / / \ \ / / \
# `-' `-`-' `-`-' `-`-' `-`-' `-`-' `-`-' `-`-'
FROM node:18.16.0 as dependencies

ARG NPM_TOKEN
ENV YARN_CACHE_FOLDER=/tmp/yarn_cache

# Update the system packages
RUN apt-get update
RUN apt-get install -y \
# Get the envsubst command (see below)
gettext-base

WORKDIR /app

# Get the source code
#
# Oh god why yarn, paleolithic technology
#
# This would normally only copy package.json and/or lockfile
# and install the dependencies from lockfile in order not to break the cache
# everytime a file changes
COPY . .

# Get the .npmrc under a different name since envsubst will not work in place
# due to how pipes work on linux
#
# envsubst is a neat little thing that can substitute environment variables in a string
# and we can use it to keep NPM_TOKEN secret
#
# What we do is :
#
# - We pass the NPM_TOKEN as ARG
# - Set it as ENV variable only for the envsubst command so that it does not hang in the environment
# - Replace the environment variables in .npmrctemplate
# - Pipe the result to .npmrc
#
# We cannot do it in place (i.e. envsubst < .npmrc > .npmrc) because how linux works
# (it will create the output .npmrc file first, the pipe to it - but since it is now empty nothing will be piped)
COPY .npmrc .npmrctemplate

RUN \
# Mount yarn cache
--mount=type=cache,target=/tmp/yarn_cache \
# Substitute NPM_TOKEN in .npmrc
NPM_TOKEN=$NPM_TOKEN envsubst < .npmrctemplate > .npmrc && \
# Install dependencies (fail if we forgot to update the lockfile)
yarn install --prefer-offline --frozen-lockfile --non-interactive && \
# Remove .npmrc immediately
rm -rf .npmrc

# .-.-. .-.-. .-.-. .-.-. .-.-. .-.-. .-.-. .-.-
# / / \ \ / / \ \ / / \ \ / / \ \ / / \ \ / / \ \ / / \ \ / / \
# `-' `-`-' `-`-' `-`-' `-`-' `-`-' `-`-' `-`-'
#
# Image that builds the project
#
# .-.-. .-.-. .-.-. .-.-. .-.-. .-.-. .-.-. .-.-
# / / \ \ / / \ \ / / \ \ / / \ \ / / \ \ / / \ \ / / \ \ / / \
# `-' `-`-' `-`-' `-`-' `-`-' `-`-' `-`-' `-`-'
FROM dependencies as build

# Let's now add some fancy shit to compensate for the yarn fail above
#
# Turborepo allows us to be specific about the scope of the scripts
# using the --filter flag - see more here https://turbo.build/repo/docs/core-concepts/monorepos/filtering
ARG FILTER

WORKDIR /app

# Since our FILTER arg can be empty, we only want to pass the --filter
# flag to turborepo if FILTER is actually used
#
# This is nicely accomplished by the + alternate value substitution
# and results in something like --filter=my-filter
RUN yarn build ${FILTER:+--filter=$FILTER}
18 changes: 18 additions & 0 deletions docker-compose.templates.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# .-.-. .-.-. .-.-. .-.-. .-.-. .-.-. .-.-. .-.-
# / / \ \ / / \ \ / / \ \ / / \ \ / / \ \ / / \ \ / / \ \ / / \
# `-' `-`-' `-`-' `-`-' `-`-' `-`-' `-`-' `-`-'
#
# Reusable services for docker compose
#
# .-.-. .-.-. .-.-. .-.-. .-.-. .-.-. .-.-. .-.-
# / / \ \ / / \ \ / / \ \ / / \ \ / / \ \ / / \ \ / / \ \ / / \
# `-' `-`-' `-`-' `-`-' `-`-' `-`-' `-`-' `-`-'
version: "3.9"

services:
# Service that can build the whole project
project:
build:
context: .
args:
NPM_TOKEN: $NPM_TOKEN
1 change: 1 addition & 0 deletions packages/hardhat-utils/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"@layerzerolabs/lz-definitions": "~1.5.58",
"@layerzerolabs/lz-evm-sdk-v1": "~1.5.58",
"@types/chai-as-promised": "^7.1.7",
"@types/mocha": "^10.0.1",
"chai": "^4.3.10",
"chai-as-promised": "^7.1.1",
"hardhat": "^2.9.9",
Expand Down
3 changes: 2 additions & 1 deletion packages/ua-utils-test-v2/.gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
cache
cache
deployments
26 changes: 26 additions & 0 deletions packages/ua-utils-test-v2/deploy/001_bootstrap.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { type DeployFunction } from "hardhat-deploy/types"
import { AddressZero } from "@ethersproject/constants"
import assert from "assert"

/**
* This deploy function will deploy and configure LayerZero endpoint
*
* @param env `HardhatRuntimeEnvironment`
*/
const deploy: DeployFunction = async ({ getUnnamedAccounts, deployments, network }) => {
assert(network.config.endpointId != null, `Missing endpoint ID for network ${network.name}`)

const [deployer] = await getUnnamedAccounts()
const endpointV2Deployment = await deployments.deploy("EndpointV2", {
from: deployer,
args: [network.config.endpointId, AddressZero],
})

console.table({
EndpointV2: endpointV2Deployment.address,
})
}

deploy.tags = ["Bootstrap", "EndpointV2"]

export default deploy
33 changes: 33 additions & 0 deletions packages/ua-utils-test-v2/docker-compose.templates.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# .-.-. .-.-. .-.-. .-.-. .-.-. .-.-. .-.-. .-.-
# / / \ \ / / \ \ / / \ \ / / \ \ / / \ \ / / \ \ / / \ \ / / \
# `-' `-`-' `-`-' `-`-' `-`-' `-`-' `-`-' `-`-'
#
# Reusable services for docker compose
#
# .-.-. .-.-. .-.-. .-.-. .-.-. .-.-. .-.-. .-.-
# / / \ \ / / \ \ / / \ \ / / \ \ / / \ \ / / \ \ / / \ \ / / \
# `-' `-`-' `-`-' `-`-' `-`-' `-`-' `-`-' `-`-'
version: "3.9"

services:
# Service that can build this package
package:
build:
args:
FILTER: ua-utils-test-v2...
extends:
file: ../../docker-compose.templates.yaml
service: project
working_dir: /app/packages/ua-utils-test-v2
volumes:
- ./:/app/packages/ua-utils-test-v2

# Hardhat node started on port 8545
node:
extends:
service: package
expose:
- 8545
command: ["npx", "hardhat", "node", "--hostname", "0.0.0.0", "--no-deploy"]
healthcheck:
test: ["CMD", "curl", "-f", "http://0.0.0.0:8545/"]
67 changes: 67 additions & 0 deletions packages/ua-utils-test-v2/docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# .-.-. .-.-. .-.-. .-.-. .-.-. .-.-. .-.-. .-.-
# / / \ \ / / \ \ / / \ \ / / \ \ / / \ \ / / \ \ / / \ \ / / \
# `-' `-`-' `-`-' `-`-' `-`-' `-`-' `-`-' `-`-'
#
# Docker compose for running E2E tests
#
# .-.-. .-.-. .-.-. .-.-. .-.-. .-.-. .-.-. .-.-
# / / \ \ / / \ \ / / \ \ / / \ \ / / \ \ / / \ \ / / \ \ / / \
# `-' `-`-' `-`-' `-`-' `-`-' `-`-' `-`-' `-`-'
version: "3.9"

services:
# ~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~
#
# Network nodes, one for every hardhat network
#
# .oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.
network-vengaboys:
extends:
file: docker-compose.templates.yaml
service: node

network-britney:
extends:
file: docker-compose.templates.yaml
service: node

# ~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~
#
# Bootstrap script that deploys all the networks
#
# .oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.
bootstrap:
extends:
file: docker-compose.templates.yaml
service: package
depends_on:
network-vengaboys:
condition: service_healthy
network-britney:
condition: service_healthy
# Can't say I love the fact that the deploy scripts are inlined here
# but at least it's all in this file that bootstraps the whole environment
#
# The "&" at the end of the lines and "wait" work together to execute the deployments
# in parallel and wait until they are all complete
command:
- /bin/bash
- -c
- |
npx hardhat --network vengaboys deploy --reset &
npx hardhat --network britney deploy --reset &
wait

# ~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~
#
# The actual tests
#
# .oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.
tests:
extends:
file: docker-compose.templates.yaml
service: package
depends_on:
bootstrap:
condition: service_completed_successfully
command: ["npx", "hardhat", "test"]
24 changes: 19 additions & 5 deletions packages/ua-utils-test-v2/hardhat.config.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,33 @@
import "hardhat-deploy"
import { withLayerZeroArtifacts } from "@layerzerolabs/hardhat-utils"
import { EndpointId } from "@layerzerolabs/lz-definitions"
import { HardhatUserConfig } from "hardhat/types"

const MNEMONIC = "test test test test test test test test test test test test"

/**
* This is a dummy hardhat config that enables us to test
* hardhat functionality without mocking too much
*/
const config: HardhatUserConfig = {
networks: {
"ethereum-mainnet": {
url: "https://eth.llamarpc.com",
hardhat: {
accounts: {
mnemonic: MNEMONIC,
},
},
vengaboys: {
endpointId: EndpointId.ETHEREUM_MAINNET,
url: "http://network-vengaboys:8545",
accounts: {
mnemonic: MNEMONIC,
},
},
"bsc-testnet": {
url: "https://bsc-testnet.publicnode.com",
britney: {
endpointId: EndpointId.AVALANCHE_MAINNET,
url: "http://network-britney:8545",
accounts: {
mnemonic: "test test test test test test test test test test test junk",
mnemonic: MNEMONIC,
},
},
},
Expand Down
9 changes: 5 additions & 4 deletions packages/ua-utils-test-v2/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"private": true,
"scripts": {
"lint": "npx eslint '**/*.{js,ts,json}'",
"test": "npx hardhat test"
"test": "docker compose run --rm tests"
},
"repository": {
"type": "git",
Expand All @@ -15,6 +15,7 @@
},
"devDependencies": {
"@ethersproject/abstract-signer": "^5.7.0",
"@ethersproject/constants": "^5.7.0",
"@ethersproject/providers": "^5.7.0",
"@ethersproject/wallet": "^5.7.0",
"@gnosis.pm/safe-core-sdk": "^2.0.0",
Expand All @@ -25,12 +26,12 @@
"@layerzerolabs/lz-definitions": "~1.5.58",
"@layerzerolabs/lz-evm-sdk-v1": "~1.5.58",
"@layerzerolabs/lz-evm-sdk-v2": "~1.5.58",
"@layerzerolabs/ua-utils": "~0.0.15",
"@types/chai-as-promised": "^7.1.7",
"@nomiclabs/hardhat-ethers": "^2.2.3",
"ethers": "^5.7.0",
"@types/chai-as-promised": "^7.1.7",
"@types/mocha": "^10.0.1",
"chai": "^4.3.10",
"chai-as-promised": "^7.1.1",
"ethers": "^5.7.0",
"hardhat": "^2.9.9",
"hardhat-deploy": "^0.11.22",
"sinon": "^17.0.1",
Expand Down
24 changes: 22 additions & 2 deletions packages/ua-utils-test-v2/test/config.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,28 @@
import hre from "hardhat"
import { expect } from "chai"
import { describe } from "mocha"
import { NetworkEnvironment, createGetNetworkEnvironment } from "@layerzerolabs/hardhat-utils"

const NETWORK_NAMES = ["vengaboys", "britney"]

describe("config", () => {
it("should always succeed", () => {
expect(1).to.equal(1)
NETWORK_NAMES.forEach((networkName) => {
const getEnvironment = createGetNetworkEnvironment(hre)

describe(`Network '${networkName}`, () => {
let environment: NetworkEnvironment

before(async () => {
environment = await getEnvironment(networkName)
})

it("should have an endpoint deployed", async () => {
const endpoint = await environment.getContract("EndpointV2", environment.provider)
const endpointId = await endpoint.eid()

expect(environment.network.config.endpointId).to.be.a("number")
expect(endpointId).to.eql(environment.network.config.endpointId)
})
})
})
})
2 changes: 1 addition & 1 deletion packages/ua-utils-test-v2/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"extends": "../../tsconfig.json",
"exclude": ["dist", "node_modules"],
"include": ["src", "test", "*.config.ts"],
"include": ["src", "test", "deploy", "*.config.ts"],
"compilerOptions": {
"module": "commonjs",
"types": ["node", "mocha"]
Expand Down
3 changes: 2 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"allowSyntheticDefaultImports": true,
"allowJs": true,
"resolveJsonModule": true,
"types": ["node"]
"types": ["node"],
"skipLibCheck": true
}
}