diff --git a/CHANGELOG.md b/CHANGELOG.md index 168b979a9b3f1c62765c79dba7b30b58260c0c89..98942dbb1c3cbe20e7ea431701ce7c980fdb0a00 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,21 @@ # CHANGELOG +## [0.4.0] - 2018-02-02 +### Added +- Search for MRs and Issues. Supports basic and advanced search. + - For basic search, just type anything and hit Enter. Extension will search in title and description fields of MRs and issues. + - For advanced search, you can use multiple tokens to search issues and MRs where tokens can be `title`, `author`, `assignee`, `labels`, `label`, `milestone`, `state`, `scope`. Some example usages: + - discussions refactor + - title: discussions refactor author: fatihacet labels: frontend, performance milestone: 10.5 + - title: group labels author: annabeldunstone assignee: timzallmann label: frontend +- Added closing issue link of current MR to status bar and clicking it will open related issue on GitLab. +- Added MIT License + +### Changed +- Pipeline not found text on status bar will be hidden if there is no GL project. +- Significantly reduced timing of opening current MR from status bar. + + ## [0.3.4] - 2018-02-01 ### Fixed - [#12](https://gitlab.com/fatihacet/gitlab-vscode-extension/issues/12) Fix fetching git remote and tracking branch names. diff --git a/package.json b/package.json index f4c3b38a79d22c31e10cbe290e3aada266d9c87a..7a89559adf0ff0a4a449c322f176e5976135569f 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "gitlab-workflow", "displayName": "GitLab Workflow", "description": "GitLab VSCode integration", - "version": "0.3.4", + "version": "0.4.0", "publisher": "fatihacet", "repository": { "type": "git", diff --git a/src/gitlab_service.js b/src/gitlab_service.js index 4b0c76d435ba357debdd6b64398e052440d1153e..201e4ea282bda7bd75682f5ef99a02502aa94c85 100644 --- a/src/gitlab_service.js +++ b/src/gitlab_service.js @@ -162,6 +162,21 @@ async function handlePipelineAction(action) { } } +async function fetchMRIssues(mrId) { + const project = await fetchCurrentProject(); + let issues = []; + + if (project) { + try { + issues = await fetch(`/projects/${project.id}/merge_requests/${mrId}/closes_issues`); + } catch (e) { + console.log('Failed to fetchMRIssue', e); + } + } + + return issues; +}; + /** * @private * @param {string} token GL PAT @@ -176,4 +191,5 @@ exports.fetchOpenMergeRequestForCurrentBranch = fetchOpenMergeRequestForCurrentB exports.fetchLastPipelineForCurrentBranch = fetchLastPipelineForCurrentBranch; exports.fetchCurrentProject = fetchCurrentProject; exports.handlePipelineAction = handlePipelineAction; +exports.fetchMRIssues = fetchMRIssues; exports._setGLToken = _setGLToken; diff --git a/src/status_bar.js b/src/status_bar.js index 0fb9a17cb8dbbb832606fa57ae494da2550fea6f..862378c90a35527a0f35e6ab595d2fa0e79993f4 100644 --- a/src/status_bar.js +++ b/src/status_bar.js @@ -1,9 +1,14 @@ const vscode = require('vscode'); +const opn = require('opn'); const gitLabService = require('./gitlab_service'); let context = null; let pipelineStatusBarItem = null; let mrStatusBarItem = null; +let mrIssueStatusBarItem = null; +let issueId = null; +let projectPath = null; +let mr = null; const createStatusBarItem = (text, command) => { const statusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left); @@ -18,6 +23,10 @@ const createStatusBarItem = (text, command) => { return statusBarItem; } +const commandRegisterHelper = (cmdName, callback) => { + vscode.commands.registerCommand(cmdName, callback); +} + async function refreshPipelines() { let project = null; let pipeline = null; @@ -41,11 +50,10 @@ async function refreshPipelines() { if (pipeline) { const { status } = pipeline; - pipelineStatusBarItem.text = `$(${statuses[status].icon}) GitLab: Pipeline ${statuses[status].text || status}`; + pipelineStatusBarItem.text = `$(${statuses[status].icon}) GitLab: Pipeline ${statuses[status].text || status}.`; pipelineStatusBarItem.show(); } else { - pipelineStatusBarItem.text = 'GitLab: No pipeline'; - pipelineStatusBarItem.hide(); + pipelineStatusBarItem.text = 'GitLab: No pipeline.'; } } @@ -57,17 +65,27 @@ const initPipelineStatus = () => { } const initMrStatus = () => { - mrStatusBarItem = createStatusBarItem('$(info) GitLab: Finding MR...', 'gl.openCurrentMergeRequest'); + const cmdName = 'gl.mrOpener'; + commandRegisterHelper(cmdName, () => { + if (mr) { + opn(mr.web_url); + } else { + vscode.window.showInformationMessage('GitLab Workflow: No MR found for this branch.'); + } + }); + + mrStatusBarItem = createStatusBarItem('$(info) GitLab: Finding MR...', cmdName); setInterval(() => { fetchBranchMr() }, 60000); fetchBranchMr(); } async function fetchBranchMr() { - let mr = null; - let text = '$(git-pull-request) GitLab: MR not found.'; + let text = '$(git-pull-request) GitLab: No MR.'; try { + const project = await gitLabService.fetchCurrentProject(); + projectPath = project.web_url; mr = await gitLabService.fetchOpenMergeRequestForCurrentBranch(); } catch (e) { mrStatusBarItem.hide(); @@ -75,22 +93,51 @@ async function fetchBranchMr() { if (mr) { text = `$(git-pull-request) GitLab: MR !${mr.iid}`; - console.log(mr); + fetchMRIssues(); + } else { + mrIssueStatusBarItem.text = `$(code) GitLab: No issue.`; } mrStatusBarItem.text = text; } +async function fetchMRIssues() { + const issues = await gitLabService.fetchMRIssues(mr.iid); + let text = `$(code) GitLab: No issue.`; + + if (issues[0]) { + issueId = issues[0].iid; + text = `$(code) GitLab: Issue #${issueId}`; + } + + mrIssueStatusBarItem.text = text; +} + +const initMrIssueStatus = () => { + const cmdName = `gl.mrIssueOpener`; + commandRegisterHelper(cmdName, () => { + if (issueId) { + opn(`${projectPath}/issues/${issueId}`); + } else { + vscode.window.showInformationMessage('GitLab Workflow: No closing issue found for this MR.'); + } + }); + + mrIssueStatusBarItem = createStatusBarItem('$(info) GitLab: Fetching closing issue...', cmdName); +} + const init = (ctx) => { context = ctx; initPipelineStatus(); initMrStatus(); + initMrIssueStatus(); } const dispose = () => { - mrStatusBarItem.hide(); - pipelineStatusBarItem.hide(); + mrStatusBarItem.dispose(); + pipelineStatusBarItem.dispose(); + mrIssueStatusBarItem.dispose(); } exports.init = init;