Skip to content

Commit 73a38c6

Browse files
darangiaminya
authored andcommitted
added tests
1 parent 41806c5 commit 73a38c6

File tree

10 files changed

+521
-0
lines changed

10 files changed

+521
-0
lines changed
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
const fetch = require('node-fetch');
2+
const npmCheck = require('npm-check');
3+
4+
// this may be updated to use github releases instead
5+
const apm = async function({ dependencies, packageDependencies }) {
6+
try {
7+
console.log('Checking apm registry...');
8+
const coreDependencies = Object.keys(dependencies).filter(dependency => {
9+
// all core packages point to a remote url
10+
return dependencies[dependency].match(new RegExp('^https?://'));
11+
});
12+
13+
const promises = coreDependencies.map(async dependency => {
14+
return fetch(`https://atom.io/api/packages/${dependency}`)
15+
.then(res => res.json())
16+
.then(res => res)
17+
.catch(ex => console.log(ex.message));
18+
});
19+
20+
const packages = await Promise.all(promises);
21+
const outdatedPackages = [];
22+
packages.map(dependency => {
23+
if (dependency.hasOwnProperty('name')) {
24+
const latestVersion = dependency.releases.latest;
25+
const installed = packageDependencies[dependency.name];
26+
if (latestVersion > installed) {
27+
outdatedPackages.push({
28+
moduleName: dependency.name,
29+
latest: dependency.releases.latest,
30+
isCorePackage: true,
31+
installed
32+
});
33+
}
34+
}
35+
});
36+
37+
console.log(`${outdatedPackages.length} outdated package(s) found`);
38+
39+
return outdatedPackages;
40+
} catch (ex) {
41+
console.error(`An error occured: ${ex.message}`);
42+
}
43+
};
44+
45+
const npm = async function(cwd) {
46+
try {
47+
console.log('Checking npm registry...');
48+
49+
const currentState = await npmCheck({
50+
cwd,
51+
ignoreDev: true,
52+
skipUnused: true
53+
});
54+
const outdatedPackages = currentState
55+
.get('packages')
56+
.filter(p => {
57+
if (p.packageJson && p.latest && p.installed) {
58+
return p.latest > p.installed;
59+
}
60+
})
61+
.map(({ packageJson, installed, moduleName, latest }) => ({
62+
packageJson,
63+
installed,
64+
moduleName,
65+
latest,
66+
isCorePackage: false
67+
}));
68+
69+
console.log(`${outdatedPackages.length} outdated package(s) found`);
70+
71+
return outdatedPackages;
72+
} catch (ex) {
73+
console.error(`An error occured: ${ex.message}`);
74+
}
75+
};
76+
77+
module.exports = {
78+
apm,
79+
npm
80+
};

script/lib/update-dependency/git.js

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
const git = (git, repositoryRootPath) => {
2+
const path = require('path');
3+
const packageJsonFilePath = path.join(repositoryRootPath, 'package.json');
4+
const packageLockFilePath = path.join(
5+
repositoryRootPath,
6+
'package-lock.json'
7+
);
8+
try {
9+
git.getRemotes((err, remotes) => {
10+
if (!err && !remotes.map(({ name }) => name).includes('ATOM')) {
11+
git.addRemote(
12+
'ATOM',
13+
`https://atom:${process.env.AUTH_TOKEN}@github.com/atom/atom.git/`
14+
);
15+
}
16+
});
17+
} catch (ex) {
18+
console.log(ex.message);
19+
}
20+
return {
21+
switchToMaster: async function() {
22+
const { current } = await git.branch();
23+
if (current !== 'master') {
24+
await git.checkout('master');
25+
}
26+
},
27+
makeBranch: async function(dependency) {
28+
const newBranch = `${dependency.moduleName}-${dependency.latest}`;
29+
const { branches } = await git.branch();
30+
const { files } = await git.status();
31+
if (files.length > 0) {
32+
await git.reset('hard');
33+
}
34+
const found = Object.keys(branches).find(
35+
branch => branch.indexOf(newBranch) > -1
36+
);
37+
found
38+
? await git.checkout(found)
39+
: await git.checkoutLocalBranch(newBranch);
40+
return { found, newBranch };
41+
},
42+
createCommit: async function({ moduleName, latest }) {
43+
try {
44+
const commitMessage = `:arrow_up: ${moduleName}@${latest}`;
45+
await git.add([packageJsonFilePath, packageLockFilePath]);
46+
await git.commit(commitMessage);
47+
} catch (ex) {
48+
throw Error(ex.message);
49+
}
50+
},
51+
publishBranch: async function(branch) {
52+
try {
53+
await git.push('ATOM', branch);
54+
} catch (ex) {
55+
throw Error(ex.message);
56+
}
57+
},
58+
deleteBranch: async function(branch) {
59+
try {
60+
await git.deleteLocalBranch(branch, true);
61+
} catch (ex) {
62+
throw Error(ex.message);
63+
}
64+
}
65+
};
66+
};
67+
module.exports = git;

