Unverified Commit 7277ba7e authored by Adam Zerella's avatar Adam Zerella Committed by GitHub
Browse files

Merge pull request #5 from paritytech/az-code-formatting

Introducing project linting
parents 28d24417 aab596c8
{
"extends": ["eslint:recommended", "prettier"],
"parserOptions": {
"ecmaVersion": "latest"
},
"env": {
"node": true,
"commonjs": true,
"es6": true
},
"rules": {
"prefer-const": "warn"
}
}
......@@ -7,3 +7,4 @@ npm-debug.log
*.pem
!mock-cert.pem
.env
.eslintcache
{
"trailingComma": "es5",
"tabWidth": 2,
"singleQuote": true,
"semi": true,
"bracketSpacing": true
}
......@@ -4,29 +4,32 @@
*/
module.exports = (app) => {
// Your code here
app.log.info("Tip bot was loaded!");
app.log.info('Tip bot was loaded!');
app.on("issue_comment", async (context) => {
app.on('issue_comment', async (context) => {
// Get all the relevant contextual information.
let commentText = context.payload.comment.body
let pullRequestBody = context.payload.issue.body;
let pullRequestUrl = context.payload.issue.html_url;
let tipper = context.payload.comment.user.login;
let contributor = context.payload.issue.user.login;
let pullRequestNumber = context.payload.issue.number;
let pullRequestRepo = context.payload.repository.name;
const commentText = context.payload.comment.body;
const pullRequestBody = context.payload.issue.body;
const pullRequestUrl = context.payload.issue.html_url;
const tipper = context.payload.comment.user.login;
const contributor = context.payload.issue.user.login;
const pullRequestNumber = context.payload.issue.number;
const pullRequestRepo = context.payload.repository.name;
// The bot only triggers on creation of a new comment on a pull request.
if (
!context.payload.issue.hasOwnProperty("pull_request") ||
context.payload.action !== "created" ||
!commentText.startsWith("/tip")
!Object.prototype.hasOwnProperty.call(
context.payload.issue,
'pull_request'
) ||
context.payload.action !== 'created' ||
!commentText.startsWith('/tip')
) {
return
return;
}
// Any problems along the way will be stored here, and used to return an error if needed.
let problemsText = [];
const problemsText = [];
if (tipper === contributor) {
// todo undo
......@@ -40,60 +43,86 @@ module.exports = (app) => {
// TODO temporarily, only allow whitelisted users access to the bot.
if (!process.env.ALLOWED_USERS.includes(tipper)) {
problemsText.push(`You are not allowed to access the tip bot. Only ${process.env.ALLOWED_USERS} are allowed.`)
problemsText.push(
`You are not allowed to access the tip bot. Only ${process.env.ALLOWED_USERS} are allowed.`
);
}
// We will populate this information by processing the pull request and tip comment.
let network, address, size;
// match "polkadot address: <ADDRESS>"
let addressRegex = /(polkadot|kusama|localtest) address:\s?([a-z0-9]+)/i;
let maybeMatch = pullRequestBody.match(addressRegex);
const addressRegex = /(polkadot|kusama|localtest) address:\s?([a-z0-9]+)/i;
const maybeMatch = pullRequestBody.match(addressRegex);
if (!maybeMatch || maybeMatch.length != 3) {
problemsText.push(`Contributor did not properly post their Polkadot or Kusama address. Make sure the pull request has: "{network} address: {address}".`);
problemsText.push(
`Contributor did not properly post their Polkadot or Kusama address. Make sure the pull request has: "{network} address: {address}".`
);
} else {
network = maybeMatch[1].toLowerCase();
if (!["polkadot", "kusama", "localtest"].includes(network)) {
problemsText.push(`Invalid network: ${maybeMatch[1]}. Please select "polkadot" or "kusama".`);
if (!['polkadot', 'kusama', 'localtest'].includes(network)) {
problemsText.push(
`Invalid network: ${maybeMatch[1]}. Please select "polkadot" or "kusama".`
);
}
address = maybeMatch[2];
}
// Tip initiation comment should be: "/tip { small / medium / large }"
let textParts = commentText.split(" ");
const textParts = commentText.split(' ');
if (textParts.length !== 2) {
problemsText.push(`Invalid command! Payload should be: "/tip { small / medium / large }".`);
problemsText.push(
`Invalid command! Payload should be: "/tip { small / medium / large }".`
);
} else {
// We already match `/tip` at the top of this program, so just check size.
size = textParts[1].toLowerCase();
if (size == "s") {
size = "small";
} else if (size == "m") {
size = "medium";
} else if (size == "l") {
size = "large";
if (size == 's') {
size = 'small';
} else if (size == 'm') {
size = 'medium';
} else if (size == 'l') {
size = 'large';
}
if (!["small", "medium", "large"].includes(size)) {
problemsText.push(`Invalid tip size. Please specify one of small, medium, or large.`)
if (!['small', 'medium', 'large'].includes(size)) {
problemsText.push(
`Invalid tip size. Please specify one of small, medium, or large.`
);
}
}
if (problemsText.length > 0) {
// there was some error to get to this point, lets list them.
let comment = "Please fix the following problems before calling the tip bot again:";
for (problem of problemsText) {
comment += `\n * ${problem}`
let comment =
'Please fix the following problems before calling the tip bot again:';
for (const problem of problemsText) {
comment += `\n * ${problem}`;
}
postComment(context, comment);
} else {
console.log(`Valid command! \n ${tipper} wants to tip ${contributor} (${address} on ${network}) a ${size} tip for pull request ${pullRequestUrl}.`);
console.log(
`Valid command! \n ${tipper} wants to tip ${contributor} (${address} on ${network}) a ${size} tip for pull request ${pullRequestUrl}.`
);
// Send the transaction to the network.
let result = await tipUser(address, contributor, network, pullRequestNumber, pullRequestRepo, size);
const result = await tipUser(
address,
contributor,
network,
pullRequestNumber,
pullRequestRepo,
size
);
// TODO actually check for problems with submitting the tip. Maybe even query storage to ensure the tip is there.
if (result) {
postComment(context, `A ${size} tip was successfully submitted for ${contributor} (${address} on ${network}). \n\n https://polkadot.js.org/apps/#/treasury/tips`);
postComment(
context,
`A ${size} tip was successfully submitted for ${contributor} (${address} on ${network}). \n\n https://polkadot.js.org/apps/#/treasury/tips`
);
} else {
postComment(context, `Could not submit tip :( Notify someone at Parity.`);
postComment(
context,
`Could not submit tip :( Notify someone at Parity.`
);
}
}
return;
......@@ -112,19 +141,26 @@ var { ApiPromise, WsProvider, Keyring } = require('@polkadot/api');
var { cryptoWaitReady } = require('@polkadot/util-crypto');
// TODO add some kind of timeout then return an error
async function tipUser(address, contributor, network, pullRequestNumber, pullRequestRepo, size) {
async function tipUser(
address,
contributor,
network,
pullRequestNumber,
pullRequestRepo,
size
) {
await cryptoWaitReady();
const keyring = new Keyring({ type: 'sr25519' });
// Connect to the appropriate network.
let provider, account;
if (network == "localtest") {
if (network == 'localtest') {
provider = new WsProvider('ws://localhost:9944');
account = keyring.addFromUri('//Alice', { name: 'Alice default' });
} else if (network == "polkadot") {
} else if (network == 'polkadot') {
provider = new WsProvider('wss://rpc.polkadot.io/');
account = keyring.addFromUri(process.env.ACCOUNT_SEED);
} else if (network == "kusama") {
} else if (network == 'kusama') {
provider = new WsProvider('wss://kusama-rpc.polkadot.io/');
account = keyring.addFromUri(process.env.ACCOUNT_SEED);
} else {
......@@ -137,16 +173,17 @@ async function tipUser(address, contributor, network, pullRequestNumber, pullReq
const [chain, nodeName, nodeVersion] = await Promise.all([
api.rpc.system.chain(),
api.rpc.system.name(),
api.rpc.system.version()
api.rpc.system.version(),
]);
console.log(
`You are connected to chain ${chain} using ${nodeName} v${nodeVersion}`
);
let reason = `TO: ${contributor} FOR: ${pullRequestRepo}#${pullRequestNumber} (${size})`;
const reason = `TO: ${contributor} FOR: ${pullRequestRepo}#${pullRequestNumber} (${size})`;
// TODO before submitting, check tip does not already exist via a storage query.
// TODO potentially prevent duplicates by also checking for reasons with the other sizes.
const unsub = await api.tx.tips.reportAwesome(reason, address)
const unsub = await api.tx.tips
.reportAwesome(reason, address)
.signAndSend(account, (result) => {
console.log(`Current status is ${result.status}`);
if (result.status.isInBlock) {
......@@ -155,7 +192,7 @@ async function tipUser(address, contributor, network, pullRequestNumber, pullReq
console.log(`Tip finalized at blockHash ${result.status.asFinalized}`);
unsub();
}
});;
});
return true;
}
......@@ -13,7 +13,9 @@
],
"scripts": {
"start": "probot run ./index.js",
"test": "jest"
"test": "jest",
"lint": "eslint index.js --cache",
"lint:fix": "eslint index.js --cache --fix"
},
"dependencies": {
"@polkadot/api": "^6.0.5",
......@@ -21,8 +23,12 @@
"probot": "^11.0.1"
},
"devDependencies": {
"eslint": "^7.32.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-prettier": "^4.0.0",
"jest": "^26.6.3",
"nock": "^13.0.5",
"prettier": "^2.4.1",
"smee-client": "^1.2.2"
},
"engines": {
......
This diff is collapsed.
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment