Skip to content

Commit

Permalink
feat(analytics): track integration environment
Browse files Browse the repository at this point in the history
This will help us capture if CLI is running e.g. in a specific IDE version
  • Loading branch information
JackuB committed Oct 19, 2020
1 parent ac87ce0 commit 8d4f267
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 35 deletions.
41 changes: 24 additions & 17 deletions src/lib/analytics-sources.ts
Expand Up @@ -13,8 +13,11 @@ import * as fs from 'fs';
import { ArgsOptions } from '../cli/args';
import { join } from 'path';

export const INTEGRATION_NAME_HEADER = 'SNYK_INTEGRATION_NAME';
export const INTEGRATION_VERSION_HEADER = 'SNYK_INTEGRATION_VERSION';
export const INTEGRATION_NAME_ENVVAR = 'SNYK_INTEGRATION_NAME';
export const INTEGRATION_VERSION_ENVVAR = 'SNYK_INTEGRATION_VERSION';
export const INTEGRATION_ENVIRONMENT_ENVVAR = 'SNYK_INTEGRATION_ENVIRONMENT';
export const INTEGRATION_ENVIRONMENT_VERSION_ENVVAR =
'SNYK_INTEGRATION_ENVIRONMENT_VERSION';

enum TrackedIntegration {
// Distribution builds/packages
Expand Down Expand Up @@ -54,12 +57,12 @@ export const getIntegrationName = (args: ArgsOptions[]): string => {
const maybeHomebrew = isHomebrew() ? 'HOMEBREW' : '';
const maybeScoop = isScoop() ? 'SCOOP' : '';

const integrationName = String(
args[0]?.integrationName || // Integration details passed through CLI flag
process.env[INTEGRATION_NAME_HEADER] ||
maybeHomebrew ||
maybeScoop ||
'',
const integrationName = (
(args[0]?.integrationName as string) || // Integration details passed through CLI flag
process.env[INTEGRATION_NAME_ENVVAR] ||
maybeHomebrew ||
maybeScoop ||
''
).toUpperCase();
if (integrationName in TrackedIntegration) {
return integrationName;
Expand All @@ -68,16 +71,20 @@ export const getIntegrationName = (args: ArgsOptions[]): string => {
return '';
};

export const getIntegrationVersion = (args: ArgsOptions[]): string => {
// Integration details passed through CLI flag
const integrationVersion = String(
args[0]?.integrationVersion ||
process.env[INTEGRATION_VERSION_HEADER] ||
'',
);
export const getIntegrationVersion = (args: ArgsOptions[]): string =>
(args[0]?.integrationVersion as string) ||
process.env[INTEGRATION_VERSION_ENVVAR] ||
'';

return integrationVersion;
};
export const getIntegrationEnvironment = (args: ArgsOptions[]): string =>
(args[0]?.integrationEnvironment as string) ||
process.env[INTEGRATION_ENVIRONMENT_ENVVAR] ||
'';

export const getIntegrationEnvironmentVersion = (args: ArgsOptions[]): string =>
(args[0]?.integrationEnvironmentVersion as string) ||
process.env[INTEGRATION_ENVIRONMENT_VERSION_ENVVAR] ||
'';

export function isScoop(): boolean {
const currentProcessPath = process.execPath;
Expand Down
6 changes: 6 additions & 0 deletions src/lib/analytics.js
Expand Up @@ -8,6 +8,8 @@ const request = require('./request');
const {
getIntegrationName,
getIntegrationVersion,
getIntegrationEnvironment,
getIntegrationEnvironmentVersion,
} = require('./analytics-sources');
const isCI = require('./is-ci').isCI;
const debug = require('debug')('snyk');
Expand Down Expand Up @@ -67,6 +69,10 @@ function postAnalytics(data) {
data.standalone = isStandalone;
data.integrationName = getIntegrationName(data.args);
data.integrationVersion = getIntegrationVersion(data.args);
data.integrationEnvironment = getIntegrationEnvironment(data.args);
data.integrationEnvironmentVersion = getIntegrationEnvironmentVersion(
data.args,
);

const seed = uuid.v4();
const shasum = crypto.createHash('sha1');
Expand Down
80 changes: 62 additions & 18 deletions test/analytics-sources.spec.ts
@@ -1,8 +1,12 @@
import {
getIntegrationName,
getIntegrationVersion,
INTEGRATION_NAME_HEADER,
INTEGRATION_VERSION_HEADER,
getIntegrationEnvironment,
getIntegrationEnvironmentVersion,
INTEGRATION_NAME_ENVVAR,
INTEGRATION_VERSION_ENVVAR,
INTEGRATION_ENVIRONMENT_ENVVAR,
INTEGRATION_ENVIRONMENT_VERSION_ENVVAR,
isScoop,
isHomebrew,
validateHomebrew,
Expand All @@ -18,8 +22,10 @@ const defaultArgsParams = {
};

beforeEach(() => {
delete process.env[INTEGRATION_NAME_HEADER];
delete process.env[INTEGRATION_VERSION_HEADER];
delete process.env[INTEGRATION_NAME_ENVVAR];
delete process.env[INTEGRATION_VERSION_ENVVAR];
delete process.env[INTEGRATION_ENVIRONMENT_ENVVAR];
delete process.env[INTEGRATION_ENVIRONMENT_VERSION_ENVVAR];
});

describe('analytics-sources - scoop detection', () => {
Expand Down Expand Up @@ -94,48 +100,48 @@ describe('analytics-sources - Homebrew detection', () => {
});

describe('analytics-sources - getIntegrationName', () => {
it('integration name is empty by default', () => {
it('returns empty integration name by default', () => {
expect(getIntegrationName(emptyArgs)).toBe('');
});

it('integration name is loaded from envvar', () => {
process.env[INTEGRATION_NAME_HEADER] = 'NPM';
it('loads integration name from envvar', () => {
process.env[INTEGRATION_NAME_ENVVAR] = 'NPM';
expect(getIntegrationName(emptyArgs)).toBe('NPM');

process.env[INTEGRATION_NAME_HEADER] = 'STANDALONE';
process.env[INTEGRATION_NAME_ENVVAR] = 'STANDALONE';
expect(getIntegrationName(emptyArgs)).toBe('STANDALONE');
});

it('integration name is empty when envvar is not recognized', () => {
process.env[INTEGRATION_NAME_HEADER] = 'INVALID';
it('returns empty integration namewhen envvar is not recognized', () => {
process.env[INTEGRATION_NAME_ENVVAR] = 'INVALID';
expect(getIntegrationName(emptyArgs)).toBe('');
});

it('integration name is loaded and formatted from CLI flag', () => {
it('loads and formats integration name from CLI flag', () => {
expect(
getIntegrationName([
{ integrationName: 'homebrew', ...defaultArgsParams },
]),
).toBe('HOMEBREW');
});

it('integration name is loaded and validated from CLI flag', () => {
it('loads and validates integration name from CLI flag', () => {
expect(
getIntegrationName([
{ integrationName: 'invalid', ...defaultArgsParams },
]),
).toBe('');
});

it('integration name SCOOP when snyk is installed with scoop', () => {
it('returns integration name SCOOP when snyk is installed with scoop', () => {
const originalExecPath = process.execPath;
process.execPath =
process.cwd() + '/test/fixtures/scoop/good-manifest/snyk-win.exe';
expect(getIntegrationName(emptyArgs)).toBe('SCOOP');
process.execPath = originalExecPath;
});

it('integration name HOMEBREW when snyk is installed with Homebrew', () => {
it('returns integration name HOMEBREW when snyk is installed with Homebrew', () => {
const originalExecPath = process.execPath;
process.execPath =
process.cwd() + '/test/fixtures/homebrew/Cellar/snyk/vX/bin/snyk'; // relies on fixture at /test/fixtures/homebrew/Cellar/vX/.brew/snyk.rb
Expand All @@ -145,20 +151,58 @@ describe('analytics-sources - getIntegrationName', () => {
});

describe('analytics-sources - getIntegrationVersion', () => {
it('integration version is empty by default', () => {
it('returns empty integration version by default', () => {
expect(getIntegrationVersion(emptyArgs)).toBe('');
});

it('integration version is loaded from envvar', () => {
process.env[INTEGRATION_VERSION_HEADER] = '1.2.3';
it('loads integration version from envvar', () => {
process.env[INTEGRATION_VERSION_ENVVAR] = '1.2.3';
expect(getIntegrationVersion(emptyArgs)).toBe('1.2.3');
});

it('integration version is loaded from CLI flag', () => {
it('loads integration version from CLI flag', () => {
expect(
getIntegrationVersion([
{ integrationVersion: '1.2.3-Crystal', ...defaultArgsParams },
]),
).toBe('1.2.3-Crystal');
});
});

describe('analytics-sources - getIntegrationEnvironment', () => {
it('returns empty integration environment by default', () => {
expect(getIntegrationEnvironment(emptyArgs)).toBe('');
});

it('loads integration environment from envvar', () => {
process.env[INTEGRATION_ENVIRONMENT_ENVVAR] = 'WebStorm';
expect(getIntegrationEnvironment(emptyArgs)).toBe('WebStorm');
});

it('loads integration environment from CLI flag', () => {
expect(
getIntegrationEnvironment([
{ integrationEnvironment: 'PhpStorm', ...defaultArgsParams },
]),
).toBe('PhpStorm');
});
});

describe('analytics-sources - getIntegrationEnvironment', () => {
it('returns empty integration environment version by default', () => {
expect(getIntegrationEnvironmentVersion(emptyArgs)).toBe('');
});

it('loads integration environment version from envvar', () => {
process.env[INTEGRATION_ENVIRONMENT_VERSION_ENVVAR] = '2020.2';
expect(getIntegrationEnvironmentVersion(emptyArgs)).toBe('2020.2');
});

it('loads integration environment version from CLI flag', () => {
expect(
getIntegrationEnvironmentVersion([
{ integrationEnvironmentVersion: '7.0.0', ...defaultArgsParams },
]),
).toBe('7.0.0');
});
});
6 changes: 6 additions & 0 deletions test/analytics.test.ts
Expand Up @@ -87,6 +87,8 @@ test('analytics', (t) => {
'durationMs',
'integrationName',
'integrationVersion',
'integrationEnvironment',
'integrationEnvironmentVersion',
].sort(),
'keys as expected',
);
Expand Down Expand Up @@ -124,6 +126,8 @@ test('analytics with args', (t) => {
'durationMs',
'integrationName',
'integrationVersion',
'integrationEnvironment',
'integrationEnvironmentVersion',
].sort(),
'keys as expected',
);
Expand Down Expand Up @@ -163,6 +167,8 @@ test('analytics with args and org', (t) => {
'org',
'integrationName',
'integrationVersion',
'integrationEnvironment',
'integrationEnvironmentVersion',
].sort(),
'keys as expected',
);
Expand Down

0 comments on commit 8d4f267

Please sign in to comment.