mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-06-06 21:24:10 +00:00
fix migrate panic and include release workflow updates
This commit is contained in:
parent
7db5b9e214
commit
062f2bd714
3 changed files with 109 additions and 30 deletions
103
.github/workflows/release.yml
vendored
103
.github/workflows/release.yml
vendored
|
|
@ -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 ../..
|
||||||
|
|
|
||||||
|
|
@ -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
14
main.go
|
|
@ -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 {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue