Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,4 @@ jobs:
run: make vet

- name: Lint
uses: golangci/golangci-lint-action@v6
uses: golangci/golangci-lint-action@v9
187 changes: 136 additions & 51 deletions .golangci.yml
Original file line number Diff line number Diff line change
@@ -1,21 +1,87 @@
run:
deadline: 5m

version: "2"
linters:
presets:
- bugs
- comment
- error
- format
- import
- metalinter
- performance
- style
- unused
enable:
- asasalint
- asciicheck
- bidichk
- bodyclose
- canonicalheader
- containedctx
- contextcheck
- copyloopvar
- decorder
- depguard
- dogsled
- dupl
- dupword
- durationcheck
- errchkjson
- errname
- errorlint
- exhaustive
- exptostd
- fatcontext
- forbidigo
- forcetypeassert
- ginkgolinter
- gocheckcompilerdirectives
- gochecknoinits
- gochecksumtype
- goconst
- gocritic
- godot
- goheader
- gomodguard
- goprintffuncname
- gosec
- gosmopolitan
- grouper
- iface
- importas
- inamedparam
- interfacebloat
- intrange
- loggercheck
- makezero
- mirror
- misspell
- mnd
- musttag
- nakedret
- nilerr
- nilnesserr
- nilnil
- noctx
- nolintlint
- nonamedreturns
- nosprintfhostport
- perfsprint
- prealloc
- predeclared
- promlinter
- protogetter
- reassign
- recvcheck
- revive
- rowserrcheck
- sloglint
- spancheck
- sqlclosecheck
- staticcheck
- tagalign
- tagliatelle
- testifylint
- tparallel
- unconvert
- unparam
- usestdlibvars
- wastedassign
- whitespace
- zerologlint
disable:
- err113
- exhaustruct
- funlen
- gci
- gochecknoglobals
- godox
- gomoddirectives
Expand All @@ -27,41 +93,60 @@ linters:
- varnamelen
- wrapcheck
- wsl
- err113

issues:
exclude-rules:
- path: _test.go
linters:
- errcheck

linters-settings:
depguard:
rules:
Main:
deny:
- pkg: sync/atomic
desc: Use go.uber.org/atomic instead of sync/atomic
- pkg: github.com/stretchr/testify/assert
desc: Use github.com/stretchr/testify/require instead of github.com/stretchr/testify/assert
- pkg: github.com/go-kit/kit/log
desc: Use github.com/go-kit/log instead of github.com/go-kit/kit/log
- pkg: github.com/pkg/errors
desc: Use fmt.Errorf instead
errcheck:
exclude-functions: ./.errcheck_excludes.txt
goimports:
local-prefixes: github.com/parca-dev/parca-debuginfo
gofumpt:
extra-rules: true
misspell:
locale: US
revive:
settings:
cyclop:
max-complexity: 15
depguard:
rules:
Main:
deny:
- pkg: sync/atomic
desc: Use go.uber.org/atomic instead of sync/atomic
- pkg: github.com/stretchr/testify/assert
desc: Use github.com/stretchr/testify/require instead of github.com/stretchr/testify/assert
- pkg: github.com/go-kit/kit/log
desc: Use github.com/go-kit/log instead of github.com/go-kit/kit/log
- pkg: github.com/pkg/errors
desc: Use fmt.Errorf instead
errcheck:
exclude-functions:
- (github.com/go-kit/log.Logger).Log
misspell:
locale: US
revive:
rules:
- name: unexported-return
severity: warning
disabled: true
exclusions:
generated: lax
presets:
- comments
- common-false-positives
- legacy
- std-error-handling
rules:
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#unexported-return
- name: unexported-return
severity: warning
disabled: true
cyclop:
# The maximal code complexity to report.
max-complexity: 15
- linters:
- errcheck
path: _test.go
paths:
- third_party$
- builtin$
- examples$
formatters:
enable:
- gofmt
- gofumpt
- goimports
settings:
gofumpt:
extra-rules: true
goimports:
local-prefixes:
- github.com/parca-dev/parca-debuginfo
exclusions:
generated: lax
paths:
- third_party$
- builtin$
- examples$
70 changes: 55 additions & 15 deletions cmd/parca-debuginfo/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,26 +43,29 @@ import (
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/credentials/insecure"
"google.golang.org/grpc/metadata"
)

const (
LogLevelDebug = "debug"
LogLevelDebug = "debug"
headerKeyValuePairElements = 2
)

