提交 4c5989a2 编写于 作者: T Tomas Vik

fix(side tree): for current branch not working for multiroot projects

上级 1b74f2cb
......@@ -453,7 +453,7 @@
}
},
"pipelineId": {
"type": "string",
"type": "number | string",
"description": "Returns vulnerabilities belonging to specified pipeline. \"branch\" returns vulnerabilities belonging to latest pipeline of the current branch. Works only with vulnerabilities"
}
}
......
const vscode = require('vscode');
const dayjs = require('dayjs');
const gitLabService = require('../gitlab_service');
const { ErrorItem } = require('./items/error_item');
const { getCurrentWorkspaceFolder } = require('../services/workspace_service');
const { handleError, logError } = require('../log');
const { ItemModel } = require('./items/item_model');
const { MrItemModel } = require('./items/mr_item_model');
const { IssueItem } = require('./items/issue_item');
const { ExternalUrlItem } = require('./items/external_url_item');
dayjs.extend(require('dayjs/plugin/relativeTime'));
class DataProvider {
constructor() {
this.eventEmitter = new vscode.EventEmitter();
this.onDidChangeTreeData = this.eventEmitter.event;
this.project = null;
this.mr = null;
this.disposableChildren = [];
}
import * as vscode from 'vscode';
import * as dayjs from 'dayjs';
import * as relativeTime from 'dayjs/plugin/relativeTime';
import * as gitLabService from '../gitlab_service';
import { ErrorItem } from './items/error_item';
import { getCurrentWorkspaceFolder } from '../services/workspace_service';
import { handleError, logError } from '../log';
import { ItemModel } from './items/item_model';
import { MrItemModel } from './items/mr_item_model';
import { IssueItem } from './items/issue_item';
import { ExternalUrlItem } from './items/external_url_item';
import { GitLabProject } from '../gitlab/gitlab_project';
dayjs.extend(relativeTime);
class DataProvider implements vscode.TreeDataProvider<ItemModel | vscode.TreeItem> {
private eventEmitter = new vscode.EventEmitter<void>();
onDidChangeTreeData = this.eventEmitter.event;
async fetchPipeline(workspaceFolder) {
private mr: RestIssuable | null = null;
private disposableChildren: vscode.Disposable[] = [];
// eslint-disable-next-line class-methods-use-this
async fetchPipeline(workspaceFolder: string, project: GitLabProject) {
let pipeline;
try {
pipeline = await gitLabService.fetchLastPipelineForCurrentBranch(workspaceFolder);
......@@ -45,12 +48,12 @@ class DataProvider {
const actionText = actions[pipeline.status] || '';
const message = `Pipeline #${pipeline.id} ${statusText} · ${actionText} ${timeAgo}`;
const url = `${this.project.webUrl}/pipelines/${pipeline.id}`;
const url = `${project.webUrl}/pipelines/${pipeline.id}`;
return new ExternalUrlItem(message, url);
}
async fetchMR(workspaceFolder) {
async fetchMR(workspaceFolder: string, project: VsProject) {
let mr;
try {
mr = await gitLabService.fetchOpenMergeRequestForCurrentBranch(workspaceFolder);
......@@ -60,35 +63,45 @@ class DataProvider {
}
if (mr) {
this.mr = mr;
const item = new MrItemModel(this.mr, this.project);
const item = new MrItemModel(mr, project);
this.disposableChildren.push(item);
return item;
}
return new vscode.TreeItem('No merge request found');
}
async fetchClosingIssue(workspaceFolder) {
async fetchClosingIssue(workspaceFolder: string, project: VsProject) {
if (this.mr) {
const issues = await gitLabService.fetchMRIssues(this.mr.iid, workspaceFolder);
if (issues.length) {
return issues.map(issue => new IssueItem(issue, this.project));
return issues.map(issue => new IssueItem(issue, project));
}
}
return [new vscode.TreeItem('No closing issue found')];
}
async getChildren(item) {
async getChildren(item: ItemModel | undefined): Promise<ItemModel[] | vscode.TreeItem[]> {
if (item) return item.getChildren();
this.disposableChildren.forEach(s => s.dispose());
this.disposableChildren = [];
const workspaceFolder = await getCurrentWorkspaceFolder();
if (!workspaceFolder) {
return [];
}
try {
const workspaceFolder = await getCurrentWorkspaceFolder();
this.project = await gitLabService.fetchCurrentProject(workspaceFolder);
const pipelineItem = await this.fetchPipeline(workspaceFolder);
const mrItem = await this.fetchMR(workspaceFolder);
const closingIssuesItems = await this.fetchClosingIssue(workspaceFolder);
return [pipelineItem, mrItem, ...closingIssuesItems];
const gitlabProject = await gitLabService.fetchCurrentProject(workspaceFolder);
if (!gitlabProject) {
return [];
}
const vsProject = {
label: gitlabProject.name,
uri: workspaceFolder,
};
const pipelineItem = await this.fetchPipeline(workspaceFolder, gitlabProject);
const mrItem = await this.fetchMR(workspaceFolder, vsProject);
const closingIssuesItems = await this.fetchClosingIssue(workspaceFolder, vsProject);
return [pipelineItem, mrItem, ...closingIssuesItems] as vscode.TreeItem[]; // TODO the actual type includes ItemMode
} catch (e) {
handleError(e);
return [new ErrorItem()];
......@@ -96,7 +109,7 @@ class DataProvider {
}
// eslint-disable-next-line class-methods-use-this
getTreeItem(item) {
getTreeItem(item: ItemModel | vscode.TreeItem) {
if (item instanceof ItemModel) return item.getTreeItem();
return item;
}
......
......@@ -29,6 +29,6 @@ export interface CustomQuery {
severityLevels?: string[];
confidenceLevels?: string[];
searchIn: string;
pipelineId?: string;
pipelineId?: number | 'branch';
noItemText: string;
}
......@@ -194,7 +194,9 @@ export async function getAllGitlabProjects(): Promise<VsProject[]> {
return Promise.all(projectsWithUri);
}
export async function fetchLastPipelineForCurrentBranch(workspaceFolder: string) {
export async function fetchLastPipelineForCurrentBranch(
workspaceFolder: string,
): Promise<RestPipeline | null> {
const project = await fetchCurrentPipelineProject(workspaceFolder);
let pipeline = null;
......@@ -306,11 +308,14 @@ export async function fetchIssuables(params: CustomQuery, workspaceFolder: strin
'not[in]': params.excludeSearchIn,
};
}
// FIXME: this 'branch' or actual numerical ID most likely doesn't make sense from user perspective
// Also, the logic allows for `pipeline_id=branch` query which doesn't make sense
// Issue to deprecate this filter: https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/issues/311
if (pipelineId) {
if (pipelineId === 'branch') {
const workspace = await getCurrentWorkspaceFolder();
if (workspace) {
pipelineId = await fetchLastPipelineForCurrentBranch(workspace);
pipelineId = (await fetchLastPipelineForCurrentBranch(workspace))?.id;
}
}
path = `${path}&pipeline_id=${pipelineId}`;
......@@ -413,7 +418,10 @@ export async function handlePipelineAction(action: string, workspaceFolder: stri
}
}
export async function fetchMRIssues(mrId: number, workspaceFolder: string) {
export async function fetchMRIssues(
mrId: number,
workspaceFolder: string,
): Promise<RestIssuable[]> {
const project = await fetchCurrentProjectSwallowError(workspaceFolder);
let issues = [];
......
import * as vscode from 'vscode';
import * as assert from 'assert';
import { GitService } from './git_service';
import { log } from './log';
import { GitLabNewService } from './gitlab/gitlab_new_service';
import { getInstanceUrl } from './utils/get_instance_url';
export function createGitService(workspaceFolder: string): GitService {
assert(workspaceFolder, 'git service requires workspaceFolder to function');
const { remoteName, pipelineGitRemoteName } = vscode.workspace.getConfiguration('gitlab');
// the getConfiguration() returns null for missing attributes, we need to convert them to
// undefined so that we can use optional properties and default function parameters
......
......@@ -48,3 +48,9 @@ interface RestVulnerability {
severity: string;
name: string;
}
interface RestPipeline {
status: 'running' | 'pending' | 'success' | 'failed' | 'canceled' | 'skipped';
updated_at: string;
id: number;
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册