name: CI/CD on: push: branches: [dev, main] pull_request: branches: [main] env: REGISTRY: gitea.jeffemmett.com IMAGE: gitea.jeffemmett.com/jeffemmett/canvas-website jobs: test: runs-on: ubuntu-latest steps: - name: Checkout run: | apt-get update -qq && apt-get install -y -qq git python3 make g++ > /dev/null 2>&1 git clone --depth 1 --branch ${{ github.ref_name }} http://token:${{ github.token }}@server:3000/${{ github.repository }}.git . - name: Install dependencies run: npm ci --legacy-peer-deps - name: Type check run: npx tsc --noEmit - name: Unit tests run: npx vitest run - name: Worker tests run: npx vitest run --config vitest.worker.config.ts build-check: runs-on: ubuntu-latest steps: - name: Checkout run: | apt-get update -qq && apt-get install -y -qq git python3 make g++ > /dev/null 2>&1 git clone --depth 1 --branch ${{ github.ref_name }} http://token:${{ github.token }}@server:3000/${{ github.repository }}.git . - name: Install dependencies run: npm ci --legacy-peer-deps - name: Build run: npm run build env: NODE_OPTIONS: "--max-old-space-size=4096" deploy: if: github.ref == 'refs/heads/main' && github.event_name == 'push' needs: [test, build-check] runs-on: ubuntu-latest container: image: docker:24-cli volumes: - /var/run/docker.sock:/var/run/docker.sock steps: - name: Setup tools run: apk add --no-cache git openssh-client curl - name: Checkout run: git clone --depth 1 --branch ${{ github.ref_name }} http://token:${{ github.token }}@server:3000/${{ github.repository }}.git . - name: Set image tag run: | SHORT_SHA=$(echo "${{ github.sha }}" | cut -c1-8) echo "IMAGE_TAG=${SHORT_SHA}" >> $GITHUB_ENV echo "Building image tag: ${SHORT_SHA}" - name: Build image run: docker build -t ${{ env.IMAGE }}:${{ env.IMAGE_TAG }} -t ${{ env.IMAGE }}:latest . - name: Push to registry run: | echo "${{ secrets.REGISTRY_TOKEN }}" | docker login ${{ env.REGISTRY }} -u ${{ secrets.REGISTRY_USER }} --password-stdin docker push ${{ env.IMAGE }}:${{ env.IMAGE_TAG }} docker push ${{ env.IMAGE }}:latest - name: Deploy to server run: | mkdir -p ~/.ssh echo "${{ secrets.DEPLOY_SSH_KEY }}" | base64 -d > ~/.ssh/deploy_key chmod 600 ~/.ssh/deploy_key ssh -o StrictHostKeyChecking=no -i ~/.ssh/deploy_key root@${{ secrets.DEPLOY_HOST }} " cd /opt/websites/canvas-website-staging cat .last-deployed-tag 2>/dev/null > .rollback-tag || true echo '${{ env.IMAGE_TAG }}' > .last-deployed-tag docker pull ${{ env.IMAGE }}:${{ env.IMAGE_TAG }} IMAGE_TAG=${{ env.IMAGE_TAG }} docker compose up -d --no-build " - name: Smoke test run: | sleep 10 HTTP_CODE=$(curl -sS -o /dev/null -w "%{http_code}" --max-time 15 https://jeffemmett.com/ 2>/dev/null || echo "000") if [ "$HTTP_CODE" != "200" ]; then echo "Smoke test failed (HTTP $HTTP_CODE) — rolling back" ROLLBACK_TAG=$(ssh -o StrictHostKeyChecking=no -i ~/.ssh/deploy_key root@${{ secrets.DEPLOY_HOST }} "cat /opt/websites/canvas-website-staging/.rollback-tag 2>/dev/null") if [ -n "$ROLLBACK_TAG" ]; then ssh -o StrictHostKeyChecking=no -i ~/.ssh/deploy_key root@${{ secrets.DEPLOY_HOST }} \ "cd /opt/websites/canvas-website-staging && IMAGE_TAG=$ROLLBACK_TAG docker compose up -d --no-build" echo "Rolled back to $ROLLBACK_TAG" fi exit 1 fi echo "Smoke test passed (HTTP $HTTP_CODE)"