Skip to content

[server] abort running prebuilds on same branch #10962

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

Merged
merged 1 commit into from
Jun 30, 2022
Merged

Conversation

svenefftinge
Copy link
Member

@svenefftinge svenefftinge commented Jun 28, 2022

Description

Cancels all running and queued prebuilds for the same branch when a new commit is pushed.
Adds a project setting to opt-out of this behavior.

Screenshot 2022-06-28 at 12 54 36

Related Issue(s)

Fixes #6569

How to test

  • Add a project with a long prebuild task
  • push multipüle times to the same branch
  • see how the previous prebuilds get cancelled.
  • push to a different branch and verify that running prebuilds on the other branch are not getting cancelled.
  • disable the project setting and verify that the cancellation doesn't happen

Release Notes

Outdated prebuilds (i.e. new commits are pushed on a branch) are automatically canceled. This behavior can be disabled in the project's settings.

Documentation

Werft options:

  • /werft with-preview

@werft-gitpod-dev-com
Copy link

started the job as gitpod-build-se-playground.11 because the annotations in the pull request description changed
(with .werft/ from main)

@svenefftinge svenefftinge force-pushed the se/playground branch 3 times, most recently from 3a680c4 to 9aaa1f6 Compare June 28, 2022 10:36
@svenefftinge svenefftinge marked this pull request as ready for review June 28, 2022 10:53
@svenefftinge svenefftinge requested a review from a team June 28, 2022 10:53
@github-actions github-actions bot added the team: webapp Issue belongs to the WebApp team label Jun 28, 2022
@jankeromnes jankeromnes self-assigned this Jun 29, 2022
@jankeromnes
Copy link
Contributor

jankeromnes commented Jun 29, 2022

Many thanks @svenefftinge for continuously improving & optimizing which prebuilds we should be running or not! 💯

I'll give this Pull Request a look. 👀

