From 2b0bcd47321ec76519074fceeda2c992686e4951 Mon Sep 17 00:00:00 2001 From: Nikolay Eskov Date: Fri, 8 Nov 2024 15:27:46 +0300 Subject: [PATCH] Add node deploy workflow (#1536) * Change 'DEB_VER' Makefile variable. * Deploy workflow works. * Increase sleep time in deploy workflow before check that service is active. * Changed a bit workflow. * Use separate deploy environments for each network and arch. * Changed 'Deploy node' workflow. * Add 'deploy' step to the 'build' workflow. * Change secrets requirements of 'Deploy node to' workflow. * Add 'workflow_dispatch' input for running 'smoke_tests' in 'build' workflow. * Update condition for 'build.deploy' step. * Improve healthchecks. * Fix rollback step. * Remove comments and TODO. * Update workflows descriptions. * Add default value for 'arch' input in 'Deploy node to' reusable workflow. * Delete 'Deploy node' workflow. * Remove 'deploy' step from 'build' workflow. * Add 'workflow_dispatch' trigger for 'Deploy node to' workflow. * Add 'check-inputs' job for 'Deploy node to' workflow. * Rename 'Deploy node to' -> 'Deploy node' workflow. * Add 'Deploy nodes' workflow. * Add 'concurrency' rules for 'Deploy node' reusable workflow. --- .github/workflows/deploy_node.yml | 192 +++++++++++++++++++++++++++++ .github/workflows/deploy_nodes.yml | 21 ++++ .github/workflows/go.yml | 14 ++- Makefile | 2 +- 4 files changed, 226 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/deploy_node.yml create mode 100644 .github/workflows/deploy_nodes.yml diff --git a/.github/workflows/deploy_node.yml b/.github/workflows/deploy_node.yml new file mode 100644 index 000000000..0240c5da4 --- /dev/null +++ b/.github/workflows/deploy_node.yml @@ -0,0 +1,192 @@ +name: "Deploy node" +on: + workflow_dispatch: + inputs: + network: + required: true + type: string + description: "Waves network name (mainnet, testnet, stagenet)" + arch: + required: true + type: string + description: "Machine architecture (amd64, arm64)" + default: "amd64" + workflow_call: + inputs: + network: + required: true + type: string + description: "Waves network name (mainnet, testnet, stagenet)" + arch: + required: true + type: string + description: "Machine architecture (amd64, arm64)" + default: "amd64" + secrets: + SSH_PRIVATE_KEY: + required: false # should be taken from the environment secrets + description: "SSH private key for deployment server" + DEPLOYMENT_SERVER: + required: false # should be taken from the environment secrets + description: "Deployment server hostname or IP address" + DEPLOYMENT_PORT: + required: false # should be taken from the environment secrets + description: "Deployment server SSH port" + DEPLOYMENT_USER: + required: false # should be taken from the environment secrets + description: "Deployment server user" + +concurrency: + group: ${{ github.workflow }}-${{ github.event.inputs.network }}-${{ github.event.inputs.arch }} + cancel-in-progress: false # don't cancel the previous deployment if a new one is triggered + +jobs: + check-inputs: + name: check-inputs + runs-on: ubuntu-latest + steps: + - name: Check inputs + run: | + echo "${{ inputs.network }}" | grep -E '^(mainnet|testnet|stagenet)$' || exit 1 # check if the network is valid + echo "${{ inputs.arch }}" | grep -E '^(amd64|arm64)$' || exit 1 # check if the architecture is valid + + deploy: + name: deploy + needs: [ check-inputs ] + runs-on: ubuntu-latest + environment: + name: "Deploy-${{ inputs.network }}-${{ inputs.arch }}" + env: + MAKEFILE_TARGET: "build-node-${{ inputs.network }}-${{ inputs.arch }}-deb-package" + SERVICE_NAME: "gowaves-${{ inputs.network }}" # also used as a package name + BACKUP_PACKAGE_PATH: "/tmp/gowaves-${{ inputs.network }}-${{ inputs.arch }}_backup_${{ github.run_number }}.deb" + PACKAGE_NAME: "" # will be set by the step that builds the deb package + + steps: + - name: Set up Go 1.22 + uses: actions/setup-go@v5.0.2 + with: + go-version: 1.22.x + check-latest: true + cache: true + + - name: Check out code into the Go module directory + uses: actions/checkout@v4 + + - name: Get dependencies + run: go mod vendor + + - name: Build ${{ inputs.network }}-${{ inputs.arch }} deb package + run: | + make ${{ env.MAKEFILE_TARGET }} # build the deb package + mv build/dist/*.deb ./ # move the deb package to the root directory + echo "PACKAGE_NAME=$(ls ./*.deb | xargs -n 1 basename)" >> $GITHUB_ENV # set the package name for the next steps + + - name: Copy deb package to the deployment server + id: copy-deb + uses: appleboy/scp-action@v0.1.7 + with: + host: ${{ secrets.DEPLOYMENT_SERVER }} + username: ${{ secrets.DEPLOYMENT_USER }} + port: ${{ secrets.DEPLOYMENT_PORT }} + key: ${{ secrets.SSH_PRIVATE_KEY }} + source: ${{ env.PACKAGE_NAME }} + target: /tmp/ + + - name: Backup deb package on the deployment server + uses: appleboy/ssh-action@v1.1.0 + id: backup-deb + env: + SERVICE_NAME: ${{ env.SERVICE_NAME }} + BACKUP_PACKAGE_PATH: ${{ env.BACKUP_PACKAGE_PATH }} + DEPLOYMENT_USER: ${{ secrets.DEPLOYMENT_USER }} + with: + host: ${{ secrets.DEPLOYMENT_SERVER }} + username: ${{ secrets.DEPLOYMENT_USER }} + port: ${{ secrets.DEPLOYMENT_PORT }} + key: ${{ secrets.SSH_PRIVATE_KEY }} + script_stop: true + envs: SERVICE_NAME, BACKUP_PACKAGE_PATH, DEPLOYMENT_USER + script: | + dpkg-query --show $SERVICE_NAME || exit 0 # check if the package exists, if not, skip the backup + export TMPDIR=$(mktemp -d) && cd $TMPDIR + sudo dpkg-repack $SERVICE_NAME + sudo mv $(ls $TMPDIR/$SERVICE_NAME*.deb) $BACKUP_PACKAGE_PATH + sudo chown $DEPLOYMENT_USER:$DEPLOYMENT_USER $BACKUP_PACKAGE_PATH + rmdir $TMPDIR + + - name: Install deb package on the deployment server + uses: appleboy/ssh-action@v1.1.0 + id: install-deb + env: + PACKAGE_NAME: ${{ env.PACKAGE_NAME }} + SERVICE_NAME: ${{ env.SERVICE_NAME }} + with: + host: ${{ secrets.DEPLOYMENT_SERVER }} + username: ${{ secrets.DEPLOYMENT_USER }} + port: ${{ secrets.DEPLOYMENT_PORT }} + key: ${{ secrets.SSH_PRIVATE_KEY }} + script_stop: true + envs: PACKAGE_NAME, SERVICE_NAME + script: | + ls -l /tmp/$PACKAGE_NAME || exit 1 # check if the package exists + sudo systemctl stop $SERVICE_NAME || echo "Service $SERVICE_NAME is not running or does not exist" + sudo dpkg -i /tmp/$PACKAGE_NAME + sudo systemctl start $SERVICE_NAME + for ((i=1; i<=60; i++)); do + systemctl is-active $SERVICE_NAME || exit 1 # wait for the service to start and check its status for 60 seconds + sleep 1 + done + + - name: Rollback deb package on the deployment server + uses: appleboy/ssh-action@v1.1.0 + if: ${{ failure() }} + env: + BACKUP_PACKAGE_PATH: ${{ env.BACKUP_PACKAGE_PATH }} + SERVICE_NAME: ${{ env.SERVICE_NAME }} + with: + host: ${{ secrets.DEPLOYMENT_SERVER }} + username: ${{ secrets.DEPLOYMENT_USER }} + port: ${{ secrets.DEPLOYMENT_PORT }} + key: ${{ secrets.SSH_PRIVATE_KEY }} + script_stop: true + envs: BACKUP_PACKAGE_PATH, SERVICE_NAME + script: | + ls -l $BACKUP_PACKAGE_PATH || exit 1 # check if the backup package exists + sudo systemctl stop $SERVICE_NAME + sudo dpkg -i $BACKUP_PACKAGE_PATH + sudo systemctl start $SERVICE_NAME + for ((i=1; i<=60; i++)); do + systemctl is-active $SERVICE_NAME || exit 1 # wait for the service to start and check its status for 60 seconds + sleep 1 + done + + - name: Clean up deb package on the deployment server + uses: appleboy/ssh-action@v1.1.0 + if: ${{ always() }} + env: + PACKAGE_NAME: ${{ env.PACKAGE_NAME }} + with: + host: ${{ secrets.DEPLOYMENT_SERVER }} + username: ${{ secrets.DEPLOYMENT_USER }} + port: ${{ secrets.DEPLOYMENT_PORT }} + key: ${{ secrets.SSH_PRIVATE_KEY }} + script_stop: true + envs: PACKAGE_NAME + script: | + rm -f /tmp/$PACKAGE_NAME + + - name: Clean up backup deb package on the deployment server + uses: appleboy/ssh-action@v1.1.0 + if: ${{ always() }} + env: + BACKUP_PACKAGE_PATH: ${{ env.BACKUP_PACKAGE_PATH }} + with: + host: ${{ secrets.DEPLOYMENT_SERVER }} + username: ${{ secrets.DEPLOYMENT_USER }} + port: ${{ secrets.DEPLOYMENT_PORT }} + key: ${{ secrets.SSH_PRIVATE_KEY }} + script_stop: true + envs: BACKUP_PACKAGE_PATH + script: | + rm -f $BACKUP_PACKAGE_PATH diff --git a/.github/workflows/deploy_nodes.yml b/.github/workflows/deploy_nodes.yml new file mode 100644 index 000000000..851bd45e2 --- /dev/null +++ b/.github/workflows/deploy_nodes.yml @@ -0,0 +1,21 @@ +name: "Deploy nodes" +on: + workflow_dispatch: + inputs: + arch: + required: true + type: string + description: "Machine architecture (amd64, arm64)" + default: "amd64" + +jobs: + deploy: + name: deploy-node + strategy: + matrix: + network: [ stagenet, testnet, mainnet ] + arch: [ "${{ github.event.inputs.arch }}" ] + uses: "./.github/workflows/deploy_node_to.yml" + with: + network: ${{ matrix.network }} + arch: ${{ matrix.arch }} diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 875bf406f..d71472796 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -1,5 +1,14 @@ name: build -on: [ push, pull_request, workflow_dispatch ] +on: + push: + pull_request: + workflow_dispatch: + inputs: + smoke_tests: + required: false + type: boolean + description: 'Run smoke tests' + default: true concurrency: group: ${{ github.workflow }}-${{ github.ref }} @@ -75,7 +84,8 @@ jobs: smoke: name: smoke_tests runs-on: self-hosted - if: github.event_name == 'pull_request' && github.repository == 'wavesplatform/gowaves' + if: ${{ (github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' && github.event.inputs.smoke_tests) && + github.repository == 'wavesplatform/gowaves'}} steps: - name: Set up Go 1.22 diff --git a/Makefile b/Makefile index 8c000ad4c..2b57054a6 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ SOURCE=$(shell find . -name '*.go' | grep -v vendor/) SOURCE_DIRS = cmd pkg VERSION=$(shell git describe --tags --always --dirty) -DEB_VER=$(shell git describe --tags --abbrev=0 | cut -c 2-) +DEB_VER=$(shell echo $(VERSION) | cut -c 2-) DEB_HASH=$(shell git rev-parse HEAD) export GO111MODULE=on