Repository: Debugger-Demons/whoknows
Pull request #61: feat/validate env and secrets workflow
Author: login: AlekOmOm
Labels: name: enhancement
description: New feature or request
Created: 2025-04-02T13:29:21Z | Merged: 2025-04-07T10:32:48Z

# Pull Request

## Changes
- [x] Code changes
- [x] Configuration changes 
- [x] Documentation updates
- [x] Infrastructure changes

## Description
Added environment secrets validation workflow to ensure proper configuration before deployment. The workflow validates that required environment variables exist in both development and production secrets, checks SSH key format, and verifies Docker credentials exist.

Includes:
- New validate.env_and_secrets.yml workflow
- Integration with branch testing workflow
- Updated Makefile to include commands for updating environment secrets

Related issue: #

## Quality Assurance
- [x] Tests added/updated
- [x] Documentation updated
- [x] Changes tested locally
- [x] Security implications considered

## Deployment
- [x] No breaking changes
- [ ] Database migrations required
- [x] Environment variables added
- [ ] Infrastructure dependencies updated

## Monitoring & Observability 
- [x] Logging added/updated
- [ ] Metrics added/updated
- [ ] Alerts configured (if needed)

## Reviewers
- [ ] Code review completed
- [ ] Architecture review completed (if needed)
- [x] Security review completed (if needed)

## Additional Notes
This workflow adds protection against deploying with misconfigured environment variables. It validates all required configuration variables exist before proceeding with deployment. No rollback plan is needed as this is a validation step that fails safely before deployment begins.

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

- **New Features**
  - Enhanced our deployment and CI/CD pipelines with automated environment and secret validation, version tracking, comprehensive health checks, and robust rollback mechanisms that ensure smooth and reliable updates.

- **Documentation**
  - Introduced updated guidelines promoting best practices for deployment processes and Docker image management.

- **Chores**
  - Streamlined workflow processes and improved configuration formatting to bolster overall system consistency and operational efficiency.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->


Diff:
diff --git a/.env.development b/.env.development
new file mode 100644
index 00000000..c8632e8f
--- /dev/null
+++ b/.env.development
@@ -0,0 +1,22 @@
+# .env.development
+############################
+# set this .env.development file as secret.DEV_ENV_FILE
+# gh secrets set <your-repo> DEV_ENV_FILE < .env.development
+
+# --- Core Configuration ---
+COMPOSE_PROJECT_NAME=whoknows # docker-compose and docker containers use
+NODE_ENV=development
+HOST_PORT_FRONTEND=8080     # <------------ main PORT   
+
+# --- Backend Configuration ---
+BACKEND_INTERNAL_PORT=92
+RUST_LOG=debug  # Verbose logging for development
+DATABASE_URL=sqlite:/app/data/whoknows.db
+
+# --- Frontend Configuration ---
+FRONTEND_INTERNAL_PORT=91
+
+# --- Deployment Variables ---
+# These are set by the CI/CD pipeline, but included as fallbacks
+IMAGE_TAG_BACKEND=ghcr.io/debugger-demons/whoknows/backend:latest
+IMAGE_TAG_FRONTEND=ghcr.io/debugger-demons/whoknows/frontend:latest
\ No newline at end of file
diff --git a/.env.production b/.env.production
new file mode 100644
index 00000000..959f4fad
--- /dev/null
+++ b/.env.production
@@ -0,0 +1,21 @@
+# .env.production
+############################
+
+# --- Core Configuration ---
+COMPOSE_PROJECT_NAME=whoknows
+NODE_ENV=production 
+
+HOST_PORT_FRONTEND=8080     # <------------ main PORT   
+
+# --- Frontend Configuration ---
+FRONTEND_INTERNAL_PORT=91 # internal ports
+# --- Backend Configuration ---
+BACKEND_INTERNAL_PORT=92  # internal ports
+RUST_LOG=warn  # less verbose
+DATABASE_URL=sqlite:/app/data/whoknows.db
+
+
+# --- Deployment Variables ---
+# - set by the CI/CD pipeline -- included as fallbacks
+IMAGE_TAG_BACKEND=ghcr.io/debugger-demons/whoknows/backend:latest
+IMAGE_TAG_FRONTEND=ghcr.io/debugger-demons/whoknows/frontend:latest
diff --git a/.github/ISSUE_TEMPLATE/rust_devving.yml b/.github/ISSUE_TEMPLATE/rust_devving.yml
index 0f145ee9..6c49e37f 100644
--- a/.github/ISSUE_TEMPLATE/rust_devving.yml
+++ b/.github/ISSUE_TEMPLATE/rust_devving.yml
@@ -1,5 +1,5 @@
 # Development Task Template
-# .github/ISSUE_TEMPLATE/development.yml
+# .github/ISSUE_TEMPLATE/rust_devving.yml
 name: Development Task
 description: Create a new development task for the WhoKnows project
 title: "[DEV]: "
@@ -9,7 +9,7 @@ body:
     attributes:
       value: |
         Thanks for creating a development issue! Please fill out the information below.
-  
+
   - type: textarea
     id: overview
     attributes:
@@ -26,9 +26,9 @@ body:
       description: Current state, target state, and dependencies
       value: |
         **Current State:**
-        
+
         **Target State:**
-        
+
         **Dependencies:**
     validations:
       required: true
@@ -51,8 +51,7 @@ body:
       description: Related documentation, reference implementations, or architecture diagrams
       value: |
         **Related Documentation:**
-        
+
         **Reference Implementations:**
-        
-        **Architecture Diagrams:**
 
+        **Architecture Diagrams:**
diff --git a/.github/workflows/cd.branch-test.yml b/.github/workflows/cd.branch-test.yml
index be4d9c38..7f53987a 100644
--- a/.github/workflows/cd.branch-test.yml
+++ b/.github/workflows/cd.branch-test.yml
@@ -1,32 +1,31 @@
-# cd.dev.yml
-name: test branch - Continuous Deployment
+# cd.branch-test.yml
+name: branch-test - Continuous Deployment
 
 on:
   push:
-    branches: [test] # <-- adjust for current branch to test
-  workflow_dispatch: # manual trigger
+    branches: [feat/validate-env_and_secrets-workflow] # <-- adjust for current branch to test
+  workflow_dispatch:
 
 env:
   # ---------------------------------------------
   # ------------ Environment Variables ----------
   #
-  # utilizing   .env.development  for env var for Testing Branch deployments
   GHCR_REGISTRY: ghcr.io
   IMAGE_BASENAME: ${{ github.repository_owner }}/${{ github.event.repository.name }}
   # Secrets:
   GHCR_PAT_OR_TOKEN: ${{ secrets.DEV_GHCR_PAT_OR_TOKEN }}
-  SERVER_USER: ${{ secrets.DEV_SERVER_USER }}
-  SERVER_HOST: ${{ secrets.DEV_SERVER_HOST }}
-  SERVER_PORT: ${{ secrets.DEV_SERVER_PORT }}
+  SERVER_USER: ${{ secrets.DEV_SERVER_USER }} # deployer
+  SERVER_HOST: ${{ secrets.DEV_SERVER_HOST }} # IP or domain
+  SERVER_PORT: ${{ secrets.DEV_SERVER_PORT }} # 22 ssh port, 10222
   # SSH:
-  SSH_PRIVATE_KEY: ${{ secrets.DEV_SSH_PRIVATE_KEY }}
-  ENV_FILE_CONTENT: ${{ secrets.DEV_ENV_FILE }}
+  SSH_PRIVATE_KEY: ${{ secrets.DEV_SSH_PRIVATE_KEY }} # private key for SSH access
+  ENV_FILE_CONTENT: ${{ secrets.DEV_ENV_FILE }} # .env file loaded content
   # Commands:
   SSH_CMD: ssh -i ~/.ssh/id_rsa -p ${{ secrets.DEV_SERVER_PORT }} -o StrictHostKeyChecking=no ${{ secrets.DEV_SERVER_USER }}@${{ secrets.DEV_SERVER_HOST }}
   SCP_CMD: scp -i ~/.ssh/id_rsa -P ${{ secrets.DEV_SERVER_PORT }} -o StrictHostKeyChecking=no
-  # Paths:
+  # paths:
   ENV_FILE: .env.development # production or development
-  DEPLOY_DIR: ./deployment/whoknows # <-- env var for deployment dir
+  DEPLOY_DIR: ./deployment/whoknows
   FRONTEND_PATH: ./frontend
   NGINX_FILE_PATH: ./frontend/nginx.conf
   BACKEND_PATH: ./backend
@@ -35,6 +34,16 @@ env:
   DOCKER_LOGIN_SCRIPT: ./deployment/scripts/docker-login.sh
 
 jobs:
+  validate-config:
+    uses: ./.github/workflows/validate.env_and_secrets.yml
+    secrets:
+      PROD_ENV_FILE: ${{ secrets.PROD_ENV_FILE }}
+      DEV_ENV_FILE: ${{ secrets.DEV_ENV_FILE }}
+      PROD_SSH_PRIVATE_KEY: ${{ secrets.PROD_SSH_PRIVATE_KEY }}
+      DEV_SSH_PRIVATE_KEY: ${{ secrets.DEV_SSH_PRIVATE_KEY }}
+      PROD_GHCR_PAT_OR_TOKEN: ${{ secrets.PROD_GHCR_PAT_OR_TOKEN }}
+      DEV_GHCR_PAT_OR_TOKEN: ${{ secrets.DEV_GHCR_PAT_OR_TOKEN }}
+
   #
   # ---------------------------------------------
   # ----------------- build-push ----------------
@@ -43,11 +52,11 @@ jobs:
     name: Build & Push Docker Images
     runs-on: ubuntu-latest
     permissions:
-      contents: read
-      packages: write
+      contents: read # permission to read the repository contents
+      packages: write # permission to write to the GitHub Container Registry (GHCR)
     outputs:
-      backend_image_sha: ${{ env.GHCR_REGISTRY }}/${{ steps.lowercaser.outputs.image_base }}/backend:${{ steps.image_tags.outputs.tag_sha }}
-      frontend_image_sha: ${{ env.GHCR_REGISTRY }}/${{ steps.lowercaser.outputs.image_base }}/frontend:${{ steps.image_tags.outputs.tag_sha }}
+      backend_image_sha: ${{ env.GHCR_REGISTRY }}/${{ steps.lowercaser.outputs.image_base }}/backend:${{ steps.image_tags.outputs.tag_sha }} # backend container image sha tag
+      frontend_image_sha: ${{ env.GHCR_REGISTRY }}/${{ steps.lowercaser.outputs.image_base }}/frontend:${{ steps.image_tags.outputs.tag_sha }} # frontend container image sha tag
 
     steps:
       - name: Checkout Repository
@@ -83,7 +92,7 @@ jobs:
         with:
           context: ${{ env.BACKEND_PATH }}
           file: ${{ env.BACKEND_PATH }}/Dockerfile
-          push: true
+          push: true # push true to push the image to the registry
           tags: |
             ${{ env.GHCR_REGISTRY }}/${{ steps.lowercaser.outputs.image_base }}/backend:${{ steps.image_tags.outputs.tag_latest }}
             ${{ env.GHCR_REGISTRY }}/${{ steps.lowercaser.outputs.image_base }}/backend:${{ steps.image_tags.outputs.tag_sha }}
@@ -138,9 +147,24 @@ jobs:
 
         # ------------------------------------------
 
+      # create/update VERSION file
+      - name: updating VERSION file
+        run: |
+          SERVER_DEST_BASE="${{ env.SERVER_USER }}@${{ env.SERVER_HOST }}:${{ env.DEPLOY_DIR }}"
+
+          echo "DEPLOYMENT_TIME=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" > VERSION
+          echo "GIT_COMMIT=${{ github.sha }}" >> VERSION
+          echo "GIT_BRANCH=${GITHUB_REF#refs/heads/}" >> VERSION
+          echo "IMAGE_TAG_BACKEND=${{ needs.build-push.outputs.backend_image_sha }}" >> VERSION
+          echo "IMAGE_TAG_FRONTEND=${{ needs.build-push.outputs.frontend_image_sha }}" >> VERSION
+
+          # Transfer to server
+          ${{ env.SCP_CMD }} VERSION ${SERVER_DEST_BASE}/VERSION
+
+        # ------------------------------------------
+
       - name: Transfer files to server
         run: |