type flags struct {
LogLevel string `kong:"enum='error,warn,info,debug',help='Log level.',default='info'"`

Upload struct {
StoreAddress string `kong:"required,help='gRPC address to sends symbols to.'"`
BearerToken string `kong:"help='Bearer token to authenticate with store.',env='PARCA_DEBUGINFO_BEARER_TOKEN'"`
BearerTokenFile string `kong:"help='File to read bearer token from to authenticate with store.'"`
Insecure bool `kong:"help='Send gRPC requests via plaintext instead of TLS.'"`
InsecureSkipVerify bool `kong:"help='Skip TLS certificate verification.'"`
NoExtract bool `kong:"help='Do not extract debug information from binaries, just upload the binary as is.'"`
NoInitiate bool `kong:"help='Do not initiate the upload, just check if it should be initiated.'"`
Force bool `kong:"help='Force upload even if the Build ID is already uploaded.'"`
Type string `kong:"enum='debuginfo,executable,sources',help='Type of the debug information to upload.',default='debuginfo'"`
BuildID string `kong:"help='Build ID of the binary to upload.'"`
StoreAddress string `kong:"required,help='gRPC address to sends symbols to.'"`
BearerToken string `kong:"help='Bearer token to authenticate with store.',env='PARCA_DEBUGINFO_BEARER_TOKEN'"`
BearerTokenFile string `kong:"help='File to read bearer token from to authenticate with store.'"`
Insecure bool `kong:"help='Send gRPC requests via plaintext instead of TLS.'"`
InsecureSkipVerify bool `kong:"help='Skip TLS certificate verification.'"`
GRPCHeaders map[string]string `kong:"help='Additional gRPC headers to send with each request (key=value pairs).'"`
NoExtract bool `kong:"help='Do not extract debug information from binaries, just upload the binary as is.'"`
NoInitiate bool `kong:"help='Do not initiate the upload, just check if it should be initiated.'"`
Force bool `kong:"help='Force upload even if the Build ID is already uploaded.'"`
Type string `kong:"enum='debuginfo,executable,sources',help='Type of the debug information to upload.',default='debuginfo'"`
BuildID string `kong:"help='Build ID of the binary to upload.'"`

Path string `kong:"required,arg,name='path',help='Paths to upload.',type:'path'"`
} `cmd:"" help:"Upload debug information files."`
Expand Down Expand Up @@ -429,10 +432,25 @@ func grpcConn(reg prometheus.Registerer, flags flags) (*grpc.ClientConn, error)
met.EnableClientHandlingTimeHistogram()
reg.MustRegister(met)

unaryInterceptors := []grpc.UnaryClientInterceptor{
met.UnaryClientInterceptor(),
}
streamInterceptors := []grpc.StreamClientInterceptor{}

if len(flags.Upload.GRPCHeaders) > 0 {
unaryInterceptors = append(
[]grpc.UnaryClientInterceptor{customHeadersUnaryInterceptor(flags.Upload.GRPCHeaders)},
unaryInterceptors...,
)
streamInterceptors = append(
[]grpc.StreamClientInterceptor{customHeadersStreamInterceptor(flags.Upload.GRPCHeaders)},
streamInterceptors...,
)
}

opts := []grpc.DialOption{
grpc.WithUnaryInterceptor(
met.UnaryClientInterceptor(),
),
grpc.WithChainUnaryInterceptor(unaryInterceptors...),
grpc.WithChainStreamInterceptor(streamInterceptors...),
}
if flags.Upload.Insecure {
opts = append(opts, grpc.WithTransportCredentials(insecure.NewCredentials()))
Expand Down Expand Up @@ -480,6 +498,28 @@ func (t *perRequestBearerToken) RequireTransportSecurity() bool {
return !t.insecure
}

func customHeadersUnaryInterceptor(headers map[string]string) grpc.UnaryClientInterceptor {
return func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
kvPairs := make([]string, 0, len(headers)*headerKeyValuePairElements)
for key, value := range headers {
kvPairs = append(kvPairs, key, value)
}
newCtx := metadata.AppendToOutgoingContext(ctx, kvPairs...)
return invoker(newCtx, method, req, reply, cc, opts...)
}
}

func customHeadersStreamInterceptor(headers map[string]string) grpc.StreamClientInterceptor {
return func(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, streamer grpc.Streamer, opts ...grpc.CallOption) (grpc.ClientStream, error) {
kvPairs := make([]string, 0, len(headers)*headerKeyValuePairElements)
for key, value := range headers {
kvPairs = append(kvPairs, key, value)
}
newCtx := metadata.AppendToOutgoingContext(ctx, kvPairs...)
return streamer(newCtx, desc, cc, method, opts...)
}
}

func uploadViaSignedURL(ctx context.Context, url string, r io.Reader) error {
req, err := http.NewRequestWithContext(ctx, http.MethodPut, url, r)
if err != nil {
Expand Down Expand Up @@ -587,7 +627,7 @@ func getNoteHexString(sectionBytes []byte, name string, noteType uint32) (string

// read descsz and compute the last index of the note data
dataSize := binary.LittleEndian.Uint32(sectionBytes[idx-4 : idx])
idxDataEnd := uint64(idxDataStart) + uint64(dataSize) //nolint:gosec
idxDataEnd := uint64(idxDataStart) + uint64(dataSize)

// Check sanity (64 is totally arbitrary, as we only use it for Linux ID and Build ID)
if idxDataEnd > uint64(len(sectionBytes)) || dataSize > 64 {
Expand Down
Loading