diff --git a/.github/workflows/deploy_staging.yaml b/.github/workflows/deploy_staging.yaml index aab9831..da7556f 100644 --- a/.github/workflows/deploy_staging.yaml +++ b/.github/workflows/deploy_staging.yaml @@ -33,11 +33,15 @@ jobs: - name: Build the binary run: make build SUFFIX=-staging-$GITHUB_SHA + - name: Build the migration binary + run: make migrate SUFFIX=-staging-$GITHUB_SHA + - name: Deploy to Server env: USER: deploy HOST: projectreshoot.com DIR: /home/deploy/releases/staging + MIG_DIR: /home/deploy/migration-bin DEPLOY_SSH_PRIVATE_KEY: ${{ secrets.DEPLOY_SSH_PRIVATE_KEY }} run: | mkdir -p ~/.ssh @@ -49,7 +53,13 @@ jobs: echo " UserKnownHostsFile /dev/null" >> ~/.ssh/config ssh -i ~/.ssh/id_ed25519 $USER@$HOST mkdir -p $DIR - scp -i ~/.ssh/id_ed25519 projectreshoot-staging-${GITHUB_SHA} $USER@$HOST:$DIR - ssh -i ~/.ssh/id_ed25519 $USER@$HOST 'bash -s' < ./deploy/deploy_staging.sh $GITHUB_SHA + ssh -i ~/.ssh/id_ed25519 $USER@$HOST mkdir -p $MIG_DIR + scp -i ~/.ssh/id_ed25519 prmigrate-${GITHUB_SHA} $USER@$HOST:$MIG_DIR + + scp -i ~/.ssh/id_ed25519 ./deploy/db/backup.sh $USER@$HOST:$MIG_DIR + scp -i ~/.ssh/id_ed25519 ./deploy/db/migrate.sh $USER@$HOST:$MIG_DIR + scp -i ~/.ssh/id_ed25519 ./deploy/db/migrationcleanup.sh $USER@$HOST:$MIG_DIR + + ssh -i ~/.ssh/id_ed25519 $USER@$HOST 'bash -s' < ./deploy/deploy.sh $GITHUB_SHA staging diff --git a/Makefile b/Makefile index a8d363a..54cdec2 100644 --- a/Makefile +++ b/Makefile @@ -34,4 +34,4 @@ clean: migrate: go mod tidy && \ go generate && \ - go build -ldflags="-w -s" -o prmigrate ./migrate + go build -ldflags="-w -s" -o prmigrate${SUFFIX} ./migrate diff --git a/deploy/db/migrate.sh b/deploy/db/migrate.sh index 9285475..436fde7 100755 --- a/deploy/db/migrate.sh +++ b/deploy/db/migrate.sh @@ -1,7 +1,7 @@ #!/bin/bash if [[ -z "$1" ]]; then - echo "Usage: $0 " + echo "Usage: $0 " exit 1 fi ENVR="$1" @@ -10,7 +10,7 @@ if [[ "$ENVR" != "production" && "$ENVR" != "staging" ]]; then exit 1 fi if [[ -z "$2" ]]; then - echo "Usage: $0 " + echo "Usage: $0 " exit 1 fi TGT_VER="$2" @@ -19,8 +19,13 @@ if ! [[ $TGT_VER =~ $re ]] ; then echo "Error: version not a number" >&2 exit 1 fi - -BACKUP_OUTPUT=$(/bin/bash ./backup.sh "$ENVR" 2>&1) +if [ -z "$3" ]; then + echo "Usage: $0 " + exit 1 +fi +COMMIT_HASH=$3 +MIGRATION_BIN="/home/deploy/migration-bin" +BACKUP_OUTPUT=$(/bin/bash ${MIGRATION_BIN}/backup.sh "$ENVR" 2>&1) echo "$BACKUP_OUTPUT" if [[ $? -ne 0 ]]; then exit 1 @@ -59,7 +64,7 @@ failed_cleanup() { trap 'if [ $? -ne 0 ]; then failed_cleanup; fi' EXIT echo "Migration in progress from $CUR_VER to $TGT_VER" -./prmigrate $UPDATED_BACKUP $CMD $TGT_VER +${MIGRATION_BIN}/prmigrate-$COMMIT_HASH $UPDATED_BACKUP $CMD $TGT_VER if [ $? -ne 0 ]; then echo "Migration failed" exit 1 diff --git a/deploy/deploy.sh b/deploy/deploy.sh new file mode 100644 index 0000000..dd198e6 --- /dev/null +++ b/deploy/deploy.sh @@ -0,0 +1,113 @@ +#!/bin/bash + +# Exit on error +set -e + +# Check if commit hash is passed as an argument +if [ -z "$1" ]; then + echo "Usage: $0 " + exit 1 +fi +COMMIT_HASH=$1 +ENVR="$2" +if [[ "$ENVR" != "production" && "$ENVR" != "staging" ]]; then + echo "Error: environment must be 'production' or 'staging'." + exit 1 +fi + +RELEASES_DIR="/home/deploy/releases/$ENVR" +DEPLOY_BIN="/home/deploy/$ENVR/projectreshoot" +MIGRATION_BIN="/home/deploy/migration-bin" +BINARY_NAME="projectreshoot-$ENVR-${COMMIT_HASH}" +declare -a PORTS=("3000" "3001" "3002") +if [[ "$ENVR" == "production" ]]; then + SERVICE_NAME="projectreshoot" + declare -a PORTS=("3000" "3001" "3002") +else + SERVICE_NAME="$ENVR.projectreshoot" + declare -a PORTS=("3005" "3006" "3007") +fi + +# Check if the binary exists +if [ ! -f "${RELEASES_DIR}/${BINARY_NAME}" ]; then + echo "Binary ${BINARY_NAME} not found in ${RELEASES_DIR}" + exit 1 +fi +DB_VER=$(${RELEASES_DIR}/${BINARY_NAME} --dbver | grep -oP '(?<=Database version: ).*') +${MIGRATION_BIN}/migrate.sh $ENVR $DB_VER $COMMIT_HASH +if [[ $? -ne 0 ]]; then + echo "Migration failed" + exit 1 +fi + +# Keep a reference to the previous binary from the symlink +if [ -L "${DEPLOY_BIN}" ]; then + PREVIOUS=$(readlink -f $DEPLOY_BIN) + echo "Current binary is ${PREVIOUS}, saved for rollback." +else + echo "No symbolic link found, no previous binary to backup." + PREVIOUS="" +fi + +rollback_deployment() { + if [ -n "$PREVIOUS" ]; then + echo "Rolling back to previous binary: ${PREVIOUS}" + ln -sfn "${PREVIOUS}" "${DEPLOY_BIN}" + else + echo "No previous binary to roll back to." + fi + + # wait to restart the services + sleep 10 + + # Restart all services with the previous binary + for port in "${PORTS[@]}"; do + SERVICE="${SERVICE_NAME}@${port}.service" + echo "Restarting $SERVICE..." + sudo systemctl restart $SERVICE + done + + echo "Rollback completed." +} + +# Copy the binary to the deployment directory +echo "Promoting ${BINARY_NAME} to ${DEPLOY_BIN}..." +ln -sf "${RELEASES_DIR}/${BINARY_NAME}" "${DEPLOY_BIN}" + +WAIT_TIME=5 +restart_service() { + local port=$1 + local SERVICE="${SERVICE_NAME}@${port}.service" + echo "Restarting ${SERVICE}..." + + # Restart the service + if ! sudo systemctl restart "$SERVICE"; then + echo "Error: Failed to restart ${SERVICE}. Rolling back deployment." + + # Call the rollback function + rollback_deployment + exit 1 + fi + + # Wait a few seconds to allow the service to fully start + echo "Waiting for ${SERVICE} to fully start..." + sleep $WAIT_TIME + + # Check the status of the service + if ! systemctl is-active --quiet "${SERVICE}"; then + echo "Error: ${SERVICE} failed to start correctly. Rolling back deployment." + + # Call the rollback function + rollback_deployment + exit 1 + fi + + echo "${SERVICE}.service restarted successfully." +} + +for port in "${PORTS[@]}"; do + restart_service $port +done + +echo "Deployment completed successfully." +${MIGRATION_BIN}/migrationcleanup.sh $ENVR $DB_VER