forked from openkfw/TruBudget
-
Notifications
You must be signed in to change notification settings - Fork 0
/
dangerfile.js
186 lines (167 loc) · 6.1 KB
/
dangerfile.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
import { danger, warn } from "danger";
const { includes } = require("lodash");
const apiSources = danger.git.fileMatch("api/src/**/*.ts");
const blockchainSources = danger.git.fileMatch("blockchain/src/*");
const frontendRootSources = danger.git.fileMatch("frontend/src/*.*");
const frontendPageSources = danger.git.fileMatch("frontend/src/pages/**/*.js");
const frontendLanguageSources = danger.git.fileMatch(
"frontend/src/languages/*"
);
const provisioningSources = danger.git.fileMatch("provisioning/src/**/*");
const e2eTestSources = danger.git.fileMatch("e2e-test/cypress/**/*");
const excelExportSources = danger.git.fileMatch("excel-export/src/**/*");
const envExampleFiles = danger.git.modified_files.filter((path) =>
path.endsWith(".env_example")
);
envExampleFiles.forEach((file) =>
getChanges(file).then((changes) => {
const rootSecrets = changes.reduce((res, { content, type }) => {
if (content.includes("ROOT_SECRET") && type === "add")
if (content.includes("'") || content.includes('"'))
res.push(content.split("=")[1].slice(1, -1));
else res.push(content.split("=")[1]);
return res;
}, []);
const orgaVaultSecrets = changes.reduce((res, { content, type }) => {
if (content.includes("ORGANIZATION_VAULT_SECRET") && type === "add")
if (content.includes("'") || content.includes('"'))
res.push(content.split("=")[1].slice(1, -1));
else res.push(content.split("=")[1]);
return res;
}, []);
if (!rootSecrets.every((val, i, arr) => val === "root-secret")) {
warn("Make sure the Root-Secret is the same in all .env_example files");
}
if (!orgaVaultSecrets.every((val, i, arr) => val === "secret")) {
warn(
"Make sure the Organization-Vault-Secret is the same in all .env_example files"
);
}
})
);
const title = danger.github.pr.title.toLowerCase();
const trivialPR = title.includes("refactor");
const changelogChanges = includes(danger.git.modified_files, "CHANGELOG.md");
const frontendChanges =
frontendRootSources.edited ||
frontendPageSources.edited ||
frontendLanguageSources.edited;
const apiResourceHasChanged = apiResourceChangesDetected();
function apiResourceChangesDetected() {
const projectSource = danger.git.fileMatch(
"api/src/service/domain/workflow/project.ts"
);
const subprojectSource = danger.git.fileMatch(
"api/src/service/domain/workflow/subproject.ts"
);
const workflowitemSource = danger.git.fileMatch(
"api/src/service/domain/workflow/workflowitem.ts"
);
if (
projectSource.edited ||
subprojectSource.edited ||
workflowitemSource.edited
) {
return true;
} else {
return false;
}
}
function deepFlat(inputArray) {
return inputArray.reduce(
(accumulator, value) =>
Array.isArray(value)
? accumulator.concat(deepFlat(value))
: accumulator.concat(value),
[]
);
}
async function getChanges(filepath) {
const files = danger.git.fileMatch(filepath);
const { edited } = files.getKeyedPaths((paths) => paths);
const chunksArray = await Promise.all(
edited.map(async (path) => {
const changes = await Promise.resolve(
danger.git.structuredDiffForFile(path)
);
return changes;
})
);
const chunks = deepFlat(chunksArray.map((chunk) => chunk.chunks));
const changes = deepFlat(chunks.map((chunk) => chunk.changes));
return changes;
}
function getContentByType(changes) {
const additions = changes
.filter((change) => change.add)
.map((change) => change.content);
const deletions = changes
.filter((change) => change.del)
.map((change) => change.content);
const normal = changes
.filter((change) => change.normal)
.map((change) => change.content);
return {
additions,
deletions,
normal,
};
}
// When there are app-changes and it's not a PR marked as trivial, expect there to be CHANGELOG changes.
if (
(frontendChanges ||
apiSources.edited ||
blockchainSources.edited ||
frontendRootSources.edited ||
provisioningSources.edited ||
e2eTestSources.edited) &&
!trivialPR &&
!changelogChanges
) {
warn("No CHANGELOG added.");
}
// If there are changes in the UI (except language files)
// and PR is not marked as trivial, expect there to be E2E-test updates
if (
(frontendRootSources.edited || frontendPageSources.edited) &&
!e2eTestSources.edited &&
!trivialPR
) {
warn(
"There were changes in the frontend, but no E2E-test was added or modified!"
);
}
// Async part to check for changes in files
(async function () {
// Warn if there were console logs added in the API
const apiChanges = await getChanges("api/**/*.ts");
const { additions: apiAdditions } = getContentByType(apiChanges);
if (apiAdditions.some((addition) => addition.includes("console.log"))) {
warn("There are new console logs in the API!");
}
// Warn if there were only keyword added in the e2e-test
const e2etestChanges = await getChanges("e2e-test/cypress/integration/*.js");
const { additions: e2etestAdditions } = getContentByType(e2etestChanges);
if (e2etestAdditions.some((addition) => addition.includes(".only"))) {
warn("The '.only' keyword was added to the e2e-tests");
}
// Warn if there where properties added to a resource(project/subproject/workflowitem) and
// excel-export is not adapted
if (apiResourceHasChanged && !excelExportSources.edited) {
warn(
"One of the resource files in the api domain layer (project.ts/subproject.ts/workflowitem.ts) were edited. " +
"If a new property was added the excel-export project has to be adapted."
);
}
const allChanges = await getChanges("**/*");
const { additions: allAdditions } = getContentByType(allChanges);
// Warn if there was a TODO added in any file
if (allAdditions.some((addition) => addition.includes("TODO"))) {
warn("A new TODO was added.");
}
// Warn if there was an id added in any file
const reg = /[a-z0-9]{8}[-][a-z0-9]{4}[-][a-z0-9]{4}[-][a-z0-9]{4}[-][a-z0-9]{12}/;
if (allAdditions.some((addition) => reg.test(addition))) {
warn("It looks like an ID was added. Please make sure it is not a secret.");
}
})();