init projectmycelium
This commit is contained in:
139
scripts/README.md
Normal file
139
scripts/README.md
Normal file
@@ -0,0 +1,139 @@
|
||||
# Project Mycelium Deployment Scripts
|
||||
|
||||
This directory contains improved deployment scripts for the Project Mycelium that handle repository and directory management robustly.
|
||||
|
||||
## Scripts Overview
|
||||
|
||||
### Development Environment
|
||||
- **Script**: [`tf-marketplace-dev.sh`](tf-marketplace-dev.sh)
|
||||
- **Domain**: dev.threefold.pro
|
||||
- **Port**: 9998
|
||||
- **Branch**: development
|
||||
- **Service**: tf-marketplace-dev
|
||||
|
||||
### Production Environment
|
||||
- **Script**: [`tf-marketplace-prod.sh`](tf-marketplace-prod.sh)
|
||||
- **Domain**: threefold.pro
|
||||
- **Port**: 9999
|
||||
- **Branch**: main
|
||||
- **Service**: tf-marketplace
|
||||
|
||||
## Key Improvements
|
||||
|
||||
### 1. Robust Directory/Repository Handling
|
||||
- ✅ Creates directory structure if it doesn't exist
|
||||
- ✅ Handles both fresh clones and existing repositories
|
||||
- ✅ Properly updates existing repositories with `git reset --hard`
|
||||
- ✅ Validates git repository integrity
|
||||
- ✅ Uses correct working directories throughout
|
||||
|
||||
### 2. Error Handling
|
||||
- ✅ Exit on error (`set -e`)
|
||||
- ✅ Validates cargo availability
|
||||
- ✅ Checks for Cargo.toml presence
|
||||
- ✅ Proper error messages with context
|
||||
|
||||
### 3. Environment-Specific Configuration
|
||||
- ✅ Separate scripts for dev and prod environments
|
||||
- ✅ Correct ports (9998 for dev, 9999 for prod)
|
||||
- ✅ Correct branches (development for dev, main for prod)
|
||||
- ✅ Clear environment identification in logs
|
||||
|
||||
## Installation
|
||||
|
||||
### 1. Copy Scripts to Server
|
||||
```bash
|
||||
# Copy the deployment scripts with explicit naming
|
||||
sudo cp tf-marketplace-dev.sh /etc/zinit/cmds/tf-marketplace-dev.sh
|
||||
sudo cp tf-marketplace-prod.sh /etc/zinit/cmds/tf-marketplace-prod.sh
|
||||
sudo chmod +x /etc/zinit/cmds/tf-marketplace-dev.sh
|
||||
sudo chmod +x /etc/zinit/cmds/tf-marketplace-prod.sh
|
||||
```
|
||||
|
||||
### 2. Install Zinit Service Definitions
|
||||
```bash
|
||||
# Copy service definitions from config directory
|
||||
sudo cp ../config/zinit/tf-marketplace-dev.yaml /etc/zinit/tf-marketplace-dev.yaml
|
||||
sudo cp ../config/zinit/tf-marketplace-prod.yaml /etc/zinit/tf-marketplace-prod.yaml
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Development Deployment
|
||||
```bash
|
||||
# Start development service
|
||||
zinit start tf-marketplace-dev
|
||||
|
||||
# Monitor development service
|
||||
zinit monitor tf-marketplace-dev
|
||||
|
||||
# View development logs
|
||||
zinit log tf-marketplace-dev
|
||||
```
|
||||
|
||||
### Production Deployment
|
||||
```bash
|
||||
# Start production service
|
||||
zinit start tf-marketplace
|
||||
|
||||
# Monitor production service
|
||||
zinit monitor tf-marketplace
|
||||
|
||||
# View production logs
|
||||
zinit log tf-marketplace
|
||||
```
|
||||
|
||||
## Comparison with Original Script
|
||||
|
||||
### Original Issues Fixed
|
||||
|
||||
1. **Directory Check Logic**:
|
||||
- ❌ Original: `[ ! -d "$DIR_NAME" ] && git clone "$REPO_URL"`
|
||||
- ✅ Fixed: Proper path handling and working directory management
|
||||
|
||||
2. **Missing Updates**:
|
||||
- ❌ Original: No git pull for existing repositories
|
||||
- ✅ Fixed: `git reset --hard origin/branch` for clean updates
|
||||
|
||||
3. **Error Handling**:
|
||||
- ❌ Original: No error checking
|
||||
- ✅ Fixed: Comprehensive error handling and validation
|
||||
|
||||
4. **Path Consistency**:
|
||||
- ❌ Original: Mixed path conventions
|
||||
- ✅ Fixed: Consistent with existing deployment infrastructure
|
||||
|
||||
## Monitoring and Troubleshooting
|
||||
|
||||
### Check Service Status
|
||||
```bash
|
||||
zinit list | grep tf-marketplace
|
||||
```
|
||||
|
||||
### View Real-time Logs
|
||||
```bash
|
||||
# Development
|
||||
tail -f /var/log/zinit/tf-marketplace-dev.log
|
||||
|
||||
# Production
|
||||
tail -f /var/log/zinit/tf-marketplace.log
|
||||
```
|
||||
|
||||
### Manual Testing
|
||||
```bash
|
||||
# Test development script manually
|
||||
sudo /etc/zinit/cmds/tf-marketplace-dev.sh
|
||||
|
||||
# Test production script manually
|
||||
sudo /etc/zinit/cmds/tf-marketplace.sh
|
||||
```
|
||||
|
||||
## Integration with Existing Infrastructure
|
||||
|
||||
These scripts are designed to work seamlessly with:
|
||||
- Existing Makefile deployment targets ([`deploy-dev`](../Makefile:14), [`deploy-prod`](../Makefile:19))
|
||||
- Current Caddy configuration
|
||||
- Existing zinit service management
|
||||
- Current directory structure conventions
|
||||
|
||||
The scripts maintain compatibility with the existing deployment workflow while providing more robust error handling and repository management.
|
155
scripts/deploy.sh
Normal file
155
scripts/deploy.sh
Normal file
@@ -0,0 +1,155 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Exit on error
|
||||
set -e
|
||||
|
||||
echo "===== Project Mycelium Simplified Deployment Script ====="
|
||||
echo "Date: $(date)"
|
||||
echo "User: $(whoami)"
|
||||
|
||||
# Check required commands
|
||||
for cmd in git cargo zinit caddy; do
|
||||
if ! command -v $cmd &> /dev/null; then
|
||||
echo "Error: Required command '$cmd' not found."
|
||||
echo "Please install all prerequisites before running this script."
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
# Variables
|
||||
REPO_URL="https://git.ourworld.tf/tfgrid_research/projectmycelium"
|
||||
INSTALL_DIR="/root/code/github.com/tfgrid_research/projectmycelium"
|
||||
SERVICE_NAME="tf-marketplace"
|
||||
PORT=9999
|
||||
DOMAIN="example.com" # Replace with your actual domain
|
||||
|
||||
# Prompt for domain name
|
||||
read -p "Enter your domain name [default: $DOMAIN]: " input_domain
|
||||
DOMAIN=${input_domain:-$DOMAIN}
|
||||
|
||||
# Generate a random secret key if not provided
|
||||
if [ -z "$SECRET_KEY" ]; then
|
||||
SECRET_KEY=$(openssl rand -base64 32)
|
||||
echo "Generated random SECRET_KEY"
|
||||
fi
|
||||
|
||||
echo "===== Cloning Repository ====="
|
||||
mkdir -p $(dirname "$INSTALL_DIR")
|
||||
if [ -d "$INSTALL_DIR" ]; then
|
||||
echo "Directory already exists. Updating repository..."
|
||||
cd "$INSTALL_DIR"
|
||||
git checkout main
|
||||
git fetch
|
||||
git pull
|
||||
else
|
||||
echo "Cloning repository..."
|
||||
git clone "$REPO_URL" "$INSTALL_DIR"
|
||||
cd "$INSTALL_DIR"
|
||||
git checkout main
|
||||
fi
|
||||
|
||||
echo "===== Creating zinit Service ====="
|
||||
# Create service script directory
|
||||
sudo mkdir -p /etc/zinit/cmds
|
||||
|
||||
# Create service script
|
||||
cat > /tmp/tf-marketplace.sh << EOF
|
||||
#!/bin/bash
|
||||
cd $INSTALL_DIR
|
||||
export RUST_LOG=info
|
||||
export SECRET_KEY="$SECRET_KEY"
|
||||
exec /root/.cargo/bin/cargo run --release -- --port $PORT
|
||||
EOF
|
||||
|
||||
sudo cp /tmp/tf-marketplace.sh /etc/zinit/cmds/$SERVICE_NAME.sh
|
||||
sudo chmod +x /etc/zinit/cmds/$SERVICE_NAME.sh
|
||||
rm /tmp/tf-marketplace.sh
|
||||
|
||||
# Create zinit service definition
|
||||
cat > /tmp/tf-marketplace.yaml << EOF
|
||||
exec: "/bin/bash -c /etc/zinit/cmds/$SERVICE_NAME.sh"
|
||||
EOF
|
||||
|
||||
sudo cp /tmp/tf-marketplace.yaml /etc/zinit/$SERVICE_NAME.yaml
|
||||
rm /tmp/tf-marketplace.yaml
|
||||
|
||||
echo "===== Configuring Caddy ====="
|
||||
cat > /tmp/Caddyfile << EOF
|
||||
$DOMAIN {
|
||||
# Enable compression
|
||||
encode gzip zstd
|
||||
|
||||
# Serve static files
|
||||
handle /static/* {
|
||||
root * $INSTALL_DIR/src
|
||||
file_server
|
||||
}
|
||||
|
||||
# Reverse proxy to the application
|
||||
reverse_proxy localhost:$PORT {
|
||||
# Customize timeouts if needed
|
||||
timeout 2m
|
||||
|
||||
# Enable WebSocket support
|
||||
header_up Connection {>Connection}
|
||||
header_up Upgrade {>Upgrade}
|
||||
}
|
||||
|
||||
# Add security headers
|
||||
header {
|
||||
# Enable HSTS
|
||||
Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
|
||||
|
||||
# Prevent MIME type sniffing
|
||||
X-Content-Type-Options "nosniff"
|
||||
|
||||
# Protect against clickjacking
|
||||
X-Frame-Options "SAMEORIGIN"
|
||||
|
||||
# Enable XSS protection
|
||||
X-XSS-Protection "1; mode=block"
|
||||
|
||||
# Control browser features
|
||||
Permissions-Policy "geolocation=(), midi=(), camera=(), usb=(), magnetometer=(), accelerometer=(), gyroscope=(), payment=()"
|
||||
|
||||
# Remove server information
|
||||
-Server
|
||||
}
|
||||
|
||||
# Log access
|
||||
log {
|
||||
output file /var/log/caddy/access.log
|
||||
format json
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
sudo mkdir -p /etc/caddy
|
||||
sudo cp /tmp/Caddyfile /etc/caddy/Caddyfile
|
||||
rm /tmp/Caddyfile
|
||||
|
||||
echo "===== Starting Services ====="
|
||||
# Start the marketplace service
|
||||
zinit start $SERVICE_NAME
|
||||
|
||||
# Restart Caddy to load new configuration
|
||||
zinit restart caddy
|
||||
|
||||
echo "===== Configuring Firewall ====="
|
||||
if command -v ufw &> /dev/null; then
|
||||
sudo ufw allow http
|
||||
sudo ufw allow https
|
||||
echo "Firewall configured to allow HTTP and HTTPS traffic."
|
||||
fi
|
||||
|
||||
echo "===== Deployment Complete ====="
|
||||
echo "Project Mycelium has been deployed at: https://$DOMAIN"
|
||||
echo
|
||||
echo "You can monitor the application with:"
|
||||
echo " zinit list"
|
||||
echo " zinit log $SERVICE_NAME"
|
||||
echo " tail -f /var/log/zinit/$SERVICE_NAME.log"
|
||||
echo
|
||||
echo "Caddy status and logs:"
|
||||
echo " zinit status caddy"
|
||||
echo " zinit log caddy"
|
65
scripts/dev/cargo-errors.sh
Executable file
65
scripts/dev/cargo-errors.sh
Executable file
@@ -0,0 +1,65 @@
|
||||
#!/usr/bin/env bash
|
||||
# Summarize Rust compiler errors into a clean, readable log.
|
||||
# Prefers cargo JSON + jq; falls back to sed/awk parser if jq is unavailable.
|
||||
# Output file: /tmp/cargo_errors_only.log (override with OUT env var)
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
OUT=${OUT:-/tmp/cargo_errors_only.log}
|
||||
PROJECT_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || echo "")
|
||||
if [[ -n "$PROJECT_ROOT" ]]; then
|
||||
cd "$PROJECT_ROOT"
|
||||
fi
|
||||
|
||||
# Ensure colorless output from cargo to avoid ANSI in fallback
|
||||
export CARGO_TERM_COLOR=never
|
||||
|
||||
# Function: JSON mode (best)
|
||||
run_json_mode() {
|
||||
# Capture cargo's exit code from the first command in the pipeline
|
||||
set +e
|
||||
set +o pipefail
|
||||
cargo check --message-format=json -q "$@" 2>/dev/null \
|
||||
| jq -r 'select(.reason=="compiler-message" and .message.level=="error") | .message.rendered' \
|
||||
| tee "$OUT"
|
||||
local cargo_status=${PIPESTATUS[0]}
|
||||
set -o pipefail
|
||||
set -e
|
||||
return "$cargo_status"
|
||||
}
|
||||
|
||||
# Function: Fallback parser (no jq required)
|
||||
run_fallback_mode() {
|
||||
# We intentionally capture stderr (diagnostics) and stdout
|
||||
set +e
|
||||
set +o pipefail
|
||||
cargo check -q "$@" 2>&1 \
|
||||
| sed -r 's/\x1B\[[0-9;]*[mK]//g' \
|
||||
| awk '
|
||||
BEGIN{inerr=0}
|
||||
/^warning:/{inerr=0; next}
|
||||
/^error(\[|:)/{inerr=1}
|
||||
# Drop cargo/rustc warning summaries while still inside an error block
|
||||
inerr && /[0-9]+ warnings? emitted/ {next}
|
||||
inerr{print}
|
||||
' \
|
||||
| tee "$OUT"
|
||||
local cargo_status=${PIPESTATUS[0]}
|
||||
set -o pipefail
|
||||
set -e
|
||||
return "$cargo_status"
|
||||
}
|
||||
|
||||
status=0
|
||||
if command -v jq >/dev/null 2>&1; then
|
||||
if ! run_json_mode "$@"; then
|
||||
status=$?
|
||||
fi
|
||||
else
|
||||
echo "INFO: jq not found; using fallback parser (install jq for best results)." >&2
|
||||
if ! run_fallback_mode "$@"; then
|
||||
status=$?
|
||||
fi
|
||||
fi
|
||||
|
||||
exit "$status"
|
194
scripts/fix_user_data.py
Normal file
194
scripts/fix_user_data.py
Normal file
@@ -0,0 +1,194 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Industry Standard Data Validation and Repair Tool
|
||||
Comprehensive fix for ThreeFold Marketplace user data files
|
||||
"""
|
||||
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
def normalize_activity_type(activity_type):
|
||||
"""Normalize activity type to match enum variants"""
|
||||
mapping = {
|
||||
"ServiceProgress": "ServiceCreated",
|
||||
"AppDeployment": "Deployment",
|
||||
"AppCreated": "AppPublished",
|
||||
"NodeCreated": "NodeAdded",
|
||||
"NodeModified": "NodeUpdated",
|
||||
"WalletDeposit": "WalletTransaction",
|
||||
"WalletWithdraw": "WalletTransaction",
|
||||
"Payment": "WalletTransaction",
|
||||
"ProfileChanged": "ProfileUpdate",
|
||||
"ConfigChange": "SettingsChange",
|
||||
"BrowseMarketplace": "MarketplaceView",
|
||||
"SliceCreation": "SliceCreated",
|
||||
"SliceAssignment": "SliceAllocated",
|
||||
"SliceRemoval": "SliceReleased",
|
||||
}
|
||||
|
||||
# Valid variants pass through unchanged
|
||||
valid_variants = {
|
||||
"Login", "Purchase", "Deployment", "ServiceCreated", "AppPublished",
|
||||
"NodeAdded", "NodeUpdated", "WalletTransaction", "ProfileUpdate",
|
||||
"SettingsChange", "MarketplaceView", "SliceCreated", "SliceAllocated",
|
||||
"SliceReleased"
|
||||
}
|
||||
|
||||
if activity_type in valid_variants:
|
||||
return activity_type
|
||||
|
||||
return mapping.get(activity_type, "ProfileUpdate")
|
||||
|
||||
def infer_category_from_activity_type(activity_type):
|
||||
"""Infer category from activity type"""
|
||||
mapping = {
|
||||
"ServiceCreated": "Service",
|
||||
"AppPublished": "App",
|
||||
"Deployment": "App",
|
||||
"NodeAdded": "Farming",
|
||||
"NodeUpdated": "Farming",
|
||||
"SliceCreated": "Farming",
|
||||
"SliceAllocated": "Farming",
|
||||
"SliceReleased": "Farming",
|
||||
"WalletTransaction": "Finance",
|
||||
"Login": "Account",
|
||||
"ProfileUpdate": "Account",
|
||||
"SettingsChange": "Account",
|
||||
"Purchase": "Marketplace",
|
||||
"MarketplaceView": "Marketplace",
|
||||
}
|
||||
|
||||
return mapping.get(activity_type, "General")
|
||||
|
||||
def repair_user_activities(data):
|
||||
"""Repair user activities to match schema"""
|
||||
if "user_activities" not in data or data["user_activities"] is None:
|
||||
data["user_activities"] = []
|
||||
return
|
||||
|
||||
for activity in data["user_activities"]:
|
||||
if activity is None:
|
||||
continue
|
||||
|
||||
# Fix activity_type
|
||||
if "activity_type" in activity and activity["activity_type"] is not None:
|
||||
activity["activity_type"] = normalize_activity_type(activity["activity_type"])
|
||||
|
||||
# Ensure category field exists
|
||||
if "category" not in activity:
|
||||
activity_type = activity.get("activity_type", "Service")
|
||||
if activity_type is not None:
|
||||
activity["category"] = infer_category_from_activity_type(activity_type)
|
||||
else:
|
||||
activity["category"] = "General"
|
||||
|
||||
def repair_farmer_settings(data):
|
||||
"""Repair farmer settings to include required fields"""
|
||||
if "farmer_settings" not in data or data["farmer_settings"] is None:
|
||||
data["farmer_settings"] = {}
|
||||
|
||||
farmer_settings = data["farmer_settings"]
|
||||
|
||||
# Ensure minimum_deployment_duration exists
|
||||
if "minimum_deployment_duration" not in farmer_settings:
|
||||
farmer_settings["minimum_deployment_duration"] = 24
|
||||
|
||||
# Ensure preferred_regions exists
|
||||
if "preferred_regions" not in farmer_settings:
|
||||
farmer_settings["preferred_regions"] = ["NA", "EU"]
|
||||
|
||||
def ensure_required_fields(data):
|
||||
"""Ensure all required top-level fields exist"""
|
||||
required_fields = {
|
||||
"user_email": "unknown@example.com",
|
||||
"wallet_balance": "0.0",
|
||||
"transactions": [],
|
||||
"services": [],
|
||||
"service_requests": [],
|
||||
"apps": [],
|
||||
"app_deployments": [],
|
||||
"nodes": [],
|
||||
"farmer_earnings": [],
|
||||
"user_activities": [],
|
||||
"pool_positions": {},
|
||||
}
|
||||
|
||||
for field, default_value in required_fields.items():
|
||||
if field not in data:
|
||||
data[field] = default_value
|
||||
|
||||
def validate_and_repair_user_data(json_str):
|
||||
"""Validate and repair user data JSON"""
|
||||
try:
|
||||
data = json.loads(json_str)
|
||||
|
||||
repair_user_activities(data)
|
||||
repair_farmer_settings(data)
|
||||
ensure_required_fields(data)
|
||||
|
||||
return json.dumps(data, indent=2, ensure_ascii=False)
|
||||
except json.JSONDecodeError as e:
|
||||
raise ValueError(f"Invalid JSON: {e}")
|
||||
|
||||
def validate_all_user_files():
|
||||
"""Validate all user data files"""
|
||||
user_data_dir = Path("user_data")
|
||||
if not user_data_dir.exists():
|
||||
raise FileNotFoundError("user_data directory not found")
|
||||
|
||||
results = []
|
||||
|
||||
for json_file in user_data_dir.glob("*.json"):
|
||||
filename = json_file.name
|
||||
|
||||
try:
|
||||
content = json_file.read_text(encoding='utf-8')
|
||||
repaired_content = validate_and_repair_user_data(content)
|
||||
|
||||
# Write back the repaired content
|
||||
json_file.write_text(repaired_content, encoding='utf-8')
|
||||
results.append(f"✅ {filename}: Successfully validated and repaired")
|
||||
|
||||
except Exception as e:
|
||||
results.append(f"❌ {filename}: {e}")
|
||||
|
||||
return results
|
||||
|
||||
def main():
|
||||
print("🔧 ThreeFold Marketplace Data Validator")
|
||||
print("========================================")
|
||||
print()
|
||||
|
||||
try:
|
||||
results = validate_all_user_files()
|
||||
|
||||
print("📊 Validation Results:")
|
||||
print()
|
||||
for result in results:
|
||||
print(f" {result}")
|
||||
print()
|
||||
|
||||
success_count = sum(1 for r in results if r.startswith("✅"))
|
||||
error_count = sum(1 for r in results if r.startswith("❌"))
|
||||
|
||||
print("📈 Summary:")
|
||||
print(f" ✅ Successfully processed: {success_count}")
|
||||
print(f" ❌ Errors encountered: {error_count}")
|
||||
|
||||
if error_count == 0:
|
||||
print()
|
||||
print("🎉 All user data files are now valid and ready for use!")
|
||||
return 0
|
||||
else:
|
||||
print()
|
||||
print("⚠️ Some files had errors. Please review the output above.")
|
||||
return 1
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Validation failed: {e}")
|
||||
return 1
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
10
scripts/start.sh
Executable file
10
scripts/start.sh
Executable file
@@ -0,0 +1,10 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Get the directory of the script and change to it
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
export SECRET_KEY=1234
|
||||
export GITEA_CLIENT_ID=""
|
||||
export GITEA_CLIENT_SECRET=""
|
||||
export GITEA_INSTANCE_URL="https://git.ourworld.tf"
|
||||
cargo run
|
10
scripts/start_with_gitea.sh
Executable file
10
scripts/start_with_gitea.sh
Executable file
@@ -0,0 +1,10 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Get the directory of the script and change to it
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
export GITEA_CLIENT_ID="9f409b35-6258-4ac3-8370-05adc187c1f5"
|
||||
export GITEA_CLIENT_SECRET="gto_4s77ae33m5ernlf2423wx6wjyyqatqoe567rym7fcu3sqmu5azea"
|
||||
export GITEA_INSTANCE_URL="https://git.ourworld.tf"
|
||||
export APP_URL="http://localhost:9999"
|
||||
cargo run
|
239
scripts/tf-marketplace-dev.sh
Normal file
239
scripts/tf-marketplace-dev.sh
Normal file
@@ -0,0 +1,239 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Exit on error
|
||||
set -e
|
||||
|
||||
echo "===== Project Mycelium Development Deployment ====="
|
||||
echo "Environment: dev.threefold.pro"
|
||||
echo "Date: $(date)"
|
||||
echo "User: $(whoami)"
|
||||
|
||||
# Load deployment credentials for git authentication
|
||||
DEPLOY_ENV="/tmp/tf-marketplace-deploy.env"
|
||||
if [ -f "$DEPLOY_ENV" ]; then
|
||||
echo "Loading deployment credentials from $DEPLOY_ENV"
|
||||
source "$DEPLOY_ENV"
|
||||
else
|
||||
echo "Warning: Deployment credentials not found at $DEPLOY_ENV"
|
||||
echo "Please run 'make deploy-setup' to copy deployment credentials"
|
||||
fi
|
||||
|
||||
# Variables
|
||||
BASE_DIR="/root/code/git.ourworld.tf/tfgrid_research"
|
||||
INSTALL_DIR="$BASE_DIR/dev/projectmycelium"
|
||||
BRANCH="development"
|
||||
PORT=9998
|
||||
DOMAIN="dev.threefold.pro"
|
||||
|
||||
# Construct authenticated Git URL if credentials are available
|
||||
if [ -n "$GITEA_USER" ] && [ -n "$GITEA_TOKEN" ]; then
|
||||
REPO_URL="https://${GITEA_USER}:${GITEA_TOKEN}@git.ourworld.tf/tfgrid_research/projectmycelium.git"
|
||||
echo "Using authenticated Git access"
|
||||
else
|
||||
REPO_URL="https://git.ourworld.tf/tfgrid_research/projectmycelium.git"
|
||||
echo "Warning: No Gitea credentials found, using unauthenticated access"
|
||||
fi
|
||||
|
||||
echo "===== Setting up directory structure ====="
|
||||
# Create base directory if it doesn't exist
|
||||
mkdir -p "$BASE_DIR"
|
||||
cd "$BASE_DIR"
|
||||
|
||||
echo "===== Repository management ====="
|
||||
if [ -d "$INSTALL_DIR" ]; then
|
||||
echo "Directory exists. Checking if it's a git repository..."
|
||||
cd "$INSTALL_DIR"
|
||||
|
||||
# Check if it's a git repository
|
||||
if [ -d ".git" ]; then
|
||||
echo "Valid git repository found. Updating..."
|
||||
# Clean up git state
|
||||
if [ -f ".git/index.lock" ]; then
|
||||
echo "Removing git lock file..."
|
||||
rm -f ".git/index.lock"
|
||||
fi
|
||||
|
||||
# Clean any uncommitted changes
|
||||
git reset --hard HEAD 2>/dev/null || true
|
||||
git clean -fd 2>/dev/null || true
|
||||
|
||||
# Update remote URL with authentication if available
|
||||
if [ -n "$GITEA_USER" ] && [ -n "$GITEA_TOKEN" ]; then
|
||||
git remote set-url origin "$REPO_URL"
|
||||
fi
|
||||
|
||||
git fetch origin
|
||||
git checkout "$BRANCH"
|
||||
git reset --hard "origin/$BRANCH"
|
||||
echo "Repository updated to latest $BRANCH branch"
|
||||
else
|
||||
echo "Directory exists but is not a git repository. Removing and cloning fresh..."
|
||||
cd "$BASE_DIR"
|
||||
rm -rf "$INSTALL_DIR"
|
||||
echo "Cloning repository..."
|
||||
git clone "$REPO_URL" "$INSTALL_DIR"
|
||||
cd "$INSTALL_DIR"
|
||||
git checkout "$BRANCH"
|
||||
echo "Repository cloned and checked out to $BRANCH branch"
|
||||
fi
|
||||
else
|
||||
echo "Cloning repository..."
|
||||
git clone "$REPO_URL" "$INSTALL_DIR"
|
||||
cd "$INSTALL_DIR"
|
||||
git checkout "$BRANCH"
|
||||
echo "Repository cloned and checked out to $BRANCH branch"
|
||||
fi
|
||||
|
||||
echo "===== Cleaning build cache ====="
|
||||
# Clean cargo cache to ensure fresh build
|
||||
echo "Cleaning cargo build cache..."
|
||||
"$CARGO_CMD" clean 2>/dev/null || true
|
||||
|
||||
echo "===== Verifying environment ====="
|
||||
echo "Current PATH: $PATH"
|
||||
echo "Current USER: $(whoami)"
|
||||
echo "Current HOME: $HOME"
|
||||
|
||||
# Find cargo using multiple methods with robust detection
|
||||
CARGO_CMD=""
|
||||
|
||||
# Method 1: Check if cargo is in PATH
|
||||
echo "Checking for cargo in PATH..."
|
||||
if command -v cargo &> /dev/null; then
|
||||
CARGO_CMD="cargo"
|
||||
echo "✓ Found cargo in PATH: $(which cargo)"
|
||||
# Method 2: Check common Rust installation locations
|
||||
elif [ -f "$HOME/.cargo/bin/cargo" ]; then
|
||||
CARGO_CMD="$HOME/.cargo/bin/cargo"
|
||||
echo "✓ Found cargo at $HOME/.cargo/bin/cargo"
|
||||
# Add to PATH for this session
|
||||
export PATH="$HOME/.cargo/bin:$PATH"
|
||||
# Method 3: Check root cargo location
|
||||
elif [ -f "/root/.cargo/bin/cargo" ]; then
|
||||
CARGO_CMD="/root/.cargo/bin/cargo"
|
||||
echo "✓ Found cargo at /root/.cargo/bin/cargo"
|
||||
export PATH="/root/.cargo/bin:$PATH"
|
||||
# Method 4: Check system-wide installation
|
||||
elif [ -f "/usr/local/bin/cargo" ]; then
|
||||
CARGO_CMD="/usr/local/bin/cargo"
|
||||
echo "✓ Found cargo at /usr/local/bin/cargo"
|
||||
elif [ -f "/usr/bin/cargo" ]; then
|
||||
CARGO_CMD="/usr/bin/cargo"
|
||||
echo "✓ Found cargo at /usr/bin/cargo"
|
||||
# Method 5: Use whereis to find cargo
|
||||
else
|
||||
echo "Searching for cargo with whereis..."
|
||||
CARGO_PATHS=$(whereis cargo 2>/dev/null | cut -d' ' -f2-)
|
||||
echo "whereis found: $CARGO_PATHS"
|
||||
|
||||
for path in $CARGO_PATHS; do
|
||||
if [ -f "$path" ] && [ -x "$path" ]; then
|
||||
CARGO_CMD="$path"
|
||||
echo "✓ Found executable cargo at $path"
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
# Method 6: Last resort - try to find cargo anywhere
|
||||
if [ -z "$CARGO_CMD" ]; then
|
||||
echo "Searching for cargo with find..."
|
||||
FOUND_CARGO=$(find /usr /root /home -name "cargo" -type f -executable 2>/dev/null | head -1)
|
||||
if [ -n "$FOUND_CARGO" ] && [ -f "$FOUND_CARGO" ]; then
|
||||
CARGO_CMD="$FOUND_CARGO"
|
||||
echo "✓ Found cargo at $FOUND_CARGO"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Final verification
|
||||
if [ -n "$CARGO_CMD" ]; then
|
||||
echo "Using cargo command: $CARGO_CMD"
|
||||
echo "Testing cargo command..."
|
||||
if "$CARGO_CMD" --version &> /dev/null; then
|
||||
echo "✓ Cargo is working: $($CARGO_CMD --version)"
|
||||
else
|
||||
echo "✗ Cargo command failed to execute"
|
||||
CARGO_CMD=""
|
||||
fi
|
||||
fi
|
||||
|
||||
# If still no cargo found, try installation
|
||||
if [ -z "$CARGO_CMD" ]; then
|
||||
echo "Cargo not found anywhere. Installing Rust toolchain..."
|
||||
|
||||
# Install Rust using rustup
|
||||
if ! command -v rustup &> /dev/null; then
|
||||
echo "Installing rustup..."
|
||||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain stable
|
||||
|
||||
# Source the cargo environment
|
||||
if [ -f "$HOME/.cargo/env" ]; then
|
||||
source "$HOME/.cargo/env"
|
||||
fi
|
||||
|
||||
# Add to PATH
|
||||
export PATH="$HOME/.cargo/bin:$PATH"
|
||||
fi
|
||||
|
||||
# Verify installation
|
||||
if command -v cargo &> /dev/null; then
|
||||
CARGO_CMD="cargo"
|
||||
echo "✓ Rust toolchain installed successfully"
|
||||
elif [ -f "$HOME/.cargo/bin/cargo" ]; then
|
||||
CARGO_CMD="$HOME/.cargo/bin/cargo"
|
||||
export PATH="$HOME/.cargo/bin:$PATH"
|
||||
echo "✓ Rust toolchain installed successfully"
|
||||
else
|
||||
echo "✗ Failed to install Rust toolchain"
|
||||
echo "Please install Rust manually: https://rustup.rs/"
|
||||
echo "Waiting 30 seconds before retrying..."
|
||||
sleep 30
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check if we're in the right directory
|
||||
if [ ! -f "Cargo.toml" ]; then
|
||||
echo "Error: Cargo.toml not found. Are we in the right directory?"
|
||||
pwd
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "===== Setting up application environment ====="
|
||||
# Generate SECRET_KEY if .env doesn't exist or doesn't have a valid key
|
||||
if [ ! -f ".env" ] || ! grep -q "^SECRET_KEY=" .env || grep -q "your_secret_key_here" .env; then
|
||||
echo "Generating SECRET_KEY for application..."
|
||||
SECRET_KEY=$(openssl rand -base64 64 | tr -d '\n')
|
||||
|
||||
# Create .env from template if it doesn't exist
|
||||
if [ ! -f ".env" ] && [ -f ".env.example" ]; then
|
||||
cp .env.example .env
|
||||
fi
|
||||
|
||||
# Update or add SECRET_KEY
|
||||
if [ -f ".env" ]; then
|
||||
if grep -q "^SECRET_KEY=" .env; then
|
||||
sed -i "s/^SECRET_KEY=.*/SECRET_KEY=$SECRET_KEY/" .env
|
||||
else
|
||||
echo "SECRET_KEY=$SECRET_KEY" >> .env
|
||||
fi
|
||||
else
|
||||
echo "SECRET_KEY=$SECRET_KEY" > .env
|
||||
fi
|
||||
echo "SECRET_KEY generated and saved to .env"
|
||||
else
|
||||
echo "Using existing SECRET_KEY from .env"
|
||||
fi
|
||||
|
||||
echo "===== Starting application ====="
|
||||
echo "Running Project Mycelium on port $PORT..."
|
||||
echo "Working directory: $(pwd)"
|
||||
echo "Branch: $(git branch --show-current)"
|
||||
echo "Commit: $(git rev-parse --short HEAD)"
|
||||
|
||||
# Set environment variables
|
||||
export RUST_LOG=info
|
||||
|
||||
# Run the application (following existing pattern)
|
||||
git checkout "$BRANCH"
|
||||
exec "$CARGO_CMD" run --release --bin projectmycelium -- --port "$PORT"
|
239
scripts/tf-marketplace-prod.sh
Normal file
239
scripts/tf-marketplace-prod.sh
Normal file
@@ -0,0 +1,239 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Exit on error
|
||||
set -e
|
||||
|
||||
echo "===== Project Mycelium Production Deployment ====="
|
||||
echo "Environment: threefold.pro"
|
||||
echo "Date: $(date)"
|
||||
echo "User: $(whoami)"
|
||||
|
||||
# Load deployment credentials for git authentication
|
||||
DEPLOY_ENV="/tmp/tf-marketplace-deploy.env"
|
||||
if [ -f "$DEPLOY_ENV" ]; then
|
||||
echo "Loading deployment credentials from $DEPLOY_ENV"
|
||||
source "$DEPLOY_ENV"
|
||||
else
|
||||
echo "Warning: Deployment credentials not found at $DEPLOY_ENV"
|
||||
echo "Please run 'make deploy-setup' to copy deployment credentials"
|
||||
fi
|
||||
|
||||
# Variables
|
||||
BASE_DIR="/root/code/git.ourworld.tf/tfgrid_research"
|
||||
INSTALL_DIR="$BASE_DIR/prod/projectmycelium"
|
||||
BRANCH="main"
|
||||
PORT=9999
|
||||
DOMAIN="threefold.pro"
|
||||
|
||||
# Construct authenticated Git URL if credentials are available
|
||||
if [ -n "$GITEA_USER" ] && [ -n "$GITEA_TOKEN" ]; then
|
||||
REPO_URL="https://${GITEA_USER}:${GITEA_TOKEN}@git.ourworld.tf/tfgrid_research/projectmycelium.git"
|
||||
echo "Using authenticated Git access"
|
||||
else
|
||||
REPO_URL="https://git.ourworld.tf/tfgrid_research/projectmycelium.git"
|
||||
echo "Warning: No Gitea credentials found, using unauthenticated access"
|
||||
fi
|
||||
|
||||
echo "===== Setting up directory structure ====="
|
||||
# Create base directory if it doesn't exist
|
||||
mkdir -p "$BASE_DIR"
|
||||
cd "$BASE_DIR"
|
||||
|
||||
echo "===== Repository management ====="
|
||||
if [ -d "$INSTALL_DIR" ]; then
|
||||
echo "Directory exists. Checking if it's a git repository..."
|
||||
cd "$INSTALL_DIR"
|
||||
|
||||
# Check if it's a git repository
|
||||
if [ -d ".git" ]; then
|
||||
echo "Valid git repository found. Updating..."
|
||||
# Clean up git state
|
||||
if [ -f ".git/index.lock" ]; then
|
||||
echo "Removing git lock file..."
|
||||
rm -f ".git/index.lock"
|
||||
fi
|
||||
|
||||
# Clean any uncommitted changes
|
||||
git reset --hard HEAD 2>/dev/null || true
|
||||
git clean -fd 2>/dev/null || true
|
||||
|
||||
# Update remote URL with authentication if available
|
||||
if [ -n "$GITEA_USER" ] && [ -n "$GITEA_TOKEN" ]; then
|
||||
git remote set-url origin "$REPO_URL"
|
||||
fi
|
||||
|
||||
git fetch origin
|
||||
git checkout "$BRANCH"
|
||||
git reset --hard "origin/$BRANCH"
|
||||
echo "Repository updated to latest $BRANCH branch"
|
||||
else
|
||||
echo "Directory exists but is not a git repository. Removing and cloning fresh..."
|
||||
cd "$BASE_DIR"
|
||||
rm -rf "$INSTALL_DIR"
|
||||
echo "Cloning repository..."
|
||||
git clone "$REPO_URL" "$INSTALL_DIR"
|
||||
cd "$INSTALL_DIR"
|
||||
git checkout "$BRANCH"
|
||||
echo "Repository cloned and checked out to $BRANCH branch"
|
||||
fi
|
||||
else
|
||||
echo "Cloning repository..."
|
||||
git clone "$REPO_URL" "$INSTALL_DIR"
|
||||
cd "$INSTALL_DIR"
|
||||
git checkout "$BRANCH"
|
||||
echo "Repository cloned and checked out to $BRANCH branch"
|
||||
fi
|
||||
|
||||
echo "===== Cleaning build cache ====="
|
||||
# Clean cargo cache to ensure fresh build
|
||||
echo "Cleaning cargo build cache..."
|
||||
"$CARGO_CMD" clean 2>/dev/null || true
|
||||
|
||||
echo "===== Verifying environment ====="
|
||||
echo "Current PATH: $PATH"
|
||||
echo "Current USER: $(whoami)"
|
||||
echo "Current HOME: $HOME"
|
||||
|
||||
# Find cargo using multiple methods with robust detection
|
||||
CARGO_CMD=""
|
||||
|
||||
# Method 1: Check if cargo is in PATH
|
||||
echo "Checking for cargo in PATH..."
|
||||
if command -v cargo &> /dev/null; then
|
||||
CARGO_CMD="cargo"
|
||||
echo "✓ Found cargo in PATH: $(which cargo)"
|
||||
# Method 2: Check common Rust installation locations
|
||||
elif [ -f "$HOME/.cargo/bin/cargo" ]; then
|
||||
CARGO_CMD="$HOME/.cargo/bin/cargo"
|
||||
echo "✓ Found cargo at $HOME/.cargo/bin/cargo"
|
||||
# Add to PATH for this session
|
||||
export PATH="$HOME/.cargo/bin:$PATH"
|
||||
# Method 3: Check root cargo location
|
||||
elif [ -f "/root/.cargo/bin/cargo" ]; then
|
||||
CARGO_CMD="/root/.cargo/bin/cargo"
|
||||
echo "✓ Found cargo at /root/.cargo/bin/cargo"
|
||||
export PATH="/root/.cargo/bin:$PATH"
|
||||
# Method 4: Check system-wide installation
|
||||
elif [ -f "/usr/local/bin/cargo" ]; then
|
||||
CARGO_CMD="/usr/local/bin/cargo"
|
||||
echo "✓ Found cargo at /usr/local/bin/cargo"
|
||||
elif [ -f "/usr/bin/cargo" ]; then
|
||||
CARGO_CMD="/usr/bin/cargo"
|
||||
echo "✓ Found cargo at /usr/bin/cargo"
|
||||
# Method 5: Use whereis to find cargo
|
||||
else
|
||||
echo "Searching for cargo with whereis..."
|
||||
CARGO_PATHS=$(whereis cargo 2>/dev/null | cut -d' ' -f2-)
|
||||
echo "whereis found: $CARGO_PATHS"
|
||||
|
||||
for path in $CARGO_PATHS; do
|
||||
if [ -f "$path" ] && [ -x "$path" ]; then
|
||||
CARGO_CMD="$path"
|
||||
echo "✓ Found executable cargo at $path"
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
# Method 6: Last resort - try to find cargo anywhere
|
||||
if [ -z "$CARGO_CMD" ]; then
|
||||
echo "Searching for cargo with find..."
|
||||
FOUND_CARGO=$(find /usr /root /home -name "cargo" -type f -executable 2>/dev/null | head -1)
|
||||
if [ -n "$FOUND_CARGO" ] && [ -f "$FOUND_CARGO" ]; then
|
||||
CARGO_CMD="$FOUND_CARGO"
|
||||
echo "✓ Found cargo at $FOUND_CARGO"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Final verification
|
||||
if [ -n "$CARGO_CMD" ]; then
|
||||
echo "Using cargo command: $CARGO_CMD"
|
||||
echo "Testing cargo command..."
|
||||
if "$CARGO_CMD" --version &> /dev/null; then
|
||||
echo "✓ Cargo is working: $($CARGO_CMD --version)"
|
||||
else
|
||||
echo "✗ Cargo command failed to execute"
|
||||
CARGO_CMD=""
|
||||
fi
|
||||
fi
|
||||
|
||||
# If still no cargo found, try installation
|
||||
if [ -z "$CARGO_CMD" ]; then
|
||||
echo "Cargo not found anywhere. Installing Rust toolchain..."
|
||||
|
||||
# Install Rust using rustup
|
||||
if ! command -v rustup &> /dev/null; then
|
||||
echo "Installing rustup..."
|
||||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain stable
|
||||
|
||||
# Source the cargo environment
|
||||
if [ -f "$HOME/.cargo/env" ]; then
|
||||
source "$HOME/.cargo/env"
|
||||
fi
|
||||
|
||||
# Add to PATH
|
||||
export PATH="$HOME/.cargo/bin:$PATH"
|
||||
fi
|
||||
|
||||
# Verify installation
|
||||
if command -v cargo &> /dev/null; then
|
||||
CARGO_CMD="cargo"
|
||||
echo "✓ Rust toolchain installed successfully"
|
||||
elif [ -f "$HOME/.cargo/bin/cargo" ]; then
|
||||
CARGO_CMD="$HOME/.cargo/bin/cargo"
|
||||
export PATH="$HOME/.cargo/bin:$PATH"
|
||||
echo "✓ Rust toolchain installed successfully"
|
||||
else
|
||||
echo "✗ Failed to install Rust toolchain"
|
||||
echo "Please install Rust manually: https://rustup.rs/"
|
||||
echo "Waiting 30 seconds before retrying..."
|
||||
sleep 30
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check if we're in the right directory
|
||||
if [ ! -f "Cargo.toml" ]; then
|
||||
echo "Error: Cargo.toml not found. Are we in the right directory?"
|
||||
pwd
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "===== Setting up application environment ====="
|
||||
# Generate SECRET_KEY if .env doesn't exist or doesn't have a valid key
|
||||
if [ ! -f ".env" ] || ! grep -q "^SECRET_KEY=" .env || grep -q "your_secret_key_here" .env; then
|
||||
echo "Generating SECRET_KEY for application..."
|
||||
SECRET_KEY=$(openssl rand -base64 64 | tr -d '\n')
|
||||
|
||||
# Create .env from template if it doesn't exist
|
||||
if [ ! -f ".env" ] && [ -f ".env.example" ]; then
|
||||
cp .env.example .env
|
||||
fi
|
||||
|
||||
# Update or add SECRET_KEY
|
||||
if [ -f ".env" ]; then
|
||||
if grep -q "^SECRET_KEY=" .env; then
|
||||
sed -i "s/^SECRET_KEY=.*/SECRET_KEY=$SECRET_KEY/" .env
|
||||
else
|
||||
echo "SECRET_KEY=$SECRET_KEY" >> .env
|
||||
fi
|
||||
else
|
||||
echo "SECRET_KEY=$SECRET_KEY" > .env
|
||||
fi
|
||||
echo "SECRET_KEY generated and saved to .env"
|
||||
else
|
||||
echo "Using existing SECRET_KEY from .env"
|
||||
fi
|
||||
|
||||
echo "===== Starting application ====="
|
||||
echo "Running Project Mycelium on port $PORT..."
|
||||
echo "Working directory: $(pwd)"
|
||||
echo "Branch: $(git branch --show-current)"
|
||||
echo "Commit: $(git rev-parse --short HEAD)"
|
||||
|
||||
# Set environment variables
|
||||
export RUST_LOG=info
|
||||
|
||||
# Run the application (following existing pattern)
|
||||
git checkout "$BRANCH"
|
||||
exec "$CARGO_CMD" run --release --bin projectmycelium -- --port "$PORT"
|
Reference in New Issue
Block a user