-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix color handling, generate the summary with JS, improve CI #1975
Conversation
Codecov Report
@@ Coverage Diff @@
## master #1975 +/- ##
==========================================
- Coverage 71.92% 71.72% -0.21%
==========================================
Files 182 179 -3
Lines 14291 14085 -206
==========================================
- Hits 10279 10102 -177
+ Misses 3368 3346 -22
+ Partials 644 637 -7
Flags with carried forward coverage won't be shown. Click here to find out more.
Continue to review full report at Codecov.
|
2c61abd
to
ab62876
Compare
45cdd2e
to
3ff9787
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems fine on first read, but we need to test this a lot ... especially on windows
ui.Dump(stdout, status) | ||
return nil | ||
|
||
return yamlPrint(stdout, status) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe this is a good case for wrapping errors as "could not marshal YAML:" will be quite strange error for someone calling k6 pause
or co.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, though to be fair, the new state isn't any worse than the previous behavior where it would have printed just the raw YAML marshaling error, without even the could not marshal YAML:
in front of it 😅 but yeah, I may wrap these errors locally as well...
I converted this back to draft because I want to make a few more changes, prompted by grafana/jslib.k6.io#32 First, I think I should rename the Also, |
cef7172
to
0aad6a6
Compare
If the environment contains TERM=dumb, we don't consider them to be a TTY. This is in line with what the github.com/fatih/color library checks: https://github.com/fatih/color/blob/v1.10.0/color.go#L20-L21
0aad6a6
to
25cd528
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, I had a couple of nitpicks, but if it works .... I am fine with merging it and my 5 minutes of testing didn't show any problems so 👍
@@ -330,7 +333,8 @@ This will execute the test on the k6 cloud service. Use "k6 login cloud" to auth | |||
return ExitCode{error: errors.New("Test progress error"), Code: cloudFailedToGetProgressErrorCode} | |||
} | |||
|
|||
fprintf(stdout, " test status: %s\n", ui.ValueColor.Sprint(testProgress.RunStatusText)) | |||
valueColor := getColor(noColor || !stdoutTTY, color.FgCyan) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given how now you repeat color.FgCyan
a lot I would argue it should probably be a constant somewhere ... probably named valueColorColor
:P
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's already a constant 😛 It's used in like 5 places across 2 modules, and not always for values (e.g. the banner), so I don't want to define a constant for that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No blockers from me, just minor suggestions. I would've preferred to review separate PRs for the color fixes and JS summary changes, but the commits are isolated, so it wasn't a big issue.
I think we're missing some integration tests to ensure color is handled correctly, but it could be added later. Though it worked fine in my manual tests. It's kind of wild we're generating the summary entirely in JS now 😄 🎉
And kudos for dropping all those Go dependencies! 👍
// getColor() returns the requested color, or an uncolored object, depending on | ||
// the value of noColor. The explicit EnableColor() and DisableColor() are | ||
// needed because the library checks os.Stdout itself otherwise... | ||
func getColor(noColor bool, attributes ...color.Attribute) *color.Color { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you add high-level (integration?) tests for this, to check the new behavior, using TERM=dumb
, etc.?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I meant high-level as in user acceptance tests, similar to the xk6 ones we have now, running k6
itself in a shell, checking the output, etc.
But that requires coming up with the framework and CI pipeline, so it's fine if we do it later as part of #342.
) | ||
|
||
// TODO: move this to a separate JS file and use go.rice to embed it | ||
const summaryWrapperLambdaCode = ` | ||
// Copied from https://github.com/k6io/jslib.k6.io/tree/master/lib/k6-summary |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This means we can deprecate the jslib, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No? jslib has a ton of other libraries. Besides, having textSummary()
in there is very helpful for users that want to define their own handleSummary()
function, e.g. to emit a json or a junit file, but they also want to continue getting the text summary at the end of the test. They can just import { textSummary } from 'https://jslib.k6.io/lib/k6-summary/0.0.1/index.js'
and use that in handleSummary()
's result.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't mean deprecating jslib.k6.io altogether 😄, just this lib.
I wasn't aware there were differences between the version committed here and the one on jslib. Though since we already bundle it in the binary, couldn't we expose it as a built-in JS module and avoid the remote loading? 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There aren't any differences, except we don't bundle the JUnit code (we'll probably split it apart in jslib as well soon). And we can potentially expose it as a JS module, if we figure out a nice module name, but that will be a separate issue/PR
We still use the noColor and stdoutTTY global variables, but we explicitly pass them as function arguments, so it's clear which parts of the code depend on them when we eventually fully refactor them into locals.
The affected commands are k6 pause, resume, scale, stats and status. This allows us to remove the github.com/zyedidia/highlight dependency and significantly simplify the color management mess.
Due to incomplete test setup, there were differences between the expected text and JSON results of the end-of-test summary handling...
This is necessary so that any handleSummary() callback, including the default one, would know if it can use colors (or other special terminal features) or not.
This is needed because we want to use the file embedding API.
This allows us to drop the github.com/dustin/go-humanize and also the explicit nature of the golang.org/x/text dependency.
This should no longer be needed, since we hopefully don't have any more rogue color generators that don't respect stdoutTTY/stderrTTY and noColor. The next step would be making these variables local and passing them through the cmd logic as arguments, not reading their values directly out of the global scope.
25cd528
to
c7e8a7b
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, just a couple of minor notes.
@@ -344,7 +345,8 @@ func (r *Runner) HandleSummary(ctx context.Context, summary *lib.Summary) (map[s | |||
}() | |||
*vu.Context = ctx | |||
|
|||
handleSummaryWrapperRaw, err := vu.Runtime.RunString(summaryWrapperLambdaCode) | |||
wrapper := strings.Replace(summaryWrapperLambdaCode, "/*JSLIB_SUMMARY_CODE*/", jslibSummaryCode, 1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm probably missing it, but what's the reason for having a wrapper and doing this replace? Since both summaryWrapperLambdaCode
and jslibSummaryCode
are static, couldn't we just bundle a single JS file?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We probably could, but this insulates us from future changes in the jslib summary code, and it also keeps the scope a bit cleaner 🤷♂️
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, sorry, misread your question. I don't want to bundle a single JS file since I want it to be easy to update the summary.js
when the one in jslib is updated
@@ -29,120 +29,6 @@ import ( | |||
"github.com/stretchr/testify/assert" | |||
) | |||
|
|||
func TestMetricHumanizeValue(t *testing.T) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These were very important tests IMO that we lose in the conversion to JS. We should probably add some for the JS implementation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I replicated (and IIRC even expanded a bit) these tests in https://github.com/k6io/jslib.k6.io/blob/master/tests/summary.js when I was writing the JS summary generation code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, neat, I forgot about those. I suppose it's fine then, though running them as part of the k6 tests would give us more confidence, as they're run more frequently and use the latest k6 version. But this goes back to the point of eventually deprecating the jslib version, which we can consider later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In k6 we have somewhat higher-level tests in https://github.com/k6io/k6/blob/master/js/summary_test.go - they are like integration tests for the JS summary code, so I'd rather expand those than to write more low-level ones.
Read commit by commit. This should be merged after we release k6 v0.32.0, I'm just polishing it and pushing it, so it's easy to merge after the release.
This PR should fix #1806 and close #1805, as well as make several other minor improvements, mostly about various dependencies (#1933).
It also introduces a minor breaking change, though I'm not sure if it's even worth noting in the release notes... k6 will no longer highlight the output of several sub-commands:
pause
,resume
,scale
,stats
, andstatus
.Finally, because I wanted to use the new file embedding capabilities in Go 1.16, I bumped the minimum required version to that. I switched the xk6 tests to run with the latest stable Go version and the tip. For the main test suite, I temporarily disabled the 1.15 tests, but also added testing with the tip (which is non-blocking, so it won't prevent a PR merge or a release). This shouldn't be a problem, since we will only release this in k6 v0.33.0, ~2.5 months from now. But it gave me the opportunity to also drop the go.rice dependency 🎉