fix: project improvements and best practices #212
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Test Suite | |
| on: | |
| pull_request: | |
| branches: [ main, develop ] | |
| push: | |
| branches: [ main, develop ] | |
| workflow_dispatch: | |
| jobs: | |
| validate-compose: | |
| name: Validate Docker Compose | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v6 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Validate docker-compose.yml | |
| run: | | |
| docker compose config > /dev/null | |
| echo "✓ docker-compose.yml is valid" | |
| - name: Check for docker-compose syntax issues | |
| run: | | |
| docker compose config --quiet | |
| echo "✓ No syntax errors found" | |
| validate-env: | |
| name: Validate Environment Configuration | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v6 | |
| - name: Validate .env.example exists | |
| run: | | |
| if [ ! -f .env.example ]; then | |
| echo "✗ .env.example not found" | |
| exit 1 | |
| fi | |
| echo "✓ .env.example exists" | |
| - name: Check .env.example format | |
| run: | | |
| # Check for basic environment variable format | |
| if ! grep -qE '^[A-Z_]+=.*$' .env.example; then | |
| echo "✗ .env.example has invalid format" | |
| exit 1 | |
| fi | |
| echo "✓ .env.example format is valid" | |
| - name: Check for required variables | |
| run: | | |
| required_vars=( | |
| "VAULT_ADDR" | |
| "VAULT_TOKEN" | |
| "POSTGRES_USER" | |
| "POSTGRES_DB" | |
| "POSTGRES_PASSWORD" | |
| "MYSQL_USER" | |
| "MYSQL_DATABASE" | |
| "RABBITMQ_VHOST" | |
| "MONGODB_USER" | |
| "MONGODB_DATABASE" | |
| ) | |
| missing=0 | |
| for var in "${required_vars[@]}"; do | |
| if ! grep -q "^${var}=" .env.example; then | |
| echo "✗ Missing required variable: $var" | |
| missing=1 | |
| fi | |
| done | |
| if [ $missing -eq 1 ]; then | |
| exit 1 | |
| fi | |
| echo "✓ All required variables present (Vault-managed credentials)" | |
| validate-scripts: | |
| name: Validate Shell Scripts | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v6 | |
| - name: Check script executability | |
| run: | | |
| scripts=( | |
| "manage-colima.sh" | |
| "configs/vault/scripts/vault-init.sh" | |
| "configs/vault/scripts/vault-bootstrap.sh" | |
| ) | |
| for script in "${scripts[@]}"; do | |
| if [ -f "$script" ] && [ ! -x "$script" ]; then | |
| echo "✗ Script not executable: $script" | |
| exit 1 | |
| fi | |
| done | |
| echo "✓ All scripts are executable" | |
| - name: Check for bash shebangs | |
| run: | | |
| scripts=$(find . -name "*.sh" -type f) | |
| for script in $scripts; do | |
| shebang=$(head -n 1 "$script") | |
| if [[ ! "$shebang" =~ ^#!/bin/bash$ ]] && \ | |
| [[ ! "$shebang" =~ ^#!/usr/bin/env\ bash$ ]] && \ | |
| [[ ! "$shebang" =~ ^#!/bin/sh$ ]]; then | |
| echo "✗ Missing or incorrect shebang in: $script" | |
| echo " Found: $shebang" | |
| echo " Expected: #!/bin/bash, #!/usr/bin/env bash, or #!/bin/sh" | |
| exit 1 | |
| fi | |
| done | |
| echo "✓ All scripts have proper shebangs" | |
| validate-configs: | |
| name: Validate Configuration Files | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v6 | |
| - name: Validate JSON files | |
| run: | | |
| json_files=$(find configs -name "*.json" -type f 2>/dev/null || true) | |
| if [ -n "$json_files" ]; then | |
| for file in $json_files; do | |
| if ! python3 -m json.tool "$file" > /dev/null 2>&1; then | |
| echo "✗ Invalid JSON in: $file" | |
| exit 1 | |
| fi | |
| done | |
| echo "✓ All JSON files are valid" | |
| else | |
| echo "ℹ No JSON files to validate" | |
| fi | |
| - name: Validate YAML files | |
| run: | | |
| yaml_files=$(find configs -name "*.yml" -o -name "*.yaml" -type f 2>/dev/null || true) | |
| if [ -n "$yaml_files" ]; then | |
| pip install pyyaml | |
| for file in $yaml_files; do | |
| if ! python3 -c "import yaml; yaml.safe_load(open('$file'))" 2>/dev/null; then | |
| echo "✗ Invalid YAML in: $file" | |
| exit 1 | |
| fi | |
| done | |
| echo "✓ All YAML files are valid" | |
| else | |
| echo "ℹ No YAML files to validate" | |
| fi | |
| test-documentation: | |
| name: Test Documentation | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v6 | |
| - name: Check README exists and is not empty | |
| run: | | |
| if [ ! -f README.md ]; then | |
| echo "✗ README.md not found" | |
| exit 1 | |
| fi | |
| if [ ! -s README.md ]; then | |
| echo "✗ README.md is empty" | |
| exit 1 | |
| fi | |
| echo "✓ README.md exists and has content" | |
| - name: Check for broken markdown links | |
| uses: gaurav-nelson/github-action-markdown-link-check@v1 | |
| with: | |
| use-quiet-mode: 'yes' | |
| config-file: '.github/workflows/markdown-link-check-config.json' | |
| continue-on-error: true | |
| - name: Validate required documentation sections | |
| run: | | |
| required_sections=( | |
| "Quick Start" | |
| "Installation" | |
| "Prerequisites" | |
| "Services" | |
| "Troubleshooting" | |
| ) | |
| for section in "${required_sections[@]}"; do | |
| if ! grep -qi "## $section" README.md; then | |
| echo "⚠ Missing recommended section: $section" | |
| fi | |
| done | |
| echo "✓ Documentation validation complete" | |
| test-python: | |
| name: Test Python Scripts | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v6 | |
| - name: Set up Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: '3.11' | |
| - name: Check Python syntax | |
| run: | | |
| python_files=$(find scripts tests -name "*.py" -type f 2>/dev/null || true) | |
| if [ -n "$python_files" ]; then | |
| for file in $python_files; do | |
| if ! python3 -m py_compile "$file"; then | |
| echo "✗ Syntax error in: $file" | |
| exit 1 | |
| fi | |
| done | |
| echo "✓ All Python files have valid syntax" | |
| else | |
| echo "ℹ No Python files to validate" | |
| fi | |
| integration-test: | |
| name: Integration Test (Basic) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v6 | |
| - name: Create .env from example | |
| run: cp .env.example .env | |
| - name: Validate Docker Compose can parse files | |
| run: | | |
| docker compose config > /dev/null | |
| echo "✓ Docker Compose configuration is valid" | |
| - name: Check service definitions (no profile) | |
| run: | | |
| services=$(docker compose config --services) | |
| echo "Services with no profile: $services" | |
| # Vault should always be available (no profile) | |
| if ! echo "$services" | grep -q "^vault$"; then | |
| echo "✗ Missing vault (should have no profile)" | |
| exit 1 | |
| fi | |
| echo "✓ Vault is defined (no profile required)" | |
| - name: Check minimal profile services | |
| run: | | |
| services=$(docker compose --profile minimal config --services) | |
| expected_services=( | |
| "vault" | |
| "postgres" | |
| "pgbouncer" | |
| "redis-1" | |
| "forgejo" | |
| ) | |
| echo "Minimal profile services:" | |
| echo "$services" | |
| for service in "${expected_services[@]}"; do | |
| if ! echo "$services" | grep -q "^${service}$"; then | |
| echo "✗ Missing expected service in minimal profile: $service" | |
| exit 1 | |
| fi | |
| done | |
| echo "✓ All minimal profile services are defined" | |
| - name: Check standard profile services | |
| run: | | |
| services=$(docker compose --profile standard config --services) | |
| expected_services=( | |
| "vault" | |
| "postgres" | |
| "pgbouncer" | |
| "mysql" | |
| "mongodb" | |
| "redis-1" | |
| "redis-2" | |
| "redis-3" | |
| "rabbitmq" | |
| "forgejo" | |
| ) | |
| echo "Standard profile services:" | |
| echo "$services" | |
| for service in "${expected_services[@]}"; do | |
| if ! echo "$services" | grep -q "^${service}$"; then | |
| echo "✗ Missing expected service in standard profile: $service" | |
| exit 1 | |
| fi | |
| done | |
| echo "✓ All standard profile services are defined" | |
| test-summary: | |
| name: Test Summary | |
| runs-on: ubuntu-latest | |
| needs: | |
| - validate-compose | |
| - validate-env | |
| - validate-scripts | |
| - validate-configs | |
| - test-documentation | |
| - test-python | |
| - integration-test | |
| if: always() | |
| steps: | |
| - name: Check test results | |
| run: | | |
| if [ "${{ needs.validate-compose.result }}" != "success" ] || \ | |
| [ "${{ needs.validate-env.result }}" != "success" ] || \ | |
| [ "${{ needs.validate-scripts.result }}" != "success" ] || \ | |
| [ "${{ needs.validate-configs.result }}" != "success" ] || \ | |
| [ "${{ needs.test-documentation.result }}" != "success" ] || \ | |
| [ "${{ needs.test-python.result }}" != "success" ] || \ | |
| [ "${{ needs.integration-test.result }}" != "success" ]; then | |
| echo "❌ Some tests failed" | |
| exit 1 | |
| fi | |
| echo "✅ All tests passed!" |