Skip to content

Commit c2b1826

Browse files
chore(src): fetch changes from main
2 parents 4ac86bd + ae044f0 commit c2b1826

32 files changed

+1421
-104
lines changed

.github/codeql/codeql-config.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
paths:
2+
- "src"
3+
paths-ignore:
4+
- "src/__tests__/**/*.js"
5+
- "src/__tests__/**/*.ts"
6+
- "src/__tests__/**/*.jsx"
7+
- "src/__tests__/**/*.tsx"

CONTRIBUTING.md

Lines changed: 50 additions & 33 deletions
Large diffs are not rendered by default.

SECURITY.md

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
# Security Policy
2+
3+
## Reporting a Vulnerability
4+
5+
To report a security issue, please email if-disclosures@greensoftware.foundation with a description of the issue, steps required to reproduce the issue, affected versions and, if known, mitigations for the issue.
6+
7+
Our contributors are comprised of volunteers so we cannot guarantee a specific response time, but someone from our team will reply and address the issue as soon as possible.
8+
9+
# Security Review
10+
11+
We perform regular reviews inline with the information provided below. All releases go through these reviews but multiple people in the project team prior to release as part of our quality and security review.
12+
13+
## Basics
14+
### Basic Project Website Content
15+
- Describe what the project does - ✅ in README and homepage at https://if.greensoftware.foundation
16+
- Provide info how to obtain/provide feedback and contribute - ✅ https://if.greensoftware.foundation/community
17+
- Explain contribution process - ✅ https://github.com/Green-Software-Foundation/if/blob/main/CONTRIBUTING.md
18+
19+
### FLOSS license
20+
- Must be released as FLOSS - ✅ MIT License https://github.com/Green-Software-Foundation/if/blob/main/LICENSE
21+
- Must post the license - ✅ https://github.com/Green-Software-Foundation/if/blob/main/LICENSE
22+
- Also approved by OSI - ✅ https://opensource.org/license/MIT/
23+
24+
### Documentation
25+
- Provides basic documentation - ✅ https://if.greensoftware.foundation
26+
27+
### Other
28+
- Project site, downloads etc must support HTTPS with TLS - ✅ using GitHub to host which supports this https://github.com/Green-Software-Foundation/if
29+
- Have mechanism for discussion - ✅ github issues https://github.com/Green-Software-Foundation/if/issues, discussion board https://github.com/Green-Software-Foundation/if/discussions and mailing list at if-community@greensoftware.foundaton
30+
- Project must be maintained - ✅ actively maintaned by GSF and its members
31+
32+
## Change control
33+
### Public VCS repo
34+
- Readable public VCS repo - ✅ yes, Github https://github.com/Green-Software-Foundation/if
35+
- Track changes - ✅ yes, Git https://github.com/Green-Software-Foundation/if/commits/main
36+
- Interim versions between releases available for review - ✅ yes, interim versions actively developed and availble on the `main` branch https://github.com/Green-Software-Foundation/if
37+
38+
### Unique versioning numbering
39+
- Unique indentifier for each release - ✅ https://github.com/Green-Software-Foundation/if/releases
40+
41+
### Release notes
42+
- Human readable release notes for each release (not git log) - ✅ https://github.com/Green-Software-Foundation/if/releases
43+
- Address each publicly known vulnerability - ✅ N/A, no vulnerability reported yet
44+
45+
## Reporting
46+
### Bug reporting process
47+
- Process to submit bugs - ✅ https://github.com/Green-Software-Foundation/if/blob/main/CONTRIBUTING.md#reporting-bugs
48+
- Must acknowledge bugs (reply) submitted between 2-12 months - ✅ each bug has at least an acknowledgement or was opened by a maintainer (so acknowledged by a maintainer): https://github.com/Green-Software-Foundation/if/issues?q=is%3Aopen+is%3Aissue+label%3Abug
49+
- Publicly available archive for reports and responses - ✅ github issues: https://github.com/Green-Software-Foundation/if/issues?q=is%3Aopen+is%3Aissue+label%3Abug
50+
51+
## Vulnerability report process
52+
- Have a vulnerability report process - ✅ Included in CONTRIBUTING.md
53+
- Private vulnerability if supported must include info how to send - ✅ N/A (allowed) - no private vulnerability reporting set up but proposed
54+
- Initial response time for vulnerability submitted in last 6 months must be <= 14 days - ✅ N/A (allowed) - no vulnerabilities have yet been reported. Response times for bugs and other issues have been <14 days, post-graduation development will be by volunteers and open source developer community, so we can't guarantee a time to resolution.
55+
56+
## Quality
57+
### Working build system
58+
- Must provide a working build system - ✅ IF is a locally running NodeJS app. We do provide a devcontainer for eays environment setup. Installation is simply achieved using `npm i @grnsft/if`.
59+
60+
### Automated test suite
61+
- Have at least one automated test suite and documentation how to run it - ✅ We have a comprehensive set of unit tests and a library of becnhmark manifest files that act as integration tests. These can be run locally, and they are executed as part of our CI/CD on any PRs into `main`.
62+
63+
## New functionaility testing
64+
- Formal/informal policy for adding tests for new features - ✅ Test suite in CI/CD checks for breaking changes in PRs. Any new feature must include unit tests and an example manifest that demonstrates usage.
65+
- Evidence of policy being adhered to - ✅
66+
67+
### Warning flags
68+
- Compiler warning flags or linter tools for code quality/errors - ✅ CodeQL analysis in automated CI : https://github.com/Green-Software-Foundation/carbon-aware-sdk/blob/dev/.github/workflows/1-pr.yaml#L82
69+
- Address warnings from these tools - ✅ blocking PRs on fail
70+
71+
## Security
72+
### Secure development knowledge
73+
- At least one primary developer who knows how to design secure software - ✅ Manushak and Narek are both primary developers and have broad experience.
74+
- At least one of the project's primary developers MUST know of common kinds of errors that lead to vulnerabilities in this kind of software, as well as at least one method to counter or mitigate each of them - ✅
75+
76+
### Use basic good cryptographic practices
77+
- https://www.bestpractices.dev/en/criteria/0#0.crypto_published - ✅ n/a
78+
- https://www.bestpractices.dev/en/criteria/0#0.crypto_floss - ✅ n/a
79+
- https://www.bestpractices.dev/en/criteria/0#0.crypto_keylength - ✅ n/a
80+
- https://www.bestpractices.dev/en/criteria/0#0.crypto_working - ✅ n/a
81+
- https://www.bestpractices.dev/en/criteria/0#0.crypto_password_storage - ✅ n/a
82+
- https://www.bestpractices.dev/en/criteria/0#0.crypto_random - ✅ n/a
83+
84+
### Secured delivery against man-in-the-middle (MITM) attacks
85+
- Delivery mechanisms that counters MITM - ✅ n/a
86+
- Cyrptographic hash NOT retrived over HTTP - ✅ n/a
87+
88+
### Publicly known vulnerabilities fixed
89+
- No unpatched vulnerabilities of medium or higher severity that have been publicly known for more than 60 day - ✅ no such vulnerabilities
90+
91+
### Other security issues
92+
- Public repo doesnt leak private credential - ✅ does not do that.
93+
94+
## Analysis
95+
### Static code analysis
96+
- At least one FLOSS static code analysis tool - ✅ CodeQL is integrated into our CI/CD.
97+
- All medium and higher severity exploitable vulnerabilities discovered with static code analysis MUST be fixed in a timely way after they are confirmed - ✅ We have not yet had any exploitable vulnerabilities reported, but the GSF team will respond promptly to any disclosed issues.
98+
99+
### Dynamic code analysis
100+
- All medium and higher severity exploitable vulnerabilities discovered with dynamic code analysis MUST be fixed in a timely way after they are confirmed. - ✅ We have not yet had any exploitable vulnerabilities reported, but the GSF team will respond promptly to any disclosed issues.

