Backend Release #114
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Backend Release | |
| on: | |
| workflow_run: | |
| workflows: ["Backend CI"] | |
| branches: [main] | |
| types: | |
| - completed | |
| permissions: | |
| contents: write | |
| jobs: | |
| release: | |
| if: ${{ github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.event == 'push' }} | |
| runs-on: ubuntu-latest | |
| outputs: | |
| version: ${{ steps.semantic.outputs.new_release_version }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| fetch-tags: true | |
| ref: ${{ github.event.workflow_run.head_sha }} | |
| # --------------------------- | |
| # Setup Node | |
| # --------------------------- | |
| - name: Setup Node | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: 20 | |
| - name: Install semantic-release | |
| run: | | |
| npm install -g semantic-release \ | |
| @semantic-release/commit-analyzer \ | |
| @semantic-release/release-notes-generator \ | |
| @semantic-release/github \ | |
| conventional-changelog-conventionalcommits | |
| # --------------------------- | |
| # Run semantic-release | |
| # --------------------------- | |
| - name: Semantic Release | |
| id: semantic | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| npx semantic-release | tee release.log | |
| VERSION=$(grep -oP 'Published release \K[0-9]+\.[0-9]+\.[0-9]+' release.log || true) | |
| echo "Detected version: $VERSION" | |
| echo "new_release_version=$VERSION" >> $GITHUB_OUTPUT | |
| # --------------------------- | |
| # Stop if no release | |
| # --------------------------- | |
| - name: Check release | |
| if: steps.semantic.outputs.new_release_version == '' | |
| run: | | |
| echo "No release created. Skipping Docker build/deploy steps." | |
| # --------------------------- | |
| # Docker Login | |
| # --------------------------- | |
| - name: Login to Docker Hub | |
| if: steps.semantic.outputs.new_release_version != '' | |
| uses: docker/login-action@v3 | |
| with: | |
| username: ${{ secrets.DOCKERHUB_USERNAME }} | |
| password: ${{ secrets.DOCKERHUB_TOKEN }} | |
| # --------------------------- | |
| # Build + Push | |
| # --------------------------- | |
| - name: Build and Push | |
| if: steps.semantic.outputs.new_release_version != '' | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: . | |
| file: ./Dockerfile | |
| push: true | |
| tags: | | |
| projectbook07/projectbook-backend:v${{ steps.semantic.outputs.new_release_version }} | |
| projectbook07/projectbook-backend:sha-${{ github.sha }} | |
| # --------------------------- | |
| # Deploy via SSH | |
| # --------------------------- | |
| - name: Deploy to VPS | |
| if: steps.semantic.outputs.new_release_version != '' | |
| uses: appleboy/ssh-action@v1.0.3 | |
| with: | |
| host: ${{ secrets.VPS_HOST }} | |
| username: ${{ secrets.VPS_USER }} | |
| key: ${{ secrets.VPS_SSH_KEY }} | |
| script: | | |
| set -e | |
| IMAGE="projectbook07/projectbook-backend:v${{ steps.semantic.outputs.new_release_version }}" | |
| CONTAINER="projectbook-backend" | |
| NEW_CONTAINER="projectbook-backend-new" | |
| echo "Pulling image..." | |
| docker pull $IMAGE | |
| echo "Starting new container..." | |
| docker run -d \ | |
| --name $NEW_CONTAINER \ | |
| --network projectbook-net \ | |
| --restart unless-stopped \ | |
| --env-file /opt/projectbook/backend.env \ | |
| -p 127.0.0.1:8081:8080 \ | |
| $IMAGE | |
| echo "Waiting for health..." | |
| for i in {1..30}; do | |
| if curl -fsS http://127.0.0.1:8081/readyz; then | |
| echo "New container healthy" | |
| break | |
| fi | |
| sleep 2 | |
| done | |
| if ! curl -fsS http://127.0.0.1:8081/readyz; then | |
| echo "New container failed" | |
| docker logs $NEW_CONTAINER | |
| docker rm -f $NEW_CONTAINER | |
| exit 1 | |
| fi | |
| echo "Replacing old container..." | |
| docker stop $CONTAINER || true | |
| docker rm $CONTAINER || true | |
| docker run -d \ | |
| --name $CONTAINER \ | |
| --network projectbook-net \ | |
| --restart unless-stopped \ | |
| --env-file /opt/projectbook/backend.env \ | |
| -p 127.0.0.1:8080:8080 \ | |
| $IMAGE | |
| docker rm -f $NEW_CONTAINER | |
| echo "Deployment complete" | |
| # --------------------------- | |
| # Promote to stable (ONLY if deploy succeeds) | |
| # --------------------------- | |
| - name: Tag stable | |
| if: success() && steps.semantic.outputs.new_release_version != '' | |
| run: | | |
| docker pull projectbook07/projectbook-backend:v${{ steps.semantic.outputs.new_release_version }} | |
| docker tag projectbook07/projectbook-backend:v${{ steps.semantic.outputs.new_release_version }} projectbook07/projectbook-backend:stable | |
| docker push projectbook07/projectbook-backend:stable |