2017-02-06 13:40:28 -05:00
|
|
|
// Imports
|
|
|
|
import * as fs from 'fs';
|
|
|
|
import * as path from 'path';
|
|
|
|
import * as shell from 'shelljs';
|
2017-06-24 18:40:04 -04:00
|
|
|
import {HIDDEN_DIR_PREFIX} from '../common/constants';
|
2017-02-06 13:40:28 -05:00
|
|
|
import {GithubPullRequests} from '../common/github-pull-requests';
|
2017-02-27 14:04:43 -05:00
|
|
|
import {assertNotMissingOrEmpty} from '../common/utils';
|
2017-02-06 13:40:28 -05:00
|
|
|
|
|
|
|
// Classes
|
|
|
|
export class BuildCleaner {
|
|
|
|
// Constructor
|
2017-02-27 15:40:13 -05:00
|
|
|
constructor(protected buildsDir: string, protected repoSlug: string, protected githubToken: string) {
|
2017-02-27 14:04:43 -05:00
|
|
|
assertNotMissingOrEmpty('buildsDir', buildsDir);
|
|
|
|
assertNotMissingOrEmpty('repoSlug', repoSlug);
|
2017-02-27 15:40:13 -05:00
|
|
|
assertNotMissingOrEmpty('githubToken', githubToken);
|
2017-02-06 13:40:28 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// Methods - Public
|
|
|
|
public cleanUp(): Promise<void> {
|
|
|
|
return Promise.all([
|
|
|
|
this.getExistingBuildNumbers(),
|
|
|
|
this.getOpenPrNumbers(),
|
|
|
|
]).then(([existingBuilds, openPrs]) => this.removeUnnecessaryBuilds(existingBuilds, openPrs));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Methods - Protected
|
|
|
|
protected getExistingBuildNumbers(): Promise<number[]> {
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
fs.readdir(this.buildsDir, (err, files) => {
|
|
|
|
if (err) {
|
|
|
|
return reject(err);
|
|
|
|
}
|
|
|
|
|
|
|
|
const buildNumbers = files.
|
2017-06-24 18:40:04 -04:00
|
|
|
map(name => name.replace(HIDDEN_DIR_PREFIX, '')). // Remove the "hidden dir" prefix
|
|
|
|
map(Number). // Convert string to number
|
|
|
|
filter(Boolean); // Ignore NaN (or 0), because they are not builds
|
2017-02-06 13:40:28 -05:00
|
|
|
|
|
|
|
resolve(buildNumbers);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
protected getOpenPrNumbers(): Promise<number[]> {
|
2017-02-28 07:17:20 -05:00
|
|
|
const githubPullRequests = new GithubPullRequests(this.githubToken, this.repoSlug);
|
2017-02-06 13:40:28 -05:00
|
|
|
|
|
|
|
return githubPullRequests.
|
|
|
|
fetchAll('open').
|
|
|
|
then(prs => prs.map(pr => pr.number));
|
|
|
|
}
|
|
|
|
|
|
|
|
protected removeDir(dir: string) {
|
|
|
|
try {
|
2017-06-24 18:40:04 -04:00
|
|
|
if (shell.test('-d', dir)) {
|
|
|
|
// Undocumented signature (see https://github.com/shelljs/shelljs/pull/663).
|
|
|
|
(shell as any).chmod('-R', 'a+w', dir);
|
|
|
|
shell.rm('-rf', dir);
|
|
|
|
}
|
2017-02-06 13:40:28 -05:00
|
|
|
} catch (err) {
|
|
|
|
console.error(`ERROR: Unable to remove '${dir}' due to:`, err);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected removeUnnecessaryBuilds(existingBuildNumbers: number[], openPrNumbers: number[]) {
|
|
|
|
const toRemove = existingBuildNumbers.filter(num => !openPrNumbers.includes(num));
|
|
|
|
|
|
|
|
console.log(`Existing builds: ${existingBuildNumbers.length}`);
|
|
|
|
console.log(`Open pull requests: ${openPrNumbers.length}`);
|
|
|
|
console.log(`Removing ${toRemove.length} build(s): ${toRemove.join(', ')}`);
|
|
|
|
|
2017-06-24 18:40:04 -04:00
|
|
|
// Try removing public dirs.
|
2017-02-06 13:40:28 -05:00
|
|
|
toRemove.
|
|
|
|
map(num => path.join(this.buildsDir, String(num))).
|
|
|
|
forEach(dir => this.removeDir(dir));
|
2017-06-24 18:40:04 -04:00
|
|
|
|
|
|
|
// Try removing hidden dirs.
|
|
|
|
toRemove.
|
|
|
|
map(num => path.join(this.buildsDir, HIDDEN_DIR_PREFIX + String(num))).
|
|
|
|
forEach(dir => this.removeDir(dir));
|
2017-02-06 13:40:28 -05:00
|
|
|
}
|
|
|
|
}
|