Skip to content

Commit

Permalink
check if tekton is installed
Browse files Browse the repository at this point in the history
Signed-off-by: Luca Stocchi <lstocchi@redhat.com>
  • Loading branch information
lstocchi committed Oct 20, 2022
1 parent 946c6ab commit 8a66736
Show file tree
Hide file tree
Showing 3 changed files with 163 additions and 132 deletions.
12 changes: 11 additions & 1 deletion src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,11 +186,21 @@ export async function activate(extensionContext: vscode.ExtensionContext): Promi
setKubeConfigPath(confApi);
});
}

contextGlobalState.globalState.update('hasTekton', await isTektonAware());
// extensionContext.subscriptions.push(disposable);
disposable.forEach((value) => extensionContext.subscriptions.push(value));
}

async function isTektonAware() {
const kubectl = await k8s.extension.kubectl.v1;
let isTekton = false;
if (kubectl.available) {
const sr = await kubectl.api.invokeCommand('api-versions');
isTekton = sr && sr.code === 0 && sr.stdout.includes('tekton.dev/v1beta1');
}
return isTekton;
}

function refreshTreeView(): void {
functionExplorer.refresh();
servingDataProvider.refresh();
Expand Down
152 changes: 21 additions & 131 deletions src/functions/function-command/build-and-deploy-function.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,13 @@

import * as path from 'path';
import * as vscode from 'vscode';
import { QuickPickItem } from 'vscode';
import * as fs from 'fs-extra';
import * as yaml from 'js-yaml';
import { CliExitData } from '../../cli/cmdCli';
import { knExecutor } from '../../cli/execute';
import { FuncAPI } from '../../cli/func-api';
import { getGitAPI, GitState } from '../../git/git';
import { Branch, Ref, Remote } from '../../git/git.d';
import { contextGlobalState } from '../../extension';
import { getGitBranchInteractively, getGitRepoInteractively, getGitStateByPath, GitModel } from '../../git/git';
import { telemetryLog } from '../../telemetry';
import { ExistingWorkspaceFolderPick } from '../../util/existing-workspace-folder-pick';
import { CACHED_CHILDPROCESS, executeCommandInOutputChannels, STILL_EXECUTING_COMMAND } from '../../util/output_channels';
Expand Down Expand Up @@ -239,145 +238,39 @@ export async function deployFunction(context?: FunctionNode): Promise<CliExitDat
return result;
}