@@ -56,19 +55,14 @@ export default function () {
const { teams } = useContext(TeamsContext);
const team = getCurrentTeam(location, teams);

const [isLoading, setIsLoading] = useState<boolean>(true);
Copy link
Contributor

Choose a reason for hiding this comment

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

❤️ Many thanks for removing a isLoading boolean! (which I might have added 🙈)

I agree that maintaining a isLoading boolean is generally bad practice, and creates many opportunities for bugs. (And when a loading state is required, it's always better to explicit wait on what still needs to be loaded, instead of trying to code this into a isLoading boolean.) 👍

Copy link
Contributor

@jankeromnes jankeromnes left a comment

Choose a reason for hiding this comment

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

Thanks again! Had an initial pass through the code, and it looks good to me, modulo a few (mostly optional) questions.

Will now give the PR a go, and try to find some edge cases (e.g. image builds?)

onChange={toggleIncrementalPrebuilds}
/>
<CheckBox
title={<span>Cancel Prebuilds on Outdated Commits </span>}
desc={<span>Cancels all pending and running prebuilds on the branch when a new commit is pushed.</span>}
Copy link
Contributor

Choose a reason for hiding this comment

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

In general, I think that this feature is super valuable and needed, and I'm happy that we're taking a first step towards it. 💯

Without having read the code much further or tested it, one initial thought that occurs is that, if one of your branches (e.g. main) takes a long time to build, and sees very frequent commits (e.g. during working hours), we might be always-cancelling running prebuilds without ever finishing one, for long stretches of time (e.g. maybe we only successfully finish running a prebuild over lunch break or at the end of the day).

const results: Promise<any>[] = [];
for (const prebuild of prebuilds) {
for (const instance of prebuild.instances) {
results.push(this.workspaceStarter.stopWorkspaceInstance({ span }, instance.id, instance.region));
Copy link
Contributor

Choose a reason for hiding this comment

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

I wonder what happens for instances which are not in a "stoppable" state, e.g. in image build? Will this fail for some not-yet-stoppable instances, or will this wait until it reaches a stoppable state? (I'm guessing the former.)

Copy link
Member Author

Choose a reason for hiding this comment

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

I don't know either but we should really move the responsibility to the ws-manager.

req.setId(instanceId);
req.setPolicy(policy || StopWorkspacePolicy.NORMALLY);

const client = await this.clientProvider.get(instanceRegion);
Copy link
Contributor

Choose a reason for hiding this comment

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

If I remember correctly, some instances might not have a region yet (e.g. still in image build or so?) and this could cause client to be incorrect or undefined. Is this still the case? 🤔 I guess this needs to be tested.

@jankeromnes
Copy link
Contributor

Err, will actually test this PR later today (in ~1.5 hours) as I have upcoming meetings. Please feel free to push any changes if you want to (i.e. no need to necessarily keep the preview env alive until then).

@geropl
Copy link
Member

geropl commented Jun 29, 2022

@svenefftinge Do you have any plans on announcing this change? This will certainly affect some heavy Gitpod users. 🤔

@svenefftinge
Copy link
Member Author

svenefftinge commented Jun 29, 2022

This will certainly affect some heavy Gitpod users. 🤔

How do you think it will affect users? In a negative way you mean?

@svenefftinge
Copy link
Member Author

svenefftinge commented Jun 29, 2022

The only path I can imagine where users might be surprised is seeing prebuilds "CANCELED". We should probably tell them why.
I'm adding the status descriptions as a tooltip for the items in the list and also add the information about new commits being pushed on the branch:
Screenshot 2022-06-29 at 15 40 26

@jankeromnes
Copy link
Contributor

jankeromnes commented Jun 29, 2022

I'm adding the status descriptions as a tooltip for the items in the list and also add the information about new commits being pushed on the branch:

Good idea! 👍 I wonder if it also makes sense to tell users that they can click on the prebuild in order to know the exact cancellation reason. (It should always be visible in the full error message below the prebuild logs.)

@svenefftinge
Copy link
Member Author

svenefftinge commented Jun 29, 2022

Good idea! 👍 I wonder if it also makes sense to tell users that they can click on the prebuild in order to know the exact cancellation reason. (It should always be visible in the full error message below the prebuild logs.)

It is the same message

@gtsiolis
Copy link
Contributor

FWIW, auto-cancelling redundant builds is a common practice in CI systems[1][2][...].

In the future, we could introduce a preference option in project settings but going with a sensible default[3] sounds better.

@svenefftinge
Copy link
Member Author

svenefftinge commented Jun 29, 2022

In the future, we could introduce a preference option in project settings but going with a sensible default[3] sounds better.

This PR already comes with that preference (default is ☑️ ):
Screenshot 2022-06-29 at 16 36 43

Copy link
Contributor

@gtsiolis gtsiolis left a comment

Choose a reason for hiding this comment

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

This PR already comes with that preference (default is ☑️ )

Perfect (Perfect)! ✨

Left one comment for updating the copy used in settings. Feel free to ignore or adjust the suggestion. 🏓

onChange={toggleIncrementalPrebuilds}
/>
<CheckBox
title={<span>Cancel Prebuilds on Outdated Commits </span>}
desc={<span>Cancels all pending and running prebuilds on the branch when a new commit is pushed.</span>}
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
desc={<span>Cancels all pending and running prebuilds on the branch when a new commit is pushed.</span>}
desc={<span>New prebuilds cancel older pending or running prebuilds on the same branch when new commits are pushed.</span>}

for (const instance of prebuild.instances) {
results.push(this.workspaceStarter.stopWorkspaceInstance({ span }, instance.id, instance.region));
}
prebuild.prebuild.state = "aborted";
Copy link
Contributor

@jankeromnes jankeromnes Jun 29, 2022

Choose a reason for hiding this comment

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

Please also specify the cancellation reason by setting a helpful prebuild.error value, similar to the rate-limit error:

Suggested change
prebuild.prebuild.state = "aborted";
prebuild.prebuild.state = "aborted";
prebuild.error = "A newer commit was pushed to the same branch.";
await this.workspaceDB.trace({ span }).storePrebuiltWorkspace(prebuild);

Copy link
Contributor

@jankeromnes jankeromnes left a comment

Choose a reason for hiding this comment

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

Many thanks! In addition to the code looking good to me earlier, I've tested this PR and it works as advertised. ✨ 🎯

For what it's worth, I also tested the behavior with image builds (by pushing a custom Dockerile and then several commits on top) -- the Prebuilds actually get cancelled, even though the logs continue to receive new updates. 😅 I guess that's fine. 👍

Screenshot 2022-06-29 at 19 12 24

Adding a hold because I'd love the cancellation reason to be explicitly added as a prebuild.error, or in case someone else would like to review.

/hold

@roboquat roboquat merged commit ba78bd4 into main Jun 30, 2022
@roboquat roboquat deleted the se/playground branch June 30, 2022 06:10
@svenefftinge
Copy link
Member Author

I'd love the cancellation reason to be explicitly added as a prebuild.error,

Will do in a follow up PR.

@roboquat roboquat added deployed: webapp Meta team change is running in production deployed Change is completely running in production labels Jun 30, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
deployed: webapp Meta team change is running in production deployed Change is completely running in production release-note size/L team: webapp Issue belongs to the WebApp team
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Pushing new commits to a branch, does not stop a prebuild from a previous commit of the same branch.
5 participants