-          # SERVER_DEST_BASE
           SERVER_DEST_BASE="${{ env.SERVER_USER }}@${{ env.SERVER_HOST }}:${{ env.DEPLOY_DIR }}"
 
           # mkdir
@@ -157,6 +181,7 @@ jobs:
                 # ~/deployment/whoknows/
                   # ├── docker-compose.yml
                   # ├── .env
+                  # ├── VERSION
                   # ├── deploy.sh
                   # ├── docker-login.sh
                   # └── nginx.conf
diff --git a/.github/workflows/cd.dev.yml b/.github/workflows/cd.dev.yml
index 35e2fcdc..c922a692 100644
--- a/.github/workflows/cd.dev.yml
+++ b/.github/workflows/cd.dev.yml
@@ -34,6 +34,9 @@ env:
   DOCKER_LOGIN_SCRIPT: ./deployment/scripts/docker-login.sh
 
 jobs:
+  validate-config:
+    uses: ./.github/workflows/validate.env_and_secrets.yml
+
   #
   # ---------------------------------------------
   # ----------------- build-push ----------------
diff --git a/.github/workflows/cd.prod.yml b/.github/workflows/cd.prod.yml
index ca9e09c9..5bd8a24f 100644
--- a/.github/workflows/cd.prod.yml
+++ b/.github/workflows/cd.prod.yml
@@ -31,6 +31,9 @@ env:
   DOCKER_LOGIN_SCRIPT: ./deployment/scripts/docker-login.sh
 
 jobs:
+  validate-config:
+    uses: ./.github/workflows/validate.env_and_secrets.yml
+
   build-push:
     name: Build & Push Docker Images
     if: github.event.pull_request.merged == true
diff --git a/.github/workflows/secrets.md b/.github/workflows/secrets.md
deleted file mode 100644
index 83e94ac4..00000000
--- a/.github/workflows/secrets.md
+++ /dev/null
@@ -1,16 +0,0 @@
-# Github Secrets utilized
-
-- SERVER_HOST
-- SERVER_PORT
-- SERVER_USERNAME
-- SERVER_SSH_KEY
-
-GitHub Container Registry
-
-- CR_PAT
-
-## safety of secrets
-
-- User in server is heavily restricted and has no sudo access
-
-- Docker Hub token is only used to pull images and is not exposed to the server
diff --git a/.github/workflows/test-secret.yml b/.github/workflows/test-secret.yml
deleted file mode 100644
index bdaf5787..00000000
--- a/.github/workflows/test-secret.yml
+++ /dev/null
@@ -1,15 +0,0 @@
-name: Test Secret
-
-on:
-  workflow_dispatch:
-
-jobs:
-  test-secret:
-    runs-on: ubuntu-latest
-    steps:
-      - name: Echo Secret (partially masked)
-        run: |
-          echo "Secret value (will be masked): ${{ secrets.PROD_ENV_FILE }}"
-          # Output to a file and view part of it
-          echo "${{ secrets.PROD_ENV_FILE }}" > secret.txt
-          head -3 secret.txt
diff --git a/.github/workflows/validate.env_and_secrets.yml b/.github/workflows/validate.env_and_secrets.yml
new file mode 100644
index 00000000..4b1978d5
--- /dev/null
+++ b/.github/workflows/validate.env_and_secrets.yml
@@ -0,0 +1,102 @@
+name: Validate Environment Secrets
+
+on:
+  workflow_dispatch: # Manual trigger for testing
+  pull_request: # Automatically run on PRs
+    branches: [development, main]
+  workflow_call:
+    secrets:
+      PROD_ENV_FILE:
+        required: true
+
+      DEV_ENV_FILE:
+        required: true
+
+      PROD_SSH_PRIVATE_KEY:
+        required: true
+
+      DEV_SSH_PRIVATE_KEY:
+        required: true
+
+      PROD_GHCR_PAT_OR_TOKEN:
+        required: true
+
+      DEV_GHCR_PAT_OR_TOKEN:
+        required: true
+
+jobs:
+  validate-prod-secrets:
+    runs-on: ubuntu-latest
+    steps:
+      - name: Check PROD environment secrets
+        run: |
+          echo "${{ secrets.PROD_ENV_FILE }}" > .env.prod
+          # Verify essential keys exist
+          grep -q "COMPOSE_PROJECT_NAME" .env.prod && echo "✓ COMPOSE_PROJECT_NAME exists" || { echo "✗ Missing COMPOSE_PROJECT_NAME"; exit 1; }
+          grep -q "HOST_PORT_FRONTEND" .env.prod && echo "✓ HOST_PORT_FRONTEND exists" || { echo "✗ Missing HOST_PORT_FRONTEND"; exit 1; }
+          grep -q "BACKEND_INTERNAL_PORT" .env.prod && echo "✓ BACKEND_INTERNAL_PORT exists" || { echo "✗ Missing BACKEND_INTERNAL_PORT"; exit 1; }
+          # Count config lines for sanity check
+          CONFIG_LINES=$(grep -v '^#' .env.prod | grep -v '^$' | wc -l)
+          echo "Total config lines: $CONFIG_LINES"
+          if [ "$CONFIG_LINES" -lt 5 ]; then
+            echo "⚠️ Warning: Fewer than expected config lines!"
+            exit 1
+          fi
+          # Test Docker image references
+          grep -q "IMAGE_TAG_BACKEND" .env.prod && echo "✓ IMAGE_TAG_BACKEND exists" || { echo "⚠️ Missing IMAGE_TAG_BACKEND (may be set by CD)"; }
+          # Clean up
+          rm .env.prod
+          echo "✅ PROD environment file validated successfully"
+
+  validate-dev-secrets:
+    runs-on: ubuntu-latest
+    steps:
+      - name: Check DEV environment secrets
+        run: |
+          # Similar validation for DEV environment
+          echo "${{ secrets.DEV_ENV_FILE }}" > .env.dev
+          # Test Docker image references
+          grep -q "IMAGE_TAG_BACKEND" .env.dev && echo "✓ IMAGE_TAG_BACKEND exists" || { echo "⚠️ Missing IMAGE_TAG_BACKEND (may be set by CD)"; }
+          # Clean up
+          rm .env.dev
+          echo "✅ DEV environment file validated successfully"
+
+  validate-ssh-keys:
+    runs-on: ubuntu-latest
+    steps:
+      - name: Verify SSH keys format
+        run: |
+          # Check PROD SSH key
+          echo "${{ secrets.PROD_SSH_PRIVATE_KEY }}" > ssh_key_prod
+          if ! grep -q "BEGIN .* PRIVATE KEY" ssh_key_prod; then
+            echo "✗ Invalid PROD SSH key format!"
+            exit 1
+          fi
+          echo "✓ PROD SSH key format valid"
+
+          # Check DEV SSH key
+          echo "${{ secrets.DEV_SSH_PRIVATE_KEY }}" > ssh_key_dev
+          if ! grep -q "BEGIN .* PRIVATE KEY" ssh_key_dev; then
+            echo "✗ Invalid DEV SSH key format!"
+            exit 1
+          fi
+          echo "✓ DEV SSH key format valid"
+
+          # Clean up
+          rm ssh_key_*
+
+  validate-docker-credentials:
+    runs-on: ubuntu-latest
+    steps:
+      - name: Check GitHub Container Registry credentials
+        run: |
+          # Test if GHCR PAT works (without actually logging in)
+          if [[ -z "${{ secrets.PROD_GHCR_PAT_OR_TOKEN }}" ]]; then
+            echo "✗ PROD_GHCR_PAT_OR_TOKEN is empty!"
+            exit 1
+          fi
+          if [[ -z "${{ secrets.DEV_GHCR_PAT_OR_TOKEN }}" ]]; then
+            echo "✗ DEV_GHCR_PAT_OR_TOKEN is empty!"
+            exit 1
+          fi
+          echo "✓ GHCR tokens exist (not validating actual auth)"
diff --git a/.github/workflows/verify-secret-hash.yml b/.github/workflows/verify-secret-hash.yml
new file mode 100644
index 00000000..1e6979dc
--- /dev/null
+++ b/.github/workflows/verify-secret-hash.yml
@@ -0,0 +1,11 @@
+name: Verify Secret Hash
+on:
+  workflow_dispatch:
+jobs:
+  verify:
+    runs-on: ubuntu-latest
+    steps:
+      - name: Calculate hash
+        run: |
+          echo "${{ secrets.DEV_ENV_FILE }}" | sha256sum | cut -d' ' -f1 > secret_hash.txt
+          echo "Secret hash: $(cat secret_hash.txt)"
diff --git a/.gitignore b/.gitignore
index 6c2b3324..1d8b17df 100644
--- a/.gitignore
+++ b/.gitignore
@@ -26,15 +26,6 @@ frontend/.env
 
 # ai prompt
 ai-prompt-content/
