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
|
#!/usr/bin/env node
/*
This script takes two parameters or three environment variables:
{CI job name|$CIRCLE_JOB} {SHA1...SHA1|$CIRCLE_MERGE_BASE...$CIRCLE_SHA1}
The flow of this script:
- List of files changed in PR: `git diff --name-only start...end`
- Extract list into array.
- Remove items from array if they match:
- Global ignore list.
- Other platform ignore lists.
- If array still contains items, do not authorize skipping CI job.
- Else if array is empty, skip CI job.
*/
const execSync = require('child_process').execSync;
const _ = require('lodash');
const minimatch = require("minimatch");
console.step = _.partial(console.log, '\n\033[1m\033[36m*', _, '\033[0m');
// BUILD PARAMETERS
const CI_JOB_NAME = process.argv[2] || process.env.CIRCLE_JOB;
if (!CI_JOB_NAME) { console.error('You must specify the name of a CI job as a parameter or environment variable.'); process.exit(1); }
const COMMIT_RANGE = process.argv[3] || `${process.env.CIRCLE_MERGE_BASE}...${process.env.CIRCLE_SHA1}`;
if (!COMMIT_RANGE || COMMIT_RANGE.includes('undefined')) { console.error('You must specify a range of commits to check for changed files in as a parameter or environment variable.'); process.exit(1); }
// FILE SKIPPING PATTERNS
const ALWAYS_SKIPPABLE_FILES = [
'**/CHANGELOG.md',
'**/README.md',
'**/CONTRIBUTING.md',
'**/DEVELOPING.md',
'**/INSTALL.md',
'**/*.podspec'
]
const ANDROID_FILES = [
'platform/android/**'
]
const IOS_FILES = [
'platform/ios/**',
'platform/darwin/**'
]
const MACOS_FILES = [
'platform/macos/**',
'platform/darwin/**'
]
const OTHER_PLATFORMS = [
'platform/glfw/**',
'platform/linux/**',
'platform/node/**',
'platform/qt/**',
'benchmark/**',
'test/**'
]
function skippableFilePatternsForCIJob(job) {
if (job.startsWith('ios')) {
return _.concat(ALWAYS_SKIPPABLE_FILES, ANDROID_FILES, MACOS_FILES, OTHER_PLATFORMS);
} else if (job.startsWith('android')) {
return _.concat(ALWAYS_SKIPPABLE_FILES, IOS_FILES, MACOS_FILES, OTHER_PLATFORMS);
} else if (job.startsWith('macos')) {
return _.concat(ALWAYS_SKIPPABLE_FILES, ANDROID_FILES, IOS_FILES, OTHER_PLATFORMS);
} else {
return ALWAYS_SKIPPABLE_FILES;
}
}
console.step(`Getting list of files changed between ${COMMIT_RANGE}`);
let changedFiles = execSync(`git diff --name-only ${COMMIT_RANGE}`)
.toString()
.trim()
.split('\n');
changedFiles = _.compact(changedFiles);
console.log(`${changedFiles.length} total files changed.`);
// Filter the changed files array to remove files that are irrelevant to the specified CI job.
_.remove(changedFiles, function(changedFile) {
for (const skippableFilePattern of skippableFilePatternsForCIJob(CI_JOB_NAME)) {
if (minimatch(changedFile, skippableFilePattern, { dot: true, nocase: true })) {
return true;
}
}
return false;
});
if (changedFiles.length) {
console.log(`Found ${changedFiles.length} unskippable changed file${changedFiles.length > 1 ? 's':''} for ${CI_JOB_NAME}:\n`, changedFiles);
} else {
console.log(`Found no relevant changed files, so it's safe to skip the remainder of this CI job.`)
if (process.env.CIRCLECI) {
console.step('Aborting CI job');
execSync(`circleci step halt`, {stdio: 'inherit'});
}
}
|