Skip to content
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

campaigns: skip changeset spec creation for cached empty diffs #397

Merged
merged 3 commits into from
Nov 25, 2020

Conversation

LawnGnome
Copy link
Contributor

It's totally valid and normal for empty diffs to be created when
executing campaign specs: sometimes you just don't want anything to
change, even though the repo matched the initial query. When this
happens, #313 added a check that prevents the changeset spec from being
created, and print a verbose mode message indicating that the repo was
skipped:

https://sourcegraph.com/github.com/sourcegraph/src-cli@d29ad54eff678d96fb7ebdf75ff95890dce6a1cf/-/blob/internal/campaigns/executor.go?utm_source=VSCode-1.1.0#L273-278

So far, so good. In #374, we made our empty diff handling even better by
caching the empty diff: this means that we don't have to recalculate
that nothing happened. Unfortunately, the check that exists in the cache
miss code path to skip changeset spec creation doesn't exist in the
cache hit code path, which means that on subsequent applications of the
campaign, a changeset spec with an empty diff will be uploaded, and
gitserver will ultimately be very grumpy.

By applying the same logic to the cache hit code path, we can filter out
these problematic changeset specs.

It's totally valid and normal for empty diffs to be created when
executing campaign specs: sometimes you just don't want anything to
change, even though the repo matched the initial query. When this
happens, #313 added a check that prevents the changeset spec from being
created, and print a verbose mode message indicating that the repo was
skipped:

https://sourcegraph.com/github.com/sourcegraph/src-cli@d29ad54eff678d96fb7ebdf75ff95890dce6a1cf/-/blob/internal/campaigns/executor.go?utm_source=VSCode-1.1.0#L273-278

So far, so good. In #374, we made our empty diff handling even better by
caching the empty diff: this means that we don't have to recalculate
that nothing happened. Unfortunately, the check that exists in the cache
miss code path to skip changeset spec creation doesn't exist in the
cache hit code path, which means that on subsequent applications of the
campaign, a changeset spec with an empty diff will be uploaded, and
gitserver will ultimately be very grumpy.

By applying the same logic to the cache hit code path, we can filter out
these problematic changeset specs.
@LawnGnome LawnGnome requested a review from a team November 25, 2020 21:49
Copy link
Member

@eseliger eseliger left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. LGTM!

// send to the server. Instead, we can just report that the task is
// complete and move on.
if len(diff) == 0 {
status.FinishedAt = time.Now()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this line could also be moved up and deduped

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought about it, but kept it there because createChangesetSpec() really marks the end of executing the task in the normal case, and I'd like to account for that time as well.

This also means that we run all the integration tests with cold and warm
caches, which should help pick up these issues in future.
@LawnGnome LawnGnome requested a review from eseliger November 25, 2020 23:25
@LawnGnome
Copy link
Contributor Author

Just asking for a quick re-review here to glance over the test changes, since they're moderately significant.

Copy link
Member

@eseliger eseliger left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work, I like that. Just a question re the test preventing this from happening again.

Comment on lines +133 to +134
// No changesets should be generated.
wantFilesChanged: map[string][]string{},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't 100% understand how this tests the behavior is right but I trust you that it does what we look for. Regardless this is a good test.
I assume this would have failed before the fix because the hot run is going to yield a change? Even though it was empty? Not sure why it would show any files changed when there was an empty diff.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Each entry in wantFilesChanged represents a changeset spec. In this case, since true won't change anything, the test should hit the empty diff code paths and not generate changeset specs, even though the cache is populated.

This does indeed fail on the old main:


~/trees/sourcegraph/src-cli on  main via 🐹 v1.15.5 ❯ go test -race ./...
ok  	github.com/sourcegraph/src-cli/cmd/src	0.224s
ok  	github.com/sourcegraph/src-cli/internal/api	(cached)
--- FAIL: TestExecutor_Integration (0.46s)
    --- FAIL: TestExecutor_Integration/empty (0.04s)
        executor_test.go:189: wrong number of changeset specs. want=0, have=1
        --- FAIL: TestExecutor_Integration/empty/warm_cache (0.00s)
            testing.go:1048: test executed panic(nil) or runtime.Goexit: subtest may have called FailNow on a parent test
FAIL
FAIL	github.com/sourcegraph/src-cli/internal/campaigns	0.565s
?   	github.com/sourcegraph/src-cli/internal/campaigns/graphql	[no test files]
ok  	github.com/sourcegraph/src-cli/internal/codeintel	(cached)
?   	github.com/sourcegraph/src-cli/internal/output	[no test files]
ok  	github.com/sourcegraph/src-cli/internal/servegit	(cached)
?   	github.com/sourcegraph/src-cli/schema	[no test files]
FAIL

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh okay makes sense. Thanks for confirming!

@LawnGnome LawnGnome merged commit ff776f6 into main Nov 25, 2020
@LawnGnome LawnGnome deleted the aharvey/skip-cached-empty-changesets branch November 25, 2020 23:39
LawnGnome added a commit to sourcegraph/sourcegraph-public-snapshot that referenced this pull request Nov 26, 2020
The previous recommended version suffered from the bug fixed by
sourcegraph/src-cli#397, so we'll want to move our users past that.
@mrnugget
Copy link
Contributor

Ah man, what a bug! Thanks for fixing this so diligently!

scjohns pushed a commit that referenced this pull request Apr 24, 2023
* campaigns: skip changeset spec creation for cached empty diffs

It's totally valid and normal for empty diffs to be created when
executing campaign specs: sometimes you just don't want anything to
change, even though the repo matched the initial query. When this
happens, #313 added a check that prevents the changeset spec from being
created, and print a verbose mode message indicating that the repo was
skipped:

https://sourcegraph.com/github.com/sourcegraph/src-cli@d29ad54eff678d96fb7ebdf75ff95890dce6a1cf/-/blob/internal/campaigns/executor.go?utm_source=VSCode-1.1.0#L273-278

So far, so good. In #374, we made our empty diff handling even better by
caching the empty diff: this means that we don't have to recalculate
that nothing happened. Unfortunately, the check that exists in the cache
miss code path to skip changeset spec creation doesn't exist in the
cache hit code path, which means that on subsequent applications of the
campaign, a changeset spec with an empty diff will be uploaded, and
gitserver will ultimately be very grumpy.

By applying the same logic to the cache hit code path, we can filter out
these problematic changeset specs.

* Extend integration tests to cover the empty diff bug.

This also means that we run all the integration tests with cold and warm
caches, which should help pick up these issues in future.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants