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

Add push experiment(s) to the command palette #3793

Merged
merged 1 commit into from
May 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,11 @@
"light": "resources/light/queue-experiment.svg"
}
},
{
"title": "Push Experiment(s)",
"command": "dvc.pushExperiments",
"category": "DVC"
},
{
"title": "Remove Experiment(s)",
"command": "dvc.removeExperiments",
Expand Down Expand Up @@ -761,6 +766,10 @@
"command": "dvc.modifyExperimentParamsResetAndRun",
"when": "dvc.commands.available && dvc.project.available && !dvc.experiment.running && dvc.experiment.checkpoints"
},
{
"command": "dvc.pushExperiments",
"when": "dvc.commands.available && dvc.project.available && !dvc.experiment.running"
},
{
"command": "dvc.queueExperiment",
"when": "dvc.commands.available && dvc.project.available && !dvc.experiment.running"
Expand Down
1 change: 1 addition & 0 deletions extension/src/commands/external.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export enum RegisteredCliCommands {
EXPERIMENT_APPLY = 'dvc.applyExperiment',
EXPERIMENT_BRANCH = 'dvc.branchExperiment',
EXPERIMENT_GARBAGE_COLLECT = 'dvc.experimentGarbageCollect',
EXPERIMENT_PUSH = 'dvc.pushExperiments',
EXPERIMENT_REMOVE = 'dvc.removeExperiments',
EXPERIMENT_REMOVE_QUEUE = 'dvc.removeExperimentQueue',
EXPERIMENT_RESET_AND_RUN = 'dvc.resetAndRunCheckpointExperiment',
Expand Down
10 changes: 8 additions & 2 deletions extension/src/experiments/commands/register.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,8 @@ const registerExperimentInputCommands = (

const registerExperimentQuickPickCommands = (
experiments: WorkspaceExperiments,
internalCommands: InternalCommands
internalCommands: InternalCommands,
setup: Setup
): void => {
internalCommands.registerExternalCliCommand(
RegisteredCliCommands.EXPERIMENT_GARBAGE_COLLECT,
Expand Down Expand Up @@ -220,6 +221,11 @@ const registerExperimentQuickPickCommands = (
() => experiments.selectQueueTasksToKill()
)

internalCommands.registerExternalCliCommand(
RegisteredCliCommands.EXPERIMENT_PUSH,
() => experiments.selectExperimentsToPush(setup)
)

internalCommands.registerExternalCliCommand(
RegisteredCliCommands.EXPERIMENT_REMOVE,
() => experiments.selectExperimentsToRemove()
Expand Down Expand Up @@ -280,7 +286,7 @@ export const registerExperimentCommands = (
registerExperimentCwdCommands(experiments, internalCommands)
registerExperimentNameCommands(experiments, internalCommands)
registerExperimentInputCommands(experiments, internalCommands)
registerExperimentQuickPickCommands(experiments, internalCommands)
registerExperimentQuickPickCommands(experiments, internalCommands, setup)
registerExperimentRunCommands(experiments, internalCommands, setup)

internalCommands.registerExternalCommand(
Expand Down
8 changes: 8 additions & 0 deletions extension/src/experiments/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,14 @@ export class Experiments extends BaseRepository<TableData> {
)
}

public pickExperimentsToPush() {
return pickExperiments(
this.experiments.getExperiments(),
this.getFirstThreeColumnOrder(),
Title.SELECT_EXPERIMENTS_PUSH
)
}

public async pickAndModifyParams(overrideId?: string) {
const id = await this.getExperimentId(overrideId)
if (!id) {
Expand Down
18 changes: 18 additions & 0 deletions extension/src/experiments/workspace.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { EventEmitter, Memento } from 'vscode'
import isEmpty from 'lodash.isempty'
import { Experiments, ModifiedExperimentAndRunCommandId } from '.'
import { getPushExperimentCommand } from './commands'
import { TableData } from './webview/contract'
import { Args } from '../cli/dvc/constants'
import {
Expand All @@ -9,6 +10,7 @@ import {
InternalCommands
} from '../commands/internal'
import { ResourceLocator } from '../resourceLocator'
import { Setup } from '../setup'
import { Toast } from '../vscode/toast'
import {
getInput,
Expand Down Expand Up @@ -172,6 +174,22 @@ export class WorkspaceExperiments extends BaseWorkspaceWebviews<
return this.runCommand(AvailableCommands.QUEUE_KILL, cwd, ...taskIds)
}

public async selectExperimentsToPush(setup: Setup) {
const dvcRoot = await this.getFocusedOrOnlyOrPickProject()
if (!dvcRoot) {
return
}

const ids = await this.getRepository(dvcRoot).pickExperimentsToPush()
if (!ids || isEmpty(ids)) {
return
}

const pushCommand = getPushExperimentCommand(this.internalCommands, setup)

return pushCommand({ dvcRoot, ids })
}

public async selectExperimentsToRemove() {
const cwd = await this.getFocusedOrOnlyOrPickProject()
if (!cwd) {
Expand Down
1 change: 1 addition & 0 deletions extension/src/telemetry/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ export interface IEventNamePropertyMapping {
[EventName.EXPERIMENT_FILTERS_REMOVE_ALL]: undefined
[EventName.EXPERIMENT_GARBAGE_COLLECT]: undefined
[EventName.EXPERIMENT_METRICS_AND_PARAMS_TOGGLE]: undefined
[EventName.EXPERIMENT_PUSH]: undefined
[EventName.EXPERIMENT_REMOVE]: undefined
[EventName.EXPERIMENT_REMOVE_QUEUE]: undefined
[EventName.EXPERIMENT_RESUME]: undefined
Expand Down
109 changes: 108 additions & 1 deletion extension/src/test/suite/experiments/workspace.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { Experiments } from '../../../experiments'
import * as QuickPick from '../../../vscode/quickPick'
import { DvcExecutor } from '../../../cli/dvc/executor'
import {
bypassProgressCloseDelay,
closeAllEditors,
getInputBoxEvent,
getTimeSafeDisposer,
Expand Down Expand Up @@ -657,6 +658,112 @@ suite('Workspace Experiments Test Suite', () => {
})
})

describe('dvc.pushExperiments', () => {
it('should ask the user to pick experiment(s) and then push selected ones to the remote', async () => {
bypassProgressCloseDelay()
const mockExperimentId = 'exp-e7a67'
const secondMockExperimentId = 'exp-83425'
type QuickPickReturnValue = QuickPickItemWithValue<string>[]
stub(Setup.prototype, 'getStudioAccessToken').returns('isat_token')

const { experiments } = buildExperiments(disposable)

await experiments.isReady()

stubWorkspaceExperimentsGetters(dvcDemoPath, experiments)

const mockShowQuickPick = stub(window, 'showQuickPick') as SinonStub<
[items: readonly QuickPickItem[], options: QuickPickOptionsWithTitle],
Thenable<QuickPickReturnValue | undefined>
>

mockShowQuickPick
.onFirstCall()
.resolves([
{
value: mockExperimentId
}
] as QuickPickReturnValue)
.onSecondCall()
.resolves([
{
value: mockExperimentId
},
{
value: secondMockExperimentId
}
] as QuickPickReturnValue)
const mockExpPush = stub(DvcExecutor.prototype, 'expPush')

await commands.executeCommand(RegisteredCliCommands.EXPERIMENT_PUSH)
expect(mockShowQuickPick).calledWithExactly(
[
{
description: '[exp-e7a67]',
detail: `Created:${formatDate(
'2020-12-29T15:31:52'
)}, loss:2.0205045, accuracy:0.37241668`,
label: '4fb124a',
value: 'exp-e7a67'
},
{
description: '[test-branch]',
detail: `Created:${formatDate(
'2020-12-29T15:28:59'
)}, loss:1.9293040, accuracy:0.46680000`,
label: '42b8736',
value: 'test-branch'
},
{
description: '[exp-83425]',
detail: `Created:${formatDate(
'2020-12-29T15:27:02'
)}, loss:1.7750162, accuracy:0.59265000`,
label: EXPERIMENT_WORKSPACE_ID,
value: 'exp-83425'
},
{
description: undefined,
detail: 'Created:-, loss:-, accuracy:-',
label: '489fd8b',
value: '489fd8b'
},
{
description: '[exp-f13bca]',
detail: `Created:${formatDate(
'2020-12-29T15:26:36'
)}, loss:-, accuracy:-`,
label: 'f0f9186',
value: 'exp-f13bca'
},
{
description: undefined,
detail: `Created:${formatDate(
'2020-12-29T15:25:27'
)}, loss:-, accuracy:-`,
label: '55d492c',
value: '55d492c'
}
],
{
canPickMany: true,
matchOnDescription: true,
matchOnDetail: true,
title: 'Select Experiment(s) to Push'
}
)
expect(mockExpPush).to.be.calledWith(dvcDemoPath, mockExperimentId)

await commands.executeCommand(RegisteredCliCommands.EXPERIMENT_PUSH)

expect(mockExpPush).to.be.calledWith(
dvcDemoPath,
mockExperimentId,
secondMockExperimentId
)
})
})

describe('dvc.removeExperiments', () => {
it('should ask the user to pick experiment(s) and then remove selected ones from the workspace', async () => {
const mockExperimentId = 'exp-e7a67'
Expand Down Expand Up @@ -754,7 +861,7 @@ suite('Workspace Experiments Test Suite', () => {
canPickMany: true,
matchOnDescription: true,
matchOnDetail: true,
title: 'Select Experiments to Remove'
title: 'Select Experiment(s) to Remove'
}
)
expect(mockExperimentRemove).to.be.calledWith(
Expand Down
3 changes: 2 additions & 1 deletion extension/src/vscode/title.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ export enum Title {
SELECT_COLUMNS = 'Select Columns to Display in the Experiments Table',
SELECT_EXPERIMENT = 'Select an Experiment',
SELECT_EXPERIMENTS = 'Select Experiments',
SELECT_EXPERIMENTS_REMOVE = 'Select Experiments to Remove',
SELECT_EXPERIMENTS_PUSH = 'Select Experiment(s) to Push',
SELECT_EXPERIMENTS_REMOVE = 'Select Experiment(s) to Remove',
SELECT_EXPERIMENTS_TO_PLOT = 'Select up to 7 Experiments to Display in Plots',
SELECT_FILTERS_TO_REMOVE = 'Select Filter(s) to Remove',
SELECT_FOCUSED_PROJECTS = 'Select Project(s) to Focus (set dvc.focusedProjects)',
Expand Down