Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Set up lighthouse artifact feed for our fork #13

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .github/pull.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
version: "1"
rules: # Array of rules
- base: master # Required. Target branch
upstream: atom:master # Required. Must be in the same fork network.
mergeMethod: rebase # Optional, one of [none, merge, squash, rebase, hardreset], Default: none.
mergeUnstable: false # Optional, merge pull request even when the mergeable_state is not clean. Default: false
label: ":arrow_heading_down: pull upstream" # Optional
80 changes: 80 additions & 0 deletions script/lib/update-dependency/fetch-outdated-dependencies.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
const fetch = require('node-fetch');
const npmCheck = require('npm-check');

// this may be updated to use github releases instead
const apm = async function({ dependencies, packageDependencies }) {
try {
console.log('Checking apm registry...');
const coreDependencies = Object.keys(dependencies).filter(dependency => {
// all core packages point to a remote url
return dependencies[dependency].match(new RegExp('^https?://'));
});

const promises = coreDependencies.map(async dependency => {
return fetch(`https://atom.io/api/packages/${dependency}`)
.then(res => res.json())
.then(res => res)
.catch(ex => console.log(ex.message));
});

const packages = await Promise.all(promises);
const outdatedPackages = [];
packages.map(dependency => {
if (dependency.hasOwnProperty('name')) {
const latestVersion = dependency.releases.latest;
const installed = packageDependencies[dependency.name];
if (latestVersion > installed) {
outdatedPackages.push({
moduleName: dependency.name,
latest: dependency.releases.latest,
isCorePackage: true,
installed
});
}
}
});

console.log(`${outdatedPackages.length} outdated package(s) found`);

return outdatedPackages;
} catch (ex) {
console.error(`An error occured: ${ex.message}`);
}
};

const npm = async function(cwd) {
try {
console.log('Checking npm registry...');

const currentState = await npmCheck({
cwd,
ignoreDev: true,
skipUnused: true
});
const outdatedPackages = currentState
.get('packages')
.filter(p => {
if (p.packageJson && p.latest && p.installed) {
return p.latest > p.installed;
}
})
.map(({ packageJson, installed, moduleName, latest }) => ({
packageJson,
installed,
moduleName,
latest,
isCorePackage: false
}));

console.log(`${outdatedPackages.length} outdated package(s) found`);

return outdatedPackages;
} catch (ex) {
console.error(`An error occured: ${ex.message}`);
}
};

module.exports = {
apm,
npm
};
67 changes: 67 additions & 0 deletions script/lib/update-dependency/git.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
const git = (git, repositoryRootPath) => {
const path = require('path');
const packageJsonFilePath = path.join(repositoryRootPath, 'package.json');
const packageLockFilePath = path.join(
repositoryRootPath,
'package-lock.json'
);
try {
git.getRemotes((err, remotes) => {
if (!err && !remotes.map(({ name }) => name).includes('ATOM')) {
git.addRemote(
'ATOM',
`https://atom:${process.env.AUTH_TOKEN}@github.com/atom/atom.git/`
);
}
});
} catch (ex) {
console.log(ex.message);
}
return {
switchToMaster: async function() {
const { current } = await git.branch();
if (current !== 'master') {
await git.checkout('master');
}
},
makeBranch: async function(dependency) {
const newBranch = `${dependency.moduleName}-${dependency.latest}`;
const { branches } = await git.branch();
const { files } = await git.status();
if (files.length > 0) {
await git.reset('hard');
}
const found = Object.keys(branches).find(
branch => branch.indexOf(newBranch) > -1
);
found
? await git.checkout(found)
: await git.checkoutLocalBranch(newBranch);
return { found, newBranch };
},
createCommit: async function({ moduleName, latest }) {
try {
const commitMessage = `:arrow_up: ${moduleName}@${latest}`;
await git.add([packageJsonFilePath, packageLockFilePath]);
await git.commit(commitMessage);
} catch (ex) {
throw Error(ex.message);
}
},
publishBranch: async function(branch) {
try {
await git.push('ATOM', branch);
} catch (ex) {
throw Error(ex.message);
}
},
deleteBranch: async function(branch) {
try {
await git.deleteLocalBranch(branch, true);
} catch (ex) {
throw Error(ex.message);
}
}
};
};
module.exports = git;
3 changes: 3 additions & 0 deletions script/lib/update-dependency/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const run = require('./main');

run();
97 changes: 97 additions & 0 deletions script/lib/update-dependency/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/* eslint-disable camelcase */
const simpleGit = require('simple-git');
const path = require('path');

