From 2e12daa7b552e73871d4627faf9de0011d50a819 Mon Sep 17 00:00:00 2001 From: florian Date: Sat, 11 Oct 2025 16:19:36 +0200 Subject: [PATCH 1/2] Github actions: Automatically increase image number pushed to GHCR and update deployment configuration file --- .gitea/workflows/build.yaml | 43 +++++++++++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/.gitea/workflows/build.yaml b/.gitea/workflows/build.yaml index 4f83eb7..9d70d02 100644 --- a/.gitea/workflows/build.yaml +++ b/.gitea/workflows/build.yaml @@ -6,7 +6,13 @@ on: - main env: + GHCR_ORG: gansejunge IMAGE_NAME: app-notifications-backend-api-internal + IMAGE_PATH: ghcr.io/gansejunge/app-notifications-backend-api-internal + OPS_ORG: notifier + OPS_REPO: ops-deployment + OPS_BRANCH_BASE: main + OPS_PATH: backend-api-internal/deployment.yaml jobs: build: @@ -18,7 +24,40 @@ jobs: - name: Log in to GHCR run: echo "${{ secrets.GHCR_TOKEN }}" | docker login ghcr.io -u ${{ secrets.GHCR_USERNAME }} --password-stdin + - name: Get Latest Tag + id: get_tag + run: | + BASE64_TOKEN=$(echo "${{ secrets.GHCR_TOKEN }}" | base64) + LATEST_TAG=$(curl -s -H "Authorization: Bearer $BASE64_TOKEN" \ + https://ghcr.io/v2/${{ env.GHCR_ORG }}/${{ env.IMAGE_NAME }}/tags/list \ + | jq -r '.tags | map(select(test("^[0-9]+$"))) | map(tonumber) | max // 0') + NEXT_TAG=$((LATEST_TAG + 1)) + echo "latest=$LATEST_TAG" >> $GITHUB_OUTPUT + echo "next=$NEXT_TAG" >> $GITHUB_OUTPUT + - name: Build and Push Docker Image run: | - docker build -t ghcr.io/gansejunge/${IMAGE_NAME}:1 . - docker push ghcr.io/gansejunge/${IMAGE_NAME}:1 + docker build -t ghcr.io/gansejunge/${{ env.IMAGE_NAME }}:${{ steps.get_tag.outputs.next }} . + docker push ghcr.io/gansejunge/${{ env.IMAGE_NAME }}:${{ steps.get_tag.outputs.next }} + + - name: Clone ops-deployment repo + uses: actions/checkout@v4 + with: + repository: notifier/ops-deployment + path: ./ops-deployment + token: ${{ secrets.BOT_TOKEN }} + + - name: Update backend-api-internal deployment + working-directory: ./ops-deployment + run: | + NEW_TAG=${{ steps.get_tag.outputs.next }} + NEW_IMAGE="${{ env.IMAGE_PATH }}:$NEW_TAG" + git config user.name "automation-bot" + git config user.email "dev@gansejunge.com" + + sed -i "s|ghcr.io/$GHCR_ORG/$IMAGE_NAME:[0-9]\+|$NEW_IMAGE|g" "$OPS_PATH" + + COMMIT_URL="https://git.gansejunge.com/${GITHUB_REPOSITORY}/commit/${GITHUB_SHA}" + git add $OPS_PATH + git commit -m "Update backend-api image to version $NEW_TAG" -m "Linked build commit: $COMMIT_URL" + git push origin $OPS_BRANCH_BASE From 608d9c54aff4828204bf336e8f705139d62bc768 Mon Sep 17 00:00:00 2001 From: florian Date: Sat, 11 Oct 2025 16:36:25 +0200 Subject: [PATCH 2/2] Prometheus: Add health check that queries the DB and RMQ for its state --- src/main.py | 44 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/src/main.py b/src/main.py index 2169745..6fb1587 100644 --- a/src/main.py +++ b/src/main.py @@ -53,9 +53,15 @@ api = FastAPI( ) @api.middleware("http") -async def prometheus_middleware(request, call_next): - response = await call_next(request) - REQUEST_COUNTER.labels(request.method, request.url.path, response.status_code).inc() +async def prometheus_middleware(request: Request, call_next): + status = 500 + try: + response = await call_next(request) + status = response.status_code + except Exception: + raise + finally: + REQUEST_COUNTER.labels(request.method, request.url.path, status).inc() return response def verify_api_key_dependency_internal(db=Depends(get_db), api_key: str = Depends(api_key_header_internal)) -> str: @@ -78,6 +84,38 @@ async def custom_http_exception_handler(request,exc): content={"detail": exc.detail} ) +@api.get("/health", tags=["Health"]) +def return_health(request:Request, db=Depends(get_db)): + try: + cursor = db.cursor() + cursor.execute("SELECT 1") + cursor.fetchone() + db_status = "ok" + except Exception as e: + logger.error(f"Health check DB failed: {e}") + db_status = "error" + + try: + rmq_conn = getattr(request.app.state, "rmq_connection", None) + if not rmq_conn or not rmq_conn.is_open: + logger.error("Health check RMQ failed: connection closed or missing") + rmq_status = "error" + except Exception as e: + logger.error(f"Health check RMQ failed: {e}") + rmq_status = "error" + + overall_status = "ok" if db_status == "ok" and rmq_status == "ok" else "error" + status_code = 200 if overall_status == "ok" else 500 + + return JSONResponse( + status_code=status_code, + content={"status": overall_status, + "components": { + "database": db_status, + "rabbitmq": rmq_status + }, + "message": "Service is running" if overall_status == "ok" else "One or more checks failed"} + ) @api.post("/internal/receive-notifications") def receive_notifications(