ci: ko build

This commit is contained in:
VaalaCat
2024-12-24 14:38:34 +00:00
parent c80788b4ba
commit e9a59a7525
17 changed files with 294 additions and 131 deletions

View File

@@ -41,27 +41,13 @@ jobs:
automatic_release_tag: latest automatic_release_tag: latest
files: | files: |
dist/* dist/*
- name: Setup ko
build-docker: uses: ko-build/setup-ko@v0.6
runs-on: ubuntu-latest env:
steps: KO_DOCKER_REPO: docker.io/vaalacat/frp-panel
- uses: actions/checkout@v4 - env:
with:
fetch-depth: 0
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }} username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }} password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and push run: |
uses: docker/build-push-action@v3 echo "${password}" | ko login docker.io --username ${username} --password-stdin
with: ko build ./cmd/frpp --bare
context: .
file: ./Dockerfile.standalone
push: true
platforms: linux/amd64,linux/arm64
tags: vaalacat/frp-panel:latest

View File

@@ -42,32 +42,14 @@ jobs:
automatic_release_tag: ${{ steps.get_version.outputs.VERSION }} automatic_release_tag: ${{ steps.get_version.outputs.VERSION }}
files: | files: |
dist/* dist/*
- name: Setup ko
build-docker: uses: ko-build/setup-ko@v0.6
runs-on: ubuntu-latest env:
steps: KO_DOCKER_REPO: docker.io/vaalacat/frp-panel
- name: Get version - name: Build image with ko
id: get_version env:
run: echo ::set-output name=VERSION::${GITHUB_REF/refs\/tags\//}
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Get git tag history
run: git fetch -a
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }} username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }} password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and push run: |
uses: docker/build-push-action@v3 echo "${password}" | ko login docker.io --username ${username} --password-stdin
with: ko build ./cmd/frpp --bare -t ${{ steps.get_version.outputs.VERSION }}
context: .
file: ./Dockerfile.standalone
push: true
platforms: linux/amd64,linux/arm64
tags: vaalacat/frp-panel:${{ steps.get_version.outputs.VERSION }}

15
.ko.yaml Normal file
View File

@@ -0,0 +1,15 @@
defaultBaseImage: alpine
builds:
- id: frpp
dir: .
main: ./cmd/frpp
ldflags:
- -s -w
- -X github.com/VaalaCat/frp-panel/conf.buildDate={{.Date}}
- -X github.com/VaalaCat/frp-panel/conf.gitCommit={{.Git.FullCommit}}
- -X github.com/VaalaCat/frp-panel/conf.gitVersion={{.Git.Tag}}
- -X github.com/VaalaCat/frp-panel/conf.gitBranch={{.Git.Branch}}
defaultPlatforms:
- all

View File

@@ -19,6 +19,7 @@ ARCH="all"
BUILD_DATE="$(date -u +'%Y-%m-%dT%H:%M:%SZ')" BUILD_DATE="$(date -u +'%Y-%m-%dT%H:%M:%SZ')"
GIT_COMMIT="$(git rev-parse HEAD)" GIT_COMMIT="$(git rev-parse HEAD)"
VERSION="$(git describe --tags --abbrev=0 | tr -d '\n')" VERSION="$(git describe --tags --abbrev=0 | tr -d '\n')"
GIT_BRANCH="$(git rev-parse --abbrev-ref HEAD)"
# Parse arguments # Parse arguments
while [[ "$#" -gt 0 ]]; do while [[ "$#" -gt 0 ]]; do
@@ -50,7 +51,7 @@ echo "Build Date: $BUILD_DATE"
echo "Git Commit: $GIT_COMMIT" echo "Git Commit: $GIT_COMMIT"
echo "Version: $VERSION" echo "Version: $VERSION"
BUILD_LD_FLAGS="-X 'github.com/VaalaCat/frp-panel/conf.buildDate=${BUILD_DATE}' -X 'github.com/VaalaCat/frp-panel/conf.gitCommit=${GIT_COMMIT}' -X 'github.com/VaalaCat/frp-panel/conf.gitVersion=${VERSION}'" BUILD_LD_FLAGS="-X 'github.com/VaalaCat/frp-panel/conf.buildDate=${BUILD_DATE}' -X 'github.com/VaalaCat/frp-panel/conf.gitCommit=${GIT_COMMIT}' -X 'github.com/VaalaCat/frp-panel/conf.gitVersion=${VERSION}' -X 'github.com/VaalaCat/frp-panel/conf.gitBranch=${GIT_BRANCH}'"
if [[ "$SKIP_FRONTEND" == "true" ]]; then if [[ "$SKIP_FRONTEND" == "true" ]]; then
echo "Skipping frontend build" echo "Skipping frontend build"

View File

@@ -3,11 +3,13 @@ package main
import ( import (
"context" "context"
"fmt" "fmt"
"os"
"github.com/VaalaCat/frp-panel/conf" "github.com/VaalaCat/frp-panel/conf"
"github.com/VaalaCat/frp-panel/logger" "github.com/VaalaCat/frp-panel/logger"
"github.com/VaalaCat/frp-panel/utils" "github.com/VaalaCat/frp-panel/utils"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/pflag"
) )
var ( var (
@@ -140,6 +142,7 @@ func initCommand() {
rootCmd.AddCommand(clientCmd, serverCmd, masterCmd, versionCmd, rootCmd.AddCommand(clientCmd, serverCmd, masterCmd, versionCmd,
installServiceCmd, uninstallServiceCmd, installServiceCmd, uninstallServiceCmd,
startServiceCmd, stopServiceCmd, restartServiceCmd) startServiceCmd, stopServiceCmd, restartServiceCmd)
clientCmd.Flags().StringVarP(&clientSecret, "secret", "s", "", "client secret") clientCmd.Flags().StringVarP(&clientSecret, "secret", "s", "", "client secret")
serverCmd.Flags().StringVarP(&clientSecret, "secret", "s", "", "client secret") serverCmd.Flags().StringVarP(&clientSecret, "secret", "s", "", "client secret")
clientCmd.Flags().StringVarP(&clientID, "id", "i", "", "client id") clientCmd.Flags().StringVarP(&clientID, "id", "i", "", "client id")
@@ -191,3 +194,11 @@ func patchConfig(host, secret, clientID, clientSecret, apiScheme string, rpcPort
conf.Get().Master.APIHost, conf.Get().Master.APIPort, conf.Get().Master.APIHost, conf.Get().Master.APIPort,
conf.Get().Master.APIScheme) conf.Get().Master.APIScheme)
} }
func setMasterCommandIfNonePresent() {
cmd, _, err := rootCmd.Find(os.Args[1:])
if err == nil && cmd.Use == rootCmd.Use && cmd.Flags().Parse(os.Args[1:]) != pflag.ErrHelp {
args := append([]string{"master"}, os.Args[1:]...)
rootCmd.SetArgs(args)
}
}

View File

@@ -14,5 +14,6 @@ func main() {
conf.InitConfig() conf.InitConfig()
rpc.InitRPCClients() rpc.InitRPCClients()
setMasterCommandIfNonePresent()
rootCmd.Execute() rootCmd.Execute()
} }

View File

@@ -3,6 +3,7 @@ package main
import ( import (
"context" "context"
"embed" "embed"
"path/filepath"
bizmaster "github.com/VaalaCat/frp-panel/biz/master" bizmaster "github.com/VaalaCat/frp-panel/biz/master"
"github.com/VaalaCat/frp-panel/biz/master/auth" "github.com/VaalaCat/frp-panel/biz/master/auth"
@@ -80,6 +81,12 @@ func initDatabase(c context.Context) {
switch conf.Get().DB.Type { switch conf.Get().DB.Type {
case "sqlite3": case "sqlite3":
if err := utils.EnsureDirectoryExists(conf.Get().DB.DSN); err != nil {
logrus.WithError(err).Warnf("ensure directory failed, data location: [%s], keep data in current directory", conf.Get().DB.DSN)
conf.Get().DB.DSN = filepath.Base(conf.Get().DB.DSN)
logrus.Infof("new data location: [%s]", conf.Get().DB.DSN)
}
if sqlitedb, err := gorm.Open(sqlite.Open(conf.Get().DB.DSN), &gorm.Config{}); err != nil { if sqlitedb, err := gorm.Open(sqlite.Open(conf.Get().DB.DSN), &gorm.Config{}); err != nil {
logrus.Panic(err) logrus.Panic(err)
} else { } else {

View File

@@ -43,7 +43,7 @@ type Config struct {
} `env-prefix:"SERVER_"` } `env-prefix:"SERVER_"`
DB struct { DB struct {
Type string `env:"TYPE" env-default:"sqlite3" env-description:"db type, mysql or sqlite3 and so on"` Type string `env:"TYPE" env-default:"sqlite3" env-description:"db type, mysql or sqlite3 and so on"`
DSN string `env:"DSN" env-default:"data.db" env-description:"db dsn, for sqlite is path, other is dsn, look at https://github.com/go-sql-driver/mysql#dsn-data-source-name"` DSN string `env:"DSN" env-default:"/data/data.db" env-description:"db dsn, for sqlite is path, other is dsn, look at https://github.com/go-sql-driver/mysql#dsn-data-source-name"`
} `env-prefix:"DB_"` } `env-prefix:"DB_"`
Client struct { Client struct {
ID string `env:"ID" env-description:"client id"` ID string `env:"ID" env-description:"client id"`

View File

@@ -12,12 +12,14 @@ import (
var ( var (
gitVersion = "dev-build" gitVersion = "dev-build"
gitCommit = "" gitCommit = ""
gitBranch = ""
buildDate = "1970-01-01T00:00:00Z" buildDate = "1970-01-01T00:00:00Z"
) )
type VersionInfo struct { type VersionInfo struct {
GitVersion string `json:"gitVersion" yaml:"gitVersion"` GitVersion string `json:"gitVersion" yaml:"gitVersion"`
GitCommit string `json:"gitCommit" yaml:"gitCommit"` GitCommit string `json:"gitCommit" yaml:"gitCommit"`
GitBranch string `json:"gitBranch" yaml:"gitBranch"`
BuildDate string `json:"buildDate" yaml:"buildDate"` BuildDate string `json:"buildDate" yaml:"buildDate"`
GoVersion string `json:"goVersion" yaml:"goVersion"` GoVersion string `json:"goVersion" yaml:"goVersion"`
Compiler string `json:"compiler" yaml:"compiler"` Compiler string `json:"compiler" yaml:"compiler"`
@@ -42,6 +44,7 @@ func (v *VersionInfo) ToProto() *pb.ClientVersion {
return &pb.ClientVersion{ return &pb.ClientVersion{
GitVersion: v.GitVersion, GitVersion: v.GitVersion,
GitCommit: v.GitCommit, GitCommit: v.GitCommit,
GitBranch: v.GitBranch,
BuildDate: v.BuildDate, BuildDate: v.BuildDate,
GoVersion: v.GoVersion, GoVersion: v.GoVersion,
Compiler: v.Compiler, Compiler: v.Compiler,
@@ -53,6 +56,7 @@ func GetVersion() *VersionInfo {
return &VersionInfo{ return &VersionInfo{
GitVersion: gitVersion, GitVersion: gitVersion,
GitCommit: gitCommit, GitCommit: gitCommit,
GitBranch: gitBranch,
BuildDate: buildDate, BuildDate: buildDate,
GoVersion: runtime.Version(), GoVersion: runtime.Version(),
Compiler: runtime.Compiler, Compiler: runtime.Compiler,

View File

@@ -27,6 +27,7 @@ message ClientVersion {
string GoVersion = 4; string GoVersion = 4;
string Compiler = 5; string Compiler = 5;
string Platform = 6; string Platform = 6;
string GitBranch = 7;
} }
message GetClientsStatusRequest { message GetClientsStatusRequest {

View File

@@ -176,6 +176,7 @@ type ClientVersion struct {
GoVersion string `protobuf:"bytes,4,opt,name=GoVersion,proto3" json:"GoVersion,omitempty"` GoVersion string `protobuf:"bytes,4,opt,name=GoVersion,proto3" json:"GoVersion,omitempty"`
Compiler string `protobuf:"bytes,5,opt,name=Compiler,proto3" json:"Compiler,omitempty"` Compiler string `protobuf:"bytes,5,opt,name=Compiler,proto3" json:"Compiler,omitempty"`
Platform string `protobuf:"bytes,6,opt,name=Platform,proto3" json:"Platform,omitempty"` Platform string `protobuf:"bytes,6,opt,name=Platform,proto3" json:"Platform,omitempty"`
GitBranch string `protobuf:"bytes,7,opt,name=GitBranch,proto3" json:"GitBranch,omitempty"`
} }
func (x *ClientVersion) Reset() { func (x *ClientVersion) Reset() {
@@ -250,6 +251,13 @@ func (x *ClientVersion) GetPlatform() string {
return "" return ""
} }
func (x *ClientVersion) GetGitBranch() string {
if x != nil {
return x.GitBranch
}
return ""
}
type GetClientsStatusRequest struct { type GetClientsStatusRequest struct {
state protoimpl.MessageState state protoimpl.MessageState
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
@@ -502,7 +510,7 @@ var file_api_master_proto_rawDesc = []byte{
0x12, 0x10, 0x0a, 0x0c, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x12, 0x10, 0x0a, 0x0c, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52,
0x10, 0x03, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x42, 0x07, 0x10, 0x03, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x42, 0x07,
0x0a, 0x05, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x42, 0x0f, 0x0a, 0x0d, 0x5f, 0x63, 0x6f, 0x6e, 0x6e, 0x0a, 0x05, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x42, 0x0f, 0x0a, 0x0d, 0x5f, 0x63, 0x6f, 0x6e, 0x6e,
0x65, 0x63, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x22, 0xc1, 0x01, 0x0a, 0x0d, 0x43, 0x6c, 0x69, 0x65, 0x63, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x22, 0xdf, 0x01, 0x0a, 0x0d, 0x43, 0x6c, 0x69,
0x65, 0x6e, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x0a, 0x0a, 0x47, 0x69, 0x65, 0x6e, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x0a, 0x0a, 0x47, 0x69,
0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a,
0x47, 0x69, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x47, 0x69, 0x47, 0x69, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x47, 0x69,
@@ -514,46 +522,48 @@ var file_api_master_proto_rawDesc = []byte{
0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72,
0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72,
0x12, 0x1a, 0x0a, 0x08, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x18, 0x06, 0x20, 0x01, 0x12, 0x1a, 0x0a, 0x08, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x18, 0x06, 0x20, 0x01,
0x28, 0x09, 0x52, 0x08, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x22, 0x6d, 0x0a, 0x17, 0x28, 0x09, 0x52, 0x08, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x12, 0x1c, 0x0a, 0x09,
0x47, 0x65, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x47, 0x69, 0x74, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52,
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x33, 0x0a, 0x0b, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x09, 0x47, 0x69, 0x74, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x22, 0x6d, 0x0a, 0x17, 0x47, 0x65,
0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x12, 0x2e, 0x63, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65,
0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x33, 0x0a, 0x0b, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f,
0x52, 0x0a, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6d,
0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x6d, 0x6f, 0x6e, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0a,
0x52, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x73, 0x22, 0xf5, 0x01, 0x0a, 0x18, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6c,
0x47, 0x65, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09,
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2b, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x73, 0x22, 0xf5, 0x01, 0x0a, 0x18, 0x47, 0x65,
0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65,
0x6e, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x48, 0x00, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2b, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73,
0x75, 0x73, 0x88, 0x01, 0x01, 0x12, 0x4b, 0x0a, 0x07, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e,
0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x61, 0x70, 0x69, 0x5f, 0x6d, 0x61, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x48, 0x00, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73,
0x74, 0x65, 0x72, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x53, 0x74, 0x88, 0x01, 0x01, 0x12, 0x4b, 0x0a, 0x07, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x02,
0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x43, 0x6c, 0x69, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x61, 0x70, 0x69, 0x5f, 0x6d, 0x61, 0x73, 0x74, 0x65,
0x65, 0x6e, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x72, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x53, 0x74, 0x61, 0x74,
0x74, 0x73, 0x1a, 0x54, 0x0a, 0x0c, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e,
0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73,
0x03, 0x6b, 0x65, 0x79, 0x12, 0x2e, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x1a, 0x54, 0x0a, 0x0c, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79,
0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x61, 0x70, 0x69, 0x5f, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b,
0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x05, 0x76, 0x65, 0x79, 0x12, 0x2e, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x73, 0x74, 0x61, 0x0b, 0x32, 0x18, 0x2e, 0x61, 0x70, 0x69, 0x5f, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x43,
0x74, 0x75, 0x73, 0x22, 0x8d, 0x01, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x05, 0x76, 0x61, 0x6c,
0x74, 0x43, 0x65, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x33, 0x0a, 0x0b, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75,
0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x73, 0x22, 0x8d, 0x01, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43,
0x0e, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x65, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x33, 0x0a, 0x0b, 0x63, 0x6c,
0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0a, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32,
0x65, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x12, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x54,
0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x23, 0x79, 0x70, 0x65, 0x52, 0x0a, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12,
0x0a, 0x0d, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x18, 0x1b, 0x0a, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01,
0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x53, 0x65, 0x63, 0x28, 0x09, 0x52, 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d,
0x72, 0x65, 0x74, 0x22, 0x63, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x18, 0x03, 0x20,
0x43, 0x65, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2b, 0x0a, 0x06, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x53, 0x65, 0x63, 0x72, 0x65,
0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x63, 0x74, 0x22, 0x63, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x65,
0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x48, 0x00, 0x52, 0x06, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2b, 0x0a, 0x06, 0x73, 0x74,
0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x88, 0x01, 0x01, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x65, 0x72, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x63, 0x6f, 0x6d,
0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x63, 0x65, 0x72, 0x74, 0x42, 0x09, 0x0a, 0x6d, 0x6f, 0x6e, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x48, 0x00, 0x52, 0x06, 0x73, 0x74,
0x07, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x42, 0x07, 0x5a, 0x05, 0x2e, 0x2e, 0x2f, 0x70, 0x61, 0x74, 0x75, 0x73, 0x88, 0x01, 0x01, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x65, 0x72, 0x74, 0x18,
0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x63, 0x65, 0x72, 0x74, 0x42, 0x09, 0x0a, 0x07, 0x5f,
0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x42, 0x07, 0x5a, 0x05, 0x2e, 0x2e, 0x2f, 0x70, 0x62, 0x62,
0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
} }
var ( var (

18
utils/files.go Normal file
View File

@@ -0,0 +1,18 @@
package utils
import (
"os"
"path/filepath"
)
func EnsureDirectoryExists(filePath string) error {
directory := filepath.Dir(filePath)
if _, err := os.Stat(directory); os.IsNotExist(err) {
err = os.MkdirAll(directory, os.ModePerm)
if err != nil {
return err
}
}
return nil
}

View File

@@ -12,6 +12,9 @@ import { ProxyInfo } from '@/lib/pb/common'
import { Button } from '../ui/button' import { Button } from '../ui/button'
import { CheckCircle2, CircleX, RefreshCcw } from "lucide-react" import { CheckCircle2, CircleX, RefreshCcw } from "lucide-react"
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import TrafficStatsCard from './stats-item'
import { Separator } from '@radix-ui/react-separator'
import { formatBytes } from '@/lib/utils'
export interface ClientStatsCardProps { export interface ClientStatsCardProps {
clientID?: string clientID?: string
@@ -19,7 +22,6 @@ export interface ClientStatsCardProps {
export const ClientStatsCard: React.FC<ClientStatsCardProps> = ({ clientID: defaultClientID }: ClientStatsCardProps = {}) => { export const ClientStatsCard: React.FC<ClientStatsCardProps> = ({ clientID: defaultClientID }: ClientStatsCardProps = {}) => {
const { t } = useTranslation(); const { t } = useTranslation();
const [clientID, setClientID] = useState<string | undefined>() const [clientID, setClientID] = useState<string | undefined>()
const [proxyName, setProxyName] = useState<string | undefined>()
const [status, setStatus] = useState<"loading" | "success" | "error" | undefined>() const [status, setStatus] = useState<"loading" | "success" | "error" | undefined>()
const [timeoutId, setTimeoutId] = useState<NodeJS.Timeout | null>(null); const [timeoutId, setTimeoutId] = useState<NodeJS.Timeout | null>(null);
@@ -69,11 +71,6 @@ export const ClientStatsCard: React.FC<ClientStatsCardProps> = ({ clientID: defa
return Array.from(mergedMap.values()); return Array.from(mergedMap.values());
}; };
function removeDuplicateCharacters(input: string): string {
const uniqueChars = new Set(input);
return Array.from(uniqueChars).join('');
}
return ( return (
<Card className="w-full"> <Card className="w-full">
<CardHeader> <CardHeader>
@@ -88,18 +85,16 @@ export const ClientStatsCard: React.FC<ClientStatsCardProps> = ({ clientID: defa
<Label>{t('client.stats.label')}</Label> <Label>{t('client.stats.label')}</Label>
<ClientSelector clientID={clientID} setClientID={handleClientChange} onOpenChange={() => { <ClientSelector clientID={clientID} setClientID={handleClientChange} onOpenChange={() => {
refetchClientStats() refetchClientStats()
setProxyName(undefined)
}} /> }} />
<Label>{t('proxy.stats.label')}</Label> <Label>{t('proxy.stats.label')}</Label>
<ProxySelector <div className="w-full grid gap-2 grid-cols-1 overflow-x-auto">
// @ts-ignore
proxyNames={Array.from(new Set(clientStatsList?.proxyInfos.map((proxyInfo) => proxyInfo.name).filter((value) => value !== undefined))) || []}
proxyName={proxyName}
setProxyname={setProxyName} />
<div className="w-full grid gap-4 grid-cols-1">
{clientStatsList && clientStatsList.proxyInfos.length > 0 && {clientStatsList && clientStatsList.proxyInfos.length > 0 &&
<ProxyStatusCard clientStatsList.proxyInfos.map((proxyInfo) => {
proxyInfo={mergeProxyInfos(clientStatsList.proxyInfos).find((proxyInfo) => proxyInfo.name === proxyName)} />} return (
<ProxyStatusCard key={proxyInfo.name} proxyInfo={proxyInfo} />
)
})
}
</div> </div>
</CardContent> </CardContent>
<CardFooter> <CardFooter>
@@ -135,21 +130,23 @@ const ProxyStatusCard: React.FC<{ proxyInfo: ProxyInfo | undefined }> = ({ proxy
} }
return ( return (
<div key={proxyInfo.name} className="flex flex-col space-y-4"> <Card key={proxyInfo.name} className="flex flex-row gap-2 p-4 w-full min-w-[900px] shadow-none justify-between">
<Label>{t('proxy.stats.tunnel_traffic', { name: proxyInfo.name })}</Label> <Label>{t('proxy.stats.tunnel_traffic', { name: proxyInfo.name })}</Label>
<ProxyTrafficOverview proxyInfo={proxyInfo} /> <Separator orientation="vertical" />
<div className='grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4'> <ProxyTrafficField label={t('traffic.today.total')} value={formatBytes(Number(proxyInfo.todayTrafficOut || BigInt(0)))} />
<ProxyTrafficPieChart <ProxyTrafficField label={t('traffic.today.inbound')} value={formatBytes(Number(proxyInfo.todayTrafficIn || BigInt(0)))} />
title={t('proxy.stats.today_traffic_title')} <ProxyTrafficField label={t('traffic.today.outbound')} value={formatBytes(Number(proxyInfo.todayTrafficOut || BigInt(0)))} />
chartLabel={t('proxy.stats.today_traffic_total')} <Separator orientation="vertical" />
trafficIn={proxyInfo.todayTrafficIn || BigInt(0)} <ProxyTrafficField label={t('traffic.history.total')} value={formatBytes(Number(proxyInfo.historyTrafficOut || BigInt(0)))} />
trafficOut={proxyInfo.todayTrafficOut || BigInt(0)} /> <ProxyTrafficField label={t('traffic.history.inbound')} value={formatBytes(Number(proxyInfo.historyTrafficIn || BigInt(0)))} />
<ProxyTrafficPieChart <ProxyTrafficField label={t('traffic.history.outbound')} value={formatBytes(Number(proxyInfo.historyTrafficOut || BigInt(0)))} />
title={t('proxy.stats.history_traffic_title')} </Card>
chartLabel={t('proxy.stats.history_traffic_total')}
trafficIn={proxyInfo.historyTrafficIn || BigInt(0)}
trafficOut={proxyInfo.historyTrafficOut || BigInt(0)} />
</div>
</div>
); );
}
const ProxyTrafficField = ({ label, value }: { label: string, value: string }) => {
return <div className="flex w-fit flex-col">
<p className="text-xs text-muted-foreground text-nowrap">{label}</p>
<div className="flex items-center text-xs font-semibold text-nowrap">{value}</div>
</div>
} }

View File

@@ -0,0 +1,114 @@
'use client'
import { Card } from "@/components/ui/card"
import { ProxyInfo } from "@/lib/pb/common";
import { formatBytes } from "@/lib/utils";
import { PieChart, Pie, Cell, ResponsiveContainer, Tooltip } from 'recharts'
const COLORS = ['#0088FE', '#00C49F'];
function preparePieData(inTraffic: bigint, outTraffic: bigint) {
return [
{ name: 'In', value: Number(inTraffic) },
{ name: 'Out', value: Number(outTraffic) }
];
}
function calculateTotalTraffic(inTraffic: bigint, outTraffic: bigint): bigint {
return inTraffic + outTraffic;
}
export default function TrafficStatsCard({ proxy }: { proxy: ProxyInfo }) {
return <Card className="p-4 hover:bg-accent/50 transition-colors">
<div className="items-center gap-4 grid grid-cols-4">
{/* Server Info */}
<div className="flex items-center gap-2 min-w-[160px]">
<div className="w-2 h-2 rounded-full bg-green-500" />
<span className="font-medium">{proxy.name}</span>
</div>
{/* Today's Traffic */}
<div className="flex items-center gap-4 ">
<div className="w-16 h-16">
<ResponsiveContainer width="100%" height="100%">
<PieChart>
<Pie
data={preparePieData(proxy.todayTrafficIn || BigInt(0), proxy.todayTrafficOut || BigInt(0))}
cx="50%"
cy="50%"
innerRadius={15}
outerRadius={30}
paddingAngle={2}
dataKey="value"
>
{preparePieData(proxy.todayTrafficIn || BigInt(0), proxy.todayTrafficOut || BigInt(0)).map((entry, index) => (
<Cell key={`cell-${index}`} fill={COLORS[index % COLORS.length]} />
))}
</Pie>
<Tooltip formatter={(value) => formatBytes(value as number)} />
</PieChart>
</ResponsiveContainer>
</div>
<div className="flex flex-col gap-1">
<div className="text-sm font-medium text-muted-foreground">Today&apos;s Traffic</div>
<div className="flex flex-col gap-1">
<div className="flex justify-between items-center">
<span className="text-sm text-muted-foreground">In:</span>
<span className="text-sm tabular-nums">{formatBytes(Number(proxy.todayTrafficIn || BigInt(0)))}</span>
</div>
<div className="flex justify-between items-center">
<span className="text-sm text-muted-foreground">Out:</span>
<span className="text-sm tabular-nums">{formatBytes(Number(proxy.todayTrafficOut || BigInt(0)))}</span>
</div>
<div className="flex justify-between items-center">
<span className="text-sm text-muted-foreground">Total:</span>
<span className="text-sm tabular-nums">{formatBytes(Number(calculateTotalTraffic(proxy.todayTrafficIn || BigInt(0), proxy.todayTrafficOut || BigInt(0))))}</span>
</div>
</div>
</div>
</div>
{/* History Traffic */}
<div className="flex items-center gap-4 min-w-[300px]">
<div className="w-16 h-16">
<ResponsiveContainer width="100%" height="100%">
<PieChart>
<Pie
data={preparePieData(proxy.historyTrafficIn || BigInt(0), proxy.historyTrafficOut || BigInt(0))}
cx="50%"
cy="50%"
innerRadius={15}
outerRadius={30}
paddingAngle={2}
dataKey="value"
>
{preparePieData(proxy.historyTrafficIn || BigInt(0), proxy.historyTrafficOut || BigInt(0)).map((entry, index) => (
<Cell key={`cell-${index}`} fill={COLORS[index % COLORS.length]} />
))}
</Pie>
<Tooltip formatter={(value) => formatBytes(value as number)} />
</PieChart>
</ResponsiveContainer>
</div>
<div className="flex flex-col gap-1">
<div className="text-sm font-medium text-muted-foreground">History Traffic</div>
<div className="flex flex-col gap-1">
<div className="flex justify-between items-center">
<span className="text-sm text-muted-foreground">In:</span>
<span className="text-sm tabular-nums">{formatBytes(Number(proxy.historyTrafficIn || BigInt(0)))}</span>
</div>
<div className="flex justify-between items-center">
<span className="text-sm text-muted-foreground">Out:</span>
<span className="text-sm tabular-nums">{formatBytes(Number(proxy.historyTrafficOut || BigInt(0)))}</span>
</div>
<div className="flex justify-between items-center">
<span className="text-sm text-muted-foreground">Total:</span>
<span className="text-sm tabular-nums">{formatBytes(Number(calculateTotalTraffic(proxy.historyTrafficIn || BigInt(0), proxy.historyTrafficOut || BigInt(0))))}</span>
</div>
</div>
</div>
</div>
</div>
</Card>
}

