Skip to content

[M] Deploy Testnet L2 #640

[M] Deploy Testnet L2

[M] Deploy Testnet L2 #640

# Deploys an Obscuro network on Azure for Testnet and Dev Testnet
#
# The Obscuro network is composed of 2 obscuro nodes running on individual vms with SGX. At the moment the workflow
# can only be triggered manually as a workflow dispatch.
#
# This script uses GitHub Environments for variables (vars) and secrets - these are configured on GitHub and
# the environments match the input.testnet_type options
name: '[M] Deploy Testnet L2'
on:
workflow_dispatch:
inputs:
testnet_type:
description: 'Testnet Type'
required: true
default: 'dev-testnet'
type: choice
options:
- 'dev-testnet'
- 'testnet'
- 'sepolia-testnet'
log_level:
description: 'Log Level 1-Error 5-Trace'
required: true
default: 3
type: number
jobs:
build:
runs-on: ubuntu-latest
# Map a step output to a job output
outputs:
MGMT_CONTRACT_ADDR: ${{ steps.deployContracts.outputs.MGMT_CONTRACT_ADDR }}
MSG_BUS_CONTRACT_ADDR: ${{ steps.deployContracts.outputs.MSG_BUS_CONTRACT_ADDR }}
L1_START_HASH: ${{ steps.deployContracts.outputs.L1_START_HASH }}
HOC_ERC20_ADDR: ${{ steps.deployContracts.outputs.HOC_ERC20_ADDR }}
POC_ERC20_ADDR: ${{ steps.deployContracts.outputs.POC_ERC20_ADDR }}
steps:
- name: Load dotenv
id: dotenv
uses: falti/[email protected]
with:
path: ${{ github.event.inputs.testnet_type }}.env
log-variables: true
export-variables: true
keys-case: bypass
- name: 'Test_ENV_1'
id: Test_ENV_1
shell: bash
run: |
echo "Loaded environment variables -> ${{ steps.dotenv.outputs.RESOURCE_TESTNET_NAME }}"
- uses: actions/checkout@v3
- uses: actions/setup-go@v4
with:
go-version: 1.20.4
- name: 'Login via Azure CLI'
uses: azure/login@v1
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- name: 'Login to Azure docker registry'
uses: azure/docker-login@v1
with:
login-server: testnetobscuronet.azurecr.io
username: testnetobscuronet
password: ${{ secrets.REGISTRY_PASSWORD }}
- name: 'Build and push obscuro node images'
run: |
DOCKER_BUILDKIT=1 docker build -t ${{vars.L2_ENCLAVE_DOCKER_BUILD_TAG}} -f dockerfiles/enclave.Dockerfile .
docker push ${{vars.L2_ENCLAVE_DOCKER_BUILD_TAG}}
DOCKER_BUILDKIT=1 docker build -t ${{vars.L2_HOST_DOCKER_BUILD_TAG}} -f dockerfiles/host.Dockerfile .
docker push ${{vars.L2_HOST_DOCKER_BUILD_TAG}}
DOCKER_BUILDKIT=1 docker build -t ${{vars.L2_HARDHATDEPLOYER_DOCKER_BUILD_TAG}} -f tools/hardhatdeployer/Dockerfile .
docker push ${{vars.L2_HARDHATDEPLOYER_DOCKER_BUILD_TAG}}
- name: 'Deploy Contracts'
id: deployContracts
shell: bash
run: |
go run ./testnet/launcher/l1contractdeployer/cmd \
-l1_http_url=${{ secrets.L1_HTTP_URL }} \
-private_key=${{ secrets.WORKER_PK }} \
-docker_image=${{vars.L2_HARDHATDEPLOYER_DOCKER_BUILD_TAG}} \
-contracts_env_file=./testnet/.env
source ./testnet/.env
echo "Contracts deployed to $MGMTCONTRACTADDR"
echo "MGMT_CONTRACT_ADDR=$MGMTCONTRACTADDR" >> $GITHUB_ENV
echo "MGMT_CONTRACT_ADDR=$MGMTCONTRACTADDR" >> $GITHUB_OUTPUT
echo "MSG_BUS_CONTRACT_ADDR=$MSGBUSCONTRACTADDR" >> $GITHUB_ENV
echo "MSG_BUS_CONTRACT_ADDR=$MSGBUSCONTRACTADDR" >> $GITHUB_OUTPUT
echo "L1_START_HASH=$L1START" >> $GITHUB_ENV
echo "L1_START_HASH=$L1START" >> $GITHUB_OUTPUT
- name: 'Save container logs on failure'
if: failure()
# Wait to make sure the logs are available in the container
run: |
sleep 60
docker logs `docker ps -aqf "name=hh-l1-deployer"` > deploy-l1-contracts.out 2>&1
# This will fail some deletions due to resource dependencies ( ie. you must first delete the vm before deleting the disk)
- name: 'Delete deployed VMs'
uses: azure/CLI@v1
with:
inlineScript: |
$(az resource list --tag ${{vars.RESOURCE_TAG_NAME}}=true --query '[]."id"' -o tsv | xargs -n1 az resource delete --verbose -g Testnet --ids) || true
# This will clean up any lingering dependencies - might fail if there are no resources to cleanup
- name: 'Delete VMs dependencies'
uses: azure/CLI@v1
with:
inlineScript: |
$(az resource list --tag ${{vars.RESOURCE_TAG_NAME}}=true --query '[]."id"' -o tsv | xargs -n1 az resource delete --verbose -g Testnet --ids) || true
- name: 'Upload container logs on failure'
uses: actions/upload-artifact@v3
if: failure()
with:
name: deploy-l1-artifacts
path: |
deploy-l1-contracts.out
retention-days: 2
deploy:
needs: build
runs-on: ubuntu-latest
environment:
name: ${{ github.event.inputs.testnet_type }}
strategy:
matrix:
host_id: [ 0,1 ]
include:
# Ensure there is a single genesis node
- is_genesis: true
host_id: 0
- is_genesis: false
host_id: 1
# Ensure there is a single sequencer
- node_type: sequencer
host_id: 0
- node_type: validator
host_id: 1
# Hardcoded lookup keys because GH actions doesn't let you build them inline with the host_id
- node_pk_lookup: NODE_WALLET_PK_0
host_id: 0
- node_pk_lookup: NODE_WALLET_PK_1
host_id: 1
- node_addr_lookup: NODE_WALLET_ADDR_0
host_id: 0
- node_addr_lookup: NODE_WALLET_ADDR_1
host_id: 1
- node_l1_ws_lookup: L1_WS_URL_0
host_id: 0
- node_l1_ws_lookup: L1_WS_URL_1
host_id: 1
steps:
- name: 'Test_ENV_2'
id: Test_ENV_2
shell: bash
run: |
echo "Loaded environment variables -> ${{ steps.dotenv.outputs.RESOURCE_TESTNET_NAME }}"
- name: 'Extract branch name'
shell: bash
run: |
echo "Branch Name: ${GITHUB_REF_NAME}"
echo "BRANCH_NAME=${GITHUB_REF_NAME}" >> $GITHUB_ENV
# The Azure API will sometimes supersede PUT requests that come in close together. This sleep will stagger the VM requests.
# It expects host_id to be an int and then multiplies it by 60s (i.e. host 0: sleep 0, host 1: sleep 60,...)
- name: 'Stagger VM creation'
shell: bash
run: sleep `expr ${{matrix.host_id}} \* 60`
- name: 'Login via Azure CLI'
uses: azure/login@v1
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- name: 'Create VM for Obscuro node-${{ matrix.host_id }} on Azure'
uses: azure/CLI@v1
with:
inlineScript: |
az vm create -g Testnet -n "${{vars.RESOURCE_STARTING_NAME}}-${{ matrix.host_id }}-${{ GITHUB.RUN_NUMBER }}" \
--admin-username obscurouser --admin-password "${{ secrets.OBSCURO_NODE_VM_PWD }}" \
--public-ip-address-dns-name "obscuronode-${{ matrix.host_id }}-${{vars.RESOURCE_TESTNET_NAME}}-${{ GITHUB.RUN_NUMBER }}" \
--tags deploygroup=ObscuroNode-${{vars.RESOURCE_TESTNET_NAME}}-${{ GITHUB.RUN_NUMBER }} ${{vars.RESOURCE_TAG_NAME}}=true \
--vnet-name ObscuroHost-${{vars.RESOURCE_TESTNET_NAME}}-01VNET --subnet ObscuroHost-${{vars.RESOURCE_TESTNET_NAME}}-01Subnet \
--size Standard_DC4s_v2 --image ObscuroConfUbuntu \
--public-ip-sku Basic --authentication-type password
- name: 'Open Obscuro node-${{ matrix.host_id }} ports on Azure'
uses: azure/CLI@v1
with:
inlineScript: |
az vm open-port -g Testnet -n "${{vars.RESOURCE_STARTING_NAME}}-${{ matrix.host_id }}-${{ GITHUB.RUN_NUMBER }}" --port 80,81,6060,6061,10000
# To overcome issues with critical VM resources being unavailable, we need to wait for the VM to be ready
- name: 'Allow time for VM initialization'
shell: bash
run: sleep 60
- name: 'Start Obscuro node-${{ matrix.host_id }} on Azure'
uses: azure/CLI@v1
with:
inlineScript: |
az vm run-command invoke -g Testnet -n "${{vars.RESOURCE_STARTING_NAME}}-${{ matrix.host_id }}-${{ GITHUB.RUN_NUMBER }}" \
--command-id RunShellScript \
--scripts 'mkdir -p /home/obscuro \
&& git clone --depth 1 -b ${{ env.BRANCH_NAME }} https://github.com/obscuronet/go-obscuro.git /home/obscuro/go-obscuro \
&& docker network create --driver bridge node_network || true \
&& docker run -d --name datadog-agent \
--network node_network \
-e DD_API_KEY=${{ secrets.DD_API_KEY }} \
-e DD_LOGS_ENABLED=true \
-e DD_LOGS_CONFIG_CONTAINER_COLLECT_ALL=true \
-e DD_LOGS_CONFIG_AUTO_MULTI_LINE_DETECTION=true \
-e DD_CONTAINER_EXCLUDE_LOGS="name:datadog-agent" \
-e DD_SITE="datadoghq.eu" \
-v /var/run/docker.sock:/var/run/docker.sock:ro \
-v /proc/:/host/proc/:ro \
-v /opt/datadog-agent/run:/opt/datadog-agent/run:rw \
-v /sys/fs/cgroup/:/host/sys/fs/cgroup:ro \
datadog/agent:latest \
&& cd /home/obscuro/go-obscuro/ \
&& sudo go run /home/obscuro/go-obscuro/go/node/cmd \
-is_genesis=${{ matrix.is_genesis }} \
-node_type=${{ matrix.node_type }} \
-is_sgx_enabled=true \
-host_id=${{ vars[matrix.node_addr_lookup] }} \
-l1_ws_url=${{ secrets[matrix.node_l1_ws_lookup] }} \
-management_contract_addr=${{needs.build.outputs.MGMT_CONTRACT_ADDR}} \
-message_bus_contract_addr=${{needs.build.outputs.MSG_BUS_CONTRACT_ADDR}} \
-l1_start=${{needs.build.outputs.L1_START_HASH}} \
-private_key=${{ secrets[matrix.node_pk_lookup] }} \
-sequencer_id=${{ vars.NODE_WALLET_ADDR_0 }} \
-host_public_p2p_addr=obscuronode-${{ matrix.host_id }}-${{vars.RESOURCE_TESTNET_NAME}}-${{ GITHUB.RUN_NUMBER }}.uksouth.cloudapp.azure.com:10000 \
-host_p2p_port=10000 \
-enclave_docker_image=${{vars.L2_ENCLAVE_DOCKER_BUILD_TAG}} \
-host_docker_image=${{vars.L2_HOST_DOCKER_BUILD_TAG}} \
-is_debug_namespace_enabled=true \
-log_level=${{ github.event.inputs.log_level }} \
-batch_interval=${{vars.BATCH_INTERVAL}} \
-rollup_interval=${{vars.ROLLUP_INTERVAL}} \
start'
update-loadbalancer:
needs:
- build
- deploy
runs-on: ubuntu-latest
environment:
name: ${{ github.event.inputs.testnet_type }}
steps:
- uses: actions/checkout@v3
- name: 'Login via Azure CLI'
uses: azure/login@v1
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- name: 'Remove existing backend nodes from the load balancer'
run: ./.github/workflows/runner-scripts/testnet-clear-loadbalancer.sh ${{vars.RESOURCE_TESTNET_NAME}}
- name: 'Add load balancer address pool to the IP configuration'
uses: azure/CLI@v1
with:
inlineScript: |
az network nic ip-config address-pool add \
--address-pool Backend-Pool-Obscuro-${{vars.RESOURCE_TESTNET_NAME}} \
--ip-config-name ipconfig${{vars.RESOURCE_STARTING_NAME}}-1-${{ GITHUB.RUN_NUMBER }} \
--nic-name ${{vars.RESOURCE_STARTING_NAME}}-1-${{ GITHUB.RUN_NUMBER }}VMNic \
--resource-group Testnet \
--lb-name ${{vars.RESOURCE_TESTNET_NAME}}-loadbalancer
check-obscuro-is-healthy:
needs:
- build
- deploy
runs-on: ubuntu-latest
environment:
name: ${{ github.event.inputs.testnet_type }}
steps:
- uses: actions/checkout@v3
- name: "Wait until obscuro node is healthy"
shell: bash
run: |
./.github/workflows/runner-scripts/wait-node-healthy.sh --host=obscuronode-0-${{vars.RESOURCE_TESTNET_NAME}}-${{ GITHUB.RUN_NUMBER }}.uksouth.cloudapp.azure.com
./.github/workflows/runner-scripts/wait-node-healthy.sh --host=obscuronode-1-${{vars.RESOURCE_TESTNET_NAME}}-${{ GITHUB.RUN_NUMBER }}.uksouth.cloudapp.azure.com
deploy-l2-contracts:
needs:
- build
- check-obscuro-is-healthy
runs-on: ubuntu-latest
environment:
name: ${{ github.event.inputs.testnet_type }}
steps:
- uses: actions/checkout@v3
- name: 'Deploy L2 contracts'
id: deployL2Contracts
shell: bash
run: |
go run ./testnet/launcher/l2contractdeployer/cmd \
-l2_host=obscuronode-0-${{vars.RESOURCE_TESTNET_NAME}}-${{ GITHUB.RUN_NUMBER }}.uksouth.cloudapp.azure.com \
-l1_http_url=${{ secrets.L1_HTTP_URL }} \
-l2_ws_port=81 \
-private_key=${{ secrets.WORKER_PK }} \
-l2_private_key=8dfb8083da6275ae3e4f41e3e8a8c19d028d32c9247e24530933782f2a05035b \
-l2_hoc_private_key=6e384a07a01263518a09a5424c7b6bbfc3604ba7d93f47e3a455cbdd7f9f0682 \
-l2_poc_private_key=4bfe14725e685901c062ccd4e220c61cf9c189897b6c78bd18d7f51291b2b8f8 \
-message_bus_contract_addr=${{ needs.build.outputs.MSG_BUS_CONTRACT_ADDR }} \
-docker_image=${{vars.L2_HARDHATDEPLOYER_DOCKER_BUILD_TAG}}
- name: 'Save container logs on failure'
if: failure()
run: |
docker logs `docker ps -aqf "name=hh-l2-deployer"` > deploy-l2-contracts.out 2>&1
- name: 'Upload container logs on failure'
uses: actions/upload-artifact@v3
if: failure()
with:
name: deploy-l2-artifacts
path: |
deploy-l2-contracts.out
retention-days: 2
deploy-faucet:
name: 'Trigger Faucet deployment for dev- / testnet on a new deployment'
uses: ./.github/workflows/manual-deploy-testnet-faucet.yml
with:
testnet_type: ${{github.event.inputs.testnet_type}}
secrets: inherit
needs:
- check-obscuro-is-healthy
obscuro-test-repository-dispatch:
runs-on: ubuntu-latest
environment:
name: ${{ github.event.inputs.testnet_type }}
needs:
- deploy-faucet
steps:
- name: 'Send a repository dispatch to obscuro-test on deployment of dev-testnet'
if: ${{ (github.event.inputs.testnet_type == 'dev-testnet') }}
run: |
curl -XPOST -H "Authorization: Bearer ${{ secrets.GH_TOKEN }}" -H "Accept:application/vnd.github" -H "Content-Type:application/json" https://api.github.com/repos/obscuronet/obscuro-test/dispatches --data '{ "event_type": "dev_testnet_deployed", "client_payload": { "ref": "${{ github.ref_name }}" }'
- name: 'Send a repository dispatch to obscuro-test on deployment of testnet'
if: ${{ (github.event.inputs.testnet_type == 'testnet') }}
run: |
curl -XPOST -H "Authorization: Bearer ${{ secrets.GH_TOKEN }}" -H "Accept:application/vnd.github" -H "Content-Type:application/json" https://api.github.com/repos/obscuronet/obscuro-test/dispatches --data '{ "event_type": "testnet_deployed", "client_payload": { "ref": "${{ github.ref_name }}" }'