-ai-prompt-content/*
-#
-ai-prompt-content/.env.production.txt
-ai-prompt-content/cd.prod.yml.txt
-ai-prompt-content/deploy.sh.txt
-ai-prompt-content/docker-compose.prod.yml.txt
-ai-prompt-content/setup_gh_secrets.sh.txt
-
-
 
 # Rust build artifacts
 backend/target/
@@ -356,3 +347,6 @@ dmypy.json
 
 # Cython debug symbols
 cython_debug/
+#
+secret.txt
+ai-prompt-content/
\ No newline at end of file
diff --git a/deployment/scripts/deploy.sh b/deployment/scripts/deploy.sh
index 9dadc9b9..c520a67a 100644
--- a/deployment/scripts/deploy.sh
+++ b/deployment/scripts/deploy.sh
@@ -1,129 +1,251 @@
 #!/bin/bash
 # Path: deployment/scripts/deploy.sh
+# Description: Deploys the application using Docker Compose, performs health checks,
+#              handles rollbacks, and cleans up old Docker images.
+
+# --- Script Setup and Safety --- ##
+# ------------------------------- ##
+# Exit immediately if a command exits with non-zero status
+# Exit on references to unset variables
+# Ensure pipelines fail if any command fails (important for CI)
+set -e -u -o pipefail
+
+# === Configuration === ##
+# --------------------- ##
+HEALTH_CHECK_MAX_RETRIES=30       # How many times to check health
+HEALTH_CHECK_RETRY_INTERVAL=3     # Seconds to wait between health checks
+ROLLBACK_STABILITY_WAIT=5         # Seconds to wait after rollback before checking health
+
+# === Function Definitions === ##
+# ---------------------------- ##
+
+# --- Function: log_message --- ##
+# Utility for consistent timestamped logging
+log_message() {
+  echo "[$(date)] $1"
+}
 
-set -e  # Exit immediately if a command exits with non-zero status
-source .env  # Load environment variables from .env file
+# --- Function: load_env_vars --- ##
+# Loads required environment variables from the .env file.
+load_env_vars() {
+  log_message "Loading environment variables from .env file..."
+  if [ ! -f .env ]; then
+      log_message "FATAL: .env file not found!"
+      exit 1
+  fi
+  # Use set -a/+a to export variables temporarily, primarily for visibility
+  # Using --env-file in docker compose commands is the preferred way.
+  set -a
+  # shellcheck disable=SC1091 # Source file is expected to exist via check above
+  source .env
+  set +a
+  log_message "Environment variables loaded."
+  # Verify essential variables loaded (optional but recommended)
+  : "${COMPOSE_PROJECT_NAME:?FATAL: COMPOSE_PROJECT_NAME not set in .env}"
+  : "${IMAGE_TAG_BACKEND:?FATAL: IMAGE_TAG_BACKEND not set in .env}"
+  : "${IMAGE_TAG_FRONTEND:?FATAL: IMAGE_TAG_FRONTEND not set in .env}"
+  : "${HOST_PORT_FRONTEND:?FATAL: HOST_PORT_FRONTEND not set in .env}"
+}
 
-# Log deployment start with timestamp
-echo "[$(date)] Deployment started"
+# --- Function: prepare_rollback --- ##
+# Identifies currently running images for this project and saves them to .env.rollback.
+prepare_rollback() {
+  log_message "Preparing for potential rollback by identifying current running images..."
+  local backend_container_name="${COMPOSE_PROJECT_NAME}_backend_dev"
+  local frontend_container_name="${COMPOSE_PROJECT_NAME}_frontend_dev"
+  local current_backend_image=""
+  local current_frontend_image=""
+
+  current_backend_image=$(docker inspect --format='{{.Config.Image}}' "${backend_container_name}" 2>/dev/null || echo "")
+  current_frontend_image=$(docker inspect --format='{{.Config.Image}}' "${frontend_container_name}" 2>/dev/null || echo "")
+
+  # Create or clear the rollback file
+  rm -f .env.rollback
+
+  if [[ -n "$current_backend_image" ]]; then
+    echo "IMAGE_TAG_BACKEND=${current_backend_image}" > .env.rollback
+    log_message "  - Saving current backend image for rollback: ${current_backend_image}"
+  else
+    log_message "  - No running backend container found for project ${COMPOSE_PROJECT_NAME}. Will not include in rollback."
+  fi
 
-# Store previous image tags for potential rollback
-if [ -f .env.previous ]; then
-  cp .env.previous .env.rollback
-fi
+  if [[ -n "$current_frontend_image" ]]; then
+    echo "IMAGE_TAG_FRONTEND=${current_frontend_image}" >> .env.rollback
+    log_message "  - Saving current frontend image for rollback: ${current_frontend_image}"
+  else
+     log_message "  - No running frontend container found for project ${COMPOSE_PROJECT_NAME}. Will not include in rollback."
+  fi
 
-# Save current environment variables for potential rollbacks
+  if [ ! -f .env.rollback ]; then
+     log_message "  - Warning: No running containers found for this project. Rollback will not be possible."
+  fi
+}
 
-set | grep "^IMAGE_TAG_" > .env.previous || true
+# --- Function: pull_new_images --- ##
+# Pulls the application images specified in the .env file.
+pull_new_images() {
+  log_message "Pulling new application images (Backend: ${IMAGE_TAG_BACKEND}, Frontend: ${IMAGE_TAG_FRONTEND})..."
+  if ! docker compose --env-file .env pull; then
+    log_message "FATAL: Failed to pull new Docker images."
+    exit 1
+  fi
+  log_message "Image pulling completed."
+}
 
-# ---------------- pull images ---------------- ##
+# --- Function: deploy_new_containers --- ##
+# Stops old containers and starts new ones using docker-compose up.
+deploy_new_containers() {
+  log_message "Stopping old containers (if any) and starting new containers..."
+  # Options explained:
+  #   --env-file .env     : Explicitly load variables from .env.
+  #   up -d               : Create/start containers detached.
+  #   --force-recreate    : Ensure containers restart even if only image changed.
+  #   --remove-orphans    : Clean up containers for removed services.
+  if ! docker compose --env-file .env up -d --force-recreate --remove-orphans; then
+    log_message "FATAL: Failed to bring up new containers with docker-compose."
+    exit 1
+  fi
+  log_message "docker-compose up completed successfully."
+}
 
-# Pull the specific tagged images defined by the env vars
-echo "[$(date)] Pulling images: $IMAGE_TAG_BACKEND and $IMAGE_TAG_FRONTEND"
-docker compose pull || { echo "Failed to pull images"; exit 1; }
+# --- Function: perform_health_check --- ##
+# Checks the application's health endpoint multiple times.
+# Returns 0 on success, 1 on failure.
+perform_health_check() {
+  local health_endpoint="http://localhost:${HOST_PORT_FRONTEND}/api/health"
+  log_message "Waiting for application health check at ${health_endpoint}..."
+
+  local i
+  for i in $(seq 1 $HEALTH_CHECK_MAX_RETRIES); do
+    local curl_exit_code=0
+    # Use curl options: -s silent, -f fail fast, -L follow redirects, -o discard output
+    if curl -s -f -L -o /dev/null "${health_endpoint}"; then
+      log_message "Health check PASSED!"
+      return 0 # Success
+    else
+      curl_exit_code=$?
+      log_message "Health check attempt $i/$HEALTH_CHECK_MAX_RETRIES FAILED (curl exit code: ${curl_exit_code}). Retrying in ${HEALTH_CHECK_RETRY_INTERVAL}s..."
+      sleep "$HEALTH_CHECK_RETRY_INTERVAL"
+    fi
+  done
 
-# Stop (if running), remove old containers, and start new ones
-echo "[$(date)] Starting containers"
-docker compose -f docker-compose.yml --env-file .env up -d --remove-orphans
+  log_message "FATAL: Application health check failed after $HEALTH_CHECK_MAX_RETRIES attempts."
+  return 1 # Failure
+}
 
-# ------------- image tags ------------- ##
+# --- Function: handle_rollback --- ##
+# Attempts to roll back to the previously saved state if .env.rollback exists.
+# Exits script with error code 1 if rollback is triggered.
+handle_rollback() {
+  log_message "Handling failed health check..."
+  if [ ! -f .env.rollback ]; then
+    log_message "FATAL: Health check failed, and no previous deployment state found in .env.rollback. Cannot roll back automatically."
+    exit 1
+  fi
 
-# backup to .env.bak
-if [ -f .env ]; then
-  cp .env .env.bak
-fi
+  log_message "Initiating rollback to previously saved container images..."
+  log_message "Rolling back using images defined in .env.rollback..."
+  # Use compose to bring up the previous version, applying the rollback env file
+  # Use set -a/+a here to make sure vars are available if compose file references them directly (though --env-file is better)
+  set -a
+  # shellcheck disable=SC1091 # File existence checked above
+  source .env.rollback
+  set +a
+  if ! docker compose --env-file .env.rollback up -d --force-recreate --remove-orphans; then
+      log_message "FATAL: Rollback command (docker-compose up) itself failed! Manual intervention likely required."
+      exit 1
+  fi
 
-# add new image tags to .env
-if [ -f image_tags.env ]; then
-  # Remove existing image tags
-  grep -v '^IMAGE_TAG_' .env > .env.new
-  # Add new image tags
-  cat image_tags.env >> .env.new
-  # Replace .env atomically
-  mv .env.new .env
-  rm image_tags.env
-fi
+  # Optional: Brief health check for the rollback itself
+  log_message "Waiting ${ROLLBACK_STABILITY_WAIT}s briefly for rollback stability check..."
+  sleep "$ROLLBACK_STABILITY_WAIT"
+  local health_endpoint="http://localhost:${HOST_PORT_FRONTEND}/api/health" # Re-evaluate endpoint based on potentially different rollback port? Assume same for now.
+  if curl -s -f -L -o /dev/null "${health_endpoint}"; then
+      log_message "Rollback appears successful. System is running previous version."
+  else
+      log_message "WARNING: Rollback command executed, but health check on rolled-back version failed. Manual inspection needed."
+  fi
 
+  # Exit with a non-zero code to signal deployment failure to the CI/CD system
+  log_message "Exiting script with error code 1 due to failed deployment requiring rollback."
+  exit 1
+}
 
-# ------------- health check ------------- ##
-
-# Wait for backend to become healthy
-echo "[$(date)] Waiting for backend health check..."
-MAX_RETRIES=30
-RETRY_INTERVAL=2
-HEALTH_ENDPOINT="http://localhost:${HOST_PORT_FRONTEND}/api/health" 
-
-cleanupRollback() {
-  # Rename rollback file
-  mv .env.rollback .env.previous 2>/dev/null || echo "No rollback file to rename"
-  mv .env .env.failed 2>/dev/null || echo "No current env file to rename"
-  
-  # Remove files, don't error if they don't exist
-  rm -f .env.previous 2>/dev/null
-  rm -f .env 2>/dev/null
-  
-  echo "[$(date)] Cleanup completed"
+# --- Function: log_success_confirmation --- ##
+# Logs the final running image versions after a successful deployment.
+log_success_confirmation() {
+    log_message "Deployment successful!"
+    local backend_container_name="${COMPOSE_PROJECT_NAME}_backend_dev"
+    local frontend_container_name="${COMPOSE_PROJECT_NAME}_frontend_dev"
+    local final_backend_image=""
+    local final_frontend_image=""
+
+    final_backend_image=$(docker inspect --format='{{.Config.Image}}' "${backend_container_name}" 2>/dev/null || echo "Not running")
+    final_frontend_image=$(docker inspect --format='{{.Config.Image}}' "${frontend_container_name}" 2>/dev/null || echo "Not running")
+
+    log_message "Final running images:"
+    log_message "  - Backend : ${final_backend_image}"
+    log_message "  - Frontend: ${final_frontend_image}"
 }
 
-for i in $(seq 1 $MAX_RETRIES); do
-  if curl -s -f "${HEALTH_ENDPOINT}" > /dev/null; then
-    echo "[$(date)] Backend is healthy!"
-    break
+# --- Function: cleanup_docker_images --- ##
+# Cleans up unused Docker images using the appropriate method based on Docker version.
+cleanup_docker_images() {
+  log_message "Cleaning up unused Docker images..."
+
+  # --- Docker Version Check and Cleanup Strategy ---
+  # Docker version 20.10.x (API 1.41) does NOT reliably support filtering prune by 'reference'.
+  # Therefore, we MUST fall back to the general prune command.
+  log_message "Note: Using 'docker image prune -af' as Docker version does not support 'reference' filter reliably."
+  log_message "This will remove ALL unused images on the system, not just for this application."
+
+  # Prune command options:
+  # -a : Prune ALL unused images (not just dangling/untagged ones).
+  # -f : Force prune without interactive confirmation.
+  # IMPORTANT: This command is SAFE regarding running containers. It will NOT remove
+  #            images used by ANY running container.
+  if ! docker image prune -af; then
+      # Log a warning, but don't fail the deployment just because prune failed
+      log_message "Warning: 'docker image prune -af' command failed. Continuing deployment."
+  else
+      log_message "General image pruning completed."
   fi
-  
-  if [ $i -eq $MAX_RETRIES ]; then
-    echo "[$(date)] Health check failed after $MAX_RETRIES attempts. Rolling back."
-    # Rollback to previous deployment if health check fails
-    if [ -f .env.rollback ]; then
-      echo "[$(date)] Rolling back to previous deployment"
-      set -a  
-      source .env.rollback
-      set +a
-      docker compose --env-file .env.rollback up -d --remove-orphans || { echo "Rollback failed"; exit 1; }
-      
-      # Wait for the rollback to become healthy
-      echo "[$(date)] Waiting for rollback health check..."
-
-      for j in $(seq 1 $MAX_RETRIES); do
-        if curl -s -f "${HEALTH_ENDPOINT}" > /dev/null; then
-          echo "[$(date)] Rollback successful!"
-          cleanupRollback
-          break
-        fi
-        
-        if [ $j -eq $MAX_RETRIES ]; then
-          echo "[$(date)] Rollback health check failed after $MAX_RETRIES attempts. Exiting."
-          exit 1
-        fi
-        
-        echo "[$(date)] Rollback attempt $j/$MAX_RETRIES: Backend not ready yet. Retrying in ${RETRY_INTERVAL}s..."
-        sleep $RETRY_INTERVAL
-      done
-      echo "[$(date)] Rollback complete"
-    else
-      echo "[$(date)] No previous deployment found for rollback"
-    fi
-    exit 1
-  fi
-  
-  echo "Attempt $i/$MAX_RETRIES: Backend not ready yet. Retrying in ${RETRY_INTERVAL}s..."
-  sleep $RETRY_INTERVAL
-done
+}
+
+# === Main Execution === ##
+# ---------------------- ##
+
+log_message "=== Starting Deployment Script ==="
 
-# --------------- logging --------------- ##
+# --- Step 1: Load Environment --- ##
+load_env_vars
 
-# Log version information for auditing
-echo "[$(date)] Deployment successful with:"
-echo "Backend: $IMAGE_TAG_BACKEND"
-echo "Frontend: $IMAGE_TAG_FRONTEND"
+# --- Step 2: Prepare for Rollback --- ##
+prepare_rollback
+
+# --- Step 3: Pull New Code/Images --- ##
+pull_new_images
+
+# --- Step 4: Deploy New Version --- ##
+deploy_new_containers
+
+# --- Step 5: Verify Deployment Health --- ##
+if ! perform_health_check; then
+  # If health check fails, attempt rollback (handle_rollback exits on failure/completion)
+  handle_rollback
+fi
 
-## ----------- clean up ---------- ##
+# --- Step 6: Confirm Success --- ##
+# Only reached if health check passed
+log_success_confirmation
 
-echo "[$(date)] Cleaning up previous application images"
+# --- Step 7: Clean Up --- ##
+cleanup_docker_images
 
-# Remove older images of this application while keeping the currently used ones
-docker images --format "{{.Repository}}:{{.Tag}}" | grep "${IMAGE_TAG_BACKEND%:*}" | grep -v "${IMAGE_TAG_BACKEND##*:}" | xargs -r docker rmi
-docker images --format "{{.Repository}}:{{.Tag}}" | grep "${IMAGE_TAG_FRONTEND%:*}" | grep -v "${IMAGE_TAG_FRONTEND##*:}" | xargs -r docker rmi
+# --- Step 8: Final Touches --- ##
+log_message "Cleaning up temporary rollback file..."
+rm -f .env.rollback
 
-# ------------ success message ------------- ##
-echo "[$(date)] Deployment completed successfully"
\ No newline at end of file
+log_message "=== Deployment Script Completed Successfully ==="
+# Exit with 0 to signal success to the CI/CD system
+exit 0
\ No newline at end of file
diff --git a/docs/.github/deployment__Best_Practices.md b/docs/.github/deployment__Best_Practices.md
new file mode 100644
index 00000000..cf1f17f9
--- /dev/null
+++ b/docs/.github/deployment__Best_Practices.md
@@ -0,0 +1,29 @@
+Best Practice Considerations:
+
+Atomicity: Deployment steps should ideally be atomic or have clean rollback.
+
+Simplicity: Less complex scripts are easier to maintain.
+
+Safety: Never try to remove an image that a container relies on.
+
+Leverage Docker Tools: Use built-in Docker commands like prune where appropriate.
+
+Source of Truth: GHCR is your image source of truth; the server only needs the currently required images and potentially the immediate previous one for rollback.
+
+Key Changes and Structure:
+
+Functions: All major logical blocks are now encapsulated in functions (e.g., load_env_vars, prepare_rollback, pull_new_images, deploy_new_containers, perform_health_check, handle_rollback, log_success_confirmation, cleanup_docker_images).
+
+Main Execution Flow: The bottom section (=== Main Execution ===) clearly shows the sequence of steps by calling these functions.
+
+Error Handling: Functions that perform critical steps (pull_new_images, deploy_new_containers) check the exit status of their core command and call exit 1 if it fails. The perform_health_check function returns 0 or 1, and the main flow checks this using if ! perform_health_check; then handle_rollback; fi. The handle_rollback function itself calls exit 1.
+
+Readability: The main execution flow is now much shorter and reads like a high-level description of the deployment process. Details are hidden within the functions.
+
+Cleanup Fix: The cleanup_docker_images function explicitly uses docker image prune -af and includes comments explaining why the targeted reference filter cannot be used with your Docker version. It also includes basic error checking for the prune command itself, logging a warning instead of failing the whole script if prune fails for some reason.
+
+Logging: A simple log_message function is added for consistent timestamped output.
+
+Configuration: Constants like retry counts are grouped at the top.
+
+Variable Verification: Added checks in load_env_vars to ensure critical variables are actually set in the .env file, causing an early exit if they are missing.
diff --git a/docs/issues/#62-Docker_container_Labelling b/docs/issues/#62-Docker_container_Labelling
new file mode 100644
index 00000000..4324ae80
--- /dev/null
+++ b/docs/issues/#62-Docker_container_Labelling
@@ -0,0 +1,76 @@
+body:
+  - type: markdown
+    attributes:
+      value: |
+        Thanks for creating a development issue! Please fill out the information below.
+
+  - type: textarea
+    id: overview
+    attributes:
+      label: Overview
+      description: Brief description of the development task
+      placeholder: "Example: Migrate user authentication module from Python to Rust"
+      value: |
+        Refactor the deployment process to use Docker image labels for targeted pruning of unused application images on the deployment server. This improves cleanup safety and specificity by avoiding the removal of unrelated images or cached layers belonging to other projects or Docker operations on the server.
+    validations:
+      required: true
+
+  - type: textarea
+    id: technical-context
+    attributes:
+      label: Technical Context
+      description: Current state, target state, and dependencies
+      value: |
+        **Current State:**
+        * The `deployment/scripts/deploy.sh` script is responsible for deploying the application via Docker Compose and cleaning up old Docker images.
+        * An attempt was made to use `docker image prune --filter reference=ghcr.io/debugger-demons/whoknows/*` for targeted cleanup.
+        * This `reference=` filter fails on the target deployment server (`Error response from daemon: invalid filter 'reference'`), likely due to Docker version limitations or subtle incompatibilities, even after a Docker version update was performed.
+        * The current working fallback in `deploy.sh` uses `docker image prune -af`, which prunes *all* unused images on the system, not just those belonging to the 'whoknows' application. This is functional but overly broad and potentially disruptive to other processes or cached layers on the server.
+
+        **Target State:**
+        * Docker images for the 'whoknows' application (both `backend` and `frontend`) are consistently built with a standard `application="whoknows"` label (or another agreed-upon label key/value).
+        * The `deployment/scripts/deploy.sh` script is updated to use `docker image prune -af --filter label=application=whoknows` for the image cleanup step.
+        * This command leverages Docker's label filtering, which is supported on the target server's Docker version.
+        * The deployment process safely and specifically removes only unused images belonging to *this* application, preserving unrelated images and layers.
+
+        **Dependencies:**
+        * Requires modifications to `backend/Dockerfile` and `frontend/Dockerfile` to add the `LABEL` instruction.
+        * Requires modification to the `cleanup_docker_images` function within `deployment/scripts/deploy.sh`.
+        * The CI/CD pipeline (`build-push` job in the GitHub Actions workflow) must successfully build and push images containing the new labels *before* the updated `deploy.sh` script is deployed and executed.
+    validations:
+      required: true
+
+  - type: checkboxes
+    id: acceptance-criteria
+    attributes:
+      label: Acceptance Criteria
+      description: The requirements for this task to be considered complete
+      options:
+        - label: '`backend/Dockerfile` updated with `LABEL application="whoknows"` (or chosen standard).'
+        - label: '`frontend/Dockerfile` updated with `LABEL application="whoknows"` (or chosen standard).'
+        - label: "`deployment/scripts/deploy.sh` updated to use `docker image prune --filter label=application=whoknows` (or chosen standard)."
+        - label: CI/CD pipeline successfully builds and pushes images containing the specified label.
+        - label: Deployment script runs successfully on the target server using the label filter for pruning.
+        - label: Verification on the server confirms that `docker image prune` (as run by the script) only removes unused `whoknows` images and leaves other unrelated images/layers untouched.
+        - label: Documentation (e.g., README section on deployment or Docker image standards) updated if necessary.
+        - label: PR review completed and changes merged.
+
+  - type: textarea
+    id: resources
+    attributes:
+      label: Resources
+      description: Related documentation, reference implementations, or architecture diagrams
+      value: |
+        **Related Documentation:**
+        * Docker Builder `LABEL` instruction: https://docs.docker.com/engine/reference/builder/#label
+        * `docker image prune` command (including `--filter`): https://docs.docker.com/engine/reference/commandline/image_prune/
+        * Open Container Initiative (OCI) standard image labels (good practice): https://github.com/opencontainers/image-spec/blob/main/annotations.md
+
+        **Relevant Files (Current State):**
+        * `deployment/scripts/deploy.sh` (specifically the `cleanup_docker_images` function)
+        * `backend/Dockerfile`
+        * `frontend/Dockerfile`
+        * GitHub Actions workflow responsible for build/push (e.g., `cd.branch-test.yml` or similar)
+
+        **Reference Implementations:**
+        * (Link to any internal examples or best practices if available)
diff --git a/docs/issues/issue_63_body.md b/docs/issues/issue_63_body.md
new file mode 100644
index 00000000..c7203764
--- /dev/null
+++ b/docs/issues/issue_63_body.md
@@ -0,0 +1,51 @@
+### Overview
+
+Refactor the deployment process to use Docker image labels for targeted pruning of unused application images on the deployment server. This improves cleanup safety and specificity by avoiding the removal of unrelated images or cached layers belonging to other projects or Docker operations on the server.
+
+### Technical Context
+
+**Current State:**
+
+- The `deployment/scripts/deploy.sh` script is responsible for deploying the application via Docker Compose and cleaning up old Docker images.
+- An attempt was made to use `docker image prune --filter reference=ghcr.io/debugger-demons/whoknows/*` for targeted cleanup.
+- This `reference=` filter fails on the target deployment server (`Error response from daemon: invalid filter 'reference'`), likely due to Docker version limitations or subtle incompatibilities, even after a Docker version update was performed.
+- The current working fallback in `deploy.sh` uses `docker image prune -af`, which prunes _all_ unused images on the system, not just those belonging to the 'whoknows' application. This is functional but overly broad and potentially disruptive to other processes or cached layers on the server.
+
+**Target State:**
+
+- Docker images for the 'whoknows' application (both `backend` and `frontend`) are consistently built with a standard `application="whoknows"` label (or another agreed-upon label key/value).
+- The `deployment/scripts/deploy.sh` script is updated to use `docker image prune -af --filter label=application=whoknows` for the image cleanup step.
+- This command leverages Docker's label filtering, which is supported on the target server's Docker version.
+- The deployment process safely and specifically removes only unused images belonging to _this_ application, preserving unrelated images and layers.
+
+**Dependencies:**
+
+- Requires modifications to `backend/Dockerfile` and `frontend/Dockerfile` to add the `LABEL` instruction.
+- Requires modification to the `cleanup_docker_images` function within `deployment/scripts/deploy.sh`.
+- The CI/CD pipeline (`build-push` job in the GitHub Actions workflow) must successfully build and push images containing the new labels _before_ the updated `deploy.sh` script is deployed and executed.
+
+### Acceptance Criteria
+
+- [ ] `backend/Dockerfile` updated with `LABEL application="whoknows"` (or chosen standard).
+- [ ] `frontend/Dockerfile` updated with `LABEL application="whoknows"` (or chosen standard).
+- [ ] `deployment/scripts/deploy.sh` updated to use `docker image prune --filter label=application=whoknows` (or chosen standard).
+- [ ] CI/CD pipeline successfully builds and pushes images containing the specified label.
+- [ ] Deployment script runs successfully on the target server using the label filter for pruning.
+- [ ] Verification on the server confirms that `docker image prune` (as run by the script) only removes unused `whoknows` images and leaves other unrelated images/layers untouched.
+- [ ] Documentation (e.g., README section on deployment or Docker image standards) updated if necessary.
+- [ ] PR review completed and changes merged.
+
+### Resources
+
+**Related Documentation:**
+
+- Docker Builder `LABEL` instruction: https://docs.docker.com/engine/reference/builder/#label
+- `docker image prune` command (including `--filter`): https://docs.docker.com/engine/reference/commandline/image_prune/
+- Open Container Initiative (OCI) standard image labels (good practice): https://github.com/opencontainers/image-spec/blob/main/annotations.md
+
+**Relevant Files (Current State):**
+
+- `deployment/scripts/deploy.sh` (specifically the `cleanup_docker_images` function)
+- `backend/Dockerfile`
+- `frontend/Dockerfile`
+- GitHub Actions workflow responsible for build/push (e.g., `cd.branch-test.yml` or similar)


Reviews:
user: login: copilot-pull-request-reviewer[bot]
body: ## Pull Request Overview

This PR introduces a set of workflows to validate environment secrets and configuration before deployment, ensuring that required variables and credentials are correctly set.  
- Added a new workflow (validate.env_and_secrets.yml) to verify both production and development environment files, SSH key formats, and GHCR tokens.  
- Integrated the validation workflow into production, development, and branch-testing deployment workflows.  
- Added a secret hash verification workflow to print the SHA-256 hash of DEV_ENV_FILE.

### Reviewed Changes

Copilot reviewed 7 out of 8 changed files in this pull request and generated 2 comments.

<details>
<summary>Show a summary per file</summary>

| File                                             | Description                                                                           |
| ------------------------------------------------ | ------------------------------------------------------------------------------------- |
| .github/workflows/verify-secret-hash.yml         | Introduces a job to compute and log a hash of the DEV environment file.                |
| .github/workflows/validate.env_and_secrets.yml     | Provides validation of PROD and DEV environment secrets, SSH keys, and GHCR credentials.|
| .github/workflows/cd.prod.yml                      | Integrates secret/config validation and updates the deployment condition in production. |
| .github/workflows/cd.dev.yml                      | Integrates secret/config validation into the development deployment workflow.          |
| .github/workflows/cd.branch-test.yml               | Adjusts branch testing workflow to include validation and updates job conditions.       |
</details>


<details>
<summary>Files not reviewed (1)</summary>

* **.github/workflows/test-secret.yml**: Language not supported
</details>

<details>
<summary>Comments suppressed due to low confidence (1)</summary>

**.github/workflows/cd.prod.yml:119**
* The deployment condition is checking 'github.event.pull_request.merged', which may be undefined in push-triggered workflows. Consider adjusting the condition to reflect the correct workflow trigger.
```
if: github.event.pull_request.merged == true
```
</details>


state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-02T13:30:40Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 1**

<details>
<summary>🧹 Nitpick comments (3)</summary><blockquote>

<details>
<summary>.github/workflows/verify-secret-hash.yml (1)</summary><blockquote>

`1-12`: **New Workflow for Secret Hash Verification**  
This workflow calculates and prints the SHA-256 hash of the `DEV_ENV_FILE` secret. While printing a hash (which is non-reversible) is typically acceptable, consider whether echoing it to logs might inadvertently expose sensitive metadata. If necessary, explore GitHub Actions’ secret masking features or limit log visibility.

</blockquote></details>
<details>
<summary>.github/workflows/validate.env_and_secrets.yml (2)</summary><blockquote>

`62-85`: **SSH Key Format Validation is Clear and Effective**  
The `validate-ssh-keys` job creates temporary files for both production and development SSH keys and uses a simple regex (`"BEGIN .* PRIVATE KEY"`) to verify their format. This is an effective initial check.  
A minor nitpick: consider a slightly more precise regex for matching (if necessary) and note that cleanup is handled by removing files via `rm ssh_key_*`, which is acceptable given the ephemeral runner environment.

---

`86-100`: **Docker Credentials Check is Straightforward**  
The job for checking GitHub Container Registry credentials verifies that both `PROD_GHCR_PAT_OR_TOKEN` and `DEV_GHCR_PAT_OR_TOKEN` are non-empty. While this basic validation is acceptable for now, if future use cases demand deeper validation (such as token format checks), consider extending this logic.

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 1b7cf6d10fcb245bba7a6f81e67e216454500754 and b09005060db5ce701938e4634cbb2b49e5fa52a0.

</details>

<details>
<summary>📒 Files selected for processing (8)</summary>

* `.env.development` (1 hunks)
* `.github/workflows/cd.branch-test.yml` (7 hunks)
* `.github/workflows/cd.dev.yml` (1 hunks)
* `.github/workflows/cd.prod.yml` (1 hunks)
* `.github/workflows/test-secret.yml` (0 hunks)
* `.github/workflows/validate.env_and_secrets.yml` (1 hunks)
* `.github/workflows/verify-secret-hash.yml` (1 hunks)
* `.gitignore` (1 hunks)

</details>

<details>
<summary>💤 Files with no reviewable changes (1)</summary>

* .github/workflows/test-secret.yml

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🪛 actionlint (1.7.4)</summary>

<details>
<summary>.github/workflows/cd.prod.yml</summary>

35-35: secret "DEV_SSH_PRIVATE_KEY" is required by "./.github/workflows/validate.env_and_secrets.yml" reusable workflow

(workflow-call)

---

35-35: secret "PROD_GHCR_PAT_OR_TOKEN" is required by "./.github/workflows/validate.env_and_secrets.yml" reusable workflow

(workflow-call)

---

35-35: secret "DEV_GHCR_PAT_OR_TOKEN" is required by "./.github/workflows/validate.env_and_secrets.yml" reusable workflow

(workflow-call)

---

35-35: secret "PROD_ENV_FILE" is required by "./.github/workflows/validate.env_and_secrets.yml" reusable workflow

(workflow-call)

---

35-35: secret "DEV_ENV_FILE" is required by "./.github/workflows/validate.env_and_secrets.yml" reusable workflow

(workflow-call)

---

35-35: secret "PROD_SSH_PRIVATE_KEY" is required by "./.github/workflows/validate.env_and_secrets.yml" reusable workflow

(workflow-call)

</details>
<details>
<summary>.github/workflows/cd.dev.yml</summary>

38-38: secret "DEV_ENV_FILE" is required by "./.github/workflows/validate.env_and_secrets.yml" reusable workflow

(workflow-call)

---

38-38: secret "PROD_SSH_PRIVATE_KEY" is required by "./.github/workflows/validate.env_and_secrets.yml" reusable workflow

(workflow-call)

---

38-38: secret "DEV_SSH_PRIVATE_KEY" is required by "./.github/workflows/validate.env_and_secrets.yml" reusable workflow

(workflow-call)

---

38-38: secret "PROD_GHCR_PAT_OR_TOKEN" is required by "./.github/workflows/validate.env_and_secrets.yml" reusable workflow

(workflow-call)

---

38-38: secret "DEV_GHCR_PAT_OR_TOKEN" is required by "./.github/workflows/validate.env_and_secrets.yml" reusable workflow

(workflow-call)

---

38-38: secret "PROD_ENV_FILE" is required by "./.github/workflows/validate.env_and_secrets.yml" reusable workflow

(workflow-call)

</details>

</details>

</details>

<details>
<summary>🔇 Additional comments (15)</summary><blockquote>

<details>
<summary>.gitignore (1)</summary>

`347-348`: **Ensure Sensitive Files are Ignored**  
The addition of `secret.txt` ensures that any sensitive information stored in this file will not be tracked by Git, which is an important security practice.

</details>
<details>
<summary>.env.development (1)</summary>

`21-22`: **Consistent Environment Configuration**  
The `IMAGE_TAG_FRONTEND` variable maintains the same value; the change is purely in formatting. This is acceptable as it keeps configuration consistent across environments.

</details>
<details>
<summary>.github/workflows/cd.dev.yml (1)</summary>

`36-39`: **Integrate Environment & Secret Validation**  
The new `validate-config` job that reuses `./.github/workflows/validate.env_and_secrets.yml` is a solid enhancement for pre-deployment checks. Please verify that all required secrets (e.g. `DEV_ENV_FILE`, `DEV_SSH_PRIVATE_KEY`, and `DEV_GHCR_PAT_OR_TOKEN`) are correctly set in the repository’s secrets.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 actionlint (1.7.4)</summary>

38-38: secret "DEV_ENV_FILE" is required by "./.github/workflows/validate.env_and_secrets.yml" reusable workflow

(workflow-call)

---

38-38: secret "PROD_SSH_PRIVATE_KEY" is required by "./.github/workflows/validate.env_and_secrets.yml" reusable workflow

(workflow-call)

---

38-38: secret "DEV_SSH_PRIVATE_KEY" is required by "./.github/workflows/validate.env_and_secrets.yml" reusable workflow

(workflow-call)

---

38-38: secret "PROD_GHCR_PAT_OR_TOKEN" is required by "./.github/workflows/validate.env_and_secrets.yml" reusable workflow

(workflow-call)

---

38-38: secret "DEV_GHCR_PAT_OR_TOKEN" is required by "./.github/workflows/validate.env_and_secrets.yml" reusable workflow

(workflow-call)

---

38-38: secret "PROD_ENV_FILE" is required by "./.github/workflows/validate.env_and_secrets.yml" reusable workflow

(workflow-call)

</details>

</details>

</details>
<details>
<summary>.github/workflows/cd.prod.yml (1)</summary>

`33-36`: **Validate Production Secrets Before Deployment**  
The addition of the `validate-config` job in the production workflow follows the pattern established in other environments. As with the development workflow, please confirm that the required secrets (such as `PROD_ENV_FILE`, `PROD_SSH_PRIVATE_KEY`, and `PROD_GHCR_PAT_OR_TOKEN`) are present and correctly configured to ensure a safe deployment process.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 actionlint (1.7.4)</summary>

35-35: secret "DEV_SSH_PRIVATE_KEY" is required by "./.github/workflows/validate.env_and_secrets.yml" reusable workflow

(workflow-call)

---

35-35: secret "PROD_GHCR_PAT_OR_TOKEN" is required by "./.github/workflows/validate.env_and_secrets.yml" reusable workflow

(workflow-call)

---

35-35: secret "DEV_GHCR_PAT_OR_TOKEN" is required by "./.github/workflows/validate.env_and_secrets.yml" reusable workflow

(workflow-call)

---

35-35: secret "PROD_ENV_FILE" is required by "./.github/workflows/validate.env_and_secrets.yml" reusable workflow

(workflow-call)

---

35-35: secret "DEV_ENV_FILE" is required by "./.github/workflows/validate.env_and_secrets.yml" reusable workflow

(workflow-call)

---

35-35: secret "PROD_SSH_PRIVATE_KEY" is required by "./.github/workflows/validate.env_and_secrets.yml" reusable workflow

(workflow-call)

</details>

</details>

</details>
<details>
<summary>.github/workflows/validate.env_and_secrets.yml (3)</summary>

`1-6`: **Workflow Triggers and Secret Declarations Look Good**  
The workflow is configured with a manual trigger (`workflow_dispatch`), PR trigger (on branches `development` and `main`), and a reusable `workflow_call` block. The secrets for production and development are clearly declared and marked as required.

---

`7-26`: **Clear Declaration of Required Secrets**  
All required secrets (environment files, SSH keys, and GHCR tokens) are explicitly listed. This improves transparency and helps ensure the workflow is only triggered when the necessary configurations are provided.

---

`28-50`: **Robust Production Environment Secrets Validation**  
The `validate-prod-secrets` job correctly creates a temporary `.env.prod` file, verifies the presence of critical configuration keys using `grep`, and performs a sanity check on the number of configuration lines. The conditional exit on detecting fewer than five non-comment, non-empty lines is a good safeguard.  
Consider adding additional validations if needed (for example, format checks on key values) in future iterations.

</details>
<details>
<summary>.github/workflows/cd.branch-test.yml (8)</summary>

`2-7`: **Updated Workflow Name and Branch Trigger Reflects Intent**  
The change from "test branch - Continuous Deployment" to "branch-test - Continuous Deployment" and updating the push branch to `[branch/testing-workflows]` makes the trigger condition more precise for current testing needs. Ensure that the branch naming consistently matches your deployment and testing strategy.

---

`9-30`: **Well-Documented Environment Variables**  
The environment variable section now includes useful inline comments that clarify the purpose of each secret and variable (e.g., `SERVER_USER`, `SERVER_HOST`, `SSH_PRIVATE_KEY`, etc.). This added documentation enhances maintainability and aids other developers in understanding configuration requirements.

---

`37-46`: **Integration of the `validate-config` Job is Effective**  
The new `validate-config` job reuses the workflow from `.github/workflows/validate.env_and_secrets.yml` by explicitly passing both production and development secrets. This not only centralizes configuration validation but also promotes reuse across different CD workflows.  
Double-check that exposing PROD secrets in a branch-test environment is intentional and secure.

---

`51-60`: **Build-Push Job Outputs and Permissions Clear and Concise**  
The build-push job correctly sets the necessary permissions for repository content and package publishing, and it defines outputs (for backend and frontend SHA tags) with clarifying comments. The usage of helper steps like `lowercaser` and `image_tags` is clean and effective.

---

`117-120`: **Deployment Trigger Condition is Appropriately Scoped**  
The deploy job’s condition (`if: github.event.pull_request.merged == true`) ensures that deployment only occurs after a PR merge, which is a prudent control step.

---

`151-165`: **Enhanced VERSION File Update Adds Valuable Deployment Metadata**  
The added steps to create and update the `VERSION` file (including deployment time, Git commit, branch, and image tags) are a strong addition for tracking deployments. Transferring this file to the server will be useful for post-deployment diagnostics and version tracking.

---

`167-190`: **File Transfer Steps Appropriately Handle Deployment Artifacts**  
The steps transferring various deployment files (such as `docker-compose.yml`, `.env`, `nginx.conf`, and deployment scripts) to the remote server are clear. The commented directory structure is a helpful reference. Ensure that file paths and permissions on the server are configured to accept these transfers securely.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 YAMLlint (1.35.1)</summary>

[error] 172-172: trailing spaces

(trailing-spaces)

---

[error] 181-181: trailing spaces

(trailing-spaces)

</details>

</details>

---

`192-219`: **SSH-Based Deployment Execution is Well-Structured**  
The final deployment step, which executes a series of SSH commands via a here-document, cleanly handles tasks including Docker login, running the deploy script, and logging out. Verifying that all referenced scripts (`docker-login.sh` and `deploy.sh`) have the expected permissions and contents will further fortify the deployment process.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 YAMLlint (1.35.1)</summary>

[error] 205-205: trailing spaces

(trailing-spaces)

---

[error] 207-207: trailing spaces

(trailing-spaces)

---

[error] 211-211: trailing spaces

(trailing-spaces)

</details>

</details>

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-02T13:34:57Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 0**

<details>
<summary>🧹 Nitpick comments (3)</summary><blockquote>

<details>
<summary>.github/workflows/validate.env_and_secrets.yml (3)</summary><blockquote>

`9-26`: **Secrets Declaration: Consider Adding Documentation**  
The secrets required for the workflow call are well organized. For better maintainability, consider adding inline comments or documentation for each secret (e.g., what format or content is expected).

---

`27-50`: **Production Secrets Validation: Key Existence & Config Line Check**  
The production validation job thoroughly checks for essential keys (`COMPOSE_PROJECT_NAME`, `HOST_PORT_FRONTEND`, and `BACKEND_INTERNAL_PORT`) and performs a sanity check on the number of config lines. One point to note is that while the absence of these keys causes an immediate failure, the check for `IMAGE_TAG_BACKEND` only issues a warning. Ensure that this behavior is intentional and clearly documented since it differs from the treatment of other keys.

---

`64-87`: **SSH Keys Validation: Enhance Regex Specificity**  
The SSH key validation correctly checks for the presence of a private key marker using the regex `"BEGIN .* PRIVATE KEY"`. For increased robustness, consider tightening the regex—for instance, matching the typical delimiters (e.g., `"-----BEGIN .* PRIVATE KEY-----"`). This could help avoid false positives on malformed keys.  

  
*Proposed diff for enhanced regex:*
```diff
-          if ! grep -q "BEGIN .* PRIVATE KEY" ssh_key_prod; then
-            echo "✗ Invalid PROD SSH key format!"
-            exit 1
-          fi
+          if ! grep -q "-----BEGIN .* PRIVATE KEY-----" ssh_key_prod; then
+            echo "✗ Invalid PROD SSH key format!"
+            exit 1
+          fi
```

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro (Legacy)**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between b09005060db5ce701938e4634cbb2b49e5fa52a0 and 616fc99de7e24e101925c07f6fc0ff5c542306e0.

</details>

<details>
<summary>📒 Files selected for processing (1)</summary>

* `.github/workflows/validate.env_and_secrets.yml` (1 hunks)

</details>

<details>
<summary>🔇 Additional comments (3)</summary><blockquote>

<details>
<summary>.github/workflows/validate.env_and_secrets.yml (3)</summary>

`1-8`: **Workflow Name & Trigger Definition Look Good**  
The workflow name "Validate Environment Secrets" is clear, and the trigger configuration (manual trigger, pull_request on development/main, and workflow_call) is set up correctly.

---

`51-63`: **DEV Environment Secrets Validation: Consider Enhancing Checks**  
The DEV environment validation only confirms the presence of `IMAGE_TAG_BACKEND`. As noted in previous reviews, it might be beneficial to mirror some of the key validations performed in production (if applicable) to ensure consistency.

---

`88-103`: **Docker Credentials Check: Clear and Secure**  
The check for the GitHub Container Registry tokens is straightforward and ensures that the necessary tokens are non-empty. This fulfills the requirement to validate the presence of credentials without exposing or authenticating them.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-02T14:10:59Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 0**

<details>
<summary>🧹 Nitpick comments (2)</summary><blockquote>

<details>
<summary>deployment/scripts/deploy.sh (2)</summary><blockquote>

`22-26`: **Consistent Logging Utility**

The `log_message` function is succinct and provides timestamped logging. If a more standardized date format is desired (e.g., ISO 8601), consider passing options to `date` (e.g., `date -Iseconds`). Overall, the implementation is clear and effective.

---

`111-134`: **Health Check Loop**

The `perform_health_check` function employs a loop with configurable retries to verify the health endpoint. It provides clear feedback on each attempt and returns a proper status code based on success or failure.  

Consider making the health endpoint configurable beyond the default by perhaps allowing an override via an environment variable.

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 93c06b0224d60110b6bff0480476e0e29e9c1470 and 6eb7d0ac10c348cb2e2236abaa505cb15cd754ef.

</details>

<details>
<summary>📒 Files selected for processing (6)</summary>

* `.gitignore` (1 hunks)
* `deployment/scripts/deploy-DESKTOP-19QVLUP.sh` (0 hunks)
* `deployment/scripts/deploy.sh` (1 hunks)
* `deployment/scripts/setup_gh_secrets-DESKTOP-19QVLUP.sh` (0 hunks)
* `deployment/scripts/setup_ssh_access-DESKTOP-19QVLUP.sh` (0 hunks)
* `docs/.github/deployment__Best_Practices.md` (1 hunks)

</details>

<details>
<summary>💤 Files with no reviewable changes (3)</summary>

* deployment/scripts/deploy-DESKTOP-19QVLUP.sh
* deployment/scripts/setup_ssh_access-DESKTOP-19QVLUP.sh
* deployment/scripts/setup_gh_secrets-DESKTOP-19QVLUP.sh

</details>

<details>
<summary>🚧 Files skipped from review as they are similar to previous changes (1)</summary>

* .gitignore

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (1)</summary>

* GitHub Check: Build & Push Docker Images

</details>

<details>
<summary>🔇 Additional comments (12)</summary><blockquote>

<details>
<summary>deployment/scripts/deploy.sh (11)</summary>

`1-4`: **Header & Description Clarity**

The file header and description clearly state the script’s purpose. The comments provide sufficient context for deploy operations using Docker Compose.

---

`8-11`: **Robust Script Safety Setup**

The use of `set -e -u -o pipefail` ensures that the script exits on errors, references to undefined variables, or failures within pipelines – a best practice for shell scripts in CI/CD environments.

---

`15-18`: **Configuration Constants Initialization**

Defining constants such as `HEALTH_CHECK_MAX_RETRIES`, `HEALTH_CHECK_RETRY_INTERVAL`, and `ROLLBACK_STABILITY_WAIT` at the top improves readability and eases future adjustments.

---

`28-48`: **Environment Variables Loader**

The `load_env_vars` function robustly checks for the existence of the `.env` file, sources it safely using `set -a`/`set +a`, and verifies that essential variables are set using parameter expansion. This prevents the deployment from proceeding with incomplete configuration.

---

`50-82`: **Rollback Preparation Logic**

The `prepare_rollback` function effectively retrieves the current Docker images for backend and frontend containers and writes them to a rollback file. The use of `docker inspect` with fallback (`|| echo ""`) ensures that the absence of a running container is handled gracefully.

---

`84-93`: **Pulling New Docker Images**

The `pull_new_images` function uses `docker compose --env-file .env pull` with proper error checking. The clear logging messages help in diagnosing image pull failures.

---

`95-109`: **Deploying New Containers**

The `deploy_new_containers` function ensures that containers are recreated using the options `--force-recreate` and `--remove-orphans`, which is crucial for a clean deployment. The error handling and logging are well implemented.

---

`136-172`: **Rollback Handling**

The `handle_rollback` function is robust – it checks for the existence of `.env.rollback`, sources it, and attempts to roll back the deployment. The post-rollback health check and clear logging messages help signal rollback status, and exiting with a non-zero code ensures the CI/CD system captures the failure appropriately.

---

`174-189`: **Final Image Logging**

The `log_success_confirmation` function effectively captures the final running images for both backend and frontend services, providing good traceability of what was deployed.

---

`191-214`: **Docker Images Cleanup**

The `cleanup_docker_images` function uses `docker image prune -af` and logs warnings if the prune command fails. This conservative approach ensures that unused images are cleaned up without risking disruption to running containers.

---

`216-252`: **Structured Main Execution Flow**

The main block sequentially calls the functions (loading environment, preparing rollback, pulling images, deploying new containers, performing health checks, handling rollback if needed, confirming success, and cleaning up). The clear commenting of each step helps in understanding the deployment process.

</details>
<details>
<summary>docs/.github/deployment__Best_Practices.md (1)</summary>

`1-30`: **Deployment Best Practices Documentation**

This new documentation file clearly outlines best practice considerations for the deployment process. It emphasizes atomicity, simplicity, safety, and consistency in error handling and logging. The high-level descriptions of functions like `load_env_vars`, `prepare_rollback`, `pull_new_images`, and others align well with the deployment script's structure.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-02T15:33:18Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 0**

<details>
<summary>🔭 Outside diff range comments (1)</summary><blockquote>

<details>
<summary>docs/issues/#62-Docker_container_Labelling (1)</summary><blockquote>

`1-77`: _🛠️ Refactor suggestion_

**Revise the filename to avoid using special characters.**

The filename `#62-Docker_container_Labelling` contains a hashtag character, which can cause issues with some systems, tools, or shell commands since # is a special character in many contexts. Consider renaming the file to something like `issue-62-Docker_container_Labelling.md` or `Docker_container_Labelling_issue_62.md`.

</blockquote></details>

</blockquote></details>

<details>
<summary>🧹 Nitpick comments (3)</summary><blockquote>

<details>
<summary>docs/issues/issue_63_body.md (1)</summary><blockquote>

`42-44`: **Fix bare URLs in markdown to improve compliance with markdown standards.**

The URLs in the resources section should be properly formatted as markdown links instead of bare URLs to comply with markdown best practices.


```diff
-Docker Builder `LABEL` instruction: https://docs.docker.com/engine/reference/builder/#label
-`docker image prune` command (including `--filter`): https://docs.docker.com/engine/reference/commandline/image_prune/
-Open Container Initiative (OCI) standard image labels (good practice): https://github.com/opencontainers/image-spec/blob/main/annotations.md
+Docker Builder `LABEL` instruction: [https://docs.docker.com/engine/reference/builder/#label](https://docs.docker.com/engine/reference/builder/#label)
+`docker image prune` command (including `--filter`): [https://docs.docker.com/engine/reference/commandline/image_prune/](https://docs.docker.com/engine/reference/commandline/image_prune/)
+Open Container Initiative (OCI) standard image labels (good practice): [https://github.com/opencontainers/image-spec/blob/main/annotations.md](https://github.com/opencontainers/image-spec/blob/main/annotations.md)
```

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 markdownlint-cli2 (0.17.2)</summary>

42-42: Bare URL used
null

(MD034, no-bare-urls)

---

43-43: Bare URL used
null

(MD034, no-bare-urls)

---

44-44: Bare URL used
null

(MD034, no-bare-urls)

</details>

</details>

</blockquote></details>
<details>
<summary>docs/issues/#62-Docker_container_Labelling (2)</summary><blockquote>

`64-67`: **Fix bare URLs in markdown to improve compliance with markdown standards.**

The URLs in the resources section should be properly formatted as markdown links instead of bare URLs to comply with markdown best practices.


```diff
-* Docker Builder `LABEL` instruction: https://docs.docker.com/engine/reference/builder/#label
-* `docker image prune` command (including `--filter`): https://docs.docker.com/engine/reference/commandline/image_prune/
-* Open Container Initiative (OCI) standard image labels (good practice): https://github.com/opencontainers/image-spec/blob/main/annotations.md
+* Docker Builder `LABEL` instruction: [https://docs.docker.com/engine/reference/builder/#label](https://docs.docker.com/engine/reference/builder/#label)
+* `docker image prune` command (including `--filter`): [https://docs.docker.com/engine/reference/commandline/image_prune/](https://docs.docker.com/engine/reference/commandline/image_prune/)
+* Open Container Initiative (OCI) standard image labels (good practice): [https://github.com/opencontainers/image-spec/blob/main/annotations.md](https://github.com/opencontainers/image-spec/blob/main/annotations.md)
```

---

`75-76`: **Add actual reference implementations or remove the placeholder.**

The "Reference Implementations" section contains only a placeholder. Either provide actual reference implementations or consider removing this section if not applicable.


```diff
-**Reference Implementations:**
-* (Link to any internal examples or best practices if available)
+**Reference Implementations:**
+* Example project using Docker labels: [organization/repo-name](https://github.com/organization/repo-name)
+* Internal documentation on Docker best practices: [link to internal wiki/docs]
```

Alternatively, if no reference implementations are available:
```diff
-**Reference Implementations:**
-* (Link to any internal examples or best practices if available)
```

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 6eb7d0ac10c348cb2e2236abaa505cb15cd754ef and 328f20047a786bb3dd6a55a1a43d4e0b654a3df9.

</details>

<details>
<summary>📒 Files selected for processing (4)</summary>

* `.github/ISSUE_TEMPLATE/rust_devving.yml` (4 hunks)
* `.gitignore` (1 hunks)
* `docs/issues/#62-Docker_container_Labelling` (1 hunks)
* `docs/issues/issue_63_body.md` (1 hunks)

</details>

<details>
<summary>✅ Files skipped from review due to trivial changes (1)</summary>

* .github/ISSUE_TEMPLATE/rust_devving.yml

</details>

<details>
<summary>🚧 Files skipped from review as they are similar to previous changes (1)</summary>

* .gitignore

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🪛 markdownlint-cli2 (0.17.2)</summary>

<details>
<summary>docs/issues/issue_63_body.md</summary>

42-42: Bare URL used
null

(MD034, no-bare-urls)

---

43-43: Bare URL used
null

(MD034, no-bare-urls)

---

44-44: Bare URL used
null

(MD034, no-bare-urls)

</details>

</details>

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (1)</summary>

* GitHub Check: Build & Push Docker Images

</details>

<details>
<summary>🔇 Additional comments (2)</summary><blockquote>

<details>
<summary>docs/issues/issue_63_body.md (1)</summary>

`1-52`: **Well-structured and comprehensive issue description.**

This is an excellent issue description that clearly outlines the problem, solution, dependencies, and acceptance criteria for the Docker image labeling refactoring task. The technical context provides a thorough explanation of both the current state and target state, making it easy for developers to understand the requirements.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 markdownlint-cli2 (0.17.2)</summary>

42-42: Bare URL used
null

(MD034, no-bare-urls)

---

43-43: Bare URL used
null

(MD034, no-bare-urls)

---

44-44: Bare URL used
null

(MD034, no-bare-urls)

</details>

</details>

</details>
<details>
<summary>docs/issues/#62-Docker_container_Labelling (1)</summary>

`1-77`: **Note about relation to PR objectives**

This issue template appears to be focused on Docker container labeling, while the PR objectives mention environment and secrets validation workflows. Consider clarifying how this issue template relates to the broader PR objectives or if it's an unrelated addition.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-02T18:04:15Z
user: login: copilot-pull-request-reviewer[bot]
body: ## Pull Request Overview

This pull request adds an automated workflow to validate environment secrets and SSH keys to prevent misconfigurations before deployment. Key changes include:
- Introducing the new "validate.env_and_secrets.yml" workflow for environment, SSH, and Docker credential validation.
- Integrating the validation workflow into production, development, and branch-test CI/CD pipelines.
- Updating related documentation and best practices to reflect these security enhancements.

### Reviewed Changes

Copilot reviewed 10 out of 15 changed files in this pull request and generated 1 comment.

<details>
<summary>Show a summary per file</summary>

| File                                                        | Description                                                                        |
| ----------------------------------------------------------- | ---------------------------------------------------------------------------------- |
| docs/issues/issue_63_body.md                                | Added documentation on Docker image labeling for targeted image pruning.           |
| docs/.github/deployment__Best_Practices.md                  | Updated best practice guidelines for deployment processes and cleanup strategies.  |
| .github/workflows/verify-secret-hash.yml                    | Introduced a workflow to calculate and verify secret hashes.                       |
| .github/workflows/validate.env_and_secrets.yml              | New workflow to validate environment secrets, SSH keys, and Docker credentials.    |
| .github/workflows/secrets.md                                | Removed obsolete secrets documentation.                                            |
| .github/workflows/cd.prod.yml                               | Integrated secret validation into the production deployment workflow.              |
| .github/workflows/cd.dev.yml                                | Integrated secret validation into the development deployment workflow.             |
| .github/workflows/cd.branch-test.yml                        | Updated branch-test workflow to include secret validation and version file update.   |
| .github/ISSUE_TEMPLATE/rust_devving.yml                     | Minor update to issue template comments.                                           |
</details>


<details>
<summary>Files not reviewed (5)</summary>

* **.env.development**: Language not supported
* **.env.production**: Language not supported
* **.github/workflows/test-secret.yml**: Language not supported
* **deployment/scripts/deploy.sh**: Language not supported
* **docs/issues/#62-Docker_container_Labelling**: Language not supported
</details>

<details>
<summary>Comments suppressed due to low confidence (1)</summary>

**.github/workflows/validate.env_and_secrets.yml:71**
* [nitpick] The regex 'BEGIN .* PRIVATE KEY' might not accurately match all valid SSH key formats. Consider refining the regex to ensure robust SSH key validation.
```
if ! grep -q "BEGIN .* PRIVATE KEY" ssh_key_prod; then
```
</details>


state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-03T11:07:11Z
user: login: pevinskevin
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-03T13:41:53Z
user: login: Jafarr1
body: Looks good 
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-07T09:24:56Z
user: login: Jafarr1
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-04-07T09:40:28Z

Review comments:
diff_hunk: @@ -107,6 +116,7 @@ jobs:
 
   deploy:
     name: Deploy to Server
+    if: github.event.pull_request.merged == true
path: .github/workflows/cd.branch-test.yml
user: login: Copilot
body: The deployment condition references 'github.event.pull_request.merged', but this workflow is triggered by push events. Adjust the condition to align with the actual event payload to avoid unintended behavior.
```suggestion

```
created_at: 2025-04-02T13:30:39Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,100 @@
+name: Validate Environment Secrets
+
+on:
+  workflow_dispatch: # Manual trigger for testing
+  pull_request: # Automatically run on PRs
+    branches: [development, main]
+  workflow_call:
+    secrets:
+      PROD_ENV_FILE:
+        required: true
+
+      DEV_ENV_FILE:
+        required: true
+
+      PROD_SSH_PRIVATE_KEY:
+        required: true
+
+      DEV_SSH_PRIVATE_KEY:
+        required: true
+
+      PROD_GHCR_PAT_OR_TOKEN:
+        required: true
+
+      DEV_GHCR_PAT_OR_TOKEN:
+        required: true
+
+jobs:
+  validate-prod-secrets:
+    runs-on: ubuntu-latest
+    steps:
+      - name: Check PROD environment secrets
+        run: |
+          echo "${{ secrets.PROD_ENV_FILE }}" > .env.prod
+          # Verify essential keys exist
+          grep -q "COMPOSE_PROJECT_NAME" .env.prod && echo "✓ COMPOSE_PROJECT_NAME exists" || { echo "✗ Missing COMPOSE_PROJECT_NAME"; exit 1; }
+          grep -q "HOST_PORT_FRONTEND" .env.prod && echo "✓ HOST_PORT_FRONTEND exists" || { echo "✗ Missing HOST_PORT_FRONTEND"; exit 1; }
+          grep -q "BACKEND_INTERNAL_PORT" .env.prod && echo "✓ BACKEND_INTERNAL_PORT exists" || { echo "✗ Missing BACKEND_INTERNAL_PORT"; exit 1; }
+          # Count config lines for sanity check
+          CONFIG_LINES=$(grep -v '^#' .env.prod | grep -v '^$' | wc -l)
+          echo "Total config lines: $CONFIG_LINES"
+          if [ "$CONFIG_LINES" -lt 5 ]; then
+            echo "⚠️ Warning: Fewer than expected config lines!"
+            exit 1
+          fi
+          # Test Docker image references
+          grep -q "IMAGE_TAG_BACKEND" .env.prod && echo "✓ IMAGE_TAG_BACKEND exists" || { echo "⚠️ Missing IMAGE_TAG_BACKEND (may be set by CD)"; }
+          # Clean up
+          rm .env.prod
+          echo "✅ PROD environment file validated successfully"
+
+  validate-dev-secrets:
+    runs-on: ubuntu-latest
+    steps:
+      - name: Check DEV environment secrets
+        run: |
+          # Similar validation for DEV environment
+          echo "${{ secrets.DEV_ENV_FILE }}" > .env.dev
+          # Add similar validation steps
path: .github/workflows/validate.env_and_secrets.yml
user: login: Copilot
body: [nitpick] The DEV environment validation step only writes and removes the .env.dev file without performing key validations as in the PROD step. Consider adding similar essential key checks for consistency.
```suggestion
          # Test Docker image references
          grep -q "IMAGE_TAG_BACKEND" .env.dev && echo "✓ IMAGE_TAG_BACKEND exists" || { echo "⚠️ Missing IMAGE_TAG_BACKEND (may be set by CD)"; }
          # Clean up
```
created_at: 2025-04-02T13:30:40Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,100 @@
+name: Validate Environment Secrets
+
+on:
+  workflow_dispatch: # Manual trigger for testing
+  pull_request: # Automatically run on PRs
+    branches: [development, main]
+  workflow_call:
+    secrets:
+      PROD_ENV_FILE:
+        required: true
+
+      DEV_ENV_FILE:
+        required: true
+
+      PROD_SSH_PRIVATE_KEY:
+        required: true
+
+      DEV_SSH_PRIVATE_KEY:
+        required: true
+
+      PROD_GHCR_PAT_OR_TOKEN:
+        required: true
+
+      DEV_GHCR_PAT_OR_TOKEN:
+        required: true
+
+jobs:
+  validate-prod-secrets:
+    runs-on: ubuntu-latest
+    steps:
+      - name: Check PROD environment secrets
+        run: |
+          echo "${{ secrets.PROD_ENV_FILE }}" > .env.prod
+          # Verify essential keys exist
+          grep -q "COMPOSE_PROJECT_NAME" .env.prod && echo "✓ COMPOSE_PROJECT_NAME exists" || { echo "✗ Missing COMPOSE_PROJECT_NAME"; exit 1; }
+          grep -q "HOST_PORT_FRONTEND" .env.prod && echo "✓ HOST_PORT_FRONTEND exists" || { echo "✗ Missing HOST_PORT_FRONTEND"; exit 1; }
+          grep -q "BACKEND_INTERNAL_PORT" .env.prod && echo "✓ BACKEND_INTERNAL_PORT exists" || { echo "✗ Missing BACKEND_INTERNAL_PORT"; exit 1; }
+          # Count config lines for sanity check
+          CONFIG_LINES=$(grep -v '^#' .env.prod | grep -v '^$' | wc -l)
+          echo "Total config lines: $CONFIG_LINES"
+          if [ "$CONFIG_LINES" -lt 5 ]; then
+            echo "⚠️ Warning: Fewer than expected config lines!"
+            exit 1
+          fi
+          # Test Docker image references
+          grep -q "IMAGE_TAG_BACKEND" .env.prod && echo "✓ IMAGE_TAG_BACKEND exists" || { echo "⚠️ Missing IMAGE_TAG_BACKEND (may be set by CD)"; }
+          # Clean up
+          rm .env.prod
+          echo "✅ PROD environment file validated successfully"
+
+  validate-dev-secrets:
+    runs-on: ubuntu-latest
+    steps:
+      - name: Check DEV environment secrets
+        run: |
+          # Similar validation for DEV environment
+          echo "${{ secrets.DEV_ENV_FILE }}" > .env.dev
+          # Add similar validation steps
+          rm .env.dev
+          echo "✅ DEV environment file validated successfully"
path: .github/workflows/validate.env_and_secrets.yml
user: login: coderabbitai[bot]
body: _🛠️ Refactor suggestion_

**DEV Environment Secrets Validation Could Be Expanded**  
The `validate-dev-secrets` job currently writes the DEV environment secret to a file and then immediately cleans up after printing a success message. Since the production validation includes detailed checks, it might be beneficial to mirror similar validations (e.g., ensuring essential keys exist) for the DEV environment as well.

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-04-02T13:34:56Z
author_association: CONTRIBUTOR
diff_hunk: @@ -138,9 +147,24 @@ jobs:
 
         # ------------------------------------------
 
+      # create/update VERSION file
+      - name: updating VERSION file
+        run: |
+          SERVER_DEST_BASE="${{ env.SERVER_USER }}@${{ env.SERVER_HOST }}:${{ env.DEPLOY_DIR }}"
+
+          echo "DEPLOYMENT_TIME=$(date -u +"%Y-%m-%dT%H:%M:%SZ")" > VERSION
path: .github/workflows/cd.branch-test.yml
user: login: Copilot
body: The nested double quotes inside the date command may cause syntax issues. Consider escaping the inner quotes or using single quotes to properly delimit the format string.
```suggestion
          echo "DEPLOYMENT_TIME=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" > VERSION
```
created_at: 2025-04-03T11:07:10Z
author_association: CONTRIBUTOR
diff_hunk: @@ -138,9 +147,24 @@ jobs:
 
         # ------------------------------------------
 
+      # create/update VERSION file
+      - name: updating VERSION file
+        run: |
+          SERVER_DEST_BASE="${{ env.SERVER_USER }}@${{ env.SERVER_HOST }}:${{ env.DEPLOY_DIR }}"
+
+          echo "DEPLOYMENT_TIME=$(date -u +"%Y-%m-%dT%H:%M:%SZ")" > VERSION
path: .github/workflows/cd.branch-test.yml
user: login: pevinskevin
body: @AlekOmOm Jeg committer CodeRabbit's feedback. 
created_at: 2025-04-03T13:41:53Z
author_association: COLLABORATOR

PR comments:
user: login: coderabbitai[bot]
created_at: 2025-04-02T13:29:30Z
body: <!-- This is an auto-generated comment: summarize by coderabbit.ai -->
<!-- walkthrough_start -->

## Walkthrough
This pull request updates multiple configuration and deployment files. It reformats environment variable declarations without changing their values, revises GitHub Actions workflows by updating names, triggers, and adding a new `validate-config` job, and introduces new workflows for environment and secret validation. The obsolete secret-testing workflow is removed, while `.gitignore` is updated to modify ignore rules. The deployment script is enhanced with structured functions for logging, error handling, rollback, and cleanup. In addition, documentation files and issue templates are added or renamed to reflect best practices and Docker container labeling.

## Changes

| File(s) | Change Summary |
|---------|----------------|
| `.env.development` | Reformatted `IMAGE_TAG_FRONTEND` declaration; value remains unchanged. |
| `.github/workflows/cd.branch-test.yml`, `.github/workflows/cd.dev.yml`, `.github/workflows/cd.prod.yml` | Updated workflow names and branch triggers; added `validate-config` job; enhanced comments and deployment steps (e.g., version file creation). |
| `.github/workflows/validate.env_and_secrets.yml`, `.github/workflows/verify-secret-hash.yml` | Added new workflows to validate environment secrets and verify secret hash values. |
| `.github/workflows/test-secret.yml` | Removed obsolete workflow for testing secret echo functionality. |
| `.gitignore` | Removed entries for specific ai-prompt-content files; added `secret.txt` and `ai-prompt-content/` to ignore list. |
| `deployment/scripts/deploy.sh` | Enhanced deployment process by adding functions for logging, environment loading, rollback preparation, image pulling, container deployment, health checking, rollback handling, success confirmation, and image cleanup. |
| `docs/.github/deployment__Best_Practices.md`, `.github/ISSUE_TEMPLATE/rust_devving.yml`, `docs/issues/#62-Docker_container_Labelling`, `docs/issues/issue_63_body.md` | Introduced new documentation and issue templates outlining deployment best practices and Docker container labeling refinements; renamed and reformatted existing templates. |

## Sequence Diagram(s)
```mermaid
sequenceDiagram
    participant User as User
    participant Script as deploy.sh
    participant Docker as Docker Engine
    participant Server as Deployment Server

    User->>Script: Initiate deployment
    Script->>Script: load_env_vars()
    Script->>Script: prepare_rollback()
    Script->>Docker: pull_new_images()
    Script->>Docker: deploy_new_containers()
    Script->>Server: perform_health_check()
    alt Health check fails
        Script->>Docker: handle_rollback()
        Script->>Script: Log failure and exit
    else Health check passes
        Script->>Script: log_success_confirmation()
        Script->>Docker: cleanup_docker_images()
    end
```

## Suggested labels
`enhancement`

## Suggested reviewers
- maztas-tech
- Jafarr1

## Poem
> I'm a rabbit hopping through lines of code,  
> Skipping across workflows where secrets are bestowed.  
> With functions and logging all crisp and clear,  
> I celebrate each change with a joyful cheer.  
> Carrots and commits keep my spirit near!

<!-- walkthrough_end -->


---

<details>
<summary>📜 Recent review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 328f20047a786bb3dd6a55a1a43d4e0b654a3df9 and f7fe0ec07799099190ad13908a865f56cd5ca0a1.

</details>

<details>
<summary>📒 Files selected for processing (1)</summary>

* `.github/workflows/cd.branch-test.yml` (6 hunks)

</details>

<details>
<summary>🚧 Files skipped from review as they are similar to previous changes (1)</summary>

* .github/workflows/cd.branch-test.yml

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (1)</summary>

* GitHub Check: Build & Push Docker Images

</details>

</details>
<!-- internal state start -->


<!-- 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 -->

<!-- internal state end -->
<!-- tips_start -->

---



<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=Debugger-Demons/whoknows&utm_content=61):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Generate unit testing code for this file.`
  - `Open a follow-up GitHub issue for this discussion.`
- Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples:
  - `@coderabbitai generate unit testing code for this file.`
  -	`@coderabbitai modularize this function.`
- PR comments: Tag `@coderabbitai` in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
  - `@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.`
  - `@coderabbitai read src/utils.ts and generate unit testing code.`
  - `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.`
  - `@coderabbitai help me debug CodeRabbit configuration file.`

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

### CodeRabbit Commands (Invoked using PR comments)

- `@coderabbitai pause` to pause the reviews on a PR.
- `@coderabbitai resume` to resume the paused reviews.
- `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
- `@coderabbitai full review` to do a full review from scratch and review all the files again.
- `@coderabbitai summary` to regenerate the summary of the PR.
- `@coderabbitai generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai plan` to trigger planning for file edits and PR creation.
- `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository.
- `@coderabbitai help` to get help.

### Other keywords and placeholders

- Add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed.
- Add `@coderabbitai summary` to generate the high-level summary at a specific location in the PR description.
- Add `@coderabbitai` anywhere in the PR title to generate the title automatically.

### CodeRabbit Configuration File (`.coderabbit.yaml`)

- You can programmatically configure CodeRabbit by adding a `.coderabbit.yaml` file to the root of your repository.
- Please see the [configuration documentation](https://docs.coderabbit.ai/guides/configure-coderabbit) for more information.
- If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: `# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json`

### Documentation and Community

- Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->
author_association: CONTRIBUTOR
user: login: deepsource-io[bot]
created_at: 2025-04-02T13:29:56Z
body: <div><p>Here's the code health analysis summary for commits <code>51adb49..f7fe0ec</code>. <a href="https://app.deepsource.com/gh/Debugger-Demons/whoknows/run/3b459f7a-c79b-4ccf-8cb5-9854b86e9528/">View details on DeepSource</a>&nbsp;↗.</p><h3>Analysis Summary</h3><table><thead><tr><th>Analyzer</th><th>Status</th><th>Summary</th><th>Link</th></tr></thead><tbody><tr><td><img src="https://static.deepsource.com/analyzer_logos/rust.svg" alt="DeepSource Rust Logo" width="16px" height="16px"/><strong>Rust</strong></td><td><span>✅&nbsp;</span><span>Success</span></td><td></td><td><a href="https://app.deepsource.com/gh/Debugger-Demons/whoknows/run/3b459f7a-c79b-4ccf-8cb5-9854b86e9528/rust/">View Check</a>&nbsp;↗</td></tr><tr><td><img src="https://static.deepsource.com/analyzer_logos/shell.svg" alt="DeepSource Shell Logo" width="16px" height="16px"/><strong>Shell</strong></td><td><span>✅&nbsp;</span><span>Success</span></td><td><div>🎯 2 occurences resolved</div></td><td><a href="https://app.deepsource.com/gh/Debugger-Demons/whoknows/run/3b459f7a-c79b-4ccf-8cb5-9854b86e9528/shell/">View Check</a>&nbsp;↗</td></tr><tr><td><img src="https://static.deepsource.com/analyzer_logos/javascript.svg" alt="DeepSource JavaScript Logo" width="16px" height="16px"/><strong>JavaScript</strong></td><td><span>✅&nbsp;</span><span>Success</span></td><td></td><td><a href="https://app.deepsource.com/gh/Debugger-Demons/whoknows/run/3b459f7a-c79b-4ccf-8cb5-9854b86e9528/javascript/">View Check</a>&nbsp;↗</td></tr><tr><td><img src="https://static.deepsource.com/analyzer_logos/docker.svg" alt="DeepSource Docker Logo" width="16px" height="16px"/><strong>Docker</strong></td><td><span>✅&nbsp;</span><span>Success</span></td><td></td><td><a href="https://app.deepsource.com/gh/Debugger-Demons/whoknows/run/3b459f7a-c79b-4ccf-8cb5-9854b86e9528/docker/">View Check</a>&nbsp;↗</td></tr></tbody></table><hr/><blockquote><div>💡 If you’re a repository administrator, you can configure the quality gates from the <a href="https://app.deepsource.com/gh/Debugger-Demons/whoknows/settings/reporting">settings</a>.</div></blockquote></div>

author_association: NONE
user: login: AlekOmOm
created_at: 2025-04-02T15:34:47Z
body: updated deploy.sh 

---

root@HOME-SERVER:/home/deploy/deployment/whoknows# ./deploy.sh
[Wed  2 Apr 16:33:03 BST 2025] === Starting Deployment Script ===
[Wed  2 Apr 16:33:03 BST 2025] Loading environment variables from .env file...
[Wed  2 Apr 16:33:03 BST 2025] Environment variables loaded.
[Wed  2 Apr 16:33:03 BST 2025] Preparing for potential rollback by identifying current running images...
[Wed  2 Apr 16:33:03 BST 2025]   - Saving current backend image for rollback: ghcr.io/debugger-demons/whoknows/backend:93c06b0
[Wed  2 Apr 16:33:03 BST 2025]   - Saving current frontend image for rollback: ghcr.io/debugger-demons/whoknows/frontend:93c06b0
[Wed  2 Apr 16:33:03 BST 2025] Pulling new application images (Backend: ghcr.io/debugger-demons/whoknows/backend:93c06b0, Frontend: ghcr.io/debugger-demons/whoknows/frontend:93c06b0)...
[+] Pulling 2/2
 ✔ frontend Pulled                                                                                                                                                                                          0.7s
 ✔ backend Pulled                                                                                                                                                                                           0.7s
[Wed  2 Apr 16:33:04 BST 2025] Image pulling completed.
[Wed  2 Apr 16:33:04 BST 2025] Stopping old containers (if any) and starting new containers...
[+] Running 2/2
 ✔ Container whoknows_frontend_dev  Started                                                                                                                                                                 1.8s
 ✔ Container whoknows_backend_dev   Started                                                                                                                                                                 1.1s
[Wed  2 Apr 16:33:06 BST 2025] docker-compose up completed successfully.
[Wed  2 Apr 16:33:06 BST 2025] Waiting for application health check at http://localhost:8080/api/health...
[Wed  2 Apr 16:33:06 BST 2025] Health check PASSED!
[Wed  2 Apr 16:33:06 BST 2025] Deployment successful!
[Wed  2 Apr 16:33:06 BST 2025] Final running images:
[Wed  2 Apr 16:33:06 BST 2025]   - Backend : ghcr.io/debugger-demons/whoknows/backend:93c06b0
[Wed  2 Apr 16:33:06 BST 2025]   - Frontend: ghcr.io/debugger-demons/whoknows/frontend:93c06b0
[Wed  2 Apr 16:33:06 BST 2025] Cleaning up unused Docker images for this application...
[Wed  2 Apr 16:33:06 BST 2025] Applying prune filter: --filter reference=ghcr.io/debugger-demons/whoknows/*
Error response from daemon: invalid filter 'reference'
[Wed  2 Apr 16:33:06 BST 2025] Warning: 'docker image prune --filter reference=ghcr.io/debugger-demons/whoknows/*' command failed. Check Docker logs. Continuing deployment.
[Wed  2 Apr 16:33:06 BST 2025] Cleaning up temporary rollback file...
[Wed  2 Apr 16:33:06 BST 2025] === Deployment Script Completed Successfully ===
author_association: COLLABORATOR
user: login: pevinskevin
created_at: 2025-04-02T17:32:23Z
body: @AlekOmOm har du mulighed for at resolve merge-konflikterne? 
author_association: COLLABORATOR