Skip to content

Commit

Permalink
Share experiment to Studio from experiments table (#3289)
Browse files Browse the repository at this point in the history
* create prototype for sharing experiments from the experiments table to Studio

* add tests

* refactor code

* self review

* rearrange code to fit existing structure

* fix package json entries

* move command out of register

* send correct params
  • Loading branch information
mattseddon authored Feb 16, 2023
1 parent a68ceba commit d8ae4a0
Show file tree
Hide file tree
Showing 19 changed files with 506 additions and 13 deletions.
16 changes: 16 additions & 0 deletions extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,12 @@
"category": "DVC",
"icon": "$(repo-push)"
},
{
"title": "%command.views.experiments.shareExperimentToStudio%",
"command": "dvc.views.experiments.shareExperimentToStudio",
"category": "DVC",
"icon": "$(repo-push)"
},
{
"title": "%command.views.experimentsTree.selectExperiments%",
"command": "dvc.views.experimentsTree.selectExperiments",
Expand Down Expand Up @@ -893,6 +899,10 @@
"command": "dvc.views.experiments.shareExperimentAsCommit",
"when": "false"
},
{
"command": "dvc.views.experiments.shareExperimentToStudio",
"when": "false"
},
{
"command": "dvc.views.experimentsFilterByTree.removeAllFilters",
"when": "false"
Expand Down Expand Up @@ -1149,6 +1159,11 @@
"group": "inline@3",
"when": "view == dvc.views.experimentsTree && dvc.commands.available && viewItem =~ /^(experiment|queued)$/ && !dvc.experiment.running"
},
{
"command": "dvc.views.experiments.shareExperimentToStudio",
"group": "1_share@0",
"when": "view == dvc.views.experimentsTree && dvc.commands.available && viewItem == experiment && !dvc.experiment.running"
},
{
"command": "dvc.views.experiments.shareExperimentAsCommit",
"group": "1_share@1",
Expand Down Expand Up @@ -1591,6 +1606,7 @@
"lodash.isequal": "4.5.0",
"lodash.merge": "4.6.2",
"lodash.omit": "4.5.0",
"node-fetch": "2.6.9",
"tree-kill": "1.2.2",
"uuid": "9.0.0",
"vscode-languageclient": "8.0.2"
Expand Down
1 change: 1 addition & 0 deletions extension/package.nls.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@
"command.views.experiments.resetAndRunCheckpointExperiment": "Modify Param(s) and Run",
"command.views.experiments.shareExperimentAsBranch": "Share as Branch",
"command.views.experiments.shareExperimentAsCommit": "Commit and Share",
"command.views.experiments.shareExperimentToStudio": "Share to Studio",
"command.views.experimentsTree.selectExperiments": "Select Experiments to Display in Plots",
"command.views.plotsPathsTree.selectPlots": "Select Plots to Display",
"command.views.plotsPathsTree.refreshPlots": "Refresh Plots for Selected Experiments",
Expand Down
2 changes: 2 additions & 0 deletions extension/src/cli/git/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export enum Command {
INITIALIZE = 'init',
LOG = 'log',
LS_FILES = 'ls-files',
LS_REMOTE = 'ls-remote',
PUSH = 'push',
RESET = 'reset',
REV_PARSE = 'rev-parse',
Expand All @@ -30,6 +31,7 @@ export enum Flag {
DOT = '.',
EXCLUDE_STANDARD = '--exclude-standard',
FORCE = '-f',
GET_URL = '--get-url',
HARD = '--hard',
MESSAGE = '-m',
NAME_ONLY = '--name-only',
Expand Down
10 changes: 10 additions & 0 deletions extension/src/cli/git/reader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { isDirectory } from '../../fileSystem'

export const autoRegisteredCommands = {
GIT_GET_COMMIT_MESSAGES: 'getCommitMessages',
GIT_GET_REMOTE_URL: 'getRemoteUrl',
GIT_GET_REPOSITORY_ROOT: 'getGitRepositoryRoot',
GIT_HAS_CHANGES: 'hasChanges',
GIT_LIST_UNTRACKED: 'listUntracked'
Expand Down Expand Up @@ -59,6 +60,15 @@ export class GitReader extends GitCli {
}
}

public async getRemoteUrl(cwd: string): Promise<string> {
const options = getOptions(cwd, Command.LS_REMOTE, Flag.GET_URL)
try {
return await this.executeProcess(options)
} catch {
return ''
}
}

public async listUntracked(cwd: string) {
const [files, dirs] = await Promise.all([
this.getUntrackedFiles(cwd),
Expand Down
3 changes: 2 additions & 1 deletion extension/src/commands/external.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,5 +99,6 @@ export enum RegisteredCommands {

CONNECT_SHOW = 'dvc.showConnect',
ADD_STUDIO_ACCESS_TOKEN = 'dvc.addStudioAccessToken',
REMOVE_STUDIO_ACCESS_TOKEN = 'dvc.removeStudioAccessToken'
REMOVE_STUDIO_ACCESS_TOKEN = 'dvc.removeStudioAccessToken',
EXPERIMENT_VIEW_SHARE_TO_STUDIO = 'dvc.views.experiments.shareExperimentToStudio'
}
5 changes: 2 additions & 3 deletions extension/src/commands/internal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,8 @@ import { Disposable } from '../class/dispose'

type Command = (...args: Args) => unknown | Promise<unknown>

// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
export const AvailableCommands = Object.assign(
{} as const,
{ EXP_PUSH: 'expPush' } as const,
CliExecutorCommands,
CliReaderCommands,
dvcRunnerCommands,
Expand All @@ -28,7 +27,7 @@ export const AvailableCommands = Object.assign(
typeof CliReaderCommands &
typeof dvcRunnerCommands &
typeof GitExecutorCommands &
typeof GitReaderCommands
typeof GitReaderCommands & { EXP_PUSH: 'expPush' }
export type CommandId =
(typeof AvailableCommands)[keyof typeof AvailableCommands]

Expand Down
6 changes: 5 additions & 1 deletion extension/src/connect/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ export class Connect extends BaseRepository<undefined> {
return this.storeSecret(STUDIO_ACCESS_TOKEN_KEY, token)
}

public getStudioAccessToken() {
return this.getSecret(STUDIO_ACCESS_TOKEN_KEY)
}

private handleMessageFromWebview(message: MessageFromWebview) {
switch (message.type) {
case MessageFromWebviewType.OPEN_STUDIO:
Expand Down Expand Up @@ -89,7 +93,7 @@ export class Connect extends BaseRepository<undefined> {
}

private async setContext() {
const storedToken = await this.getSecret(STUDIO_ACCESS_TOKEN_KEY)
const storedToken = await this.getStudioAccessToken()
if (isStudioAccessToken(storedToken)) {
if (this.deferred.state === 'resolved') {
void showInformation(
Expand Down
20 changes: 19 additions & 1 deletion extension/src/experiments/commands/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { Progress } from 'vscode'
import { Progress, commands } from 'vscode'
import { AvailableCommands, InternalCommands } from '../../commands/internal'
import { Toast } from '../../vscode/toast'
import { WorkspaceExperiments } from '../workspace'
import { Connect } from '../../connect'
import { RegisteredCommands } from '../../commands/external'

export const getBranchExperimentCommand =
(experiments: WorkspaceExperiments) =>
Expand Down Expand Up @@ -104,3 +106,19 @@ export const getShareExperimentAsCommitCommand =
return Toast.delayProgressClosing()
})
}

export const getShareExperimentToStudioCommand =
(internalCommands: InternalCommands, connect: Connect) =>
async ({ dvcRoot, id }: { dvcRoot: string; id: string }) => {
const studioAccessToken = await connect.getStudioAccessToken()
if (!studioAccessToken) {
return commands.executeCommand(RegisteredCommands.CONNECT_SHOW)
}

return internalCommands.executeCommand(
AvailableCommands.EXP_PUSH,
studioAccessToken,
dvcRoot,
id
)
}
12 changes: 10 additions & 2 deletions extension/src/experiments/commands/register.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import {
getBranchExperimentCommand,
getShareExperimentAsBranchCommand,
getShareExperimentAsCommitCommand
getShareExperimentAsCommitCommand,
getShareExperimentToStudioCommand
} from '.'
import { pickGarbageCollectionFlags } from '../quickPick'
import { WorkspaceExperiments } from '../workspace'
Expand All @@ -14,6 +15,7 @@ import { Title } from '../../vscode/title'
import { Context, getDvcRootFromContext } from '../../vscode/context'
import { Setup } from '../../setup'
import { showSetupOrExecuteCommand } from '../../commands/util'
import { Connect } from '../../connect'

type ExperimentDetails = { dvcRoot: string; id: string }

Expand Down Expand Up @@ -329,7 +331,8 @@ const registerExperimentRunCommands = (
export const registerExperimentCommands = (
experiments: WorkspaceExperiments,
internalCommands: InternalCommands,
setup: Setup
setup: Setup,
connect: Connect
) => {
registerExperimentCwdCommands(experiments, internalCommands)
registerExperimentNameCommands(experiments, internalCommands)
Expand All @@ -354,4 +357,9 @@ export const registerExperimentCommands = (
({ dvcRoot, id }: ExperimentDetails) =>
experiments.getRepository(dvcRoot).toggleExperimentStatus(id)
)

internalCommands.registerExternalCommand(
RegisteredCommands.EXPERIMENT_VIEW_SHARE_TO_STUDIO,
getShareExperimentToStudioCommand(internalCommands, connect)
)
}
5 changes: 5 additions & 0 deletions extension/src/experiments/webview/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,11 @@ export class WebviewMessages {
case MessageFromWebviewType.ADD_CONFIGURATION: {
return this.addConfiguration()
}
case MessageFromWebviewType.SHARE_EXPERIMENT_TO_STUDIO:
return commands.executeCommand(
RegisteredCommands.EXPERIMENT_VIEW_SHARE_TO_STUDIO,
{ dvcRoot: this.dvcRoot, id: message.payload }
)

default:
Logger.error(`Unexpected message: ${JSON.stringify(message)}`)
Expand Down
5 changes: 4 additions & 1 deletion extension/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ import { stopProcesses } from './processExecution'
import { Flag } from './cli/dvc/constants'
import { LanguageClient } from './languageClient'
import { collectRunningExperimentPids } from './experiments/processExecution/collect'
import { registerPatchCommand } from './patch'
export class Extension extends Disposable {
protected readonly internalCommands: InternalCommands

Expand Down Expand Up @@ -193,10 +194,12 @@ export class Extension extends Disposable {

registerConnectCommands(this.connect, this.internalCommands)

registerPatchCommand(this.internalCommands)
registerExperimentCommands(
this.experiments,
this.internalCommands,
this.setup
this.setup,
this.connect
)
registerPlotsCommands(this.plots, this.internalCommands, this.setup)
this.internalCommands.registerExternalCommand(
Expand Down
Loading

0 comments on commit d8ae4a0

Please sign in to comment.