Skip to content

Commit 57b8233

Browse files
committed
refactor: apply code style and linter improvements across Go files
- Refactor file locking parameters into top-level constants in filelock.go for improved maintainability. - Replace duplicated error handling durations and retry settings with reusable constants in file locking logic. - Update for-loops to use range-based iteration on integer variables for better Go style in tests and concurrency code. - Replace usage of fmt.Errorf with errors.New for static error strings. - Prefer named http.Method* constants over string literals for HTTP methods in main.go and tests. - Use map[string]any instead of map[string]interface{} for type declarations. - Add and fine-tune multiple linters and their configurations in .golangci.yml; introduce new linter settings and rules, improve output formatting, and remove several linters no longer used. - Update comments or linter ignore statements for greater clarity. - Use a min() helper rather than manual interval capping in polling logic. Signed-off-by: appleboy <appleboy.tw@gmail.com>
1 parent c986f6f commit 57b8233

6 files changed

Lines changed: 137 additions & 59 deletions

File tree

.golangci.yml

Lines changed: 89 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,118 @@
11
version: "2"
2+
output:
3+
sort-order:
4+
- file
25
linters:
36
default: none
47
enable:
8+
- bidichk
59
- bodyclose
6-
- dogsled
7-
- dupl
10+
- depguard
811
- errcheck
9-
- exhaustive
10-
- goconst
12+
- forbidigo
13+
- gocheckcompilerdirectives
1114
- gocritic
12-
- gocyclo
13-
- goprintffuncname
14-
- gosec
1515
- govet
1616
- ineffassign
17-
- misspell
17+
- mirror
18+
- modernize
1819
- nakedret
19-
- noctx
20+
- nilnil
2021
- nolintlint
21-
- rowserrcheck
22+
- perfsprint
23+
- revive
2224
- staticcheck
25+
- testifylint
2326
- unconvert
2427
- unparam
2528
- unused
26-
- whitespace
29+
- usestdlibvars
30+
- usetesting
31+
- wastedassign
32+
settings:
33+
depguard:
34+
rules:
35+
main:
36+
deny:
37+
- pkg: io/ioutil
38+
desc: use os or io instead
39+
- pkg: golang.org/x/exp
40+
desc: it's experimental and unreliable
41+
- pkg: github.com/pkg/errors
42+
desc: use builtin errors package instead
43+
nolintlint:
44+
allow-unused: false
45+
require-explanation: true
46+
require-specific: true
47+
gocritic:
48+
enabled-checks:
49+
- equalFold
50+
disabled-checks: []
51+
revive:
52+
severity: error
53+
rules:
54+
- name: blank-imports
55+
- name: constant-logical-expr
56+
- name: context-as-argument
57+
- name: context-keys-type
58+
- name: dot-imports
59+
- name: empty-lines
60+
- name: error-return
61+
- name: error-strings
62+
- name: exported
63+
- name: identical-branches
64+
- name: if-return
65+
- name: increment-decrement
66+
- name: modifies-value-receiver
67+
- name: package-comments
68+
- name: redefines-builtin-id
69+
- name: superfluous-else
70+
- name: time-naming
71+
- name: unexported-return
72+
- name: var-declaration
73+
- name: var-naming
74+
disabled: true
75+
staticcheck:
76+
checks:
77+
- all
78+
testifylint: {}
79+
usetesting:
80+
os-temp-dir: true
81+
forbidigo:
82+
forbid:
83+
- pattern: "^(print|println)$"
84+
msg: "use fmt.Print* instead of built-in print/println"
85+
perfsprint:
86+
concat-loop: false
87+
govet:
88+
enable:
89+
- nilness
90+
- unusedwrite
2791
exclusions:
2892
generated: lax
2993
presets:
3094
- comments
3195
- common-false-positives
3296
- legacy
3397
- std-error-handling
34-
paths:
35-
- third_party$
36-
- builtin$
37-
- examples$
98+
rules:
99+
- linters:
100+
- errcheck
101+
- staticcheck
102+
- unparam
103+
path: _test\.go
104+
issues:
105+
max-issues-per-linter: 0
106+
max-same-issues: 0
38107
formatters:
39108
enable:
40109
- gofmt
41110
- gofumpt
42-
- goimports
43111
- golines
112+
settings:
113+
gofumpt:
114+
extra-rules: true
44115
exclusions:
45116
generated: lax
46-
paths:
47-
- third_party$
48-
- builtin$
49-
- examples$
117+
run:
118+
timeout: 10m

