Skip to content

Commit

Permalink
Incremental workspaces
Browse files Browse the repository at this point in the history
  • Loading branch information
svenefftinge committed Nov 7, 2022
1 parent ec73a64 commit 327e06f
Show file tree
Hide file tree
Showing 11 changed files with 94 additions and 280 deletions.
12 changes: 1 addition & 11 deletions components/dashboard/src/projects/Project.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -378,17 +378,7 @@ export default function () {
)}
</a>
<span className="flex-grow" />
<a
href={
prebuild
? gitpodHostUrl
.withContext(
`open-prebuild/${prebuild.info.id}/${prebuild.info.changeUrl}`,
)
.toString()
: gitpodHostUrl.withContext(`${branch.url}`).toString()
}
>
<a href={gitpodHostUrl.withContext(`${branch.url}`).toString()}>
<button
className={`primary mr-2 py-2 opacity-0 group-hover:opacity-100`}
>
Expand Down
12 changes: 12 additions & 0 deletions components/dashboard/src/projects/ProjectSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,18 @@ export default function () {
checked={!project.settings?.keepOutdatedPrebuildsRunning}
onChange={({ target }) => updateProjectSettings({ keepOutdatedPrebuildsRunning: !target.checked })}
/>
<h3 className="mt-12">Workspace Starts</h3>
<CheckBox
title={<span>Incrementally update from old prebuilds</span>}
desc={
<span>
Whether new workspaces can be started based on prebuilds that ran on older Git commits and get
incrementally updated.
</span>
}
checked={!!project.settings?.allowUsingPreviousPrebuilds}
onChange={({ target }) => updateProjectSettings({ allowUsingPreviousPrebuilds: target.checked })}
/>
{showPersistentVolumeClaimUI && (
<>
<br></br>
Expand Down
99 changes: 10 additions & 89 deletions components/dashboard/src/start/CreateWorkspace.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,7 @@
*/

import React, { useEffect, useContext, useState } from "react";
import {
CreateWorkspaceMode,
WorkspaceCreationResult,
RunningWorkspacePrebuildStarting,
ContextURL,
DisposableCollection,
Team,
} from "@gitpod/gitpod-protocol";
import { WorkspaceCreationResult, ContextURL, Team, GitpodServer } from "@gitpod/gitpod-protocol";
import { ErrorCodes } from "@gitpod/gitpod-protocol/lib/messaging/error";
import Modal from "../components/Modal";
import { getGitpodService, gitpodHostUrl } from "../service/service";
Expand All @@ -22,14 +15,12 @@ import StartWorkspace, { parseProps } from "./StartWorkspace";
import { openAuthorizeWindow } from "../provider-utils";
import { SelectAccountPayload } from "@gitpod/gitpod-protocol/lib/auth";
import { SelectAccountModal } from "../settings/SelectAccountModal";
import PrebuildLogs from "../components/PrebuildLogs";
import FeedbackComponent from "../feedback-form/FeedbackComponent";
import { isGitpodIo } from "../utils";
import { BillingAccountSelector } from "../components/BillingAccountSelector";
import { AttributionId } from "@gitpod/gitpod-protocol/lib/attribution";
import { TeamsContext } from "../teams/teams-context";
import Alert from "../components/Alert";
import { FeatureFlagContext } from "../contexts/FeatureFlagContext";

export interface CreateWorkspaceProps {
contextUrl: string;
Expand All @@ -48,22 +39,22 @@ export default class CreateWorkspace extends React.Component<CreateWorkspaceProp
this.state = { stillParsing: true };
}

static contextType = UserContext;

componentDidMount() {
this.createWorkspace();
}

async createWorkspace(mode = CreateWorkspaceMode.SelectIfRunning, forceDefaultConfig = false) {
async createWorkspace(opts?: Omit<GitpodServer.CreateWorkspaceOptions, "contextUrl">) {
// Invalidate any previous result.
this.setState({ result: undefined, stillParsing: true });

// We assume anything longer than 3 seconds is no longer just parsing the context URL (i.e. it's now creating a workspace).
let timeout = setTimeout(() => this.setState({ stillParsing: false }), 3000);

try {
const result = await getGitpodService().server.createWorkspace({
contextUrl: this.props.contextUrl,
mode,
forceDefaultConfig,
ignoreRunningWorkspaceOnSameCommit: false,
...opts,
});
if (result.workspaceURL) {
window.location.href = result.workspaceURL;
Expand Down Expand Up @@ -148,7 +139,7 @@ export default class CreateWorkspace extends React.Component<CreateWorkspaceProp
<button
className=""
onClick={() => {
this.createWorkspace(CreateWorkspaceMode.Default, true);
this.createWorkspace({ forceDefaultConfig: true });
}}
>
Continue with default configuration
Expand Down Expand Up @@ -262,21 +253,12 @@ export default class CreateWorkspace extends React.Component<CreateWorkspaceProp
</>
</div>
<div className="flex justify-end mt-6">
<button onClick={() => this.createWorkspace(CreateWorkspaceMode.Default)}>New Workspace</button>
<button onClick={() => this.createWorkspace({ ignoreRunningWorkspaceOnSameCommit: true })}>
New Workspace
</button>
</div>
</Modal>
);
} else if (result?.runningWorkspacePrebuild) {
return (
<RunningPrebuildView
runningPrebuild={result.runningWorkspacePrebuild}
onUseLastSuccessfulPrebuild={() =>
this.createWorkspace(CreateWorkspaceMode.UseLastSuccessfulPrebuild)
}
onIgnorePrebuild={() => this.createWorkspace(CreateWorkspaceMode.ForceNew)}
onPrebuildSucceeded={() => this.createWorkspace(CreateWorkspaceMode.UsePrebuild)}
/>
);
}

return (
Expand Down Expand Up @@ -526,64 +508,3 @@ function RepositoryNotFoundView(p: { error: StartWorkspaceError }) {
</StartPage>
);
}

interface RunningPrebuildViewProps {
runningPrebuild: {
prebuildID: string;
workspaceID: string;
instanceID: string;
starting: RunningWorkspacePrebuildStarting;
sameCluster: boolean;
};
onUseLastSuccessfulPrebuild: () => void;
onIgnorePrebuild: () => void;
onPrebuildSucceeded: () => void;
}

function RunningPrebuildView(props: RunningPrebuildViewProps) {
const workspaceId = props.runningPrebuild.workspaceID;
const { showUseLastSuccessfulPrebuild } = useContext(FeatureFlagContext);

useEffect(() => {
const disposables = new DisposableCollection();

disposables.push(
getGitpodService().registerClient({
onInstanceUpdate: (update) => {
if (update.workspaceId !== workspaceId) {
return;
}
if (update.status.phase === "stopped") {
props.onPrebuildSucceeded();
}
},
}),
);

return function cleanup() {
disposables.dispose();
};
// eslint-disable-next-line
}, [workspaceId]);

return (
<StartPage title="Prebuild in Progress">
{/* TODO(gpl) Copied around in Start-/CreateWorkspace. This should properly go somewhere central. */}
<div className="h-full mt-6 w-11/12 lg:w-3/5">
<PrebuildLogs workspaceId={workspaceId} onIgnorePrebuild={props.onIgnorePrebuild}>
{showUseLastSuccessfulPrebuild && (
<button
className="secondary"
onClick={() => props.onUseLastSuccessfulPrebuild && props.onUseLastSuccessfulPrebuild()}
>
Use Last Successful Prebuild
</button>
)}
<button className="secondary" onClick={() => props.onIgnorePrebuild && props.onIgnorePrebuild()}>
Skip Prebuild
</button>
</PrebuildLogs>
</div>
</StartPage>
);
}
4 changes: 2 additions & 2 deletions components/gitpod-protocol/src/gitpod-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import {
WhitelistedRepository,
WorkspaceImageBuild,
AuthProviderInfo,
CreateWorkspaceMode,
Token,
UserEnvVarValue,
Terms,
Expand Down Expand Up @@ -422,7 +421,8 @@ export namespace GitpodServer {
}
export interface CreateWorkspaceOptions {
contextUrl: string;
mode?: CreateWorkspaceMode;
// whether running workspaces on the same context should be ignored. If false (default) users will be asked.
ignoreRunningWorkspaceOnSameCommit?: boolean;
forceDefaultConfig?: boolean;
}
export interface StartWorkspaceOptions {
Expand Down
8 changes: 0 additions & 8 deletions components/gitpod-protocol/src/protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1370,14 +1370,6 @@ export interface WorkspaceCreationResult {
createdWorkspaceId?: string;
workspaceURL?: string;
existingWorkspaces?: WorkspaceInfo[];
runningWorkspacePrebuild?: {
prebuildID: string;
workspaceID: string;
instanceID: string;
starting: RunningWorkspacePrebuildStarting;
sameCluster: boolean;
};
runningPrebuildWorkspaceID?: string;
}
export type RunningWorkspacePrebuildStarting = "queued" | "starting" | "running";

Expand Down
2 changes: 2 additions & 0 deletions components/gitpod-protocol/src/teams-projects-protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ export interface ProjectSettings {
useIncrementalPrebuilds?: boolean;
usePersistentVolumeClaim?: boolean;
keepOutdatedPrebuildsRunning?: boolean;
// whether new workspaces can start on older prebuilds and incrementally update
allowUsingPreviousPrebuilds?: boolean;
}

export interface Project {
Expand Down
1 change: 1 addition & 0 deletions components/server/ee/src/prebuilds/prebuild-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ export class PrebuildManager {
const workspace = await this.workspaceFactory.createForContext(
{ span },
user,
project,
prebuildContext,
context.normalizedContextURL!,
);
Expand Down
Loading

0 comments on commit 327e06f

Please sign in to comment.