deploy CI
This commit is contained in:
233
.github/workflows/deploy.yml
vendored
Normal file
233
.github/workflows/deploy.yml
vendored
Normal file
@@ -0,0 +1,233 @@
|
|||||||
|
name: Deploy to Windows Server
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ main, master ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ main, master ]
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
env:
|
||||||
|
GO_VERSION: '1.23'
|
||||||
|
SERVICE_NAME: 'ACC Server Manager'
|
||||||
|
BINARY_NAME: 'acc-server-manager'
|
||||||
|
MIGRATE_BINARY_NAME: 'acc-migrate'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up Go
|
||||||
|
uses: actions/setup-go@v4
|
||||||
|
with:
|
||||||
|
go-version: ${{ env.GO_VERSION }}
|
||||||
|
|
||||||
|
- name: Cache Go modules
|
||||||
|
uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/.cache/go-build
|
||||||
|
~/go/pkg/mod
|
||||||
|
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-go-
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
run: go test -v ./...
|
||||||
|
|
||||||
|
- name: Build API for Windows
|
||||||
|
env:
|
||||||
|
GOOS: windows
|
||||||
|
GOARCH: amd64
|
||||||
|
run: |
|
||||||
|
go build -o ${{ env.BINARY_NAME }}.exe ./cmd/api
|
||||||
|
|
||||||
|
- name: Build Migration tool for Windows
|
||||||
|
env:
|
||||||
|
GOOS: windows
|
||||||
|
GOARCH: amd64
|
||||||
|
run: |
|
||||||
|
go build -o ${{ env.MIGRATE_BINARY_NAME }}.exe ./cmd/migrate
|
||||||
|
|
||||||
|
- name: Upload build artifacts
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: windows-binaries
|
||||||
|
path: |
|
||||||
|
${{ env.BINARY_NAME }}.exe
|
||||||
|
${{ env.MIGRATE_BINARY_NAME }}.exe
|
||||||
|
retention-days: 5
|
||||||
|
|
||||||
|
deploy:
|
||||||
|
needs: build
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master'
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Download build artifacts
|
||||||
|
uses: actions/download-artifact@v3
|
||||||
|
with:
|
||||||
|
name: windows-binaries
|
||||||
|
path: ./build
|
||||||
|
|
||||||
|
- name: Setup SSH key
|
||||||
|
uses: webfactory/ssh-agent@v0.7.0
|
||||||
|
with:
|
||||||
|
ssh-private-key: ${{ secrets.WINDOWS_SERVER_SSH_KEY }}
|
||||||
|
|
||||||
|
- name: Deploy to Windows Server
|
||||||
|
env:
|
||||||
|
SERVER_HOST: ${{ secrets.WINDOWS_SERVER_HOST }}
|
||||||
|
SERVER_USER: ${{ secrets.WINDOWS_SERVER_USER }}
|
||||||
|
SERVER_PASSWORD: ${{ secrets.WINDOWS_SERVER_PASSWORD }}
|
||||||
|
DEPLOY_PATH: ${{ secrets.DEPLOY_PATH }}
|
||||||
|
run: |
|
||||||
|
# Install PowerShell Core if not available
|
||||||
|
if ! command -v pwsh &> /dev/null; then
|
||||||
|
echo "Installing PowerShell Core..."
|
||||||
|
wget -q https://github.com/PowerShell/PowerShell/releases/download/v7.4.0/powershell_7.4.0-1.deb_amd64.deb
|
||||||
|
sudo dpkg -i powershell_7.4.0-1.deb_amd64.deb
|
||||||
|
sudo apt-get install -f
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create deployment script
|
||||||
|
cat > deploy_script.ps1 << 'EOF'
|
||||||
|
param(
|
||||||
|
[string]$ServiceName = "${{ env.SERVICE_NAME }}",
|
||||||
|
[string]$BinaryName = "${{ env.BINARY_NAME }}",
|
||||||
|
[string]$MigrateBinaryName = "${{ env.MIGRATE_BINARY_NAME }}",
|
||||||
|
[string]$DeployPath = "$env:DEPLOY_PATH"
|
||||||
|
)
|
||||||
|
|
||||||
|
Write-Host "Starting deployment process..." -ForegroundColor Green
|
||||||
|
|
||||||
|
# Check if service exists and stop it
|
||||||
|
$service = Get-Service -Name $ServiceName -ErrorAction SilentlyContinue
|
||||||
|
if ($service) {
|
||||||
|
Write-Host "Stopping service: $ServiceName" -ForegroundColor Yellow
|
||||||
|
Stop-Service -Name $ServiceName -Force
|
||||||
|
|
||||||
|
# Wait for service to stop
|
||||||
|
$timeout = 30
|
||||||
|
$elapsed = 0
|
||||||
|
while ($service.Status -ne 'Stopped' -and $elapsed -lt $timeout) {
|
||||||
|
Start-Sleep -Seconds 1
|
||||||
|
$elapsed++
|
||||||
|
$service.Refresh()
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($service.Status -ne 'Stopped') {
|
||||||
|
Write-Error "Failed to stop service within timeout"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
Write-Host "Service stopped successfully" -ForegroundColor Green
|
||||||
|
} else {
|
||||||
|
Write-Host "Service not found: $ServiceName" -ForegroundColor Yellow
|
||||||
|
}
|
||||||
|
|
||||||
|
# Create backup of current deployment
|
||||||
|
$backupPath = "$DeployPath\backup_$(Get-Date -Format 'yyyyMMdd_HHmmss')"
|
||||||
|
if (Test-Path "$DeployPath\$BinaryName.exe") {
|
||||||
|
Write-Host "Creating backup at: $backupPath" -ForegroundColor Yellow
|
||||||
|
New-Item -ItemType Directory -Path $backupPath -Force | Out-Null
|
||||||
|
Copy-Item "$DeployPath\*" -Destination $backupPath -Recurse -Force
|
||||||
|
}
|
||||||
|
|
||||||
|
# Copy new binaries
|
||||||
|
Write-Host "Copying new binaries to: $DeployPath" -ForegroundColor Yellow
|
||||||
|
Copy-Item "C:\temp\$BinaryName.exe" -Destination "$DeployPath\$BinaryName.exe" -Force
|
||||||
|
Copy-Item "C:\temp\$MigrateBinaryName.exe" -Destination "$DeployPath\$MigrateBinaryName.exe" -Force
|
||||||
|
|
||||||
|
# Run migrations
|
||||||
|
Write-Host "Running database migrations..." -ForegroundColor Yellow
|
||||||
|
$migrateResult = & "$DeployPath\$MigrateBinaryName.exe" 2>&1
|
||||||
|
Write-Host "Migration output: $migrateResult" -ForegroundColor Cyan
|
||||||
|
|
||||||
|
# Start service
|
||||||
|
if ($service) {
|
||||||
|
Write-Host "Starting service: $ServiceName" -ForegroundColor Yellow
|
||||||
|
Start-Service -Name $ServiceName
|
||||||
|
|
||||||
|
# Wait for service to start
|
||||||
|
$timeout = 30
|
||||||
|
$elapsed = 0
|
||||||
|
while ($service.Status -ne 'Running' -and $elapsed -lt $timeout) {
|
||||||
|
Start-Sleep -Seconds 1
|
||||||
|
$elapsed++
|
||||||
|
$service.Refresh()
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($service.Status -ne 'Running') {
|
||||||
|
Write-Error "Failed to start service within timeout"
|
||||||
|
# Rollback
|
||||||
|
Write-Host "Rolling back deployment..." -ForegroundColor Red
|
||||||
|
if (Test-Path $backupPath) {
|
||||||
|
Copy-Item "$backupPath\*" -Destination $DeployPath -Recurse -Force
|
||||||
|
Start-Service -Name $ServiceName
|
||||||
|
}
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
Write-Host "Service started successfully" -ForegroundColor Green
|
||||||
|
} else {
|
||||||
|
Write-Host "Service not configured. Manual start required." -ForegroundColor Yellow
|
||||||
|
}
|
||||||
|
|
||||||
|
# Cleanup old backups (keep last 5)
|
||||||
|
$backupDir = Split-Path $DeployPath -Parent
|
||||||
|
Get-ChildItem -Path $backupDir -Directory -Name "backup_*" |
|
||||||
|
Sort-Object -Descending |
|
||||||
|
Select-Object -Skip 5 |
|
||||||
|
ForEach-Object { Remove-Item -Path "$backupDir\$_" -Recurse -Force }
|
||||||
|
|
||||||
|
Write-Host "Deployment completed successfully!" -ForegroundColor Green
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Copy files to Windows server using SCP
|
||||||
|
echo "Copying files to Windows server..."
|
||||||
|
scp -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \
|
||||||
|
./build/${{ env.BINARY_NAME }}.exe \
|
||||||
|
./build/${{ env.MIGRATE_BINARY_NAME }}.exe \
|
||||||
|
deploy_script.ps1 \
|
||||||
|
${{ env.SERVER_USER }}@${{ env.SERVER_HOST }}:C:/temp/
|
||||||
|
|
||||||
|
# Execute deployment script on Windows server
|
||||||
|
echo "Executing deployment script on Windows server..."
|
||||||
|
ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \
|
||||||
|
${{ env.SERVER_USER }}@${{ env.SERVER_HOST }} \
|
||||||
|
"powershell.exe -ExecutionPolicy Bypass -File C:/temp/deploy_script.ps1"
|
||||||
|
|
||||||
|
# Cleanup temp files
|
||||||
|
ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \
|
||||||
|
${{ env.SERVER_USER }}@${{ env.SERVER_HOST }} \
|
||||||
|
"del C:/temp/${{ env.BINARY_NAME }}.exe C:/temp/${{ env.MIGRATE_BINARY_NAME }}.exe C:/temp/deploy_script.ps1"
|
||||||
|
|
||||||
|
echo "Deployment completed successfully!"
|
||||||
|
|
||||||
|
notify:
|
||||||
|
needs: [build, deploy]
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: always()
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Notify deployment status
|
||||||
|
env:
|
||||||
|
WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
|
||||||
|
run: |
|
||||||
|
if [ "${{ needs.deploy.result }}" == "success" ]; then
|
||||||
|
STATUS="✅ SUCCESS"
|
||||||
|
COLOR="good"
|
||||||
|
else
|
||||||
|
STATUS="❌ FAILED"
|
||||||
|
COLOR="danger"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$WEBHOOK_URL" ]; then
|
||||||
|
curl -X POST -H 'Content-type: application/json' \
|
||||||
|
--data "{\"text\":\"ACC Server Manager Deployment $STATUS\",\"attachments\":[{\"color\":\"$COLOR\",\"fields\":[{\"title\":\"Branch\",\"value\":\"${{ github.ref_name }}\",\"short\":true},{\"title\":\"Commit\",\"value\":\"${{ github.sha }}\",\"short\":true}]}]}" \
|
||||||
|
$WEBHOOK_URL
|
||||||
|
fi
|
||||||
69
db_dump.txt
69
db_dump.txt
@@ -1,69 +0,0 @@
|
|||||||
PRAGMA foreign_keys=OFF;
|
|
||||||
BEGIN TRANSACTION;
|
|
||||||
CREATE TABLE `api_models` (`api` text);
|
|
||||||
INSERT INTO api_models VALUES('Works');
|
|
||||||
CREATE TABLE `configs` (`id` integer PRIMARY KEY AUTOINCREMENT,`server_id` integer NOT NULL,`config_file` text NOT NULL,`old_config` text,`new_config` text,`changed_at` datetime DEFAULT CURRENT_TIMESTAMP);
|
|
||||||
CREATE TABLE `tracks` (`name` text,`unique_pit_boxes` integer,`private_server_slots` integer,PRIMARY KEY (`name`));
|
|
||||||
INSERT INTO tracks VALUES('monza',29,60);
|
|
||||||
INSERT INTO tracks VALUES('zolder',34,50);
|
|
||||||
INSERT INTO tracks VALUES('brands_hatch',32,50);
|
|
||||||
INSERT INTO tracks VALUES('silverstone',36,60);
|
|
||||||
INSERT INTO tracks VALUES('paul_ricard',33,80);
|
|
||||||
INSERT INTO tracks VALUES('misano',30,50);
|
|
||||||
INSERT INTO tracks VALUES('spa',82,82);
|
|
||||||
INSERT INTO tracks VALUES('nurburgring',30,50);
|
|
||||||
INSERT INTO tracks VALUES('barcelona',29,50);
|
|
||||||
INSERT INTO tracks VALUES('hungaroring',27,50);
|
|
||||||
INSERT INTO tracks VALUES('zandvoort',25,50);
|
|
||||||
INSERT INTO tracks VALUES('kyalami',40,50);
|
|
||||||
INSERT INTO tracks VALUES('mount_panorama',36,50);
|
|
||||||
INSERT INTO tracks VALUES('suzuka',51,105);
|
|
||||||
INSERT INTO tracks VALUES('laguna_seca',30,50);
|
|
||||||
INSERT INTO tracks VALUES('imola',30,50);
|
|
||||||
INSERT INTO tracks VALUES('oulton_park',28,50);
|
|
||||||
INSERT INTO tracks VALUES('donington',37,50);
|
|
||||||
INSERT INTO tracks VALUES('snetterton',26,50);
|
|
||||||
INSERT INTO tracks VALUES('cota',30,70);
|
|
||||||
INSERT INTO tracks VALUES('indianapolis',30,60);
|
|
||||||
INSERT INTO tracks VALUES('watkins_glen',30,60);
|
|
||||||
INSERT INTO tracks VALUES('valencia',29,50);
|
|
||||||
INSERT INTO tracks VALUES('nurburgring_24h',50,110);
|
|
||||||
INSERT INTO tracks VALUES('red_bull_ring',50,50);
|
|
||||||
CREATE TABLE `car_models` (`value` integer PRIMARY KEY AUTOINCREMENT,`car_model` text);
|
|
||||||
INSERT INTO car_models VALUES(1,'Porsche 991 GT3 R');
|
|
||||||
CREATE TABLE `cup_categories` (`value` integer PRIMARY KEY AUTOINCREMENT,`category` text);
|
|
||||||
INSERT INTO cup_categories VALUES(1,'Overall');
|
|
||||||
INSERT INTO cup_categories VALUES(2,'Am');
|
|
||||||
INSERT INTO cup_categories VALUES(3,'Silver');
|
|
||||||
INSERT INTO cup_categories VALUES(4,'National');
|
|
||||||
CREATE TABLE `driver_categories` (`value` integer PRIMARY KEY AUTOINCREMENT,`category` text);
|
|
||||||
INSERT INTO driver_categories VALUES(1,'Silver');
|
|
||||||
INSERT INTO driver_categories VALUES(2,'Gold');
|
|
||||||
INSERT INTO driver_categories VALUES(3,'Platinum');
|
|
||||||
CREATE TABLE `session_types` (`value` integer PRIMARY KEY AUTOINCREMENT,`session_type` text);
|
|
||||||
INSERT INTO session_types VALUES(1,'Practice');
|
|
||||||
INSERT INTO session_types VALUES(4,'Qualifying');
|
|
||||||
INSERT INTO session_types VALUES(10,'Race');
|
|
||||||
CREATE TABLE `state_histories` (`id` integer PRIMARY KEY AUTOINCREMENT,`server_id` integer NOT NULL,`session` text,`player_count` integer,`date_created` datetime,`session_duration_minutes` integer, `track` text, `session_start` datetime, `session_id` integer NOT NULL DEFAULT 0);
|
|
||||||
INSERT INTO state_histories VALUES(1,1,'Practice',0,'2025-05-28 22:09:01.0782616+00:00',10,NULL,NULL,0);
|
|
||||||
INSERT INTO state_histories VALUES(2,1,'Practice',0,'2025-05-28 22:12:57.9930478+00:00',10,NULL,NULL,0);
|
|
||||||
CREATE TABLE `servers` (`id` integer PRIMARY KEY AUTOINCREMENT,`name` text NOT NULL,`ip` text NOT NULL,`port` integer NOT NULL,`config_path` text NOT NULL,`service_name` text NOT NULL,`date_created` datetime);
|
|
||||||
INSERT INTO servers VALUES(1,'ACC Server - Barcelona','',0,'C:\steamcmd\acc','ACC-Barcelona','2025-06-01 11:39:12.818073+00:00');
|
|
||||||
INSERT INTO servers VALUES(2,'ACC Server - Monza','',0,'C:\steamcmd\acc2','ACC-Monza','2025-06-01 11:39:12.8917064+00:00');
|
|
||||||
INSERT INTO servers VALUES(3,'ACC Server - Spa','',0,'C:\steamcmd\acc3','ACC-Spa','2025-06-01 11:39:12.9500828+00:00');
|
|
||||||
INSERT INTO servers VALUES(4,'ACC Server - League','',0,'C:\steamcmd\acc-league','ACC-League','2025-06-01 11:39:13.0086536+00:00');
|
|
||||||
CREATE TABLE `steam_credentials` (`id` integer PRIMARY KEY AUTOINCREMENT,`username` text NOT NULL,`password` text NOT NULL,`date_created` datetime,`last_updated` datetime);
|
|
||||||
INSERT INTO steam_credentials VALUES(1,'jurmica','HxkPHrsClVPhxP2IntwBc3TGB0hMYtUkScJgLRNYj2Z/GnL+lF4uAO2+','2025-06-01 15:39:45.2399668+00:00','2025-06-01 15:39:45.2404672+00:00');
|
|
||||||
CREATE TABLE `system_configs` (`id` integer PRIMARY KEY AUTOINCREMENT,`key` text,`value` text,`default_value` text,`description` text,`date_modified` text);
|
|
||||||
INSERT INTO system_configs VALUES(1,'steamcmd_path','','c:\steamcmd\steamcmd.exe','Path to SteamCMD executable','2025-06-01T16:11:59Z');
|
|
||||||
INSERT INTO system_configs VALUES(2,'nssm_path','','.\nssm.exe','Path to NSSM executable','2025-06-01T16:11:59Z');
|
|
||||||
DELETE FROM sqlite_sequence;
|
|
||||||
INSERT INTO sqlite_sequence VALUES('car_models',1);
|
|
||||||
INSERT INTO sqlite_sequence VALUES('driver_categories',3);
|
|
||||||
INSERT INTO sqlite_sequence VALUES('cup_categories',4);
|
|
||||||
INSERT INTO sqlite_sequence VALUES('session_types',10);
|
|
||||||
INSERT INTO sqlite_sequence VALUES('state_histories',2);
|
|
||||||
INSERT INTO sqlite_sequence VALUES('servers',4);
|
|
||||||
INSERT INTO sqlite_sequence VALUES('steam_credentials',1);
|
|
||||||
INSERT INTO sqlite_sequence VALUES('system_configs',2);
|
|
||||||
COMMIT;
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
CREATE TABLE `api_models` (`api` text);
|
|
||||||
CREATE TABLE sqlite_sequence(name,seq);
|
|
||||||
CREATE TABLE `configs` (`id` integer PRIMARY KEY AUTOINCREMENT,`server_id` integer NOT NULL,`config_file` text NOT NULL,`old_config` text,`new_config` text,`changed_at` datetime DEFAULT CURRENT_TIMESTAMP);
|
|
||||||
CREATE TABLE `tracks` (`name` text,`unique_pit_boxes` integer,`private_server_slots` integer,PRIMARY KEY (`name`));
|
|
||||||
CREATE TABLE `car_models` (`value` integer PRIMARY KEY AUTOINCREMENT,`car_model` text);
|
|
||||||
CREATE TABLE `cup_categories` (`value` integer PRIMARY KEY AUTOINCREMENT,`category` text);
|
|
||||||
CREATE TABLE `driver_categories` (`value` integer PRIMARY KEY AUTOINCREMENT,`category` text);
|
|
||||||
CREATE TABLE `session_types` (`value` integer PRIMARY KEY AUTOINCREMENT,`session_type` text);
|
|
||||||
CREATE TABLE `state_histories` (`id` integer PRIMARY KEY AUTOINCREMENT,`server_id` integer NOT NULL,`session` text,`player_count` integer,`date_created` datetime,`session_duration_minutes` integer, `track` text, `session_start` datetime, `session_id` integer NOT NULL DEFAULT 0);
|
|
||||||
CREATE TABLE `servers` (`id` integer PRIMARY KEY AUTOINCREMENT,`name` text NOT NULL,`ip` text NOT NULL,`port` integer NOT NULL,`config_path` text NOT NULL,`service_name` text NOT NULL,`date_created` datetime);
|
|
||||||
CREATE TABLE `steam_credentials` (`id` integer PRIMARY KEY AUTOINCREMENT,`username` text NOT NULL,`password` text NOT NULL,`date_created` datetime,`last_updated` datetime);
|
|
||||||
CREATE TABLE `system_configs` (`id` integer PRIMARY KEY AUTOINCREMENT,`key` text,`value` text,`default_value` text,`description` text,`date_modified` text);
|
|
||||||
7584
main_db_dump.txt
7584
main_db_dump.txt
File diff suppressed because it is too large
Load Diff
256
scripts/README.md
Normal file
256
scripts/README.md
Normal file
@@ -0,0 +1,256 @@
|
|||||||
|
# ACC Server Manager Deployment Scripts
|
||||||
|
|
||||||
|
This directory contains scripts and tools for deploying the ACC Server Manager to a Windows server.
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
The deployment process automates the following steps:
|
||||||
|
1. Build the application binaries for Windows
|
||||||
|
2. Copy binaries to the target server
|
||||||
|
3. Stop the Windows service
|
||||||
|
4. Backup current deployment
|
||||||
|
5. Deploy new binaries
|
||||||
|
6. Run database migrations
|
||||||
|
7. Start the Windows service
|
||||||
|
8. Verify deployment success
|
||||||
|
|
||||||
|
## Files
|
||||||
|
|
||||||
|
- `deploy.ps1` - Main PowerShell deployment script
|
||||||
|
- `deploy.bat` - Batch file wrapper for easier execution
|
||||||
|
- `deploy.config.example` - Configuration template
|
||||||
|
- `README.md` - This documentation
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
### Local Machine (Build Environment)
|
||||||
|
- Go 1.23 or later
|
||||||
|
- PowerShell (Windows PowerShell 5.1+ or PowerShell Core 7+)
|
||||||
|
- SSH client (OpenSSH recommended)
|
||||||
|
- SCP utility
|
||||||
|
|
||||||
|
### Target Windows Server
|
||||||
|
- Windows Server 2016 or later
|
||||||
|
- PowerShell 5.1 or later
|
||||||
|
- SSH Server (OpenSSH Server or similar)
|
||||||
|
- ACC Server Manager Windows service configured
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
### 1. Configure SSH Access
|
||||||
|
|
||||||
|
Ensure SSH access to your Windows server:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
# On Windows Server, install OpenSSH Server
|
||||||
|
Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0
|
||||||
|
Start-Service sshd
|
||||||
|
Set-Service -Name sshd -StartupType 'Automatic'
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Create Deployment Configuration
|
||||||
|
|
||||||
|
Copy the configuration template and customize it:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cp deploy.config.example deploy.config
|
||||||
|
# Edit deploy.config with your server details
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Set Up Windows Service
|
||||||
|
|
||||||
|
Ensure the ACC Server Manager is installed as a Windows service on the target server. You can use tools like NSSM or create a native Windows service.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Option 1: Using Batch Script (Recommended)
|
||||||
|
|
||||||
|
```batch
|
||||||
|
# Basic deployment
|
||||||
|
deploy.bat 192.168.1.100 admin "C:\AccServerManager"
|
||||||
|
|
||||||
|
# With additional options
|
||||||
|
deploy.bat 192.168.1.100 admin "C:\AccServerManager" -SkipTests
|
||||||
|
|
||||||
|
# Test deployment (dry run)
|
||||||
|
deploy.bat 192.168.1.100 admin "C:\AccServerManager" -WhatIf
|
||||||
|
```
|
||||||
|
|
||||||
|
### Option 2: Using PowerShell Script Directly
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
# Basic deployment
|
||||||
|
.\deploy.ps1 -ServerHost "192.168.1.100" -ServerUser "admin" -DeployPath "C:\AccServerManager"
|
||||||
|
|
||||||
|
# With custom service name
|
||||||
|
.\deploy.ps1 -ServerHost "192.168.1.100" -ServerUser "admin" -DeployPath "C:\AccServerManager" -ServiceName "MyAccService"
|
||||||
|
|
||||||
|
# Skip tests and build
|
||||||
|
.\deploy.ps1 -ServerHost "192.168.1.100" -ServerUser "admin" -DeployPath "C:\AccServerManager" -SkipTests -SkipBuild
|
||||||
|
|
||||||
|
# Dry run
|
||||||
|
.\deploy.ps1 -ServerHost "192.168.1.100" -ServerUser "admin" -DeployPath "C:\AccServerManager" -WhatIf
|
||||||
|
```
|
||||||
|
|
||||||
|
### Option 3: Using GitHub Actions
|
||||||
|
|
||||||
|
The CI/CD pipeline automatically deploys when changes are pushed to the main branch. Configure the following secrets in your GitHub repository:
|
||||||
|
|
||||||
|
- `WINDOWS_SERVER_HOST` - Server hostname or IP
|
||||||
|
- `WINDOWS_SERVER_USER` - SSH username
|
||||||
|
- `WINDOWS_SERVER_SSH_KEY` - SSH private key
|
||||||
|
- `DEPLOY_PATH` - Deployment directory on server
|
||||||
|
- `SLACK_WEBHOOK_URL` - (Optional) Slack webhook for notifications
|
||||||
|
|
||||||
|
## Parameters
|
||||||
|
|
||||||
|
### Required Parameters
|
||||||
|
- `ServerHost` - Target Windows server hostname or IP address
|
||||||
|
- `ServerUser` - Username for SSH connection
|
||||||
|
- `DeployPath` - Full path where the application will be deployed
|
||||||
|
|
||||||
|
### Optional Parameters
|
||||||
|
- `ServiceName` - Windows service name (default: "ACC Server Manager")
|
||||||
|
- `BinaryName` - Main binary name (default: "acc-server-manager")
|
||||||
|
- `MigrateBinaryName` - Migration binary name (default: "acc-migrate")
|
||||||
|
- `SkipBuild` - Skip the build process
|
||||||
|
- `SkipTests` - Skip running tests
|
||||||
|
- `WhatIf` - Show what would be done without executing
|
||||||
|
|
||||||
|
## Deployment Process Details
|
||||||
|
|
||||||
|
### 1. Build Phase
|
||||||
|
- Runs Go tests (unless `-SkipTests` is specified)
|
||||||
|
- Builds API binary for Windows (GOOS=windows, GOARCH=amd64)
|
||||||
|
- Builds migration tool for Windows
|
||||||
|
- Creates binaries in `.\build` directory
|
||||||
|
|
||||||
|
### 2. Pre-deployment
|
||||||
|
- Copies binaries to server's temporary directory
|
||||||
|
- Creates deployment script on server
|
||||||
|
|
||||||
|
### 3. Deployment
|
||||||
|
- Stops the Windows service
|
||||||
|
- Creates backup of current deployment
|
||||||
|
- Copies new binaries to deployment directory
|
||||||
|
- Runs database migrations
|
||||||
|
- Starts the Windows service
|
||||||
|
- Verifies service is running
|
||||||
|
|
||||||
|
### 4. Rollback (if deployment fails)
|
||||||
|
- Restores from backup
|
||||||
|
- Restarts service with previous version
|
||||||
|
- Reports failure
|
||||||
|
|
||||||
|
### 5. Cleanup
|
||||||
|
- Removes temporary files
|
||||||
|
- Keeps last 5 backups (configurable)
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Common Issues
|
||||||
|
|
||||||
|
#### SSH Connection Failed
|
||||||
|
```
|
||||||
|
Test-NetConnection -ComputerName <server> -Port 22
|
||||||
|
```
|
||||||
|
Ensure SSH server is running and accessible.
|
||||||
|
|
||||||
|
#### Service Not Found
|
||||||
|
Verify the service name matches exactly:
|
||||||
|
```powershell
|
||||||
|
Get-Service -Name "ACC Server Manager"
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Permission Denied
|
||||||
|
Ensure the SSH user has permissions to:
|
||||||
|
- Stop/start the service
|
||||||
|
- Write to the deployment directory
|
||||||
|
- Execute PowerShell scripts
|
||||||
|
|
||||||
|
#### Build Failures
|
||||||
|
Check Go version and dependencies:
|
||||||
|
```bash
|
||||||
|
go version
|
||||||
|
go mod tidy
|
||||||
|
go test ./...
|
||||||
|
```
|
||||||
|
|
||||||
|
### Debug Mode
|
||||||
|
|
||||||
|
Run with verbose output:
|
||||||
|
```powershell
|
||||||
|
$VerbosePreference = "Continue"
|
||||||
|
.\deploy.ps1 -ServerHost "..." -ServerUser "..." -DeployPath "..." -Verbose
|
||||||
|
```
|
||||||
|
|
||||||
|
### Log Files
|
||||||
|
|
||||||
|
Deployment logs are stored in:
|
||||||
|
- Local: PowerShell transcript files
|
||||||
|
- Remote: Windows Event Log (Application log)
|
||||||
|
|
||||||
|
## Security Considerations
|
||||||
|
|
||||||
|
1. **SSH Keys**: Use SSH key authentication instead of passwords
|
||||||
|
2. **Service Account**: Run the service with minimal required permissions
|
||||||
|
3. **Firewall**: Restrict SSH access to deployment machines only
|
||||||
|
4. **Backup Encryption**: Consider encrypting backup files
|
||||||
|
5. **Secrets Management**: Use secure storage for configuration files
|
||||||
|
|
||||||
|
## Customization
|
||||||
|
|
||||||
|
### Custom Migration Scripts
|
||||||
|
|
||||||
|
Place custom migration scripts in the `scripts/migrations` directory. They will be executed in alphabetical order.
|
||||||
|
|
||||||
|
### Pre/Post Deployment Hooks
|
||||||
|
|
||||||
|
Configure custom scripts in the deployment configuration:
|
||||||
|
```ini
|
||||||
|
PreDeployScript=scripts/pre-deploy.ps1
|
||||||
|
PostDeployScript=scripts/post-deploy.ps1
|
||||||
|
```
|
||||||
|
|
||||||
|
### Environment Variables
|
||||||
|
|
||||||
|
Set environment variables during deployment:
|
||||||
|
```ini
|
||||||
|
EnvironmentVariables=ENV=production,LOG_LEVEL=info
|
||||||
|
```
|
||||||
|
|
||||||
|
## Monitoring and Notifications
|
||||||
|
|
||||||
|
### Slack Notifications
|
||||||
|
Configure Slack webhook URL to receive deployment notifications:
|
||||||
|
```ini
|
||||||
|
SlackWebhookUrl=https://hooks.slack.com/services/YOUR/WEBHOOK/URL
|
||||||
|
```
|
||||||
|
|
||||||
|
### Health Checks
|
||||||
|
Configure health check endpoint to verify deployment:
|
||||||
|
```ini
|
||||||
|
HealthCheckUrl=http://localhost:8080/health
|
||||||
|
HealthCheckTimeout=60
|
||||||
|
```
|
||||||
|
|
||||||
|
## Best Practices
|
||||||
|
|
||||||
|
1. **Test deployments** in a staging environment first
|
||||||
|
2. **Use the `-WhatIf` flag** to preview changes
|
||||||
|
3. **Monitor service logs** after deployment
|
||||||
|
4. **Keep backups** of working deployments
|
||||||
|
5. **Use version tagging** for releases
|
||||||
|
6. **Document configuration changes**
|
||||||
|
7. **Test rollback procedures** regularly
|
||||||
|
|
||||||
|
## Support
|
||||||
|
|
||||||
|
For issues with deployment scripts:
|
||||||
|
1. Check the troubleshooting section
|
||||||
|
2. Review deployment logs
|
||||||
|
3. Verify server prerequisites
|
||||||
|
4. Test SSH connectivity manually
|
||||||
|
5. Check Windows service configuration
|
||||||
|
|
||||||
|
For application-specific issues, refer to the main project documentation.
|
||||||
86
scripts/deploy.bat
Normal file
86
scripts/deploy.bat
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
@echo off
|
||||||
|
setlocal enabledelayedexpansion
|
||||||
|
|
||||||
|
:: ACC Server Manager Deployment Script
|
||||||
|
:: This is a wrapper for the PowerShell deployment script
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo ===================================
|
||||||
|
echo ACC Server Manager Deployment Tool
|
||||||
|
echo ===================================
|
||||||
|
echo.
|
||||||
|
|
||||||
|
:: Check if PowerShell is available
|
||||||
|
where powershell >nul 2>&1
|
||||||
|
if %errorlevel% neq 0 (
|
||||||
|
echo ERROR: PowerShell is not installed or not in PATH
|
||||||
|
echo Please install PowerShell to use this deployment script
|
||||||
|
pause
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
|
||||||
|
:: Check if required parameters are provided
|
||||||
|
if "%~1"=="" (
|
||||||
|
echo Usage: deploy.bat [ServerHost] [ServerUser] [DeployPath] [additional options]
|
||||||
|
echo.
|
||||||
|
echo Examples:
|
||||||
|
echo deploy.bat 192.168.1.100 admin "C:\AccServerManager"
|
||||||
|
echo deploy.bat server.example.com deploy "C:\Services\AccServerManager" -SkipTests
|
||||||
|
echo deploy.bat 192.168.1.100 admin "C:\AccServerManager" -WhatIf
|
||||||
|
echo.
|
||||||
|
echo For more options, run: powershell -File scripts\deploy.ps1
|
||||||
|
pause
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
|
||||||
|
:: Set variables
|
||||||
|
set SERVER_HOST=%~1
|
||||||
|
set SERVER_USER=%~2
|
||||||
|
set DEPLOY_PATH=%~3
|
||||||
|
|
||||||
|
:: Shift parameters to get additional options
|
||||||
|
shift
|
||||||
|
shift
|
||||||
|
shift
|
||||||
|
|
||||||
|
set ADDITIONAL_PARAMS=
|
||||||
|
:loop
|
||||||
|
if "%~1"=="" goto :continue
|
||||||
|
set ADDITIONAL_PARAMS=%ADDITIONAL_PARAMS% %1
|
||||||
|
shift
|
||||||
|
goto :loop
|
||||||
|
:continue
|
||||||
|
|
||||||
|
echo Server Host: %SERVER_HOST%
|
||||||
|
echo Server User: %SERVER_USER%
|
||||||
|
echo Deploy Path: %DEPLOY_PATH%
|
||||||
|
if not "%ADDITIONAL_PARAMS%"=="" (
|
||||||
|
echo Additional Parameters: %ADDITIONAL_PARAMS%
|
||||||
|
)
|
||||||
|
echo.
|
||||||
|
|
||||||
|
:: Confirm deployment
|
||||||
|
set /p CONFIRM=Do you want to proceed with deployment? (Y/N):
|
||||||
|
if /i not "%CONFIRM%"=="Y" (
|
||||||
|
echo Deployment cancelled.
|
||||||
|
pause
|
||||||
|
exit /b 0
|
||||||
|
)
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo Starting deployment...
|
||||||
|
echo.
|
||||||
|
|
||||||
|
:: Execute PowerShell deployment script
|
||||||
|
powershell -ExecutionPolicy Bypass -File "%~dp0deploy.ps1" -ServerHost "%SERVER_HOST%" -ServerUser "%SERVER_USER%" -DeployPath "%DEPLOY_PATH%" %ADDITIONAL_PARAMS%
|
||||||
|
|
||||||
|
if %errorlevel% neq 0 (
|
||||||
|
echo.
|
||||||
|
echo Deployment failed with error code: %errorlevel%
|
||||||
|
pause
|
||||||
|
exit /b %errorlevel%
|
||||||
|
)
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo Deployment completed successfully!
|
||||||
|
pause
|
||||||
109
scripts/deploy.config.example
Normal file
109
scripts/deploy.config.example
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
# ACC Server Manager Deployment Configuration
|
||||||
|
# Copy this file to deploy.config and fill in your server details
|
||||||
|
|
||||||
|
[Server]
|
||||||
|
# Windows server hostname or IP address
|
||||||
|
ServerHost=192.168.1.100
|
||||||
|
|
||||||
|
# Username for SSH connection to Windows server
|
||||||
|
ServerUser=admin
|
||||||
|
|
||||||
|
# Full path where the application will be deployed on the server
|
||||||
|
DeployPath=C:\AccServerManager
|
||||||
|
|
||||||
|
# Windows service name (must match the service installed on the server)
|
||||||
|
ServiceName=ACC Server Manager
|
||||||
|
|
||||||
|
[Build]
|
||||||
|
# Main application binary name (without .exe extension)
|
||||||
|
BinaryName=acc-server-manager
|
||||||
|
|
||||||
|
# Migration tool binary name (without .exe extension)
|
||||||
|
MigrateBinaryName=acc-migrate
|
||||||
|
|
||||||
|
# Skip running tests during build (true/false)
|
||||||
|
SkipTests=false
|
||||||
|
|
||||||
|
# Skip building binaries (useful if you already have them built)
|
||||||
|
SkipBuild=false
|
||||||
|
|
||||||
|
[Deployment]
|
||||||
|
# Backup retention - number of backup directories to keep
|
||||||
|
BackupRetention=5
|
||||||
|
|
||||||
|
# Service stop timeout in seconds
|
||||||
|
ServiceStopTimeout=30
|
||||||
|
|
||||||
|
# Service start timeout in seconds
|
||||||
|
ServiceStartTimeout=30
|
||||||
|
|
||||||
|
# Enable rollback on deployment failure (true/false)
|
||||||
|
EnableRollback=true
|
||||||
|
|
||||||
|
[Notifications]
|
||||||
|
# Slack webhook URL for deployment notifications (optional)
|
||||||
|
SlackWebhookUrl=
|
||||||
|
|
||||||
|
# Discord webhook URL for deployment notifications (optional)
|
||||||
|
DiscordWebhookUrl=
|
||||||
|
|
||||||
|
# Email settings for notifications (optional)
|
||||||
|
EmailSmtpServer=
|
||||||
|
EmailSmtpPort=587
|
||||||
|
EmailUsername=
|
||||||
|
EmailPassword=
|
||||||
|
EmailFrom=
|
||||||
|
EmailTo=
|
||||||
|
|
||||||
|
[SSH]
|
||||||
|
# SSH private key file path (optional, uses default SSH key if not specified)
|
||||||
|
SshKeyPath=
|
||||||
|
|
||||||
|
# SSH port (default is 22)
|
||||||
|
SshPort=22
|
||||||
|
|
||||||
|
# SSH connection timeout in seconds
|
||||||
|
SshTimeout=30
|
||||||
|
|
||||||
|
[Database]
|
||||||
|
# Database connection string template for migrations
|
||||||
|
# This will be passed to the migration tool
|
||||||
|
DatabaseConnectionString=
|
||||||
|
|
||||||
|
# Run migrations automatically during deployment (true/false)
|
||||||
|
AutoMigrate=true
|
||||||
|
|
||||||
|
# Migration timeout in seconds
|
||||||
|
MigrationTimeout=300
|
||||||
|
|
||||||
|
[Advanced]
|
||||||
|
# PowerShell execution policy for remote execution
|
||||||
|
ExecutionPolicy=Bypass
|
||||||
|
|
||||||
|
# Temporary directory on remote server for file transfers
|
||||||
|
RemoteTempPath=C:\temp
|
||||||
|
|
||||||
|
# Local build directory
|
||||||
|
LocalBuildPath=.\build
|
||||||
|
|
||||||
|
# Additional Go build flags
|
||||||
|
GoBuildFlags=-ldflags="-s -w"
|
||||||
|
|
||||||
|
# Pre-deployment script to run locally (optional)
|
||||||
|
PreDeployScript=
|
||||||
|
|
||||||
|
# Post-deployment script to run on remote server (optional)
|
||||||
|
PostDeployScript=
|
||||||
|
|
||||||
|
# Environment variables to set during deployment (comma-separated)
|
||||||
|
# Format: KEY1=VALUE1,KEY2=VALUE2
|
||||||
|
EnvironmentVariables=
|
||||||
|
|
||||||
|
# Custom service restart command (if service management is different)
|
||||||
|
ServiceRestartCommand=
|
||||||
|
|
||||||
|
# Health check URL to verify deployment success
|
||||||
|
HealthCheckUrl=http://localhost:8080/health
|
||||||
|
|
||||||
|
# Health check timeout in seconds
|
||||||
|
HealthCheckTimeout=60
|
||||||
310
scripts/deploy.ps1
Normal file
310
scripts/deploy.ps1
Normal file
@@ -0,0 +1,310 @@
|
|||||||
|
param(
|
||||||
|
[Parameter(Mandatory=$true)]
|
||||||
|
[string]$ServerHost,
|
||||||
|
|
||||||
|
[Parameter(Mandatory=$true)]
|
||||||
|
[string]$ServerUser,
|
||||||
|
|
||||||
|
[Parameter(Mandatory=$true)]
|
||||||
|
[string]$DeployPath,
|
||||||
|
|
||||||
|
[string]$ServiceName = "ACC Server Manager",
|
||||||
|
[string]$BinaryName = "acc-server-manager",
|
||||||
|
[string]$MigrateBinaryName = "acc-migrate",
|
||||||
|
[switch]$SkipBuild,
|
||||||
|
[switch]$SkipTests,
|
||||||
|
[switch]$WhatIf
|
||||||
|
)
|
||||||
|
|
||||||
|
# Configuration
|
||||||
|
$ErrorActionPreference = "Stop"
|
||||||
|
$LocalBuildPath = ".\build"
|
||||||
|
$RemoteTempPath = "C:\temp"
|
||||||
|
|
||||||
|
function Write-Status {
|
||||||
|
param([string]$Message, [string]$Color = "Green")
|
||||||
|
Write-Host "[$(Get-Date -Format 'HH:mm:ss')] $Message" -ForegroundColor $Color
|
||||||
|
}
|
||||||
|
|
||||||
|
function Write-Error-Status {
|
||||||
|
param([string]$Message)
|
||||||
|
Write-Host "[$(Get-Date -Format 'HH:mm:ss')] ERROR: $Message" -ForegroundColor Red
|
||||||
|
}
|
||||||
|
|
||||||
|
function Write-Warning-Status {
|
||||||
|
param([string]$Message)
|
||||||
|
Write-Host "[$(Get-Date -Format 'HH:mm:ss')] WARNING: $Message" -ForegroundColor Yellow
|
||||||
|
}
|
||||||
|
|
||||||
|
function Test-Prerequisites {
|
||||||
|
Write-Status "Checking prerequisites..."
|
||||||
|
|
||||||
|
# Check if Go is installed
|
||||||
|
if (-not (Get-Command go -ErrorAction SilentlyContinue)) {
|
||||||
|
throw "Go is not installed or not in PATH"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check if we can connect to the server
|
||||||
|
$testConnection = Test-NetConnection -ComputerName $ServerHost -Port 22 -WarningAction SilentlyContinue
|
||||||
|
if (-not $testConnection.TcpTestSucceeded) {
|
||||||
|
Write-Warning-Status "Cannot connect to $ServerHost on port 22. Make sure SSH is enabled."
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Status "Prerequisites check completed"
|
||||||
|
}
|
||||||
|
|
||||||
|
function Build-Application {
|
||||||
|
if ($SkipBuild) {
|
||||||
|
Write-Status "Skipping build (SkipBuild flag set)"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Status "Building application..."
|
||||||
|
|
||||||
|
# Clean build directory
|
||||||
|
if (Test-Path $LocalBuildPath) {
|
||||||
|
Remove-Item -Path $LocalBuildPath -Recurse -Force
|
||||||
|
}
|
||||||
|
New-Item -ItemType Directory -Path $LocalBuildPath -Force | Out-Null
|
||||||
|
|
||||||
|
# Run tests
|
||||||
|
if (-not $SkipTests) {
|
||||||
|
Write-Status "Running tests..."
|
||||||
|
& go test -v ./...
|
||||||
|
if ($LASTEXITCODE -ne 0) {
|
||||||
|
throw "Tests failed"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Build API for Windows
|
||||||
|
Write-Status "Building API binary..."
|
||||||
|
$env:GOOS = "windows"
|
||||||
|
$env:GOARCH = "amd64"
|
||||||
|
& go build -o "$LocalBuildPath\$BinaryName.exe" .\cmd\api
|
||||||
|
if ($LASTEXITCODE -ne 0) {
|
||||||
|
throw "Failed to build API binary"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Build migration tool for Windows
|
||||||
|
Write-Status "Building migration binary..."
|
||||||
|
& go build -o "$LocalBuildPath\$MigrateBinaryName.exe" .\cmd\migrate
|
||||||
|
if ($LASTEXITCODE -ne 0) {
|
||||||
|
throw "Failed to build migration binary"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Reset environment variables
|
||||||
|
Remove-Item Env:\GOOS -ErrorAction SilentlyContinue
|
||||||
|
Remove-Item Env:\GOARCH -ErrorAction SilentlyContinue
|
||||||
|
|
||||||
|
Write-Status "Build completed successfully"
|
||||||
|
}
|
||||||
|
|
||||||
|
function Copy-FilesToServer {
|
||||||
|
Write-Status "Copying files to server..."
|
||||||
|
|
||||||
|
if ($WhatIf) {
|
||||||
|
Write-Status "WHAT-IF: Would copy files to $ServerHost" -Color "Cyan"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
# Copy binaries to server
|
||||||
|
scp -o StrictHostKeyChecking=no "$LocalBuildPath\$BinaryName.exe" "${ServerUser}@${ServerHost}:${RemoteTempPath}/"
|
||||||
|
if ($LASTEXITCODE -ne 0) {
|
||||||
|
throw "Failed to copy API binary to server"
|
||||||
|
}
|
||||||
|
|
||||||
|
scp -o StrictHostKeyChecking=no "$LocalBuildPath\$MigrateBinaryName.exe" "${ServerUser}@${ServerHost}:${RemoteTempPath}/"
|
||||||
|
if ($LASTEXITCODE -ne 0) {
|
||||||
|
throw "Failed to copy migration binary to server"
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Status "Files copied successfully"
|
||||||
|
}
|
||||||
|
|
||||||
|
function Deploy-ToServer {
|
||||||
|
Write-Status "Deploying to server..."
|
||||||
|
|
||||||
|
if ($WhatIf) {
|
||||||
|
Write-Status "WHAT-IF: Would deploy to $ServerHost" -Color "Cyan"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
# Create deployment script
|
||||||
|
$deployScript = @"
|
||||||
|
Write-Host "Starting deployment process..." -ForegroundColor Green
|
||||||
|
|
||||||
|
# Check if service exists and stop it
|
||||||
|
`$service = Get-Service -Name '$ServiceName' -ErrorAction SilentlyContinue
|
||||||
|
if (`$service) {
|
||||||
|
Write-Host "Stopping service: $ServiceName" -ForegroundColor Yellow
|
||||||
|
Stop-Service -Name '$ServiceName' -Force
|
||||||
|
|
||||||
|
# Wait for service to stop
|
||||||
|
`$timeout = 30
|
||||||
|
`$elapsed = 0
|
||||||
|
while (`$service.Status -ne 'Stopped' -and `$elapsed -lt `$timeout) {
|
||||||
|
Start-Sleep -Seconds 1
|
||||||
|
`$elapsed++
|
||||||
|
`$service.Refresh()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (`$service.Status -ne 'Stopped') {
|
||||||
|
Write-Error "Failed to stop service within timeout"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
Write-Host "Service stopped successfully" -ForegroundColor Green
|
||||||
|
} else {
|
||||||
|
Write-Host "Service not found: $ServiceName" -ForegroundColor Yellow
|
||||||
|
}
|
||||||
|
|
||||||
|
# Create backup of current deployment
|
||||||
|
`$backupPath = "$DeployPath\backup_`$(Get-Date -Format 'yyyyMMdd_HHmmss')"
|
||||||
|
if (Test-Path "$DeployPath\$BinaryName.exe") {
|
||||||
|
Write-Host "Creating backup at: `$backupPath" -ForegroundColor Yellow
|
||||||
|
New-Item -ItemType Directory -Path `$backupPath -Force | Out-Null
|
||||||
|
Copy-Item "$DeployPath\*" -Destination `$backupPath -Recurse -Force
|
||||||
|
}
|
||||||
|
|
||||||
|
# Copy new binaries
|
||||||
|
Write-Host "Copying new binaries to: $DeployPath" -ForegroundColor Yellow
|
||||||
|
if (-not (Test-Path "$DeployPath")) {
|
||||||
|
New-Item -ItemType Directory -Path "$DeployPath" -Force | Out-Null
|
||||||
|
}
|
||||||
|
Copy-Item "$RemoteTempPath\$BinaryName.exe" -Destination "$DeployPath\$BinaryName.exe" -Force
|
||||||
|
Copy-Item "$RemoteTempPath\$MigrateBinaryName.exe" -Destination "$DeployPath\$MigrateBinaryName.exe" -Force
|
||||||
|
|
||||||
|
# Run migrations
|
||||||
|
Write-Host "Running database migrations..." -ForegroundColor Yellow
|
||||||
|
try {
|
||||||
|
`$migrateResult = & "$DeployPath\$MigrateBinaryName.exe" 2>&1
|
||||||
|
Write-Host "Migration output: `$migrateResult" -ForegroundColor Cyan
|
||||||
|
} catch {
|
||||||
|
Write-Warning "Migration failed: `$_"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Start service
|
||||||
|
if (`$service) {
|
||||||
|
Write-Host "Starting service: $ServiceName" -ForegroundColor Yellow
|
||||||
|
Start-Service -Name '$ServiceName'
|
||||||
|
|
||||||
|
# Wait for service to start
|
||||||
|
`$timeout = 30
|
||||||
|
`$elapsed = 0
|
||||||
|
while (`$service.Status -ne 'Running' -and `$elapsed -lt `$timeout) {
|
||||||
|
Start-Sleep -Seconds 1
|
||||||
|
`$elapsed++
|
||||||
|
`$service.Refresh()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (`$service.Status -ne 'Running') {
|
||||||
|
Write-Error "Failed to start service within timeout"
|
||||||
|
# Rollback
|
||||||
|
Write-Host "Rolling back deployment..." -ForegroundColor Red
|
||||||
|
if (Test-Path `$backupPath) {
|
||||||
|
Copy-Item "`$backupPath\*" -Destination "$DeployPath" -Recurse -Force
|
||||||
|
Start-Service -Name '$ServiceName'
|
||||||
|
}
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
Write-Host "Service started successfully" -ForegroundColor Green
|
||||||
|
} else {
|
||||||
|
Write-Host "Service not configured. Manual start required." -ForegroundColor Yellow
|
||||||
|
}
|
||||||
|
|
||||||
|
# Cleanup old backups (keep last 5)
|
||||||
|
`$backupDir = Split-Path "$DeployPath" -Parent
|
||||||
|
Get-ChildItem -Path `$backupDir -Directory -Name "backup_*" |
|
||||||
|
Sort-Object -Descending |
|
||||||
|
Select-Object -Skip 5 |
|
||||||
|
ForEach-Object { Remove-Item -Path "`$backupDir\`$_" -Recurse -Force }
|
||||||
|
|
||||||
|
# Cleanup temp files
|
||||||
|
Remove-Item "$RemoteTempPath\$BinaryName.exe" -Force -ErrorAction SilentlyContinue
|
||||||
|
Remove-Item "$RemoteTempPath\$MigrateBinaryName.exe" -Force -ErrorAction SilentlyContinue
|
||||||
|
|
||||||
|
Write-Host "Deployment completed successfully!" -ForegroundColor Green
|
||||||
|
"@
|
||||||
|
|
||||||
|
# Save script to temp file
|
||||||
|
$tempScript = [System.IO.Path]::GetTempFileName() + ".ps1"
|
||||||
|
$deployScript | Out-File -FilePath $tempScript -Encoding UTF8
|
||||||
|
|
||||||
|
try {
|
||||||
|
# Copy deployment script to server
|
||||||
|
scp -o StrictHostKeyChecking=no $tempScript "${ServerUser}@${ServerHost}:${RemoteTempPath}/deploy_script.ps1"
|
||||||
|
if ($LASTEXITCODE -ne 0) {
|
||||||
|
throw "Failed to copy deployment script to server"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Execute deployment script on server
|
||||||
|
ssh -o StrictHostKeyChecking=no "${ServerUser}@${ServerHost}" "powershell.exe -ExecutionPolicy Bypass -File ${RemoteTempPath}/deploy_script.ps1"
|
||||||
|
if ($LASTEXITCODE -ne 0) {
|
||||||
|
throw "Deployment script failed on server"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Cleanup deployment script
|
||||||
|
ssh -o StrictHostKeyChecking=no "${ServerUser}@${ServerHost}" "del ${RemoteTempPath}/deploy_script.ps1"
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
# Remove temp script
|
||||||
|
Remove-Item $tempScript -Force -ErrorAction SilentlyContinue
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Status "Deployment completed successfully"
|
||||||
|
}
|
||||||
|
|
||||||
|
function Show-Usage {
|
||||||
|
Write-Host @"
|
||||||
|
ACC Server Manager Deployment Script
|
||||||
|
|
||||||
|
Usage: .\deploy.ps1 -ServerHost <host> -ServerUser <user> -DeployPath <path> [options]
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
-ServerHost Target Windows server hostname or IP
|
||||||
|
-ServerUser Username for SSH connection
|
||||||
|
-DeployPath Deployment directory on target server
|
||||||
|
-ServiceName Windows service name (default: "ACC Server Manager")
|
||||||
|
-BinaryName Main binary name (default: "acc-server-manager")
|
||||||
|
-MigrateBinaryName Migration binary name (default: "acc-migrate")
|
||||||
|
-SkipBuild Skip the build process
|
||||||
|
-SkipTests Skip running tests
|
||||||
|
-WhatIf Show what would be done without executing
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
.\deploy.ps1 -ServerHost "192.168.1.100" -ServerUser "admin" -DeployPath "C:\AccServerManager"
|
||||||
|
.\deploy.ps1 -ServerHost "server.example.com" -ServerUser "deploy" -DeployPath "C:\Services\AccServerManager" -SkipTests
|
||||||
|
.\deploy.ps1 -ServerHost "192.168.1.100" -ServerUser "admin" -DeployPath "C:\AccServerManager" -WhatIf
|
||||||
|
|
||||||
|
Requirements:
|
||||||
|
- Go installed locally
|
||||||
|
- SSH client (OpenSSH)
|
||||||
|
- SCP utility
|
||||||
|
- PowerShell on target Windows server
|
||||||
|
- SSH server running on target Windows server
|
||||||
|
|
||||||
|
"@ -ForegroundColor Cyan
|
||||||
|
}
|
||||||
|
|
||||||
|
# Main execution
|
||||||
|
try {
|
||||||
|
Write-Status "Starting ACC Server Manager deployment" -Color "Cyan"
|
||||||
|
Write-Status "Target: $ServerUser@$ServerHost"
|
||||||
|
Write-Status "Deploy Path: $DeployPath"
|
||||||
|
Write-Status "Service Name: $ServiceName"
|
||||||
|
|
||||||
|
if ($WhatIf) {
|
||||||
|
Write-Status "WHAT-IF MODE: No changes will be made" -Color "Cyan"
|
||||||
|
}
|
||||||
|
|
||||||
|
Test-Prerequisites
|
||||||
|
Build-Application
|
||||||
|
Copy-FilesToServer
|
||||||
|
Deploy-ToServer
|
||||||
|
|
||||||
|
Write-Status "Deployment completed successfully!" -Color "Green"
|
||||||
|
|
||||||
|
} catch {
|
||||||
|
Write-Error-Status $_.Exception.Message
|
||||||
|
Write-Host "Deployment failed. Check the error above for details." -ForegroundColor Red
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user