diff --git a/.github/workflows/deploy_staging.yaml b/.github/workflows/deploy_staging.yaml new file mode 100644 index 0000000..21f7705 --- /dev/null +++ b/.github/workflows/deploy_staging.yaml @@ -0,0 +1,55 @@ +name: Deploy Staging to Server + +on: + push: + branches: + - staging + +jobs: + build-and-deploy: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: '1.24.x' + + - name: Install Templ + run: go install github.com/a-h/templ/cmd/templ@latest + + - name: Install tailwindcsscli + run: | + curl -fsSL -o tailwindcss https://github.com/tailwindlabs/tailwindcss/releases/latest/download/tailwindcss-linux-x64 + chmod +x tailwindcss + sudo mv tailwindcss /usr/local/bin/ + + - name: Run tests + run: make test + + - name: Build the binary + run: make build + + - name: Deploy to Server + env: + USER: deploy + HOST: projectreshoot.com + DIR: /home/deploy/releases/staging + DEPLOY_SSH_PRIVATE_KEY: ${{ secrets.DEPLOY_SSH_PRIVATE_KEY }} + run: | + mkdir -p ~/.ssh + echo "$DEPLOY_SSH_PRIVATE_KEY" > ~/.ssh/id_ed25519 + chmod 600 ~/.ssh/id_ed25519 + + echo "Host *" > ~/.ssh/config + echo " StrictHostKeyChecking no" >> ~/.ssh/config + echo " UserKnownHostsFile /dev/null" >> ~/.ssh/config + + ssh -i ~/.ssh/id_ed25519 $USER@$HOST mkdir -p $DIR + + scp -i ~/.ssh/id_ed25519 projectreshoot-${GITHUB_SHA} $USER@$HOST:$DIR + + ssh -i ~/.ssh/id_ed25519 $USER@$HOST 'bash -s' < ./deploy/deploy.sh $GITHUB_SHA diff --git a/Makefile b/Makefile index 68d12a7..7c92eaf 100644 --- a/Makefile +++ b/Makefile @@ -21,8 +21,8 @@ tester: test: rm -f **/.projectreshoot-test-database.db go mod tidy && \ - go test . - go test ./middleware + go generate && \ + go test ./... clean: go clean diff --git a/deploy/deploy_staging.sh b/deploy/deploy_staging.sh new file mode 100644 index 0000000..e7c77bf --- /dev/null +++ b/deploy/deploy_staging.sh @@ -0,0 +1,94 @@ +#!/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 +RELEASES_DIR="/home/deploy/releases/staging" +DEPLOY_BIN="/home/deploy/staging/projectreshoot" +SERVICE_NAME="staging.projectreshoot" +BINARY_NAME="projectreshoot-${COMMIT_HASH}" +declare -a PORTS=("3005" "3006" "3007") + +# Check if the binary exists +if [ ! -f "${RELEASES_DIR}/${BINARY_NAME}" ]; then + echo "Binary ${BINARY_NAME} not found in ${RELEASES_DIR}" + 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." diff --git a/deploy/systemd/production@.service b/deploy/systemd/production@.service new file mode 100644 index 0000000..84e3f2d --- /dev/null +++ b/deploy/systemd/production@.service @@ -0,0 +1,29 @@ +[Unit] +Description=Project Reshoot %i +After=network.target + +[Service] +ExecStart=/home/deploy/production/projectreshoot +WorkingDirectory=/home/deploy/production +User=deploy +Group=deploy +EnvironmentFile=/etc/env/projectreshoot.env +Environment="HOST=127.0.0.1" +Environment="PORT=%i" +Environment="TRUSTED_HOST=projectreshoot.com" +Environment="SSL=true" +Environment="GZIP=true" +Environment="LOG_LEVEL=info" +Environment="LOG_OUTPUT=file" +Environment="LOG_DIR=/home/deploy/production/logs" +LimitNOFILE=65536 +Restart=on-failure +TimeoutSec=30 +PrivateTmp=true +NoNewPrivilages=true +AmbientCapabilites=CAP_NET_BIND_SERVICE +StandardOutput=journal +StandardError=journal + +[Install] +WantedBy=multi-user.target diff --git a/deploy/systemd/staging@.service b/deploy/systemd/staging@.service new file mode 100644 index 0000000..8dad36f --- /dev/null +++ b/deploy/systemd/staging@.service @@ -0,0 +1,29 @@ +[Unit] +Description=Project Reshoot Staging %i +After=network.target + +[Service] +ExecStart=/home/deploy/staging/projectreshoot +WorkingDirectory=/home/deploy/staging +User=deploy +Group=deploy +EnvironmentFile=/etc/env/staging.projectreshoot.env +Environment="HOST=127.0.0.1" +Environment="PORT=%i" +Environment="TRUSTED_HOST=staging.projectreshoot.com" +Environment="SSL=true" +Environment="GZIP=true" +Environment="LOG_LEVEL=debug" +Environment="LOG_OUTPUT=both" +Environment="LOG_DIR=/home/deploy/staging/logs" +LimitNOFILE=65536 +Restart=on-failure +TimeoutSec=30 +PrivateTmp=true +ProtectSystem=full +ProtectHome=yes +StandardOutput=journal +StandardError=journal + +[Install] +WantedBy=multi-user.target