adopters.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Adopters
2+
3+
Impact Framework is being used by several major organizations to introspect their software systems, as well as having a thriving open source community.
4+
5+
One adopter we will highlight in this file is Amadeus. They have used IF at a large scale, processing multi-million line manifests covering thousands of production servers. they have built their own tooling stack on top of IF. They kindly provided the following quote:
6+
7+
"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."
8+
9+
*Robin Castellon, Amadeus*

package-lock.json

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

src/__mocks__/fs/index.ts

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ export const readFile = async (filePath: string) => {
1818
throw new Error('file not found');
1919
}
2020

21+
if (filePath.includes('fail-yaml')) {
22+
throw new Error('file not found');
23+
}
24+
2125
if (filePath.includes('fail-csv-reader.csv')) {
2226
return `
2327
cpu-cores-available,≈ç≈¬˚∆∑∂´®øˆ´cpu-cores-utilized, ---- cpu-manufacturer,cpu-model-name,cpu-tdp,gpu-count,gpu-model-name,Hardware Information on AWS Documentation & Comments,instance-class,instance-storage,memory-available,platform-memory,release-date,storage-drives
@@ -76,6 +80,15 @@ export const writeFile = async (pathToFile: string, content: string) => {
7680
const fileContentObject = JSON.parse(fileContent);
7781
const parsedContent = JSON.parse(content);
7882

83+
for (const property in fileContentObject) {
84+
expect(parsedContent).toHaveProperty(property);
85+
}
86+
} else if (pathToFile.includes('package.json-npm2')) {
87+
const updatedPath = pathToFile.replace('-npm2', '');
88+
const fileContent = await fsAsync.readFile(updatedPath, 'utf8');
89+
const fileContentObject = JSON.parse(fileContent);
90+
const parsedContent = JSON.parse(content);
91+
7992
for (const property in fileContentObject) {
8093
expect(parsedContent).toHaveProperty(property);
8194
}
@@ -112,7 +125,7 @@ export const appendFile = (file: string, appendContent: string) =>
112125
`${file}${appendContent}`;
113126

114127
export const stat = async (filePath: string) => {
115-
if (filePath === 'true') {
128+
if (filePath === 'true' || filePath === 'mock-path') {
116129
return true;
117130
} else {
118131
throw new Error('File not found.');
@@ -128,7 +141,7 @@ export const access = async (directoryPath: string) => {
128141
};
129142

130143
export const unlink = async (filePath: string) => {
131-
if (filePath === 'true') {
144+
if (filePath === 'true' || filePath === 'mock-path') {
132145
return;
133146
} else {
134147
throw new Error('File not found.');
@@ -148,14 +161,19 @@ export const readdir = (directoryPath: string) => {
148161
return ['subdir/file2.yml', 'file1.yaml'];
149162
}
150163

164+
if (directoryPath.includes('mock-nested-directory')) {
165+
return ['mock-sub-directory'];
166+
}
167+
151168
return [];
152169
};
153170

154171
export const lstat = (filePath: string) => {
155172
if (
156173
filePath.includes('mock-directory') ||
157174
filePath.includes('mock-sub-directory/subdir') ||
158-
filePath === 'true'
175+
filePath === 'true' ||
176+
filePath.includes('npm-node-test')
159177
) {
160178
return {
161179
isDirectory: () => true,
@@ -169,3 +187,11 @@ export const lstat = (filePath: string) => {
169187
}
170188
return;
171189
};
190+
191+
export const rm = (path: string) => {
192+
if (path.includes('npm-node-test')) {
193+
return;
194+
} else {
195+
throw new Error('File not found.');
196+
}
197+
};

src/__mocks__/plugin/lib/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
export {Mockavizta} from './mockavizta';
2+
export {SciEmbodied} from './sci-embodied';
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import {PluginFactory} from '@grnsft/if-core/interfaces';
2+
import {PluginParams} from '@grnsft/if-core/types';
3+
4+
export const SciEmbodied = PluginFactory({
5+
metadata: {
6+
inputs: {
7+
vCPUs: {
8+
description: 'number of CPUs allocated to an application',
9+
unit: 'CPUs',
10+
'aggregation-method': {
11+
time: 'copy',
12+
component: 'copy',
13+
},
14+
},
15+
},
16+
outputs: {
17+
'embodied-carbon': {
18+
description: 'embodied carbon for a resource, scaled by usage',
19+
unit: 'gCO2eq',
20+
'aggregation-method': {
21+
time: 'sum',
22+
component: 'sum',
23+
},
24+
},
25+
},
26+
},
27+
implementation: async (inputs: PluginParams[]) => inputs,
28+
});

src/__tests__/common/util/debug-logger.test.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,4 +93,30 @@ describe('util/debug-logger: ', () => {
9393

9494
expect(debugSpy).not.toHaveBeenCalled();
9595
});
96+
97+
it('logs empty messages when the message is `\n`.', () => {
98+
console.debug('\n');
99+
100+
expect(logSpy).toHaveBeenCalledTimes(1);
101+
expect(logSpy).toHaveBeenCalledWith();
102+
});
103+
104+
it('logs messages when the message contains `**Computing`.', () => {
105+
const logMessage = '**Computing some pipline message';
106+
console.debug(logMessage);
107+
108+
expect(debugSpy).toHaveBeenCalledTimes(1);
109+
expect(debugSpy).toHaveBeenCalledWith(expect.stringContaining(logMessage));
110+
});
111+
112+
it('logs messages when the message is a number.', () => {
113+
const logMessage = 10;
114+
console.debug(logMessage);
115+
116+
expect(debugSpy).toHaveBeenCalledTimes(1);
117+
expect(debugSpy).toHaveBeenCalledWith(expect.stringContaining('DEBUG:'));
118+
expect(debugSpy).toHaveBeenCalledWith(
119+
expect.stringContaining(logMessage.toString())
120+
);
121+
});
96122
});

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

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ describe('util/fs: ', () => {
9393
expect(fsReaddirSpy).toHaveBeenCalledWith('/mock-empty-directory');
9494
});
9595

96-
it('returns YAML files in the directory', async () => {
96+
it('returns YAML files in the directory.', async () => {
9797
const fsReaddirSpy = jest.spyOn(fs, 'readdir');
9898
jest
9999
.spyOn(fs, 'lstat')
@@ -108,19 +108,29 @@ describe('util/fs: ', () => {
108108
expect(fsReaddirSpy).toHaveBeenCalledWith('/mock-directory');
109109
});
110110

111-
it('recursively finds YAML files in nested directories.', async () => {
111+
it('recursively finds YAML files if the directory exists.', async () => {
112112
const fsReaddirSpy = jest.spyOn(fs, 'readdir');
113-
jest
114-
.spyOn(fs, 'lstat')
115-
.mockResolvedValue({isDirectory: () => false} as any);
116-
const result = await getYamlFiles('/mock-sub-directory');
113+
114+
jest.spyOn(fs, 'lstat').mockImplementation((path: any) => {
115+
return Promise.resolve({
116+
isDirectory: () => {
117+
if (path.endsWith('.yaml') || path.endsWith('.yml')) {
118+
return false;
119+
}
120+
return true;
121+
},
122+
} as any);
123+
});
124+
125+
const path = '/mock-nested-directory';
126+
const result = await getYamlFiles(path);
117127

118128
expect.assertions(2);
119129
expect(result).toEqual([
120-
'/mock-sub-directory/subdir/file2.yml',
121-
'/mock-sub-directory/file1.yaml',
130+
'/mock-nested-directory/mock-sub-directory/subdir/file2.yml',
131+
'/mock-nested-directory/mock-sub-directory/file1.yaml',
122132
]);
123-
expect(fsReaddirSpy).toHaveBeenCalledWith('/mock-directory');
133+
expect(fsReaddirSpy).toHaveBeenCalledWith(path);
124134
});
125135
});
126136

0 commit comments

Comments
 (0)