diff --git a/.gitea/workflows/docker-build.yml b/.gitea/workflows/docker-build.yml new file mode 100644 index 0000000..9cdd5de --- /dev/null +++ b/.gitea/workflows/docker-build.yml @@ -0,0 +1,366 @@ +# Gitea Actions: Major Domo Database - Docker Build, Push, and Notify +# +# This workflow provides a complete CI/CD pipeline for the Major Domo Database API: +# - Validates semantic versioning on PRs +# - Builds Docker images on every push/PR +# - Pushes to Docker Hub on main branch merges +# - Sends Discord notifications on success/failure +# +# Created: 2026-02-04 +# Adapted from: paper-dynasty-database template + +name: Build Docker Image + +on: + push: + branches: + - main + pull_request: + branches: + - main + +jobs: + build: + runs-on: ubuntu-latest + + steps: + # ============================================== + # 1. CHECKOUT CODE + # ============================================== + - name: Checkout code + uses: actions/checkout@v4 + + # ============================================== + # 2. SEMANTIC VERSION VALIDATION (PRs only) + # ============================================== + # Enforces proper semantic versioning: + # - Blocks PRs that don't bump VERSION file + # - Validates version changes follow semver rules + # - Prevents skipping versions or going backwards + # + # Valid bumps: + # - Patch: 2.4.1 → 2.4.2 (bug fixes) + # - Minor: 2.4.1 → 2.5.0 (new features) + # - Major: 2.4.1 → 3.0.0 (breaking changes) + # + # Invalid bumps: + # - 2.4.1 → 2.6.0 (skipped minor version) + # - 2.4.1 → 2.3.0 (went backwards) + # - 2.4.1 → 2.5.1 (didn't reset patch) + # + - name: Check VERSION was bumped (semantic versioning) + if: github.event_name == 'pull_request' + run: | + # Get VERSION from this PR branch + PR_VERSION=$(cat VERSION 2>/dev/null || echo "0.0.0") + + # Get VERSION from main branch + git fetch origin main:main + MAIN_VERSION=$(git show main:VERSION 2>/dev/null || echo "0.0.0") + + echo "📋 Semantic Version Check" + echo "Main branch version: $MAIN_VERSION" + echo "PR branch version: $PR_VERSION" + echo "" + + # Parse versions into components + IFS='.' read -r MAIN_MAJOR MAIN_MINOR MAIN_PATCH <<< "$MAIN_VERSION" + IFS='.' read -r PR_MAJOR PR_MINOR PR_PATCH <<< "$PR_VERSION" + + # Remove any non-numeric characters + MAIN_MAJOR=${MAIN_MAJOR//[!0-9]/} + MAIN_MINOR=${MAIN_MINOR//[!0-9]/} + MAIN_PATCH=${MAIN_PATCH//[!0-9]/} + PR_MAJOR=${PR_MAJOR//[!0-9]/} + PR_MINOR=${PR_MINOR//[!0-9]/} + PR_PATCH=${PR_PATCH//[!0-9]/} + + # Check if VERSION unchanged + if [ "$PR_VERSION" = "$MAIN_VERSION" ]; then + echo "❌ ERROR: VERSION file has not been updated!" + echo "" + echo "Please update the VERSION file in your PR." + echo "Current version: $MAIN_VERSION" + exit 1 + fi + + # Validate semantic version bump + VALID=false + BUMP_TYPE="" + + # Check for major version bump (X.0.0) + if [ "$PR_MAJOR" -eq $((MAIN_MAJOR + 1)) ] && [ "$PR_MINOR" -eq 0 ] && [ "$PR_PATCH" -eq 0 ]; then + VALID=true + BUMP_TYPE="major" + # Check for minor version bump (x.X.0) + elif [ "$PR_MAJOR" -eq "$MAIN_MAJOR" ] && [ "$PR_MINOR" -eq $((MAIN_MINOR + 1)) ] && [ "$PR_PATCH" -eq 0 ]; then + VALID=true + BUMP_TYPE="minor" + # Check for patch version bump (x.x.X) + elif [ "$PR_MAJOR" -eq "$MAIN_MAJOR" ] && [ "$PR_MINOR" -eq "$MAIN_MINOR" ] && [ "$PR_PATCH" -eq $((MAIN_PATCH + 1)) ]; then + VALID=true + BUMP_TYPE="patch" + fi + + if [ "$VALID" = true ]; then + echo "✅ Valid $BUMP_TYPE version bump: $MAIN_VERSION → $PR_VERSION" + else + echo "❌ ERROR: Invalid semantic version change!" + echo "" + echo "Current version: $MAIN_VERSION" + echo "PR version: $PR_VERSION" + echo "" + echo "Valid version bumps:" + echo " - Patch: $MAIN_MAJOR.$MAIN_MINOR.$((MAIN_PATCH + 1))" + echo " - Minor: $MAIN_MAJOR.$((MAIN_MINOR + 1)).0" + echo " - Major: $((MAIN_MAJOR + 1)).0.0" + echo "" + echo "Common issues:" + echo " ❌ Skipping versions (e.g., 2.5.0 → 2.7.0)" + echo " ❌ Going backwards (e.g., 2.5.0 → 2.4.0)" + echo " ❌ Not resetting lower components (e.g., 2.5.0 → 2.6.1)" + exit 1 + fi + + # ============================================== + # 3. DOCKER BUILDX SETUP + # ============================================== + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + # ============================================== + # 4. DOCKER HUB LOGIN (main branch only) + # ============================================== + # Requires secrets in Gitea: + # - DOCKERHUB_USERNAME: Your Docker Hub username (manticorum67) + # - DOCKERHUB_TOKEN: Docker Hub access token (not password!) + # + # To create token: + # 1. Go to hub.docker.com + # 2. Account Settings → Security → New Access Token + # 3. Copy token to Gitea repo → Settings → Secrets → Actions + # + - name: Login to Docker Hub + if: github.ref == 'refs/heads/main' + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + # ============================================== + # 5. EXTRACT METADATA + # ============================================== + # Reads VERSION file and generates image tags: + # - version: From VERSION file (e.g., "2.4.1") + # - sha_short: First 7 chars of commit SHA + # - version_sha: Combined version+commit (e.g., "v2.4.1-a1b2c3d") + # - branch: Current branch name + # - timestamp: ISO 8601 format for Discord + # + - name: Extract metadata + id: meta + run: | + VERSION=$(cat VERSION 2>/dev/null || echo "0.0.0") + SHA_SHORT=$(echo ${{ github.sha }} | cut -c1-7) + echo "version=${VERSION}" >> $GITHUB_OUTPUT + echo "sha_short=${SHA_SHORT}" >> $GITHUB_OUTPUT + echo "version_sha=v${VERSION}-${SHA_SHORT}" >> $GITHUB_OUTPUT + echo "branch=${{ github.ref_name }}" >> $GITHUB_OUTPUT + echo "timestamp=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> $GITHUB_OUTPUT + + # ============================================== + # 6. BUILD AND PUSH DOCKER IMAGE + # ============================================== + # Creates 3 tags for each build: + # - latest: Always points to newest build + # - v{VERSION}: Semantic version from VERSION file + # - v{VERSION}-{COMMIT}: Version + commit hash for traceability + # + # Example tags: + # - manticorum67/major-domo-database:latest + # - manticorum67/major-domo-database:v2.4.1 + # - manticorum67/major-domo-database:v2.4.1-a1b2c3d + # + # Push behavior: + # - PRs: Build only (test), don't push + # - Main: Build and push to Docker Hub + # + - name: Build Docker image + uses: docker/build-push-action@v5 + with: + context: . + push: ${{ github.ref == 'refs/heads/main' }} + tags: | + manticorum67/major-domo-database:latest + manticorum67/major-domo-database:v${{ steps.meta.outputs.version }} + manticorum67/major-domo-database:${{ steps.meta.outputs.version_sha }} + cache-from: type=gha + cache-to: type=gha,mode=max + + # ============================================== + # 7. BUILD SUMMARY + # ============================================== + # Creates a formatted summary visible in Actions UI + # Shows: image tags, build details, push status + # + - name: Build Summary + run: | + echo "## 🐳 Docker Build Successful! ✅" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "**Image Tags:**" >> $GITHUB_STEP_SUMMARY + echo "- \`manticorum67/major-domo-database:latest\`" >> $GITHUB_STEP_SUMMARY + echo "- \`manticorum67/major-domo-database:v${{ steps.meta.outputs.version }}\`" >> $GITHUB_STEP_SUMMARY + echo "- \`manticorum67/major-domo-database:${{ steps.meta.outputs.version_sha }}\`" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "**Build Details:**" >> $GITHUB_STEP_SUMMARY + echo "- Branch: \`${{ steps.meta.outputs.branch }}\`" >> $GITHUB_STEP_SUMMARY + echo "- Commit: \`${{ github.sha }}\`" >> $GITHUB_STEP_SUMMARY + echo "- Timestamp: \`${{ steps.meta.outputs.timestamp }}\`" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + if [ "${{ github.ref }}" == "refs/heads/main" ]; then + echo "🚀 **Pushed to Docker Hub!**" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "Pull with: \`docker pull manticorum67/major-domo-database:latest\`" >> $GITHUB_STEP_SUMMARY + else + echo "_PR build - image not pushed to Docker Hub_" >> $GITHUB_STEP_SUMMARY + fi + + # ============================================== + # 8. DISCORD NOTIFICATION - SUCCESS + # ============================================== + # Sends green embed to Discord on successful builds + # + # Only fires on main branch pushes (not PRs) + # + # Setup: + # 1. Create webhook in Discord channel: + # Right-click channel → Edit → Integrations → Webhooks → New + # 2. Copy webhook URL + # 3. Add as secret: DISCORD_WEBHOOK_URL in Gitea repo settings + # + - name: Discord Notification - Success + if: success() && github.ref == 'refs/heads/main' + run: | + curl -H "Content-Type: application/json" \ + -d '{ + "embeds": [{ + "title": "✅ Major Domo Database Build Successful", + "description": "Docker image built and pushed to Docker Hub!", + "color": 3066993, + "fields": [ + { + "name": "Version", + "value": "`v${{ steps.meta.outputs.version }}`", + "inline": true + }, + { + "name": "Image Tag", + "value": "`${{ steps.meta.outputs.version_sha }}`", + "inline": true + }, + { + "name": "Branch", + "value": "`${{ steps.meta.outputs.branch }}`", + "inline": true + }, + { + "name": "Commit", + "value": "`${{ steps.meta.outputs.sha_short }}`", + "inline": true + }, + { + "name": "Author", + "value": "${{ github.actor }}", + "inline": true + }, + { + "name": "Docker Hub", + "value": "[manticorum67/major-domo-database](https://hub.docker.com/r/manticorum67/major-domo-database)", + "inline": false + }, + { + "name": "View Run", + "value": "[Click here](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})", + "inline": false + } + ], + "timestamp": "${{ steps.meta.outputs.timestamp }}" + }] + }' \ + ${{ secrets.DISCORD_WEBHOOK_URL }} + + # ============================================== + # 9. DISCORD NOTIFICATION - FAILURE + # ============================================== + # Sends red embed to Discord on build failures + # + # Only fires on main branch pushes (not PRs) + # + - name: Discord Notification - Failure + if: failure() && github.ref == 'refs/heads/main' + run: | + TIMESTAMP=$(date -u +%Y-%m-%dT%H:%M:%SZ) + curl -H "Content-Type: application/json" \ + -d '{ + "embeds": [{ + "title": "❌ Major Domo Database Build Failed", + "description": "Docker build encountered an error.", + "color": 15158332, + "fields": [ + { + "name": "Branch", + "value": "`${{ github.ref_name }}`", + "inline": true + }, + { + "name": "Commit", + "value": "`${{ github.sha }}`", + "inline": true + }, + { + "name": "Author", + "value": "${{ github.actor }}", + "inline": true + }, + { + "name": "View Logs", + "value": "[Click here](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})", + "inline": false + } + ], + "timestamp": "'"$TIMESTAMP"'" + }] + }' \ + ${{ secrets.DISCORD_WEBHOOK_URL }} + +# ============================================== +# SETUP REQUIRED +# ============================================== +# Before this workflow will work: +# +# ✅ Add secrets to Gitea repo (Settings → Secrets → Actions): +# - DOCKERHUB_USERNAME: manticorum67 +# - DOCKERHUB_TOKEN: Docker Hub access token +# - DISCORD_WEBHOOK_URL: Discord webhook for build notifications +# +# ✅ Ensure VERSION file exists in repo root (currently: 2.4.1) +# +# ============================================== +# TROUBLESHOOTING +# ============================================== +# Common issues and solutions: +# +# 1. VERSION validation failing unexpectedly +# - Ensure VERSION file contains only version number (no 'v' prefix) +# - Verify version follows semver: MAJOR.MINOR.PATCH +# +# 2. Docker Hub push failing +# - Verify DOCKERHUB_USERNAME and DOCKERHUB_TOKEN secrets are set +# - Check Docker Hub token has push permissions +# +# 3. Discord notifications not appearing +# - Test webhook URL manually with curl +# - Check webhook still exists in Discord channel settings +# - Look for HTTP error codes in Actions logs +# +# ============================================== diff --git a/GITEA_ACTIONS_SETUP.md b/GITEA_ACTIONS_SETUP.md new file mode 100644 index 0000000..d905df9 --- /dev/null +++ b/GITEA_ACTIONS_SETUP.md @@ -0,0 +1,294 @@ +# Gitea Actions Setup for Major Domo Database + +Complete CI/CD pipeline for automated Docker builds, semantic versioning, and Discord notifications. + +## Overview + +The Gitea Actions workflow in `.gitea/workflows/docker-build.yml` provides: + +- ✅ Semantic version validation on pull requests +- ✅ Automated Docker image builds +- ✅ Push to Docker Hub on main branch merges +- ✅ Discord notifications for build success/failure +- ✅ Multi-tag strategy (latest, version, version+commit) +- ✅ Build caching for faster builds + +## Initial Setup + +### 1. Create Docker Hub Access Token + +1. Go to https://hub.docker.com +2. Login → Account Settings → Security +3. Click "New Access Token" +4. Name: `gitea-major-domo-database` +5. Permissions: Read & Write +6. Copy the token (you won't see it again!) + +### 2. Add Gitea Secrets + +1. Go to https://git.manticorum.com/cal/major-domo-database +2. Navigate to: Settings → Secrets → Actions +3. Add three secrets: + +| Secret Name | Value | +|-------------|-------| +| `DOCKERHUB_USERNAME` | `manticorum67` | +| `DOCKERHUB_TOKEN` | [Docker Hub access token from step 1] | +| `DISCORD_WEBHOOK_URL` | [Discord webhook URL for build notifications] | + +### 3. Create Discord Webhook (Optional) + +If you want build notifications in Discord: + +1. Open Discord channel for CI/CD notifications +2. Right-click channel → Edit Channel → Integrations +3. Click "Create Webhook" +4. Name: `Major Domo Database CI` +5. Copy webhook URL +6. Add as `DISCORD_WEBHOOK_URL` secret in Gitea (step 2 above) + +### 4. Enable Actions in Repository + +1. Go to repository settings in Gitea +2. Navigate to "Workflow" or "Actions" section +3. Enable Actions for this repository + +## Usage + +### Creating a Pull Request + +1. Create a feature branch: + ```bash + git checkout -b feature/my-feature + ``` + +2. Make your changes + +3. **Bump the VERSION file** (required for PR approval): + ```bash + # Current version: 2.4.1 + # For bug fix: + echo "2.4.2" > VERSION + + # For new feature: + echo "2.5.0" > VERSION + + # For breaking change: + echo "3.0.0" > VERSION + ``` + +4. Commit and push: + ```bash + git add . + git commit -m "Add new feature" + git push origin feature/my-feature + ``` + +5. Create PR in Gitea + +**The workflow will:** +- ✅ Validate the VERSION bump follows semantic versioning +- ✅ Build the Docker image (but not push it) +- ❌ Block the PR if VERSION wasn't bumped or is invalid + +### Merging to Main + +When you merge the PR to main: + +**The workflow will:** +1. Build the Docker image +2. Push to Docker Hub with three tags: + - `manticorum67/major-domo-database:latest` + - `manticorum67/major-domo-database:v2.4.2` + - `manticorum67/major-domo-database:v2.4.2-a1b2c3d` +3. Send Discord notification (if configured) +4. Create build summary in Actions UI + +## Semantic Versioning Rules + +The workflow enforces strict semantic versioning: + +### Valid Version Bumps + +| Type | Example | When to Use | +|------|---------|-------------| +| **Patch** | 2.4.1 → 2.4.2 | Bug fixes, minor tweaks | +| **Minor** | 2.4.1 → 2.5.0 | New features, backward compatible | +| **Major** | 2.4.1 → 3.0.0 | Breaking changes | + +### Invalid Version Bumps + +❌ Skipping versions: `2.4.1 → 2.6.0` (skipped 2.5.0) +❌ Going backwards: `2.4.1 → 2.3.0` +❌ Not resetting: `2.4.1 → 2.5.1` (should be 2.5.0) +❌ No change: `2.4.1 → 2.4.1` + +## Manual Deployment + +Use the included `deploy.sh` script for manual deployments: + +```bash +# Deploy latest version +./deploy.sh + +# Deploy specific version +./deploy.sh v2.4.2 +``` + +The script will: +1. Check SSH connection to production server +2. Verify container exists +3. Ask for confirmation +4. Pull new image +5. Restart container +6. Show status and recent logs + +## Deployment Server Details + +- **Server**: strat-database (10.10.0.42) +- **User**: cal +- **Path**: /home/cal/container-data/sba-database +- **Container**: sba_database +- **Image**: manticorum67/major-domo-database + +## Troubleshooting + +### PR Blocked - VERSION Not Updated + +**Error:** "VERSION file has not been updated!" + +**Solution:** Update the VERSION file in your branch: +```bash +echo "2.4.2" > VERSION +git add VERSION +git commit -m "Bump version to 2.4.2" +git push +``` + +### PR Blocked - Invalid Semantic Version + +**Error:** "Invalid semantic version change!" + +**Solution:** Follow semantic versioning rules. From 2.4.1: +- Bug fix → `2.4.2` (not 2.4.3, 2.5.0, etc.) +- New feature → `2.5.0` (not 2.6.0, 2.5.1, etc.) +- Breaking change → `3.0.0` (not 4.0.0, 3.1.0, etc.) + +### Docker Hub Push Failed + +**Error:** "unauthorized: authentication required" + +**Solution:** +1. Verify `DOCKERHUB_USERNAME` and `DOCKERHUB_TOKEN` secrets are set +2. Check Docker Hub token hasn't expired +3. Regenerate token if needed and update secret + +### Discord Notifications Not Appearing + +**Problem:** Build succeeds but no Discord message + +**Solutions:** +1. Verify `DISCORD_WEBHOOK_URL` secret is set correctly +2. Test webhook manually: + ```bash + curl -H "Content-Type: application/json" \ + -d '{"content": "Test message"}' \ + YOUR_WEBHOOK_URL + ``` +3. Check webhook still exists in Discord channel settings + +### Build Failing on Main but PR Passed + +**Possible causes:** +1. Merge conflict not resolved properly +2. Dependencies changed between PR and merge +3. Docker Hub credentials invalid + +**Solution:** +1. Check Actions logs in Gitea +2. Look for specific error messages +3. Test build locally: + ```bash + docker build -t test-build . + ``` + +## Viewing Build Status + +### In Gitea + +1. Go to repository → Actions +2. Click on workflow run to see details +3. View step-by-step logs +4. Check build summary + +### In Discord + +If webhook is configured, you'll get: +- ✅ Green embed on successful builds +- ❌ Red embed on failed builds +- Version, commit, and Docker Hub link + +### On Docker Hub + +1. Go to https://hub.docker.com/r/manticorum67/major-domo-database +2. Check "Tags" tab for new versions +3. Verify timestamp matches your push + +## Advanced Usage + +### Disable Version Validation + +If you need to merge without version bump (not recommended): + +1. Edit `.gitea/workflows/docker-build.yml` +2. Delete or comment out the "Check VERSION was bumped" step +3. Commit and push + +### Disable Discord Notifications + +1. Edit `.gitea/workflows/docker-build.yml` +2. Delete both "Discord Notification" steps +3. Commit and push + +### Add Additional Tags + +Edit the "Build Docker image" step in the workflow: + +```yaml +tags: | + manticorum67/major-domo-database:latest + manticorum67/major-domo-database:v${{ steps.meta.outputs.version }} + manticorum67/major-domo-database:${{ steps.meta.outputs.version_sha }} + manticorum67/major-domo-database:stable # Add custom tag +``` + +## Workflow File Location + +The workflow is located at: +``` +.gitea/workflows/docker-build.yml +``` + +This file is tracked in git and will be used automatically by Gitea Actions when: +- You push to main branch +- You create a pull request to main branch + +## Related Documentation + +- [Docker Build Template](/mnt/NV2/Development/claude-home/server-configs/gitea/workflow-templates/docker-build-template.yml) +- [Gitea Actions Documentation](https://git.manticorum.com/gitea/docs) +- [Semantic Versioning Specification](https://semver.org/) + +## Questions or Issues? + +If you encounter problems: +1. Check Actions logs in Gitea +2. Review this troubleshooting section +3. Test components manually (Docker build, webhook, etc.) +4. Check Gitea Actions runner status + +--- + +**Last Updated:** 2026-02-04 +**Current Version:** 2.4.1 +**Template Version:** 1.0.0 (based on paper-dynasty-database) diff --git a/deploy.sh b/deploy.sh new file mode 100755 index 0000000..b44c895 --- /dev/null +++ b/deploy.sh @@ -0,0 +1,82 @@ +#!/bin/bash +# Major Domo Database - Manual Deployment Script +# +# Usage: ./deploy.sh [version] +# Example: ./deploy.sh v2.4.1 +# +# This script provides a safe, manual way to deploy Major Domo Database +# with proper checks and rollback capability. + +set -e + +VERSION=${1:-latest} +SERVER="strat-database" +SERVER_IP="10.10.0.42" +DEPLOY_PATH="/home/cal/container-data/sba-database" + +echo "🚀 Deploying Major Domo Database ${VERSION} to production" +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + +# Pre-deployment checks +echo "" +echo "📋 Pre-deployment checks..." + +# Check SSH connection +if ! ssh cal@${SERVER_IP} "echo 'SSH OK'" > /dev/null 2>&1; then + echo "❌ Cannot connect to ${SERVER}" + exit 1 +fi +echo "✅ SSH connection OK" + +# Check if container exists +if ! ssh cal@${SERVER_IP} "cd ${DEPLOY_PATH} && docker compose ps" > /dev/null 2>&1; then + echo "❌ Cannot find Major Domo Database container on ${SERVER}" + exit 1 +fi +echo "✅ Container found" + +# Confirm deployment +echo "" +echo "⚠️ This will restart the Major Domo Database API (brief downtime)" +read -p "Continue with deployment? (y/N) " -n 1 -r +echo +if [[ ! $REPLY =~ ^[Yy]$ ]]; then + echo "❌ Deployment cancelled" + exit 1 +fi + +# Deploy +echo "" +echo "📥 Pulling image manticorum67/major-domo-database:${VERSION}..." +ssh cal@${SERVER_IP} << EOF + cd ${DEPLOY_PATH} + + # Pull new image + docker compose pull + + # Stop old container + echo "🛑 Stopping container..." + docker compose down + + # Start new container + echo "▶️ Starting container..." + docker compose up -d + + # Wait for startup + sleep 5 + + # Check status + echo "" + echo "📊 Container status:" + docker compose ps + + echo "" + echo "📝 Recent logs:" + docker compose logs --tail 20 +EOF + +echo "" +echo "✅ Deployment complete!" +echo "" +echo "To check logs: ssh ${SERVER} 'cd ${DEPLOY_PATH} && docker compose logs -f'" +echo "To rollback: ssh ${SERVER} 'cd ${DEPLOY_PATH} && docker compose down && docker compose up -d'"