fix migrate panic and include release workflow updates

This commit is contained in:
Sora39831 2026-04-05 03:12:29 +08:00
parent 7db5b9e214
commit 062f2bd714
3 changed files with 109 additions and 30 deletions

View file

@ -91,6 +91,15 @@ jobs:
go-version-file: go.mod go-version-file: go.mod
check-latest: true check-latest: true
- name: Cache Go build
uses: actions/cache@v4
with:
path: |
~/.cache/go-build
key: gobuild-${{ matrix.platform }}-${{ hashFiles('**/*.go', 'go.mod', 'go.sum') }}
restore-keys: |
gobuild-${{ matrix.platform }}-
- name: Get latest Xray version - name: Get latest Xray version
id: xray_version id: xray_version
run: | run: |
@ -98,6 +107,66 @@ jobs:
echo "version=$LATEST" >> "$GITHUB_OUTPUT" echo "version=$LATEST" >> "$GITHUB_OUTPUT"
echo "Latest Xray version: $LATEST" echo "Latest Xray version: $LATEST"
- name: Cache Xray binary
id: cache_xray
uses: actions/cache@v4
with:
path: /tmp/xray
key: xray-${{ matrix.platform }}-${{ steps.xray_version.outputs.version }}
restore-keys: |
xray-${{ matrix.platform }}-
- name: Download Xray
if: steps.cache_xray.outputs.cache-hit != 'true'
run: |
Xray_URL="https://github.com/XTLS/Xray-core/releases/download/${{ steps.xray_version.outputs.version }}/"
declare -A XRAY_MAP=(
[amd64]="Xray-linux-64.zip"
[arm64]="Xray-linux-arm64-v8a.zip"
[armv7]="Xray-linux-arm32-v7a.zip"
[armv6]="Xray-linux-arm32-v6.zip"
[386]="Xray-linux-32.zip"
[armv5]="Xray-linux-arm32-v5.zip"
[s390x]="Xray-linux-s390x.zip"
)
XRAY_FILE="${XRAY_MAP[${{ matrix.platform }}]}"
[ -z "$XRAY_FILE" ] && { echo "Unknown platform: ${{ matrix.platform }}" >&2; exit 1; }
mkdir -p /tmp/xray
curl -fL -sS --retry 3 --retry-delay 5 -o "/tmp/xray/$XRAY_FILE" "${Xray_URL}${XRAY_FILE}"
cd /tmp/xray
unzip -q "$XRAY_FILE"
rm -f "$XRAY_FILE"
- name: Get cache date
id: cache_date
run: echo "date=$(date -u +%Y-%m-%d)" >> "$GITHUB_OUTPUT"
- name: Cache geo data
id: cache_geo
uses: actions/cache@v4
with:
path: /tmp/geo
key: geo-${{ steps.cache_date.outputs.date }}
- name: Download geo data
if: steps.cache_geo.outputs.cache-hit != 'true'
run: |
mkdir -p /tmp/geo
cd /tmp/geo
curl -fL -sS --retry 3 -o geoip.dat \
https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geoip.dat &
curl -fL -sS --retry 3 -o geosite.dat \
https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geosite.dat &
curl -fL -sS --retry 3 -o geoip_IR.dat \
https://github.com/chocolate4u/Iran-v2ray-rules/releases/latest/download/geoip.dat &
curl -fL -sS --retry 3 -o geosite_IR.dat \
https://github.com/chocolate4u/Iran-v2ray-rules/releases/latest/download/geosite.dat &
curl -fL -sS --retry 3 -o geoip_RU.dat \
https://github.com/runetfreedom/russia-v2ray-rules-dat/releases/latest/download/geoip.dat &
curl -fL -sS --retry 3 -o geosite_RU.dat \
https://github.com/runetfreedom/russia-v2ray-rules-dat/releases/latest/download/geosite.dat &
wait
- name: Cache Bootlin toolchain - name: Cache Bootlin toolchain
uses: actions/cache@v4 uses: actions/cache@v4
with: with:
@ -157,37 +226,11 @@ jobs:
mkdir x-ui/bin mkdir x-ui/bin
cd x-ui/bin cd x-ui/bin
# Download Xray # Copy Xray from cache
Xray_URL="https://github.com/XTLS/Xray-core/releases/download/${{ steps.xray_version.outputs.version }}/" cp /tmp/xray/xray .
declare -A XRAY_MAP=(
[amd64]="Xray-linux-64.zip"
[arm64]="Xray-linux-arm64-v8a.zip"
[armv7]="Xray-linux-arm32-v7a.zip"
[armv6]="Xray-linux-arm32-v6.zip"
[386]="Xray-linux-32.zip"
[armv5]="Xray-linux-arm32-v5.zip"
[s390x]="Xray-linux-s390x.zip"
)
XRAY_FILE="${XRAY_MAP[${{ matrix.platform }}]}"
[ -z "$XRAY_FILE" ] && { echo "Unknown platform: ${{ matrix.platform }}" >&2; exit 1; }
curl -fL -sS --retry 3 --retry-delay 5 -o "$XRAY_FILE" "${Xray_URL}${XRAY_FILE}"
unzip -q "$XRAY_FILE"
rm -f "$XRAY_FILE"
# Download geo data in parallel # Copy geo data from cache
curl -fL -sS --retry 3 -o geoip.dat \ cp /tmp/geo/* .
https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geoip.dat &
curl -fL -sS --retry 3 -o geosite.dat \
https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geosite.dat &
curl -fL -sS --retry 3 -o geoip_IR.dat \
https://github.com/chocolate4u/Iran-v2ray-rules/releases/latest/download/geoip.dat &
curl -fL -sS --retry 3 -o geosite_IR.dat \
https://github.com/chocolate4u/Iran-v2ray-rules/releases/latest/download/geosite.dat &
curl -fL -sS --retry 3 -o geoip_RU.dat \
https://github.com/runetfreedom/russia-v2ray-rules-dat/releases/latest/download/geoip.dat &
curl -fL -sS --retry 3 -o geosite_RU.dat \
https://github.com/runetfreedom/russia-v2ray-rules-dat/releases/latest/download/geosite.dat &
wait
mv xray xray-linux-${{ matrix.platform }} mv xray xray-linux-${{ matrix.platform }}
cd ../.. cd ../..

View file

@ -7,6 +7,7 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"runtime" "runtime"
"sync"
"time" "time"
"github.com/mhsanaei/3x-ui/v2/config" "github.com/mhsanaei/3x-ui/v2/config"
@ -22,6 +23,7 @@ const (
var ( var (
logger *logging.Logger logger *logging.Logger
logFile *os.File logFile *os.File
once sync.Once
// logBuffer maintains recent log entries in memory for web UI retrieval // logBuffer maintains recent log entries in memory for web UI retrieval
logBuffer []struct { logBuffer []struct {
@ -31,6 +33,16 @@ var (
} }
) )
// ensureLogger lazily initializes logger to avoid nil-pointer panics
// when code paths log before explicit InitLogger() call.
func ensureLogger() {
once.Do(func() {
if logger == nil {
InitLogger(logging.INFO)
}
})
}
// InitLogger initializes dual logging backends: console/syslog and file. // InitLogger initializes dual logging backends: console/syslog and file.
// Console logging uses the specified level, file logging always uses DEBUG level. // Console logging uses the specified level, file logging always uses DEBUG level.
func InitLogger(level logging.Level) { func InitLogger(level logging.Level) {
@ -127,60 +139,70 @@ func CloseLogger() {
// Debug logs a debug message and adds it to the log buffer. // Debug logs a debug message and adds it to the log buffer.
func Debug(args ...any) { func Debug(args ...any) {
ensureLogger()
logger.Debug(args...) logger.Debug(args...)
addToBuffer("DEBUG", fmt.Sprint(args...)) addToBuffer("DEBUG", fmt.Sprint(args...))
} }
// Debugf logs a formatted debug message and adds it to the log buffer. // Debugf logs a formatted debug message and adds it to the log buffer.
func Debugf(format string, args ...any) { func Debugf(format string, args ...any) {
ensureLogger()
logger.Debugf(format, args...) logger.Debugf(format, args...)
addToBuffer("DEBUG", fmt.Sprintf(format, args...)) addToBuffer("DEBUG", fmt.Sprintf(format, args...))
} }
// Info logs an info message and adds it to the log buffer. // Info logs an info message and adds it to the log buffer.
func Info(args ...any) { func Info(args ...any) {
ensureLogger()
logger.Info(args...) logger.Info(args...)
addToBuffer("INFO", fmt.Sprint(args...)) addToBuffer("INFO", fmt.Sprint(args...))
} }
// Infof logs a formatted info message and adds it to the log buffer. // Infof logs a formatted info message and adds it to the log buffer.
func Infof(format string, args ...any) { func Infof(format string, args ...any) {
ensureLogger()
logger.Infof(format, args...) logger.Infof(format, args...)
addToBuffer("INFO", fmt.Sprintf(format, args...)) addToBuffer("INFO", fmt.Sprintf(format, args...))
} }
// Notice logs a notice message and adds it to the log buffer. // Notice logs a notice message and adds it to the log buffer.
func Notice(args ...any) { func Notice(args ...any) {
ensureLogger()
logger.Notice(args...) logger.Notice(args...)
addToBuffer("NOTICE", fmt.Sprint(args...)) addToBuffer("NOTICE", fmt.Sprint(args...))
} }
// Noticef logs a formatted notice message and adds it to the log buffer. // Noticef logs a formatted notice message and adds it to the log buffer.
func Noticef(format string, args ...any) { func Noticef(format string, args ...any) {
ensureLogger()
logger.Noticef(format, args...) logger.Noticef(format, args...)
addToBuffer("NOTICE", fmt.Sprintf(format, args...)) addToBuffer("NOTICE", fmt.Sprintf(format, args...))
} }
// Warning logs a warning message and adds it to the log buffer. // Warning logs a warning message and adds it to the log buffer.
func Warning(args ...any) { func Warning(args ...any) {
ensureLogger()
logger.Warning(args...) logger.Warning(args...)
addToBuffer("WARNING", fmt.Sprint(args...)) addToBuffer("WARNING", fmt.Sprint(args...))
} }
// Warningf logs a formatted warning message and adds it to the log buffer. // Warningf logs a formatted warning message and adds it to the log buffer.
func Warningf(format string, args ...any) { func Warningf(format string, args ...any) {
ensureLogger()
logger.Warningf(format, args...) logger.Warningf(format, args...)
addToBuffer("WARNING", fmt.Sprintf(format, args...)) addToBuffer("WARNING", fmt.Sprintf(format, args...))
} }
// Error logs an error message and adds it to the log buffer. // Error logs an error message and adds it to the log buffer.
func Error(args ...any) { func Error(args ...any) {
ensureLogger()
logger.Error(args...) logger.Error(args...)
addToBuffer("ERROR", fmt.Sprint(args...)) addToBuffer("ERROR", fmt.Sprint(args...))
} }
// Errorf logs a formatted error message and adds it to the log buffer. // Errorf logs a formatted error message and adds it to the log buffer.
func Errorf(format string, args ...any) { func Errorf(format string, args ...any) {
ensureLogger()
logger.Errorf(format, args...) logger.Errorf(format, args...)
addToBuffer("ERROR", fmt.Sprintf(format, args...)) addToBuffer("ERROR", fmt.Sprintf(format, args...))
} }

14
main.go
View file

@ -391,6 +391,20 @@ func GetListenIP(getListen bool) {
// migrateDb performs database migration operations for the 3x-ui panel. // migrateDb performs database migration operations for the 3x-ui panel.
func migrateDb() { func migrateDb() {
inboundService := service.InboundService{} inboundService := service.InboundService{}
switch config.GetLogLevel() {
case config.Debug:
logger.InitLogger(logging.DEBUG)
case config.Info:
logger.InitLogger(logging.INFO)
case config.Notice:
logger.InitLogger(logging.NOTICE)
case config.Warning:
logger.InitLogger(logging.WARNING)
case config.Error:
logger.InitLogger(logging.ERROR)
default:
logger.InitLogger(logging.INFO)
}
err := database.InitDB() err := database.InitDB()
if err != nil { if err != nil {