function getRemoteByCommit(refs: Ref[], remotes: Remote[], branch: Branch): Remote {
const refsByCommit = refs
.map((r) => {
if (r.remote && r.name) {
return {
...r,
name: r.name.replace(`${r.remote}/`, ''),
};
}
return r;
})
.filter((r) => r.commit === branch.commit && r.name === branch.name)
.sort((a, b) => {
if (!a.remote) {
return 1;
}
if (!b.remote) {
return -1;
}
return a.remote.localeCompare(b.remote);
});
const remoteNameByCommit = refsByCommit[0]?.remote;
if (remoteNameByCommit) {
// eslint-disable-next-line prefer-destructuring
return remotes.filter((r) => r.name === remoteNameByCommit)[0];
}
return undefined;
}
async function getGitModel(fsPath?: string): Promise<GitModel> {
const gitState = getGitStateByPath(fsPath);

function getFunctionGitState(rootPath?: string): GitState {
let remotes: Remote[] = [];
let refs: Ref[] = [];
let remote: Remote;
let branch: Branch;
let isGit = false;

const api = getGitAPI();
if (api) {
const repositories = api.repositories.filter((r) => r.rootUri.fsPath === rootPath);
isGit = repositories.length > 0;
if (isGit) {
const repo = repositories[0];
remotes = repo.state.remotes;
refs = repo.state.refs;
branch = repo.state.HEAD;
if (branch.commit) {
remote = getRemoteByCommit(refs, remotes, branch);
}
}
const gitRemote = await getGitRepoInteractively(gitState);
if (!gitRemote) {
return null;
}

const gitBranch = await getGitBranchInteractively(gitState, gitRemote);
if (!gitBranch) {
return null;
}
return {
remotes,
refs,
remote,
branch,
isGit,
remoteUrl: gitState.remotes.filter((r) => r.name === gitRemote).map((r) => r.fetchUrl)[0],
branchName: gitBranch,
};
}

function showWarningByState(gitState: GitState) {
if (!gitState.isGit) {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
vscode.window.showWarningMessage(
'This project is not a git repository. Please git initialise it and then proceed to build it on the cluster.',
);
}

if (!gitState.remote && gitState.branch) {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
vscode.window.showWarningMessage(
'The local branch is not present remotely. Push it to remote and then proceed to build it on cluster.',
);
}
}

function showGitQuickPick(gitState: GitState, title: string, value: string, items: QuickPickItem[]): Promise<string | undefined> {
showWarningByState(gitState);
// eslint-disable-next-line @typescript-eslint/no-unused-vars
return new Promise<string | undefined>((resolve, _reject) => {
const quickPick = vscode.window.createQuickPick<QuickPickItem>();
quickPick.items = items;
quickPick.value = value;
quickPick.onDidHide(() => {
resolve(undefined);
quickPick.dispose();
});
quickPick.onDidChangeSelection((e) => {
quickPick.value = e[0].label;
});
quickPick.onDidAccept(() => {
resolve(quickPick.value);
quickPick.dispose();
});
quickPick.canSelectMany = false;
quickPick.ignoreFocusOut = true;
quickPick.title = title;
quickPick.show();
});
}

async function getGitRepoInteractively(gitState: GitState): Promise<string | undefined> {
return showGitQuickPick(
gitState,
`Provide the git repository with the function source code`,
gitState.remote?.name,
gitState.remotes.map((r) => ({
label: r.name,
description: r.fetchUrl,
})),
);
}

async function getGitBranchInteractively(gitState: GitState, repository: string): Promise<string | undefined> {
return showGitQuickPick(
gitState,
`Git revision to be used (branch, tag, commit).`,
gitState.branch?.name,
gitState.refs
.filter((r) => repository === r.remote)
.map((r) => ({
label: r.name?.replace(`${repository}/`, ''),
})),
);
}

export async function onClusterBuildFunction(context?: FunctionNode): Promise<void> {
if (!context) {
return null;
}
const gitState = getFunctionGitState(context.contextPath?.fsPath);

const gitRemote = await getGitRepoInteractively(gitState);
if (!gitRemote) {
if (!contextGlobalState.globalState.get('hasTekton')) {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
await vscode.window.showWarningMessage(
'This action requires Tekton to be installed on the cluster. Please install it and then proceed to build the function on the cluster.',
);
return null;
}

const gitBranch = await getGitBranchInteractively(gitState, gitRemote);
if (!gitBranch) {
const gitModel = await getGitModel(context.contextPath?.fsPath);
if (!gitModel) {
return null;
}

Expand All @@ -392,10 +285,7 @@ export async function onClusterBuildFunction(context?: FunctionNode): Promise<vo
context.contextPath.fsPath,
imageAndBuildMode,
context?.getParent()?.getName(),
{
remoteUrl: gitState.remotes.filter((r) => r.name === gitRemote).map((r) => r.fetchUrl)[0],
branchName: gitBranch,
},
gitModel,
);
const name = `On Cluster Build: ${context.getName()}`;
await knExecutor.executeInTerminal(command, process.cwd(), name);
Expand Down
131 changes: 131 additions & 0 deletions src/git/git.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,134 @@ export function getGitAPI(): API {
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return gitExtension.getAPI(1);
}

function getRemoteByCommit(refs: Ref[], remotes: Remote[], branch: Branch): Remote {
const refsByCommit = refs
.map((r) => {
if (r.remote && r.name) {
return {
...r,
name: r.name.replace(`${r.remote}/`, ''),
};
}
return r;
})
.filter((r) => r.commit === branch.commit && r.name === branch.name)
.sort((a, b) => {
if (!a.remote) {
return 1;
}
if (!b.remote) {
return -1;
}
return a.remote.localeCompare(b.remote);
});
const remoteNameByCommit = refsByCommit[0]?.remote;
if (remoteNameByCommit) {
// eslint-disable-next-line prefer-destructuring
return remotes.filter((r) => r.name === remoteNameByCommit)[0];
}
return undefined;
}

export function getGitStateByPath(rootPath?: string): GitState {
let remotes: Remote[] = [];
let refs: Ref[] = [];
let remote: Remote;
let branch: Branch;
let isGit = false;

const api = getGitAPI();
if (api) {
const repositories = api.repositories.filter((r) => r.rootUri.fsPath === rootPath);
isGit = repositories.length > 0;
if (isGit) {
const repo = repositories[0];
remotes = repo.state.remotes;
refs = repo.state.refs;
branch = repo.state.HEAD;
if (branch.commit) {
remote = getRemoteByCommit(refs, remotes, branch);
}
}
}

return {
remotes,
refs,
remote,
branch,
isGit,
};
}

function showWarningByState(gitState: GitState) {
if (!gitState.isGit) {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
vscode.window.showWarningMessage(
'This project is not a git repository. Please git initialise it and then proceed to build it on the cluster.',
);
}

if (!gitState.remote && gitState.branch) {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
vscode.window.showWarningMessage(
'The local branch is not present remotely. Push it to remote and then proceed to build it on cluster.',
);
}
}

function showGitQuickPick(
gitState: GitState,
title: string,
value: string,
items: vscode.QuickPickItem[],
): Promise<string | undefined> {
showWarningByState(gitState);
// eslint-disable-next-line @typescript-eslint/no-unused-vars
return new Promise<string | undefined>((resolve, _reject) => {
const quickPick = vscode.window.createQuickPick<vscode.QuickPickItem>();
quickPick.items = items;
quickPick.value = value;
quickPick.onDidHide(() => {
resolve(undefined);
quickPick.dispose();
});
quickPick.onDidChangeSelection((e) => {
quickPick.value = e[0].label;
});
quickPick.onDidAccept(() => {
resolve(quickPick.value);
quickPick.dispose();
});
quickPick.canSelectMany = false;
quickPick.ignoreFocusOut = true;
quickPick.title = title;
quickPick.show();
});
}

export async function getGitRepoInteractively(gitState: GitState): Promise<string | undefined> {
return showGitQuickPick(
gitState,
`Provide the git repository with the function source code`,
gitState.remote?.name,
gitState.remotes.map((r) => ({
label: r.name,
description: r.fetchUrl,
})),
);
}

export async function getGitBranchInteractively(gitState: GitState, repository: string): Promise<string | undefined> {
return showGitQuickPick(
gitState,
`Git revision to be used (branch, tag, commit).`,
gitState.branch?.name,
gitState.refs
.filter((r) => repository === r.remote)
.map((r) => ({
label: r.name?.replace(`${repository}/`, ''),
})),
);
}

0 comments on commit 8a66736

Please # to comment.