From ca6a7b6d2c4a873e22bdbad57ddf143f4082275f Mon Sep 17 00:00:00 2001 From: Yevhen Vydolob Date: Tue, 28 Jul 2020 16:28:00 +0300 Subject: [PATCH] #371 open PipelineRun diagram from Tekton tree Signed-off-by: Yevhen Vydolob --- .vscode/settings.json | 2 +- images/dark/icon-diagram.svg | 11 +++++++++ images/light/icon-diagram.svg | 11 +++++++++ package.json | 14 +++++++++++ src/extension.ts | 1 + src/pipeline/pipeline-graph.ts | 4 +-- src/pipeline/pipeline-preview.ts | 19 +++++++++++++++ src/pipeline/preview-manager.ts | 3 ++- src/pipeline/preview.ts | 42 +++++++++++++++++--------------- src/tekton/pipelinerun.ts | 5 ++++ 10 files changed, 89 insertions(+), 23 deletions(-) create mode 100644 images/dark/icon-diagram.svg create mode 100644 images/light/icon-diagram.svg diff --git a/.vscode/settings.json b/.vscode/settings.json index cb63b4a3..7d7ece5c 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -9,5 +9,5 @@ // Turn off tsc task auto detection since we have the necessary tasks as npm scripts "typescript.tsc.autoDetect": "off", "debug.node.autoAttach": "off", - "svg.preview.background": "custom" + "svg.preview.background": "transparent" } diff --git a/images/dark/icon-diagram.svg b/images/dark/icon-diagram.svg new file mode 100644 index 00000000..fa6bec22 --- /dev/null +++ b/images/dark/icon-diagram.svg @@ -0,0 +1,11 @@ + + + + background + + + + Layer 1 + + + diff --git a/images/light/icon-diagram.svg b/images/light/icon-diagram.svg new file mode 100644 index 00000000..39bef489 --- /dev/null +++ b/images/light/icon-diagram.svg @@ -0,0 +1,11 @@ + + + + background + + + + Layer 1 + + + diff --git a/package.json b/package.json index 66417e02..01637751 100644 --- a/package.json +++ b/package.json @@ -444,6 +444,15 @@ "dark": "images/dark/icon-delete.svg", "light": "images/light/icon-delete.svg" } + }, + { + "command": "tekton.view.pipelinerun.diagram", + "title": "Open Diagram", + "category": "Tekton", + "icon": { + "dark": "images/dark/icon-diagram.svg", + "light": "images/light/icon-diagram.svg" + } } ], "viewsContainers": { @@ -711,6 +720,11 @@ "when": "view =~ /^tekton(CustomTree|PipelineExplorer)View/ && viewItem == taskrun", "group": "inline@1" }, + { + "command": "tekton.view.pipelinerun.diagram", + "when": "view =~ /^tekton(CustomTree|PipelineExplorer)View/ && viewItem == pipelinerun", + "group": "inline@1" + }, { "command": "tekton.open.condition", "when": "view =~ /^tekton(CustomTree|PipelineExplorer)View/ && viewItem == tr", diff --git a/src/extension.ts b/src/extension.ts index 2bd6eb04..b2f95f08 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -88,6 +88,7 @@ export async function activate(context: vscode.ExtensionContext): Promise vscode.commands.registerCommand('tekton.open.condition', (context) => execute(TaskRun.openConditionDefinition, context)), vscode.commands.registerCommand('tekton.open.task', (context) => execute(TaskRun.openDefinition, context)), vscode.commands.registerCommand('tekton.open.task.palette', (context) => execute(TaskRun.openDefinition, context)), + vscode.commands.registerCommand('tekton.view.pipelinerun.diagram', (context) => execute(PipelineRun.showDiagram, context)), pipelineExplorer, // Temporarily loaded resource providers diff --git a/src/pipeline/pipeline-graph.ts b/src/pipeline/pipeline-graph.ts index 2435545b..6351ed49 100644 --- a/src/pipeline/pipeline-graph.ts +++ b/src/pipeline/pipeline-graph.ts @@ -15,7 +15,7 @@ import { tektonFSUri, tektonVfsProvider } from '../util/tekton-vfs'; const pipelineRunTaskCache = new Map(); export interface GraphProvider { - (document: vscode.TextDocument, pipelineRun?: PipelineRunData): Promise; + (document: vscode.TextDocument | VirtualDocument, pipelineRun?: PipelineRunData): Promise; getElementBySelection?(document: vscode.TextDocument, selection: vscode.Selection): string | undefined; } @@ -36,7 +36,7 @@ calculatePipelineGraph.getElementBySelection = function (document: vscode.TextDo return pipelineYaml.findTask(document, selection.start); } -export async function calculatePipelineRunGraph(document: vscode.TextDocument, pipelineRun?: PipelineRunData): Promise { +export async function calculatePipelineRunGraph(document: VirtualDocument, pipelineRun?: PipelineRunData): Promise { const doc: YamlDocument = await getPipelineDocument(document, TektonYamlType.PipelineRun); if (!doc) { return []; // TODO: throw error there diff --git a/src/pipeline/pipeline-preview.ts b/src/pipeline/pipeline-preview.ts index d50f89e7..87c41ca9 100644 --- a/src/pipeline/pipeline-preview.ts +++ b/src/pipeline/pipeline-preview.ts @@ -7,6 +7,8 @@ import { TektonYamlType, tektonYaml, pipelineRunYaml } from '../yaml-support/tkn import { previewManager, PreviewSettings } from './preview-manager'; import { CommandContext, setCommandContext } from '../commands'; import { calculatePipelineGraph, calculatePipelineRunGraph, askToSelectPipeline } from './pipeline-graph'; +import { tektonFSUri, tektonVfsProvider } from '../util/tekton-vfs'; +import { ContextType } from '../tkn'; export async function showPipelinePreview(): Promise { const document = vscode.window.activeTextEditor?.document; @@ -42,6 +44,23 @@ export async function showPipelinePreview(): Promise { } } +export async function showPipelineRunPreview(name: string): Promise { + if (!name) { + return; + } + const uri = tektonFSUri(ContextType.PIPELINERUN, name, 'yaml'); + const pipelineRunDoc = await tektonVfsProvider.loadTektonDocument(uri); + const pipelineRun = tektonYaml.getTektonDocuments(pipelineRunDoc, TektonYamlType.PipelineRun); + + previewManager.createPipelinePreview(pipelineRunDoc, { + resourceColumn: vscode.ViewColumn.Active, + previewColumn: vscode.ViewColumn.Active, + graphProvider: calculatePipelineRunGraph, + pipelineRunName: name, + pipelineRunStatus: pipelineRunYaml.getPipelineRunStatus(pipelineRun[0]) + } as PreviewSettings); +} + export function registerPipelinePreviewContext(): void { setCommandContext(CommandContext.PipelinePreview, getContext(vscode.window.activeTextEditor?.document)); diff --git a/src/pipeline/preview-manager.ts b/src/pipeline/preview-manager.ts index 96c5148e..a1a0885b 100644 --- a/src/pipeline/preview-manager.ts +++ b/src/pipeline/preview-manager.ts @@ -6,6 +6,7 @@ import { TextDocument, ViewColumn } from 'vscode'; import { PipelinePreview } from './preview'; import { Disposable } from '../util/disposable'; import { GraphProvider } from './pipeline-graph'; +import { VirtualDocument } from '../yaml-support/yaml-locator'; export interface PreviewSettings { @@ -37,7 +38,7 @@ export class PreviewManager extends Disposable { preview.update(document); } - createPipelinePreview(document: TextDocument, settings: PreviewSettings): PipelinePreview { + createPipelinePreview(document: TextDocument | VirtualDocument, settings: PreviewSettings): PipelinePreview { const preview = PipelinePreview.create( { document, diff --git a/src/pipeline/preview.ts b/src/pipeline/preview.ts index 45d30eb5..2e88c30a 100644 --- a/src/pipeline/preview.ts +++ b/src/pipeline/preview.ts @@ -12,9 +12,10 @@ import { debounce } from 'debounce'; import { kubectl } from '../kubectl'; import { PipelineRunData } from '../tekton'; import { NodeData } from '../../preview-src/model'; +import { VirtualDocument } from '../yaml-support/yaml-locator'; export interface PipelinePreviewInput { - readonly document: vscode.TextDocument; + readonly document: vscode.TextDocument | VirtualDocument; readonly resourceColumn: vscode.ViewColumn; readonly line?: number; readonly graphProvider: GraphProvider; @@ -31,7 +32,7 @@ export class PipelinePreview extends Disposable { previewColumn: vscode.ViewColumn): PipelinePreview { const webview = vscode.window.createWebviewPanel( PipelinePreview.viewType, - `Preview ${path.basename(input.document.fileName)}`, + `Preview ${path.basename(input.document.uri.fsPath)}`, previewColumn, { enableFindWidget: true, @@ -43,7 +44,7 @@ export class PipelinePreview extends Disposable { } private editor: vscode.WebviewPanel; - private document: vscode.TextDocument; + private document: vscode.TextDocument | VirtualDocument; private updateFunc = debounce(() => this.doUpdate(), 500); private graphProvider: GraphProvider; private readonly onDisposeEmitter = new vscode.EventEmitter(); @@ -62,7 +63,7 @@ export class PipelinePreview extends Disposable { })); this.register(vscode.workspace.onDidChangeTextDocument(e => { - if (e.document.fileName === this.document.fileName) { + if (e.document.fileName === this.document.uri.fsPath) { this.update(e.document); } })); @@ -76,7 +77,7 @@ export class PipelinePreview extends Disposable { })); this.register(vscode.window.onDidChangeTextEditorSelection(e => { - if (e.textEditor.document.fileName === this.document.fileName) { + if (e.textEditor.document.fileName === this.document.uri.fsPath) { this.highlightNode(e.textEditor.document, e.selections); } })); @@ -113,7 +114,7 @@ export class PipelinePreview extends Disposable { } update(document: vscode.TextDocument): void { - if (this.document.fileName === document.fileName) { + if (this.document.uri.fsPath === document.fileName) { this.updateFunc(); } } @@ -130,21 +131,24 @@ export class PipelinePreview extends Disposable { } private async onDidClick(node: NodeData): Promise { - const position = this.document.positionAt(node.yamlPosition); - for (const visibleEditor of vscode.window.visibleTextEditors) { - if (this.isPreviewOf(visibleEditor.document.uri)) { - const editor = await vscode.window.showTextDocument(visibleEditor.document, visibleEditor.viewColumn); - editor.selection = new vscode.Selection(position, position); - editor.revealRange(new vscode.Range(position, position), vscode.TextEditorRevealType.InCenterIfOutsideViewport); - return; + if ((this.document as vscode.TextDocument).positionAt) { + const position = (this.document as vscode.TextDocument).positionAt(node.yamlPosition); + for (const visibleEditor of vscode.window.visibleTextEditors) { + if (this.isPreviewOf(visibleEditor.document.uri)) { + const editor = await vscode.window.showTextDocument(visibleEditor.document, visibleEditor.viewColumn); + editor.selection = new vscode.Selection(position, position); + editor.revealRange(new vscode.Range(position, position), vscode.TextEditorRevealType.InCenterIfOutsideViewport); + return; + } } + + vscode.workspace.openTextDocument(this.document.uri) + .then(vscode.window.showTextDocument) + .then(undefined, () => { + vscode.window.showErrorMessage(`Could not open ${this.document.uri.toString()}`); + }); } - vscode.workspace.openTextDocument(this.document.uri) - .then(vscode.window.showTextDocument) - .then(undefined, () => { - vscode.window.showErrorMessage(`Could not open ${this.document.uri.toString()}`); - }); } private isPreviewOf(resource: vscode.Uri): boolean { @@ -182,7 +186,7 @@ export class PipelinePreview extends Disposable { } private setContent(html: string): void { - const fileName = path.basename(this.document.fileName); + const fileName = path.basename(this.document.uri.fsPath); this.editor.title = `Preview ${fileName}`; // this.editor.iconPath = this.iconPath; //TODO: implement this.editor.webview.options = getWebviewOptions(); diff --git a/src/tekton/pipelinerun.ts b/src/tekton/pipelinerun.ts index 01807e4f..756f9612 100644 --- a/src/tekton/pipelinerun.ts +++ b/src/tekton/pipelinerun.ts @@ -7,6 +7,7 @@ import { TektonItem } from './tektonitem'; import { TektonNode, Command } from '../tkn'; import { window } from 'vscode'; import { CliCommand } from '../cli'; +import { showPipelineRunPreview } from '../pipeline/pipeline-preview'; export class PipelineRun extends TektonItem { @@ -53,4 +54,8 @@ export class PipelineRun extends TektonItem { static getDeleteCommand(item: TektonNode): CliCommand { return Command.deletePipelineRun(item.getName()) } + + static async showDiagram(item: TektonNode): Promise { + await showPipelineRunPreview(item.getName()); + } }