+
+
+
Contribute to the Community
+
+
freeCodeCamp is possible thanks to thousands of kind volunteers like you.
+ Here are 5 fun quick ways you can help the community right now:
+
+
+
+
+
+
+
diff --git a/tools/dashboard/probot/public/style.css b/tools/dashboard/probot/public/style.css
new file mode 100644
index 0000000000..2cb14772b8
--- /dev/null
+++ b/tools/dashboard/probot/public/style.css
@@ -0,0 +1,11 @@
+@media (max-width: 991px) {
+ .main-content {
+ margin-top: 65px !important;
+ }
+}
+
+.return-to-free-code-camp {
+ padding: 0!important;
+ margin: -9px 0!important;
+ height: 50px!important;
+}
\ No newline at end of file
diff --git a/tools/dashboard/probot/sample.env b/tools/dashboard/probot/sample.env
new file mode 100644
index 0000000000..f4833ceea7
--- /dev/null
+++ b/tools/dashboard/probot/sample.env
@@ -0,0 +1,17 @@
+GITHUB_USERNAME='camperbot'
+GITHUB_ACCESS_TOKEN=
+REPOSITORY_OWNER='freeCodeCamp'
+REPOSITORY='freeCodeCamp'
+PORT=3001
+MONGO_HOST=mongodb://localhost/contributor-tools
+MONGO_PORT=27017
+PRODUCTION_RUN=false
+
+# PROBOT
+# The ID of your GitHub App
+APP_ID=
+# Go to https://smee.io/new set this to the URL that you are redirected to.
+WEBHOOK_PROXY_URL=
+WEBHOOK_SECRET=
+# Use `trace` to get verbose logging or `info` to show less
+LOG_LEVEL=info
diff --git a/tools/dashboard/probot/server/models/index.js b/tools/dashboard/probot/server/models/index.js
new file mode 100644
index 0000000000..b31295873f
--- /dev/null
+++ b/tools/dashboard/probot/server/models/index.js
@@ -0,0 +1,24 @@
+const mongoose = require('mongoose');
+
+const pr = new mongoose.Schema({
+ _id: Number,
+ updatedAt: String,
+ username: String,
+ title: String,
+ filenames: [String]
+});
+
+const info = new mongoose.Schema({
+ lastUpdate: Date,
+ numPRs: Number,
+ prRange: String
+});
+
+const dbCollections = {
+ pr: 'openprs',
+ info: 'info'
+};
+
+const PR = mongoose.model('PR', pr, dbCollections['pr']);
+const INFO = mongoose.model('INFO', info, dbCollections['info']);
+module.exports = { PR, INFO, dbCollections };
diff --git a/tools/dashboard/probot/server/presolver.js b/tools/dashboard/probot/server/presolver.js
new file mode 100644
index 0000000000..fa5dc86dcd
--- /dev/null
+++ b/tools/dashboard/probot/server/presolver.js
@@ -0,0 +1,113 @@
+// const { updateDb } = require('./tools/update-db');
+
+class Presolver {
+ constructor(context, { owner, repo, logger = console, ...config }) {
+ this.context = context;
+ this.github = context.github;
+ this.logger = logger;
+ this.config = {
+ ...require('../../lib/defaults'),
+ ...(config || {}),
+ ...{
+ owner,
+ repo
+ }
+ };
+ this.pullRequest = {};
+ this.conflictingFiles = [];
+ // this._updateDb = updateDb;
+ }
+
+ async presolve(pullRequest) {
+ Object.assign(this.pullRequest, pullRequest);
+ // await this._updateDb(this.context);
+ await this._ensurePresolverLabelExists();
+ await this._getState();
+ const labelObj = this.config.labelPRConflict;
+ if (this.conflictingFiles.length) {
+ await this._addLabel(labelObj);
+ }
+ }
+
+ async _getState() {
+ // console.log(this.context.issue())
+ const files = await this.github.pullRequests.listFiles(this.context.issue());
+ // console.log(files)
+ const { owner, repo } = this.config;
+ const prs =
+ (await this.github.pullRequests.list({ owner, repo }).data) || [];
+ // console.log(prs)
+ await this._getConflictingFiles(prs, files);
+ }
+
+ async _getConflictingFiles(prs, files) {
+ const { owner, repo } = this.config;
+ const github = this.github;
+ const conflictingFiles = this.conflictingFiles;
+ // console.log(prs, files)
+ prs.forEach(pr => {
+ const prIssue = {
+ number: pr.number,
+ owner: owner,
+ repo: repo
+ };
+ const prFiles = github.pullRequests.listFiles(prIssue);
+ prFiles.data.forEach(file => {
+ files.data.forEach(f => {
+ if (f.filename === file.filename) {
+ conflictingFiles.push(file.filename);
+ }
+ });
+ });
+ });
+ }
+
+ async _ensurePresolverLabelExists() {
+ const label = this.config.labelPRConflict;
+ await this._createLabel(label);
+ }
+
+ async _createLabel(labelObj) {
+ const { owner, repo } = this.config;
+ const github = this.github;
+ return this.github.issues
+ .getLabel({ owner, repo, name: labelObj.name })
+ .catch(() => {
+ return github.issues.createLabel({
+ owner,
+ repo,
+ name: labelObj.name,
+ color: labelObj.color
+ });
+ });
+ }
+
+ _getLabel(labelObj) {
+ return new Promise((resolve, reject) => {
+ for (const label of this.pullRequest.labels) {
+ if (labelObj && labelObj.name && label.name === labelObj.name) {
+ resolve(labelObj);
+ }
+ }
+ reject(new Error('Not found'));
+ });
+ }
+ async _addLabel(labelObj) {
+ const { owner, repo } = this.config;
+ const number = this.pullRequest.number;
+ const label = this.config.labelPRConflict;
+ const github = this.github;
+ // Check if a label does not exist. If it does, it addes the label.
+ return this._getLabel(label).catch(() => {
+ // console.log(labelObj)
+ return github.issues.addLabels({
+ owner,
+ repo,
+ number,
+ labels: [labelObj.name]
+ });
+ });
+ }
+}
+
+module.exports = Presolver;
diff --git a/tools/dashboard/probot/server/routes/index.js b/tools/dashboard/probot/server/routes/index.js
new file mode 100644
index 0000000000..73f6a9538f
--- /dev/null
+++ b/tools/dashboard/probot/server/routes/index.js
@@ -0,0 +1,6 @@
+const pareto = require('./pareto');
+const pr = require('./pr');
+const search = require('./search');
+const info = require('./info');
+
+module.exports = { pareto, pr, search, info };
diff --git a/tools/dashboard/probot/server/routes/info.js b/tools/dashboard/probot/server/routes/info.js
new file mode 100644
index 0000000000..8a9ed20636
--- /dev/null
+++ b/tools/dashboard/probot/server/routes/info.js
@@ -0,0 +1,9 @@
+const router = require('express').Router();
+const { INFO } = require('../models');
+
+router.get('/', async (request, response) => {
+ const [{ lastUpdate, numPRs, prRange }] = await INFO.find({});
+ response.json({ ok: true, lastUpdate, numPRs, prRange });
+});
+
+module.exports = router;
diff --git a/tools/dashboard/probot/server/routes/pareto.js b/tools/dashboard/probot/server/routes/pareto.js
new file mode 100644
index 0000000000..afdc71992d
--- /dev/null
+++ b/tools/dashboard/probot/server/routes/pareto.js
@@ -0,0 +1,37 @@
+const router = require('express').Router();
+const { PR } = require('../models');
+
+const createPareto = reportObj =>
+ Object.keys(reportObj)
+ .reduce((arr, filename) => {
+ const { count, prs } = reportObj[filename];
+ if (count > 1) {
+ arr.push({ filename, count, prs });
+ }
+ return arr;
+ }, [])
+ .sort((a, b) => b.count - a.count);
+
+router.get('/', async (reqeust, response) => {
+ const prs = await PR.find({}).then(data => data);
+ prs.sort((a, b) => a._id - b._id);
+ const reportObj = prs.reduce((obj, pr) => {
+ const { _id: number, filenames, username, title } = pr;
+ filenames.forEach(filename => {
+ if (obj[filename]) {
+ const { count, prs } = obj[filename];
+ obj[filename] = {
+ count: count + 1,
+ prs: prs.concat({ number, username, title })
+ };
+ } else {
+ obj[filename] = { count: 1, prs: [{ number, username, title }] };
+ }
+ });
+ return obj;
+ }, {});
+
+ response.json({ ok: true, pareto: createPareto(reportObj) });
+});
+
+module.exports = router;
diff --git a/tools/dashboard/probot/server/routes/pr.js b/tools/dashboard/probot/server/routes/pr.js
new file mode 100644
index 0000000000..2ff84eab86
--- /dev/null
+++ b/tools/dashboard/probot/server/routes/pr.js
@@ -0,0 +1,46 @@
+const router = require('express').Router();
+const { PR } = require('../models');
+
+router.get('/:number', async (request, response) => {
+ const prs = await PR.find({}).then(data => data);
+ prs.sort((a, b) => a._id - b._id);
+ const indices = prs.reduce((obj, { _id }, index) => {
+ obj[_id] = index;
+ return obj;
+ }, {});
+ const { number: refNumber } = request.params;
+ const index = indices[refNumber];
+
+ if (!index && index !== 0) {
+ response.json({
+ ok: true,
+ message: `Unable to find an open PR with #${refNumber}.`,
+ results: []
+ });
+ return;
+ }
+
+ const pr = prs[index];
+ const results = [];
+ const { filenames: refFilenames } = pr;
+
+ prs.forEach(({ _id: number, filenames, username, title }) => {
+ if (number !== +refNumber) {
+ const matchedFilenames = filenames.filter(filename => {
+ return refFilenames.includes(filename);
+ });
+ if (matchedFilenames.length) {
+ results.push({ number, filenames: matchedFilenames, username, title });
+ }
+ }
+ });
+
+ if (!results.length) {
+ let msg = `No other open PRs with matching filenames of PR #${refNumber}`;
+ response.json({ ok: true, message: msg, results: [] });
+ return;
+ }
+ response.json({ ok: true, results });
+});
+
+module.exports = router;
diff --git a/tools/dashboard/probot/server/routes/probot.js b/tools/dashboard/probot/server/routes/probot.js
new file mode 100644
index 0000000000..59b7043553
--- /dev/null
+++ b/tools/dashboard/probot/server/routes/probot.js
@@ -0,0 +1,16 @@
+const router = require('express').Router();
+const shell = require('shelljs');
+
+router.get('/', (request, response) => {
+ // not working yet
+ shell
+ .exec('npm run presolver')
+ .then(function() {
+ return response.status(200).send('ok');
+ })
+ .catch(err => {
+ console.log(err);
+ });
+});
+
+module.exports = router;
diff --git a/tools/dashboard/probot/server/routes/search.js b/tools/dashboard/probot/server/routes/search.js
new file mode 100644
index 0000000000..f72d5a989a
--- /dev/null
+++ b/tools/dashboard/probot/server/routes/search.js
@@ -0,0 +1,47 @@
+const router = require('express').Router();
+const { PR } = require('../models');
+
+router.get('/', async (request, response) => {
+ const prs = await PR.find({}).then(data => data);
+ prs.sort((a, b) => a._id - b._id);
+ const indices = prs.reduce((obj, { _id }, index) => {
+ obj[_id] = index;
+ return obj;
+ }, {});
+ const value = request.query.value;
+
+ if (value) {
+ const filesFound = {};
+ prs.forEach(({ _id: number, filenames, username, title }) => {
+ filenames.forEach(filename => {
+ if (filename.toLowerCase().includes(value.toLowerCase())) {
+ const fileCount = prs[indices[number]].filenames.length;
+ const prObj = { number, fileCount, username, title };
+
+ if (filesFound.hasOwnProperty(filename)) {
+ filesFound[filename].push(prObj);
+ } else {
+ filesFound[filename] = [prObj];
+ }
+ }
+ });
+ });
+
+ let results = Object.keys(filesFound)
+ .map(filename => ({ filename, prs: filesFound[filename] }))
+ .sort((a, b) => {
+ if (a.filename === b.filename) {
+ return 0;
+ } else {
+ return a.filename < b.filename ? -1 : 1;
+ }
+ });
+ if (!results.length) {
+ response.json({ ok: true, message: 'No matching results.', results: [] });
+ return;
+ }
+ response.json({ ok: true, results });
+ }
+});
+
+module.exports = router;
diff --git a/tools/dashboard/probot/server/tools/update-db.js b/tools/dashboard/probot/server/tools/update-db.js
new file mode 100644
index 0000000000..92ed52492b
--- /dev/null
+++ b/tools/dashboard/probot/server/tools/update-db.js
@@ -0,0 +1,99 @@
+const config = require('../../../config');
+// config should be imported before importing any other file
+const mongoose = require('mongoose');
+
+// added to prevent deprecation warning when findOneAndUpdate is used
+mongoose.set('useFindAndModify', false);
+
+// connect to mongo db
+const mongoUri = config.mongo.host;
+const db = mongoose.connect(
+ mongoUri,
+ { useNewUrlParser: true }
+);
+
+const { PR, INFO } = require('../models');
+const { getPRs, getUserInput, getFilenames } = require('../../../lib/get-prs');
+const { rateLimiter } = require('../../../lib/utils');
+
+const lastUpdate = new Date();
+
+db.then(async () => {
+ const oldPRs = await PR.find({}).then(data => data);
+ const oldIndices = oldPRs.reduce((obj, { _id }, index) => {
+ obj[_id] = index;
+ return obj;
+ }, {});
+
+ const { totalPRs, firstPR, lastPR } = await getUserInput('all');
+ const prPropsToGet = ['number', 'user', 'title', 'updated_at'];
+ const { openPRs } = await getPRs(totalPRs, firstPR, lastPR, prPropsToGet);
+ let count = 0;
+ const newIndices = {};
+ for (let i = 0; i < openPRs.length; i++) {
+ const {
+ number,
+ updated_at: updatedAt,
+ title,
+ user: { login: username }
+ } = openPRs[i];
+
+ newIndices[number] = i;
+ let oldPrData = oldPRs[oldIndices[number]];
+ const oldUpdatedAt = oldPrData ? oldPrData.updatedAt : null;
+ if (!oldIndices.hasOwnProperty(number)) {
+ // insert a new pr
+ const filenames = await getFilenames(number);
+ count++;
+ await PR.create({ _id: number, updatedAt, title, username, filenames });
+ console.log('added PR# ' + number);
+ } else if (updatedAt > oldUpdatedAt) {
+ // update an existing pr
+ const filenames = await getFilenames(number);
+ count++;
+ await PR.findOneAndUpdate(
+ { _id: number },
+ { updatedAt, title, username, filenames }
+ );
+ console.log('updated PR #' + number);
+ }
+ if (count > 4500) {
+ await rateLimiter(4500);
+ }
+ }
+ for (let j = 0; j < oldPRs.length; j++) {
+ const { _id: number } = oldPRs[j];
+ if (!newIndices.hasOwnProperty(number)) {
+ // delete pr because it is no longer open
+ await PR.deleteOne({ _id: number });
+ console.log('deleted PR #' + number);
+ }
+ }
+})
+ .then(async () => {
+ // update info collection
+ const [ { firstPR, lastPR }] = await PR.aggregate(
+ [{
+ $group: {
+ _id: null,
+ firstPR: { $min: '$_id' },
+ lastPR: { $max: '$_id' }
+ }
+ }]
+ );
+ const numPRs = await PR.countDocuments();
+ const info = {
+ lastUpdate,
+ numPRs,
+ prRange: `${firstPR}-${lastPR}`
+ };
+ await INFO.updateOne({}, info, { upsert: true })
+ .catch(err => {
+ console.log(err);
+ });
+ mongoose.connection.close();
+ })
+ .catch(err => {
+ mongoose.connection.close();
+ throw err;
+ });
diff --git a/tools/dashboard/probot/test/index.test.js b/tools/dashboard/probot/test/index.test.js
new file mode 100644
index 0000000000..46e370f60c
--- /dev/null
+++ b/tools/dashboard/probot/test/index.test.js
@@ -0,0 +1,149 @@
+const expect = require('expect');
+const { Probot } = require('probot');
+const prOpened = require('./payloads/events/pullRequests.opened');
+const prExisting = require('./payloads/events/pullRequests.existing');
+const prUnrelated = require('./payloads/events/pullRequests.unrelated');
+const prClosed = require('./payloads/events/pullRequests.closed');
+const prOpenedFiles = require('./payloads/files/files.opened');
+const prExistingFiles = require('./payloads/files/files.existing');
+const prUnrelatedFiles = require('./payloads/files/files.unrelated');
+const probotPlugin = require('..');
+const { PRtest } = require('./utils/testmodels');
+// const mongoose = require('mongoose');
+
+describe('Presolver', () => {
+ let probot, github;
+
+ afterEach(async (done) => {
+ await PRtest.deleteMany({}).catch(err => console.log(err));
+ done();
+ });
+
+ beforeEach( async() => {
+
+ probot = new Probot({});
+ // Load our app into probot
+ let app = await probot.load(probotPlugin);
+ await PRtest.deleteMany({}).catch(err => console.log(err));
+ // This is an easy way to mock out the GitHub API
+ // https://probot.github.io/docs/testing/
+ github = {
+ issues: {
+ /* eslint-disable no-undef */
+ createComment: jest.fn().mockReturnValue(Promise.resolve({})),
+ addLabels: jest.fn(),
+ getLabel: jest.fn().mockImplementation(() => Promise.resolve([])),
+ createLabel: jest.fn()
+ /* eslint-enable no-undef */
+ },
+ repos: {
+ getContent: () =>
+ Promise.resolve({
+ data: Buffer.from(
+ `
+ issueOpened: Message
+ pullRequestOpened: Message
+ `
+ ).toString('base64')
+ })
+ },
+ pullRequests: {
+ // eslint-disable-next-line no-undef
+ listFiles: jest.fn().mockImplementation((issue) => {
+ const { number } = issue;
+ let data;
+ switch (number) {
+ case 31525:
+ data = prOpenedFiles;
+ break;
+ case 33363:
+ data = prExistingFiles;
+ break;
+ case 34559:
+ data = prUnrelatedFiles;
+ break;
+ default:
+ data = prExistingFiles;
+ }
+ return { data };
+ }),
+ // eslint-disable-next-line no-undef
+ list: jest
+ .fn()
+ .mockImplementation(() => ({ data: [
+ prExisting.pull_request
+ ] }))
+ }
+ };
+ app.auth = () => Promise.resolve(github);
+ });
+
+ test(`adds a label if a PR has changes to files targeted by an
+ existing PR`, async () => {
+ // Receive a webhook event
+ await probot.receive({
+ name: 'pull_request.opened',
+ payload: prOpened
+ });
+ expect(github.issues.addLabels).toHaveBeenCalled();
+ });
+
+ test('does not add a label when files do not coincide', async () => {
+ await probot.receive({
+ name: 'pull_request.opened',
+ payload: prUnrelated
+ });
+ expect(github.issues.addLabels).toHaveBeenCalledTimes(0);
+ });
+
+ test('db should update if the action is opened', async () => {
+ await probot.receive({
+ name: 'pull_request.opened',
+ payload: prOpened
+ });
+ const results = await PRtest.find({}).then(data => data);
+ expect(results.length).toBeGreaterThan(0);
+ });
+
+ test('db should update if the action is reopened', async () => {
+ await probot.receive({
+ name: 'pull_request.reopened',
+ payload: prOpened
+ });
+ const results = await PRtest.find({}).then(data => data);
+ expect(results.length).toBeGreaterThan(0);
+ });
+
+ test('db should update if the action is synchronize', async () => {
+ await probot.receive({
+ name: 'pull_request.synchronize',
+ payload: prOpened
+ });
+ const results = await PRtest.find({}).then(data => data);
+ expect(results.length).toBeGreaterThan(0);
+ });
+
+ test('db should update if the action is edited', async () => {
+ await probot.receive({
+ name: 'pull_request.edited',
+ payload: prOpened
+ });
+ const results = await PRtest.find({}).then(data => data);
+ expect(results.length).toBeGreaterThan(0);
+ });
+
+ test('db should have removed document if action is closed', async () => {
+ await probot.receive({
+ name: 'pull_request.closed',
+ payload: prClosed
+ });
+ const result = await PRtest.findOne(
+ { _id: prClosed.number }).then(doc => doc)
+ .catch(err => console.log(err));
+ expect(result).toBe(null);
+
+ });
+});
+
+// For more information about testing with Jest see:
+// https://facebook.github.io/jest/
diff --git a/tools/dashboard/probot/test/payloads/events/pullRequests.closed.json b/tools/dashboard/probot/test/payloads/events/pullRequests.closed.json
new file mode 100644
index 0000000000..c4668085c8
--- /dev/null
+++ b/tools/dashboard/probot/test/payloads/events/pullRequests.closed.json
@@ -0,0 +1,473 @@
+{
+ "action": "closed",
+ "number": 33363,
+ "pull_request": {
+ "url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/pulls/33363",
+ "id": 227227572,
+ "node_id": "MDExOlB1bGxSZXF1ZXN0MjI3MjI3NTcy",
+ "html_url": "https://github.com/freeCodeCamp/freeCodeCamp/pull/33363",
+ "diff_url": "https://github.com/freeCodeCamp/freeCodeCamp/pull/33363.diff",
+ "patch_url": "https://github.com/freeCodeCamp/freeCodeCamp/pull/33363.patch",
+ "issue_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/issues/33363",
+ "number": 33363,
+ "state": "closed",
+ "locked": false,
+ "title": "Add the text \"16\"",
+ "user": {
+ "login": "fredydev",
+ "id": 9504948,
+ "node_id": "MDQ6VXNlcjk1MDQ5NDg=",
+ "avatar_url": "https://avatars0.githubusercontent.com/u/9504948?v=4",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/fredydev",
+ "html_url": "https://github.com/fredydev",
+ "followers_url": "https://api.github.com/users/fredydev/followers",
+ "following_url": "https://api.github.com/users/fredydev/following{/other_user}",
+ "gists_url": "https://api.github.com/users/fredydev/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/fredydev/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/fredydev/subscriptions",
+ "organizations_url": "https://api.github.com/users/fredydev/orgs",
+ "repos_url": "https://api.github.com/users/fredydev/repos",
+ "events_url": "https://api.github.com/users/fredydev/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/fredydev/received_events",
+ "type": "User",
+ "site_admin": false
+ },
+ "body": "\r\n\r\n- [x] I have read [freeCodeCamp's contribution guidelines](https://github.com/freeCodeCamp/freeCodeCamp/blob/master/CONTRIBUTING.md).\r\n- [x] My pull request has a descriptive title (not a vague title like `Update index.md`)\r\n- [x] My pull request targets the `master` branch of freeCodeCamp.\r\n- [x] None of my changes are plagiarized from another source without proper attribution.\r\n- [x] My article does not contain shortened URLs or affiliate links.\r\n\r\nIf your pull request closes a GitHub issue, replace the XXXXX below with the issue number.\r\n\r\nCloses #XXXXX\r\n",
+ "created_at": "2018-10-31T10:15:23Z",
+ "updated_at": "2018-11-13T03:49:07Z",
+ "closed_at": null,
+ "merged_at": null,
+ "merge_commit_sha": "84a7a48d2a90f79fa05eb32d0bff9b0df1d7fe3b",
+ "assignee": null,
+ "assignees": [],
+ "requested_reviewers": [],
+ "requested_teams": [],
+ "labels": [
+ {
+ "id": 1088400742,
+ "node_id": "MDU6TGFiZWwxMDg4NDAwNzQy",
+ "url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/labels/scope:%20guide",
+ "name": "scope: guide",
+ "color": "9631e2",
+ "default": false
+ }
+ ],
+ "milestone": null,
+ "commits_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/pulls/33363/commits",
+ "review_comments_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/pulls/33363/comments",
+ "review_comment_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/pulls/comments{/number}",
+ "comments_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/issues/33363/comments",
+ "statuses_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/statuses/ccadaeb4ed4ae17274fb7c32abe2071ea1e3898b",
+ "head": {
+ "label": "fredydev:patch-1",
+ "ref": "patch-1",
+ "sha": "ccadaeb4ed4ae17274fb7c32abe2071ea1e3898b",
+ "user": {
+ "login": "fredydev",
+ "id": 9504948,
+ "node_id": "MDQ6VXNlcjk1MDQ5NDg=",
+ "avatar_url": "https://avatars0.githubusercontent.com/u/9504948?v=4",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/fredydev",
+ "html_url": "https://github.com/fredydev",
+ "followers_url": "https://api.github.com/users/fredydev/followers",
+ "following_url": "https://api.github.com/users/fredydev/following{/other_user}",
+ "gists_url": "https://api.github.com/users/fredydev/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/fredydev/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/fredydev/subscriptions",
+ "organizations_url": "https://api.github.com/users/fredydev/orgs",
+ "repos_url": "https://api.github.com/users/fredydev/repos",
+ "events_url": "https://api.github.com/users/fredydev/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/fredydev/received_events",
+ "type": "User",
+ "site_admin": false
+ },
+ "repo": {
+ "id": 155534904,
+ "node_id": "MDEwOlJlcG9zaXRvcnkxNTU1MzQ5MDQ=",
+ "name": "freeCodeCamp",
+ "full_name": "fredydev/freeCodeCamp",
+ "private": false,
+ "owner": {
+ "login": "fredydev",
+ "id": 9504948,
+ "node_id": "MDQ6VXNlcjk1MDQ5NDg=",
+ "avatar_url": "https://avatars0.githubusercontent.com/u/9504948?v=4",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/fredydev",
+ "html_url": "https://github.com/fredydev",
+ "followers_url": "https://api.github.com/users/fredydev/followers",
+ "following_url": "https://api.github.com/users/fredydev/following{/other_user}",
+ "gists_url": "https://api.github.com/users/fredydev/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/fredydev/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/fredydev/subscriptions",
+ "organizations_url": "https://api.github.com/users/fredydev/orgs",
+ "repos_url": "https://api.github.com/users/fredydev/repos",
+ "events_url": "https://api.github.com/users/fredydev/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/fredydev/received_events",
+ "type": "User",
+ "site_admin": false
+ },
+ "html_url": "https://github.com/fredydev/freeCodeCamp",
+ "description": "The https://freeCodeCamp.org open source codebase and curriculum. Learn to code for free together with millions of people.",
+ "fork": true,
+ "url": "https://api.github.com/repos/fredydev/freeCodeCamp",
+ "forks_url": "https://api.github.com/repos/fredydev/freeCodeCamp/forks",
+ "keys_url": "https://api.github.com/repos/fredydev/freeCodeCamp/keys{/key_id}",
+ "collaborators_url": "https://api.github.com/repos/fredydev/freeCodeCamp/collaborators{/collaborator}",
+ "teams_url": "https://api.github.com/repos/fredydev/freeCodeCamp/teams",
+ "hooks_url": "https://api.github.com/repos/fredydev/freeCodeCamp/hooks",
+ "issue_events_url": "https://api.github.com/repos/fredydev/freeCodeCamp/issues/events{/number}",
+ "events_url": "https://api.github.com/repos/fredydev/freeCodeCamp/events",
+ "assignees_url": "https://api.github.com/repos/fredydev/freeCodeCamp/assignees{/user}",
+ "branches_url": "https://api.github.com/repos/fredydev/freeCodeCamp/branches{/branch}",
+ "tags_url": "https://api.github.com/repos/fredydev/freeCodeCamp/tags",
+ "blobs_url": "https://api.github.com/repos/fredydev/freeCodeCamp/git/blobs{/sha}",
+ "git_tags_url": "https://api.github.com/repos/fredydev/freeCodeCamp/git/tags{/sha}",
+ "git_refs_url": "https://api.github.com/repos/fredydev/freeCodeCamp/git/refs{/sha}",
+ "trees_url": "https://api.github.com/repos/fredydev/freeCodeCamp/git/trees{/sha}",
+ "statuses_url": "https://api.github.com/repos/fredydev/freeCodeCamp/statuses/{sha}",
+ "languages_url": "https://api.github.com/repos/fredydev/freeCodeCamp/languages",
+ "stargazers_url": "https://api.github.com/repos/fredydev/freeCodeCamp/stargazers",
+ "contributors_url": "https://api.github.com/repos/fredydev/freeCodeCamp/contributors",
+ "subscribers_url": "https://api.github.com/repos/fredydev/freeCodeCamp/subscribers",
+ "subscription_url": "https://api.github.com/repos/fredydev/freeCodeCamp/subscription",
+ "commits_url": "https://api.github.com/repos/fredydev/freeCodeCamp/commits{/sha}",
+ "git_commits_url": "https://api.github.com/repos/fredydev/freeCodeCamp/git/commits{/sha}",
+ "comments_url": "https://api.github.com/repos/fredydev/freeCodeCamp/comments{/number}",
+ "issue_comment_url": "https://api.github.com/repos/fredydev/freeCodeCamp/issues/comments{/number}",
+ "contents_url": "https://api.github.com/repos/fredydev/freeCodeCamp/contents/{+path}",
+ "compare_url": "https://api.github.com/repos/fredydev/freeCodeCamp/compare/{base}...{head}",
+ "merges_url": "https://api.github.com/repos/fredydev/freeCodeCamp/merges",
+ "archive_url": "https://api.github.com/repos/fredydev/freeCodeCamp/{archive_format}{/ref}",
+ "downloads_url": "https://api.github.com/repos/fredydev/freeCodeCamp/downloads",
+ "issues_url": "https://api.github.com/repos/fredydev/freeCodeCamp/issues{/number}",
+ "pulls_url": "https://api.github.com/repos/fredydev/freeCodeCamp/pulls{/number}",
+ "milestones_url": "https://api.github.com/repos/fredydev/freeCodeCamp/milestones{/number}",
+ "notifications_url": "https://api.github.com/repos/fredydev/freeCodeCamp/notifications{?since,all,participating}",
+ "labels_url": "https://api.github.com/repos/fredydev/freeCodeCamp/labels{/name}",
+ "releases_url": "https://api.github.com/repos/fredydev/freeCodeCamp/releases{/id}",
+ "deployments_url": "https://api.github.com/repos/fredydev/freeCodeCamp/deployments",
+ "created_at": "2018-10-31T09:55:52Z",
+ "updated_at": "2018-10-31T09:56:56Z",
+ "pushed_at": "2018-10-31T12:28:21Z",
+ "git_url": "git://github.com/fredydev/freeCodeCamp.git",
+ "ssh_url": "git@github.com:fredydev/freeCodeCamp.git",
+ "clone_url": "https://github.com/fredydev/freeCodeCamp.git",
+ "svn_url": "https://github.com/fredydev/freeCodeCamp",
+ "homepage": "",
+ "size": 95184,
+ "stargazers_count": 0,
+ "watchers_count": 0,
+ "language": "JavaScript",
+ "has_issues": false,
+ "has_projects": true,
+ "has_downloads": true,
+ "has_wiki": false,
+ "has_pages": false,
+ "forks_count": 0,
+ "mirror_url": null,
+ "archived": false,
+ "open_issues_count": 0,
+ "license": {
+ "key": "bsd-3-clause",
+ "name": "BSD 3-Clause \"New\" or \"Revised\" License",
+ "spdx_id": "BSD-3-Clause",
+ "url": "https://api.github.com/licenses/bsd-3-clause",
+ "node_id": "MDc6TGljZW5zZTU="
+ },
+ "forks": 0,
+ "open_issues": 0,
+ "watchers": 0,
+ "default_branch": "master"
+ }
+ },
+ "base": {
+ "label": "freeCodeCamp:master",
+ "ref": "master",
+ "sha": "4a48031353c0b0dfbafe46bfa41a17acc4e2a5ae",
+ "user": {
+ "login": "freeCodeCamp",
+ "id": 9892522,
+ "node_id": "MDEyOk9yZ2FuaXphdGlvbjk4OTI1MjI=",
+ "avatar_url": "https://avatars0.githubusercontent.com/u/9892522?v=4",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/freeCodeCamp",
+ "html_url": "https://github.com/freeCodeCamp",
+ "followers_url": "https://api.github.com/users/freeCodeCamp/followers",
+ "following_url": "https://api.github.com/users/freeCodeCamp/following{/other_user}",
+ "gists_url": "https://api.github.com/users/freeCodeCamp/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/freeCodeCamp/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/freeCodeCamp/subscriptions",
+ "organizations_url": "https://api.github.com/users/freeCodeCamp/orgs",
+ "repos_url": "https://api.github.com/users/freeCodeCamp/repos",
+ "events_url": "https://api.github.com/users/freeCodeCamp/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/freeCodeCamp/received_events",
+ "type": "Organization",
+ "site_admin": false
+ },
+ "repo": {
+ "id": 28457823,
+ "node_id": "MDEwOlJlcG9zaXRvcnkyODQ1NzgyMw==",
+ "name": "freeCodeCamp",
+ "full_name": "freeCodeCamp/freeCodeCamp",
+ "private": false,
+ "owner": {
+ "login": "freeCodeCamp",
+ "id": 9892522,
+ "node_id": "MDEyOk9yZ2FuaXphdGlvbjk4OTI1MjI=",
+ "avatar_url": "https://avatars0.githubusercontent.com/u/9892522?v=4",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/freeCodeCamp",
+ "html_url": "https://github.com/freeCodeCamp",
+ "followers_url": "https://api.github.com/users/freeCodeCamp/followers",
+ "following_url": "https://api.github.com/users/freeCodeCamp/following{/other_user}",
+ "gists_url": "https://api.github.com/users/freeCodeCamp/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/freeCodeCamp/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/freeCodeCamp/subscriptions",
+ "organizations_url": "https://api.github.com/users/freeCodeCamp/orgs",
+ "repos_url": "https://api.github.com/users/freeCodeCamp/repos",
+ "events_url": "https://api.github.com/users/freeCodeCamp/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/freeCodeCamp/received_events",
+ "type": "Organization",
+ "site_admin": false
+ },
+ "html_url": "https://github.com/freeCodeCamp/freeCodeCamp",
+ "description": "The https://www.freeCodeCamp.org open source codebase and curriculum. Learn to code for free together with millions of people.",
+ "fork": false,
+ "url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp",
+ "forks_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/forks",
+ "keys_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/keys{/key_id}",
+ "collaborators_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/collaborators{/collaborator}",
+ "teams_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/teams",
+ "hooks_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/hooks",
+ "issue_events_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/issues/events{/number}",
+ "events_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/events",
+ "assignees_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/assignees{/user}",
+ "branches_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/branches{/branch}",
+ "tags_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/tags",
+ "blobs_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/git/blobs{/sha}",
+ "git_tags_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/git/tags{/sha}",
+ "git_refs_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/git/refs{/sha}",
+ "trees_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/git/trees{/sha}",
+ "statuses_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/statuses/{sha}",
+ "languages_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/languages",
+ "stargazers_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/stargazers",
+ "contributors_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/contributors",
+ "subscribers_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/subscribers",
+ "subscription_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/subscription",
+ "commits_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/commits{/sha}",
+ "git_commits_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/git/commits{/sha}",
+ "comments_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/comments{/number}",
+ "issue_comment_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/issues/comments{/number}",
+ "contents_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/contents/{+path}",
+ "compare_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/compare/{base}...{head}",
+ "merges_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/merges",
+ "archive_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/{archive_format}{/ref}",
+ "downloads_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/downloads",
+ "issues_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/issues{/number}",
+ "pulls_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/pulls{/number}",
+ "milestones_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/milestones{/number}",
+ "notifications_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/notifications{?since,all,participating}",
+ "labels_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/labels{/name}",
+ "releases_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/releases{/id}",
+ "deployments_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/deployments",
+ "created_at": "2014-12-24T17:49:19Z",
+ "updated_at": "2019-01-08T17:05:29Z",
+ "pushed_at": "2019-01-08T17:09:22Z",
+ "git_url": "git://github.com/freeCodeCamp/freeCodeCamp.git",
+ "ssh_url": "git@github.com:freeCodeCamp/freeCodeCamp.git",
+ "clone_url": "https://github.com/freeCodeCamp/freeCodeCamp.git",
+ "svn_url": "https://github.com/freeCodeCamp/freeCodeCamp",
+ "homepage": "",
+ "size": 103712,
+ "stargazers_count": 296829,
+ "watchers_count": 296829,
+ "language": "JavaScript",
+ "has_issues": true,
+ "has_projects": false,
+ "has_downloads": true,
+ "has_wiki": false,
+ "has_pages": false,
+ "forks_count": 20716,
+ "mirror_url": null,
+ "archived": false,
+ "open_issues_count": 5762,
+ "license": {
+ "key": "bsd-3-clause",
+ "name": "BSD 3-Clause \"New\" or \"Revised\" License",
+ "spdx_id": "BSD-3-Clause",
+ "url": "https://api.github.com/licenses/bsd-3-clause",
+ "node_id": "MDc6TGljZW5zZTU="
+ },
+ "forks": 20716,
+ "open_issues": 5762,
+ "watchers": 296829,
+ "default_branch": "master"
+ }
+ },
+ "_links": {
+ "self": {
+ "href": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/pulls/33363"
+ },
+ "html": {
+ "href": "https://github.com/freeCodeCamp/freeCodeCamp/pull/33363"
+ },
+ "issue": {
+ "href": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/issues/33363"
+ },
+ "comments": {
+ "href": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/issues/33363/comments"
+ },
+ "review_comments": {
+ "href": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/pulls/33363/comments"
+ },
+ "review_comment": {
+ "href": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/pulls/comments{/number}"
+ },
+ "commits": {
+ "href": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/pulls/33363/commits"
+ },
+ "statuses": {
+ "href": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/statuses/ccadaeb4ed4ae17274fb7c32abe2071ea1e3898b"
+ }
+ },
+ "author_association": "NONE",
+ "merged": false,
+ "mergeable": false,
+ "rebaseable": false,
+ "mergeable_state": "dirty",
+ "merged_by": null,
+ "comments": 0,
+ "review_comments": 0,
+ "maintainer_can_modify": true,
+ "commits": 1,
+ "additions": 1,
+ "deletions": 1,
+ "changed_files": 1
+ },
+ "repository": {
+ "id": 28457823,
+ "node_id": "MDEwOlJlcG9zaXRvcnkyODQ1NzgyMw==",
+ "name": "freeCodeCamp",
+ "full_name": "freeCodeCamp/freeCodeCamp",
+ "private": false,
+ "owner": {
+ "login": "freeCodeCamp",
+ "id": 9892522,
+ "node_id": "MDEyOk9yZ2FuaXphdGlvbjk4OTI1MjI=",
+ "avatar_url": "https://avatars0.githubusercontent.com/u/9892522?v=4",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/freeCodeCamp",
+ "html_url": "https://github.com/freeCodeCamp",
+ "followers_url": "https://api.github.com/users/freeCodeCamp/followers",
+ "following_url": "https://api.github.com/users/freeCodeCamp/following{/other_user}",
+ "gists_url": "https://api.github.com/users/freeCodeCamp/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/freeCodeCamp/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/freeCodeCamp/subscriptions",
+ "organizations_url": "https://api.github.com/users/freeCodeCamp/orgs",
+ "repos_url": "https://api.github.com/users/freeCodeCamp/repos",
+ "events_url": "https://api.github.com/users/freeCodeCamp/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/freeCodeCamp/received_events",
+ "type": "Organization",
+ "site_admin": false
+ },
+ "html_url": "https://github.com/freeCodeCamp/freeCodeCamp",
+ "description": "The https://www.freeCodeCamp.org open source codebase and curriculum. Learn to code for free together with millions of people.",
+ "fork": false,
+ "url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp",
+ "forks_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/forks",
+ "keys_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/keys{/key_id}",
+ "collaborators_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/collaborators{/collaborator}",
+ "teams_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/teams",
+ "hooks_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/hooks",
+ "issue_events_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/issues/events{/number}",
+ "events_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/events",
+ "assignees_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/assignees{/user}",
+ "branches_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/branches{/branch}",
+ "tags_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/tags",
+ "blobs_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/git/blobs{/sha}",
+ "git_tags_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/git/tags{/sha}",
+ "git_refs_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/git/refs{/sha}",
+ "trees_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/git/trees{/sha}",
+ "statuses_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/statuses/{sha}",
+ "languages_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/languages",
+ "stargazers_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/stargazers",
+ "contributors_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/contributors",
+ "subscribers_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/subscribers",
+ "subscription_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/subscription",
+ "commits_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/commits{/sha}",
+ "git_commits_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/git/commits{/sha}",
+ "comments_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/comments{/number}",
+ "issue_comment_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/issues/comments{/number}",
+ "contents_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/contents/{+path}",
+ "compare_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/compare/{base}...{head}",
+ "merges_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/merges",
+ "archive_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/{archive_format}{/ref}",
+ "downloads_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/downloads",
+ "issues_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/issues{/number}",
+ "pulls_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/pulls{/number}",
+ "milestones_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/milestones{/number}",
+ "notifications_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/notifications{?since,all,participating}",
+ "labels_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/labels{/name}",
+ "releases_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/releases{/id}",
+ "deployments_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/deployments",
+ "created_at": "2014-12-24T17:49:19Z",
+ "updated_at": "2019-01-08T17:05:29Z",
+ "pushed_at": "2019-01-08T17:09:22Z",
+ "git_url": "git://github.com/freeCodeCamp/freeCodeCamp.git",
+ "ssh_url": "git@github.com:freeCodeCamp/freeCodeCamp.git",
+ "clone_url": "https://github.com/freeCodeCamp/freeCodeCamp.git",
+ "svn_url": "https://github.com/freeCodeCamp/freeCodeCamp",
+ "homepage": "",
+ "size": 103712,
+ "stargazers_count": 296829,
+ "watchers_count": 296829,
+ "language": "JavaScript",
+ "has_issues": true,
+ "has_projects": false,
+ "has_downloads": true,
+ "has_wiki": false,
+ "has_pages": false,
+ "forks_count": 20716,
+ "mirror_url": null,
+ "archived": false,
+ "open_issues_count": 5762,
+ "license": {
+ "key": "bsd-3-clause",
+ "name": "BSD 3-Clause \"New\" or \"Revised\" License",
+ "spdx_id": "BSD-3-Clause",
+ "url": "https://api.github.com/licenses/bsd-3-clause",
+ "node_id": "MDc6TGljZW5zZTU="
+ },
+ "forks": 20716,
+ "open_issues": 5762,
+ "watchers": 296829,
+ "default_branch": "master"
+ },
+ "sender": {
+ "login": "tbushman",
+ "id": 7049294,
+ "node_id": "MDQ6VXNlcjcwNDkyOTQ=",
+ "avatar_url": "https://avatars2.githubusercontent.com/u/7049294?v=4",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/tbushman",
+ "html_url": "https://github.com/tbushman",
+ "followers_url": "https://api.github.com/users/tbushman/followers",
+ "following_url": "https://api.github.com/users/tbushman/following{/other_user}",
+ "gists_url": "https://api.github.com/users/tbushman/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/tbushman/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/tbushman/subscriptions",
+ "organizations_url": "https://api.github.com/users/tbushman/orgs",
+ "repos_url": "https://api.github.com/users/tbushman/repos",
+ "events_url": "https://api.github.com/users/tbushman/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/tbushman/received_events",
+ "type": "User",
+ "site_admin": false
+ },
+ "installation": {
+ "id": 421598,
+ "node_id": "MDIzOkludGVncmF0aW9uSW5zdGFsbGF0aW9uNDIxNTk4"
+ }
+}
diff --git a/tools/dashboard/probot/test/payloads/events/pullRequests.existing.json b/tools/dashboard/probot/test/payloads/events/pullRequests.existing.json
new file mode 100644
index 0000000000..e544468fe9
--- /dev/null
+++ b/tools/dashboard/probot/test/payloads/events/pullRequests.existing.json
@@ -0,0 +1,481 @@
+{
+ "action": "opened",
+ "number": 31525,
+ "pull_request": {
+ "url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/pulls/31525",
+ "id": 226420344,
+ "node_id": "MDExOlB1bGxSZXF1ZXN0MjI2NDIwMzQ0",
+ "html_url": "https://github.com/freeCodeCamp/freeCodeCamp/pull/31525",
+ "diff_url": "https://github.com/freeCodeCamp/freeCodeCamp/pull/31525.diff",
+ "patch_url": "https://github.com/freeCodeCamp/freeCodeCamp/pull/31525.patch",
+ "issue_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/issues/31525",
+ "number": 31525,
+ "state": "open",
+ "locked": false,
+ "title": "Fix the duplicate ‘15’ into '16'",
+ "user": {
+ "login": "imdonnie",
+ "id": 42952467,
+ "node_id": "MDQ6VXNlcjQyOTUyNDY3",
+ "avatar_url": "https://avatars0.githubusercontent.com/u/42952467?v=4",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/imdonnie",
+ "html_url": "https://github.com/imdonnie",
+ "followers_url": "https://api.github.com/users/imdonnie/followers",
+ "following_url": "https://api.github.com/users/imdonnie/following{/other_user}",
+ "gists_url": "https://api.github.com/users/imdonnie/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/imdonnie/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/imdonnie/subscriptions",
+ "organizations_url": "https://api.github.com/users/imdonnie/orgs",
+ "repos_url": "https://api.github.com/users/imdonnie/repos",
+ "events_url": "https://api.github.com/users/imdonnie/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/imdonnie/received_events",
+ "type": "User",
+ "site_admin": false
+ },
+ "body": "- [x] I have read [freeCodeCamp's contribution guidelines](https://github.com/freeCodeCamp/freeCodeCamp/blob/master/CONTRIBUTING.md).\r\n- [x] My pull request has a descriptive title (not a vague title like `Update index.md`)\r\n- [x] My pull request targets the `master` branch of freeCodeCamp.\r\n- [x] None of my changes are plagiarized from another source without proper attribution.\r\n- [x] My article does not contain shortened URLs or affiliate links.\r\n\r\n",
+ "created_at": "2018-10-29T02:23:02Z",
+ "updated_at": "2018-11-27T17:47:52Z",
+ "closed_at": null,
+ "merged_at": null,
+ "merge_commit_sha": "8d8e905729bbbc2d7561df7e252a1537f60aaff5",
+ "assignee": null,
+ "assignees": [],
+ "requested_reviewers": [],
+ "requested_teams": [],
+ "labels": [
+ {
+ "id": 1088400742,
+ "node_id": "MDU6TGFiZWwxMDg4NDAwNzQy",
+ "url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/labels/scope:%20guide",
+ "name": "scope: guide",
+ "color": "9631e2",
+ "default": false
+ },
+ {
+ "id": 1096429566,
+ "node_id": "MDU6TGFiZWwxMDk2NDI5NTY2",
+ "url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/labels/status:%20merge%20conflict",
+ "name": "status: merge conflict",
+ "color": "4386bc",
+ "default": false
+ }
+ ],
+ "milestone": null,
+ "commits_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/pulls/31525/commits",
+ "review_comments_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/pulls/31525/comments",
+ "review_comment_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/pulls/comments{/number}",
+ "comments_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/issues/31525/comments",
+ "statuses_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/statuses/e3b300f24ef8d9aee1eb2677af0b897e8736fcea",
+ "head": {
+ "label": "imdonnie:patch-5",
+ "ref": "patch-5",
+ "sha": "e3b300f24ef8d9aee1eb2677af0b897e8736fcea",
+ "user": {
+ "login": "imdonnie",
+ "id": 42952467,
+ "node_id": "MDQ6VXNlcjQyOTUyNDY3",
+ "avatar_url": "https://avatars0.githubusercontent.com/u/42952467?v=4",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/imdonnie",
+ "html_url": "https://github.com/imdonnie",
+ "followers_url": "https://api.github.com/users/imdonnie/followers",
+ "following_url": "https://api.github.com/users/imdonnie/following{/other_user}",
+ "gists_url": "https://api.github.com/users/imdonnie/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/imdonnie/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/imdonnie/subscriptions",
+ "organizations_url": "https://api.github.com/users/imdonnie/orgs",
+ "repos_url": "https://api.github.com/users/imdonnie/repos",
+ "events_url": "https://api.github.com/users/imdonnie/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/imdonnie/received_events",
+ "type": "User",
+ "site_admin": false
+ },
+ "repo": {
+ "id": 153862987,
+ "node_id": "MDEwOlJlcG9zaXRvcnkxNTM4NjI5ODc=",
+ "name": "freeCodeCamp",
+ "full_name": "imdonnie/freeCodeCamp",
+ "private": false,
+ "owner": {
+ "login": "imdonnie",
+ "id": 42952467,
+ "node_id": "MDQ6VXNlcjQyOTUyNDY3",
+ "avatar_url": "https://avatars0.githubusercontent.com/u/42952467?v=4",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/imdonnie",
+ "html_url": "https://github.com/imdonnie",
+ "followers_url": "https://api.github.com/users/imdonnie/followers",
+ "following_url": "https://api.github.com/users/imdonnie/following{/other_user}",
+ "gists_url": "https://api.github.com/users/imdonnie/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/imdonnie/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/imdonnie/subscriptions",
+ "organizations_url": "https://api.github.com/users/imdonnie/orgs",
+ "repos_url": "https://api.github.com/users/imdonnie/repos",
+ "events_url": "https://api.github.com/users/imdonnie/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/imdonnie/received_events",
+ "type": "User",
+ "site_admin": false
+ },
+ "html_url": "https://github.com/imdonnie/freeCodeCamp",
+ "description": "The https://freeCodeCamp.org open source codebase and curriculum. Learn to code for free together with millions of people.",
+ "fork": true,
+ "url": "https://api.github.com/repos/imdonnie/freeCodeCamp",
+ "forks_url": "https://api.github.com/repos/imdonnie/freeCodeCamp/forks",
+ "keys_url": "https://api.github.com/repos/imdonnie/freeCodeCamp/keys{/key_id}",
+ "collaborators_url": "https://api.github.com/repos/imdonnie/freeCodeCamp/collaborators{/collaborator}",
+ "teams_url": "https://api.github.com/repos/imdonnie/freeCodeCamp/teams",
+ "hooks_url": "https://api.github.com/repos/imdonnie/freeCodeCamp/hooks",
+ "issue_events_url": "https://api.github.com/repos/imdonnie/freeCodeCamp/issues/events{/number}",
+ "events_url": "https://api.github.com/repos/imdonnie/freeCodeCamp/events",
+ "assignees_url": "https://api.github.com/repos/imdonnie/freeCodeCamp/assignees{/user}",
+ "branches_url": "https://api.github.com/repos/imdonnie/freeCodeCamp/branches{/branch}",
+ "tags_url": "https://api.github.com/repos/imdonnie/freeCodeCamp/tags",
+ "blobs_url": "https://api.github.com/repos/imdonnie/freeCodeCamp/git/blobs{/sha}",
+ "git_tags_url": "https://api.github.com/repos/imdonnie/freeCodeCamp/git/tags{/sha}",
+ "git_refs_url": "https://api.github.com/repos/imdonnie/freeCodeCamp/git/refs{/sha}",
+ "trees_url": "https://api.github.com/repos/imdonnie/freeCodeCamp/git/trees{/sha}",
+ "statuses_url": "https://api.github.com/repos/imdonnie/freeCodeCamp/statuses/{sha}",
+ "languages_url": "https://api.github.com/repos/imdonnie/freeCodeCamp/languages",
+ "stargazers_url": "https://api.github.com/repos/imdonnie/freeCodeCamp/stargazers",
+ "contributors_url": "https://api.github.com/repos/imdonnie/freeCodeCamp/contributors",
+ "subscribers_url": "https://api.github.com/repos/imdonnie/freeCodeCamp/subscribers",
+ "subscription_url": "https://api.github.com/repos/imdonnie/freeCodeCamp/subscription",
+ "commits_url": "https://api.github.com/repos/imdonnie/freeCodeCamp/commits{/sha}",
+ "git_commits_url": "https://api.github.com/repos/imdonnie/freeCodeCamp/git/commits{/sha}",
+ "comments_url": "https://api.github.com/repos/imdonnie/freeCodeCamp/comments{/number}",
+ "issue_comment_url": "https://api.github.com/repos/imdonnie/freeCodeCamp/issues/comments{/number}",
+ "contents_url": "https://api.github.com/repos/imdonnie/freeCodeCamp/contents/{+path}",
+ "compare_url": "https://api.github.com/repos/imdonnie/freeCodeCamp/compare/{base}...{head}",
+ "merges_url": "https://api.github.com/repos/imdonnie/freeCodeCamp/merges",
+ "archive_url": "https://api.github.com/repos/imdonnie/freeCodeCamp/{archive_format}{/ref}",
+ "downloads_url": "https://api.github.com/repos/imdonnie/freeCodeCamp/downloads",
+ "issues_url": "https://api.github.com/repos/imdonnie/freeCodeCamp/issues{/number}",
+ "pulls_url": "https://api.github.com/repos/imdonnie/freeCodeCamp/pulls{/number}",
+ "milestones_url": "https://api.github.com/repos/imdonnie/freeCodeCamp/milestones{/number}",
+ "notifications_url": "https://api.github.com/repos/imdonnie/freeCodeCamp/notifications{?since,all,participating}",
+ "labels_url": "https://api.github.com/repos/imdonnie/freeCodeCamp/labels{/name}",
+ "releases_url": "https://api.github.com/repos/imdonnie/freeCodeCamp/releases{/id}",
+ "deployments_url": "https://api.github.com/repos/imdonnie/freeCodeCamp/deployments",
+ "created_at": "2018-10-20T02:41:07Z",
+ "updated_at": "2018-10-20T02:42:07Z",
+ "pushed_at": "2019-01-04T20:05:18Z",
+ "git_url": "git://github.com/imdonnie/freeCodeCamp.git",
+ "ssh_url": "git@github.com:imdonnie/freeCodeCamp.git",
+ "clone_url": "https://github.com/imdonnie/freeCodeCamp.git",
+ "svn_url": "https://github.com/imdonnie/freeCodeCamp",
+ "homepage": "",
+ "size": 98408,
+ "stargazers_count": 0,
+ "watchers_count": 0,
+ "language": "JavaScript",
+ "has_issues": false,
+ "has_projects": true,
+ "has_downloads": true,
+ "has_wiki": false,
+ "has_pages": false,
+ "forks_count": 0,
+ "mirror_url": null,
+ "archived": false,
+ "open_issues_count": 0,
+ "license": {
+ "key": "bsd-3-clause",
+ "name": "BSD 3-Clause \"New\" or \"Revised\" License",
+ "spdx_id": "BSD-3-Clause",
+ "url": "https://api.github.com/licenses/bsd-3-clause",
+ "node_id": "MDc6TGljZW5zZTU="
+ },
+ "forks": 0,
+ "open_issues": 0,
+ "watchers": 0,
+ "default_branch": "master"
+ }
+ },
+ "base": {
+ "label": "freeCodeCamp:master",
+ "ref": "master",
+ "sha": "f3c601ee16838fdd94fd828c1dbd88d387fc603d",
+ "user": {
+ "login": "freeCodeCamp",
+ "id": 9892522,
+ "node_id": "MDEyOk9yZ2FuaXphdGlvbjk4OTI1MjI=",
+ "avatar_url": "https://avatars0.githubusercontent.com/u/9892522?v=4",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/freeCodeCamp",
+ "html_url": "https://github.com/freeCodeCamp",
+ "followers_url": "https://api.github.com/users/freeCodeCamp/followers",
+ "following_url": "https://api.github.com/users/freeCodeCamp/following{/other_user}",
+ "gists_url": "https://api.github.com/users/freeCodeCamp/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/freeCodeCamp/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/freeCodeCamp/subscriptions",
+ "organizations_url": "https://api.github.com/users/freeCodeCamp/orgs",
+ "repos_url": "https://api.github.com/users/freeCodeCamp/repos",
+ "events_url": "https://api.github.com/users/freeCodeCamp/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/freeCodeCamp/received_events",
+ "type": "Organization",
+ "site_admin": false
+ },
+ "repo": {
+ "id": 28457823,
+ "node_id": "MDEwOlJlcG9zaXRvcnkyODQ1NzgyMw==",
+ "name": "freeCodeCamp",
+ "full_name": "freeCodeCamp/freeCodeCamp",
+ "private": false,
+ "owner": {
+ "login": "freeCodeCamp",
+ "id": 9892522,
+ "node_id": "MDEyOk9yZ2FuaXphdGlvbjk4OTI1MjI=",
+ "avatar_url": "https://avatars0.githubusercontent.com/u/9892522?v=4",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/freeCodeCamp",
+ "html_url": "https://github.com/freeCodeCamp",
+ "followers_url": "https://api.github.com/users/freeCodeCamp/followers",
+ "following_url": "https://api.github.com/users/freeCodeCamp/following{/other_user}",
+ "gists_url": "https://api.github.com/users/freeCodeCamp/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/freeCodeCamp/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/freeCodeCamp/subscriptions",
+ "organizations_url": "https://api.github.com/users/freeCodeCamp/orgs",
+ "repos_url": "https://api.github.com/users/freeCodeCamp/repos",
+ "events_url": "https://api.github.com/users/freeCodeCamp/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/freeCodeCamp/received_events",
+ "type": "Organization",
+ "site_admin": false
+ },
+ "html_url": "https://github.com/freeCodeCamp/freeCodeCamp",
+ "description": "The https://www.freeCodeCamp.org open source codebase and curriculum. Learn to code for free together with millions of people.",
+ "fork": false,
+ "url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp",
+ "forks_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/forks",
+ "keys_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/keys{/key_id}",
+ "collaborators_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/collaborators{/collaborator}",
+ "teams_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/teams",
+ "hooks_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/hooks",
+ "issue_events_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/issues/events{/number}",
+ "events_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/events",
+ "assignees_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/assignees{/user}",
+ "branches_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/branches{/branch}",
+ "tags_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/tags",
+ "blobs_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/git/blobs{/sha}",
+ "git_tags_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/git/tags{/sha}",
+ "git_refs_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/git/refs{/sha}",
+ "trees_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/git/trees{/sha}",
+ "statuses_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/statuses/{sha}",
+ "languages_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/languages",
+ "stargazers_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/stargazers",
+ "contributors_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/contributors",
+ "subscribers_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/subscribers",
+ "subscription_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/subscription",
+ "commits_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/commits{/sha}",
+ "git_commits_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/git/commits{/sha}",
+ "comments_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/comments{/number}",
+ "issue_comment_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/issues/comments{/number}",
+ "contents_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/contents/{+path}",
+ "compare_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/compare/{base}...{head}",
+ "merges_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/merges",
+ "archive_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/{archive_format}{/ref}",
+ "downloads_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/downloads",
+ "issues_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/issues{/number}",
+ "pulls_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/pulls{/number}",
+ "milestones_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/milestones{/number}",
+ "notifications_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/notifications{?since,all,participating}",
+ "labels_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/labels{/name}",
+ "releases_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/releases{/id}",
+ "deployments_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/deployments",
+ "created_at": "2014-12-24T17:49:19Z",
+ "updated_at": "2019-01-08T17:05:29Z",
+ "pushed_at": "2019-01-08T17:09:22Z",
+ "git_url": "git://github.com/freeCodeCamp/freeCodeCamp.git",
+ "ssh_url": "git@github.com:freeCodeCamp/freeCodeCamp.git",
+ "clone_url": "https://github.com/freeCodeCamp/freeCodeCamp.git",
+ "svn_url": "https://github.com/freeCodeCamp/freeCodeCamp",
+ "homepage": "",
+ "size": 103712,
+ "stargazers_count": 296829,
+ "watchers_count": 296829,
+ "language": "JavaScript",
+ "has_issues": true,
+ "has_projects": false,
+ "has_downloads": true,
+ "has_wiki": false,
+ "has_pages": false,
+ "forks_count": 20716,
+ "mirror_url": null,
+ "archived": false,
+ "open_issues_count": 5762,
+ "license": {
+ "key": "bsd-3-clause",
+ "name": "BSD 3-Clause \"New\" or \"Revised\" License",
+ "spdx_id": "BSD-3-Clause",
+ "url": "https://api.github.com/licenses/bsd-3-clause",
+ "node_id": "MDc6TGljZW5zZTU="
+ },
+ "forks": 20716,
+ "open_issues": 5762,
+ "watchers": 296829,
+ "default_branch": "master"
+ }
+ },
+ "_links": {
+ "self": {
+ "href": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/pulls/31525"
+ },
+ "html": {
+ "href": "https://github.com/freeCodeCamp/freeCodeCamp/pull/31525"
+ },
+ "issue": {
+ "href": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/issues/31525"
+ },
+ "comments": {
+ "href": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/issues/31525/comments"
+ },
+ "review_comments": {
+ "href": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/pulls/31525/comments"
+ },
+ "review_comment": {
+ "href": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/pulls/comments{/number}"
+ },
+ "commits": {
+ "href": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/pulls/31525/commits"
+ },
+ "statuses": {
+ "href": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/statuses/e3b300f24ef8d9aee1eb2677af0b897e8736fcea"
+ }
+ },
+ "author_association": "CONTRIBUTOR",
+ "merged": false,
+ "mergeable": null,
+ "rebaseable": null,
+ "mergeable_state": "unknown",
+ "merged_by": null,
+ "comments": 0,
+ "review_comments": 0,
+ "maintainer_can_modify": true,
+ "commits": 1,
+ "additions": 1,
+ "deletions": 1,
+ "changed_files": 1
+ },
+ "repository": {
+ "id": 28457823,
+ "node_id": "MDEwOlJlcG9zaXRvcnkyODQ1NzgyMw==",
+ "name": "freeCodeCamp",
+ "full_name": "freeCodeCamp/freeCodeCamp",
+ "private": false,
+ "owner": {
+ "login": "freeCodeCamp",
+ "id": 9892522,
+ "node_id": "MDEyOk9yZ2FuaXphdGlvbjk4OTI1MjI=",
+ "avatar_url": "https://avatars0.githubusercontent.com/u/9892522?v=4",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/freeCodeCamp",
+ "html_url": "https://github.com/freeCodeCamp",
+ "followers_url": "https://api.github.com/users/freeCodeCamp/followers",
+ "following_url": "https://api.github.com/users/freeCodeCamp/following{/other_user}",
+ "gists_url": "https://api.github.com/users/freeCodeCamp/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/freeCodeCamp/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/freeCodeCamp/subscriptions",
+ "organizations_url": "https://api.github.com/users/freeCodeCamp/orgs",
+ "repos_url": "https://api.github.com/users/freeCodeCamp/repos",
+ "events_url": "https://api.github.com/users/freeCodeCamp/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/freeCodeCamp/received_events",
+ "type": "Organization",
+ "site_admin": false
+ },
+ "html_url": "https://github.com/freeCodeCamp/freeCodeCamp",
+ "description": "The https://www.freeCodeCamp.org open source codebase and curriculum. Learn to code for free together with millions of people.",
+ "fork": false,
+ "url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp",
+ "forks_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/forks",
+ "keys_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/keys{/key_id}",
+ "collaborators_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/collaborators{/collaborator}",
+ "teams_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/teams",
+ "hooks_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/hooks",
+ "issue_events_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/issues/events{/number}",
+ "events_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/events",
+ "assignees_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/assignees{/user}",
+ "branches_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/branches{/branch}",
+ "tags_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/tags",
+ "blobs_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/git/blobs{/sha}",
+ "git_tags_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/git/tags{/sha}",
+ "git_refs_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/git/refs{/sha}",
+ "trees_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/git/trees{/sha}",
+ "statuses_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/statuses/{sha}",
+ "languages_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/languages",
+ "stargazers_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/stargazers",
+ "contributors_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/contributors",
+ "subscribers_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/subscribers",
+ "subscription_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/subscription",
+ "commits_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/commits{/sha}",
+ "git_commits_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/git/commits{/sha}",
+ "comments_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/comments{/number}",
+ "issue_comment_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/issues/comments{/number}",
+ "contents_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/contents/{+path}",
+ "compare_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/compare/{base}...{head}",
+ "merges_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/merges",
+ "archive_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/{archive_format}{/ref}",
+ "downloads_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/downloads",
+ "issues_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/issues{/number}",
+ "pulls_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/pulls{/number}",
+ "milestones_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/milestones{/number}",
+ "notifications_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/notifications{?since,all,participating}",
+ "labels_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/labels{/name}",
+ "releases_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/releases{/id}",
+ "deployments_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/deployments",
+ "created_at": "2014-12-24T17:49:19Z",
+ "updated_at": "2019-01-08T17:05:29Z",
+ "pushed_at": "2019-01-08T17:09:22Z",
+ "git_url": "git://github.com/freeCodeCamp/freeCodeCamp.git",
+ "ssh_url": "git@github.com:freeCodeCamp/freeCodeCamp.git",
+ "clone_url": "https://github.com/freeCodeCamp/freeCodeCamp.git",
+ "svn_url": "https://github.com/freeCodeCamp/freeCodeCamp",
+ "homepage": "",
+ "size": 103712,
+ "stargazers_count": 296829,
+ "watchers_count": 296829,
+ "language": "JavaScript",
+ "has_issues": true,
+ "has_projects": false,
+ "has_downloads": true,
+ "has_wiki": false,
+ "has_pages": false,
+ "forks_count": 20716,
+ "mirror_url": null,
+ "archived": false,
+ "open_issues_count": 5762,
+ "license": {
+ "key": "bsd-3-clause",
+ "name": "BSD 3-Clause \"New\" or \"Revised\" License",
+ "spdx_id": "BSD-3-Clause",
+ "url": "https://api.github.com/licenses/bsd-3-clause",
+ "node_id": "MDc6TGljZW5zZTU="
+ },
+ "forks": 20716,
+ "open_issues": 5762,
+ "watchers": 296829,
+ "default_branch": "master"
+ },
+ "sender": {
+ "login": "tbushman",
+ "id": 7049294,
+ "node_id": "MDQ6VXNlcjcwNDkyOTQ=",
+ "avatar_url": "https://avatars2.githubusercontent.com/u/7049294?v=4",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/tbushman",
+ "html_url": "https://github.com/tbushman",
+ "followers_url": "https://api.github.com/users/tbushman/followers",
+ "following_url": "https://api.github.com/users/tbushman/following{/other_user}",
+ "gists_url": "https://api.github.com/users/tbushman/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/tbushman/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/tbushman/subscriptions",
+ "organizations_url": "https://api.github.com/users/tbushman/orgs",
+ "repos_url": "https://api.github.com/users/tbushman/repos",
+ "events_url": "https://api.github.com/users/tbushman/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/tbushman/received_events",
+ "type": "User",
+ "site_admin": false
+ },
+ "installation": {
+ "id": 421598,
+ "node_id": "MDIzOkludGVncmF0aW9uSW5zdGFsbGF0aW9uNDIxNTk4"
+ }
+}
diff --git a/tools/dashboard/probot/test/payloads/events/pullRequests.opened.json b/tools/dashboard/probot/test/payloads/events/pullRequests.opened.json
new file mode 100644
index 0000000000..637f2bc6bf
--- /dev/null
+++ b/tools/dashboard/probot/test/payloads/events/pullRequests.opened.json
@@ -0,0 +1,473 @@
+{
+ "action": "opened",
+ "number": 33363,
+ "pull_request": {
+ "url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/pulls/33363",
+ "id": 227227572,
+ "node_id": "MDExOlB1bGxSZXF1ZXN0MjI3MjI3NTcy",
+ "html_url": "https://github.com/freeCodeCamp/freeCodeCamp/pull/33363",
+ "diff_url": "https://github.com/freeCodeCamp/freeCodeCamp/pull/33363.diff",
+ "patch_url": "https://github.com/freeCodeCamp/freeCodeCamp/pull/33363.patch",
+ "issue_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/issues/33363",
+ "number": 33363,
+ "state": "open",
+ "locked": false,
+ "title": "Add the text \"16\"",
+ "user": {
+ "login": "fredydev",
+ "id": 9504948,
+ "node_id": "MDQ6VXNlcjk1MDQ5NDg=",
+ "avatar_url": "https://avatars0.githubusercontent.com/u/9504948?v=4",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/fredydev",
+ "html_url": "https://github.com/fredydev",
+ "followers_url": "https://api.github.com/users/fredydev/followers",
+ "following_url": "https://api.github.com/users/fredydev/following{/other_user}",
+ "gists_url": "https://api.github.com/users/fredydev/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/fredydev/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/fredydev/subscriptions",
+ "organizations_url": "https://api.github.com/users/fredydev/orgs",
+ "repos_url": "https://api.github.com/users/fredydev/repos",
+ "events_url": "https://api.github.com/users/fredydev/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/fredydev/received_events",
+ "type": "User",
+ "site_admin": false
+ },
+ "body": "\r\n\r\n- [x] I have read [freeCodeCamp's contribution guidelines](https://github.com/freeCodeCamp/freeCodeCamp/blob/master/CONTRIBUTING.md).\r\n- [x] My pull request has a descriptive title (not a vague title like `Update index.md`)\r\n- [x] My pull request targets the `master` branch of freeCodeCamp.\r\n- [x] None of my changes are plagiarized from another source without proper attribution.\r\n- [x] My article does not contain shortened URLs or affiliate links.\r\n\r\nIf your pull request closes a GitHub issue, replace the XXXXX below with the issue number.\r\n\r\nCloses #XXXXX\r\n",
+ "created_at": "2018-10-31T10:15:23Z",
+ "updated_at": "2018-11-13T03:49:07Z",
+ "closed_at": null,
+ "merged_at": null,
+ "merge_commit_sha": "84a7a48d2a90f79fa05eb32d0bff9b0df1d7fe3b",
+ "assignee": null,
+ "assignees": [],
+ "requested_reviewers": [],
+ "requested_teams": [],
+ "labels": [
+ {
+ "id": 1088400742,
+ "node_id": "MDU6TGFiZWwxMDg4NDAwNzQy",
+ "url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/labels/scope:%20guide",
+ "name": "scope: guide",
+ "color": "9631e2",
+ "default": false
+ }
+ ],
+ "milestone": null,
+ "commits_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/pulls/33363/commits",
+ "review_comments_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/pulls/33363/comments",
+ "review_comment_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/pulls/comments{/number}",
+ "comments_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/issues/33363/comments",
+ "statuses_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/statuses/ccadaeb4ed4ae17274fb7c32abe2071ea1e3898b",
+ "head": {
+ "label": "fredydev:patch-1",
+ "ref": "patch-1",
+ "sha": "ccadaeb4ed4ae17274fb7c32abe2071ea1e3898b",
+ "user": {
+ "login": "fredydev",
+ "id": 9504948,
+ "node_id": "MDQ6VXNlcjk1MDQ5NDg=",
+ "avatar_url": "https://avatars0.githubusercontent.com/u/9504948?v=4",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/fredydev",
+ "html_url": "https://github.com/fredydev",
+ "followers_url": "https://api.github.com/users/fredydev/followers",
+ "following_url": "https://api.github.com/users/fredydev/following{/other_user}",
+ "gists_url": "https://api.github.com/users/fredydev/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/fredydev/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/fredydev/subscriptions",
+ "organizations_url": "https://api.github.com/users/fredydev/orgs",
+ "repos_url": "https://api.github.com/users/fredydev/repos",
+ "events_url": "https://api.github.com/users/fredydev/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/fredydev/received_events",
+ "type": "User",
+ "site_admin": false
+ },
+ "repo": {
+ "id": 155534904,
+ "node_id": "MDEwOlJlcG9zaXRvcnkxNTU1MzQ5MDQ=",
+ "name": "freeCodeCamp",
+ "full_name": "fredydev/freeCodeCamp",
+ "private": false,
+ "owner": {
+ "login": "fredydev",
+ "id": 9504948,
+ "node_id": "MDQ6VXNlcjk1MDQ5NDg=",
+ "avatar_url": "https://avatars0.githubusercontent.com/u/9504948?v=4",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/fredydev",
+ "html_url": "https://github.com/fredydev",
+ "followers_url": "https://api.github.com/users/fredydev/followers",
+ "following_url": "https://api.github.com/users/fredydev/following{/other_user}",
+ "gists_url": "https://api.github.com/users/fredydev/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/fredydev/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/fredydev/subscriptions",
+ "organizations_url": "https://api.github.com/users/fredydev/orgs",
+ "repos_url": "https://api.github.com/users/fredydev/repos",
+ "events_url": "https://api.github.com/users/fredydev/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/fredydev/received_events",
+ "type": "User",
+ "site_admin": false
+ },
+ "html_url": "https://github.com/fredydev/freeCodeCamp",
+ "description": "The https://freeCodeCamp.org open source codebase and curriculum. Learn to code for free together with millions of people.",
+ "fork": true,
+ "url": "https://api.github.com/repos/fredydev/freeCodeCamp",
+ "forks_url": "https://api.github.com/repos/fredydev/freeCodeCamp/forks",
+ "keys_url": "https://api.github.com/repos/fredydev/freeCodeCamp/keys{/key_id}",
+ "collaborators_url": "https://api.github.com/repos/fredydev/freeCodeCamp/collaborators{/collaborator}",
+ "teams_url": "https://api.github.com/repos/fredydev/freeCodeCamp/teams",
+ "hooks_url": "https://api.github.com/repos/fredydev/freeCodeCamp/hooks",
+ "issue_events_url": "https://api.github.com/repos/fredydev/freeCodeCamp/issues/events{/number}",
+ "events_url": "https://api.github.com/repos/fredydev/freeCodeCamp/events",
+ "assignees_url": "https://api.github.com/repos/fredydev/freeCodeCamp/assignees{/user}",
+ "branches_url": "https://api.github.com/repos/fredydev/freeCodeCamp/branches{/branch}",
+ "tags_url": "https://api.github.com/repos/fredydev/freeCodeCamp/tags",
+ "blobs_url": "https://api.github.com/repos/fredydev/freeCodeCamp/git/blobs{/sha}",
+ "git_tags_url": "https://api.github.com/repos/fredydev/freeCodeCamp/git/tags{/sha}",
+ "git_refs_url": "https://api.github.com/repos/fredydev/freeCodeCamp/git/refs{/sha}",
+ "trees_url": "https://api.github.com/repos/fredydev/freeCodeCamp/git/trees{/sha}",
+ "statuses_url": "https://api.github.com/repos/fredydev/freeCodeCamp/statuses/{sha}",
+ "languages_url": "https://api.github.com/repos/fredydev/freeCodeCamp/languages",
+ "stargazers_url": "https://api.github.com/repos/fredydev/freeCodeCamp/stargazers",
+ "contributors_url": "https://api.github.com/repos/fredydev/freeCodeCamp/contributors",
+ "subscribers_url": "https://api.github.com/repos/fredydev/freeCodeCamp/subscribers",
+ "subscription_url": "https://api.github.com/repos/fredydev/freeCodeCamp/subscription",
+ "commits_url": "https://api.github.com/repos/fredydev/freeCodeCamp/commits{/sha}",
+ "git_commits_url": "https://api.github.com/repos/fredydev/freeCodeCamp/git/commits{/sha}",
+ "comments_url": "https://api.github.com/repos/fredydev/freeCodeCamp/comments{/number}",
+ "issue_comment_url": "https://api.github.com/repos/fredydev/freeCodeCamp/issues/comments{/number}",
+ "contents_url": "https://api.github.com/repos/fredydev/freeCodeCamp/contents/{+path}",
+ "compare_url": "https://api.github.com/repos/fredydev/freeCodeCamp/compare/{base}...{head}",
+ "merges_url": "https://api.github.com/repos/fredydev/freeCodeCamp/merges",
+ "archive_url": "https://api.github.com/repos/fredydev/freeCodeCamp/{archive_format}{/ref}",
+ "downloads_url": "https://api.github.com/repos/fredydev/freeCodeCamp/downloads",
+ "issues_url": "https://api.github.com/repos/fredydev/freeCodeCamp/issues{/number}",
+ "pulls_url": "https://api.github.com/repos/fredydev/freeCodeCamp/pulls{/number}",
+ "milestones_url": "https://api.github.com/repos/fredydev/freeCodeCamp/milestones{/number}",
+ "notifications_url": "https://api.github.com/repos/fredydev/freeCodeCamp/notifications{?since,all,participating}",
+ "labels_url": "https://api.github.com/repos/fredydev/freeCodeCamp/labels{/name}",
+ "releases_url": "https://api.github.com/repos/fredydev/freeCodeCamp/releases{/id}",
+ "deployments_url": "https://api.github.com/repos/fredydev/freeCodeCamp/deployments",
+ "created_at": "2018-10-31T09:55:52Z",
+ "updated_at": "2018-10-31T09:56:56Z",
+ "pushed_at": "2018-10-31T12:28:21Z",
+ "git_url": "git://github.com/fredydev/freeCodeCamp.git",
+ "ssh_url": "git@github.com:fredydev/freeCodeCamp.git",
+ "clone_url": "https://github.com/fredydev/freeCodeCamp.git",
+ "svn_url": "https://github.com/fredydev/freeCodeCamp",
+ "homepage": "",
+ "size": 95184,
+ "stargazers_count": 0,
+ "watchers_count": 0,
+ "language": "JavaScript",
+ "has_issues": false,
+ "has_projects": true,
+ "has_downloads": true,
+ "has_wiki": false,
+ "has_pages": false,
+ "forks_count": 0,
+ "mirror_url": null,
+ "archived": false,
+ "open_issues_count": 0,
+ "license": {
+ "key": "bsd-3-clause",
+ "name": "BSD 3-Clause \"New\" or \"Revised\" License",
+ "spdx_id": "BSD-3-Clause",
+ "url": "https://api.github.com/licenses/bsd-3-clause",
+ "node_id": "MDc6TGljZW5zZTU="
+ },
+ "forks": 0,
+ "open_issues": 0,
+ "watchers": 0,
+ "default_branch": "master"
+ }
+ },
+ "base": {
+ "label": "freeCodeCamp:master",
+ "ref": "master",
+ "sha": "4a48031353c0b0dfbafe46bfa41a17acc4e2a5ae",
+ "user": {
+ "login": "freeCodeCamp",
+ "id": 9892522,
+ "node_id": "MDEyOk9yZ2FuaXphdGlvbjk4OTI1MjI=",
+ "avatar_url": "https://avatars0.githubusercontent.com/u/9892522?v=4",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/freeCodeCamp",
+ "html_url": "https://github.com/freeCodeCamp",
+ "followers_url": "https://api.github.com/users/freeCodeCamp/followers",
+ "following_url": "https://api.github.com/users/freeCodeCamp/following{/other_user}",
+ "gists_url": "https://api.github.com/users/freeCodeCamp/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/freeCodeCamp/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/freeCodeCamp/subscriptions",
+ "organizations_url": "https://api.github.com/users/freeCodeCamp/orgs",
+ "repos_url": "https://api.github.com/users/freeCodeCamp/repos",
+ "events_url": "https://api.github.com/users/freeCodeCamp/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/freeCodeCamp/received_events",
+ "type": "Organization",
+ "site_admin": false
+ },
+ "repo": {
+ "id": 28457823,
+ "node_id": "MDEwOlJlcG9zaXRvcnkyODQ1NzgyMw==",
+ "name": "freeCodeCamp",
+ "full_name": "freeCodeCamp/freeCodeCamp",
+ "private": false,
+ "owner": {
+ "login": "freeCodeCamp",
+ "id": 9892522,
+ "node_id": "MDEyOk9yZ2FuaXphdGlvbjk4OTI1MjI=",
+ "avatar_url": "https://avatars0.githubusercontent.com/u/9892522?v=4",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/freeCodeCamp",
+ "html_url": "https://github.com/freeCodeCamp",
+ "followers_url": "https://api.github.com/users/freeCodeCamp/followers",
+ "following_url": "https://api.github.com/users/freeCodeCamp/following{/other_user}",
+ "gists_url": "https://api.github.com/users/freeCodeCamp/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/freeCodeCamp/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/freeCodeCamp/subscriptions",
+ "organizations_url": "https://api.github.com/users/freeCodeCamp/orgs",
+ "repos_url": "https://api.github.com/users/freeCodeCamp/repos",
+ "events_url": "https://api.github.com/users/freeCodeCamp/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/freeCodeCamp/received_events",
+ "type": "Organization",
+ "site_admin": false
+ },
+ "html_url": "https://github.com/freeCodeCamp/freeCodeCamp",
+ "description": "The https://www.freeCodeCamp.org open source codebase and curriculum. Learn to code for free together with millions of people.",
+ "fork": false,
+ "url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp",
+ "forks_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/forks",
+ "keys_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/keys{/key_id}",
+ "collaborators_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/collaborators{/collaborator}",
+ "teams_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/teams",
+ "hooks_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/hooks",
+ "issue_events_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/issues/events{/number}",
+ "events_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/events",
+ "assignees_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/assignees{/user}",
+ "branches_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/branches{/branch}",
+ "tags_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/tags",
+ "blobs_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/git/blobs{/sha}",
+ "git_tags_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/git/tags{/sha}",
+ "git_refs_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/git/refs{/sha}",
+ "trees_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/git/trees{/sha}",
+ "statuses_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/statuses/{sha}",
+ "languages_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/languages",
+ "stargazers_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/stargazers",
+ "contributors_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/contributors",
+ "subscribers_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/subscribers",
+ "subscription_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/subscription",
+ "commits_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/commits{/sha}",
+ "git_commits_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/git/commits{/sha}",
+ "comments_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/comments{/number}",
+ "issue_comment_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/issues/comments{/number}",
+ "contents_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/contents/{+path}",
+ "compare_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/compare/{base}...{head}",
+ "merges_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/merges",
+ "archive_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/{archive_format}{/ref}",
+ "downloads_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/downloads",
+ "issues_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/issues{/number}",
+ "pulls_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/pulls{/number}",
+ "milestones_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/milestones{/number}",
+ "notifications_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/notifications{?since,all,participating}",
+ "labels_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/labels{/name}",
+ "releases_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/releases{/id}",
+ "deployments_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/deployments",
+ "created_at": "2014-12-24T17:49:19Z",
+ "updated_at": "2019-01-08T17:05:29Z",
+ "pushed_at": "2019-01-08T17:09:22Z",
+ "git_url": "git://github.com/freeCodeCamp/freeCodeCamp.git",
+ "ssh_url": "git@github.com:freeCodeCamp/freeCodeCamp.git",
+ "clone_url": "https://github.com/freeCodeCamp/freeCodeCamp.git",
+ "svn_url": "https://github.com/freeCodeCamp/freeCodeCamp",
+ "homepage": "",
+ "size": 103712,
+ "stargazers_count": 296829,
+ "watchers_count": 296829,
+ "language": "JavaScript",
+ "has_issues": true,
+ "has_projects": false,
+ "has_downloads": true,
+ "has_wiki": false,
+ "has_pages": false,
+ "forks_count": 20716,
+ "mirror_url": null,
+ "archived": false,
+ "open_issues_count": 5762,
+ "license": {
+ "key": "bsd-3-clause",
+ "name": "BSD 3-Clause \"New\" or \"Revised\" License",
+ "spdx_id": "BSD-3-Clause",
+ "url": "https://api.github.com/licenses/bsd-3-clause",
+ "node_id": "MDc6TGljZW5zZTU="
+ },
+ "forks": 20716,
+ "open_issues": 5762,
+ "watchers": 296829,
+ "default_branch": "master"
+ }
+ },
+ "_links": {
+ "self": {
+ "href": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/pulls/33363"
+ },
+ "html": {
+ "href": "https://github.com/freeCodeCamp/freeCodeCamp/pull/33363"
+ },
+ "issue": {
+ "href": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/issues/33363"
+ },
+ "comments": {
+ "href": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/issues/33363/comments"
+ },
+ "review_comments": {
+ "href": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/pulls/33363/comments"
+ },
+ "review_comment": {
+ "href": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/pulls/comments{/number}"
+ },
+ "commits": {
+ "href": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/pulls/33363/commits"
+ },
+ "statuses": {
+ "href": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/statuses/ccadaeb4ed4ae17274fb7c32abe2071ea1e3898b"
+ }
+ },
+ "author_association": "NONE",
+ "merged": false,
+ "mergeable": false,
+ "rebaseable": false,
+ "mergeable_state": "dirty",
+ "merged_by": null,
+ "comments": 0,
+ "review_comments": 0,
+ "maintainer_can_modify": true,
+ "commits": 1,
+ "additions": 1,
+ "deletions": 1,
+ "changed_files": 1
+ },
+ "repository": {
+ "id": 28457823,
+ "node_id": "MDEwOlJlcG9zaXRvcnkyODQ1NzgyMw==",
+ "name": "freeCodeCamp",
+ "full_name": "freeCodeCamp/freeCodeCamp",
+ "private": false,
+ "owner": {
+ "login": "freeCodeCamp",
+ "id": 9892522,
+ "node_id": "MDEyOk9yZ2FuaXphdGlvbjk4OTI1MjI=",
+ "avatar_url": "https://avatars0.githubusercontent.com/u/9892522?v=4",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/freeCodeCamp",
+ "html_url": "https://github.com/freeCodeCamp",
+ "followers_url": "https://api.github.com/users/freeCodeCamp/followers",
+ "following_url": "https://api.github.com/users/freeCodeCamp/following{/other_user}",
+ "gists_url": "https://api.github.com/users/freeCodeCamp/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/freeCodeCamp/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/freeCodeCamp/subscriptions",
+ "organizations_url": "https://api.github.com/users/freeCodeCamp/orgs",
+ "repos_url": "https://api.github.com/users/freeCodeCamp/repos",
+ "events_url": "https://api.github.com/users/freeCodeCamp/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/freeCodeCamp/received_events",
+ "type": "Organization",
+ "site_admin": false
+ },
+ "html_url": "https://github.com/freeCodeCamp/freeCodeCamp",
+ "description": "The https://www.freeCodeCamp.org open source codebase and curriculum. Learn to code for free together with millions of people.",
+ "fork": false,
+ "url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp",
+ "forks_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/forks",
+ "keys_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/keys{/key_id}",
+ "collaborators_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/collaborators{/collaborator}",
+ "teams_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/teams",
+ "hooks_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/hooks",
+ "issue_events_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/issues/events{/number}",
+ "events_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/events",
+ "assignees_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/assignees{/user}",
+ "branches_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/branches{/branch}",
+ "tags_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/tags",
+ "blobs_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/git/blobs{/sha}",
+ "git_tags_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/git/tags{/sha}",
+ "git_refs_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/git/refs{/sha}",
+ "trees_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/git/trees{/sha}",
+ "statuses_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/statuses/{sha}",
+ "languages_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/languages",
+ "stargazers_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/stargazers",
+ "contributors_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/contributors",
+ "subscribers_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/subscribers",
+ "subscription_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/subscription",
+ "commits_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/commits{/sha}",
+ "git_commits_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/git/commits{/sha}",
+ "comments_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/comments{/number}",
+ "issue_comment_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/issues/comments{/number}",
+ "contents_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/contents/{+path}",
+ "compare_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/compare/{base}...{head}",
+ "merges_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/merges",
+ "archive_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/{archive_format}{/ref}",
+ "downloads_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/downloads",
+ "issues_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/issues{/number}",
+ "pulls_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/pulls{/number}",
+ "milestones_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/milestones{/number}",
+ "notifications_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/notifications{?since,all,participating}",
+ "labels_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/labels{/name}",
+ "releases_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/releases{/id}",
+ "deployments_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/deployments",
+ "created_at": "2014-12-24T17:49:19Z",
+ "updated_at": "2019-01-08T17:05:29Z",
+ "pushed_at": "2019-01-08T17:09:22Z",
+ "git_url": "git://github.com/freeCodeCamp/freeCodeCamp.git",
+ "ssh_url": "git@github.com:freeCodeCamp/freeCodeCamp.git",
+ "clone_url": "https://github.com/freeCodeCamp/freeCodeCamp.git",
+ "svn_url": "https://github.com/freeCodeCamp/freeCodeCamp",
+ "homepage": "",
+ "size": 103712,
+ "stargazers_count": 296829,
+ "watchers_count": 296829,
+ "language": "JavaScript",
+ "has_issues": true,
+ "has_projects": false,
+ "has_downloads": true,
+ "has_wiki": false,
+ "has_pages": false,
+ "forks_count": 20716,
+ "mirror_url": null,
+ "archived": false,
+ "open_issues_count": 5762,
+ "license": {
+ "key": "bsd-3-clause",
+ "name": "BSD 3-Clause \"New\" or \"Revised\" License",
+ "spdx_id": "BSD-3-Clause",
+ "url": "https://api.github.com/licenses/bsd-3-clause",
+ "node_id": "MDc6TGljZW5zZTU="
+ },
+ "forks": 20716,
+ "open_issues": 5762,
+ "watchers": 296829,
+ "default_branch": "master"
+ },
+ "sender": {
+ "login": "tbushman",
+ "id": 7049294,
+ "node_id": "MDQ6VXNlcjcwNDkyOTQ=",
+ "avatar_url": "https://avatars2.githubusercontent.com/u/7049294?v=4",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/tbushman",
+ "html_url": "https://github.com/tbushman",
+ "followers_url": "https://api.github.com/users/tbushman/followers",
+ "following_url": "https://api.github.com/users/tbushman/following{/other_user}",
+ "gists_url": "https://api.github.com/users/tbushman/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/tbushman/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/tbushman/subscriptions",
+ "organizations_url": "https://api.github.com/users/tbushman/orgs",
+ "repos_url": "https://api.github.com/users/tbushman/repos",
+ "events_url": "https://api.github.com/users/tbushman/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/tbushman/received_events",
+ "type": "User",
+ "site_admin": false
+ },
+ "installation": {
+ "id": 421598,
+ "node_id": "MDIzOkludGVncmF0aW9uSW5zdGFsbGF0aW9uNDIxNTk4"
+ }
+}
diff --git a/tools/dashboard/probot/test/payloads/events/pullRequests.unrelated.json b/tools/dashboard/probot/test/payloads/events/pullRequests.unrelated.json
new file mode 100644
index 0000000000..73773d5814
--- /dev/null
+++ b/tools/dashboard/probot/test/payloads/events/pullRequests.unrelated.json
@@ -0,0 +1,489 @@
+{
+ "action": "opened",
+ "number": 34559,
+ "pull_request": {
+ "url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/pulls/34559",
+ "id": 236302173,
+ "node_id": "MDExOlB1bGxSZXF1ZXN0MjM2MzAyMTcz",
+ "html_url": "https://github.com/freeCodeCamp/freeCodeCamp/pull/34559",
+ "diff_url": "https://github.com/freeCodeCamp/freeCodeCamp/pull/34559.diff",
+ "patch_url": "https://github.com/freeCodeCamp/freeCodeCamp/pull/34559.patch",
+ "issue_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/issues/34559",
+ "number": 34559,
+ "state": "open",
+ "locked": false,
+ "title": "Feat/test challenges for all lang",
+ "user": {
+ "login": "ValeraS",
+ "id": 10867286,
+ "node_id": "MDQ6VXNlcjEwODY3Mjg2",
+ "avatar_url": "https://avatars0.githubusercontent.com/u/10867286?v=4",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/ValeraS",
+ "html_url": "https://github.com/ValeraS",
+ "followers_url": "https://api.github.com/users/ValeraS/followers",
+ "following_url": "https://api.github.com/users/ValeraS/following{/other_user}",
+ "gists_url": "https://api.github.com/users/ValeraS/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/ValeraS/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/ValeraS/subscriptions",
+ "organizations_url": "https://api.github.com/users/ValeraS/orgs",
+ "repos_url": "https://api.github.com/users/ValeraS/repos",
+ "events_url": "https://api.github.com/users/ValeraS/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/ValeraS/received_events",
+ "type": "User",
+ "site_admin": false
+ },
+ "body": "This PR shows challenge errors for other langs.",
+ "created_at": "2018-12-05T19:54:11Z",
+ "updated_at": "2018-12-07T11:46:29Z",
+ "closed_at": null,
+ "merged_at": null,
+ "merge_commit_sha": "470bb6e1825ed500ab7016897c2796a989affe11",
+ "assignee": null,
+ "assignees": [],
+ "requested_reviewers": [],
+ "requested_teams": [],
+ "labels": [
+ {
+ "id": 252661769,
+ "node_id": "MDU6TGFiZWwyNTI2NjE3Njk=",
+ "url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/labels/scope:%20curriculum",
+ "name": "scope: curriculum",
+ "color": "9631e2",
+ "default": false
+ },
+ {
+ "id": 252689581,
+ "node_id": "MDU6TGFiZWwyNTI2ODk1ODE=",
+ "url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/labels/scope:%20tests",
+ "name": "scope: tests",
+ "color": "9631e2",
+ "default": false
+ },
+ {
+ "id": 1086669320,
+ "node_id": "MDU6TGFiZWwxMDg2NjY5MzIw",
+ "url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/labels/status:%20need%20to%20test%20locally",
+ "name": "status: need to test locally",
+ "color": "df9ae2",
+ "default": false
+ }
+ ],
+ "milestone": null,
+ "commits_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/pulls/34559/commits",
+ "review_comments_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/pulls/34559/comments",
+ "review_comment_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/pulls/comments{/number}",
+ "comments_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/issues/34559/comments",
+ "statuses_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/statuses/3e3abdc74b526972dedeb4d704b55a503b388944",
+ "head": {
+ "label": "ValeraS:feat/test-challenges-for-all-lang",
+ "ref": "feat/test-challenges-for-all-lang",
+ "sha": "3e3abdc74b526972dedeb4d704b55a503b388944",
+ "user": {
+ "login": "ValeraS",
+ "id": 10867286,
+ "node_id": "MDQ6VXNlcjEwODY3Mjg2",
+ "avatar_url": "https://avatars0.githubusercontent.com/u/10867286?v=4",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/ValeraS",
+ "html_url": "https://github.com/ValeraS",
+ "followers_url": "https://api.github.com/users/ValeraS/followers",
+ "following_url": "https://api.github.com/users/ValeraS/following{/other_user}",
+ "gists_url": "https://api.github.com/users/ValeraS/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/ValeraS/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/ValeraS/subscriptions",
+ "organizations_url": "https://api.github.com/users/ValeraS/orgs",
+ "repos_url": "https://api.github.com/users/ValeraS/repos",
+ "events_url": "https://api.github.com/users/ValeraS/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/ValeraS/received_events",
+ "type": "User",
+ "site_admin": false
+ },
+ "repo": {
+ "id": 141251006,
+ "node_id": "MDEwOlJlcG9zaXRvcnkxNDEyNTEwMDY=",
+ "name": "freeCodeCamp",
+ "full_name": "ValeraS/freeCodeCamp",
+ "private": false,
+ "owner": {
+ "login": "ValeraS",
+ "id": 10867286,
+ "node_id": "MDQ6VXNlcjEwODY3Mjg2",
+ "avatar_url": "https://avatars0.githubusercontent.com/u/10867286?v=4",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/ValeraS",
+ "html_url": "https://github.com/ValeraS",
+ "followers_url": "https://api.github.com/users/ValeraS/followers",
+ "following_url": "https://api.github.com/users/ValeraS/following{/other_user}",
+ "gists_url": "https://api.github.com/users/ValeraS/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/ValeraS/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/ValeraS/subscriptions",
+ "organizations_url": "https://api.github.com/users/ValeraS/orgs",
+ "repos_url": "https://api.github.com/users/ValeraS/repos",
+ "events_url": "https://api.github.com/users/ValeraS/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/ValeraS/received_events",
+ "type": "User",
+ "site_admin": false
+ },
+ "html_url": "https://github.com/ValeraS/freeCodeCamp",
+ "description": "The https://freeCodeCamp.org open source codebase and curriculum. Learn to code and help nonprofits.",
+ "fork": true,
+ "url": "https://api.github.com/repos/ValeraS/freeCodeCamp",
+ "forks_url": "https://api.github.com/repos/ValeraS/freeCodeCamp/forks",
+ "keys_url": "https://api.github.com/repos/ValeraS/freeCodeCamp/keys{/key_id}",
+ "collaborators_url": "https://api.github.com/repos/ValeraS/freeCodeCamp/collaborators{/collaborator}",
+ "teams_url": "https://api.github.com/repos/ValeraS/freeCodeCamp/teams",
+ "hooks_url": "https://api.github.com/repos/ValeraS/freeCodeCamp/hooks",
+ "issue_events_url": "https://api.github.com/repos/ValeraS/freeCodeCamp/issues/events{/number}",
+ "events_url": "https://api.github.com/repos/ValeraS/freeCodeCamp/events",
+ "assignees_url": "https://api.github.com/repos/ValeraS/freeCodeCamp/assignees{/user}",
+ "branches_url": "https://api.github.com/repos/ValeraS/freeCodeCamp/branches{/branch}",
+ "tags_url": "https://api.github.com/repos/ValeraS/freeCodeCamp/tags",
+ "blobs_url": "https://api.github.com/repos/ValeraS/freeCodeCamp/git/blobs{/sha}",
+ "git_tags_url": "https://api.github.com/repos/ValeraS/freeCodeCamp/git/tags{/sha}",
+ "git_refs_url": "https://api.github.com/repos/ValeraS/freeCodeCamp/git/refs{/sha}",
+ "trees_url": "https://api.github.com/repos/ValeraS/freeCodeCamp/git/trees{/sha}",
+ "statuses_url": "https://api.github.com/repos/ValeraS/freeCodeCamp/statuses/{sha}",
+ "languages_url": "https://api.github.com/repos/ValeraS/freeCodeCamp/languages",
+ "stargazers_url": "https://api.github.com/repos/ValeraS/freeCodeCamp/stargazers",
+ "contributors_url": "https://api.github.com/repos/ValeraS/freeCodeCamp/contributors",
+ "subscribers_url": "https://api.github.com/repos/ValeraS/freeCodeCamp/subscribers",
+ "subscription_url": "https://api.github.com/repos/ValeraS/freeCodeCamp/subscription",
+ "commits_url": "https://api.github.com/repos/ValeraS/freeCodeCamp/commits{/sha}",
+ "git_commits_url": "https://api.github.com/repos/ValeraS/freeCodeCamp/git/commits{/sha}",
+ "comments_url": "https://api.github.com/repos/ValeraS/freeCodeCamp/comments{/number}",
+ "issue_comment_url": "https://api.github.com/repos/ValeraS/freeCodeCamp/issues/comments{/number}",
+ "contents_url": "https://api.github.com/repos/ValeraS/freeCodeCamp/contents/{+path}",
+ "compare_url": "https://api.github.com/repos/ValeraS/freeCodeCamp/compare/{base}...{head}",
+ "merges_url": "https://api.github.com/repos/ValeraS/freeCodeCamp/merges",
+ "archive_url": "https://api.github.com/repos/ValeraS/freeCodeCamp/{archive_format}{/ref}",
+ "downloads_url": "https://api.github.com/repos/ValeraS/freeCodeCamp/downloads",
+ "issues_url": "https://api.github.com/repos/ValeraS/freeCodeCamp/issues{/number}",
+ "pulls_url": "https://api.github.com/repos/ValeraS/freeCodeCamp/pulls{/number}",
+ "milestones_url": "https://api.github.com/repos/ValeraS/freeCodeCamp/milestones{/number}",
+ "notifications_url": "https://api.github.com/repos/ValeraS/freeCodeCamp/notifications{?since,all,participating}",
+ "labels_url": "https://api.github.com/repos/ValeraS/freeCodeCamp/labels{/name}",
+ "releases_url": "https://api.github.com/repos/ValeraS/freeCodeCamp/releases{/id}",
+ "deployments_url": "https://api.github.com/repos/ValeraS/freeCodeCamp/deployments",
+ "created_at": "2018-07-17T07:43:04Z",
+ "updated_at": "2018-08-06T11:42:53Z",
+ "pushed_at": "2018-12-29T13:46:06Z",
+ "git_url": "git://github.com/ValeraS/freeCodeCamp.git",
+ "ssh_url": "git@github.com:ValeraS/freeCodeCamp.git",
+ "clone_url": "https://github.com/ValeraS/freeCodeCamp.git",
+ "svn_url": "https://github.com/ValeraS/freeCodeCamp",
+ "homepage": "",
+ "size": 104232,
+ "stargazers_count": 0,
+ "watchers_count": 0,
+ "language": "JavaScript",
+ "has_issues": false,
+ "has_projects": true,
+ "has_downloads": true,
+ "has_wiki": false,
+ "has_pages": false,
+ "forks_count": 0,
+ "mirror_url": null,
+ "archived": false,
+ "open_issues_count": 0,
+ "license": {
+ "key": "bsd-3-clause",
+ "name": "BSD 3-Clause \"New\" or \"Revised\" License",
+ "spdx_id": "BSD-3-Clause",
+ "url": "https://api.github.com/licenses/bsd-3-clause",
+ "node_id": "MDc6TGljZW5zZTU="
+ },
+ "forks": 0,
+ "open_issues": 0,
+ "watchers": 0,
+ "default_branch": "staging"
+ }
+ },
+ "base": {
+ "label": "freeCodeCamp:master",
+ "ref": "master",
+ "sha": "4862246eab9511656294c9be0e4854f253c0ca38",
+ "user": {
+ "login": "freeCodeCamp",
+ "id": 9892522,
+ "node_id": "MDEyOk9yZ2FuaXphdGlvbjk4OTI1MjI=",
+ "avatar_url": "https://avatars0.githubusercontent.com/u/9892522?v=4",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/freeCodeCamp",
+ "html_url": "https://github.com/freeCodeCamp",
+ "followers_url": "https://api.github.com/users/freeCodeCamp/followers",
+ "following_url": "https://api.github.com/users/freeCodeCamp/following{/other_user}",
+ "gists_url": "https://api.github.com/users/freeCodeCamp/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/freeCodeCamp/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/freeCodeCamp/subscriptions",
+ "organizations_url": "https://api.github.com/users/freeCodeCamp/orgs",
+ "repos_url": "https://api.github.com/users/freeCodeCamp/repos",
+ "events_url": "https://api.github.com/users/freeCodeCamp/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/freeCodeCamp/received_events",
+ "type": "Organization",
+ "site_admin": false
+ },
+ "repo": {
+ "id": 28457823,
+ "node_id": "MDEwOlJlcG9zaXRvcnkyODQ1NzgyMw==",
+ "name": "freeCodeCamp",
+ "full_name": "freeCodeCamp/freeCodeCamp",
+ "private": false,
+ "owner": {
+ "login": "freeCodeCamp",
+ "id": 9892522,
+ "node_id": "MDEyOk9yZ2FuaXphdGlvbjk4OTI1MjI=",
+ "avatar_url": "https://avatars0.githubusercontent.com/u/9892522?v=4",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/freeCodeCamp",
+ "html_url": "https://github.com/freeCodeCamp",
+ "followers_url": "https://api.github.com/users/freeCodeCamp/followers",
+ "following_url": "https://api.github.com/users/freeCodeCamp/following{/other_user}",
+ "gists_url": "https://api.github.com/users/freeCodeCamp/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/freeCodeCamp/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/freeCodeCamp/subscriptions",
+ "organizations_url": "https://api.github.com/users/freeCodeCamp/orgs",
+ "repos_url": "https://api.github.com/users/freeCodeCamp/repos",
+ "events_url": "https://api.github.com/users/freeCodeCamp/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/freeCodeCamp/received_events",
+ "type": "Organization",
+ "site_admin": false
+ },
+ "html_url": "https://github.com/freeCodeCamp/freeCodeCamp",
+ "description": "The https://www.freeCodeCamp.org open source codebase and curriculum. Learn to code for free together with millions of people.",
+ "fork": false,
+ "url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp",
+ "forks_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/forks",
+ "keys_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/keys{/key_id}",
+ "collaborators_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/collaborators{/collaborator}",
+ "teams_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/teams",
+ "hooks_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/hooks",
+ "issue_events_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/issues/events{/number}",
+ "events_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/events",
+ "assignees_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/assignees{/user}",
+ "branches_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/branches{/branch}",
+ "tags_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/tags",
+ "blobs_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/git/blobs{/sha}",
+ "git_tags_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/git/tags{/sha}",
+ "git_refs_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/git/refs{/sha}",
+ "trees_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/git/trees{/sha}",
+ "statuses_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/statuses/{sha}",
+ "languages_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/languages",
+ "stargazers_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/stargazers",
+ "contributors_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/contributors",
+ "subscribers_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/subscribers",
+ "subscription_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/subscription",
+ "commits_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/commits{/sha}",
+ "git_commits_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/git/commits{/sha}",
+ "comments_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/comments{/number}",
+ "issue_comment_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/issues/comments{/number}",
+ "contents_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/contents/{+path}",
+ "compare_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/compare/{base}...{head}",
+ "merges_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/merges",
+ "archive_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/{archive_format}{/ref}",
+ "downloads_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/downloads",
+ "issues_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/issues{/number}",
+ "pulls_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/pulls{/number}",
+ "milestones_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/milestones{/number}",
+ "notifications_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/notifications{?since,all,participating}",
+ "labels_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/labels{/name}",
+ "releases_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/releases{/id}",
+ "deployments_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/deployments",
+ "created_at": "2014-12-24T17:49:19Z",
+ "updated_at": "2019-01-08T17:32:49Z",
+ "pushed_at": "2019-01-08T17:09:22Z",
+ "git_url": "git://github.com/freeCodeCamp/freeCodeCamp.git",
+ "ssh_url": "git@github.com:freeCodeCamp/freeCodeCamp.git",
+ "clone_url": "https://github.com/freeCodeCamp/freeCodeCamp.git",
+ "svn_url": "https://github.com/freeCodeCamp/freeCodeCamp",
+ "homepage": "",
+ "size": 103712,
+ "stargazers_count": 296827,
+ "watchers_count": 296827,
+ "language": "JavaScript",
+ "has_issues": true,
+ "has_projects": false,
+ "has_downloads": true,
+ "has_wiki": false,
+ "has_pages": false,
+ "forks_count": 20716,
+ "mirror_url": null,
+ "archived": false,
+ "open_issues_count": 5762,
+ "license": {
+ "key": "bsd-3-clause",
+ "name": "BSD 3-Clause \"New\" or \"Revised\" License",
+ "spdx_id": "BSD-3-Clause",
+ "url": "https://api.github.com/licenses/bsd-3-clause",
+ "node_id": "MDc6TGljZW5zZTU="
+ },
+ "forks": 20716,
+ "open_issues": 5762,
+ "watchers": 296827,
+ "default_branch": "master"
+ }
+ },
+ "_links": {
+ "self": {
+ "href": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/pulls/34559"
+ },
+ "html": {
+ "href": "https://github.com/freeCodeCamp/freeCodeCamp/pull/34559"
+ },
+ "issue": {
+ "href": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/issues/34559"
+ },
+ "comments": {
+ "href": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/issues/34559/comments"
+ },
+ "review_comments": {
+ "href": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/pulls/34559/comments"
+ },
+ "review_comment": {
+ "href": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/pulls/comments{/number}"
+ },
+ "commits": {
+ "href": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/pulls/34559/commits"
+ },
+ "statuses": {
+ "href": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/statuses/3e3abdc74b526972dedeb4d704b55a503b388944"
+ }
+ },
+ "author_association": "COLLABORATOR",
+ "merged": false,
+ "mergeable": null,
+ "rebaseable": null,
+ "mergeable_state": "unknown",
+ "merged_by": null,
+ "comments": 1,
+ "review_comments": 0,
+ "maintainer_can_modify": true,
+ "commits": 3,
+ "additions": 127,
+ "deletions": 95,
+ "changed_files": 4
+ },
+ "repository": {
+ "id": 28457823,
+ "node_id": "MDEwOlJlcG9zaXRvcnkyODQ1NzgyMw==",
+ "name": "freeCodeCamp",
+ "full_name": "freeCodeCamp/freeCodeCamp",
+ "private": false,
+ "owner": {
+ "login": "freeCodeCamp",
+ "id": 9892522,
+ "node_id": "MDEyOk9yZ2FuaXphdGlvbjk4OTI1MjI=",
+ "avatar_url": "https://avatars0.githubusercontent.com/u/9892522?v=4",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/freeCodeCamp",
+ "html_url": "https://github.com/freeCodeCamp",
+ "followers_url": "https://api.github.com/users/freeCodeCamp/followers",
+ "following_url": "https://api.github.com/users/freeCodeCamp/following{/other_user}",
+ "gists_url": "https://api.github.com/users/freeCodeCamp/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/freeCodeCamp/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/freeCodeCamp/subscriptions",
+ "organizations_url": "https://api.github.com/users/freeCodeCamp/orgs",
+ "repos_url": "https://api.github.com/users/freeCodeCamp/repos",
+ "events_url": "https://api.github.com/users/freeCodeCamp/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/freeCodeCamp/received_events",
+ "type": "Organization",
+ "site_admin": false
+ },
+ "html_url": "https://github.com/freeCodeCamp/freeCodeCamp",
+ "description": "The https://www.freeCodeCamp.org open source codebase and curriculum. Learn to code for free together with millions of people.",
+ "fork": false,
+ "url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp",
+ "forks_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/forks",
+ "keys_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/keys{/key_id}",
+ "collaborators_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/collaborators{/collaborator}",
+ "teams_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/teams",
+ "hooks_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/hooks",
+ "issue_events_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/issues/events{/number}",
+ "events_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/events",
+ "assignees_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/assignees{/user}",
+ "branches_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/branches{/branch}",
+ "tags_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/tags",
+ "blobs_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/git/blobs{/sha}",
+ "git_tags_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/git/tags{/sha}",
+ "git_refs_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/git/refs{/sha}",
+ "trees_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/git/trees{/sha}",
+ "statuses_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/statuses/{sha}",
+ "languages_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/languages",
+ "stargazers_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/stargazers",
+ "contributors_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/contributors",
+ "subscribers_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/subscribers",
+ "subscription_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/subscription",
+ "commits_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/commits{/sha}",
+ "git_commits_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/git/commits{/sha}",
+ "comments_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/comments{/number}",
+ "issue_comment_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/issues/comments{/number}",
+ "contents_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/contents/{+path}",
+ "compare_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/compare/{base}...{head}",
+ "merges_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/merges",
+ "archive_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/{archive_format}{/ref}",
+ "downloads_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/downloads",
+ "issues_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/issues{/number}",
+ "pulls_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/pulls{/number}",
+ "milestones_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/milestones{/number}",
+ "notifications_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/notifications{?since,all,participating}",
+ "labels_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/labels{/name}",
+ "releases_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/releases{/id}",
+ "deployments_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/deployments",
+ "created_at": "2014-12-24T17:49:19Z",
+ "updated_at": "2019-01-08T17:05:29Z",
+ "pushed_at": "2019-01-08T17:09:22Z",
+ "git_url": "git://github.com/freeCodeCamp/freeCodeCamp.git",
+ "ssh_url": "git@github.com:freeCodeCamp/freeCodeCamp.git",
+ "clone_url": "https://github.com/freeCodeCamp/freeCodeCamp.git",
+ "svn_url": "https://github.com/freeCodeCamp/freeCodeCamp",
+ "homepage": "",
+ "size": 103712,
+ "stargazers_count": 296829,
+ "watchers_count": 296829,
+ "language": "JavaScript",
+ "has_issues": true,
+ "has_projects": false,
+ "has_downloads": true,
+ "has_wiki": false,
+ "has_pages": false,
+ "forks_count": 20716,
+ "mirror_url": null,
+ "archived": false,
+ "open_issues_count": 5762,
+ "license": {
+ "key": "bsd-3-clause",
+ "name": "BSD 3-Clause \"New\" or \"Revised\" License",
+ "spdx_id": "BSD-3-Clause",
+ "url": "https://api.github.com/licenses/bsd-3-clause",
+ "node_id": "MDc6TGljZW5zZTU="
+ },
+ "forks": 20716,
+ "open_issues": 5762,
+ "watchers": 296829,
+ "default_branch": "master"
+ },
+ "sender": {
+ "login": "tbushman",
+ "id": 7049294,
+ "node_id": "MDQ6VXNlcjcwNDkyOTQ=",
+ "avatar_url": "https://avatars2.githubusercontent.com/u/7049294?v=4",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/tbushman",
+ "html_url": "https://github.com/tbushman",
+ "followers_url": "https://api.github.com/users/tbushman/followers",
+ "following_url": "https://api.github.com/users/tbushman/following{/other_user}",
+ "gists_url": "https://api.github.com/users/tbushman/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/tbushman/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/tbushman/subscriptions",
+ "organizations_url": "https://api.github.com/users/tbushman/orgs",
+ "repos_url": "https://api.github.com/users/tbushman/repos",
+ "events_url": "https://api.github.com/users/tbushman/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/tbushman/received_events",
+ "type": "User",
+ "site_admin": false
+ },
+ "installation": {
+ "id": 421598,
+ "node_id": "MDIzOkludGVncmF0aW9uSW5zdGFsbGF0aW9uNDIxNTk4"
+ }
+}
diff --git a/tools/dashboard/probot/test/payloads/files/files.existing.json b/tools/dashboard/probot/test/payloads/files/files.existing.json
new file mode 100644
index 0000000000..60cbe07e4b
--- /dev/null
+++ b/tools/dashboard/probot/test/payloads/files/files.existing.json
@@ -0,0 +1,14 @@
+[
+ {
+ "sha": "49131c31d624d9434171ec700b992fe1e3698513",
+ "filename": "guide/english/linux/basic-linux-commands/index.md",
+ "status": "modified",
+ "additions": 1,
+ "deletions": 1,
+ "changes": 2,
+ "blob_url": "https://github.com/freeCodeCamp/freeCodeCamp/blob/e3b300f24ef8d9aee1eb2677af0b897e8736fcea/guide/english/linux/basic-linux-commands/index.md",
+ "raw_url": "https://github.com/freeCodeCamp/freeCodeCamp/raw/e3b300f24ef8d9aee1eb2677af0b897e8736fcea/guide/english/linux/basic-linux-commands/index.md",
+ "contents_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/contents/guide/english/linux/basic-linux-commands/index.md?ref=e3b300f24ef8d9aee1eb2677af0b897e8736fcea",
+ "patch": "@@ -61,7 +61,7 @@ When starting out with linux, there are some basic commands everyone should know\n 25409 s004 Ss 0:00.04 login -pf
\n ```\n \n- 15. **df -h** Checks disk space in human readable form\n+ 16. **df -h** Checks disk space in human readable form\n - Shows the size, amount used, amount available and capacity percentage of mounted drives/partitions.\n \n "
+ }
+]
\ No newline at end of file
diff --git a/tools/dashboard/probot/test/payloads/files/files.opened.json b/tools/dashboard/probot/test/payloads/files/files.opened.json
new file mode 100644
index 0000000000..d313749af7
--- /dev/null
+++ b/tools/dashboard/probot/test/payloads/files/files.opened.json
@@ -0,0 +1,14 @@
+[
+ {
+ "sha": "49131c31d624d9434171ec700b992fe1e3698513",
+ "filename": "guide/english/linux/basic-linux-commands/index.md",
+ "status": "modified",
+ "additions": 1,
+ "deletions": 1,
+ "changes": 2,
+ "blob_url": "https://github.com/freeCodeCamp/freeCodeCamp/blob/ccadaeb4ed4ae17274fb7c32abe2071ea1e3898b/guide/english/linux/basic-linux-commands/index.md",
+ "raw_url": "https://github.com/freeCodeCamp/freeCodeCamp/raw/ccadaeb4ed4ae17274fb7c32abe2071ea1e3898b/guide/english/linux/basic-linux-commands/index.md",
+ "contents_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/contents/guide/english/linux/basic-linux-commands/index.md?ref=ccadaeb4ed4ae17274fb7c32abe2071ea1e3898b",
+ "patch": "@@ -61,7 +61,7 @@ When starting out with linux, there are some basic commands everyone should know\n 25409 s004 Ss 0:00.04 login -pf \n ```\n \n- 15. **df -h** Checks disk space in human readable form\n+ 16. **df -h** Checks disk space in human readable form\n - Shows the size, amount used, amount available and capacity percentage of mounted drives/partitions.\n \n "
+ }
+]
\ No newline at end of file
diff --git a/tools/dashboard/probot/test/payloads/files/files.unrelated.json b/tools/dashboard/probot/test/payloads/files/files.unrelated.json
new file mode 100644
index 0000000000..ee5b44a652
--- /dev/null
+++ b/tools/dashboard/probot/test/payloads/files/files.unrelated.json
@@ -0,0 +1,50 @@
+[
+ {
+ "sha": "53d25622b620a1fdb5b58c68b54e35a42233b1f8",
+ "filename": "curriculum/schema/challengeSchema.js",
+ "status": "modified",
+ "additions": 83,
+ "deletions": 78,
+ "changes": 161,
+ "blob_url": "https://github.com/freeCodeCamp/freeCodeCamp/blob/3e3abdc74b526972dedeb4d704b55a503b388944/curriculum/schema/challengeSchema.js",
+ "raw_url": "https://github.com/freeCodeCamp/freeCodeCamp/raw/3e3abdc74b526972dedeb4d704b55a503b388944/curriculum/schema/challengeSchema.js",
+ "contents_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/contents/curriculum/schema/challengeSchema.js?ref=3e3abdc74b526972dedeb4d704b55a503b388944",
+ "patch": "@@ -1,84 +1,89 @@\n const Joi = require('joi');\n Joi.objectId = require('joi-objectid')(Joi);\n-const path = require('path');\n-require('dotenv').config({ path: path.resolve(__dirname, '../../.env') });\n \n-const { LOCALE: lang = 'english' } = process.env;\n-\n-let schema = Joi.object().keys({\n- block: Joi.string(),\n- blockId: Joi.objectId(),\n- challengeOrder: Joi.number(),\n- challengeType: Joi.number()\n- .min(0)\n- .max(9)\n- .required(),\n- checksum: Joi.number(),\n- dashedName: Joi.string(),\n- description: Joi.string().required(),\n- fileName: Joi.string(),\n- files: Joi.array().items(\n- Joi.object().keys({\n- key: Joi.string(),\n- ext: Joi.string(),\n- name: Joi.string(),\n- head: [Joi.array().items(Joi.string().allow('')), Joi.string().allow('')],\n- tail: [Joi.array().items(Joi.string().allow('')), Joi.string().allow('')],\n- contents: [\n- Joi.array().items(Joi.string().allow('')),\n- Joi.string().allow('')\n- ]\n- })\n- ),\n- guideUrl: Joi.string().uri({ scheme: 'https' }),\n- videoUrl: Joi.string().allow(''),\n- helpRoom: Joi.string(),\n- id: Joi.objectId().required(),\n- instructions: Joi.string().required(),\n- isBeta: Joi.bool(),\n- isComingSoon: Joi.bool(),\n- isLocked: Joi.bool(),\n- isPrivate: Joi.bool(),\n- isRequired: Joi.bool(),\n- name: Joi.string(),\n- order: Joi.number(),\n- required: Joi.array().items(\n- Joi.object().keys({\n- link: Joi.string(),\n- raw: Joi.bool(),\n- src: Joi.string(),\n- crossDomain: Joi.bool()\n- })\n- ),\n- solutions: Joi.array().items(Joi.string().optional()),\n- superBlock: Joi.string(),\n- superOrder: Joi.number(),\n- suborder: Joi.number(),\n- tests: Joi.array().items(\n- // public challenges\n- Joi.object().keys({\n- text: Joi.string().required(),\n- testString: Joi.string()\n- .allow('')\n- .required()\n- }),\n- // our tests used in certification verification\n- Joi.object().keys({\n- id: Joi.string().required(),\n- title: Joi.string().required()\n- })\n- ),\n- template: Joi.string().allow(''),\n- time: Joi.string().allow(''),\n- title: Joi.string().required()\n-});\n-\n-if (lang !== 'english') {\n- schema = schema.append({\n- localeTitle: Joi.string().required()\n+function getSchemaForLang(lang) {\n+ let schema = Joi.object().keys({\n+ block: Joi.string(),\n+ blockId: Joi.objectId(),\n+ challengeOrder: Joi.number(),\n+ challengeType: Joi.number()\n+ .min(0)\n+ .max(9)\n+ .required(),\n+ checksum: Joi.number(),\n+ dashedName: Joi.string(),\n+ description: Joi.string().required(),\n+ fileName: Joi.string(),\n+ files: Joi.array().items(\n+ Joi.object().keys({\n+ key: Joi.string(),\n+ ext: Joi.string(),\n+ name: Joi.string(),\n+ head: [\n+ Joi.array().items(Joi.string().allow('')),\n+ Joi.string().allow('')\n+ ],\n+ tail: [\n+ Joi.array().items(Joi.string().allow('')),\n+ Joi.string().allow('')\n+ ],\n+ contents: [\n+ Joi.array().items(Joi.string().allow('')),\n+ Joi.string().allow('')\n+ ]\n+ })\n+ ),\n+ guideUrl: Joi.string().uri({ scheme: 'https' }),\n+ videoUrl: Joi.string().allow(''),\n+ helpRoom: Joi.string(),\n+ id: Joi.objectId().required(),\n+ instructions: Joi.string().required(),\n+ isBeta: Joi.bool(),\n+ isComingSoon: Joi.bool(),\n+ isLocked: Joi.bool(),\n+ isPrivate: Joi.bool(),\n+ isRequired: Joi.bool(),\n+ name: Joi.string(),\n+ order: Joi.number(),\n+ required: Joi.array().items(\n+ Joi.object().keys({\n+ link: Joi.string(),\n+ raw: Joi.bool(),\n+ src: Joi.string(),\n+ crossDomain: Joi.bool()\n+ })\n+ ),\n+ solutions: Joi.array().items(Joi.string().optional()),\n+ superBlock: Joi.string(),\n+ superOrder: Joi.number(),\n+ suborder: Joi.number(),\n+ tests: Joi.array().items(\n+ // public challenges\n+ Joi.object().keys({\n+ text: Joi.string().required(),\n+ testString: Joi.string()\n+ .allow('')\n+ .required()\n+ }),\n+ // our tests used in certification verification\n+ Joi.object().keys({\n+ id: Joi.string().required(),\n+ title: Joi.string().required()\n+ })\n+ ),\n+ template: Joi.string().allow(''),\n+ time: Joi.string().allow(''),\n+ title: Joi.string().required()\n });\n-}\n \n-exports.validateChallenge = function validateChallenge(challenge) {\n- return Joi.validate(challenge, schema);\n+ if (lang !== 'english') {\n+ schema = schema.append({\n+ localeTitle: Joi.string().required()\n+ });\n+ }\n+ return schema;\n+}\n+exports.challengeSchemaValidator = lang => {\n+ const schema = getSchemaForLang(lang);\n+ return challenge => Joi.validate(challenge, schema);\n };"
+ },
+ {
+ "sha": "648329aaa0ac1e052f5a9174d0ca6027b42c3a92",
+ "filename": "curriculum/test/test-challenges.js",
+ "status": "modified",
+ "additions": 33,
+ "deletions": 16,
+ "changes": 49,
+ "blob_url": "https://github.com/freeCodeCamp/freeCodeCamp/blob/3e3abdc74b526972dedeb4d704b55a503b388944/curriculum/test/test-challenges.js",
+ "raw_url": "https://github.com/freeCodeCamp/freeCodeCamp/raw/3e3abdc74b526972dedeb4d704b55a503b388944/curriculum/test/test-challenges.js",
+ "contents_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/contents/curriculum/test/test-challenges.js?ref=3e3abdc74b526972dedeb4d704b55a503b388944",
+ "patch": "@@ -22,27 +22,27 @@ const { getChallengesForLang } = require('../getChallenges');\n \n const MongoIds = require('./utils/mongoIds');\n const ChallengeTitles = require('./utils/challengeTitles');\n-const { validateChallenge } = require('../schema/challengeSchema');\n+const { challengeSchemaValidator } = require('../schema/challengeSchema');\n const { challengeTypes } = require('../../client/utils/challengeTypes');\n \n-const { LOCALE: lang = 'english' } = process.env;\n+const { supportedLangs } = require('../utils');\n \n const oldRunnerFail = Mocha.Runner.prototype.fail;\n Mocha.Runner.prototype.fail = function(test, err) {\n- if (err.stack && err instanceof AssertionError) {\n- const assertIndex = err.message.indexOf(': expected');\n+ if (err instanceof AssertionError) {\n+ const errMessage = String(err.message || '');\n+ const assertIndex = errMessage.indexOf(': expected');\n if (assertIndex !== -1) {\n- err.message = err.message.slice(0, assertIndex);\n+ err.message = errMessage.slice(0, assertIndex);\n }\n // Don't show stacktrace for assertion errors.\n- delete err.stack;\n+ if (err.stack) {\n+ delete err.stack;\n+ }\n }\n return oldRunnerFail.call(this, test, err);\n };\n \n-let mongoIds = new MongoIds();\n-let challengeTitles = new ChallengeTitles();\n-\n const { JSDOM } = jsdom;\n \n const babelOptions = {\n@@ -55,7 +55,23 @@ const jQueryScript = fs.readFileSync(\n 'utf8'\n );\n \n-(async function() {\n+runTests();\n+\n+async function runTests() {\n+ let testLangs = [...supportedLangs];\n+ if (process.env.TEST_CHALLENGES_FOR_LANGS) {\n+ const filterLangs = process.env.TEST_CHALLENGES_FOR_LANGS.split(',').map(\n+ lang => lang.trim().toLowerCase()\n+ );\n+ testLangs = testLangs.filter(lang => filterLangs.includes(lang));\n+ }\n+\n+ await Promise.all(testLangs.map(lang => populateTestsForLang(lang)));\n+\n+ run();\n+}\n+\n+async function populateTestsForLang(lang) {\n const allChallenges = await getChallengesForLang(lang).then(curriculum =>\n Object.keys(curriculum)\n .map(key => curriculum[key].blocks)\n@@ -67,7 +83,11 @@ const jQueryScript = fs.readFileSync(\n }, [])\n );\n \n- describe('Check challenges tests', async function() {\n+ const mongoIds = new MongoIds();\n+ const challengeTitles = new ChallengeTitles();\n+ const validateChallenge = challengeSchemaValidator(lang);\n+\n+ describe(`Check challenges (${lang})`, async function() {\n before(async function() {\n this.timeout(30000);\n global.browser = await puppeteer.launch({ args: ['--no-sandbox'] });\n@@ -87,8 +107,7 @@ const jQueryScript = fs.readFileSync(\n it('Common checks', function() {\n const result = validateChallenge(challenge);\n if (result.error) {\n- console.log(result.value);\n- throw new Error(result.error);\n+ throw new AssertionError(result.error);\n }\n const { id, title } = challenge;\n mongoIds.check(id, title);\n@@ -208,9 +227,7 @@ const jQueryScript = fs.readFileSync(\n });\n });\n });\n-\n- run();\n-})();\n+}\n \n // Fake Deep Equal dependency\n const DeepEqual = (a, b) => JSON.stringify(a) === JSON.stringify(b);"
+ },
+ {
+ "sha": "d8b52ff8ae6587f3701ca5f8bc5339981f1adde4",
+ "filename": "curriculum/utils.js",
+ "status": "modified",
+ "additions": 9,
+ "deletions": 1,
+ "changes": 10,
+ "blob_url": "https://github.com/freeCodeCamp/freeCodeCamp/blob/3e3abdc74b526972dedeb4d704b55a503b388944/curriculum/utils.js",
+ "raw_url": "https://github.com/freeCodeCamp/freeCodeCamp/raw/3e3abdc74b526972dedeb4d704b55a503b388944/curriculum/utils.js",
+ "contents_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/contents/curriculum/utils.js?ref=3e3abdc74b526972dedeb4d704b55a503b388944",
+ "patch": "@@ -6,5 +6,13 @@ exports.dasherize = function dasherize(name) {\n .replace(/\\:/g, '');\n };\n \n-const supportedLangs = ['english', 'spanish'];\n+const supportedLangs = [\n+ 'arabic',\n+ 'chinese',\n+ 'english',\n+ 'portuguese',\n+ 'russian',\n+ 'spanish'\n+];\n+\n exports.supportedLangs = supportedLangs;"
+ },
+ {
+ "sha": "5e847f5188b3962ed7811ebae55c7099ee18940d",
+ "filename": "sample.env",
+ "status": "modified",
+ "additions": 2,
+ "deletions": 0,
+ "changes": 2,
+ "blob_url": "https://github.com/freeCodeCamp/freeCodeCamp/blob/3e3abdc74b526972dedeb4d704b55a503b388944/sample.env",
+ "raw_url": "https://github.com/freeCodeCamp/freeCodeCamp/raw/3e3abdc74b526972dedeb4d704b55a503b388944/sample.env",
+ "contents_url": "https://api.github.com/repos/freeCodeCamp/freeCodeCamp/contents/sample.env?ref=3e3abdc74b526972dedeb4d704b55a503b388944",
+ "patch": "@@ -28,3 +28,5 @@ API_LOCATION='http://localhost:3000'\n FORUM_LOCATION='https://forum.localhost'\n FORUM_PROXY_LOCATION='https://proxy.localhost'\n LOCALE=english\n+\n+TEST_CHALLENGES_FOR_LANGS=english"
+ }
+]
\ No newline at end of file
diff --git a/tools/dashboard/probot/test/utils/testmodels.js b/tools/dashboard/probot/test/utils/testmodels.js
new file mode 100644
index 0000000000..1a898e986f
--- /dev/null
+++ b/tools/dashboard/probot/test/utils/testmodels.js
@@ -0,0 +1,24 @@
+const mongoose = require('mongoose');
+
+const prTest = new mongoose.Schema({
+ _id: Number,
+ updatedAt: String,
+ username: String,
+ title: String,
+ filenames: [String]
+});
+
+const infoTest = new mongoose.Schema({
+ lastUpdate: Date,
+ numPRs: Number,
+ prRange: String
+});
+
+const dbCollections = {
+ prtest: 'test_openprs',
+ infotest: 'test_info'
+};
+
+const PRtest = mongoose.model('PRtest', prTest, dbCollections['pr']);
+const INFOtest = mongoose.model('INFOtest', infoTest, dbCollections['info']);
+module.exports = { PRtest, INFOtest, dbCollections };
diff --git a/tools/dashboard/probot/travis.yml b/tools/dashboard/probot/travis.yml
new file mode 100644
index 0000000000..a4c1164e6b
--- /dev/null
+++ b/tools/dashboard/probot/travis.yml
@@ -0,0 +1,23 @@
+sudo: false
+language: node_js
+node_js:
+ - "8.3"
+notifications:
+ disabled: true
+cache:
+ directories:
+ - "node_modules"
+branches:
+ only:
+ - master
+install:
+ - npm install
+script:
+ - echo "Skipping tests"
+deploy:
+ provider: pages
+ skip-cleanup: true
+ github-token: $GITHUB_ACCESS_TOKEN
+ keep-history: true
+ on:
+ branch: master
diff --git a/tools/dashboard/work-logs/.gitignore b/tools/dashboard/work-logs/.gitignore
new file mode 100644
index 0000000000..5e7d2734cf
--- /dev/null
+++ b/tools/dashboard/work-logs/.gitignore
@@ -0,0 +1,4 @@
+# Ignore everything in this directory
+*
+# Except this file
+!.gitignore