Skip to content

Commit 0602cec

Browse files
Merge pull request #77 from VirdocsSoftware/release/v2.11.0
release v2.11.0 to main
2 parents b2f8aae + a228b6d commit 0602cec

3 files changed

Lines changed: 112 additions & 1 deletion

File tree

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
name: "Static Analysis"
2+
description: "Runs static analysis on the code"
3+
4+
runs:
5+
using: "composite"
6+
steps:
7+
- name: Checkout Code
8+
uses: actions/checkout@v4
9+
- name: Scan workflow yml files
10+
run: |
11+
echo "Running the following script: ${{ github.action_path }}/scan_github_actions.js"
12+
echo "With the current working directory: $(pwd)"
13+
node ${{ github.action_path }}/scan_github_actions.js
14+
shell: bash
15+
working-directory: ${{ github.workspace }}
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
class StaticAnalysis {
2+
constructor(dataProvider, process) {
3+
this.dataProvider = dataProvider;
4+
this.process = process;
5+
}
6+
7+
isCommitHash(ref) {
8+
return /^[0-9a-f]{40}$/.test(ref);
9+
}
10+
11+
findYamlFiles(dir) {
12+
let results = [];
13+
const list = this.dataProvider.readDirectory(dir);
14+
list.forEach(file => {
15+
const fullPath = this.dataProvider.path.join(dir, file);
16+
const stat = this.dataProvider.getFileStats(fullPath);
17+
if (stat && stat.isDirectory()) {
18+
results = results.concat(this.findYamlFiles(fullPath));
19+
} else if (file.endsWith('.yml') || file.endsWith('.yaml')) {
20+
results.push(fullPath);
21+
}
22+
});
23+
return results;
24+
}
25+
26+
scanFile(filePath) {
27+
const content = this.dataProvider.readFile(filePath);
28+
const regex = /uses:\s*[\w-]+\/[\w-]+@([\w-.]+)/g;
29+
let match;
30+
let warnings = [];
31+
while ((match = regex.exec(content)) !== null) {
32+
const ref = match[1];
33+
if (!this.isCommitHash(ref)) {
34+
warnings.push(`Warning: In file ${filePath}, '${match[0]}' does not use a commit hash.`);
35+
}
36+
}
37+
return warnings;
38+
}
39+
40+
run() {
41+
const workflowDir = this.dataProvider.path.join(this.process.cwd(), '.github', 'workflows');
42+
if (!this.dataProvider.fileExists(workflowDir)) {
43+
console.error(`Error: Directory ${workflowDir} does not exist.`);
44+
this.process.exit(1);
45+
}
46+
47+
const yamlFiles = this.findYamlFiles(workflowDir);
48+
let allWarnings = [];
49+
50+
yamlFiles.forEach(filePath => {
51+
const warnings = this.scanFile(filePath);
52+
allWarnings = allWarnings.concat(warnings);
53+
});
54+
55+
if (allWarnings.length > 0) {
56+
allWarnings.forEach(warning => console.warn(warning));
57+
console.log('To fix these issues, refer to the solution in the following Jira ticket: https://virdocs.atlassian.net/browse/RD-2964');
58+
this.process.exit(0); // TODO: Exit with non-zero code if warnings are found
59+
} else {
60+
console.log('No issues found. All action calls use commit hashes.');
61+
this.process.exit(0);
62+
}
63+
}
64+
}
65+
66+
class DataProvider {
67+
constructor(fs, path) {
68+
this.fs = fs;
69+
this.path = path;
70+
}
71+
72+
readDirectory(dir) {
73+
return this.fs.readdirSync(dir);
74+
}
75+
76+
readFile(filePath) {
77+
return this.fs.readFileSync(filePath, 'utf8');
78+
}
79+
80+
fileExists(filePath) {
81+
return this.fs.existsSync(filePath);
82+
}
83+
84+
getFileStats(filePath) {
85+
return this.fs.statSync(filePath);
86+
}
87+
}
88+
89+
// Dependency injection
90+
const fs = require('fs');
91+
const path = require('path');
92+
const process = require('process');
93+
94+
const dataProvider = new DataProvider(fs, path);
95+
const staticAnalysis = new StaticAnalysis(dataProvider, process);
96+
staticAnalysis.run();

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "github-actions",
3-
"version": "2.10.0",
3+
"version": "2.11.0",
44
"description": "Used to store GitHub actions for use across the enterprise",
55
"scripts": {
66
"test": "./tooling/scripts/run_tests.sh",

0 commit comments

Comments
 (0)