const { repositoryRootPath } = require('../../config');
const packageJSON = require(path.join(repositoryRootPath, 'package.json'));
const git = simpleGit(repositoryRootPath);
const { createPR, findPR, addLabel } = require('./pull-request');
const runApmInstall = require('../run-apm-install');
const {
makeBranch,
createCommit,
switchToMaster,
publishBranch,
deleteBranch
} = require('./git')(git, repositoryRootPath);
const { updatePackageJson, sleep } = require('./util')(repositoryRootPath);
const fetchOutdatedDependencies = require('./fetch-outdated-dependencies');

module.exports = async function() {
try {
// ensure we are on master
await switchToMaster();
const failedBumps = [];
const successfullBumps = [];
const outdateDependencies = [
...(await fetchOutdatedDependencies.npm(repositoryRootPath)),
...(await fetchOutdatedDependencies.apm(packageJSON))
];
const totalDependencies = outdateDependencies.length;
const pendingPRs = [];
for (const dependency of outdateDependencies) {
const { found, newBranch } = await makeBranch(dependency);
if (found) {
console.log(`Branch was found ${found}`);
console.log('checking if a PR already exists');
const {
data: { total_count }
} = await findPR(dependency, newBranch);
if (total_count > 0) {
console.log(`pull request found!`);
} else {
console.log(`pull request not found!`);
const pr = { dependency, branch: newBranch, branchIsRemote: false };
// confirm if branch found is a local branch
if (found.indexOf('remotes') === -1) {
await publishBranch(found);
} else {
pr.branchIsRemote = true;
}
pendingPRs.push(pr);
}
} else {
await updatePackageJson(dependency);
runApmInstall(repositoryRootPath, false);
await createCommit(dependency);
await publishBranch(newBranch);
pendingPRs.push({
dependency,
branch: newBranch,
branchIsRemote: false
});
}

await switchToMaster();
}
// create PRs here
for (const { dependency, branch, branchIsRemote } of pendingPRs) {
const { status, data = {} } = await createPR(dependency, branch);
if (status === 201) {
successfullBumps.push(dependency);
await addLabel(data.number);
} else {
failedBumps.push(dependency);
}

if (!branchIsRemote) {
await deleteBranch(branch);
}
// https://developer.github.com/v3/guides/best-practices-for-integrators/#dealing-with-abuse-rate-limits
await sleep(2000);
}
console.table([
{
totalDependencies,
totalSuccessfullBumps: successfullBumps.length,
totalFailedBumps: failedBumps.length
}
]);
console.log('Successfull bumps');
console.table(successfullBumps);
console.log('Failed bumps');
console.table(failedBumps);
} catch (ex) {
console.log(ex.message);
}
};
40 changes: 40 additions & 0 deletions script/lib/update-dependency/pull-request.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
const { request } = require('@octokit/request');

const requestWithAuth = request.defaults({
baseUrl: 'https://api.github.com',
headers: {
'user-agent': 'atom',
authorization: `token ${process.env.AUTH_TOKEN}`
},
owner: 'atom',
repo: 'atom'
});

module.exports = {
createPR: async (
{ moduleName, isCorePackage, latest, installed },
branch
) => {
let description = `Bumps ${moduleName} from ${installed} to ${latest}`;
if (isCorePackage) {
description = `*List of changes between ${moduleName}@${installed} and ${moduleName}@${latest}: https://github.com/atom/${moduleName}/compare/v${installed}...v${latest}*`;
}
return requestWithAuth('POST /repos/:owner/:repo/pulls', {
title: `⬆️ ${moduleName}@${latest}`,
body: description,
base: 'master',
head: branch
});
},
findPR: async ({ moduleName, latest }, branch) => {
return requestWithAuth('GET /search/issues', {
q: `${moduleName} type:pr ${moduleName}@${latest} in:title repo:atom/atom head:${branch} state:open`
});
},
addLabel: async pullRequestNumber => {
return requestWithAuth('PATCH /repos/:owner/:repo/issues/:issue_number', {
labels: ['depency ⬆️'],
issue_number: pullRequestNumber
});
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
const path = require('path');
const fetchOutdatedDependencies = require('../fetch-outdated-dependencies');
const { nativeDependencies } = require('./helpers');
const repositoryRootPath = path.resolve('.', 'fixtures', 'dummy');
const packageJSON = require(path.join(repositoryRootPath, 'package.json'));

describe('Fetch outdated dependencies', function() {
it('should fetch outdated native dependencies', async () => {
spyOn(fetchOutdatedDependencies, 'npm').andReturn(
Promise.resolve(nativeDependencies)
);

expect(await fetchOutdatedDependencies.npm(repositoryRootPath)).toEqual(
nativeDependencies
);
});

it('should fetch outdated core dependencies', async () => {
spyOn(fetchOutdatedDependencies, 'apm').andReturn(
Promise.resolve(nativeDependencies)
);

expect(await fetchOutdatedDependencies.apm(packageJSON)).toEqual(
nativeDependencies
);
});
});
Loading