-
Notifications
You must be signed in to change notification settings - Fork 598
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
chore: ensure syft binary is up-to-date when running CLI tests locally #2016
Conversation
Signed-off-by: Keith Zantow <[email protected]>
test/cli/utils_test.go
Outdated
bin := getSyftBinaryLocationByOS(t, runtime.GOOS) | ||
|
||
// only run on valid bin target, when not running in CI | ||
if bin != "" && os.Getenv("CI") == "" { |
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 unsure the best way to determine if this is being run locally. It would also be fine (for me, at least) if this only runs when running a single test.
This also could be moved to getSyftBinaryLocationByOS
so the linux build also works (and we'd have to do something slightly different to ensure each architecture/platform gets built only once); this draft PR is a prototype.
test/cli/utils_test.go
Outdated
|
||
var stdout, stderr string | ||
var err error | ||
switch "go" { |
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.
Change this to try the different variants.
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 like the idea of by default having the goreleaser approach done since it would be most consistent with how we're going to release. That being said, I also like that this is swappable strategy... we could simply leave this here and wire it up to an environment variable so the dev could choose between go and goreleaser (should probably removed the make approach though).
test/cli/utils_test.go
Outdated
d := yaml.NewDecoder(strings.NewReader(goreleaserYamlContents(dir))) | ||
type releaser struct { | ||
Builds []struct { | ||
ID string `yaml:"id"` | ||
LDFlags string `yaml:"ldflags"` | ||
} `yaml:"builds"` | ||
} | ||
r := releaser{} | ||
_ = d.Decode(&r) | ||
ldflags := "" | ||
for _, b := range r.Builds { | ||
if b.ID == "linux-build" { | ||
ldflags = executeTemplate(b.LDFlags, struct { | ||
Version string | ||
Commit string | ||
Date string | ||
Summary string | ||
}{ | ||
Version: "VERSION", | ||
Commit: "COMMIT", | ||
Date: "DATE", | ||
Summary: "SUMMARY", | ||
}) | ||
break | ||
} | ||
} |
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 just just for using the same ldflags
the goreleaser build uses.
Benchmark Test ResultsBenchmark results from the latest changes vs base branch
|
took := time.Now().Sub(start).Round(time.Millisecond) | ||
if err == nil { | ||
if len(stderr) == 0 { | ||
t.Logf("binary is up to date: %s in %v", outfile, took) |
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.
Note this is not entirely accurate. This is reported if there are no code changes and the build cache hasn't changed, but the binary is rebuilt anyway.
test/cli/utils_test.go
Outdated
goreleaserYaml := goreleaserYamlContents(dir) | ||
|
||
// # create a config with the dist dir overridden | ||
tmpGoreleaserYamlFile := path.Join(tmpDir, "goreleaser.yaml") | ||
_ = os.WriteFile(tmpGoreleaserYamlFile, []byte("dist: snapshot\n"+goreleaserYaml), os.ModePerm) |
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.
Emulating what happens in the Makefile
Signed-off-by: Keith Zantow <[email protected]>
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.
my vote is to get this change in, though should probably drop the make
approach entirely and default to either go or goreleaser and have the strategy be accessible via environment variable and document it in the DEVELOPING.md.
Signed-off-by: Keith Zantow <[email protected]>
Signed-off-by: Keith Zantow <[email protected]>
Signed-off-by: Keith Zantow <[email protected]>
Signed-off-by: Keith Zantow <[email protected]>
Signed-off-by: Keith Zantow <[email protected]>
Signed-off-by: Keith Zantow <[email protected]>
Signed-off-by: Keith Zantow <[email protected]>
Superseded by #2998 |
While attempting to debug a CLI test locally, I got dramatically different results, which took debugging to realize that these tests use syft binaries built with
make snapshot
. However, it is confusing when this happens and not especially convenient to runmake snapshot
each time a code change is made before running each tests. Additionally,make snapshot
is not especially fast: ~17s on my local machine, so the dev-test cycle is a bit painful.I implemented something that can build the syft binary fairly quickly (in the 2-4s range, depending on the amount changed from the last build) and also much more quickly if there are no changes -- in the < 1sec range. However, this is using the
go build
command directly, which is a bit less than ideal -- since we're usinggoreleaser
, it would be nice to have this consistent.It should be noted: in all cases, this runs once for each test run, whether it's a single test or the entire CLI test suite.
So I implemented a few different options for this and ran them under different scenarios (I've included build times with an up-to-date go build cache):
Build using go directly
This populates the goreleaser build flags with [hopefully] obvious placeholder values.
Version output:
Build using goreleaser directly
Version output:
Build using
make snapshot
Version output is the same as building with goreleaser directly.
Summary:
make snapshot
builds all binaries every time it's run. The 17-ish second turnaround would be painful to sit through when running an individual test with a dev-test cycle.Building with
goreleaser
needs--clean
, to remove the prior build artifact, so it rebuilds each time. ~4 seconds overhead for each dev-test cycle is a little painful, still, but not the worst.Building with
go
directly is fast with no changes, but each change could result in each run adding approximately 4s if changing files between runs. However, testing this with a small change can still be in the <1s range:Finally: since both
go
andgoreleaser
variants only build a single binary that matches the current platform and architecture, they do not build the linux variant with any of these changes. This means the one test that runs syft on docker fails:TestDirectoryScanCompletesWithinTimeout
. Themake snapshot
does not have this problem, since it's building all platform/architectures.