Deploy Network #91
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--- | |
concurrency: ci-$ # Only a single workflow can be executed concurrently | |
name: Deploy Network | |
on: # yamllint disable-line rule:truthy | |
workflow_dispatch: | |
inputs: | |
environment: | |
description: The environment to run against | |
type: choice | |
options: [dev, test] # nightly should not be initiated manually | |
block_gas_limit: | |
description: Block Gas Limit | |
type: string | |
default: "200000000" | |
required: true | |
block_time: | |
description: Block Time | |
type: string | |
default: "2" | |
required: true | |
max_slots: | |
description: Max Slots | |
type: string | |
default: "276480" | |
required: true | |
max_enqueued: | |
description: Max Enqueued | |
type: string | |
default: "276480" | |
required: true | |
is_london_fork_active: | |
description: EIP-1559 | |
type: boolean | |
default: true | |
is_bridge_active: | |
description: With Bridge | |
type: boolean | |
default: true | |
gossip_msg_size: | |
description: Gossip Message Size | |
type: string | |
default: "1048576" | |
required: true | |
notification: | |
description: Notification | |
type: boolean | |
default: true | |
workflow_call: | |
inputs: | |
environment: | |
description: The environment to run against | |
type: string | |
required: true | |
block_gas_limit: | |
description: Block Gas Limit | |
type: string | |
required: true | |
block_time: | |
description: Block Time | |
type: string | |
required: true | |
max_slots: | |
description: Max Slots | |
type: string | |
required: true | |
max_enqueued: | |
description: Max Enqueued | |
type: string | |
required: true | |
is_london_fork_active: | |
description: EIP-1559 | |
type: boolean | |
required: true | |
is_bridge_active: | |
description: With Bridge | |
type: boolean | |
required: true | |
gossip_msg_size: | |
description: Gossip Message Size | |
type: string | |
required: true | |
notification: | |
description: Notification | |
type: boolean | |
required: true | |
outputs: | |
terraform_output: | |
description: Terraform output | |
value: ${{ jobs.deploy_network.outputs.terraform_output }} | |
ansible_output: | |
description: Ansible output | |
value: ${{ jobs.deploy_network.outputs.ansible_output }} | |
blade_healthcheck_output: | |
description: Blade Healthcheck output | |
value: ${{ jobs.deploy_network.outputs.blade_healthcheck_output }} | |
rpc_url: | |
description: RPC URL | |
value: ${{ jobs.check_network.outputs.rpc_url || jobs.deploy_network.outputs.rpc_url }} | |
secrets: | |
AWS_ROLE_ARN: | |
required: true | |
AWS_S3_BLADE_BUCKET: | |
required: true | |
VAULT_PASSWORD: | |
required: true | |
permissions: | |
id-token: write | |
contents: read | |
security-events: write | |
jobs: | |
check_network: | |
name: Check if the network is already deployed | |
runs-on: ubuntu-latest | |
outputs: | |
check_output: ${{ steps.check_state_file.outputs.resources }} | |
rpc_url: ${{ steps.rpc_url.outputs.url }} | |
steps: | |
- name: Checkout code | |
uses: actions/[email protected] | |
- name: Configure AWS Credentials | |
uses: aws-actions/[email protected] | |
with: | |
aws-region: ${{ vars.AWS_REGION }} | |
role-to-assume: ${{ secrets.AWS_ROLE_ARN }} | |
- name: Retrieve state file from s3 | |
id: retrieve_state | |
run: echo "retrieve_state_output=$(aws s3 cp s3://${{ secrets.AWS_S3_BLADE_BUCKET }}/states/${{ inputs.environment }} state.json)" >> $GITHUB_OUTPUT | |
- name: Check state file | |
id: check_state_file | |
if: contains(steps.retrieve_state.outputs.retrieve_state_output, 'download') | |
run: echo "resources=$(cat state.json | jq -r '.resources' | jq length)" >> $GITHUB_OUTPUT | |
- name: Set RPC URL | |
id: rpc_url | |
if: contains(steps.retrieve_state.outputs.retrieve_state_output, 'download') | |
run: echo "url=$(cat state.json | jq -r '.outputs.aws_lb_ext_domain.value // empty')" >> $GITHUB_OUTPUT | |
deploy_network: | |
name: Deploy the network | |
runs-on: ubuntu-latest | |
needs: check_network | |
if: needs.check_network.outputs.check_output == 0 | |
environment: ${{ inputs.environment }} | |
outputs: | |
terraform_output: ${{ steps.terraform_failure.outputs.terraform_output }} | |
ansible_output: ${{ steps.ansible_failure.outputs.ansible_output }} | |
blade_healthcheck_output: ${{ steps.blade_healthcheck.outputs.healthcheck }} | |
rpc_url: ${{ steps.rpc_url.outputs.url }} | |
steps: | |
- name: Checkout code | |
uses: actions/[email protected] | |
with: | |
repository: Ethernal-Tech/blade-deployment | |
ref: main | |
- name: Configure AWS Credentials | |
uses: aws-actions/[email protected] | |
with: | |
aws-region: ${{ vars.AWS_REGION }} | |
role-to-assume: ${{ secrets.AWS_ROLE_ARN }} | |
- name: Install Terraform | |
uses: hashicorp/[email protected] | |
with: | |
terraform_version: 1.4.5 | |
- name: Configure Terraform | |
run: sed 's/# backend "s3" {}/backend "s3" {}/' main.tf > main.tf.tmp && mv main.tf.tmp main.tf | |
- name: Terraform Init | |
run: terraform init -backend-config="bucket=${{ secrets.AWS_S3_BLADE_BUCKET }}" -backend-config="key=states/${{ inputs.environment }}" -backend-config="region=${{ vars.AWS_REGION }}" | |
- name: Terraform Validate | |
run: terraform validate -no-color | |
continue-on-error: true | |
- name: Terraform Apply | |
run: terraform apply -auto-approve | |
env: | |
TF_VAR_deployment_name: ${{ inputs.environment }} | |
TF_VAR_base_instance_type: ${{ vars.AWS_INSTANCE_TYPE }} | |
TF_VAR_geth_count: ${{ vars.GETH_COUNT }} | |
TF_VAR_fullnode_count: ${{ vars.FULLNODE_COUNT }} | |
TF_VAR_validator_count: ${{ vars.VALIDATOR_COUNT }} | |
- name: Terraform Failed | |
if: failure() | |
id: terraform_failure | |
run: echo "terraform_output=false" >> $GITHUB_OUTPUT | |
- name: Configure private keys | |
run: | | |
terraform output pk_ansible > ~/private.key | |
chmod 600 ~/private.key | |
eval "$(ssh-agent)" | |
ssh-add ~/private.key | |
- name: Install Ansible / botocore / boto3 | |
run: | | |
python3 -m pip install --user ansible | |
python3 -m pip install boto3 botocore | |
- name: Configure Ansible | |
working-directory: ansible | |
run: | | |
echo "${{ secrets.VAULT_PASSWORD }}" > password.txt | |
sed 's/devnet/${{ inputs.environment }}/g' inventory/aws_ec2.yml > inventory/aws_ec2.yml.tmp && mv inventory/aws_ec2.yml.tmp inventory/aws_ec2.yml | |
sed 's/blade_tag: .*/blade_tag: ${{ github.sha }}/g' group_vars/all.yml > group_vars/all.yml.tmp && mv group_vars/all.yml.tmp group_vars/all.yml | |
sed 's/is_bridge_active: .*/is_bridge_active: ${{ inputs.is_bridge_active }}/g' group_vars/all.yml > group_vars/all.yml.tmp && mv group_vars/all.yml.tmp group_vars/all.yml | |
sed 's/is_london_fork_active: .*/is_london_fork_active: ${{ inputs.is_london_fork_active }}/g' group_vars/all.yml > group_vars/all.yml.tmp && mv group_vars/all.yml.tmp group_vars/all.yml | |
sed 's/gossip_msg_size: .*/gossip_msg_size: ${{ inputs.gossip_msg_size }}/g' group_vars/all.yml > group_vars/all.yml.tmp && mv group_vars/all.yml.tmp group_vars/all.yml | |
sed 's/tx_gossip_batch_size: .*/tx_gossip_batch_size: 10000/g' group_vars/all.yml > group_vars/all.yml.tmp && mv group_vars/all.yml.tmp group_vars/all.yml | |
sed 's/json_rpc_batch_request_limit: .*/json_rpc_batch_request_limit: 0/g' group_vars/all.yml > group_vars/all.yml.tmp && mv group_vars/all.yml.tmp group_vars/all.yml | |
sed 's/log_level: .*/log_level: ${{ vars.LOG_LEVEL }}/g' group_vars/all.yml > group_vars/all.yml.tmp && mv group_vars/all.yml.tmp group_vars/all.yml | |
sed 's/epoch_reward: .*/epoch_reward: 1000000000/g' group_vars/all.yml > group_vars/all.yml.tmp && mv group_vars/all.yml.tmp group_vars/all.yml | |
sed 's/reward_wallet_balance: .*/reward_wallet_balance: 0xD3C21BCECCEDA1000000/g' group_vars/all.yml > group_vars/all.yml.tmp && mv group_vars/all.yml.tmp group_vars/all.yml | |
sed 's/config_socket: .*/config_socket: ${{ vars.CONFIG_SOCKET }}/g' group_vars/all.yml > group_vars/all.yml.tmp && mv group_vars/all.yml.tmp group_vars/all.yml | |
- name: Setup Ansible | |
working-directory: ansible | |
run: | | |
ansible-inventory --graph | |
ansible-galaxy install -r requirements.yml | |
- name: Check previous blade data | |
id: previous_data | |
run: echo "previous_data_output=$(aws s3 cp s3://${{ secrets.AWS_S3_BLADE_BUCKET }}/states/${{ inputs.environment }}.data.tar.gz .)" >> $GITHUB_OUTPUT | |
- name: Run Ansible (Bootstrap blade) | |
if: (steps.previous_data.outputs.previous_data_output == '' || contains(steps.previous_data.outputs.previous_data_output, 'error')) | |
working-directory: ansible | |
run: ansible-playbook site.yml --extra-vars "clean_deploy_title=${{ inputs.environment }} blade_repository=${{ github.repository }} block_gas_limit=${{ inputs.block_gas_limit }} block_time=${{ inputs.block_time }} max_slots=${{ inputs.max_slots }} max_enqueued=${{ inputs.max_enqueued }}" | |
- name: Run Ansible (Restore data) | |
if: contains(steps.previous_data.outputs.previous_data_output, 'download') | |
working-directory: ansible | |
run: ansible-playbook site.yml --extra-vars "clean_deploy_title=${{ inputs.environment }} blade_repository=${{ github.repository }} s3_bucket=${{ secrets.AWS_S3_BLADE_BUCKET }} restore_data=true" | |
- name: Ansible Failed | |
if: failure() | |
id: ansible_failure | |
run: echo "ansible_output=false" >> $GITHUB_OUTPUT | |
- name: Set RPC URL | |
id: rpc_url | |
run: echo "url=$(terraform output -raw aws_lb_ext_domain | grep -o -E '^ext[^:]*')" >> $GITHUB_OUTPUT | |
- name: Blade healthcheck | |
id: blade_healthcheck | |
run: echo "healthcheck=`curl http://${{ steps.rpc_url.outputs.url }} | jq -r 'select(.name == "blade") | length != 0'`" >> $GITHUB_OUTPUT | |
notification: | |
name: Deploy Notification | |
needs: [check_network, deploy_network] | |
uses: ./.github/workflows/notification-deploy-network.yml | |
if: ((success() || failure()) && inputs.notification) | |
with: | |
environment: ${{ inputs.environment }} | |
block_gas_limit: ${{ inputs.block_gas_limit }} | |
block_time: ${{ inputs.block_time }} | |
max_slots: ${{ inputs.max_slots }} | |
max_enqueued: ${{ inputs.max_enqueued }} | |
is_london_fork_active: ${{ inputs.is_london_fork_active }} | |
is_bridge_active: ${{ inputs.is_bridge_active }} | |
gossip_msg_size: ${{ inputs.gossip_msg_size }} | |
deploy_network_terraform_output: ${{ needs.deploy_network.outputs.terraform_output }} | |
deploy_network_ansible_output: ${{ needs.deploy_network.outputs.ansible_output }} | |
deploy_network_blade_healthcheck_output: ${{ needs.deploy_network.outputs.blade_healthcheck_output }} | |
rpc_url: ${{ needs.check_network.outputs.rpc_url || needs.deploy_network.outputs.rpc_url }} | |
secrets: | |
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} |