Skip to content

Commit

Permalink
Allow running faucet tests against custom network (#9910)
Browse files Browse the repository at this point in the history
  • Loading branch information
banool authored Sep 19, 2023
1 parent fc55d9d commit 9c4150f
Show file tree
Hide file tree
Showing 8 changed files with 190 additions and 20 deletions.
7 changes: 5 additions & 2 deletions .github/actions/run-faucet-tests/action.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ description: |
Runs the tests for the Aptos faucet against a local testnet built from a particular release branch
inputs:
NETWORK:
description: "The network branch for running the local testnet: devnet or testnet."
description: "The network branch for running the local testnet: devnet, testnet, or custom for a specific tag."
required: true
IMAGE_TAG:
description: "The docker image tag to use for the local testnet if NETWORK=custom."
required: true
GCP_DOCKER_ARTIFACT_REPO:
description: "The GCP Docker artifact repository."
Expand Down Expand Up @@ -35,7 +38,7 @@ runs:
# testnet, moving the mint key where the tests expect it to be, and running the
# integration tests.
- name: Run integration tests
run: poetry run python main.py --base-network ${{ inputs.NETWORK }} --external-test-dir ${{ runner.temp }}/testnet --image-repo-with-project ${{ inputs.GCP_DOCKER_ARTIFACT_REPO }}
run: poetry run python main.py --base-network ${{ inputs.NETWORK }} --tag ${{ inputs.IMAGE_TAG }} --external-test-dir ${{ runner.temp }}/testnet --image-repo-with-project ${{ inputs.GCP_DOCKER_ARTIFACT_REPO }}
working-directory: crates/aptos-faucet/integration-tests
shell: bash

Expand Down
16 changes: 16 additions & 0 deletions .github/workflows/docker-build-test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,22 @@ jobs:
GIT_SHA: ${{ needs.determine-docker-build-metadata.outputs.gitSha }}
SKIP_JOB: ${{ needs.file_change_determinator.outputs.only_docs_changed == 'true' }}

faucet-tests-main:
needs: [permission-check, rust-images, determine-docker-build-metadata, file_change_determinator] # runs with the default release docker build variant "rust-images"
if: |
(
github.event_name == 'push' ||
github.event_name == 'workflow_dispatch' ||
contains(github.event.pull_request.labels.*.name, 'CICD:run-e2e-tests') ||
github.event.pull_request.auto_merge != null) ||
contains(github.event.pull_request.body, '#e2e'
)
uses: ./.github/workflows/faucet-tests-main.yaml
secrets: inherit
with:
GIT_SHA: ${{ needs.determine-docker-build-metadata.outputs.gitSha }}
SKIP_JOB: ${{ needs.file_change_determinator.outputs.only_docs_changed == 'true' }}

indexer-grpc-e2e-tests:
needs: [permission-check, rust-images, determine-docker-build-metadata] # runs with the default release docker build variant "rust-images"
if: |
Expand Down
74 changes: 74 additions & 0 deletions .github/workflows/faucet-tests-main.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
## IMPORTANT NOTE TO EDITORS OF THIS FILE ##

## If you are trying to change how this CI works, you MUST go read the important
## note at the top of docker-build-test.yaml. In short, to test this, you must temporarily
## change docker-build-test to use the pull_request trigger instead of pull_request_target.

## Make sure to add the CICD:CICD:build-images and CICD:run-e2e-tests labels to test
## this within an in-review PR.

## If the above approach is too slow (since you have to wait for the rust images
## to build), you can cut the iteration time dramatically by changing the envs
## - Replace env.IMAGE_TAG for a known image tag
## - env.GIT_SHA will resolve to that of your PR branch

# These tests ensure that changes to the node don't break compatibility with the faucet.
#
# For tests that prevent changes to the faucet breaking compatibility with the production
# networks, see faucet-tests-prod.
#
# This test uses the node image built from the previous step, hence the workflow_call
# trigger.

name: "Faucet Integration Tests: Main"
on:
# This is called from within the docker-build-test.yaml workflow since we depend
# on the images having been built before this workflow runs.
workflow_call:
inputs:
GIT_SHA:
required: true
type: string
description: Use this to override the git SHA1, branch name (e.g. devnet) or tag to release the SDK from
SKIP_JOB:
required: false
default: false
type: boolean
description: Set to true to skip this job. Useful for PRs that don't require this workflow.

env:
# This is the docker image tag that will be used for the SDK release.
# It is also used to pull the docker images for the CI.
IMAGE_TAG: ${{ inputs.GIT_SHA || 'devnet' }} # default to "devnet" tag when not running on workflow_call
GIT_SHA: ${{ inputs.GIT_SHA || github.event.pull_request.head.sha || github.sha }} # default to PR branch sha when not running on workflow_call

jobs:
# These tests ensure that the faucet works with a node built from main. If we only
# upgrade devnet if this job is green and we always update the faucet image alongside
# the image for the faucet private fullnode, the faucet and fullnode should always
# be compatible in production.
run-tests-main:
if: contains(github.event.pull_request.labels.*.name, 'CICD:non-required-tests')
runs-on: high-perf-docker
steps:
- uses: actions/checkout@v3
if: ${{ !inputs.SKIP_JOB }}
with:
ref: ${{ env.GIT_SHA }}

- uses: aptos-labs/aptos-core/.github/actions/docker-setup@main
if: ${{ !inputs.SKIP_JOB }}
with:
GCP_WORKLOAD_IDENTITY_PROVIDER: ${{ secrets.GCP_WORKLOAD_IDENTITY_PROVIDER }}
GCP_SERVICE_ACCOUNT_EMAIL: ${{ secrets.GCP_SERVICE_ACCOUNT_EMAIL }}
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_DOCKER_ARTIFACT_REPO: ${{ secrets.AWS_DOCKER_ARTIFACT_REPO }}
GIT_CREDENTIALS: ${{ secrets.GIT_CREDENTIALS }}

- uses: ./.github/actions/run-faucet-tests
if: ${{ !inputs.SKIP_JOB }}
with:
NETWORK: custom
IMAGE_TAG: ${{ env.IMAGE_TAG }}
GCP_DOCKER_ARTIFACT_REPO: ${{ secrets.GCP_DOCKER_ARTIFACT_REPO }}
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
name: "Faucet Integration Tests"
# These tests ensure that changes to the faucet itself or its code dependencies don't
# cause the faucet to stop working with the production (devnet and testnet) networks.
#
# For tests that prevent the node from breaking compatibility with the faucet, see
# faucet-tests-main.
#
# These tests use node images built from devnet / testnet so we don't need to use
# workflow_call to wait for the image build to finish.

name: "Faucet Integration Tests: Prod"
on:
pull_request_target:
types: [labeled, opened, synchronize, reopened, auto_merge_enabled]
Expand All @@ -24,6 +33,7 @@ jobs:
required-permission: write
comment-not-permitted: Sorry, you don't have permission to trigger this workflow.

# These tests ensure that the faucet works with the nodes running on devnet.
run-tests-devnet:
if: contains(github.event.pull_request.labels.*.name, 'CICD:non-required-tests')
needs: [permission-check]
Expand All @@ -43,6 +53,7 @@ jobs:
NETWORK: devnet
GCP_DOCKER_ARTIFACT_REPO: ${{ secrets.GCP_DOCKER_ARTIFACT_REPO }}

# These tests ensure that the faucet works with the nodes running on testnet.
run-tests-testnet:
if: contains(github.event.pull_request.labels.*.name, 'CICD:non-required-tests')
needs: [permission-check]
Expand Down
8 changes: 4 additions & 4 deletions crates/aptos-faucet/core/src/server/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -825,7 +825,7 @@ mod test {

// Assert that the account exists now with the expected balance.
let response = aptos_node_api_client
.get_account_balance(AccountAddress::from_hex(fund_request.address.unwrap()).unwrap())
.get_account_balance(AccountAddress::from_str(&fund_request.address.unwrap()).unwrap())
.await?;

assert_eq!(response.into_inner().get(), 10);
Expand Down Expand Up @@ -883,7 +883,7 @@ mod test {

// Assert that the account exists now with the expected balance.
let response = aptos_node_api_client
.get_account_balance(AccountAddress::from_hex(fund_request.address.unwrap()).unwrap())
.get_account_balance(AccountAddress::from_str(&fund_request.address.unwrap()).unwrap())
.await?;

assert_eq!(response.into_inner().get(), 10);
Expand Down Expand Up @@ -931,7 +931,7 @@ mod test {

// Confirm that the account was given the full 1000 OCTA as requested.
let response = aptos_node_api_client
.get_account_balance(AccountAddress::from_hex(fund_request.address.unwrap()).unwrap())
.get_account_balance(AccountAddress::from_str(&fund_request.address.unwrap()).unwrap())
.await?;

assert_eq!(response.into_inner().get(), 1000);
Expand All @@ -949,7 +949,7 @@ mod test {

// Confirm that the account was only given 100 OCTA (maximum_amount), not 1000.
let response = aptos_node_api_client
.get_account_balance(AccountAddress::from_hex(fund_request.address.unwrap()).unwrap())
.get_account_balance(AccountAddress::from_str(&fund_request.address.unwrap()).unwrap())
.await?;

assert_eq!(response.into_inner().get(), 100);
Expand Down
59 changes: 52 additions & 7 deletions crates/aptos-faucet/integration-tests/common.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,63 @@
# Copyright © Aptos Foundation
# SPDX-License-Identifier: Apache-2.0

from enum import Enum
from dataclasses import dataclass
from typing import Optional

NODE_PORT = 8080


class Network(Enum):
DEVNET = "devnet"
TESTNET = "testnet"
DEVNET = "devnet"
TESTNET = "testnet"
CUSTOM = "custom"


@dataclass
class Network:
def __str__(self) -> str:
raise NotImplementedError()


class DevnetNetwork(Network):
def __str__(self) -> str:
return DEVNET

def tag(self) -> str:
return str(self)


class TestnetNetwork(Network):
def __str__(self):
return self.value
return TESTNET

def tag(self) -> str:
return str(self)


class CustomNetwork(Network):
def __init__(self, tag: str):
self._tag = tag

def __str__(self) -> str:
return self._tag

def tag(self) -> str:
return self._tag


VALID_NETWORK_OPTIONS = [DEVNET, TESTNET, CUSTOM]


def network_from_str(str: str, tag: Optional[str]) -> Network:
if str == DEVNET:
return DevnetNetwork()
elif str == TESTNET:
return TestnetNetwork()
else:
if not tag:
raise ValueError("--tag must be provided for custom network")
return CustomNetwork(tag)


def build_image_name(image_repo_with_project: str, tag: str):
return f"{image_repo_with_project}/tools:{tag}"
def build_image_name(image_repo_with_project: str, network: Network):
return f"{image_repo_with_project}/tools:{network.tag()}"
2 changes: 1 addition & 1 deletion crates/aptos-faucet/integration-tests/local_testnet.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
# stop running it later using the container name. For an explanation of these
# arguments, see the argument parser in main.py.
def run_node(network: Network, image_repo_with_project: str, external_test_dir: str):
image_name = build_image_name(image_repo_with_project, str(network))
image_name = build_image_name(image_repo_with_project, network)
container_name = f"local-testnet-{network}"
internal_mount_path = "/mymount"
LOG.info(f"Trying to run local testnet from image: {image_name}")
Expand Down
31 changes: 26 additions & 5 deletions crates/aptos-faucet/integration-tests/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,11 @@
import argparse
import logging
import os
import platform
import shutil
import sys

from common import Network
from common import VALID_NETWORK_OPTIONS, Network, network_from_str
from local_testnet import run_node, stop_node, wait_for_startup
from prechecks import check_redis_is_running
from tests import run_faucet_integration_tests
Expand Down Expand Up @@ -59,9 +60,18 @@ def parse_args():
parser.add_argument(
"--base-network",
required=True,
type=Network,
choices=list(Network),
help="What branch the Aptos CLI used for the local testnet should be built from",
choices=VALID_NETWORK_OPTIONS,
help=(
"What branch the Aptos CLI used for the local testnet should be built "
'from. If "custom", --tag must be set.'
),
)
parser.add_argument(
"--tag",
help=(
'If --base-network is set to "custom", this must be set to the image tag'
"to use. Otherwise this has no effect."
),
)
parser.add_argument(
"--base-startup-timeout",
Expand All @@ -87,13 +97,24 @@ def main():
else:
logging.getLogger().setLevel(logging.INFO)

if platform.system() == "Darwin" and platform.processor().startswith("arm"):
if not os.environ.get("DOCKER_DEFAULT_PLATFORM"):
os.environ["DOCKER_DEFAULT_PLATFORM"] = "linux/amd64"
LOG.info(
"Detected ARM Mac and DOCKER_DEFAULT_PLATFORM was not set, setting it "
"to linux/amd64"
)

# Build the Network.
network = network_from_str(args.base_network, args.tag)

# Verify that a local Redis instance is running. This is just a basic check that
# something is listening at the expected port.
check_redis_is_running()

# Run a node and wait for it to start up.
container_name = run_node(
args.base_network, args.image_repo_with_project, args.external_test_dir
network, args.image_repo_with_project, args.external_test_dir
)
wait_for_startup(container_name, args.base_startup_timeout)

Expand Down

0 comments on commit 9c4150f

Please sign in to comment.