filelock.go

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@ import (
66
"time"
77
)
88

9+
const (
10+
lockMaxRetries = 50
11+
lockRetryDelay = 100 * time.Millisecond
12+
staleLockTimeout = 30 * time.Second
13+
)
14+
915
// fileLock represents a file lock.
1016
type fileLock struct {
1117
lockFile *os.File
@@ -16,10 +22,8 @@ type fileLock struct {
1622
// Uses a separate lock file to coordinate access across processes.
1723
func acquireFileLock(filePath string) (*fileLock, error) {
1824
lockPath := filePath + ".lock"
19-
maxRetries := 50
20-
retryDelay := 100 * time.Millisecond
2125

22-
for i := 0; i < maxRetries; i++ {
26+
for range lockMaxRetries {
2327
lockFile, err := os.OpenFile(lockPath, os.O_CREATE|os.O_EXCL|os.O_WRONLY, 0o600)
2428
if err == nil {
2529
fmt.Fprintf(lockFile, "%d", os.Getpid())
@@ -31,7 +35,7 @@ func acquireFileLock(filePath string) (*fileLock, error) {
3135

3236
if os.IsExist(err) {
3337
if info, statErr := os.Stat(lockPath); statErr == nil {
34-
if time.Since(info.ModTime()) > 30*time.Second {
38+
if time.Since(info.ModTime()) > staleLockTimeout {
3539
if remErr := os.Remove(lockPath); remErr != nil && !os.IsNotExist(remErr) {
3640
return nil, fmt.Errorf(
3741
"failed to remove stale lock file %s: %w",
@@ -42,7 +46,7 @@ func acquireFileLock(filePath string) (*fileLock, error) {
4246
continue
4347
}
4448
}
45-
time.Sleep(retryDelay)
49+
time.Sleep(lockRetryDelay)
4650
continue
4751
}
4852

@@ -51,7 +55,7 @@ func acquireFileLock(filePath string) (*fileLock, error) {
5155

5256
return nil, fmt.Errorf(
5357
"timeout waiting for file lock after %v",
54-
time.Duration(maxRetries)*retryDelay,
58+
time.Duration(lockMaxRetries)*lockRetryDelay,
5559
)
5660
}
5761

filelock_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ func TestConcurrentLocks(t *testing.T) {
4040
var mu sync.Mutex
4141
concurrent := 0
4242

43-
for i := 0; i < goroutines; i++ {
43+
for i := range goroutines {
4444
wg.Add(1)
4545
go func(idx int) {
4646
defer wg.Done()

main.go

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ func getEnv(key, defaultValue string) string {
157157
// validateServerURL validates that the server URL is properly formatted
158158
func validateServerURL(rawURL string) error {
159159
if rawURL == "" {
160-
return fmt.Errorf("server URL cannot be empty")
160+
return errors.New("server URL cannot be empty")
161161
}
162162

163163
u, err := url.Parse(rawURL)
@@ -170,7 +170,7 @@ func validateServerURL(rawURL string) error {
170170
}
171171

172172
if u.Host == "" {
173-
return fmt.Errorf("URL must include a host")
173+
return errors.New("URL must include a host")
174174
}
175175

176176
return nil
@@ -182,12 +182,12 @@ type ErrorResponse struct {
182182
}
183183

184184
// ErrRefreshTokenExpired indicates that the refresh token has expired or is invalid
185-
var ErrRefreshTokenExpired = fmt.Errorf("refresh token expired or invalid")
185+
var ErrRefreshTokenExpired = errors.New("refresh token expired or invalid")
186186

187187
// validateTokenResponse validates the OAuth token response
188188
func validateTokenResponse(accessToken, tokenType string, expiresIn int) error {
189189
if accessToken == "" {
190-
return fmt.Errorf("access_token is empty")
190+
return errors.New("access_token is empty")
191191
}
192192

193193
if len(accessToken) < 10 {
@@ -330,7 +330,7 @@ func requestDeviceCode(ctx context.Context) (*oauth2.DeviceAuthResponse, error)
330330

331331
req, err := http.NewRequestWithContext(
332332
reqCtx,
333-
"POST",
333+
http.MethodPost,
334334
serverURL+"/oauth/device/code",
335335
strings.NewReader(data.Encode()),
336336
)
@@ -491,21 +491,20 @@ func pollForTokenWithProgress(
491491
case "slow_down":
492492
// Server requests slower polling - increase interval
493493
backoffMultiplier *= 1.5
494-
newInterval := time.Duration(float64(pollInterval) * backoffMultiplier)
495-
if newInterval > 60*time.Second {
496-
newInterval = 60 * time.Second // Cap at 60 seconds
497-
}
498-
pollInterval = newInterval
494+
pollInterval = min(
495+
time.Duration(float64(pollInterval)*backoffMultiplier),
496+
60*time.Second,
497+
)
499498
pollTicker.Reset(pollInterval)
500499
continue
501500

502501
case "expired_token":
503502
fmt.Println()
504-
return nil, fmt.Errorf("device code expired, please restart the flow")
503+
return nil, errors.New("device code expired, please restart the flow")
505504

506505
case "access_denied":
507506
fmt.Println()
508-
return nil, fmt.Errorf("user denied authorization")
507+
return nil, errors.New("user denied authorization")
509508

510509
default:
511510
fmt.Println()
@@ -558,7 +557,7 @@ func exchangeDeviceCode(
558557

559558
req, err := http.NewRequestWithContext(
560559
reqCtx,
561-
"POST",
560+
http.MethodPost,
562561
tokenURL,
563562
strings.NewReader(data.Encode()),
564563
)
@@ -623,7 +622,9 @@ func verifyToken(ctx context.Context, accessToken string) error {
623622
reqCtx, cancel := context.WithTimeout(ctx, tokenVerificationTimeout)
624623
defer cancel()
625624

626-
req, err := http.NewRequestWithContext(reqCtx, "GET", serverURL+"/oauth/tokeninfo", nil)
625+
req, err := http.NewRequestWithContext(
626+
reqCtx, http.MethodGet, serverURL+"/oauth/tokeninfo", nil,
627+
)
627628
if err != nil {
628629
return fmt.Errorf("failed to create request: %w", err)
629630
}
@@ -666,7 +667,7 @@ func loadTokens() (*TokenStorage, error) {
666667
}
667668

668669
if storageMap.Tokens == nil {
669-
return nil, fmt.Errorf("no tokens found in token file")
670+
return nil, errors.New("no tokens found in token file")
670671
}
671672

672673
// Look up token for current client_id
@@ -755,7 +756,7 @@ func refreshAccessToken(ctx context.Context, refreshToken string) (*TokenStorage
755756

756757
req, err := http.NewRequestWithContext(
757758
reqCtx,
758-
"POST",
759+
http.MethodPost,
759760
serverURL+"/oauth/token",
760761
strings.NewReader(data.Encode()),
761762
)
@@ -840,7 +841,9 @@ func makeAPICallWithAutoRefresh(ctx context.Context, storage *TokenStorage) erro
840841
reqCtx, cancel := context.WithTimeout(ctx, tokenVerificationTimeout)
841842
defer cancel()
842843

843-
req, err := http.NewRequestWithContext(reqCtx, "GET", serverURL+"/oauth/tokeninfo", nil)
844+
req, err := http.NewRequestWithContext(
845+
reqCtx, http.MethodGet, serverURL+"/oauth/tokeninfo", nil,
846+
)
844847
if err != nil {
845848
return fmt.Errorf("failed to create request: %w", err)
846849
}
@@ -877,7 +880,9 @@ func makeAPICallWithAutoRefresh(ctx context.Context, storage *TokenStorage) erro
877880
retryCtx, retryCancel := context.WithTimeout(ctx, tokenVerificationTimeout)
878881
defer retryCancel()
879882

880-
req, err = http.NewRequestWithContext(retryCtx, "GET", serverURL+"/oauth/tokeninfo", nil)
883+
req, err = http.NewRequestWithContext(
884+
retryCtx, http.MethodGet, serverURL+"/oauth/tokeninfo", nil,
885+
)
881886
if err != nil {
882887
return fmt.Errorf("failed to create retry request: %w", err)
883888
}

0 commit comments

Comments
 (0)