-
Notifications
You must be signed in to change notification settings - Fork 0
feat(execution): Implement execution layer for test management #14
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| # Git | ||
| .git | ||
| .gitignore | ||
|
|
||
| # Python | ||
| __pycache__ | ||
| *.py[cod] | ||
| *.pyo | ||
| *.pyd | ||
| .Python | ||
| *.egg-info | ||
| .eggs | ||
| dist | ||
| build | ||
| *.egg | ||
| .venv | ||
| venv | ||
| env | ||
|
|
||
| # IDE | ||
| .vscode | ||
| .idea | ||
| *.swp | ||
| *.swo | ||
|
|
||
| # Testing/Coverage | ||
| .pytest_cache | ||
| .coverage | ||
| htmlcov | ||
| coverage.xml | ||
| *.cover | ||
|
|
||
| # Node/Frontend | ||
| node_modules | ||
| client/node_modules | ||
| client/build | ||
|
|
||
| # Docs and misc | ||
| docs | ||
| *.md | ||
| !README.md | ||
| *.log | ||
| .DS_Store | ||
|
|
||
| # Local data | ||
| data/ | ||
| logs/ | ||
| __blobstorage__ | ||
|
|
||
| # Deploy folder (avoid recursive copy) | ||
| deploy/ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| # Copyright (c) Microsoft Corporation. | ||
| # Licensed under the MIT License. | ||
|
|
||
| # Stage 1: Build stage | ||
| FROM mcr.microsoft.com/azurelinux/base/python:3.12 as builder | ||
| WORKDIR /app | ||
| RUN tdnf update -y && tdnf install -y \ | ||
| gcc \ | ||
| libffi-devel \ | ||
| && tdnf clean all | ||
| COPY requirements.txt . | ||
| RUN pip install --no-cache-dir --user -r requirements.txt | ||
|
|
||
| # Stage 2: Startup stage | ||
| FROM mcr.microsoft.com/azurelinux/base/python:3.12 | ||
| WORKDIR /app | ||
| RUN tdnf update -y && tdnf install -y \ | ||
| openssh-clients \ | ||
| git \ | ||
| curl \ | ||
| util-linux \ | ||
| && tdnf clean all \ | ||
| && mkdir -p /app/data /app/logs /root/.ssh \ | ||
| && chmod 700 /root/.ssh | ||
| COPY --from=builder /root/.local /root/.local | ||
| ENV PATH=/root/.local/bin:$PATH | ||
| COPY src/ ./src/ | ||
| COPY docs/ ./docs/ | ||
| COPY WORKSPACES/ ./WORKSPACES/ | ||
| RUN mkdir -p /app/data | ||
| ENV PYTHONPATH=/app | ||
| ENV PYTHONUNBUFFERED=1 | ||
| HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ | ||
| CMD curl -f http://localhost:8000/healthz || exit 1 | ||
| EXPOSE 8000 | ||
| CMD ["uvicorn", "src.api.app:app", "--host", "0.0.0.0", "--port", "8000"] | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| # Copyright (c) Microsoft Corporation. | ||
| # Licensed under the MIT License. | ||
|
|
||
| services: | ||
| sap-qa-service: | ||
| build: | ||
| context: .. | ||
| dockerfile: deploy/Dockerfile | ||
| container_name: sap-qa-service | ||
| restart: unless-stopped | ||
| ports: | ||
| - "8000:8000" | ||
| environment: | ||
| - LOG_FORMAT=${LOG_FORMAT:-json} | ||
| - LOG_LEVEL=${LOG_LEVEL:-INFO} | ||
| - SCHEDULER_CHECK_INTERVAL=${SCHEDULER_CHECK_INTERVAL:-60} | ||
| - PYTHONPATH=/app | ||
| volumes: | ||
| - sap-qa-data:/app/data | ||
| - ssh-keys:/root/.ssh:ro | ||
| - ../WORKSPACES:/app/WORKSPACES | ||
| healthcheck: | ||
| test: ["CMD", "curl", "-f", "http://localhost:8000/health"] | ||
|
Comment on lines
+22
to
+23
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The compose healthcheck hits Useful? React with 👍 / 👎. |
||
| interval: 30s | ||
| timeout: 10s | ||
| retries: 3 | ||
| start_period: 10s | ||
| networks: | ||
| - sap-qa-network | ||
| logging: | ||
| driver: "json-file" | ||
| options: | ||
| max-size: "10m" | ||
| max-file: "3" | ||
|
|
||
| volumes: | ||
| sap-qa-data: | ||
| driver: local | ||
| ssh-keys: | ||
| driver: local | ||
|
|
||
| networks: | ||
| sap-qa-network: | ||
| driver: bridge | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,153 @@ | ||
| #!/bin/bash | ||
|
|
||
| # Copyright (c) Microsoft Corporation. | ||
| # Licensed under the MIT License. | ||
| set -euo pipefail | ||
|
|
||
| script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" | ||
| source "${script_dir}/utils.sh" | ||
| set_output_context | ||
|
|
||
| PROJECT_ROOT="$(dirname "$script_dir")" | ||
| DEPLOY_DIR="$PROJECT_ROOT/deploy" | ||
|
|
||
| # Check and install Docker if needed | ||
| ensure_docker() { | ||
| if ! command_exists docker; then | ||
| log "INFO" "Docker not found. Installing..." | ||
| install_docker | ||
| else | ||
| log "INFO" "Docker is already installed." | ||
| fi | ||
|
|
||
| if ! docker compose version &> /dev/null; then | ||
| log "ERROR" "Docker Compose plugin not available." | ||
| log "INFO" "Attempting to install Docker Compose plugin..." | ||
| install_docker | ||
| fi | ||
|
|
||
| if ! docker info &> /dev/null 2>&1; then | ||
| log "INFO" "Starting Docker daemon..." | ||
| if command_exists systemctl && systemctl is-system-running &>/dev/null; then | ||
| sudo systemctl start docker | ||
| else | ||
| sudo service docker start | ||
| fi | ||
| fi | ||
|
|
||
| if command_exists systemctl && systemctl is-system-running &>/dev/null; then | ||
| log "INFO" "Enabling Docker to start on system boot..." | ||
| sudo systemctl enable docker 2>/dev/null || true | ||
| fi | ||
| } | ||
|
|
||
| # Build and start the container | ||
| deploy_container() { | ||
| log "INFO" "=== SAP QA Service Deployment ===" | ||
|
|
||
| if [[ ! -d "$DEPLOY_DIR" ]]; then | ||
| log "ERROR" "Deploy directory not found: $DEPLOY_DIR" | ||
| exit 1 | ||
| fi | ||
|
|
||
| check_file_exists "$DEPLOY_DIR/docker-compose.yml" "docker-compose.yml not found in $DEPLOY_DIR" | ||
| check_file_exists "$DEPLOY_DIR/Dockerfile" "Dockerfile not found in $DEPLOY_DIR" | ||
|
|
||
| log "INFO" "Creating data directories..." | ||
| mkdir -p "$PROJECT_ROOT/data/jobs/history" | ||
|
|
||
| log "INFO" "Stopping existing container (if any)..." | ||
| docker compose -f "$DEPLOY_DIR/docker-compose.yml" down 2>/dev/null || true | ||
|
|
||
| log "INFO" "Building Docker image..." | ||
| docker compose -f "$DEPLOY_DIR/docker-compose.yml" build | ||
|
|
||
| log "INFO" "Starting SAP QA service..." | ||
| docker compose -f "$DEPLOY_DIR/docker-compose.yml" up -d | ||
|
|
||
| log "INFO" "Waiting for service to be healthy..." | ||
| sleep 5 | ||
|
|
||
| if docker compose -f "$DEPLOY_DIR/docker-compose.yml" ps | grep -q "Up"; then | ||
| log "INFO" "=== Deployment Successful ===" | ||
| echo "" | ||
| echo "SAP QA Service is running at: http://localhost:8000" | ||
| echo "Health check: http://localhost:8000/health" | ||
| echo "" | ||
| echo "The service will auto-restart on system reboot." | ||
| echo "" | ||
| echo "Commands:" | ||
| echo " View logs: docker compose -f $DEPLOY_DIR/docker-compose.yml logs -f" | ||
| echo " Stop: docker compose -f $DEPLOY_DIR/docker-compose.yml down" | ||
| echo " Restart: docker compose -f $DEPLOY_DIR/docker-compose.yml restart" | ||
| echo "" | ||
|
|
||
| if command_exists curl; then | ||
| curl -s http://localhost:8000/health && echo "" | ||
| fi | ||
| else | ||
| log "ERROR" "=== Deployment Failed ===" | ||
| log "ERROR" "Check logs: docker compose -f $DEPLOY_DIR/docker-compose.yml logs" | ||
| exit 1 | ||
| fi | ||
| } | ||
|
|
||
| # Stop the container | ||
| stop_container() { | ||
| log "INFO" "Stopping SAP QA service..." | ||
| docker compose -f "$DEPLOY_DIR/docker-compose.yml" down | ||
| log "INFO" "Service stopped." | ||
| } | ||
|
|
||
| # Show container status | ||
| status_container() { | ||
| docker compose -f "$DEPLOY_DIR/docker-compose.yml" ps | ||
| } | ||
|
|
||
| # Show container logs | ||
| logs_container() { | ||
| docker compose -f "$DEPLOY_DIR/docker-compose.yml" logs -f | ||
| } | ||
|
|
||
| # Main entry point | ||
| main() { | ||
| local command="${1:-deploy}" | ||
|
|
||
| case "$command" in | ||
| deploy|start) | ||
| ensure_docker | ||
| deploy_container | ||
| ;; | ||
| stop) | ||
| stop_container | ||
| ;; | ||
| restart) | ||
| stop_container | ||
| deploy_container | ||
| ;; | ||
| status) | ||
| status_container | ||
| ;; | ||
| logs) | ||
| logs_container | ||
| ;; | ||
| install-docker) | ||
| install_docker | ||
| ;; | ||
| *) | ||
| echo "Usage: $0 {deploy|start|stop|restart|status|logs|install-docker}" | ||
| echo "" | ||
| echo "Commands:" | ||
| echo " deploy Install Docker (if needed) and start the service" | ||
| echo " start Same as deploy" | ||
| echo " stop Stop the service" | ||
| echo " restart Restart the service" | ||
| echo " status Show service status" | ||
| echo " logs Show service logs (follow mode)" | ||
| echo " install-docker Install Docker only" | ||
| exit 1 | ||
| ;; | ||
| esac | ||
| } | ||
|
|
||
| main "$@" |
Check failure
Code scanning / Trivy
Image user should not be 'root' High