ci: запинить версии gomobile, goimports и docker-действия

This commit is contained in:
samosvalishe
2026-09-21 13:36:18 +03:00
parent a7ec2b949a
commit 802ea7d0af
6 changed files with 179 additions and 4 deletions
+1 -1
View File
@@ -16,7 +16,7 @@ env:
GOLANGCI_VERSION: v2.12.2
GOVULN_VERSION: v1.6.0
GORELEASER_VERSION: v2.17.1
GOMOBILE_VERSION: latest
GOMOBILE_VERSION: v0.0.0-20260821190718-4776eadac327
TASK_VERSION: 3.52.0
jobs:
+2 -2
View File
@@ -12,7 +12,7 @@ permissions:
env:
GO_VERSION: "1.26.7"
GORELEASER_VERSION: v2.17.1
GOMOBILE_VERSION: latest
GOMOBILE_VERSION: v0.0.0-20260821190718-4776eadac327
TASK_VERSION: 3.52.0
jobs:
@@ -120,7 +120,7 @@ jobs:
echo "EOF"
} >> "$GITHUB_OUTPUT"
- uses: docker/build-push-action@v6
- uses: docker/build-push-action@v6.19.2
with:
context: .
file: docker/awg/Dockerfile
+2 -1
View File
@@ -7,6 +7,7 @@ vars:
LDFLAGS: -s -w -checklinkname=0 -X main.version={{.VERSION}}
GOLANGCI_VERSION: v2.12.2
GOVULN_VERSION: v1.6.0
GOIMPORTS_VERSION: v0.49.0
GORELEASER_VERSION: v2.17.1
TASK_VERSION: v3.52.0
@@ -125,7 +126,7 @@ tasks:
tools:install:
desc: Install dev tools (golangci-lint, govulncheck, goreleaser, goimports)
cmds:
- go install golang.org/x/tools/cmd/goimports@latest
- go install golang.org/x/tools/cmd/goimports@{{.GOIMPORTS_VERSION}}
- go install golang.org/x/vuln/cmd/govulncheck@{{.GOVULN_VERSION}}
- go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@{{.GOLANGCI_VERSION}}
- go install github.com/goreleaser/goreleaser/v2@{{.GORELEASER_VERSION}}
+52
View File
@@ -0,0 +1,52 @@
// Package shutdown связывает сигналы ОС с отменой контекста процесса.
package shutdown
import (
"context"
"os"
"os/signal"
"syscall"
"time"
"github.com/samosvalishe/free-turn-proxy/internal/logx"
)
// Grace - время на доработку после отмены контекста.
const Grace = 5 * time.Second
// Watch отменяет ctx по SIGINT/SIGTERM. Возвращённый stop снимает обработчик при
// штатном выходе - без него процесс уходил бы в форс-выход с кодом 1 на каждой остановке.
func Watch(parent context.Context, log logx.Logger) (context.Context, func()) {
log = logx.OrNop(log)
ctx, cancel := context.WithCancel(parent)
sig := make(chan os.Signal, 1)
signal.Notify(sig, syscall.SIGTERM, syscall.SIGINT)
done := make(chan struct{})
go func() {
select {
case <-sig:
case <-done:
return
}
log.Infof("Terminating...")
cancel()
select {
case <-sig:
log.Warnf("Forced exit on second signal")
case <-done:
return
case <-time.After(Grace):
log.Warnf("Forced exit after %s shutdown timeout", Grace)
}
// Форс-выход сжигает defer-ы (в том числе снятие host-маршрутов) - только как крайняя мера.
os.Exit(1)
}()
return ctx, func() {
signal.Stop(sig)
close(done)
cancel()
}
}
+43
View File
@@ -0,0 +1,43 @@
package wire
import (
"fmt"
"net"
dtlsnet "github.com/pion/dtls/v3/pkg/net"
pionudp "github.com/pion/transport/v4/udp"
)
// NewServerCodec создаёт кодек для очередного принятого соединения: состояние RTP-сессии
// у каждого клиента своё, общий у профиля только ключ.
type NewServerCodec func() (Codec, error)
// ListenCodec - единственная серверная обвязка на все профили: они отличались только
// именем пакета в текстах ошибок.
func ListenCodec(addr *net.UDPAddr, newCodec NewServerCodec) (dtlsnet.PacketListener, error) {
inner, err := pionudp.Listen("udp", addr)
if err != nil {
return nil, fmt.Errorf("wire: udp listen: %w", err)
}
return &packetListener{inner: dtlsnet.PacketListenerFromListener(inner), newCodec: newCodec}, nil
}
type packetListener struct {
inner dtlsnet.PacketListener
newCodec NewServerCodec
}
func (l *packetListener) Accept() (net.PacketConn, net.Addr, error) {
pc, addr, err := l.inner.Accept()
if err != nil {
return pc, addr, err
}
codec, err := l.newCodec()
if err != nil {
return nil, addr, err
}
return &RelayPacketConn{Relay: pc, Codec: codec}, addr, nil
}
func (l *packetListener) Close() error { return l.inner.Close() }
func (l *packetListener) Addr() net.Addr { return l.inner.Addr() }
+79
View File
@@ -0,0 +1,79 @@
package wire
import (
"crypto/rand"
"net"
"testing"
"time"
)
// Серверная обвязка общая для всех профилей - проверяем каждый через реальный UDP.
func TestListenCodecRoundTrip(t *testing.T) {
t.Parallel()
for _, profile := range []string{ProfileRTPOpus, ProfileRTPOpus2, ProfileRTPOpus3} {
t.Run(profile, func(t *testing.T) {
t.Parallel()
key := make([]byte, 32)
if _, err := rand.Read(key); err != nil {
t.Fatal(err)
}
ln, err := Listen(profile, &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1)}, key)
if err != nil {
t.Fatal(err)
}
defer func() { _ = ln.Close() }()
raw, err := net.ListenUDP("udp", &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1)})
if err != nil {
t.Fatal(err)
}
defer func() { _ = raw.Close() }()
codec, err := NewClientCodec(profile, key)
if err != nil {
t.Fatal(err)
}
client := &RelayPacketConn{Relay: raw, Peer: ln.Addr(), Codec: codec}
want := []byte("obfuscated payload")
if _, err = client.WriteTo(want, nil); err != nil {
t.Fatal(err)
}
srv, _, err := ln.Accept()
if err != nil {
t.Fatal(err)
}
defer func() { _ = srv.Close() }()
buf := make([]byte, 1500)
if err = srv.SetReadDeadline(time.Now().Add(5 * time.Second)); err != nil {
t.Fatal(err)
}
n, from, err := srv.ReadFrom(buf)
if err != nil {
t.Fatal(err)
}
if string(buf[:n]) != string(want) {
t.Fatalf("server got %q, want %q", buf[:n], want)
}
// Peer у серверной стороны пустой: ответ обязан уйти отправителю.
if _, err = srv.WriteTo(buf[:n], from); err != nil {
t.Fatal(err)
}
if err = client.SetReadDeadline(time.Now().Add(5 * time.Second)); err != nil {
t.Fatal(err)
}
n, _, err = client.ReadFrom(buf)
if err != nil {
t.Fatal(err)
}
if string(buf[:n]) != string(want) {
t.Fatalf("client got %q, want %q", buf[:n], want)
}
})
}
}