diff --git a/.azure-pipelines/common/build.yml b/.azure-pipelines/common/build.yml index 8f29e12086..725ecde347 100644 --- a/.azure-pipelines/common/build.yml +++ b/.azure-pipelines/common/build.yml @@ -1,4 +1,9 @@ steps: +- task: NodeTool@0 + displayName: 'Use Node 8.x' + inputs: + versionSpec: 8.x + - task: Npm@1 displayName: 'npm install' diff --git a/.azure-pipelines/common/publish-test-results.yml b/.azure-pipelines/common/publish-test-results.yml deleted file mode 100644 index 338a8ba2a3..0000000000 --- a/.azure-pipelines/common/publish-test-results.yml +++ /dev/null @@ -1,7 +0,0 @@ -steps: -- task: PublishTestResults@2 - displayName: 'Publish Test Results' - inputs: - testResultsFiles: '*-results.xml' - testRunTitle: '$(Agent.OS)' - condition: succeededOrFailed() diff --git a/.azure-pipelines/common/test.yml b/.azure-pipelines/common/test.yml index da4a9900dc..e9f891fe36 100644 --- a/.azure-pipelines/common/test.yml +++ b/.azure-pipelines/common/test.yml @@ -1,11 +1,27 @@ steps: -- task: Gulp@0 +- script: | + sudo cp .azure-pipelines/linux/xvfb.init /etc/init.d/xvfb + sudo chmod +x /etc/init.d/xvfb + sudo update-rc.d xvfb defaults + sudo service xvfb start + displayName: 'Start X Virtual Frame Buffer' + condition: eq(variables['Agent.OS'], 'Linux') + +- task: Npm@1 displayName: 'Test' inputs: - targets: 'test' + command: custom + customCommand: test env: SERVICE_PRINCIPAL_CLIENT_ID: $(SERVICE_PRINCIPAL_CLIENT_ID) SERVICE_PRINCIPAL_SECRET: $(SERVICE_PRINCIPAL_SECRET) SERVICE_PRINCIPAL_DOMAIN: $(SERVICE_PRINCIPAL_DOMAIN) + DISPLAY: :10 # Only necessary for linux tests + DOCKER_UNAVAILABLE: ${{ parameters.dockerUnavailable }} -- template: publish-test-results.yml +- task: PublishTestResults@2 + displayName: 'Publish Test Results' + inputs: + testResultsFiles: '*-results.xml' + testRunTitle: '$(Agent.OS)' + condition: succeededOrFailed() diff --git a/.azure-pipelines/linux/test-linux.yml b/.azure-pipelines/linux/test-linux.yml deleted file mode 100644 index 421b627f0f..0000000000 --- a/.azure-pipelines/linux/test-linux.yml +++ /dev/null @@ -1,18 +0,0 @@ -steps: -- script: | - sudo cp .azure-pipelines/linux/xvfb.init /etc/init.d/xvfb - sudo chmod +x /etc/init.d/xvfb - sudo update-rc.d xvfb defaults - sudo service xvfb start - displayName: 'Start X Virtual Frame Buffer' - -- script: | - npm test - displayName: 'Test' - env: - DISPLAY: :10 - SERVICE_PRINCIPAL_CLIENT_ID: $(SERVICE_PRINCIPAL_CLIENT_ID) - SERVICE_PRINCIPAL_SECRET: $(SERVICE_PRINCIPAL_SECRET) - SERVICE_PRINCIPAL_DOMAIN: $(SERVICE_PRINCIPAL_DOMAIN) - -- template: ../common/publish-test-results.yml diff --git a/.azure-pipelines/macOs/test.yml b/.azure-pipelines/macOs/test.yml deleted file mode 100644 index ac066e0c5f..0000000000 --- a/.azure-pipelines/macOs/test.yml +++ /dev/null @@ -1,13 +0,0 @@ -steps: -- task: Gulp@0 - displayName: 'Test' - inputs: - targets: 'test' - env: - # Docker not available on MacOS agents (https://docs.microsoft.com/en-us/azure/devops/pipelines/languages/docker) - DOCKER_UNAVAILBLE: 1 - SERVICE_PRINCIPAL_CLIENT_ID: $(SERVICE_PRINCIPAL_CLIENT_ID) - SERVICE_PRINCIPAL_SECRET: $(SERVICE_PRINCIPAL_SECRET) - SERVICE_PRINCIPAL_DOMAIN: $(SERVICE_PRINCIPAL_DOMAIN) - -- template: ../common/publish-test-results.yml diff --git a/.azure-pipelines/main.yml b/.azure-pipelines/main.yml index 3d084a6c57..5c6c41a686 100644 --- a/.azure-pipelines/main.yml +++ b/.azure-pipelines/main.yml @@ -16,13 +16,15 @@ jobs: - template: common/webpack-prod.yml # This will also run during vsce package, but vscep pack doesn't show STDOUT so we won't see full errors there - template: common/publish-vsix.yml # Only publish vsix from linux build since we use this to release and want to stay consistent - template: common/lint.yml - - template: linux/test-linux.yml + - template: common/test.yml - job: macOS pool: vmImage: macOS 10.13 steps: - template: common/build.yml - # - template: common/webpack-prod.yml + - template: common/webpack-prod.yml - template: common/lint.yml - # - template: macOs/test.yml + - template: common/test.yml + parameters: + dockerUnavailable: 1 # Docker not available on MacOS agents (https://docs.microsoft.com/en-us/azure/devops/pipelines/languages/docker) diff --git a/commands/azureCommands/acr-logs-utils/logFileManager.ts b/commands/azureCommands/acr-logs-utils/logFileManager.ts index a44b0d6518..93bb31810f 100644 --- a/commands/azureCommands/acr-logs-utils/logFileManager.ts +++ b/commands/azureCommands/acr-logs-utils/logFileManager.ts @@ -58,7 +58,9 @@ export async function downloadLog(content: string, title: string): Promise filters: { 'Log': ['.log', '.txt'] }, defaultUri: vscode.Uri.file(`${title}.log`) }); - fse.writeFile(uri.fsPath, content, + fse.writeFile( + uri.fsPath, + content, (err) => { if (err) { throw err; } }); diff --git a/commands/docker-compose.ts b/commands/docker-compose.ts index b73d640356..ad6f2e3335 100644 --- a/commands/docker-compose.ts +++ b/commands/docker-compose.ts @@ -7,9 +7,7 @@ import * as path from 'path'; import * as vscode from 'vscode'; import { COMPOSE_FILE_GLOB_PATTERN } from '../constants'; import { ext } from '../extensionVariables'; -import { reporter } from '../telemetry/telemetry'; import { quickPickWorkspaceFolder } from './utils/quickPickWorkspaceFolder'; -const teleCmdId: string = 'vscode-docker.compose.'; // we append up or down when reporting telemetry async function getDockerComposeFileUris(folder: vscode.WorkspaceFolder): Promise { return await vscode.workspace.findFiles(new vscode.RelativePattern(folder, COMPOSE_FILE_GLOB_PATTERN), null, 9999, undefined); @@ -75,16 +73,6 @@ async function compose(commands: ('up' | 'down')[], message: string, dockerCompo terminal.sendText(command.toLowerCase() === 'up' ? `docker-compose -f "${item.file}" ${command} ${detached} ${build}` : `docker-compose -f "${item.file}" ${command}`); }); terminal.show(); - if (reporter) { - /* __GDPR__ - "command" : { - "command" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } - } - */ - reporter.sendTelemetryEvent('command', { - command: teleCmdId + command - }); - } } } diff --git a/commands/inspect-image.ts b/commands/inspect-image.ts index e05862f90c..6c82af449a 100644 --- a/commands/inspect-image.ts +++ b/commands/inspect-image.ts @@ -6,7 +6,6 @@ import { IActionContext } from "vscode-azureextensionui"; import DockerInspectDocumentContentProvider from "../documentContentProviders/dockerInspect"; import { ImageNode } from "../explorer/models/imageNode"; -import { reporter } from "../telemetry/telemetry"; import { quickPickImage } from "./utils/quick-pick-image"; export default async function inspectImage(actionContext: IActionContext, context: ImageNode | undefined): Promise { @@ -24,14 +23,5 @@ export default async function inspectImage(actionContext: IActionContext, contex if (imageToInspect) { await DockerInspectDocumentContentProvider.openImageInspectDocument(imageToInspect); - - if (reporter) { - /* __GDPR__ - "command" : { - "command" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } - } - */ - reporter.sendTelemetryEvent("command", { command: "vscode-docker.image.inspect" }); - } } } diff --git a/commands/push-image.ts b/commands/push-image.ts index d8c5fd28bc..0bb92a9a59 100644 --- a/commands/push-image.ts +++ b/commands/push-image.ts @@ -9,11 +9,8 @@ import { configurationKeys } from '../constants'; import { ImageNode } from '../explorer/models/imageNode'; import { RootNode } from '../explorer/models/rootNode'; import { ext } from '../extensionVariables'; -import { reporter } from '../telemetry/telemetry'; import { askToSaveRegistryPath } from './registrySettings'; import { addImageTaggingTelemetry, getOrAskForImageAndTag, IHasImageDescriptorAndLabel, tagImage } from './tag-image'; -const teleCmdId: string = 'vscode-docker.image.push'; -const teleAzureId: string = 'vscode-docker.image.push.azureContainerRegistry'; export async function pushImage(actionContext: IActionContext, context: ImageNode | RootNode | undefined): Promise { let properties: { @@ -53,27 +50,5 @@ export async function pushImage(actionContext: IActionContext, context: ImageNod const terminal = ext.terminalProvider.createTerminal(imageName); terminal.sendText(`docker push ${imageName}`); terminal.show(); - if (reporter) { - /* __GDPR__ - "command" : { - "command" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } - } - */ - reporter.sendTelemetryEvent('command', { - command: teleCmdId - }); - - if (imageName.toLowerCase().includes('azurecr.io')) { - /* __GDPR__ - "command" : { - "command" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } - } - */ - reporter.sendTelemetryEvent('command', { - command: teleAzureId - }); - - } - } } } diff --git a/commands/remove-container.ts b/commands/remove-container.ts index acfb87ede7..b47906b651 100644 --- a/commands/remove-container.ts +++ b/commands/remove-container.ts @@ -8,7 +8,6 @@ import { IActionContext } from 'vscode-azureextensionui'; import { dockerExplorerProvider } from '../dockerExtension'; import { ContainerNode } from '../explorer/models/containerNode'; import { RootNode } from '../explorer/models/rootNode'; -import { reporter } from '../telemetry/telemetry'; import { docker } from './utils/docker-endpoint'; import { ContainerItem, quickPickContainer } from './utils/quick-pick-container'; @@ -60,14 +59,4 @@ export async function removeContainer(actionContext: IActionContext, context: Ro }); })); } - - if (reporter) { - /* __GDPR__ - "command" : { - "command" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } - } - */ - reporter.sendTelemetryEvent("command", { command: teleCmdId }); - } - } diff --git a/commands/remove-image.ts b/commands/remove-image.ts index d9964d005e..77665e3b58 100644 --- a/commands/remove-image.ts +++ b/commands/remove-image.ts @@ -5,15 +5,11 @@ import vscode = require('vscode'); import { IActionContext } from 'vscode-azureextensionui'; -import { dockerExplorerProvider } from '../dockerExtension'; import { ImageNode } from "../explorer/models/imageNode"; import { RootNode } from '../explorer/models/rootNode'; -import { reporter } from '../telemetry/telemetry'; import { docker } from './utils/docker-endpoint'; import { ImageItem, quickPickImage } from './utils/quick-pick-image'; -const teleCmdId: string = 'vscode-docker.image.remove'; - export async function removeImage(actionContext: IActionContext, context: ImageNode | RootNode | undefined): Promise { let imagesToRemove: Docker.ImageDesc[]; @@ -52,15 +48,4 @@ export async function removeImage(actionContext: IActionContext, context: ImageN }); })); } - - if (reporter) { - /* __GDPR__ - "command" : { - "command" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } - } - */ - reporter.sendTelemetryEvent('command', { - command: teleCmdId - }); - } } diff --git a/commands/restart-container.ts b/commands/restart-container.ts index 5a933b3ff5..32c9d8feec 100644 --- a/commands/restart-container.ts +++ b/commands/restart-container.ts @@ -3,18 +3,14 @@ * Licensed under the MIT License. See LICENSE.md in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import vscode = require('vscode'); +import { IActionContext } from 'vscode-azureextensionui'; import { dockerExplorerProvider } from '../dockerExtension'; import { ContainerNode } from '../explorer/models/containerNode'; -import { reporter } from '../telemetry/telemetry'; +import { RootNode } from '../explorer/models/rootNode'; import { docker } from './utils/docker-endpoint'; import { ContainerItem, quickPickContainer } from './utils/quick-pick-container'; -import vscode = require('vscode'); -import { IActionContext } from 'vscode-azureextensionui'; -import { RootNode } from '../explorer/models/rootNode'; - -const teleCmdId: string = 'vscode-docker.container.restart'; - export async function restartContainer(actionContext: IActionContext, context: RootNode | ContainerNode | undefined): Promise { let containersToRestart: Docker.ContainerDesc[]; @@ -59,16 +55,5 @@ export async function restartContainer(actionContext: IActionContext, context: R }); }); })); - - if (reporter) { - /* __GDPR__ - "command" : { - "command" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } - } - */ - reporter.sendTelemetryEvent('command', { - command: teleCmdId - }); - } } } diff --git a/commands/showlogs-container.ts b/commands/showlogs-container.ts index 3b2e479027..875a8318c7 100644 --- a/commands/showlogs-container.ts +++ b/commands/showlogs-container.ts @@ -8,9 +8,7 @@ import { IActionContext } from 'vscode-azureextensionui'; import { ContainerNode } from '../explorer/models/containerNode'; import { RootNode } from '../explorer/models/rootNode'; import { ext } from '../extensionVariables'; -import { reporter } from '../telemetry/telemetry'; import { ContainerItem, quickPickContainer } from './utils/quick-pick-container'; -const teleCmdId: string = 'vscode-docker.container.show-logs'; export async function showLogsContainer(actionContext: IActionContext, context: RootNode | ContainerNode | undefined): Promise { @@ -34,15 +32,5 @@ export async function showLogsContainer(actionContext: IActionContext, context: const terminal = ext.terminalProvider.createTerminal(containerToLog.Image); terminal.sendText(`docker logs -f ${containerToLog.Id}`); terminal.show(); - if (reporter) { - /* __GDPR__ - "command" : { - "command" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } - } - */ - reporter.sendTelemetryEvent('command', { - command: teleCmdId - }); - } } } diff --git a/commands/start-container.ts b/commands/start-container.ts index e6d30709eb..c16a0faccd 100644 --- a/commands/start-container.ts +++ b/commands/start-container.ts @@ -72,7 +72,8 @@ export async function startAzureCLI(actionContext: IActionContext): Promise('Currently, you can only run the Azure CLI when running Linux based containers.', + const selected = await vscode.window.showErrorMessage( + 'Currently, you can only run the Azure CLI when running Linux based containers.', { title: 'More Information', }, diff --git a/commands/stop-container.ts b/commands/stop-container.ts index c7d285f39d..4007eb383b 100644 --- a/commands/stop-container.ts +++ b/commands/stop-container.ts @@ -5,7 +5,6 @@ import { dockerExplorerProvider } from '../dockerExtension'; import { ContainerNode } from '../explorer/models/containerNode'; -import { reporter } from '../telemetry/telemetry'; import { docker } from './utils/docker-endpoint'; import { ContainerItem, quickPickContainer } from './utils/quick-pick-container'; @@ -13,8 +12,6 @@ import vscode = require('vscode'); import { IActionContext } from 'vscode-azureextensionui'; import { RootNode } from '../explorer/models/rootNode'; -const teleCmdId: string = 'vscode-docker.container.stop'; - export async function stopContainer(actionContext: IActionContext, context: RootNode | ContainerNode | undefined): Promise { let containersToStop: Docker.ContainerDesc[]; @@ -58,16 +55,5 @@ export async function stopContainer(actionContext: IActionContext, context: Root }); }); })); - - if (reporter) { - /* __GDPR__ - "command" : { - "command" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } - } - */ - reporter.sendTelemetryEvent('command', { - command: teleCmdId - }); - } } } diff --git a/commands/system-prune.ts b/commands/system-prune.ts index 2b460e23c4..5e25e06c8e 100644 --- a/commands/system-prune.ts +++ b/commands/system-prune.ts @@ -19,7 +19,8 @@ export async function systemPrune(actionContext: IActionContext): Promise try { if (configOptions.get('promptOnSystemPrune', true)) { - let res = await vscode.window.showWarningMessage('Remove all unused containers, volumes, networks and images (both dangling and unreferenced)?', + let res = await vscode.window.showWarningMessage( + 'Remove all unused containers, volumes, networks and images (both dangling and unreferenced)?', { title: 'Yes' }, { title: 'Cancel', isCloseAffordance: true } ); diff --git a/commands/tag-image.ts b/commands/tag-image.ts index 613b72046e..e3c0ad4f58 100644 --- a/commands/tag-image.ts +++ b/commands/tag-image.ts @@ -11,12 +11,9 @@ import { RootNode } from '../explorer/models/rootNode'; import { delay } from '../explorer/utils/utils'; import { ext } from '../extensionVariables'; import { extractRegExGroups } from '../helpers/extractRegExGroups'; -import { reporter } from '../telemetry/telemetry'; import { docker } from './utils/docker-endpoint'; import { ImageItem, quickPickImage } from './utils/quick-pick-image'; -const teleCmdId: string = 'vscode-docker.image.tag'; - export async function tagImage(actionContext: IActionContext, context: ImageNode | RootNode | IHasImageDescriptorAndLabel | undefined): Promise { // If a RootNode or no node is passed in, we ask the user to pick an image let [imageToTag, currentName] = await getOrAskForImageAndTag(actionContext, context instanceof RootNode ? undefined : context); @@ -44,16 +41,6 @@ export async function tagImage(actionContext: IActionContext, context: ImageNode } }); - if (reporter) { - /* __GDPR__ - "command" : { - "command" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } - } - */ - reporter.sendTelemetryEvent('command', { - command: teleCmdId - }); - } return newTaggedName; } } diff --git a/configureWorkspace/configure.ts b/configureWorkspace/configure.ts index 619020a169..e345d19c83 100644 --- a/configureWorkspace/configure.ts +++ b/configureWorkspace/configure.ts @@ -187,15 +187,17 @@ async function readPomOrGradle(folderPath: string): Promise<{ foundPath?: string foundPath = pomPath; let json = await new Promise((resolve, reject) => { // tslint:disable-next-line:no-unsafe-any - pomParser.parse({ - filePath: pomPath - }, (error, response: { pomObject: PomXmlContents }) => { - if (error) { - reject(`Failed to parse pom.xml: ${error}`); - return; - } - resolve(response.pomObject); - }); + pomParser.parse( + { + filePath: pomPath + }, + (error, response: { pomObject: PomXmlContents }) => { + if (error) { + reject(`Failed to parse pom.xml: ${error}`); + return; + } + resolve(response.pomObject); + }); }); json = json || {}; diff --git a/configureWorkspace/configure_python.ts b/configureWorkspace/configure_python.ts index aa8d11b59e..410733e3eb 100644 --- a/configureWorkspace/configure_python.ts +++ b/configureWorkspace/configure_python.ts @@ -32,6 +32,7 @@ WORKDIR /app ADD . /app # Using pip: +RUN if [ ! -f requirements.txt ]; then pip3 freeze > requirements.txt; fi RUN python3 -m pip install -r requirements.txt CMD ["python3", "-m", "${serviceNameAndRelativePath}"] diff --git a/debugging/coreclr/commandLineBuilder.ts b/debugging/coreclr/commandLineBuilder.ts index 7e49aac09a..ced61c5d5a 100644 --- a/debugging/coreclr/commandLineBuilder.ts +++ b/debugging/coreclr/commandLineBuilder.ts @@ -2,7 +2,7 @@ * Copyright (C) Microsoft Corporation. All rights reserved. *--------------------------------------------------------*/ - export type CommandLineArgFactory = () => (string | undefined); +export type CommandLineArgFactory = () => (string | undefined); export class CommandLineBuilder { private readonly args: CommandLineArgFactory[] = []; diff --git a/dockerExtension.ts b/dockerExtension.ts index e36bf836a4..c367f60ec9 100644 --- a/dockerExtension.ts +++ b/dockerExtension.ts @@ -63,7 +63,6 @@ import { RootNode } from './explorer/models/rootNode'; import { browseAzurePortal } from './explorer/utils/browseAzurePortal'; import { browseDockerHub, dockerHubLogout } from './explorer/utils/dockerHubUtils'; import { ext } from './extensionVariables'; -import { initializeTelemetryReporter, reporter } from './telemetry/telemetry'; import { addUserAgent } from './utils/addUserAgent'; import { AzureUtilityManager } from './utils/azureUtilityManager'; import { getTrustedCertificates } from './utils/getTrustedCertificates'; @@ -96,8 +95,7 @@ function initializeExtensionVariables(ctx: vscode.ExtensionContext): void { if (!ext.terminalProvider) { ext.terminalProvider = new DefaultTerminalProvider(); } - initializeTelemetryReporter(createTelemetryReporter(ctx)); - ext.reporter = reporter; + ext.reporter = createTelemetryReporter(ctx); if (!ext.keytar) { ext.keytar = Keytar.tryCreate(); } diff --git a/dockerHubSearch.ts b/dockerHubSearch.ts index e70a664b20..98cda54762 100644 --- a/dockerHubSearch.ts +++ b/dockerHubSearch.ts @@ -82,12 +82,14 @@ export function searchImagesInRegistryHub(prefix: string, cache: boolean): Promi // tslint:disable-next-line:promise-function-async // Grandfathered in function invokeHubSearch(imageName: string, count: number, cache: boolean): Promise { // https://registry.hub.docker.com/v1/search?q=redis&n=1 - return fetchHttpsJson({ - hostname: 'registry.hub.docker.com', - port: 443, - path: '/v1/search?q=' + encodeURIComponent(imageName) + '&n=' + count, - method: 'GET', - }, cache); + return fetchHttpsJson( + { + hostname: 'registry.hub.docker.com', + port: 443, + path: '/v1/search?q=' + encodeURIComponent(imageName) + '&n=' + count, + method: 'GET', + }, + cache); } export interface IHubSearchResponse { num_pages: number; diff --git a/explorer/deploy/webAppCreator.ts b/explorer/deploy/webAppCreator.ts index 3af5f72a5a..3aeab8c210 100644 --- a/explorer/deploy/webAppCreator.ts +++ b/explorer/deploy/webAppCreator.ts @@ -11,7 +11,6 @@ import WebSiteManagementClient = require('azure-arm-website'); import * as WebSiteModels from 'azure-arm-website/lib/models'; import * as vscode from 'vscode'; import { addExtensionUserAgent } from 'vscode-azureextensionui'; -import { reporter } from '../../telemetry/telemetry'; import { AzureImageTagNode } from '../models/azureRegistryNodes'; import { CustomImageTagNode } from '../models/customRegistryNodes'; import { DockerHubImageTagNode } from '../models/dockerHubNodes'; @@ -19,8 +18,6 @@ import { AzureAccountWrapper } from './azureAccountWrapper'; import * as util from './util'; import { QuickPickItemWithData, SubscriptionStepBase, UserCancelledError, WizardBase, WizardResult, WizardStep } from './wizard'; -const teleCmdId: string = 'vscode-docker.deploy.azureAppService'; - export class WebAppCreator extends WizardBase { constructor(output: vscode.OutputChannel, readonly azureAccount: AzureAccountWrapper, context: AzureImageTagNode | DockerHubImageTagNode, subscription?: SubscriptionModels.Subscription) { super(output); @@ -540,18 +537,6 @@ class WebsiteStep extends WebAppCreatorStepBase { this.wizard.writeline(`Web App "${this._website.name}" ready: https://${this._website.defaultHostName}`); this.wizard.writeline(''); - - if (reporter) { - /* __GDPR__ - "command" : { - "command" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } - } - */ - reporter.sendTelemetryEvent('command', { - command: teleCmdId - }); - } - } get website(): WebSiteModels.Site { diff --git a/explorer/models/azureRegistryNodes.ts b/explorer/models/azureRegistryNodes.ts index 6b94d7edb4..286e882494 100644 --- a/explorer/models/azureRegistryNodes.ts +++ b/explorer/models/azureRegistryNodes.ts @@ -55,7 +55,8 @@ export class AzureRegistryNode extends NodeBase { const repositories: Repository[] = await getRepositoriesByRegistry(element.registry); for (let repository of repositories) { - let node = new AzureRepositoryNode(repository.name, + let node = new AzureRepositoryNode( + repository.name, element, this.azureAccount, element.subscription, diff --git a/explorer/models/rootNode.ts b/explorer/models/rootNode.ts index 9919ab0dfc..2b56a4359f 100644 --- a/explorer/models/rootNode.ts +++ b/explorer/models/rootNode.ts @@ -65,31 +65,34 @@ export class RootNode extends NodeBase { } if (refreshInterval > 0) { - this._imageDebounceTimer = setInterval(async () => { - const images: Docker.ImageDesc[] = await docker.getImageDescriptors(imageFilters); - images.sort((img1, img2) => { - if (img1.Id > img2.Id) { - return -1; - } else if (img1.Id < img2.Id) { - return 1; - } else { - return 0; - } - }); + this._imageDebounceTimer = setInterval( + async () => { + const images: Docker.ImageDesc[] = await docker.getImageDescriptors(imageFilters); + images.sort((img1, img2) => { + if (img1.Id > img2.Id) { + return -1; + } else if (img1.Id < img2.Id) { + return 1; + } else { + return 0; + } + }); - if (!this._sortedImageCache) { - this._sortedImageCache = images; - return; - } + if (!this._sortedImageCache) { + this._sortedImageCache = images; + return; + } - let imagesAsJson = JSON.stringify(images); - let cacheAsJson = JSON.stringify(this._sortedImageCache); - if (imagesAsJson !== cacheAsJson) { - this.eventEmitter.fire(this._imagesNode); - this._sortedImageCache = images; - } + let imagesAsJson = JSON.stringify(images); + let cacheAsJson = JSON.stringify(this._sortedImageCache); + if (imagesAsJson !== cacheAsJson) { + this.eventEmitter.fire(this._imagesNode); + this._sortedImageCache = images; + } - }, refreshInterval); + }, + refreshInterval + ); } } @@ -177,47 +180,47 @@ export class RootNode extends NodeBase { } if (refreshInterval > 0) { - this._containerDebounceTimer = setInterval(async () => { + this._containerDebounceTimer = setInterval( + async () => { + let needToRefresh: boolean = false; + let found: boolean = false; - let needToRefresh: boolean = false; - let found: boolean = false; + const containers: Docker.ContainerDesc[] = await docker.getContainerDescriptors(containerFilters); - const containers: Docker.ContainerDesc[] = await docker.getContainerDescriptors(containerFilters); - - if (!this._containerCache) { - this._containerCache = containers; - } + if (!this._containerCache) { + this._containerCache = containers; + } - if (this._containerCache.length !== containers.length) { - needToRefresh = true; - } else { - for (let cachedContainer of this._containerCache) { - let ctr: Docker.ContainerDesc = cachedContainer; - for (let cont of containers) { - // can't do a full object compare because "Status" keeps changing for running containers - if (ctr.Id === cont.Id && - ctr.Image === cont.Image && - ctr.State === cont.State && - this.isContainerUnhealthy(ctr) === this.isContainerUnhealthy(cont)) { - found = true; - break; + if (this._containerCache.length !== containers.length) { + needToRefresh = true; + } else { + for (let cachedContainer of this._containerCache) { + let ctr: Docker.ContainerDesc = cachedContainer; + for (let cont of containers) { + // can't do a full object compare because "Status" keeps changing for running containers + if (ctr.Id === cont.Id && + ctr.Image === cont.Image && + ctr.State === cont.State && + this.isContainerUnhealthy(ctr) === this.isContainerUnhealthy(cont)) { + found = true; + break; + } } - } - if (!found) { - needToRefresh = true; - break + if (!found) { + needToRefresh = true; + break + } } } - } - - if (needToRefresh) { - this.eventEmitter.fire(this._containersNode); - this._containerCache = containers; - } - }, refreshInterval); + if (needToRefresh) { + this.eventEmitter.fire(this._containersNode); + this._containerCache = containers; + } + }, + refreshInterval); } } diff --git a/explorer/utils/utils.ts b/explorer/utils/utils.ts index 5a790cb7b4..1f7de44be7 100644 --- a/explorer/utils/utils.ts +++ b/explorer/utils/utils.ts @@ -19,8 +19,6 @@ export function trimWithElipsis(str: string, max: number = 10): string { export async function delay(ms: number): Promise { return new Promise(resolve => { - setTimeout(() => { - resolve(); - }, ms); + setTimeout(() => { resolve(); }, ms); }); } diff --git a/gulpfile.js b/gulpfile.ts similarity index 74% rename from gulpfile.js rename to gulpfile.ts index 0d31010468..1ddf4b889d 100644 --- a/gulpfile.js +++ b/gulpfile.ts @@ -3,36 +3,37 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -const gulp = require('gulp'); -const decompress = require('gulp-decompress'); -const download = require('gulp-download'); -const path = require('path'); -const fse = require('fs-extra'); -const os = require('os'); -const cp = require('child_process'); -const glob = require('glob'); +// Grandfathered in +// tslint:disable:typedef +// tslint:disable:no-unsafe-any -const env = process.env; +import * as cp from 'child_process'; +import * as fse from 'fs-extra'; +import * as glob from 'glob'; +import * as gulp from 'gulp'; +import * as decompress from 'gulp-decompress'; +import * as download from 'gulp-download'; +import * as os from 'os'; +import * as path from 'path'; -gulp.task('webpack-dev', async () => { - preWebpack(); - return spawn(path.join(__dirname, './node_modules/.bin/webpack'), ['--mode', 'development'], { stdio: 'inherit', env }); -}); +const env = process.env; -gulp.task('webpack-prod', async () => { - preWebpack(); - return spawn(path.join(__dirname, './node_modules/.bin/webpack'), ['--mode', 'production'], { stdio: 'inherit', env }); -}); +function webpack(mode) { + // without this, webpack can run out of memory in some environments + env.NODE_OPTIONS = '--max-old-space-size=8192'; + return spawn(path.join(__dirname, './node_modules/.bin/webpack'), ['--mode', mode], { stdio: 'inherit', env }); +} /** * Installs the azure account extension before running tests (otherwise our extension would fail to activate) * NOTE: The version isn't super important since we don't actually use the account extension in tests */ -gulp.task('install-azure-account', async () => { +function installAzureAccount() { const version = '0.4.3'; const extensionPath = path.join(os.homedir(), `.vscode/extensions/ms-vscode.azure-account-${version}`); const existingExtensions = glob.sync(extensionPath.replace(version, '*')); if (existingExtensions.length === 0) { + // tslint:disable-next-line:no-http-string return download(`http://ms-vscode.gallery.vsassets.io/_apis/public/gallery/publisher/ms-vscode/extension/azure-account/${version}/assetbyname/Microsoft.VisualStudio.Services.VSIXPackage`) .pipe(decompress({ filter: file => file.path.startsWith('extension/'), @@ -44,15 +45,16 @@ gulp.task('install-azure-account', async () => { .pipe(gulp.dest(extensionPath)); } else { console.log('Azure Account extension already installed.'); + return Promise.resolve(); } -}); +} -gulp.task('test', gulp.series('install-azure-account', async () => { - env.DEBUGTELEMETRY = 1; +function test() { + env.DEBUGTELEMETRY = '1'; env.CODE_TESTS_WORKSPACE = path.join(__dirname, 'test/test.code-workspace'); env.CODE_TESTS_PATH = path.join(__dirname, 'dist/test'); return spawn('node', ['./node_modules/vscode/bin/test'], { stdio: 'inherit', env }); -})); +} function spawn(command, args, options) { if (process.platform === 'win32') { @@ -61,13 +63,11 @@ function spawn(command, args, options) { } else if (fse.pathExistsSync(command + '.cmd')) { command = command + '.cmd'; } - } return cp.spawn(command, args, options); } -function preWebpack() { - // without this, webpack can run out of memory in some environments - env.NODE_OPTIONS = '--max-old-space-size=8192'; -} +exports['webpack-dev'] = () => webpack('development'); +exports['webpack-prod'] = () => webpack('production'); +exports.test = gulp.series(installAzureAccount, test); diff --git a/package-lock.json b/package-lock.json index 40af3e0a06..4048a17c61 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5963,6 +5963,12 @@ "pify": "^3.0.0" } }, + "make-error": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.5.tgz", + "integrity": "sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g==", + "dev": true + }, "make-iterator": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", @@ -8990,6 +8996,30 @@ } } }, + "ts-node": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-7.0.1.tgz", + "integrity": "sha512-BVwVbPJRspzNh2yfslyT1PSbl5uIk03EZlb493RKHN4qej/D06n1cEhjlOJG69oFsE7OT8XjpTUcYf6pKTLMhw==", + "dev": true, + "requires": { + "arrify": "^1.0.0", + "buffer-from": "^1.1.0", + "diff": "^3.1.0", + "make-error": "^1.1.1", + "minimist": "^1.2.0", + "mkdirp": "^0.5.1", + "source-map-support": "^0.5.6", + "yn": "^2.0.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, "tslib": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", @@ -10208,6 +10238,12 @@ "buffer-crc32": "~0.2.3" } }, + "yn": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yn/-/yn-2.0.0.tgz", + "integrity": "sha1-5a2ryKz0CPY4X8dklWhMiOavaJo=", + "dev": true + }, "zone.js": { "version": "0.7.6", "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.7.6.tgz", diff --git a/package.json b/package.json index 4210fe4530..dd9128f07c 100644 --- a/package.json +++ b/package.json @@ -917,6 +917,7 @@ "mocha-multi-reporters": "^1.1.7", "string-replace-webpack-plugin": "^0.1.3", "ts-loader": "^5.3.0", + "ts-node": "^7.0.1", "tslint": "^5.11.0", "tslint-microsoft-contrib": "^5.2.1", "typescript": "^3.1.1", diff --git a/telemetry/telemetry.ts b/telemetry/telemetry.ts deleted file mode 100644 index cc7ada7759..0000000000 --- a/telemetry/telemetry.ts +++ /dev/null @@ -1,14 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See LICENSE.md in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import vscode = require('vscode'); -import { createTelemetryReporter, ITelemetryReporter } from 'vscode-azureextensionui'; -import { ext } from '../extensionVariables'; - -export let reporter: ITelemetryReporter; - -export function initializeTelemetryReporter(newReporter: ITelemetryReporter): void { - reporter = newReporter; -} diff --git a/tsconfig.json b/tsconfig.json index fe49f4a160..98dc96223e 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -20,6 +20,7 @@ }, "exclude": [ "node_modules", - ".vscode-test" + ".vscode-test", + "gulpfile.ts" ] } diff --git a/tslint.json b/tslint.json index 5083966bec..f3cf60fb86 100644 --- a/tslint.json +++ b/tslint.json @@ -215,7 +215,7 @@ "react-a11y-tabindex-no-positive": true, "react-a11y-titles": true, "align": [ - false, // TODO: true, + true, "parameters", "arguments", "statements" diff --git a/utils/Azure/acrTools.ts b/utils/Azure/acrTools.ts index 6deba9b918..3082204ad3 100644 --- a/utils/Azure/acrTools.ts +++ b/utils/Azure/acrTools.ts @@ -157,25 +157,29 @@ export async function sendRequest(http_method: string, login_server: string, export async function getImageDigest(image: AzureImage): Promise { const { acrAccessToken } = await acquireACRAccessTokenFromRegistry(image.registry, `repository:${image.repository.name}:pull`); - return new Promise((resolve, reject) => ext.request.get('https://' + image.registry.loginServer + `/v2/${image.repository.name}/manifests/${image.tag}`, { - auth: { - bearer: acrAccessToken - }, - headers: { - accept: 'application/vnd.docker.distribution.manifest.v2+json; 0.5, application/vnd.docker.distribution.manifest.list.v2+json; 0.6' - } - }, (_err, _httpResponse, _body) => { - if (_err) { - reject(_err); - } else { - const imageDigest = _httpResponse.headers['docker-content-digest']; - if (imageDigest instanceof Array) { - reject(new Error('docker-content-digest should be a string not an array.')) - } else { - resolve(imageDigest); - } - } - })); + return new Promise( + (resolve, reject) => ext.request.get( + 'https://' + image.registry.loginServer + `/v2/${image.repository.name}/manifests/${image.tag}`, + { + auth: { + bearer: acrAccessToken + }, + headers: { + accept: 'application/vnd.docker.distribution.manifest.v2+json; 0.5, application/vnd.docker.distribution.manifest.list.v2+json; 0.6' + } + }, + (_err, _httpResponse, _body) => { + if (_err) { + reject(_err); + } else { + const imageDigest = _httpResponse.headers['docker-content-digest']; + if (imageDigest instanceof Array) { + reject(new Error('docker-content-digest should be a string not an array.')) + } else { + resolve(imageDigest); + } + } + })); } //Credential management @@ -300,40 +304,47 @@ export async function streamLogs(registry: Registry, run: Run, providedClient?: let available = 0; let start = 0; - let obtainLogs = setInterval(async () => { - let props: BlobService.BlobResult; - let metadata: { [key: string]: string; }; - try { - props = await getBlobProperties(blobInfo, blob); - metadata = props.metadata; - } catch (err) { - const error = parseError(err); - //Not found happens when the properties havent yet been set, blob is not ready. Wait 1 second and try again - if (error.errorType === "NotFound") { return; } else { throw error; } - } - available = +props.contentLength; - let text: string; - //Makes sure that if item fails it does so due to network/azure errors not lack of new content - if (available > start) { - text = await getBlobToText(blobInfo, blob, start); - let utf8encoded = (new Buffer(text, 'ascii')).toString('utf8'); - start += text.length; - ext.outputChannel.append(utf8encoded); - } - if (metadata.Complete) { - clearInterval(obtainLogs); - } - }, 1000); + let obtainLogs = setInterval( + async () => { + let props: BlobService.BlobResult; + let metadata: { [key: string]: string; }; + try { + props = await getBlobProperties(blobInfo, blob); + metadata = props.metadata; + } catch (err) { + const error = parseError(err); + //Not found happens when the properties havent yet been set, blob is not ready. Wait 1 second and try again + if (error.errorType === "NotFound") { return; } else { throw error; } + } + available = +props.contentLength; + let text: string; + //Makes sure that if item fails it does so due to network/azure errors not lack of new content + if (available > start) { + text = await getBlobToText(blobInfo, blob, start); + let utf8encoded = (new Buffer(text, 'ascii')).toString('utf8'); + start += text.length; + ext.outputChannel.append(utf8encoded); + } + if (metadata.Complete) { + clearInterval(obtainLogs); + } + }, + 1000 + ); } // Promisify getBlobToText for readability and error handling purposes export async function getBlobToText(blobInfo: IBlobInfo, blob: BlobService, rangeStart: number): Promise { - return new Promise((resolve, reject) => { - blob.getBlobToText(blobInfo.containerName, blobInfo.blobName, { rangeStart: rangeStart }, - (error, result) => { - if (error) { reject(error) } else { resolve(result); } - }); - }); + return new Promise( + (resolve, reject) => { + blob.getBlobToText( + blobInfo.containerName, + blobInfo.blobName, + { rangeStart: rangeStart }, + (error, result) => { + if (error) { reject(error) } else { resolve(result); } + }); + }); } // Promisify getBlobProperties for readability and error handling purposes diff --git a/utils/azureUtilityManager.ts b/utils/azureUtilityManager.ts index 9c2cc02157..b58e22df60 100644 --- a/utils/azureUtilityManager.ts +++ b/utils/azureUtilityManager.ts @@ -118,7 +118,8 @@ export class AzureUtilityManager { return new ResourceManagementClient(await this.getCredentialByTenantId(getTenantId(subscription)), getSubscriptionId(subscription)); } - public async getRegistries(subscription?: Subscription, resourceGroup?: string, + public async getRegistries( + subscription?: Subscription, resourceGroup?: string, compareFn: (a: ContainerModels.Registry, b: ContainerModels.Registry) => number = this.sortRegistriesAlphabetically ): Promise {