View File

@@ -25,11 +25,13 @@
"traffic": { "traffic": {
"today": { "today": {
"inbound": "Today's Inbound", "inbound": "Today's Inbound",
"outbound": "Today's Outbound" "outbound": "Today's Outbound",
"total": "Today's Total"
}, },
"history": { "history": {
"inbound": "Historical Inbound", "inbound": "Historical Inbound",
"outbound": "Historical Outbound" "outbound": "Historical Outbound",
"total": "Historical Total"
}, },
"stats": { "stats": {
"title": "Traffic Statistics", "title": "Traffic Statistics",
@@ -318,7 +320,7 @@
"proxy": { "proxy": {
"stats": { "stats": {
"label": "Tunnel Name", "label": "Tunnel Name",
"tunnel_traffic": "Tunnel Traffic: {{name}}", "tunnel_traffic": "Tunnel: {{name}}",
"today_traffic_title": "Today's Traffic", "today_traffic_title": "Today's Traffic",
"today_traffic_total": "Today's Total", "today_traffic_total": "Today's Total",
"history_traffic_title": "Historical Traffic", "history_traffic_title": "Historical Traffic",

View File

@@ -24,12 +24,14 @@
}, },
"traffic": { "traffic": {
"today": { "today": {
"inbound": "今日入站流量", "inbound": "今日入站",
"outbound": "今日出站流量" "outbound": "今日出站",
"total": "今日总流量"
}, },
"history": { "history": {
"inbound": "历史入站流量", "inbound": "历史入站",
"outbound": "历史出站流量" "outbound": "历史出站",
"total": "历史总流量"
}, },
"stats": { "stats": {
"title": "流量统计", "title": "流量统计",
@@ -318,7 +320,7 @@
"proxy": { "proxy": {
"stats": { "stats": {
"label": "隧道名称", "label": "隧道名称",
"tunnel_traffic": "隧道流量{{name}}", "tunnel_traffic": "隧道:{{name}}",
"today_traffic_title": "今日流量", "today_traffic_title": "今日流量",
"today_traffic_total": "今日总计", "today_traffic_total": "今日总计",
"history_traffic_title": "历史流量", "history_traffic_title": "历史流量",

View File

@@ -94,6 +94,10 @@ export interface ClientVersion {
* @generated from protobuf field: string Platform = 6 [json_name = "Platform"]; * @generated from protobuf field: string Platform = 6 [json_name = "Platform"];
*/ */
platform: string; platform: string;
/**
* @generated from protobuf field: string GitBranch = 7 [json_name = "GitBranch"];
*/
gitBranch: string;
} }
/** /**
* @generated from protobuf message api_master.GetClientsStatusRequest * @generated from protobuf message api_master.GetClientsStatusRequest
@@ -254,7 +258,8 @@ class ClientVersion$Type extends MessageType<ClientVersion> {
{ no: 3, name: "BuildDate", kind: "scalar", jsonName: "BuildDate", T: 9 /*ScalarType.STRING*/ }, { no: 3, name: "BuildDate", kind: "scalar", jsonName: "BuildDate", T: 9 /*ScalarType.STRING*/ },
{ no: 4, name: "GoVersion", kind: "scalar", jsonName: "GoVersion", T: 9 /*ScalarType.STRING*/ }, { no: 4, name: "GoVersion", kind: "scalar", jsonName: "GoVersion", T: 9 /*ScalarType.STRING*/ },
{ no: 5, name: "Compiler", kind: "scalar", jsonName: "Compiler", T: 9 /*ScalarType.STRING*/ }, { no: 5, name: "Compiler", kind: "scalar", jsonName: "Compiler", T: 9 /*ScalarType.STRING*/ },
{ no: 6, name: "Platform", kind: "scalar", jsonName: "Platform", T: 9 /*ScalarType.STRING*/ } { no: 6, name: "Platform", kind: "scalar", jsonName: "Platform", T: 9 /*ScalarType.STRING*/ },
{ no: 7, name: "GitBranch", kind: "scalar", jsonName: "GitBranch", T: 9 /*ScalarType.STRING*/ }
]); ]);
} }
create(value?: PartialMessage<ClientVersion>): ClientVersion { create(value?: PartialMessage<ClientVersion>): ClientVersion {
@@ -265,6 +270,7 @@ class ClientVersion$Type extends MessageType<ClientVersion> {
message.goVersion = ""; message.goVersion = "";
message.compiler = ""; message.compiler = "";
message.platform = ""; message.platform = "";
message.gitBranch = "";
if (value !== undefined) if (value !== undefined)
reflectionMergePartial<ClientVersion>(this, message, value); reflectionMergePartial<ClientVersion>(this, message, value);
return message; return message;
@@ -292,6 +298,9 @@ class ClientVersion$Type extends MessageType<ClientVersion> {
case /* string Platform = 6 [json_name = "Platform"];*/ 6: case /* string Platform = 6 [json_name = "Platform"];*/ 6:
message.platform = reader.string(); message.platform = reader.string();
break; break;
case /* string GitBranch = 7 [json_name = "GitBranch"];*/ 7:
message.gitBranch = reader.string();
break;
default: default:
let u = options.readUnknownField; let u = options.readUnknownField;
if (u === "throw") if (u === "throw")
@@ -322,6 +331,9 @@ class ClientVersion$Type extends MessageType<ClientVersion> {
/* string Platform = 6 [json_name = "Platform"]; */ /* string Platform = 6 [json_name = "Platform"]; */
if (message.platform !== "") if (message.platform !== "")
writer.tag(6, WireType.LengthDelimited).string(message.platform); writer.tag(6, WireType.LengthDelimited).string(message.platform);
/* string GitBranch = 7 [json_name = "GitBranch"]; */
if (message.gitBranch !== "")
writer.tag(7, WireType.LengthDelimited).string(message.gitBranch);
let u = options.writeUnknownFields; let u = options.writeUnknownFields;
if (u !== false) if (u !== false)
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);