mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-10-01 11:42:07 +03:00
fix(amneziawg): resolve all 3 real CI failures (typecheck/lint/codegen)
Found by checking the fork's Actions tab after the last two pushes —
the release build passed (it doesn't run these checks) but the
separate CI workflow caught three real issues:
- golangci-lint (noctx): every internal/amneziawg/manager.go exec.Command
call is now exec.CommandContext with a 30s timeout, so a hung
awg-quick/awg invocation can't block the reconcile job indefinitely
(mirrors internal/mtproto/process.go's own CommandContext usage).
- tsc --noEmit: frontend/src/schemas/client.ts's hand-maintained
InboundOptionSchema (used by the useClients hook, separate from the
auto-generated one in generated/) never got an awgServer field added
when the AmneziaWG frontend work was done — every read of
inbound.awgServer.* in amneziawgConfig.ts was typing as {}. Added
AwgServerOptionSchema, nested (not flattened like wg*) to match what
amneziawgConfig.ts already expects. Also guarded server.publicKey in
inbound-link.ts's genAmneziaWGLink against the schema's optional type.
- codegen staleness: frontend/public/openapi.json is produced by a Node
script (gen:api) this machine can't run; hand-applied the exact diff
the CI failure log already showed (amneziawg protocol enum entry,
ServerSettings schema, InboundOption.awgServer, one example payload),
verified as valid JSON.
Also confirmed independently by this run: install_amneziawg (previous
commit) installed and loaded the DKMS module successfully on both amd64
and arm64 CI runners. The two "Deploy Smoke Tests" failures are
unrelated to this change — this fork has only ever published the
dev-latest pre-release, and GitHub's /releases/latest API deliberately
excludes pre-releases, so the smoke test's no-argument install path
(which resolves "latest") has nothing to find. Not a regression; needs
an actual tagged release whenever that's wanted.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -3,6 +3,7 @@ package amneziawg
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"maps"
|
||||
@@ -534,9 +535,16 @@ func removeConfigFile(interfaceName string) {
|
||||
}
|
||||
}
|
||||
|
||||
// awgCommandTimeout bounds every short-lived awg/awg-quick invocation so a
|
||||
// hung command (e.g. a stuck kernel module operation) can't block the
|
||||
// reconcile job indefinitely.
|
||||
const awgCommandTimeout = 30 * time.Second
|
||||
|
||||
// interfaceUp brings an AmneziaWG interface up via awg-quick.
|
||||
func interfaceUp(interfaceName string) error {
|
||||
out, err := exec.Command("awg-quick", "up", configPath(interfaceName)).CombinedOutput()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), awgCommandTimeout)
|
||||
defer cancel()
|
||||
out, err := exec.CommandContext(ctx, "awg-quick", "up", configPath(interfaceName)).CombinedOutput()
|
||||
if err != nil {
|
||||
return fmt.Errorf("awg-quick up %s failed: %s: %w", interfaceName, strings.TrimSpace(string(out)), err)
|
||||
}
|
||||
@@ -545,7 +553,9 @@ func interfaceUp(interfaceName string) error {
|
||||
|
||||
// interfaceDown takes an AmneziaWG interface down via awg-quick.
|
||||
func interfaceDown(interfaceName string) error {
|
||||
out, err := exec.Command("awg-quick", "down", configPath(interfaceName)).CombinedOutput()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), awgCommandTimeout)
|
||||
defer cancel()
|
||||
out, err := exec.CommandContext(ctx, "awg-quick", "down", configPath(interfaceName)).CombinedOutput()
|
||||
if err != nil {
|
||||
return fmt.Errorf("awg-quick down %s failed: %s: %w", interfaceName, strings.TrimSpace(string(out)), err)
|
||||
}
|
||||
@@ -555,7 +565,9 @@ func interfaceDown(interfaceName string) error {
|
||||
// isInterfaceUp checks whether the named AmneziaWG interface currently
|
||||
// exists.
|
||||
func isInterfaceUp(interfaceName string) bool {
|
||||
return exec.Command("awg", "show", interfaceName).Run() == nil
|
||||
ctx, cancel := context.WithTimeout(context.Background(), awgCommandTimeout)
|
||||
defer cancel()
|
||||
return exec.CommandContext(ctx, "awg", "show", interfaceName).Run() == nil
|
||||
}
|
||||
|
||||
// syncConfig applies a peers-only config change without dropping existing
|
||||
@@ -566,13 +578,17 @@ func syncConfig(inst Instance) error {
|
||||
return interfaceUp(inst.InterfaceName)
|
||||
}
|
||||
|
||||
stripped, err := exec.Command("awg-quick", "strip", configPath(inst.InterfaceName)).Output()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), awgCommandTimeout)
|
||||
defer cancel()
|
||||
stripped, err := exec.CommandContext(ctx, "awg-quick", "strip", configPath(inst.InterfaceName)).Output()
|
||||
if err != nil {
|
||||
logger.Warningf("amneziawg: awg-quick strip failed for %s, restarting: %v", inst.InterfaceName, err)
|
||||
return restartInterface(inst.InterfaceName)
|
||||
}
|
||||
|
||||
sync := exec.Command("awg", "syncconf", inst.InterfaceName, "/dev/stdin")
|
||||
syncCtx, syncCancel := context.WithTimeout(context.Background(), awgCommandTimeout)
|
||||
defer syncCancel()
|
||||
sync := exec.CommandContext(syncCtx, "awg", "syncconf", inst.InterfaceName, "/dev/stdin")
|
||||
sync.Stdin = bytes.NewReader(stripped)
|
||||
if out, err := sync.CombinedOutput(); err != nil {
|
||||
logger.Warningf("amneziawg: awg syncconf failed for %s, restarting: %s: %v", inst.InterfaceName, strings.TrimSpace(string(out)), err)
|
||||
@@ -601,7 +617,9 @@ type peerStat struct {
|
||||
// preshared-key, endpoint, allowed-ips, latest-handshake, transfer-rx,
|
||||
// transfer-tx, persistent-keepalive).
|
||||
func getPeerStats(interfaceName string) ([]peerStat, error) {
|
||||
out, err := exec.Command("awg", "show", interfaceName, "dump").Output()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), awgCommandTimeout)
|
||||
defer cancel()
|
||||
out, err := exec.CommandContext(ctx, "awg", "show", interfaceName, "dump").Output()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("awg show %s dump failed: %w", interfaceName, err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user