Skip to content

Commit 1edc457

Browse files
authored
Merge pull request #1152 from wakatime/develop
Release v1.110.0
2 parents 80e53d7 + 92addb5 commit 1edc457

20 files changed

+106
-148
lines changed

.golangci.yml

+4
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ linters:
1818
- revive
1919
- testpackage
2020
- unconvert
21+
- usetesting
2122
- usestdlibvars
2223
- whitespace
2324
- wsl
@@ -54,6 +55,9 @@ linters-settings:
5455
- name: unused-receiver
5556
- name: var-declaration
5657
- name: var-naming
58+
usetesting:
59+
os-setenv: true
60+
os-temp-dir: true
5761
issues:
5862
exclude-use-default: false
5963
exclude-dirs:

cmd/api/api.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package api
33
import (
44
"context"
55
"fmt"
6+
"runtime/debug"
67
"strings"
78

89
paramscmd "github.com/wakatime/wakatime-cli/cmd/params"
@@ -85,8 +86,8 @@ func newClient(ctx context.Context, params paramscmd.API, opts ...api.Option) (*
8586

8687
func timezone() (name string, err error) {
8788
defer func() {
88-
if e := recover(); e != nil {
89-
err = fmt.Errorf("panicked when detecting timezone: %s", e)
89+
if r := recover(); r != nil {
90+
err = fmt.Errorf("panicked: failed to get timezone: %v. Stack: %s", r, string(debug.Stack()))
9091
}
9192
}()
9293

cmd/logfile/logfile.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ func LoadParams(ctx context.Context, v *viper.Viper) (Params, error) {
4848
if logFile != "" {
4949
p, err := homedir.Expand(logFile)
5050
if err != nil {
51-
return Params{}, fmt.Errorf("failed expanding log file: %s", err)
51+
return Params{}, fmt.Errorf("failed to expand log file: %s", err)
5252
}
5353

5454
params.File = p
@@ -58,7 +58,7 @@ func LoadParams(ctx context.Context, v *viper.Viper) (Params, error) {
5858

5959
folder, err := ini.WakaResourcesDir(ctx)
6060
if err != nil {
61-
return Params{}, fmt.Errorf("failed getting resource directory: %s", err)
61+
return Params{}, fmt.Errorf("failed to get resource directory: %s", err)
6262
}
6363

6464
params.File = filepath.Join(folder, defaultFile)

cmd/logfile/logfile_test.go

+1-4
Original file line numberDiff line numberDiff line change
@@ -132,10 +132,7 @@ func TestLoadParams(t *testing.T) {
132132
v.Set("settings.debug", test.ViperDebug)
133133
v.Set("verbose", test.ViperDebugConfig)
134134

135-
err := os.Setenv("WAKATIME_HOME", test.EnvVar)
136-
require.NoError(t, err)
137-
138-
defer os.Unsetenv("WAKATIME_HOME")
135+
t.Setenv("WAKATIME_HOME", test.EnvVar)
139136

140137
params, err := logfile.LoadParams(ctx, v)
141138
require.NoError(t, err)

cmd/params/params.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"os"
1212
"os/exec"
1313
"regexp"
14+
"runtime/debug"
1415
"strconv"
1516
"strings"
1617
"sync"
@@ -732,7 +733,7 @@ func LoadStatusBarParams(v *viper.Viper) (StatusBar, error) {
732733
func safeTimeParse(format string, s string) (parsed time.Time, err error) {
733734
defer func() {
734735
if r := recover(); r != nil {
735-
err = fmt.Errorf("time.Parse panic: %v", r)
736+
err = fmt.Errorf("panicked: failed to time.Parse: %v. Stack: %s", r, string(debug.Stack()))
736737
}
737738
}()
738739

cmd/params/params_test.go

+10-37
Original file line numberDiff line numberDiff line change
@@ -2093,10 +2093,7 @@ func TestLoadParams_ApiKey_FromVault_Err_Darwin(t *testing.T) {
20932093
func TestLoadAPIParams_APIKeyFromEnv(t *testing.T) {
20942094
v := viper.New()
20952095

2096-
err := os.Setenv("WAKATIME_API_KEY", "00000000-0000-4000-8000-000000000000")
2097-
require.NoError(t, err)
2098-
2099-
defer os.Unsetenv("WAKATIME_API_KEY")
2096+
t.Setenv("WAKATIME_API_KEY", "00000000-0000-4000-8000-000000000000")
21002097

21012098
params, err := cmdparams.LoadAPIParams(context.Background(), v)
21022099
require.NoError(t, err)
@@ -2107,12 +2104,9 @@ func TestLoadAPIParams_APIKeyFromEnv(t *testing.T) {
21072104
func TestLoadAPIParams_APIKeyFromEnvInvalid(t *testing.T) {
21082105
v := viper.New()
21092106

2110-
err := os.Setenv("WAKATIME_API_KEY", "00000000-0000-4000-0000-000000000000")
2111-
require.NoError(t, err)
2107+
t.Setenv("WAKATIME_API_KEY", "00000000-0000-4000-0000-000000000000")
21122108

2113-
defer os.Unsetenv("WAKATIME_API_KEY")
2114-
2115-
_, err = cmdparams.LoadAPIParams(context.Background(), v)
2109+
_, err := cmdparams.LoadAPIParams(context.Background(), v)
21162110
require.Error(t, err)
21172111

21182112
var errauth api.ErrAuth
@@ -2125,10 +2119,7 @@ func TestLoadAPIParams_APIKeyFromEnv_ConfigTakesPrecedence(t *testing.T) {
21252119
v := viper.New()
21262120
v.Set("settings.api_key", "00000000-0000-4000-8000-000000000000")
21272121

2128-
err := os.Setenv("WAKATIME_API_KEY", "10000000-0000-4000-8000-000000000000")
2129-
require.NoError(t, err)
2130-
2131-
defer os.Unsetenv("WAKATIME_API_KEY")
2122+
t.Setenv("WAKATIME_API_KEY", "10000000-0000-4000-8000-000000000000")
21322123

21332124
params, err := cmdparams.LoadAPIParams(context.Background(), v)
21342125
require.NoError(t, err)
@@ -2370,10 +2361,7 @@ func TestLoadAPIParams_ProxyURL_UserDefinedTakesPrecedenceOverEnvironment(t *tes
23702361
v.Set("key", "00000000-0000-4000-8000-000000000000")
23712362
v.Set("proxy", "https://john:[email protected]:8888")
23722363

2373-
err := os.Setenv("HTTPS_PROXY", "https://papa:[email protected]:9000")
2374-
require.NoError(t, err)
2375-
2376-
defer os.Unsetenv("HTTPS_PROXY")
2364+
t.Setenv("HTTPS_PROXY", "https://papa:[email protected]:9000")
23772365

23782366
params, err := cmdparams.LoadAPIParams(context.Background(), v)
23792367
require.NoError(t, err)
@@ -2396,10 +2384,7 @@ func TestLoadAPIParams_ProxyURL_FromEnvironment(t *testing.T) {
23962384
v := viper.New()
23972385
v.Set("key", "00000000-0000-4000-8000-000000000000")
23982386

2399-
err := os.Setenv("HTTPS_PROXY", "https://john:[email protected]:8888")
2400-
require.NoError(t, err)
2401-
2402-
defer os.Unsetenv("HTTPS_PROXY")
2387+
t.Setenv("HTTPS_PROXY", "https://john:[email protected]:8888")
24032388

24042389
params, err := cmdparams.LoadAPIParams(context.Background(), v)
24052390
require.NoError(t, err)
@@ -2411,10 +2396,7 @@ func TestLoadAPIParams_ProxyURL_NoProxyFromEnvironment(t *testing.T) {
24112396
v := viper.New()
24122397
v.Set("key", "00000000-0000-4000-8000-000000000000")
24132398

2414-
err := os.Setenv("NO_PROXY", "https://some.org,https://api.wakatime.com")
2415-
require.NoError(t, err)
2416-
2417-
defer os.Unsetenv("NO_PROXY")
2399+
t.Setenv("NO_PROXY", "https://some.org,https://api.wakatime.com")
24182400

24192401
params, err := cmdparams.LoadAPIParams(context.Background(), v)
24202402
require.NoError(t, err)
@@ -2470,10 +2452,7 @@ func TestLoadAPIParams_Hostname_FlagTakesPrecedence(t *testing.T) {
24702452
v.Set("hostname", "my-machine")
24712453
v.Set("settings.hostname", "ignored")
24722454

2473-
err := os.Setenv("GITPOD_WORKSPACE_ID", "gitpod")
2474-
require.NoError(t, err)
2475-
2476-
defer os.Unsetenv("GITPOD_WORKSPACE_ID")
2455+
t.Setenv("GITPOD_WORKSPACE_ID", "gitpod")
24772456

24782457
params, err := cmdparams.LoadAPIParams(context.Background(), v)
24792458
require.NoError(t, err)
@@ -2497,10 +2476,7 @@ func TestLoadAPIParams_Hostname_ConfigTakesPrecedence(t *testing.T) {
24972476
v.Set("key", "00000000-0000-4000-8000-000000000000")
24982477
v.Set("settings.hostname", "my-machine")
24992478

2500-
err := os.Setenv("GITPOD_WORKSPACE_ID", "gitpod")
2501-
require.NoError(t, err)
2502-
2503-
defer os.Unsetenv("GITPOD_WORKSPACE_ID")
2479+
t.Setenv("GITPOD_WORKSPACE_ID", "gitpod")
25042480

25052481
params, err := cmdparams.LoadAPIParams(context.Background(), v)
25062482
require.NoError(t, err)
@@ -2512,10 +2488,7 @@ func TestLoadAPIParams_Hostname_FromGitpodEnv(t *testing.T) {
25122488
v := viper.New()
25132489
v.Set("key", "00000000-0000-4000-8000-000000000000")
25142490

2515-
err := os.Setenv("GITPOD_WORKSPACE_ID", "gitpod")
2516-
require.NoError(t, err)
2517-
2518-
defer os.Unsetenv("GITPOD_WORKSPACE_ID")
2491+
t.Setenv("GITPOD_WORKSPACE_ID", "gitpod")
25192492

25202493
params, err := cmdparams.LoadAPIParams(context.Background(), v)
25212494
require.NoError(t, err)

cmd/run.go

+21-40
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ import (
3838
"github.com/spf13/cobra"
3939
"github.com/spf13/viper"
4040
"go.uber.org/zap/zapcore"
41-
iniv1 "gopkg.in/ini.v1"
4241
"gopkg.in/natefinch/lumberjack.v2"
4342
)
4443

@@ -53,17 +52,10 @@ type diagnostics struct {
5352
func RunE(cmd *cobra.Command, v *viper.Viper) error {
5453
ctx := context.Background()
5554

56-
// force setup logging otherwise log goes to std out
57-
logger, err := SetupLogging(ctx, v)
58-
if err != nil {
59-
// log to std out as logger is not setup yet
60-
stdlog.Fatalf("failed to setup logging: %s", err)
61-
}
62-
63-
// save logger to context
64-
ctx = log.ToContext(ctx, logger)
55+
// extract logger from context despite it's not fully initialized yet
56+
logger := log.Extract(ctx)
6557

66-
err = parseConfigFiles(ctx, v)
58+
err := parseConfigFiles(ctx, v)
6759
if err != nil {
6860
logger.Errorf("failed to parse config files: %s", err)
6961

@@ -74,12 +66,15 @@ func RunE(cmd *cobra.Command, v *viper.Viper) error {
7466
}
7567
}
7668

77-
// setup logging again to use config file settings if available
7869
logger, err = SetupLogging(ctx, v)
7970
if err != nil {
80-
logger.Fatalf("failed to setup logging: %s", err)
71+
// log to std out and exit, as logger instance failed to setup
72+
stdlog.Fatalf("failed to setup logging: %s", err)
8173
}
8274

75+
// save logger to context
76+
ctx = log.ToContext(ctx, logger)
77+
8378
// register all custom lexers
8479
if err := lexer.RegisterAll(); err != nil {
8580
logger.Fatalf("failed to register custom lexers: %s", err)
@@ -183,30 +178,24 @@ func RunE(cmd *cobra.Command, v *viper.Viper) error {
183178
}
184179

185180
func parseConfigFiles(ctx context.Context, v *viper.Viper) error {
181+
logger := log.Extract(ctx)
182+
186183
var configFiles = []struct {
187-
fn func(context.Context, *viper.Viper) (string, error)
188-
vp *viper.Viper
189-
merge bool
184+
filePathFn func(context.Context, *viper.Viper) (string, error)
190185
}{
191186
{
192-
fn: ini.FilePath,
193-
vp: v,
187+
filePathFn: ini.FilePath,
194188
},
195189
{
196-
fn: ini.ImportFilePath,
197-
vp: v,
190+
filePathFn: ini.ImportFilePath,
198191
},
199192
{
200-
fn: ini.InternalFilePath,
201-
vp: viper.NewWithOptions(viper.IniLoadOptions(iniv1.LoadOptions{SkipUnrecognizableLines: true})),
202-
merge: true,
193+
filePathFn: ini.InternalFilePath,
203194
},
204195
}
205196

206-
logger := log.Extract(ctx)
207-
208197
for _, c := range configFiles {
209-
configFile, err := c.fn(ctx, v)
198+
configFile, err := c.filePathFn(ctx, v)
210199
if err != nil {
211200
return fmt.Errorf("error getting config file path: %s", err)
212201
}
@@ -221,16 +210,9 @@ func parseConfigFiles(ctx context.Context, v *viper.Viper) error {
221210
continue
222211
}
223212

224-
if err := ini.ReadInConfig(c.vp, configFile); err != nil {
213+
if err := ini.ReadInConfig(v, configFile); err != nil {
225214
return fmt.Errorf("failed to load configuration file: %s", err)
226215
}
227-
228-
if c.merge {
229-
err = v.MergeConfigMap(c.vp.AllSettings())
230-
if err != nil {
231-
logger.Warnf("failed to merge configuration file: %s", err)
232-
}
233-
}
234216
}
235217

236218
return nil
@@ -251,10 +233,11 @@ func SetupLogging(ctx context.Context, v *viper.Viper) (*log.Logger, error) {
251233
if _, err := os.Stat(dir); os.IsNotExist(err) {
252234
err := os.MkdirAll(dir, 0750)
253235
if err != nil {
254-
return nil, fmt.Errorf("error creating log file directory: %s", err)
236+
return nil, fmt.Errorf("failed to create log file directory %q: %s", dir, err)
255237
}
256238
}
257239

240+
// rotate log files
258241
destOutput = &lumberjack.Logger{
259242
Filename: params.File,
260243
MaxSize: log.MaxLogFileSize,
@@ -269,8 +252,6 @@ func SetupLogging(ctx context.Context, v *viper.Viper) (*log.Logger, error) {
269252
log.WithMetrics(params.Metrics),
270253
)
271254

272-
log.SetJww(params.Verbose, destOutput)
273-
274255
return logger, nil
275256
}
276257

@@ -306,13 +287,13 @@ func runCmd(ctx context.Context, v *viper.Viper, verbose bool, sendDiagsOnErrors
306287

307288
// catch panics
308289
defer func() {
309-
if err := recover(); err != nil {
310-
logger.Errorf("panicked: %v. Stack: %s", err, string(debug.Stack()))
290+
if r := recover(); r != nil {
291+
logger.Errorf("panicked: %v. Stack: %s", r, string(debug.Stack()))
311292

312293
resetLogs()
313294

314295
diags := diagnostics{
315-
OriginalError: err,
296+
OriginalError: r,
316297
Panicked: true,
317298
Stack: string(debug.Stack()),
318299
}

cmd/run_internal_test.go

+25
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,31 @@ func TestParseConfigFiles(t *testing.T) {
417417
v.GetString("internal.backoff_at"))
418418
}
419419

420+
func TestParseConfigFiles_MissingAPIKey(t *testing.T) {
421+
v := viper.New()
422+
v.Set("config", "testdata/.wakatime-empty.cfg")
423+
v.Set("internal-config", "testdata/.wakatime-internal.cfg")
424+
425+
err := parseConfigFiles(context.Background(), v)
426+
427+
assert.NoError(t, err)
428+
}
429+
430+
func TestParseConfigFiles_APIKey_FlagTakesPrecedence(t *testing.T) {
431+
v := viper.New()
432+
v.Set("key", "00000000-0000-4000-8000-000000000000")
433+
v.Set("config", "testdata/.wakatime-empty.cfg")
434+
v.Set("settings.import_cfg", "")
435+
v.Set("internal-config", "testdata/.wakatime-internal.cfg")
436+
437+
err := parseConfigFiles(context.Background(), v)
438+
require.NoError(t, err)
439+
440+
assert.Equal(t,
441+
"00000000-0000-4000-8000-000000000000",
442+
v.GetString("key"))
443+
}
444+
420445
func jsonEscape(t *testing.T, i string) string {
421446
b, err := json.Marshal(i)
422447
require.NoError(t, err)

cmd/testdata/.wakatime-empty.cfg

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[settings]

go.mod

+2-3
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,12 @@ require (
1717
github.com/pkg/sftp v1.13.7
1818
github.com/slongfield/pyfmt v0.0.0-20220222012616-ea85ff4c361f
1919
github.com/spf13/cobra v1.8.1
20-
github.com/spf13/jwalterweatherman v1.1.0
2120
github.com/spf13/viper v1.19.0
2221
github.com/stretchr/testify v1.9.0
2322
go.etcd.io/bbolt v1.3.11
2423
go.uber.org/zap v1.27.0
2524
golang.org/x/crypto v0.31.0
26-
golang.org/x/net v0.32.0
25+
golang.org/x/net v0.33.0
2726
golang.org/x/text v0.21.0
2827
gopkg.in/ini.v1 v1.67.0
2928
gopkg.in/natefinch/lumberjack.v2 v2.2.1
@@ -52,7 +51,7 @@ require (
5251
github.com/sergi/go-diff v1.3.1 // indirect
5352
github.com/sourcegraph/conc v0.3.0 // indirect
5453
github.com/spf13/afero v1.11.0 // indirect
55-
github.com/spf13/cast v1.7.0 // indirect
54+
github.com/spf13/cast v1.7.1 // indirect
5655
github.com/spf13/pflag v1.0.5 // indirect
5756
github.com/subosito/gotenv v1.6.0 // indirect
5857
github.com/yookoala/realpath v1.0.0 // indirect

0 commit comments

Comments
 (0)