From 7388656ea002427c35097acdfeec1625f6706f40 Mon Sep 17 00:00:00 2001 From: Ndibe Raymond Olisaemeka Date: Mon, 27 Nov 2023 07:27:48 +0100 Subject: [PATCH] Create new github action to handle auto creation and destruction of test vms Issue: 1002 Signed-off-by: Ndibe Raymond Olisaemeka --- .github/workflows/create_destroy_test_vm.yaml | 190 ++++++++++++++++++ zubhub_frontend/zubhub/Dockerfile | 2 +- 2 files changed, 191 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/create_destroy_test_vm.yaml diff --git a/.github/workflows/create_destroy_test_vm.yaml b/.github/workflows/create_destroy_test_vm.yaml new file mode 100644 index 000000000..38827bb2a --- /dev/null +++ b/.github/workflows/create_destroy_test_vm.yaml @@ -0,0 +1,190 @@ +name: Create/Destroy Test VM + +on: + pull_request: + types: [opened, reopened, synchronize, labeled, unlabeled, closed] + +jobs: + create_test_vm: + if: | + ( + ( + github.event.action == 'opened' || + github.event.action == 'reopened' || + github.event.action == 'synchronize' + ) && contains(github.event.pull_request.labels.*.name, 'create-test-vm') + ) || + ( + github.event.action == 'labeled' && + github.event.label.name == 'create-test-vm' + ) + runs-on: ubuntu-latest + steps: + - name: Checkout files + uses: actions/checkout@v2 + + - name: Install doctl + uses: digitalocean/action-doctl@v2 + with: + token: ${{ secrets.DO_ACCESS_TOKEN }} + + - name: Create new droplet and DNS records + run: | + + NEW_DROPLET_NAME=zubhub-test-${{ github.event.pull_request.number }} + echo "NEW_DROPLET_NAME=$NEW_DROPLET_NAME" >> $GITHUB_ENV + # check if droplet already exists and exit script if it does + NEW_DROPLET_IP=$(doctl compute droplet get $NEW_DROPLET_NAME \ + --format PublicIPv4 --no-header 2>/dev/null || true) + if [ -n "$NEW_DROPLET_IP" ] ; then + echo "Droplet already exists. Save droplet IP to env variable and exit..." + echo "NEW_DROPLET_IP=$NEW_DROPLET_IP" >> $GITHUB_ENV + exit 0 + fi + + # create new droplet + doctl compute droplet create $NEW_DROPLET_NAME --image \ + ${{ secrets.SOURCE_SNAPSHOT_ID }} --tag-name zubhub-test --size s-1vcpu-2gb \ + --region nyc1 --enable-monitoring --ssh-keys ${{ secrets.DO_PUBLIC_SSHKEY_FP_TEMP }} --wait + # --region nyc1 --enable-monitoring --ssh-keys ${{ secrets.DO_PUBLIC_SSHKEY_FP }} --wait + sleep 30s + NEW_DROPLET_IP=$(doctl compute droplet get $NEW_DROPLET_NAME \ + --format PublicIPv4 --no-header) + echo "NEW_DROPLET_IP=$NEW_DROPLET_IP" >> $GITHUB_ENV + + # we only need records for frontend, media server and api server + FRONTEND_DOMAIN=${NEW_DROPLET_NAME}.unstructured.studio + API_DOMAIN=api.${FRONTEND_DOMAIN} + MEDIA_DOMAIN=media.${FRONTEND_DOMAIN} + echo "FRONTEND_DOMAIN=$FRONTEND_DOMAIN" >> $GITHUB_ENV + echo "API_DOMAIN=$API_DOMAIN" >> $GITHUB_ENV + echo "MEDIA_DOMAIN=$MEDIA_DOMAIN" >> $GITHUB_ENV + doctl compute domain records create unstructured.studio --record-type A --record-name \ + $FRONTEND_DOMAIN --record-data $NEW_DROPLET_IP --record-ttl 60 + doctl compute domain records create unstructured.studio --record-type A --record-name \ + $API_DOMAIN --record-data $NEW_DROPLET_IP --record-ttl 60 + doctl compute domain records create unstructured.studio --record-type A --record-name \ + $MEDIA_DOMAIN --record-data $NEW_DROPLET_IP --record-ttl 60 + + - name: Copy file via scp + uses: appleboy/scp-action@master + with: + host: ${{env.NEW_DROPLET_IP}} + username: ${{ secrets.DO_BACKEND_USERNAME }} + key: ${{ secrets.DO_SSHKEY }} + source: "." + target: "/home/zubhub" + + - name: Executing remote command + uses: appleboy/ssh-action@master + with: + host: ${{env.NEW_DROPLET_IP}} + username: ${{ secrets.DO_BACKEND_USERNAME }} + key: ${{ secrets.DO_SSHKEY }} + script: | + echo "========== env.frontend_domain: ${{env.FRONTEND_DOMAIN}}" + echo "========== env.api_domain: ${{env.API_DOMAIN}}" + echo "========== env.media_domain: ${{env.MEDIA_DOMAIN}}" + echo "========== frontend_domain: $FRONTEND_DOMAIN" + echo "========== api_domain: $API_DOMAIN" + echo "========== media_domain: $MEDIA_DOMAIN" + echo "========== {frontend_domain}: ${FRONTEND_DOMAIN}" + echo "========== {api_domain}: ${API_DOMAIN}" + echo "========== {media_domain}: ${MEDIA_DOMAIN}" + echo "========== env.new_droplet_ip: ${{env.NEW_DROPLET_IP}}" + echo "========== new_droplet_ip: $NEW_DROPLET_IP" + echo "========== {new_droplet_ip}: ${NEW_DROPLET_IP}" + # create env file for backend + cat << EOF > /home/zubhub_backend/.env + ENVIRONMENT=production + DEFAULT_FRONTEND_DOMAIN=$FRONTEND_DOMAIN + DEFAULT_BACKEND_DOMAIN=$API_DOMAIN + DEFAULT_DISPLAY_NAME=ZubHub + DEFAULT_FRONTEND_PROTOCOL=https + DEFAULT_BACKEND_PROTOCOL=https + SECRET_KEY=random string + DEBUG=1 + STORE_MEDIA_LOCALLY=1 + MEDIA_SECRET=random string + DEFAULT_MEDIA_SERVER_PROTOCOL=https + DEFAULT_MEDIA_SERVER_DOMAIN=$MEDIA_DOMAIN + POSTGRES_NAME=postgres + POSTGRES_USER=postgres + POSTGRES_PASSWORD=postgres + POSTGRES_HOST=db + GF_ADMIN_USER=admin + GF_ADMIN_PASSWORD=admin + RABBITMQ_DEFAULT_USER=admin + RABBITMQ_DEFAULT_PASS=admin + CELERY_BROKER=amqp://admin:admin@rabbitmq:5672/ + CELERY_BACKEND=django-db + CELERY_FLOWER_USER=admin + CELERY_FLOWER_PASSWORD=admin + PROXY_COUNT=0 + DETECT_MISCONFIG=0 + SUPERUSER_PASSWORD=dummy_password + EOF + + # create env file for frontend + cat << EOF > /home/zubhub_frontend/zubhub/.env + GENERATE_SOURCEMAP=false + REACT_APP_NODE_ENV=production + REACT_APP_BACKEND_DEVELOPMENT_URL= + REACT_APP_BACKEND_PRODUCTION_URL=https://${API_DOMAIN} + REACT_APP_DOSPACE_ACCESS_KEY_ID= + REACT_APP_DOSPACE_ACCESS_SECRET_KEY= + REACT_APP_VIDEO_UPLOAD_URL= + REACT_APP_VIDEO_FOLDER_NAME=videos + REACT_APP_DEV_VIDEO_FOLDER_NAME=dev_videos + REACT_APP_VIDEO_UPLOAD_PRESET_NAME=video_upload_preset + REACT_APP_DEV_VIDEO_UPLOAD_PRESET_NAME=dev_video_upload_preset + EOF + + # deploy project + cd /home/zubhub + sudo bash /home/zubhub/deploy_unscalable_fullstack.sh + + destroy_test_vm: + if: | + github.event.action == 'closed' || ( + github.event.action == 'unlabeled' && github.event.label.name == 'create-test-vm' + ) + runs-on: ubuntu-latest + steps: + - name: Install doctl + uses: digitalocean/action-doctl@v2 + with: + token: ${{ secrets.DO_ACCESS_TOKEN }} + + - name: Get pr number + run: | + # for events like unlabelled, github.event.pull_request.number is available + if [ -n ${{ github.event.pull_request.number }} ] ; then + echo "PR_NUMBER=${{ github.event.pull_request.number }}" >> $GITHUB_ENV + exit 1 + fi + + # github.event.pull_request.number is not available in closed event + sudo apt-get install jq -y + PR_NUMBER=$(curl --silent --show-error -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \ + https://api.github.com/repos/${{ github.repository }}/commits/${{ github.sha }}/pulls | \ + jq -r '.[0].number') + echo "PR_NUMBER=$(($PR_NUMBER))" >> $GITHUB_ENV + + - name: Delete test droplet + run: | + NEW_DROPLET_NAME=zubhub-test-${{env.PR_NUMBER}} + echo "NEW_DROPLET_NAME=$NEW_DROPLET_NAME" >> $GITHUB_ENV + doctl compute droplet delete $NEW_DROPLET_NAME --force + + - name: delete DNS records + run: | + FRONTEND_DOMAIN=${NEW_DROPLET_NAME}.unstructured.studio + API_DOMAIN=api.${FRONTEND_DOMAIN} + MEDIA_DOMAIN=media.${FRONTEND_DOMAIN} + doctl compute domain records delete unstructured.studio --record-name \ + $FRONTEND_DOMAIN + doctl compute domain records delete unstructured.studio --record-name \ + $API_DOMAIN + doctl compute domain records delete unstructured.studio --record-name \ + $MEDIA_DOMAIN diff --git a/zubhub_frontend/zubhub/Dockerfile b/zubhub_frontend/zubhub/Dockerfile index 51aab0df5..13ac950ac 100644 --- a/zubhub_frontend/zubhub/Dockerfile +++ b/zubhub_frontend/zubhub/Dockerfile @@ -15,4 +15,4 @@ COPY --from=build /zubhub_frontend/build /usr/share/nginx/html # new COPY nginx/dev/default.conf /etc/nginx/conf.d/default.conf EXPOSE 3000 -CMD ["nginx", "-g", "daemon off;"] \ No newline at end of file +CMD ["nginx", "-g", "daemon off;"]