Skip to content

Fix remaining mypy type checking errors for CI #6

Fix remaining mypy type checking errors for CI

Fix remaining mypy type checking errors for CI #6

Workflow file for this run

name: CI/CD
on:
push:
branches: [main]
pull_request:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}
jobs:
# Static analysis jobs run in parallel
lint:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: "3.11"
cache: 'pip'
- name: Install dependencies
run: |
pip install -r requirements.txt
pip install ruff black mypy
- name: Run linting with ruff
run: ruff check .
- name: Run code formatting check with black
run: black --check .
- name: Run type checking with mypy
run: mypy .
# Unit tests (when available)
unit-tests:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: "3.11"
cache: 'pip'
- name: Install dependencies
run: pip install -r requirements.txt
- name: Run unit tests
run: |
# TODO: Add unit tests
echo "Unit tests placeholder - add pytest tests later"
# Build Docker image
build-image:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@v4
- uses: docker/setup-buildx-action@v3
- uses: docker/login-action@v3
with:
username: nikolajer
password: ${{ secrets.DOCKER_REGISTRY_TOKEN }}
- uses: docker/build-push-action@v6
with:
context: .
file: ./Dockerfile
push: true
tags: nikolajer/life-as-code-app:${{ github.event.pull_request.head.sha || github.sha }},nikolajer/life-as-code-app:latest
deploy:
needs: [lint, unit-tests, build-image]
runs-on: ubuntu-latest
environment: production # Only production - no staging
permissions:
contents: read
env:
NAMESPACE: life-as-code-production
ENVIRONMENT: production
steps:
- uses: actions/checkout@v4
- name: Setup kubectl and Helm
run: |
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
chmod +x kubectl
sudo mv kubectl /usr/local/bin/
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
- name: Configure kubeconfig
run: |
mkdir -p $HOME/.kube
echo "${{ secrets.KUBE_CONFIG }}" | base64 -d > $HOME/.kube/config
chmod 600 $HOME/.kube/config
- name: Deploy Life-as-Code with Helm
id: helm-deploy
continue-on-error: true
run: |
# Create app namespace with proper labels if it doesn't exist
if ! kubectl get namespace $NAMESPACE 2>/dev/null; then
echo "Creating $NAMESPACE namespace..."
kubectl create namespace $NAMESPACE
kubectl label namespace $NAMESPACE app.kubernetes.io/managed-by=Helm
kubectl annotate namespace $NAMESPACE meta.helm.sh/release-name=life-as-code
kubectl annotate namespace $NAMESPACE meta.helm.sh/release-namespace=$NAMESPACE
fi
# Uninstall existing release if it exists to avoid "operation in progress" errors
helm uninstall life-as-code --namespace $NAMESPACE || true
# Wait a moment for cleanup
sleep 10
IMAGE_TAG="${{ github.event.pull_request.head.sha || github.sha }}"
echo "Deploying with image tag: $IMAGE_TAG"
helm upgrade --install life-as-code ./helm/life-as-code-app \
--namespace $NAMESPACE \
--set namespace=$NAMESPACE \
--set app.image.repository=nikolajer/life-as-code-app \
--set app.image.tag=$IMAGE_TAG \
--set ingress.host=life-as-code.nikolay-eremeev.com \
--set secrets.postgresDb="life_as_code" \
--set secrets.postgresUser="life_as_code_user" \
--set secrets.postgresPassword="${{ secrets.POSTGRES_LIFE_AS_CODE_PASSWORD }}" \
--set secrets.secretKey="${{ secrets.LIFE_AS_CODE_SECRET_KEY }}" \
--set secrets.fernetKey="${{ secrets.LIFE_AS_CODE_FERNET_KEY }}" \
--wait --timeout 5m
- name: Check Migration Logs
if: always()
run: |
echo "Checking for migration job..."
# Give it a moment for the job to be created
sleep 5
# Check if migration job exists
if kubectl get job life-as-code-migrations -n $NAMESPACE 2>/dev/null; then
echo "Migration job found. Monitoring for completion or failure..."
# Monitor job status in a loop to catch failure immediately
for i in $(seq 1 60); do
sleep 5
# Check job status
JOB_STATUS=$(kubectl get job life-as-code-migrations -n $NAMESPACE -o jsonpath='{.status}' 2>/dev/null || echo '{}')
COMPLETED=$(echo "$JOB_STATUS" | jq -r '.succeeded // 0')
FAILED=$(echo "$JOB_STATUS" | jq -r '.failed // 0')
echo "Attempt $i/60: Completed: $COMPLETED, Failed: $FAILED"
# If completed successfully
if [ "$COMPLETED" -gt "0" ]; then
echo "Migration job completed successfully!"
break
fi
# If failed, immediately capture logs before cleanup
if [ "$FAILED" -gt "0" ]; then
echo "Migration job failed! Capturing logs immediately..."
echo ""
echo "=== Migration Job Status ==="
kubectl describe job/life-as-code-migrations -n $NAMESPACE || true
echo ""
echo "=== Migration Pod Logs ==="
kubectl logs job/life-as-code-migrations -n $NAMESPACE --all-containers=true || true
# Also try to get logs from pods directly
echo ""
echo "=== Migration Pod Status ==="
kubectl get pods -l job-name=life-as-code-migrations -n $NAMESPACE || true
echo ""
echo "=== Direct Pod Logs ==="
kubectl logs -l job-name=life-as-code-migrations -n $NAMESPACE --all-containers=true || true
echo "Migration job failed!"
exit 1
fi
done
# If we exit the loop without completion, something's wrong
echo "Migration job monitoring timed out after 5 minutes"
echo ""
echo "=== Final Migration Job Status ==="
kubectl describe job/life-as-code-migrations -n $NAMESPACE || true
echo ""
echo "=== Final Migration Logs ==="
kubectl logs job/life-as-code-migrations -n $NAMESPACE --all-containers=true || true
else
echo "Migration job not found. Helm deployment may have failed."
fi
- name: Check Kubernetes Status
if: steps.helm-deploy.outcome == 'success'
run: |
echo "Checking Kubernetes namespaces and deployments..."
echo "=== Available Namespaces ==="
kubectl get namespaces
echo ""
echo "=== Life-as-Code Deployment Status ==="
kubectl get all -n $NAMESPACE
echo ""
echo "To create admin user manually, run:"
echo "kubectl exec -it deployment/life-as-code -n $NAMESPACE -- python manage_users.py"
- name: Check Deployment Status
if: steps.helm-deploy.outcome == 'failure'
run: |
echo "Helm deployment failed. Checking status..."
kubectl get all -n $NAMESPACE
exit 1
test-deployed:
needs: deploy
runs-on: ubuntu-latest
permissions:
contents: read
env:
APP_URL: https://life-as-code.nikolay-eremeev.com
steps:
- uses: actions/checkout@v4
- name: Test deployed application
run: |
echo "Testing deployed Life-as-Code application..."
# Wait for deployment to be fully ready
sleep 30
# Test basic connectivity
echo "Testing basic connectivity..."
curl -f -s -o /dev/null $APP_URL || {
echo "Failed to connect to $APP_URL"
exit 1
}
echo "✅ Application is responding"
# Test login page
echo "Testing login page..."
curl -s $APP_URL/login | grep -q "Life-as-Code" || {
echo "Login page doesn't contain expected content"
exit 1
}
echo "✅ Login page is working"
echo "🎉 Life-as-Code deployment test completed successfully!"