add build scripts and resolve migration
This commit is contained in:
106
local/migrations/004_fix_ddl_comments.go
Normal file
106
local/migrations/004_fix_ddl_comments.go
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
package migrations
|
||||||
|
|
||||||
|
import (
|
||||||
|
"acc-server-manager/local/utl/logging"
|
||||||
|
"fmt"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
var sqlLineCommentRegexp = regexp.MustCompile(`--[^\n]*`)
|
||||||
|
|
||||||
|
type Migration004FixDDLComments struct {
|
||||||
|
DB *gorm.DB
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewMigration004FixDDLComments(db *gorm.DB) *Migration004FixDDLComments {
|
||||||
|
return &Migration004FixDDLComments{DB: db}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Migration004FixDDLComments) Up() error {
|
||||||
|
if err := m.DB.AutoMigrate(&MigrationRecord{}); err != nil {
|
||||||
|
return fmt.Errorf("failed to create migration tracking table: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var record MigrationRecord
|
||||||
|
if err := m.DB.Where("migration_name = ?", "004_fix_ddl_comments").First(&record).Error; err == nil {
|
||||||
|
logging.Info("DDL comment fix migration already applied, skipping")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var tables []string
|
||||||
|
if err := m.DB.Raw(
|
||||||
|
"SELECT name FROM sqlite_master WHERE type = 'table' AND sql LIKE '%--%' ORDER BY name",
|
||||||
|
).Scan(&tables).Error; err != nil {
|
||||||
|
return fmt.Errorf("failed to query tables with DDL comments: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(tables) == 0 {
|
||||||
|
logging.Info("No tables with DDL comments found, skipping")
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, table := range tables {
|
||||||
|
if err := m.rebuildTable(table); err != nil {
|
||||||
|
return fmt.Errorf("failed to rebuild table %q: %v", table, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
record = MigrationRecord{
|
||||||
|
MigrationName: "004_fix_ddl_comments",
|
||||||
|
AppliedAt: "datetime('now')",
|
||||||
|
Success: true,
|
||||||
|
Notes: fmt.Sprintf("Rebuilt %d table(s): %s", len(tables), strings.Join(tables, ", ")),
|
||||||
|
}
|
||||||
|
if err := m.DB.Create(&record).Error; err != nil {
|
||||||
|
return fmt.Errorf("failed to record migration: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Migration004FixDDLComments) rebuildTable(table string) error {
|
||||||
|
var originalDDL string
|
||||||
|
if err := m.DB.Raw(
|
||||||
|
"SELECT sql FROM sqlite_master WHERE type = 'table' AND name = ?", table,
|
||||||
|
).Row().Scan(&originalDDL); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanDDL := sqlLineCommentRegexp.ReplaceAllString(originalDDL, "")
|
||||||
|
|
||||||
|
tmpTable := table + "__fixed"
|
||||||
|
createTmp := strings.Replace(cleanDDL, `"`+table+`"`, "`"+tmpTable+"`", 1)
|
||||||
|
if createTmp == cleanDDL {
|
||||||
|
createTmp = strings.Replace(cleanDDL, table, "`"+tmpTable+"`", 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
logging.Info("Rebuilding table %q to remove DDL comments...", table)
|
||||||
|
|
||||||
|
return m.DB.Transaction(func(tx *gorm.DB) error {
|
||||||
|
for _, sql := range []string{
|
||||||
|
"PRAGMA foreign_keys = OFF",
|
||||||
|
fmt.Sprintf("DROP TABLE IF EXISTS `%s`", tmpTable),
|
||||||
|
createTmp,
|
||||||
|
fmt.Sprintf("INSERT INTO `%s` SELECT * FROM `%s`", tmpTable, table),
|
||||||
|
fmt.Sprintf("DROP TABLE `%s`", table),
|
||||||
|
fmt.Sprintf("ALTER TABLE `%s` RENAME TO `%s`", tmpTable, table),
|
||||||
|
"PRAGMA foreign_keys = ON",
|
||||||
|
} {
|
||||||
|
if err := tx.Exec(sql).Error; err != nil {
|
||||||
|
return fmt.Errorf("exec %q: %w", sql, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
logging.Info("Table %q rebuilt successfully", table)
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Migration004FixDDLComments) Down() error {
|
||||||
|
return fmt.Errorf("DDL comment fix migration rollback is not supported")
|
||||||
|
}
|
||||||
|
|
||||||
|
func RunFixDDLCommentsMigration(db *gorm.DB) error {
|
||||||
|
return NewMigration004FixDDLComments(db).Up()
|
||||||
|
}
|
||||||
@@ -33,6 +33,8 @@ func Start(di *dig.Container) {
|
|||||||
func Migrate(db *gorm.DB) {
|
func Migrate(db *gorm.DB) {
|
||||||
logging.Info("Migrating database")
|
logging.Info("Migrating database")
|
||||||
|
|
||||||
|
runMigrations(db)
|
||||||
|
|
||||||
err := db.AutoMigrate(
|
err := db.AutoMigrate(
|
||||||
&model.ServiceControlModel{},
|
&model.ServiceControlModel{},
|
||||||
&model.Config{},
|
&model.Config{},
|
||||||
@@ -66,6 +68,10 @@ func Migrate(db *gorm.DB) {
|
|||||||
func runMigrations(db *gorm.DB) {
|
func runMigrations(db *gorm.DB) {
|
||||||
logging.Info("Running custom database migrations...")
|
logging.Info("Running custom database migrations...")
|
||||||
|
|
||||||
|
if err := migrations.RunFixDDLCommentsMigration(db); err != nil {
|
||||||
|
logging.Error("Failed to run DDL comment fix migration: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
if err := migrations.RunPasswordSecurityMigration(db); err != nil {
|
if err := migrations.RunPasswordSecurityMigration(db); err != nil {
|
||||||
logging.Error("Failed to run password security migration: %v", err)
|
logging.Error("Failed to run password security migration: %v", err)
|
||||||
}
|
}
|
||||||
|
|||||||
57
scripts/build.ps1
Normal file
57
scripts/build.ps1
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
param(
|
||||||
|
[string]$BinaryName = "acc-server-manager",
|
||||||
|
[string]$MigrateBinaryName = "acc-migrate",
|
||||||
|
[string]$GOOS = "windows",
|
||||||
|
[string]$GOARCH = "amd64",
|
||||||
|
[string]$OutputPath = ".\build",
|
||||||
|
[switch]$SkipTests
|
||||||
|
)
|
||||||
|
|
||||||
|
$ErrorActionPreference = "Stop"
|
||||||
|
|
||||||
|
function Write-Status {
|
||||||
|
param([string]$Message, [string]$Color = "Green")
|
||||||
|
Write-Host "[$(Get-Date -Format 'HH:mm:ss')] $Message" -ForegroundColor $Color
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check if Go is installed
|
||||||
|
if (-not (Get-Command go -ErrorAction SilentlyContinue)) {
|
||||||
|
throw "Go is not installed or not in PATH"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Clean output directory
|
||||||
|
if (Test-Path $OutputPath) {
|
||||||
|
Remove-Item -Path $OutputPath -Recurse -Force
|
||||||
|
}
|
||||||
|
New-Item -ItemType Directory -Path $OutputPath -Force | Out-Null
|
||||||
|
|
||||||
|
# Run tests
|
||||||
|
if (-not $SkipTests) {
|
||||||
|
Write-Status "Running tests..."
|
||||||
|
& go test ./...
|
||||||
|
if ($LASTEXITCODE -ne 0) {
|
||||||
|
throw "Tests failed"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Set build environment
|
||||||
|
$env:GOOS = $GOOS
|
||||||
|
$env:GOARCH = $GOARCH
|
||||||
|
|
||||||
|
$ext = if ($GOOS -eq "windows") { ".exe" } else { "" }
|
||||||
|
|
||||||
|
# Build API binary
|
||||||
|
Write-Status "Building API binary ($GOOS/$GOARCH)..."
|
||||||
|
& go build -o "$OutputPath\$BinaryName$ext" .\cmd\api
|
||||||
|
if ($LASTEXITCODE -ne 0) { throw "Failed to build API binary" }
|
||||||
|
|
||||||
|
# Build migration binary
|
||||||
|
Write-Status "Building migration binary ($GOOS/$GOARCH)..."
|
||||||
|
& go build -o "$OutputPath\$MigrateBinaryName$ext" .\cmd\migrate
|
||||||
|
if ($LASTEXITCODE -ne 0) { throw "Failed to build migration binary" }
|
||||||
|
|
||||||
|
# Reset environment
|
||||||
|
Remove-Item Env:\GOOS -ErrorAction SilentlyContinue
|
||||||
|
Remove-Item Env:\GOARCH -ErrorAction SilentlyContinue
|
||||||
|
|
||||||
|
Write-Status "Build completed -> $OutputPath"
|
||||||
79
scripts/build.sh
Executable file
79
scripts/build.sh
Executable file
@@ -0,0 +1,79 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
BINARY_NAME="acc-server-manager"
|
||||||
|
MIGRATE_BINARY_NAME="acc-migrate"
|
||||||
|
GOOS="windows"
|
||||||
|
GOARCH="amd64"
|
||||||
|
OUTPUT_PATH="./build"
|
||||||
|
SKIP_TESTS=false
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
cat <<EOF
|
||||||
|
Usage: $0 [options]
|
||||||
|
|
||||||
|
Options:
|
||||||
|
--binary-name <name> Main binary name (default: acc-server-manager)
|
||||||
|
--migrate-binary-name <n> Migration binary name (default: acc-migrate)
|
||||||
|
--goos <os> Target OS (default: windows)
|
||||||
|
--goarch <arch> Target arch (default: amd64)
|
||||||
|
--output-path <path> Output directory (default: ./build)
|
||||||
|
--skip-tests Skip running tests
|
||||||
|
-h, --help Show this help
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
log() { echo "[$(date '+%H:%M:%S')] $*"; }
|
||||||
|
die() { echo "[$(date '+%H:%M:%S')] ERROR: $*" >&2; exit 1; }
|
||||||
|
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case $1 in
|
||||||
|
--binary-name) BINARY_NAME="$2"; shift 2 ;;
|
||||||
|
--migrate-binary-name) MIGRATE_BINARY_NAME="$2"; shift 2 ;;
|
||||||
|
--goos) GOOS="$2"; shift 2 ;;
|
||||||
|
--goarch) GOARCH="$2"; shift 2 ;;
|
||||||
|
--output-path) OUTPUT_PATH="$2"; shift 2 ;;
|
||||||
|
--skip-tests) SKIP_TESTS=true; shift ;;
|
||||||
|
-h|--help) usage; exit 0 ;;
|
||||||
|
*) die "Unknown option: $1" ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
command -v go >/dev/null 2>&1 || die "Go is not installed or not in PATH"
|
||||||
|
|
||||||
|
# Clean output directory
|
||||||
|
rm -rf "$OUTPUT_PATH"
|
||||||
|
mkdir -p "$OUTPUT_PATH"
|
||||||
|
|
||||||
|
# Run tests on host before setting cross-compilation environment
|
||||||
|
if [[ "$SKIP_TESTS" == false ]]; then
|
||||||
|
log "Running tests..."
|
||||||
|
go test ./...
|
||||||
|
fi
|
||||||
|
|
||||||
|
# CGo cross-compilation setup (set after tests so they run natively)
|
||||||
|
HOST_OS="$(go env GOHOSTOS)"
|
||||||
|
if [[ "$GOOS" == "windows" && "$HOST_OS" != "windows" ]]; then
|
||||||
|
command -v x86_64-w64-mingw32-gcc >/dev/null 2>&1 \
|
||||||
|
|| die "mingw-w64 not found. Install it with: sudo apt install gcc-mingw-w64-x86-64"
|
||||||
|
export CC=x86_64-w64-mingw32-gcc
|
||||||
|
export CGO_ENABLED=1
|
||||||
|
log "Cross-compiling for Windows (CC=$CC)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
EXT=""
|
||||||
|
[[ "$GOOS" == "windows" ]] && EXT=".exe"
|
||||||
|
|
||||||
|
export GOOS GOARCH
|
||||||
|
|
||||||
|
# Build API binary
|
||||||
|
log "Building API binary ($GOOS/$GOARCH)..."
|
||||||
|
go build -o "$OUTPUT_PATH/$BINARY_NAME$EXT" ./cmd/api
|
||||||
|
|
||||||
|
# Build migration binary
|
||||||
|
log "Building migration binary ($GOOS/$GOARCH)..."
|
||||||
|
go build -o "$OUTPUT_PATH/$MIGRATE_BINARY_NAME$EXT" ./cmd/migrate
|
||||||
|
|
||||||
|
unset GOOS GOARCH CC CGO_ENABLED
|
||||||
|
|
||||||
|
log "Build completed -> $OUTPUT_PATH"
|
||||||
@@ -61,42 +61,18 @@ function Build-Application {
|
|||||||
|
|
||||||
Write-Status "Building application..."
|
Write-Status "Building application..."
|
||||||
|
|
||||||
# Clean build directory
|
$buildScript = Join-Path $PSScriptRoot "build.ps1"
|
||||||
if (Test-Path $LocalBuildPath) {
|
$buildArgs = @(
|
||||||
Remove-Item -Path $LocalBuildPath -Recurse -Force
|
"-BinaryName", $BinaryName,
|
||||||
}
|
"-MigrateBinaryName", $MigrateBinaryName,
|
||||||
New-Item -ItemType Directory -Path $LocalBuildPath -Force | Out-Null
|
"-OutputPath", $LocalBuildPath
|
||||||
|
)
|
||||||
|
if ($SkipTests) { $buildArgs += "-SkipTests" }
|
||||||
|
|
||||||
# Run tests
|
& $buildScript @buildArgs
|
||||||
if (-not $SkipTests) {
|
|
||||||
Write-Status "Running tests..."
|
|
||||||
& go test -v ./...
|
|
||||||
if ($LASTEXITCODE -ne 0) {
|
if ($LASTEXITCODE -ne 0) {
|
||||||
throw "Tests failed"
|
throw "Build 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 {
|
function Copy-FilesToServer {
|
||||||
|
|||||||
Reference in New Issue
Block a user