script/lib/update-dependency/main.js

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
/* eslint-disable camelcase */
2+
const simpleGit = require('simple-git');
3+
const path = require('path');
4+
5+
const { repositoryRootPath } = require('../../config');
6+
const packageJSON = require(path.join(repositoryRootPath, 'package.json'));
7+
const git = simpleGit(repositoryRootPath);
8+
const { createPR, findPR, addLabel } = require('./pull-request');
9+
const runApmInstall = require('../run-apm-install');
10+
const {
11+
makeBranch,
12+
createCommit,
13+
switchToMaster,
14+
publishBranch,
15+
deleteBranch
16+
} = require('./git')(git, repositoryRootPath);
17+
const { updatePackageJson, sleep } = require('./util')(repositoryRootPath);
18+
const fetchOutdatedDependencies = require('./fetch-outdated-dependencies');
19+
20+
module.exports = async function() {
21+
try {
22+
// ensure we are on master
23+
await switchToMaster();
24+
const failedBumps = [];
25+
const successfullBumps = [];
26+
const outdateDependencies = [
27+
...(await fetchOutdatedDependencies.npm(repositoryRootPath)),
28+
...(await fetchOutdatedDependencies.apm(packageJSON))
29+
];
30+
const totalDependencies = outdateDependencies.length;
31+
const pendingPRs = [];
32+
for (const dependency of outdateDependencies) {
33+
const { found, newBranch } = await makeBranch(dependency);
34+
if (found) {
35+
console.log(`Branch was found ${found}`);
36+
console.log('checking if a PR already exists');
37+
const {
38+
data: { total_count }
39+
} = await findPR(dependency, newBranch);
40+
if (total_count > 0) {
41+
console.log(`pull request found!`);
42+
} else {
43+
console.log(`pull request not found!`);
44+
const pr = { dependency, branch: newBranch, branchIsRemote: false };
45+
// confirm if branch found is a local branch
46+
if (found.indexOf('remotes') === -1) {
47+
await publishBranch(found);
48+
} else {
49+
pr.branchIsRemote = true;
50+
}
51+
pendingPRs.push(pr);
52+
}
53+
} else {
54+
await updatePackageJson(dependency);
55+
runApmInstall(repositoryRootPath, false);
56+
await createCommit(dependency);
57+
await publishBranch(newBranch);
58+
pendingPRs.push({
59+
dependency,
60+
branch: newBranch,
61+
branchIsRemote: false
62+
});
63+
}
64+
65+
await switchToMaster();
66+
}
67+
// create PRs here
68+
for (const { dependency, branch, branchIsRemote } of pendingPRs) {
69+
const { status, data = {} } = await createPR(dependency, branch);
70+
if (status === 201) {
71+
successfullBumps.push(dependency);
72+
await addLabel(data.number);
73+
} else {
74+
failedBumps.push(dependency);
75+
}
76+
77+
if (!branchIsRemote) {
78+
await deleteBranch(branch);
79+
}
80+
// https://developer.github.com/v3/guides/best-practices-for-integrators/#dealing-with-abuse-rate-limits
81+
await sleep(2000);
82+
}
83+
console.table([
84+
{
85+
totalDependencies,
86+
totalSuccessfullBumps: successfullBumps.length,
87+
totalFailedBumps: failedBumps.length
88+
}
89+
]);
90+
console.log('Successfull bumps');
91+
console.table(successfullBumps);
92+
console.log('Failed bumps');
93+
console.table(failedBumps);
94+
} catch (ex) {
95+
console.log(ex.message);
96+
}
97+
};
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
const path = require('path');
2+
const fetchOutdatedDependencies = require('../fetch-outdated-dependencies');
3+
const { nativeDependencies } = require('./helpers');
4+
const repositoryRootPath = path.resolve('.', 'fixtures', 'dummy');
5+
const packageJSON = require(path.join(repositoryRootPath, 'package.json'));
6+
7+
describe('Fetch outdated dependencies', function() {
8+
it('should fetch outdated native dependencies', async () => {
9+
spyOn(fetchOutdatedDependencies, 'npm').andReturn(
10+
Promise.resolve(nativeDependencies)
11+
);
12+
13+
expect(await fetchOutdatedDependencies.npm(repositoryRootPath)).toEqual(
14+
nativeDependencies
15+
);
16+
});
17+
18+
it('should fetch outdated core dependencies', async () => {
19+
spyOn(fetchOutdatedDependencies, 'apm').andReturn(
20+
Promise.resolve(nativeDependencies)
21+
);
22+
23+
expect(await fetchOutdatedDependencies.apm(packageJSON)).toEqual(
24+
nativeDependencies
25+
);
26+
});
27+
});
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Subproject commit 526c50836158b43d38cbaf11ad305fa8a6f43d1f
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
{
2+
"name": "test",
3+
"version": "1.0.0",
4+
"description": "just test",
5+
"main": "index.js",
6+
"dependencies": {
7+
"spell-check": "https://www.atom.io/api/packages/spell-check/versions/0.79.1/tarball",
8+
"status-bar": "https://www.atom.io/api/packages/status-bar/versions/2.8.17/tarball",
9+
"styleguide": "https://www.atom.io/api/packages/styleguide/versions/1.49.12/tarball",
10+
"symbols-view": "https://www.atom.io/api/packages/symbols-view/versions/0.118.5/tarball",
11+
"@atom/watcher": "1.3.1",
12+
"clear-cut": "^2.0.3",
13+
"dedent": "^1.0.0",
14+
"devtron": "1.2.6"
15+
},
16+
"packageDependencies": {
17+
"spell-check": "0.79.1",
18+
"status-bar": "2.8.17",
19+
"styleguide": "1.49.12",
20+
"symbols-view": "0.118.5"
21+
},
22+
"scripts": {
23+
"test": "echo \"Error: no test specified\" && exit 1"
24+
},
25+
"author": "darangi",
26+
"license": "ISC"
27+
}
28+

0 commit comments

Comments
 (0)