From e1d0565481bad769031238982d10c15fe0347a5c Mon Sep 17 00:00:00 2001 From: vivekpunchh <49975837+vivekpunchh@users.noreply.github.com> Date: Fri, 11 Apr 2025 13:14:42 +0530 Subject: [PATCH 01/15] [CX-2682, CX-2683, CX-2684] - Move all configuration/secrets to AWS Secret Manager (#2) * [CX-2682, CX-2684] - Move all configuration/secrets to AWS Secret Manager * CX-2682: Addressed code review changes. * CX-2682: Removed unwanted files. * CX-2683: Fix the code vulnerabilities/snyk reported issues * [CX-2682] Redis TTL & Ping endpoint. * CX-2682: Addressed code review changes. --- Dockerfile | 26 +++++ config/app.json | 3 - config/app.prod.json | 44 -------- config/config.go | 252 ++++++++++++++++++++++++++++++++----------- go.mod | 20 ++-- go.sum | 69 +++++------- main.go | 6 ++ request/app.go | 3 +- request/client.go | 27 ++++- 9 files changed, 281 insertions(+), 169 deletions(-) create mode 100644 Dockerfile delete mode 100644 config/app.json delete mode 100644 config/app.prod.json diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..39713e3 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,26 @@ +# Build the application from source +FROM golang:1.21.5 AS build-stage + +WORKDIR /app + +COPY go.mod go.sum ./ +RUN go mod download + +COPY . . + +RUN CGO_ENABLED=0 GOOS=linux go build -o /server main.go + +# Deploy the application binary into a lean image +FROM alpine:3.21.3 AS build-release-stage + +RUN apk update \ + && apk --no-cache add ca-certificates \ + && apk --no-cache add -U tzdata \ + && rm -rf /var/cache/apk/* + +WORKDIR /usr/app/ + +COPY --from=build-stage server . + +EXPOSE 8080 +ENTRYPOINT ["./server"] diff --git a/config/app.json b/config/app.json deleted file mode 100644 index f7131c7..0000000 --- a/config/app.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "mode":"prod" -} \ No newline at end of file diff --git a/config/app.prod.json b/config/app.prod.json deleted file mode 100644 index 8aa921b..0000000 --- a/config/app.prod.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "DBUser": { - "Write": { - "UserName": "root", - "Password": "", - "Host": "127.0.0.1", - "Port": 3306, - "DBname": "code-push" - }, - "MaxIdleConns": 10, - "MaxOpenConns": 100, - "ConnMaxLifetime": 1 - }, - "Redis": { - "Host": "127.0.0.1", - "Port": 6379, - "DBIndex": 0, - "UserName": "", - "Password": "" - }, - "CodePush": { - "FileLocal":"local", - "Local":{ - "SavePath":"./bundles" - }, - "Aws":{ - "Endpoint":"", - "Region":"", - "S3ForcePathStyle":true, - "KeyId":"", - "Secret":"", - "Bucket":"" - }, - "Ftp":{ - "ServerUrl":"", - "UserName":"", - "Password":"" - } - }, - "UrlPrefix": "/", - "ResourceUrl": "", - "Port": ":8080", - "TokenExpireTime": 30 -} \ No newline at end of file diff --git a/config/config.go b/config/config.go index f5fb461..8432fa6 100644 --- a/config/config.go +++ b/config/config.go @@ -2,52 +2,14 @@ package config import ( "encoding/json" + "fmt" "os" - "os/exec" - "path/filepath" + "strconv" "strings" -) - -var configFile *appConfig - -func getExcPath() string { - file, _ := exec.LookPath(os.Args[0]) - // 获取包含可执行文件名称的路径 - path, _ := filepath.Abs(file) - // 获取可执行文件所在目录 - index := strings.LastIndex(path, string(os.PathSeparator)) - ret := path[:index] - return strings.Replace(ret, "\\", "/", -1) -} - -func GetConfig() appConfig { - if configFile != nil { - return *configFile - } - path := getExcPath() - var mode modeConfig = readJson[modeConfig](path + "/config/app.json") - - appConfig := readJson[appConfig](path + "/config/app." + mode.Mode + ".json") - configFile = &appConfig - return *configFile -} - -func readJson[T any](path string) T { - file, err := os.Open(path) - if err != nil { - panic(path + " config not found") - } - defer file.Close() - decoder := json.NewDecoder(file) + "sync" - var jsonF T - decoder.Decode(&jsonF) - return jsonF -} - -type modeConfig struct { - Mode string -} + "github.com/go-playground/validator/v10" +) type appConfig struct { DBUser dbConfig @@ -55,8 +17,10 @@ type appConfig struct { CodePush codePush UrlPrefix string Port string - ResourceUrl string + ResourceUrl string `json:"resource_url" validate:"required"` TokenExpireTime int64 + Environment string `json:"environment" validate:"required"` + TenantName string `json:"tenant_name" validate:"required"` } type dbConfig struct { Write dbConfigObj @@ -65,38 +29,196 @@ type dbConfig struct { ConnMaxLifetime uint } type dbConfigObj struct { - UserName string - Password string - Host string - Port uint - DBname string + UserName string `json:"db_username" validate:"required"` + Password string `json:"db_password" validate:"required"` + Host string `json:"db_host" validate:"required"` + Port uint `json:"db_port" validate:"required"` + DBname string `json:"db_name" validate:"required"` } type redisConfig struct { - Host string - Port uint - DBIndex uint - UserName string - Password string + Host string `json:"redis_host" validate:"required"` + Port uint `json:"redis_port" validate:"required"` + DBIndex uint `json:"redis_db_index"` + UserName string `json:"redis_username"` + Password string `json:"redis_password"` } type codePush struct { - FileLocal string + FileLocal string `json:"build_save_location" validate:"required"` Local localConfig Aws awsConfig Ftp ftpConfig } type awsConfig struct { - Endpoint string - Region string - S3ForcePathStyle bool - KeyId string - Secret string - Bucket string + Endpoint string `json:"aws_s3_endpoint" validate:"required"` + Region string `json:"aws_region" validate:"required"` + S3ForcePathStyle bool `json:"aws_s3_force_path_style" validate:"required"` + KeyId string `json:"aws_access_key_id" validate:"required"` + Secret string `json:"aws_secret_access_key" validate:"required"` + Bucket string `json:"aws_s3_bucket_name" validate:"required"` } type ftpConfig struct { - ServerUrl string - UserName string - Password string + ServerUrl string `json:"ftp_server_url"` + UserName string `json:"ftp_username"` + Password string `ftp_password` } type localConfig struct { - SavePath string + SavePath string `json:"local_build_save_path"` +} + +var config *appConfig +var once sync.Once + +func GetConfig() *appConfig { + once.Do(func() { + config = LoadConfig() + }) + return config +} + +func LoadConfig() *appConfig { + fmt.Println("Fetching config from AWS secret manager...") + keys := []string{ + "global", // Global secrets + "tenant", // Tendancy punchh-server secrets + "service", // Email template secrets + "db", // DB secrets + } + + var config appConfig + + var dbObj dbConfigObj + var redis redisConfig + var buildSaveLocation codePush + var aws awsConfig + var ftp ftpConfig + + // default values + config.DBUser.MaxIdleConns = 5 + config.DBUser.MaxOpenConns = 20 + config.DBUser.ConnMaxLifetime = 300 + + config.Port = ":8080" + config.UrlPrefix = "/" + config.ResourceUrl = "" + config.TokenExpireTime = 1 //in days + + for _, key := range keys { + key = key + "_secrets" + + data, ok := os.LookupEnv(key) + if !ok { + fmt.Println("config: no secrets found for - ", key) + continue + } + + secrets := make(map[string]interface{}) + if err := json.Unmarshal([]byte(data), &secrets); err != nil { + fmt.Println("config: error unmarshalling secrets for - ", key) + panic(err) + } + + for k, v := range secrets { + k = strings.ToLower(k) + fmt.Println(k) + // DB + if k == "db_username" { + dbObj.UserName = v.(string) + } + if k == "db_password" { + dbObj.Password = v.(string) + } + if k == "db_host" { + dbObj.Host = v.(string) + } + if k == "db_port" { + u64, _ := strconv.ParseUint(v.(string), 10, 32) + dbObj.Port = uint(u64) + } + if k == "db_name" { + dbObj.DBname = v.(string) + } + + // Redis + if k == "redis_host" { + redis.Host = v.(string) + } + if k == "redis_port" { + u64, _ := strconv.ParseUint(v.(string), 10, 32) + redis.Port = uint(u64) + } + if k == "redis_db_index" { + u64, _ := strconv.ParseUint(v.(string), 10, 32) + redis.DBIndex = uint(u64) + } + if k == "redis_username" { + redis.UserName = v.(string) + } + if k == "redis_password" { + redis.Password = v.(string) + } + + // local bundle save location + if k == "build_save_location" { + buildSaveLocation.FileLocal = v.(string) + } + + // AWS + if k == "aws_s3_endpoint" { + aws.Endpoint = v.(string) + } + if k == "aws_region" { + aws.Region = v.(string) + } + if k == "aws_s3_force_path_style" { + aws.S3ForcePathStyle = true + } + if k == "aws_access_key_id" { + aws.KeyId = v.(string) + } + if k == "aws_secret_access_key" { + aws.Secret = v.(string) + } + if k == "aws_s3_bucket_name" { + aws.Bucket = v.(string) + } + + // ftp + if k == "ftp_server_url" { + ftp.ServerUrl = v.(string) + } + if k == "ftp_username" { + ftp.UserName = v.(string) + } + if k == "ftp_password" { + ftp.Password = v.(string) + } + // common + + // if build_save_location is set to `local` then resource URL should the self server URL + // if build_save_location is set to `aws` then resource URL should the AWS S3 bucket URL + if k == "resource_url" { + config.ResourceUrl = v.(string) + } + if k == "tenant_name" { + config.TenantName = v.(string) + } + + if k == "environment" { + config.Environment = v.(string) + } + } + } + config.DBUser.Write = dbObj + config.Redis = redis + config.CodePush = buildSaveLocation + config.CodePush.Aws = aws + config.CodePush.Ftp = ftp + + // validate the config + validate := validator.New() + if err := validate.Struct(config); err != nil { + fmt.Println("config: invalid/missing configuration", err) + panic(err) + } + return &config } diff --git a/go.mod b/go.mod index 8c3414d..77411a9 100644 --- a/go.mod +++ b/go.mod @@ -2,7 +2,11 @@ module com.lc.go.codepush/server go 1.21.5 -require gorm.io/driver/mysql v1.5.6 +require ( + github.com/go-playground/validator/v10 v10.19.0 + github.com/jlaffaye/ftp v0.2.0 + gorm.io/driver/mysql v1.5.6 +) require ( github.com/bytedance/sonic v1.11.3 // indirect @@ -10,15 +14,13 @@ require ( github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect github.com/chenzhuoyu/iasm v0.9.1 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect - github.com/gabriel-vasile/mimetype v1.4.3 // indirect + github.com/gabriel-vasile/mimetype v1.4.8 // indirect github.com/gin-contrib/sse v0.1.0 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect - github.com/go-playground/validator/v10 v10.19.0 // indirect github.com/goccy/go-json v0.10.2 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect - github.com/jlaffaye/ftp v0.2.0 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/klauspost/cpuid/v2 v2.2.7 // indirect @@ -30,10 +32,10 @@ require ( github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/ugorji/go/codec v1.2.12 // indirect golang.org/x/arch v0.7.0 // indirect - golang.org/x/crypto v0.21.0 // indirect - golang.org/x/net v0.22.0 // indirect - golang.org/x/sys v0.18.0 // indirect - golang.org/x/text v0.14.0 // indirect + golang.org/x/crypto v0.31.0 // indirect + golang.org/x/net v0.33.0 // indirect + golang.org/x/sys v0.28.0 // indirect + golang.org/x/text v0.21.0 // indirect google.golang.org/protobuf v1.33.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) @@ -47,5 +49,5 @@ require ( github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect github.com/redis/go-redis/v9 v9.5.1 - gorm.io/gorm v1.25.9 // indirect + gorm.io/gorm v1.25.9 ) diff --git a/go.sum b/go.sum index 96b83ba..aeee0a5 100644 --- a/go.sum +++ b/go.sum @@ -1,15 +1,16 @@ github.com/aws/aws-sdk-go v1.51.24 h1:nwL5MaommPkwb7Ixk24eWkdx5HY4of1gD10kFFVAl6A= github.com/aws/aws-sdk-go v1.51.24/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= +github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= +github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c= +github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= +github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0= github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= -github.com/bytedance/sonic v1.9.1 h1:6iJ6NqdoxCDr6mbY8h18oSO+cShGSMRGCEo7F2h0x8s= -github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U= github.com/bytedance/sonic v1.10.0-rc/go.mod h1:ElCzW+ufi8qKqNW0FY314xriJhyJhuoJ3gFZdAHF7NM= github.com/bytedance/sonic v1.11.3 h1:jRN+yEjakWh8aK5FzrciUHG8OFXK+4/KrAX/ysEtHAA= github.com/bytedance/sonic v1.11.3/go.mod h1:iZcSUejdk5aukTND/Eu/ivjQuEL0Cu9/rf50Hi0u/g4= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= -github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams= github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk= github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d h1:77cEq6EriyTZ0g/qfRdp61a3Uu/AWrgIq2s0ClJV1g0= github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d/go.mod h1:8EPpVsBuRksnlj1mLy4AWzRNQYxauNi62uWcE3to6eA= @@ -17,32 +18,31 @@ github.com/chenzhuoyu/iasm v0.9.0/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLI github.com/chenzhuoyu/iasm v0.9.1 h1:tUHQJXo3NhBqw6s33wkGn9SP3bvrWLdlVIJ3hQBL7P0= github.com/chenzhuoyu/iasm v0.9.1/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= -github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU= -github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA= -github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= -github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= +github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM= +github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8= github.com/gin-contrib/gzip v1.0.0 h1:UKN586Po/92IDX6ie5CWLgMI81obiIp5nSP85T3wlTk= github.com/gin-contrib/gzip v1.0.0/go.mod h1:CtG7tQrPB3vIBo6Gat9FVUsis+1emjvQqd66ME5TdnE= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg= github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= +github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= +github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= -github.com/go-playground/validator/v10 v10.14.0 h1:vgvQWe3XCz3gIeFDm/HnTIbj6UGmg/+t63MyGU2n5js= -github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= github.com/go-playground/validator/v10 v10.19.0 h1:ol+5Fu+cSq9JD7SoSqe04GMI92cbn0+wvQ3bZ8b/AU4= github.com/go-playground/validator/v10 v10.19.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc= github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= @@ -60,21 +60,16 @@ github.com/jlaffaye/ftp v0.2.0 h1:lXNvW7cBu7R/68bknOX3MrRIIqZ61zELs1P2RAiA3lg= github.com/jlaffaye/ftp v0.2.0/go.mod h1:is2Ds5qkhceAPy2xD6RLI6hmp/qysSoymZ+Z2uTnspI= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= +github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk= -github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM= github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= -github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= -github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= -github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= -github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -82,10 +77,9 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ= -github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4= github.com/pelletier/go-toml/v2 v2.2.0 h1:QLgLl2yMN7N+ruc31VynXs1vhMZa7CeHHejIeBAsoHo= github.com/pelletier/go-toml/v2 v2.2.0/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/redis/go-redis/v9 v9.5.1 h1:H1X4D3yHPaYrkL5X06Wh6xNVM/pX0Ft4RV0vMGvLBh8= github.com/redis/go-redis/v9 v9.5.1/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M= @@ -98,54 +92,39 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= -github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= -github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE= github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= -golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k= -golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/arch v0.7.0 h1:pskyeJh/3AmoQ8CPE95vxHLqp1G1GfGNXTmcl9NEKTc= golang.org/x/arch v0.7.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= -golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g= -golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= -golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= -golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= -golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= -golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc= -golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= -golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= +golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= +golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= +golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= -golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= -golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= -golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= +golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= -google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gorm.io/driver/mysql v1.5.6 h1:Ld4mkIickM+EliaQZQx3uOJDJHtrd70MxAUqWqlx3Y8= gorm.io/driver/mysql v1.5.6/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkDM= -gorm.io/gorm v1.25.7 h1:VsD6acwRjz2zFxGO50gPO6AkNs7KKnvfzUjHQhZDz/A= gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= gorm.io/gorm v1.25.9 h1:wct0gxZIELDk8+ZqF/MVnHLkA1rvYlBWUMv2EdsK1g8= gorm.io/gorm v1.25.9/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= diff --git a/main.go b/main.go index c2da58d..ba67ab1 100644 --- a/main.go +++ b/main.go @@ -22,6 +22,12 @@ func main() { // g.Static("/bundels", "bundels") + g.GET("/ping", func(c *gin.Context) { + c.JSON(200, gin.H{ + "message": "pong", + }) + }) + g.GET("/v0.1/public/codepush/update_check", request.Client{}.CheckUpdate) g.POST("/v0.1/public/codepush/report_status/deploy", request.Client{}.ReportStatus) g.POST("/v0.1/public/codepush/report_status/download", request.Client{}.Download) diff --git a/request/app.go b/request/app.go index c16623e..55f9533 100644 --- a/request/app.go +++ b/request/app.go @@ -5,6 +5,7 @@ import ( "log" "net/http" "os" + "path" "com.lc.go.codepush/server/config" "com.lc.go.codepush/server/db" @@ -197,7 +198,7 @@ func (App) UploadBundle(ctx *gin.Context) { if err != nil { log.Panic(err.Error()) } - os.WriteFile(config.CodePush.Local.SavePath+"/"+key, buf.Bytes(), 0777) + os.WriteFile(path.Clean(config.CodePush.Local.SavePath+"/"+key), buf.Bytes(), 0777) case "aws": s3Config := &aws.Config{ Credentials: credentials.NewStaticCredentials(config.CodePush.Aws.KeyId, config.CodePush.Aws.Secret, ""), diff --git a/request/client.go b/request/client.go index 1b7c866..53de07e 100644 --- a/request/client.go +++ b/request/client.go @@ -4,12 +4,17 @@ import ( "log" "net/http" "strconv" + "time" "com.lc.go.codepush/server/config" "com.lc.go.codepush/server/db/redis" "com.lc.go.codepush/server/model" "com.lc.go.codepush/server/model/constants" "com.lc.go.codepush/server/utils" + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/credentials" + "github.com/aws/aws-sdk-go/aws/session" + "github.com/aws/aws-sdk-go/service/s3" "github.com/gin-gonic/gin" ) @@ -62,7 +67,25 @@ func (Client) CheckUpdate(ctx *gin.Context) { updateInfoRedis.IsMandatory = true label := strconv.Itoa(*packag.Id) updateInfoRedis.Label = label - updateInfoRedis.DownloadUrl = config.ResourceUrl + *packag.Download + + s3Config := &aws.Config{ + Credentials: credentials.NewStaticCredentials(config.CodePush.Aws.KeyId, config.CodePush.Aws.Secret, ""), + Endpoint: aws.String(config.CodePush.Aws.Endpoint), + Region: aws.String(config.CodePush.Aws.Region), + } + newSession, _ := session.NewSession(s3Config) + + s3Client := s3.New(newSession) + request, _ := s3Client.GetObjectRequest(&s3.GetObjectInput{ + Bucket: aws.String(config.CodePush.Aws.Bucket), + Key: aws.String(*packag.Download), + }) + + resourceURL, err := request.Presign(24 * time.Hour) // 24 hours + if err != nil { + log.Panic("Failed to sign request", err) + } + updateInfoRedis.DownloadUrl = resourceURL if packag.Description != nil { updateInfoRedis.Description = *packag.Description } @@ -73,7 +96,7 @@ func (Client) CheckUpdate(ctx *gin.Context) { if deploymentVersionNew != nil { updateInfoRedis.NewVersion = *deploymentVersionNew.AppVersion } - redis.SetRedisObj(redisKey, updateInfoRedis, -1) + redis.SetRedisObj(redisKey, updateInfoRedis, time.Duration(24*time.Hour-(10*time.Second))) } if updateInfoRedis.PackageHash != "" { if updateInfoRedis.PackageHash != packageHash && appVersion == updateInfoRedis.TargetBinaryRange { From 5247b7e212c9ac37931957b1f9f70f59ec22b7d5 Mon Sep 17 00:00:00 2001 From: vivekpunchh <49975837+vivekpunchh@users.noreply.github.com> Date: Fri, 25 Apr 2025 18:55:46 +0530 Subject: [PATCH 02/15] [DEVOPS-12984] - GO version update. (#7) --- Dockerfile | 2 +- go.mod | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 39713e3..2c73fbd 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # Build the application from source -FROM golang:1.21.5 AS build-stage +FROM golang:1.21 AS build-stage WORKDIR /app diff --git a/go.mod b/go.mod index 77411a9..caa96d3 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module com.lc.go.codepush/server -go 1.21.5 +go 1.21 require ( github.com/go-playground/validator/v10 v10.19.0 From 3001d3709204fee4d6698f88da70dd4ae55ad24a Mon Sep 17 00:00:00 2001 From: Vivek Balakrishnan Date: Mon, 2 Jun 2025 13:03:12 +0530 Subject: [PATCH 03/15] Test - Fix S3 download image URL. --- request/client.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/request/client.go b/request/client.go index 53de07e..7802f2a 100644 --- a/request/client.go +++ b/request/client.go @@ -69,9 +69,10 @@ func (Client) CheckUpdate(ctx *gin.Context) { updateInfoRedis.Label = label s3Config := &aws.Config{ - Credentials: credentials.NewStaticCredentials(config.CodePush.Aws.KeyId, config.CodePush.Aws.Secret, ""), - Endpoint: aws.String(config.CodePush.Aws.Endpoint), - Region: aws.String(config.CodePush.Aws.Region), + Credentials: credentials.NewStaticCredentials(config.CodePush.Aws.KeyId, config.CodePush.Aws.Secret, ""), + Endpoint: aws.String(config.CodePush.Aws.Endpoint), + Region: aws.String(config.CodePush.Aws.Region), + S3ForcePathStyle: aws.Bool(config.CodePush.Aws.S3ForcePathStyle), } newSession, _ := session.NewSession(s3Config) From 8973d571a823f5223f7178da4ec44d19cc70e6a0 Mon Sep 17 00:00:00 2001 From: Ankit Jaiswal Date: Thu, 3 Apr 2025 10:19:13 +0530 Subject: [PATCH 04/15] Removed mandatory option --- request/client.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/request/client.go b/request/client.go index 53de07e..e9b4cfd 100644 --- a/request/client.go +++ b/request/client.go @@ -64,7 +64,7 @@ func (Client) CheckUpdate(ctx *gin.Context) { updateInfoRedis.PackageHash = *packag.Hash updateInfoRedis.PackageSize = *packag.Size updateInfoRedis.IsAvailable = true - updateInfoRedis.IsMandatory = true + updateInfoRedis.IsMandatory = false label := strconv.Itoa(*packag.Id) updateInfoRedis.Label = label @@ -104,7 +104,7 @@ func (Client) CheckUpdate(ctx *gin.Context) { updateInfo.PackageHash = updateInfoRedis.PackageHash updateInfo.PackageSize = updateInfoRedis.PackageSize updateInfo.IsAvailable = true - updateInfo.IsMandatory = true + updateInfo.IsMandatory = false updateInfo.Label = updateInfoRedis.Label updateInfo.DownloadUrl = updateInfoRedis.DownloadUrl updateInfo.Description = updateInfoRedis.Description From 6d55eac0687b275b48b589c7f0de8452a40f9879 Mon Sep 17 00:00:00 2001 From: Kshitij Singh Date: Thu, 9 Apr 2026 17:51:32 +0530 Subject: [PATCH 05/15] newrelic and airbrake integration --- Dockerfile | 29 +++++-------------- config/config.go | 28 +++++++++++++++++++ db/db.go | 8 +++++- go.mod | 27 +++++++++++++----- go.sum | 72 ++++++++++++++++++++++++++++++++++++------------ main.go | 46 +++++++++++++++++++++++++++---- 6 files changed, 157 insertions(+), 53 deletions(-) diff --git a/Dockerfile b/Dockerfile index 2c73fbd..3e25a1b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,26 +1,11 @@ -# Build the application from source -FROM golang:1.21 AS build-stage - -WORKDIR /app - -COPY go.mod go.sum ./ -RUN go mod download - -COPY . . - -RUN CGO_ENABLED=0 GOOS=linux go build -o /server main.go - -# Deploy the application binary into a lean image -FROM alpine:3.21.3 AS build-release-stage - +FROM alpine:3.21.3 RUN apk update \ - && apk --no-cache add ca-certificates \ - && apk --no-cache add -U tzdata \ - && rm -rf /var/cache/apk/* - -WORKDIR /usr/app/ + && apk --no-cache add ca-certificates \ + && apk --no-cache add -U tzdata \ + && rm -rf /var/cache/apk/* -COPY --from=build-stage server . +WORKDIR /server +COPY server . EXPOSE 8080 -ENTRYPOINT ["./server"] +CMD ["./server"] diff --git a/config/config.go b/config/config.go index 8432fa6..f696a5a 100644 --- a/config/config.go +++ b/config/config.go @@ -21,6 +21,10 @@ type appConfig struct { TokenExpireTime int64 Environment string `json:"environment" validate:"required"` TenantName string `json:"tenant_name" validate:"required"` + // Observability (same JSON keys as go-email-templates service secrets) + AirbrakeProjectID int64 + AirbrakeProjectKey string + NewRelicLicenseKey string } type dbConfig struct { Write dbConfigObj @@ -76,6 +80,20 @@ func GetConfig() *appConfig { } func LoadConfig() *appConfig { + intFormatter := func(v interface{}) (val int64) { + switch ta := v.(type) { + case int: + val = int64(ta) + case int64: + val = ta + case float64: + val = int64(ta) + case string: + val, _ = strconv.ParseInt(ta, 10, 64) + } + return + } + fmt.Println("Fetching config from AWS secret manager...") keys := []string{ "global", // Global secrets @@ -206,6 +224,16 @@ func LoadConfig() *appConfig { if k == "environment" { config.Environment = v.(string) } + + if k == "airbrake_project_id" { + config.AirbrakeProjectID = intFormatter(v) + } + if k == "airbrake_project_key" { + config.AirbrakeProjectKey = v.(string) + } + if k == "newrelic_license_key" { + config.NewRelicLicenseKey = v.(string) + } } } config.DBUser.Write = dbObj diff --git a/db/db.go b/db/db.go index 63b6daa..79a774b 100644 --- a/db/db.go +++ b/db/db.go @@ -5,6 +5,8 @@ import ( "time" "com.lc.go.codepush/server/config" + + _ "github.com/newrelic/go-agent/v3/integrations/nrmysql" "gorm.io/driver/mysql" "gorm.io/gorm" "gorm.io/gorm/logger" @@ -20,7 +22,11 @@ func GetUserDB() (odb *gorm.DB, err error) { dbConfig := config.GetConfig().DBUser dsnSource := dbConfig.Write.UserName + ":" + dbConfig.Write.Password + "@tcp(" + dbConfig.Write.Host + ":" + strconv.Itoa(int(dbConfig.Write.Port)) + ")/" + dbConfig.Write.DBname + "?charset=utf8mb4&parseTime=True&loc=Local" - db, err := gorm.Open(mysql.Open(dsnSource), &gorm.Config{ + // Same driver as go-email-templates (sql.Open("nrmysql", ...)); pairs with HTTP txns when using Request context. + db, err := gorm.Open(mysql.New(mysql.Config{ + DriverName: "nrmysql", + DSN: dsnSource, + }), &gorm.Config{ Logger: logger.Default.LogMode(logger.Error), }) if err != nil { diff --git a/go.mod b/go.mod index caa96d3..359f3e4 100644 --- a/go.mod +++ b/go.mod @@ -1,16 +1,22 @@ module com.lc.go.codepush/server -go 1.21 +go 1.24 require ( github.com/go-playground/validator/v10 v10.19.0 github.com/jlaffaye/ftp v0.2.0 + github.com/newrelic/go-agent/v3/integrations/nrgin v1.2.1 + github.com/newrelic/go-agent/v3/integrations/nrmysql v1.2.2 + github.com/punchh/go-packages v1.2.1 + github.com/sirupsen/logrus v1.9.4 gorm.io/driver/mysql v1.5.6 ) require ( + github.com/airbrake/gobrake/v5 v5.6.2 // indirect github.com/bytedance/sonic v1.11.3 // indirect - github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/caio/go-tdigest/v4 v4.0.1 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect github.com/chenzhuoyu/iasm v0.9.1 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect @@ -19,24 +25,31 @@ require ( github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect github.com/goccy/go-json v0.10.2 // indirect + github.com/golang-jwt/jwt/v4 v4.5.2 // indirect + github.com/golang/protobuf v1.5.4 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect + github.com/jonboulle/clockwork v0.5.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/klauspost/cpuid/v2 v2.2.7 // indirect github.com/leodido/go-urn v1.4.0 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/newrelic/go-agent/v3 v3.24.0 // indirect github.com/pelletier/go-toml/v2 v2.2.0 // indirect + github.com/pkg/errors v0.9.1 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/ugorji/go/codec v1.2.12 // indirect golang.org/x/arch v0.7.0 // indirect - golang.org/x/crypto v0.31.0 // indirect - golang.org/x/net v0.33.0 // indirect - golang.org/x/sys v0.28.0 // indirect - golang.org/x/text v0.21.0 // indirect - google.golang.org/protobuf v1.33.0 // indirect + golang.org/x/crypto v0.33.0 // indirect + golang.org/x/net v0.35.0 // indirect + golang.org/x/sys v0.30.0 // indirect + golang.org/x/text v0.22.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19 // indirect + google.golang.org/grpc v1.54.0 // indirect + google.golang.org/protobuf v1.36.5 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index aeee0a5..5ba206f 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,5 @@ +github.com/airbrake/gobrake/v5 v5.6.2 h1:/LLjm0B3Jy3gqg17VpeGEnSTRqiIElGDy3RZy9s7+MU= +github.com/airbrake/gobrake/v5 v5.6.2/go.mod h1:7lOWiGlpBnOnmWdz7BJzY/shByCkuAIL4LvHbGBKeZs= github.com/aws/aws-sdk-go v1.51.24 h1:nwL5MaommPkwb7Ixk24eWkdx5HY4of1gD10kFFVAl6A= github.com/aws/aws-sdk-go v1.51.24/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= @@ -8,8 +10,10 @@ github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1 github.com/bytedance/sonic v1.10.0-rc/go.mod h1:ElCzW+ufi8qKqNW0FY314xriJhyJhuoJ3gFZdAHF7NM= github.com/bytedance/sonic v1.11.3 h1:jRN+yEjakWh8aK5FzrciUHG8OFXK+4/KrAX/ysEtHAA= github.com/bytedance/sonic v1.11.3/go.mod h1:iZcSUejdk5aukTND/Eu/ivjQuEL0Cu9/rf50Hi0u/g4= -github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= -github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/caio/go-tdigest/v4 v4.0.1 h1:sx4ZxjmIEcLROUPs2j1BGe2WhOtHD6VSe6NNbBdKYh4= +github.com/caio/go-tdigest/v4 v4.0.1/go.mod h1:Wsa+f0EZnV2gShdj1adgl0tQSoXRxtM0QioTgukFw8U= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk= github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d h1:77cEq6EriyTZ0g/qfRdp61a3Uu/AWrgIq2s0ClJV1g0= @@ -30,6 +34,8 @@ github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg= github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= +github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= +github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= @@ -42,8 +48,12 @@ github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= -github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/golang-jwt/jwt/v4 v4.5.2 h1:YtQM7lnr8iZ+j5q71MGKkNw9Mn7AjHM68uc9g5fXeUI= +github.com/golang-jwt/jwt/v4 v4.5.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -62,12 +72,16 @@ github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9Y github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= +github.com/jonboulle/clockwork v0.5.0 h1:Hyh9A8u51kptdkR+cqRpT1EebBwTn1oK9YfGYbdFz6I= +github.com/jonboulle/clockwork v0.5.0/go.mod h1:3mZlmanh0g2NDKO5TWZVJAfofYk64M7XN3SzBPjZF60= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM= github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= +github.com/leesper/go_rng v0.0.0-20190531154944-a612b043e353 h1:X/79QL0b4YJVO5+OsPH9rF2u428CIrGL/jLmPsoOQQ4= +github.com/leesper/go_rng v0.0.0-20190531154944-a612b043e353/go.mod h1:N0SVk0uhy+E1PZ3C9ctsPRlvOPAFPkCNlcPBDkt0N3U= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= @@ -77,12 +91,28 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/newrelic/go-agent/v3 v3.24.0 h1:DPfbd+p0akRjv6UpWzWJl+pfOMSs+QkAeNRUp0fPLZI= +github.com/newrelic/go-agent/v3 v3.24.0/go.mod h1:7GnP0o5ZwEsnC001iDSoZRJ63jS6AtoAOggpg5XVJh8= +github.com/newrelic/go-agent/v3/integrations/nrgin v1.2.1 h1:re7DEe0rP5oek23/0N1aFfdtH5h2yBk8JhmLZvYAUqo= +github.com/newrelic/go-agent/v3/integrations/nrgin v1.2.1/go.mod h1:nXd6QMW8iuY9U/bQSXpjRLbMdCnDaydncooVLqzxygA= +github.com/newrelic/go-agent/v3/integrations/nrmysql v1.2.2 h1:JtaJdL4y1hj5mH0JA2XIIIZtOsivsCmG0wsp3cGtoNo= +github.com/newrelic/go-agent/v3/integrations/nrmysql v1.2.2/go.mod h1:0JZ1gqlaBi9FUrQsg9LLZR357oDH4fGYYTbQQPhOd8o= +github.com/onsi/ginkgo/v2 v2.7.0 h1:/XxtEV3I3Eif/HobnVx9YmJgk8ENdRsuUmM+fLCFNow= +github.com/onsi/ginkgo/v2 v2.7.0/go.mod h1:yjiuMwPokqY1XauOgju45q3sJt6VzQ/Fict1LFVcsAo= +github.com/onsi/gomega v1.24.2 h1:J/tulyYK6JwBldPViHJReihxxZ+22FHs0piGjQAvoUE= +github.com/onsi/gomega v1.24.2/go.mod h1:gs3J10IS7Z7r7eXRoNJIrNqU4ToQukCJhFtKrWgHWnk= github.com/pelletier/go-toml/v2 v2.2.0 h1:QLgLl2yMN7N+ruc31VynXs1vhMZa7CeHHejIeBAsoHo= github.com/pelletier/go-toml/v2 v2.2.0/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/punchh/go-packages v1.2.1 h1:y7HWLFNVXh23wGNk0I6AXiitNy/UOd01EQqVq6H4sJI= +github.com/punchh/go-packages v1.2.1/go.mod h1:DZ5pM4qI81hZOHx54PPw4k5DM0Y8a52kn9D8dajfMCA= github.com/redis/go-redis/v9 v9.5.1 h1:H1X4D3yHPaYrkL5X06Wh6xNVM/pX0Ft4RV0vMGvLBh8= github.com/redis/go-redis/v9 v9.5.1/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M= +github.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w= +github.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= @@ -93,8 +123,9 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE= @@ -102,24 +133,29 @@ github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZ golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/arch v0.7.0 h1:pskyeJh/3AmoQ8CPE95vxHLqp1G1GfGNXTmcl9NEKTc= golang.org/x/arch v0.7.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= -golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= -golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= -golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= -golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= +golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus= +golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M= +golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8= +golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= -golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= -golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= -google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= +golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= +golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= +gonum.org/v1/gonum v0.11.0 h1:f1IJhK4Km5tBJmaiJXtk/PkL4cdVX6J+tGiM187uT5E= +gonum.org/v1/gonum v0.11.0/go.mod h1:fSG4YDCxxUZQJ7rKsQrj0gMOg00Il0Z96/qMA4bVQhA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19 h1:0nDDozoAU19Qb2HwhXadU8OcsiO/09cnTqhUtq2MEOM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= +google.golang.org/grpc v1.54.0 h1:EhTqbhiYeixwWQtAEZAxmV9MGqcjEU2mFx52xCzNyag= +google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g= +google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= +google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/main.go b/main.go index ba67ab1..b80162f 100644 --- a/main.go +++ b/main.go @@ -2,23 +2,59 @@ package main import ( "fmt" + "os" + "strconv" "com.lc.go.codepush/server/config" - "com.lc.go.codepush/server/middleware" + localmw "com.lc.go.codepush/server/middleware" "com.lc.go.codepush/server/request" "github.com/gin-contrib/gzip" - "github.com/gin-gonic/gin" + "github.com/newrelic/go-agent/v3/integrations/nrgin" + punchhmw "github.com/punchh/go-packages/middleware" + "github.com/sirupsen/logrus" ) func main() { fmt.Println("code-push-server-go V1.0.5") // gin.SetMode(gin.ReleaseMode) + + logger := punchhmw.NewLogger(logrus.StandardLogger()) + configs := config.GetConfig() + + // Airbrake on logrus errors (same hook as go-email-templates / go-packages) + airPID, airKey := configs.AirbrakeProjectID, configs.AirbrakeProjectKey + if airPID == 0 { + if s := os.Getenv("AIRBRAKE_PROJECT_ID"); s != "" { + airPID, _ = strconv.ParseInt(s, 10, 64) + } + } + if airKey == "" { + airKey = os.Getenv("AIRBRAKE_PROJECT_KEY") + } + if airPID > 0 && airKey != "" { + logger.AddHook(punchhmw.NewAirbrake(configs.Environment, airPID, airKey)) + } + + nrKey := configs.NewRelicLicenseKey + if nrKey == "" { + nrKey = os.Getenv("NEW_RELIC_LICENSE_KEY") + } + + nr, err := punchhmw.Newnewrelic(configs.Environment, "code-push-server-go", nrKey) + if err != nil { + logger.Println("newrelic init:", err) + } + + logger.Println("starting HTTP server") + g := gin.Default() + if nr != nil && nr.Application != nil { + g.Use(nrgin.Middleware(nr.Application)) + } g.Use(gzip.Gzip(gzip.DefaultCompression)) - g.Use(middleware.Recover) - configs := config.GetConfig() + g.Use(localmw.Recover) // g.Static("/bundels", "bundels") @@ -36,7 +72,7 @@ func main() { { apiGroup.POST("/login", request.User{}.Login) } - authApi := apiGroup.Use(middleware.CheckToken) + authApi := apiGroup.Use(localmw.CheckToken) { authApi.POST("/createApp", request.App{}.CreateApp) authApi.POST("/createDeployment", request.App{}.CreateDeployment) From 2dc84e43b94ff13a8e8563483166606e7ac50a85 Mon Sep 17 00:00:00 2001 From: Kshitij Singh Date: Wed, 15 Apr 2026 12:48:56 +0530 Subject: [PATCH 06/15] airbrake recovery added --- main.go | 8 ++++++-- middleware/middleware.go | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/main.go b/main.go index b80162f..8ed0652 100644 --- a/main.go +++ b/main.go @@ -34,7 +34,9 @@ func main() { airKey = os.Getenv("AIRBRAKE_PROJECT_KEY") } if airPID > 0 && airKey != "" { - logger.AddHook(punchhmw.NewAirbrake(configs.Environment, airPID, airKey)) + abHook := punchhmw.NewAirbrake(configs.Environment, airPID, airKey) + logger.AddHook(abHook) + localmw.SetAirbrakeHook(abHook) } nrKey := configs.NewRelicLicenseKey @@ -49,7 +51,9 @@ func main() { logger.Println("starting HTTP server") - g := gin.Default() + g := gin.New() + g.Use(gin.Logger()) + g.Use(localmw.AirbrakeRecovery()) if nr != nil && nr.Application != nil { g.Use(nrgin.Middleware(nr.Application)) } diff --git a/middleware/middleware.go b/middleware/middleware.go index c04e315..4795e88 100644 --- a/middleware/middleware.go +++ b/middleware/middleware.go @@ -10,8 +10,44 @@ import ( "com.lc.go.codepush/server/model/constants" "com.lc.go.codepush/server/utils" "github.com/gin-gonic/gin" + punchhmw "github.com/punchh/go-packages/middleware" ) +var airbrakeHook *punchhmw.Airbrake + +func SetAirbrakeHook(hook *punchhmw.Airbrake) { + airbrakeHook = hook +} + +func AirbrakeRecovery() gin.HandlerFunc { + return func(c *gin.Context) { + defer func() { + if r := recover(); r != nil { + if airbrakeHook != nil { + airbrakeHook.Notify(r, c.Request) + } + log.Printf("Error:%v", r) + c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{ + "code": 500, + "msg": "Internal Server Error", + "success": false, + }) + } + }() + c.Next() + if c.Writer.Status() >= http.StatusInternalServerError { + if len(c.Errors) > 0 { + for _, e := range c.Errors { + if airbrakeHook != nil { + airbrakeHook.Notify(e.Err, c.Request) + } + log.Printf("server error: %v", e.Err) + } + } + } + } +} + // 檢查token func CheckToken(ctx *gin.Context) { var token, _ = ctx.Cookie("token") From 0733873e1614fbafa77762f4d91c21eeb15c8718 Mon Sep 17 00:00:00 2001 From: Kshitij Singh Date: Fri, 24 Apr 2026 18:42:35 +0530 Subject: [PATCH 07/15] github workflow changes --- .github/workflows/ci.yml | 42 ++++++++++++++++++++++++++++++++++++++++ .github/workflows/go.yml | 30 ---------------------------- 2 files changed, 42 insertions(+), 30 deletions(-) create mode 100644 .github/workflows/ci.yml delete mode 100644 .github/workflows/go.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..24e7c42 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,42 @@ +name: Go CI + +on: + pull_request: + push: + branches: + - main + + workflow_dispatch: + inputs: + skip_tests: + description: 'Skip running tests' + required: false + default: false + type: boolean + triggered_user: + description: 'Who triggered the workflow' + required: false + default: "" + type: string + +jobs: + go-ci: + permissions: + id-token: write + contents: write + packages: read + uses: punchh/GHA-central-workflow/.github/workflows/go-ci.yml@main + + with: + repository: ${{ github.repository }} + branch: ${{ github.event_name == 'workflow_dispatch' && github.ref_name || (github.event_name == 'pull_request' && github.event.pull_request.head.ref || github.ref_name) }} + go_version: 1.24 + triggered_user: ${{ github.event_name == 'workflow_dispatch' && inputs.triggered_user || '' }} + skip_tests: ${{ github.event_name == 'workflow_dispatch' && inputs.skip_tests || false }} + test_cases: false + snyk_severity_threshold: "critical" + go_build: true + secrets: + SVC_ACCOUNT_GITHUB_ORG_TOKEN: ${{ secrets.SVC_ACCOUNT_GITHUB_ORG_TOKEN }} + SVC_ACCOUNT_SNYK_ORG_TOKEN: ${{ secrets.SVC_ACCOUNT_SNYK_ORG_TOKEN }} + CAPTAIN_DEVOPS_SLACK_BOT_TOKEN: ${{ secrets.CAPTAIN_DEVOPS_SLACK_BOT_TOKEN }} diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml deleted file mode 100644 index 07331c2..0000000 --- a/.github/workflows/go.yml +++ /dev/null @@ -1,30 +0,0 @@ -# This workflow will build a golang project -# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-go - -name: Go - -on: - push: - branches: [ "main" ] - pull_request: - branches: [ "main" ] - pull_request_review: - types: [submitted, dismissed] - -jobs: - - build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - name: Set up Go - uses: actions/setup-go@v4 - with: - go-version: '1.21.5' - - name: Install dependencies - run: go get . - - name: Build - run: go build -v ./... - - name: Test with the Go CLI - run: go test From e82c8eac503f8dfe4b3f34c049fed1bce2127814 Mon Sep 17 00:00:00 2001 From: Kshitij Singh Date: Fri, 24 Apr 2026 19:14:13 +0530 Subject: [PATCH 08/15] github workflow changes --- .github/workflows/ci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 24e7c42..353c22a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -35,7 +35,6 @@ jobs: skip_tests: ${{ github.event_name == 'workflow_dispatch' && inputs.skip_tests || false }} test_cases: false snyk_severity_threshold: "critical" - go_build: true secrets: SVC_ACCOUNT_GITHUB_ORG_TOKEN: ${{ secrets.SVC_ACCOUNT_GITHUB_ORG_TOKEN }} SVC_ACCOUNT_SNYK_ORG_TOKEN: ${{ secrets.SVC_ACCOUNT_SNYK_ORG_TOKEN }} From e3a47261c0c8227dfef2928dc490290a8ed9b8dd Mon Sep 17 00:00:00 2001 From: Kshitij Singh Date: Sat, 25 Apr 2026 07:55:13 +0530 Subject: [PATCH 09/15] github workflow changes --- .github/workflows/ci.yml | 69 ++++++++++++++++++++++------------------ 1 file changed, 38 insertions(+), 31 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 353c22a..82599a0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,3 +1,6 @@ +# Self-contained Go CI (does not call punchh/GHA-central-workflow — that reusable +# workflow must be allowed by org settings; use this file if you see "workflow was not found".) + name: Go CI on: @@ -5,37 +8,41 @@ on: push: branches: - main - workflow_dispatch: - inputs: - skip_tests: - description: 'Skip running tests' - required: false - default: false - type: boolean - triggered_user: - description: 'Who triggered the workflow' - required: false - default: "" - type: string + +permissions: + contents: read jobs: - go-ci: - permissions: - id-token: write - contents: write - packages: read - uses: punchh/GHA-central-workflow/.github/workflows/go-ci.yml@main - - with: - repository: ${{ github.repository }} - branch: ${{ github.event_name == 'workflow_dispatch' && github.ref_name || (github.event_name == 'pull_request' && github.event.pull_request.head.ref || github.ref_name) }} - go_version: 1.24 - triggered_user: ${{ github.event_name == 'workflow_dispatch' && inputs.triggered_user || '' }} - skip_tests: ${{ github.event_name == 'workflow_dispatch' && inputs.skip_tests || false }} - test_cases: false - snyk_severity_threshold: "critical" - secrets: - SVC_ACCOUNT_GITHUB_ORG_TOKEN: ${{ secrets.SVC_ACCOUNT_GITHUB_ORG_TOKEN }} - SVC_ACCOUNT_SNYK_ORG_TOKEN: ${{ secrets.SVC_ACCOUNT_SNYK_ORG_TOKEN }} - CAPTAIN_DEVOPS_SLACK_BOT_TOKEN: ${{ secrets.CAPTAIN_DEVOPS_SLACK_BOT_TOKEN }} + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-go@v5 + with: + go-version: "1.24" + + - name: Configure private Go modules (punchh) + env: + TOKEN: ${{ secrets.SVC_ACCOUNT_GITHUB_ORG_TOKEN }} + run: | + if [ -n "$TOKEN" ]; then + git config --global url."https://x-access-token:${TOKEN}@github.com/punchh/".insteadOf "https://github.com/punchh/" + fi + + - name: Go mod download + env: + GOPRIVATE: github.com/punchh + GONOSUMDB: github.com/punchh + run: go mod download + + - name: Build + env: + GOPRIVATE: github.com/punchh + run: go build -v ./... + + - name: Test + env: + GOPRIVATE: github.com/punchh + run: go test -v ./... From 36ee8a384643bf35566060710274935ea2a6281d Mon Sep 17 00:00:00 2001 From: Kshitij Singh Date: Sat, 25 Apr 2026 07:58:18 +0530 Subject: [PATCH 10/15] github workflow changes --- .github/workflows/ci.yml | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 82599a0..99b47db 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,26 +23,41 @@ jobs: with: go-version: "1.24" - - name: Configure private Go modules (punchh) + # Go uses git for GOPRIVATE modules; netrc + url.insteadOf avoids + # "could not read Username for 'https://github.com': terminal prompts disabled". + - name: Authenticate for private github.com/punchh modules env: TOKEN: ${{ secrets.SVC_ACCOUNT_GITHUB_ORG_TOKEN }} run: | - if [ -n "$TOKEN" ]; then - git config --global url."https://x-access-token:${TOKEN}@github.com/punchh/".insteadOf "https://github.com/punchh/" + if [ -z "$TOKEN" ]; then + echo "::error::SVC_ACCOUNT_GITHUB_ORG_TOKEN is empty or not passed to this job." + echo "Add the org/repo secret under Settings → Secrets and variables → Actions." + echo "Fork PRs: GitHub does not give fork workflows access to org secrets—use a branch on this repo for the PR." + exit 1 fi + { + echo "machine github.com" + echo "login x-access-token" + echo "password ${TOKEN}" + } >> "$HOME/.netrc" + chmod 600 "$HOME/.netrc" + git config --global url."https://x-access-token:${TOKEN}@github.com/punchh/".insteadOf "https://github.com/punchh/" - name: Go mod download env: GOPRIVATE: github.com/punchh GONOSUMDB: github.com/punchh + GOPROXY: direct run: go mod download - name: Build env: GOPRIVATE: github.com/punchh + GOPROXY: direct run: go build -v ./... - name: Test env: GOPRIVATE: github.com/punchh + GOPROXY: direct run: go test -v ./... From fc884bcef829b9cee476550dbde5ff92dc60b81b Mon Sep 17 00:00:00 2001 From: Kshitij Singh Date: Sat, 25 Apr 2026 08:01:12 +0530 Subject: [PATCH 11/15] github workflow changes --- .github/workflows/ci.yml | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 99b47db..70c00ef 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -25,15 +25,19 @@ jobs: # Go uses git for GOPRIVATE modules; netrc + url.insteadOf avoids # "could not read Username for 'https://github.com': terminal prompts disabled". + # Prefer org PAT (works for fork PRs if you expose a dedicated secret — usually you still + # need a branch on the upstream repo). If unset, fall back to GITHUB_TOKEN (same-repo + # workflows only; org must allow Actions to read private repos — see GitHub docs). - name: Authenticate for private github.com/punchh modules env: - TOKEN: ${{ secrets.SVC_ACCOUNT_GITHUB_ORG_TOKEN }} + PAT: ${{ secrets.SVC_ACCOUNT_GITHUB_ORG_TOKEN }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | + TOKEN="${PAT}" if [ -z "$TOKEN" ]; then - echo "::error::SVC_ACCOUNT_GITHUB_ORG_TOKEN is empty or not passed to this job." - echo "Add the org/repo secret under Settings → Secrets and variables → Actions." - echo "Fork PRs: GitHub does not give fork workflows access to org secrets—use a branch on this repo for the PR." - exit 1 + TOKEN="${GITHUB_TOKEN}" + echo "SVC_ACCOUNT_GITHUB_ORG_TOKEN not set — using GITHUB_TOKEN for git HTTPS." + echo "If go mod download fails with 403, add SVC_ACCOUNT_GITHUB_ORG_TOKEN or open the PR from a branch on this repo (not a fork)." fi { echo "machine github.com" From b3a1584a4b095af392300e270f5f0815b8d0f6ad Mon Sep 17 00:00:00 2001 From: Kshitij Singh Date: Sat, 25 Apr 2026 08:03:54 +0530 Subject: [PATCH 12/15] github workflow changes --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 70c00ef..7e0a8dc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -47,21 +47,21 @@ jobs: chmod 600 "$HOME/.netrc" git config --global url."https://x-access-token:${TOKEN}@github.com/punchh/".insteadOf "https://github.com/punchh/" + # Do not set GOPROXY=direct: it forces every module through git; some public tags + # (e.g. chenzhuoyu/iasm) can fail with "unknown revision" on GitHub while proxy.golang.org still serves them. + # GOPRIVATE already makes only github.com/punchh/* bypass the proxy. - name: Go mod download env: GOPRIVATE: github.com/punchh GONOSUMDB: github.com/punchh - GOPROXY: direct run: go mod download - name: Build env: GOPRIVATE: github.com/punchh - GOPROXY: direct run: go build -v ./... - name: Test env: GOPRIVATE: github.com/punchh - GOPROXY: direct run: go test -v ./... From dda49e23e661de167ff7c7e1f2beeaa62a344052 Mon Sep 17 00:00:00 2001 From: Kshitij Singh Date: Sat, 25 Apr 2026 08:06:39 +0530 Subject: [PATCH 13/15] github workflow changes --- .github/workflows/ci.yml | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7e0a8dc..2c9d3a9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,21 +23,19 @@ jobs: with: go-version: "1.24" - # Go uses git for GOPRIVATE modules; netrc + url.insteadOf avoids - # "could not read Username for 'https://github.com': terminal prompts disabled". - # Prefer org PAT (works for fork PRs if you expose a dedicated secret — usually you still - # need a branch on the upstream repo). If unset, fall back to GITHUB_TOKEN (same-repo - # workflows only; org must allow Actions to read private repos — see GitHub docs). + # Private module github.com/punchh/go-packages must use a PAT: GITHUB_TOKEN only has + # access to *this* repo, so GitHub returns misleading "repository not found" for other private repos. + # Fork PRs: org secrets are not available — push a branch on punchh/code-push-server-go. - name: Authenticate for private github.com/punchh modules env: - PAT: ${{ secrets.SVC_ACCOUNT_GITHUB_ORG_TOKEN }} - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + TOKEN: ${{ secrets.SVC_ACCOUNT_GITHUB_ORG_TOKEN }} run: | - TOKEN="${PAT}" if [ -z "$TOKEN" ]; then - TOKEN="${GITHUB_TOKEN}" - echo "SVC_ACCOUNT_GITHUB_ORG_TOKEN not set — using GITHUB_TOKEN for git HTTPS." - echo "If go mod download fails with 403, add SVC_ACCOUNT_GITHUB_ORG_TOKEN or open the PR from a branch on this repo (not a fork)." + echo "::error::SVC_ACCOUNT_GITHUB_ORG_TOKEN is required to clone github.com/punchh/go-packages." + echo "GITHUB_TOKEN cannot read sibling private repos (GitHub reports that as 'repository not found')." + echo "Add an org or repo Actions secret: classic PAT with repo scope, or fine-grained PAT with read on punchh/go-packages." + echo "Fork PRs do not receive org secrets — open the PR from a branch on this repository." + exit 1 fi { echo "machine github.com" From 1d5f8e142491d7ba8a2735e1c13b3264cc3adf85 Mon Sep 17 00:00:00 2001 From: Kshitij Singh Date: Sat, 25 Apr 2026 08:08:13 +0530 Subject: [PATCH 14/15] github workflow changes --- .github/workflows/ci.yml | 89 +++++++++++++++------------------------- 1 file changed, 33 insertions(+), 56 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2c9d3a9..b3ad83d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,65 +1,42 @@ -# Self-contained Go CI (does not call punchh/GHA-central-workflow — that reusable -# workflow must be allowed by org settings; use this file if you see "workflow was not found".) - name: Go CI on: pull_request: - push: + push: branches: - main - workflow_dispatch: -permissions: - contents: read + workflow_dispatch: + inputs: + skip_tests: + description: 'Skip running tests' + required: false + default: false + type: boolean + triggered_user: + description: 'Who triggered the workflow' + required: false + default: "" + type: string jobs: - build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - uses: actions/setup-go@v5 - with: - go-version: "1.24" - - # Private module github.com/punchh/go-packages must use a PAT: GITHUB_TOKEN only has - # access to *this* repo, so GitHub returns misleading "repository not found" for other private repos. - # Fork PRs: org secrets are not available — push a branch on punchh/code-push-server-go. - - name: Authenticate for private github.com/punchh modules - env: - TOKEN: ${{ secrets.SVC_ACCOUNT_GITHUB_ORG_TOKEN }} - run: | - if [ -z "$TOKEN" ]; then - echo "::error::SVC_ACCOUNT_GITHUB_ORG_TOKEN is required to clone github.com/punchh/go-packages." - echo "GITHUB_TOKEN cannot read sibling private repos (GitHub reports that as 'repository not found')." - echo "Add an org or repo Actions secret: classic PAT with repo scope, or fine-grained PAT with read on punchh/go-packages." - echo "Fork PRs do not receive org secrets — open the PR from a branch on this repository." - exit 1 - fi - { - echo "machine github.com" - echo "login x-access-token" - echo "password ${TOKEN}" - } >> "$HOME/.netrc" - chmod 600 "$HOME/.netrc" - git config --global url."https://x-access-token:${TOKEN}@github.com/punchh/".insteadOf "https://github.com/punchh/" - - # Do not set GOPROXY=direct: it forces every module through git; some public tags - # (e.g. chenzhuoyu/iasm) can fail with "unknown revision" on GitHub while proxy.golang.org still serves them. - # GOPRIVATE already makes only github.com/punchh/* bypass the proxy. - - name: Go mod download - env: - GOPRIVATE: github.com/punchh - GONOSUMDB: github.com/punchh - run: go mod download - - - name: Build - env: - GOPRIVATE: github.com/punchh - run: go build -v ./... - - - name: Test - env: - GOPRIVATE: github.com/punchh - run: go test -v ./... + go-ci: + permissions: + id-token: write + contents: write + packages: read + uses: punchh/GHA-central-workflow/.github/workflows/go-ci.yml@main + + with: + repository: ${{ github.repository }} + branch: ${{ github.event_name == 'workflow_dispatch' && github.ref_name || (github.event_name == 'pull_request' && github.event.pull_request.head.ref || github.ref_name) }} + go_version: 1.24.1 + triggered_user: ${{ github.event_name == 'workflow_dispatch' && inputs.triggered_user || '' }} + skip_tests: ${{ github.event_name == 'workflow_dispatch' && inputs.skip_tests || false }} + test_cases: false + snyk_severity_threshold: "critical" + go_build: true + secrets: + SVC_ACCOUNT_GITHUB_ORG_TOKEN: ${{ secrets.SVC_ACCOUNT_GITHUB_ORG_TOKEN }} + SVC_ACCOUNT_SNYK_ORG_TOKEN: ${{ secrets.SVC_ACCOUNT_SNYK_ORG_TOKEN }} + CAPTAIN_DEVOPS_SLACK_BOT_TOKEN: ${{ secrets.CAPTAIN_DEVOPS_SLACK_BOT_TOKEN }} \ No newline at end of file From f4f380899cd8281e0b0e792714ce23ee6cca5461 Mon Sep 17 00:00:00 2001 From: Kshitij Singh Date: Sat, 25 Apr 2026 10:15:12 +0530 Subject: [PATCH 15/15] newrelic and airbrake integration changes --- .github/workflows/release.yaml | 4 ++-- README.md | 2 +- config/config.go | 23 +++++++++++++------ db/db.go | 5 +++- main.go | 11 +++++---- middleware/middleware.go | 42 +++++++++++----------------------- 6 files changed, 43 insertions(+), 44 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 6abb60e..3e5cd7d 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -19,9 +19,9 @@ jobs: with: fetch-depth: 0 - run: git fetch --force --tags - - uses: actions/setup-go@v3 + - uses: actions/setup-go@v5 with: - go-version: '1.21.5' + go-version: '1.24' cache: true # More assembly might be required: Docker logins, GPG, etc. It all depends # on your needs. diff --git a/README.md b/README.md index ab74d14..c7fa41a 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ Codepush server go is compatible with [react-native-code-push](https://github.co ## Support version - [mysql](https://dev.mysql.com/downloads/mysql/) >= 8.0 -- [golang](https://go.dev/dl/) >= 1.21.5 +- [golang](https://go.dev/dl/) >= 1.24 - [redis](https://redis.io/downloads/) >= 5.0 ## Support client version diff --git a/config/config.go b/config/config.go index f696a5a..2b3d111 100644 --- a/config/config.go +++ b/config/config.go @@ -80,18 +80,23 @@ func GetConfig() *appConfig { } func LoadConfig() *appConfig { - intFormatter := func(v interface{}) (val int64) { + intFormatter := func(v interface{}) (val int64, ok bool) { switch ta := v.(type) { case int: - val = int64(ta) + return int64(ta), true case int64: - val = ta + return ta, true case float64: - val = int64(ta) + return int64(ta), true case string: - val, _ = strconv.ParseInt(ta, 10, 64) + parsed, err := strconv.ParseInt(ta, 10, 64) + if err != nil { + return 0, false + } + return parsed, true + default: + return 0, false } - return } fmt.Println("Fetching config from AWS secret manager...") @@ -226,7 +231,11 @@ func LoadConfig() *appConfig { } if k == "airbrake_project_id" { - config.AirbrakeProjectID = intFormatter(v) + if parsed, ok := intFormatter(v); ok { + config.AirbrakeProjectID = parsed + } else { + fmt.Printf("config: invalid airbrake_project_id value (%T): %v\n", v, v) + } } if k == "airbrake_project_key" { config.AirbrakeProjectKey = v.(string) diff --git a/db/db.go b/db/db.go index 79a774b..2671a48 100644 --- a/db/db.go +++ b/db/db.go @@ -22,7 +22,10 @@ func GetUserDB() (odb *gorm.DB, err error) { dbConfig := config.GetConfig().DBUser dsnSource := dbConfig.Write.UserName + ":" + dbConfig.Write.Password + "@tcp(" + dbConfig.Write.Host + ":" + strconv.Itoa(int(dbConfig.Write.Port)) + ")/" + dbConfig.Write.DBname + "?charset=utf8mb4&parseTime=True&loc=Local" - // Same driver as go-email-templates (sql.Open("nrmysql", ...)); pairs with HTTP txns when using Request context. + // New Relic datastore instrumentation: + // Using the "nrmysql" driver enables MySQL metrics. To associate DB segments with the + // current HTTP transaction, queries must run with the request context + // (e.g. via `db.WithContext(c.Request.Context())` in handlers). db, err := gorm.Open(mysql.New(mysql.Config{ DriverName: "nrmysql", DSN: dsnSource, diff --git a/main.go b/main.go index 8ed0652..593136a 100644 --- a/main.go +++ b/main.go @@ -44,16 +44,19 @@ func main() { nrKey = os.Getenv("NEW_RELIC_LICENSE_KEY") } - nr, err := punchhmw.Newnewrelic(configs.Environment, "code-push-server-go", nrKey) - if err != nil { - logger.Println("newrelic init:", err) + var nr *punchhmw.NewRelic + if nrKey != "" { + var err error + nr, err = punchhmw.Newnewrelic(configs.Environment, "code-push-server-go", nrKey) + if err != nil { + logger.Println("newrelic init:", err) + } } logger.Println("starting HTTP server") g := gin.New() g.Use(gin.Logger()) - g.Use(localmw.AirbrakeRecovery()) if nr != nil && nr.Application != nil { g.Use(nrgin.Middleware(nr.Application)) } diff --git a/middleware/middleware.go b/middleware/middleware.go index 4795e88..4f0ab28 100644 --- a/middleware/middleware.go +++ b/middleware/middleware.go @@ -19,35 +19,6 @@ func SetAirbrakeHook(hook *punchhmw.Airbrake) { airbrakeHook = hook } -func AirbrakeRecovery() gin.HandlerFunc { - return func(c *gin.Context) { - defer func() { - if r := recover(); r != nil { - if airbrakeHook != nil { - airbrakeHook.Notify(r, c.Request) - } - log.Printf("Error:%v", r) - c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{ - "code": 500, - "msg": "Internal Server Error", - "success": false, - }) - } - }() - c.Next() - if c.Writer.Status() >= http.StatusInternalServerError { - if len(c.Errors) > 0 { - for _, e := range c.Errors { - if airbrakeHook != nil { - airbrakeHook.Notify(e.Err, c.Request) - } - log.Printf("server error: %v", e.Err) - } - } - } - } -} - // 檢查token func CheckToken(ctx *gin.Context) { var token, _ = ctx.Cookie("token") @@ -90,6 +61,9 @@ func Recover(c *gin.Context) { // 加载defer异常处理 defer func() { if err := recover(); err != nil { + if airbrakeHook != nil { + airbrakeHook.Notify(err, c.Request) + } c.Writer.WriteHeader(http.StatusInternalServerError) log.Printf("Error:%s", err) // 返回统一的Json风格 @@ -115,4 +89,14 @@ func Recover(c *gin.Context) { } //继续操作 c.Next() + + // Report 5xx errors after handler execution (non-panic paths). + if c.Writer.Status() >= http.StatusInternalServerError && len(c.Errors) > 0 { + for _, e := range c.Errors { + if airbrakeHook != nil { + airbrakeHook.Notify(e.Err, c.Request) + } + log.Printf("server error: %v", e.Err) + } + } }