-
Notifications
You must be signed in to change notification settings - Fork 41
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #665 from Green-Software-Foundation/env-data-in-ou…
…tput Env data in output
- Loading branch information
Showing
14 changed files
with
436 additions
and
15 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
/* eslint-disable @typescript-eslint/ban-ts-comment */ | ||
import {injectEnvironment} from '../../../lib/environment'; | ||
|
||
describe('lib/envirnoment: ', () => { | ||
describe('injectEnvironment(): ', () => { | ||
const context = {}; | ||
|
||
it('checks response to have `execution` property.', async () => { | ||
// @ts-ignore | ||
const response = await injectEnvironment(context); | ||
expect(response).toHaveProperty('execution'); | ||
}); | ||
|
||
it('checks `execution` to have `command` and `environment` props.', async () => { | ||
// @ts-ignore | ||
const response = await injectEnvironment(context); | ||
const {execution} = response; | ||
|
||
expect(execution).toHaveProperty('command'); | ||
expect(execution).toHaveProperty('environment'); | ||
}); | ||
|
||
it('checks environment response type.', async () => { | ||
// @ts-ignore | ||
const response = await injectEnvironment(context); | ||
const {environment} = response.execution; | ||
|
||
expect(typeof environment['date-time']).toEqual('string'); | ||
expect(Array.isArray(environment.dependencies)).toBeTruthy(); | ||
expect(typeof environment['node-version']).toEqual('string'); | ||
expect(typeof environment.os).toEqual('string'); | ||
expect(typeof environment['os-version']).toEqual('string'); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,151 @@ | ||
/* eslint-disable no-restricted-properties */ | ||
jest.mock('os', () => ({ | ||
platform: () => { | ||
if (process.env.KIND === 'darwin') return 'darwin'; | ||
if (process.env.KIND === 'linux') return 'linux'; | ||
if (process.env.KIND === 'win32') return 'win32'; | ||
|
||
return 'sunos'; | ||
}, | ||
release: () => 'm.m.m', | ||
})); | ||
jest.mock('../../../util/helpers', () => ({ | ||
execPromise: async () => { | ||
if (process.env.KIND === 'darwin' && process.env.REJECT === 'true') | ||
return { | ||
stdout: '', | ||
}; | ||
if (process.env.KIND === 'linux' && process.env.REJECT === 'true') { | ||
return { | ||
stdout: '', | ||
}; | ||
} | ||
if (process.env.KIND === 'win32' && process.env.REJECT === 'true') | ||
return { | ||
stdout: '', | ||
}; | ||
if (process.env.KIND === 'darwin') { | ||
return { | ||
stdout: ` | ||
ProductName: macOS | ||
ProductVersion: 14.3.1 | ||
BuildVersion: 23D60 | ||
`, | ||
}; | ||
} | ||
|
||
if (process.env.KIND === 'linux') { | ||
return { | ||
stdout: ` | ||
Distributor ID: Ubuntu | ||
Description: Ubuntu 22.04.4 LTS | ||
Release: 22.04 | ||
Codename: jammy | ||
`, | ||
}; | ||
} | ||
|
||
if (process.env.KIND === 'win32') { | ||
return { | ||
stdout: ` | ||
OS Name: Microsoft Windows 11 Enterprise | ||
OS Version: 10.0.22631 N/A Build 22631 | ||
`, | ||
}; | ||
} | ||
|
||
return ''; | ||
}, | ||
})); | ||
|
||
import {osInfo} from '../../../util/os-checker'; | ||
|
||
describe('util/os-checker: ', () => { | ||
describe('osInfo(): ', () => { | ||
it('returns object with `os` and `os-version` properties.', async () => { | ||
const response = await osInfo(); | ||
expect.assertions(2); | ||
|
||
expect(response).toHaveProperty('os'); | ||
expect(response).toHaveProperty('os-version'); | ||
}); | ||
|
||
it('returns mac os information.', async () => { | ||
process.env.KIND = 'darwin'; | ||
expect.assertions(1); | ||
|
||
const expectedResponse = { | ||
os: 'macOS', | ||
'os-version': '14.3.1', | ||
}; | ||
const response = await osInfo(); | ||
expect(response).toEqual(expectedResponse); | ||
}); | ||
|
||
it('returns windows information.', async () => { | ||
process.env.KIND = 'win32'; | ||
expect.assertions(1); | ||
|
||
const expectedResponse = { | ||
os: 'Microsoft Windows 11 Enterprise', | ||
'os-version': '10.0.22631 N/A Build 22631', | ||
}; | ||
const response = await osInfo(); | ||
expect(response).toEqual(expectedResponse); | ||
}); | ||
|
||
it('returns linux information.', async () => { | ||
process.env.KIND = 'linux'; | ||
expect.assertions(1); | ||
|
||
const expectedResponse = { | ||
os: 'Ubuntu', | ||
'os-version': '22.04.4 LTS', | ||
}; | ||
const response = await osInfo(); | ||
expect(response).toEqual(expectedResponse); | ||
}); | ||
|
||
it('returns default information.', async () => { | ||
process.env.KIND = 'other'; | ||
expect.assertions(2); | ||
|
||
const response = await osInfo(); | ||
expect(typeof response.os).toEqual('string'); | ||
expect(typeof response['os-version']).toEqual('string'); | ||
}); | ||
|
||
it('returns info from node os on linux.', async () => { | ||
process.env.KIND = 'linux'; | ||
process.env.REJECT = 'true'; | ||
|
||
const response = await osInfo(); | ||
const expectedOS = 'linux'; | ||
const expectedOSVersion = 'm.m.m'; | ||
expect(response.os).toEqual(expectedOS); | ||
expect(response['os-version']).toEqual(expectedOSVersion); | ||
}); | ||
|
||
it('returns info from node os on darwin.', async () => { | ||
process.env.KIND = 'darwin'; | ||
process.env.REJECT = 'true'; | ||
|
||
const response = await osInfo(); | ||
const expectedOS = 'darwin'; | ||
const expectedOSVersion = 'm.m.m'; | ||
expect(response.os).toEqual(expectedOS); | ||
expect(response['os-version']).toEqual(expectedOSVersion); | ||
}); | ||
|
||
it('returns info from node os on win32.', async () => { | ||
process.env.KIND = 'win32'; | ||
process.env.REJECT = 'true'; | ||
|
||
const response = await osInfo(); | ||
const expectedOS = 'win32'; | ||
const expectedOSVersion = 'm.m.m'; | ||
expect(response.os).toEqual(expectedOS); | ||
expect(response['os-version']).toEqual(expectedOSVersion); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
import {DateTime} from 'luxon'; | ||
|
||
import {execPromise} from '../util/helpers'; | ||
|
||
import {Context, ContextWithExec} from '../types/manifest'; | ||
import {NpmListResponse, PackageDependency} from '../types/environment'; | ||
import {osInfo} from '../util/os-checker'; | ||
|
||
const packageJson = require('../../package.json'); | ||
|
||
/** | ||
* 1. Gets the high-resolution real time when the application starts. | ||
* 2. Converts the high-resolution time to milliseconds. | ||
* 3. Gets the current DateTime. | ||
* 4. Subtracts the milliseconds from the current DateTime. | ||
*/ | ||
const getProcessStartingTimestamp = () => { | ||
const startTime = process.hrtime(); | ||
|
||
const [seconds, nanoseconds] = process.hrtime(startTime); | ||
const milliseconds = seconds * 1000 + nanoseconds / 1e6; | ||
|
||
const currentDateTime = DateTime.local(); | ||
|
||
const applicationStartDateTime = currentDateTime.minus({ | ||
milliseconds: milliseconds, | ||
}); | ||
|
||
return applicationStartDateTime.toUTC().toString(); | ||
}; | ||
|
||
/** | ||
* Goes through the dependencies, converts them into oneliner. | ||
*/ | ||
const flattenDependencies = (dependencies: [string, PackageDependency][]) => | ||
dependencies.map(dependency => { | ||
const [packageName, versionInfo] = dependency; | ||
const {version, extraneous, resolved} = versionInfo; | ||
const ifExtraneous = extraneous ? ` extraneous -> ${resolved}` : ''; | ||
const ifFromGithub = | ||
resolved && resolved.startsWith('git') ? ` (${resolved})` : ''; | ||
const formattedString = `${packageName}@${version}${ | ||
ifExtraneous || ifFromGithub | ||
}`; | ||
|
||
return formattedString; | ||
}); | ||
|
||
/** | ||
* 1. Runs `npm list --json`. | ||
* 2. Parses json data and converts to list. | ||
*/ | ||
const listDependencies = async () => { | ||
const {stdout} = await execPromise('npm list --json'); | ||
const npmListResponse: NpmListResponse = JSON.parse(stdout); | ||
const dependencies = Object.entries(npmListResponse.dependencies); | ||
|
||
return flattenDependencies(dependencies); | ||
}; | ||
|
||
/** | ||
* Injects execution information (command, environment) to existing context. | ||
*/ | ||
export const injectEnvironment = async (context: Context) => { | ||
const dependencies = await listDependencies(); | ||
const info = await osInfo(); | ||
const dateTime = `${getProcessStartingTimestamp()} (UTC)`; | ||
|
||
const contextWithExec: ContextWithExec = { | ||
...context, | ||
execution: { | ||
command: process.argv.join(' '), | ||
environment: { | ||
'if-version': packageJson.version, | ||
os: info.os, | ||
'os-version': info['os-version'], | ||
'node-version': process.versions.node, | ||
'date-time': dateTime, | ||
dependencies, | ||
}, | ||
}, | ||
}; | ||
|
||
return contextWithExec; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
export type PackageDependency = { | ||
version: string; | ||
resolved?: string; | ||
overridden: boolean; | ||
extraneous?: boolean; | ||
}; | ||
|
||
type PackageProblem = { | ||
extraneous: string; | ||
}; | ||
|
||
export type NpmListResponse = { | ||
version: string; | ||
name: string; | ||
problems?: PackageProblem[]; | ||
dependencies: { | ||
[key: string]: PackageDependency; | ||
}; | ||
}; |
Oops, something went wrong.