Skip to content

Commit 8854b66

Browse files
Merge pull request #1110 from Green-Software-Foundation/release-v1.0.0
Release v1.0.0
2 parents 3dbf094 + 90f7604 commit 8854b66

File tree

41 files changed

+1850
-203
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+1850
-203
lines changed

adopters.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,6 @@ One adopter we will highlight in this file is Amadeus. They have used IF at a la
77
"At Amadeus, the Impact Framework (IF) has become an essential brick in our software carbon measurement engine. Its scalability provides us with a transparent and robust way to model the energy consumption and carbon emissions of our whole cloud infrastructure. Its open-source nature fosters collaboration and innovation, making it a critical part of our efforts to drive environmental responsibility."
88

99
*Robin Castellon, Amadeus*
10+
11+
12+
NCS Group Singapore also used IF and various IF plugins to measure the software carbon intensity of their top 5 Azure apps (as reported by Teck Chun Pang, NCS Group, Singapore)
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
name: csv-import
2+
description: successful path
3+
tags:
4+
initialize:
5+
plugins:
6+
data-import:
7+
method: CSVImport
8+
path: 'builtin'
9+
config:
10+
filepath: manifests/examples/builtins/csv-import/test.csv
11+
# filepath: https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv
12+
output: '*'
13+
tree:
14+
children:
15+
child:
16+
pipeline:
17+
compute:
18+
- data-import
19+
inputs:
20+
- timestamp: 2023-07-06T00:00
21+
duration: 300
22+
physical-processor: AMD 3020e
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
timestamp,duration,cpu-util,energy
2+
2023-07-06T00:00,1,20,5
3+
2023-07-06T00:01,1,30,10
4+
2023-07-06T00:02,1,40,15
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
name: csv-import
2+
description: successful path
3+
tags: null
4+
initialize:
5+
plugins:
6+
data-import:
7+
path: builtin
8+
method: CSVImport
9+
config:
10+
filepath: manifests/examples/builtins/csv-import/test.csv
11+
output: '*'
12+
execution:
13+
command: >-
14+
/Users/manushak/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node
15+
/Users/manushak/Documents/Projects/Green-Software/if/src/if-run/index.ts -m
16+
manifests/examples/builtins/csv-import/success.yaml -o
17+
manifests/outputs/builtins/csv-import/success
18+
environment:
19+
if-version: 0.7.2
20+
os: macOS
21+
os-version: 14.6.1
22+
node-version: 18.20.4
23+
date-time: 2024-12-06T06:45:15.935Z (UTC)
24+
dependencies:
25+
- '@babel/core@7.22.10'
26+
- '@babel/preset-typescript@7.23.3'
27+
- '@commitlint/cli@18.6.0'
28+
- '@commitlint/config-conventional@18.6.0'
29+
- '@grnsft/if-core@0.0.28'
30+
- >-
31+
@grnsft/if-eco-ci-plugin@0.0.1 extraneous ->
32+
file:../../../if-eco-ci-plugin
33+
- '@jest/globals@29.7.0'
34+
- '@types/jest@29.5.8'
35+
- '@types/js-yaml@4.0.9'
36+
- '@types/luxon@3.4.2'
37+
- '@types/node@20.9.0'
38+
- axios-mock-adapter@1.22.0
39+
- axios@1.7.7
40+
- cross-env@7.0.3
41+
- csv-parse@5.5.6
42+
- csv-stringify@6.4.6
43+
- fixpack@4.0.0
44+
- gts@5.2.0
45+
- husky@8.0.3
46+
- jest@29.7.0
47+
- js-yaml@4.1.0
48+
- lint-staged@15.2.10
49+
- luxon@3.4.4
50+
- release-it@16.3.0
51+
- rimraf@5.0.5
52+
- ts-command-line-args@2.5.1
53+
- ts-jest@29.1.1
54+
- typescript-cubic-spline@1.0.1
55+
- typescript@5.2.2
56+
- winston@3.11.0
57+
- zod@3.23.8
58+
status: success
59+
tree:
60+
children:
61+
child:
62+
pipeline:
63+
compute:
64+
- data-import
65+
inputs:
66+
- timestamp: 2023-07-06T00:00
67+
duration: 300
68+
physical-processor: AMD 3020e
69+
outputs:
70+
- timestamp: 2023-07-06T00:00
71+
duration: 300
72+
physical-processor: AMD 3020e
73+
- timestamp: 2023-07-06T00:00
74+
duration: 1
75+
cpu-util: 20
76+
energy: 5
77+
- timestamp: 2023-07-06T00:01
78+
duration: 1
79+
cpu-util: 30
80+
energy: 10
81+
- timestamp: 2023-07-06T00:02
82+
duration: 1
83+
cpu-util: 40
84+
energy: 15

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@grnsft/if",
33
"description": "Impact Framework",
4-
"version": "1.0.0-beta.0",
4+
"version": "1.0.0",
55
"author": {
66
"name": "Green Software Foundation",
77
"email": "info@gsf.com"

src/__tests__/common/util/helpers.test.ts

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,23 @@
1+
import {execFileSync} from 'child_process';
2+
13
jest.mock('node:readline/promises', () =>
24
require('../../../__mocks__/readline')
35
);
46

5-
import {parseManifestFromStdin} from '../../../common/util/helpers';
7+
jest.mock('child_process', () => {
8+
const originalModule = jest.requireActual('child_process');
9+
return {
10+
...originalModule,
11+
execFileSync: jest.fn(() => {
12+
return 'Command executed successfully';
13+
}),
14+
};
15+
});
16+
17+
import {
18+
parseManifestFromStdin,
19+
runHelpCommand,
20+
} from '../../../common/util/helpers';
621

722
describe('common/util/helpers: ', () => {
823
describe('parseManifestFromStdin(): ', () => {
@@ -41,4 +56,50 @@ describe('common/util/helpers: ', () => {
4156
expect(response).toEqual(expectedMessage);
4257
});
4358
});
59+
60+
describe('runHelpCommand(): ', () => {
61+
const originalEnv = process.env;
62+
it('calls process.exit with code 1 on error.', () => {
63+
expect.assertions(3);
64+
65+
jest.spyOn(process, 'exit').mockImplementation((code?: number) => {
66+
expect(code).toEqual(1);
67+
throw new Error(`process.exit(${code}) called`);
68+
});
69+
70+
expect(() => runHelpCommand('if-run')).toThrow('process.exit(1) called');
71+
expect(execFileSync).toHaveBeenCalledWith(
72+
'npm',
73+
['run', 'if-run', '--silent', '--', '-h'],
74+
{
75+
cwd: process.env.CURRENT_DIR || process.cwd(),
76+
stdio: 'inherit',
77+
shell: false,
78+
}
79+
);
80+
});
81+
82+
it('executes when the script runs from the global.', () => {
83+
expect.assertions(3);
84+
process.env.npm_config_global = 'true';
85+
86+
jest.spyOn(process, 'exit').mockImplementation((code?: number) => {
87+
expect(code).toEqual(1);
88+
throw new Error(`process.exit(${code}) called`);
89+
});
90+
91+
expect(() => runHelpCommand('if-run')).toThrow('process.exit(1) called');
92+
expect(execFileSync).toHaveBeenCalledWith(
93+
'if-run',
94+
['--silent', '--', '-h'],
95+
{
96+
cwd: process.env.CURRENT_DIR || process.cwd(),
97+
stdio: 'inherit',
98+
shell: false,
99+
}
100+
);
101+
});
102+
103+
process.env = originalEnv;
104+
});
44105
});

src/__tests__/if-check/util/args.test.ts

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,15 @@
1+
import {execFileSync} from 'child_process';
2+
3+
jest.mock('child_process', () => {
4+
const originalModule = jest.requireActual('child_process');
5+
return {
6+
...originalModule,
7+
execFileSync: jest.fn(() => {
8+
return 'Command executed successfully';
9+
}),
10+
};
11+
});
12+
113
jest.mock('../../../common/util/fs', () => ({
214
isFileExists: () => {
315
if (process.env.fileExists === 'true') {
@@ -151,17 +163,28 @@ describe('if-check/util: ', () => {
151163
}
152164
});
153165

154-
it('throws an error if parsing failed.', async () => {
166+
it('runs help command if the passed argument is incorrect.', async () => {
167+
expect.assertions(3);
168+
jest.spyOn(process, 'exit').mockImplementation((code?: number) => {
169+
expect(code).toEqual(1);
170+
throw new Error(`process.exit(${code}) called`);
171+
});
172+
155173
process.env.result = 'env-throw-error';
156-
expect.assertions(1);
157174

158-
try {
159-
await parseIfCheckArgs();
160-
} catch (error) {
161-
if (error instanceof Error) {
162-
expect(error).toEqual(new ParseCliParamsError('mock-error'));
175+
await expect(parseIfCheckArgs()).rejects.toThrow(
176+
'process.exit(1) called'
177+
);
178+
179+
expect(execFileSync).toHaveBeenCalledWith(
180+
'npm',
181+
['run', 'if-check', '--silent', '--', '-h'],
182+
{
183+
cwd: process.env.CURRENT_DIR || process.cwd(),
184+
stdio: 'inherit',
185+
shell: false,
163186
}
164-
}
187+
);
165188
});
166189

167190
it('throws error if parsing failed (not instance of error).', async () => {

src/__tests__/if-check/util/npm.test.ts

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,51 @@ jest.mock('child_process', () => {
3434
Array.isArray(args) ? `${file} ${args.join(' ')}` : file.trim()
3535
)
3636
).toBeTruthy();
37+
break;
38+
case 'if-check-prefix':
39+
expect(
40+
[
41+
'npm run if-env -- --prefix=.. -m ./src/__mocks__/mock-manifest.yaml',
42+
'npm run if-run -- --prefix=.. -m ./src/__mocks__/mock-manifest.yaml -o src/__mocks__/re-mock-manifest',
43+
'npm run if-diff -- --prefix=.. -s src/__mocks__/re-mock-manifest.yaml -t ./src/__mocks__/mock-manifest.yaml',
44+
'node -p Boolean(process.stdout.isTTY)',
45+
].includes(
46+
Array.isArray(args) ? `${file} ${args.join(' ')}` : file.trim()
47+
)
48+
).toBeTruthy();
49+
break;
50+
case 'if-check-global':
51+
expect(
52+
[
53+
'if-env -m ./src/__mocks__/mock-manifest.yaml',
54+
'if-run -m ./src/__mocks__/mock-manifest.yaml -o src/__mocks__/re-mock-manifest',
55+
'if-diff -s src/__mocks__/re-mock-manifest.yaml -t ./src/__mocks__/mock-manifest.yaml',
56+
'node -p Boolean(process.stdout.isTTY)',
57+
].includes(
58+
Array.isArray(args) ? `${file} ${args.join(' ')}` : file.trim()
59+
)
60+
).toBeTruthy();
61+
62+
break;
63+
case 'if-check-tty':
64+
expect(
65+
[
66+
'if-env -m ./src/__mocks__/mock-manifest.yaml',
67+
'if-run -m ./src/__mocks__/mock-manifest.yaml -o src/__mocks__/re-mock-manifest',
68+
'if-diff -s src/__mocks__/re-mock-manifest.yaml -t ./src/__mocks__/mock-manifest.yaml',
69+
'tty | if-diff -s src/__mocks__/re-mock-manifest.yaml -t ./src/__mocks__/mock-manifest.yaml',
70+
'node -p Boolean(process.stdout.isTTY)',
71+
].includes(
72+
Array.isArray(args) ? `${file} ${args.join(' ')}` : file.trim()
73+
)
74+
).toBeTruthy();
75+
3776
break;
3877
}
78+
79+
if (process.env.NPM_INSTALL === 'if-check-tty') {
80+
return true;
81+
}
3982
return;
4083
},
4184
};
@@ -44,7 +87,16 @@ jest.mock('child_process', () => {
4487
import {executeCommands} from '../../../if-check/util/npm';
4588

4689
describe('if-check/util/npm: ', () => {
90+
const originalEnv = process.env;
4791
describe('executeCommands(): ', () => {
92+
beforeEach(() => {
93+
jest.clearAllMocks();
94+
});
95+
96+
afterEach(() => {
97+
process.env = originalEnv;
98+
});
99+
48100
it('successfully executes with correct commands.', async () => {
49101
process.env.NPM_INSTALL = 'if-check';
50102
const manifest = './src/__mocks__/mock-manifest.yaml';
@@ -57,5 +109,54 @@ describe('if-check/util/npm: ', () => {
57109
'✔ if-check successfully verified mock-manifest.yaml\n'
58110
);
59111
});
112+
113+
it('successfully executes with prefix.', async () => {
114+
process.env.CURRENT_DIR = 'mock-dir';
115+
process.env.NPM_INSTALL = 'if-check-prefix';
116+
const manifest = './src/__mocks__/mock-manifest.yaml';
117+
const logSpy = jest.spyOn(global.console, 'log');
118+
119+
await executeCommands(manifest, false);
120+
121+
expect.assertions(6);
122+
expect(logSpy).toHaveBeenCalledWith(
123+
'✔ if-check successfully verified mock-manifest.yaml\n'
124+
);
125+
delete process.env.CURRENT_DIR;
126+
});
127+
128+
it('successfully executes when it runs from the global.', async () => {
129+
process.env.NPM_INSTALL = 'if-check-global';
130+
process.env.npm_config_global = 'true';
131+
132+
const manifest = './src/__mocks__/mock-manifest.yaml';
133+
const logSpy = jest.spyOn(global.console, 'log');
134+
135+
await executeCommands(manifest, false);
136+
137+
expect.assertions(6);
138+
expect(logSpy).toHaveBeenCalledWith(
139+
'✔ if-check successfully verified mock-manifest.yaml\n'
140+
);
141+
});
142+
143+
it('successfully executes when the `tty` is true.', async () => {
144+
const originalIsTTY = process.stdin.isTTY;
145+
process.stdin.isTTY = true;
146+
process.env.NPM_INSTALL = 'if-check-tty';
147+
process.env.npm_config_global = 'true';
148+
149+
const manifest = './src/__mocks__/mock-manifest.yaml';
150+
const logSpy = jest.spyOn(global.console, 'log');
151+
152+
await executeCommands(manifest, false);
153+
154+
expect.assertions(6);
155+
expect(logSpy).toHaveBeenCalledWith(
156+
'✔ if-check successfully verified mock-manifest.yaml\n'
157+
);
158+
159+
process.stdin.isTTY = originalIsTTY;
160+
});
60161
});
61162
});

0 commit comments

Comments
 (0)