From bc783106165f46a5c4386a41ec159c32009ee936 Mon Sep 17 00:00:00 2001 From: Jon Rohan Date: Fri, 4 May 2018 14:35:39 -0700 Subject: [PATCH] Updating probot script to watch for primer component changes also --- index.js | 216 +++++++++++++++++++++++++++++++++++---------------- package.json | 2 +- 2 files changed, 152 insertions(+), 66 deletions(-) diff --git a/index.js b/index.js index 63fc613..66ad66b 100644 --- a/index.js +++ b/index.js @@ -29,7 +29,7 @@ const getFigmaComponents = (figmaFileKey) => { }) } -const getFigmaImages = (figmaFileKey, componentIds) => { +const getFigmaImages = (figmaFileKey, componentIds, aws=true) => { return new Promise((resolve, reject) => { got.get(`https://api.figma.com/v1/images/${figmaFileKey}`, { query: { @@ -47,20 +47,24 @@ const getFigmaImages = (figmaFileKey, componentIds) => { } }) .then(images => { - resolve( - Promise.all(Object.keys(images).map(k => { - const url = images[k] - return got.get(url, { - headers: { 'Content-Type': 'images/svg+xml' } - }).then(response => { - return { - 'url': url, - 'id': k, - 'raw': response.body - } - }) - })) - ) + if (aws) { + resolve( + Promise.all(Object.keys(images).map(k => { + const url = images[k] + return got.get(url, { + headers: { 'Content-Type': 'images/svg+xml' } + }).then(response => { + return { + 'url': url, + 'id': k, + 'raw': response.body + } + }) + })) + ) + } else { + resolve(images) + } }) .catch(err => reject(err)) }) @@ -76,69 +80,151 @@ const hasChanged = (before, after) => { return false } -// Template -const changeComment = (data) => { - return ` -| Before | After | -| :-- | :-- | -${Object.values(data.before.components).map((b) => { - const a = data.after.components[b.id] - return `| **Name:** \`${b.name}\`
**Description:** \`${b.description}\` [](${b.image.url}) | **Name:** \`${a.name}\`
**Description:** \`${a.description}\` [](${a.image.url}) |` -}).join('\n')}` +const getFigmaFileId = (str) => { + return /www\.figma\.com\/file\/(.+)\//.exec(str).pop() +} + +const octiconsBeforeAfter = async (diff, context) => { + + let data = {} + + diff.match(/^[-+]\s.*www\.figma\.com\/file\/.+\//gm).forEach(m => { + data[m[0] === '-' ? 'before' : 'after'] = { + 'fileId': getFigmaFileId(m) + } + }) + + if (data.before.fileId && data.after.fileId) { + // Get Before components + data.before.components = (await getFigmaComponents(data.before.fileId)) + + // Get After components + data.after.components = (await getFigmaComponents(data.after.fileId)) + + // Get Before images + let bimages = (await getFigmaImages(data.before.fileId, Object.keys(data.before.components).join(','))) + + bimages.forEach(bi => { + data.before.components[bi.id].image = bi + }) + + // Get After images + let aimages = (await getFigmaImages(data.after.fileId, Object.keys(data.after.components).join(','))) + + aimages.forEach(ai => { + data.after.components[ai.id].image = ai + }) + + // Mark any that changed on the surface (no data in first call) + Object.keys(data.before.components).forEach((k) => { + if (!hasChanged(data.before.components[k], data.after.components[k])) { + delete data.before.components[k] + delete data.after.components[k] + } + }) + + // Exit early if no components have changed + if (Object.keys(data.before.components).length === 0 || + Object.keys(data.after.components).length === 0) return + + return ` + | Before | After | + | :-- | :-- | + ${Object.values(data.before.components).map((b) => { + const a = data.after.components[b.id] + return `| **Name:** \`${b.name}\`
**Description:** \`${b.description}\` [](${b.image.url}) | **Name:** \`${a.name}\`
**Description:** \`${a.description}\` [](${a.image.url}) |` + }).join('\n')}` + } +} + +const primerComponentChanges = async (diff, context) => { + + let modules = diff.match(/^diff --git a\/([\w\/\-]*).scss/gm).map(line => { + + const file = /^diff --git a\/([\w\/\-]*).scss/.exec(line).pop().split("/") + return { + name: file[1], + path: `${file.slice(0,2).join("/")}/package.json`, + components: [] + } + }) + // If a scss file was changed + modules = (await modules.map(async m => { + + // Getting module package.json from github and parsing as JSON + const pkg = JSON.parse(Buffer.from((await context.github.repos.getContent(context.repo({ + path: m.path, + ref: context.payload.pull_request.head.ref, + repo: context.payload.repository.name, + owner: context.payload.repository.owner.login + }))).data.content, 'base64').toString()) + + m.url = pkg.figma.url + + const components = Object.values(pkg.figma.components).map(m => m.id).join(",") + const fileId = getFigmaFileId(pkg.figma.url) + + let images = (await getFigmaImages(fileId, components, false)) + Object.keys(images).map(i => { + m.components.push({ + id: i, + url: images[i], + name: Object.keys(pkg.figma.components).find(k => pkg.figma.components[k].id == i) + }) + }) + m.components.sort((a, b) => b.name - a.name) + return m + })) + return Promise.all(modules) + .then(modules => { + const componentsTemplate = (module) => { + return module.components.map(i => { + return `* \`${i.name}\` – 🔗[figma file](${module.url}?node-id=${encodeURIComponent(i.id)}) + + [![](${i.url})](${module.url}?node-id=${encodeURIComponent(i.id)})` + }).join("\n") + } + + return `@${context.payload.pull_request.user.login} This pull request changes the \`${modules.map(m => m.name).join(", ")}\` module${(modules.length > 1 ? 's' : '')}. Here are a list of what the components currently look like in figma. + +${modules.map(module => { + return `#### ${module.name}\n${componentsTemplate(module)}` +}).join("\n")}` + }) } module.exports = robot => { + // Will trigger whenever a new PR is opened or pushed to robot.on(['pull_request.opened', 'pull_request.synchronize'], async context => { + let message = "" // Get the diff of the PR const diff = (await context.github.pullRequests.get(context.issue({ headers: { Accept: 'application/vnd.github.diff' } }))).data - let data = {} + switch (context.payload.repository.full_name) { + case "primer/octicons": + message = (await octiconsBeforeAfter(diff, context)) + break; + case "primer/primer": + message = (await primerComponentChanges(diff, context)) + break; + default: + } - diff.match(/^[-+]\s.*www\.figma\.com\/file\/.+\//gm).forEach(m => { - data[m[0] === '-' ? 'before' : 'after'] = { - 'fileId': /www\.figma\.com\/file\/(.+)\//.exec(m).pop() - } - }) - - if (data.before.fileId && data.after.fileId) { - // Get Before components - data.before.components = (await getFigmaComponents(data.before.fileId)) - - // Get After components - data.after.components = (await getFigmaComponents(data.after.fileId)) - - // Get Before images - let bimages = (await getFigmaImages(data.before.fileId, Object.keys(data.before.components).join(','))) - - bimages.forEach(bi => { - data.before.components[bi.id].image = bi - }) - - // Get After images - let aimages = (await getFigmaImages(data.after.fileId, Object.keys(data.after.components).join(','))) - - aimages.forEach(ai => { - data.after.components[ai.id].image = ai - }) - - // Mark any that changed on the surface (no data in first call) - Object.keys(data.before.components).forEach((k) => { - if (!hasChanged(data.before.components[k], data.after.components[k])) { - delete data.before.components[k] - delete data.after.components[k] - } - }) - - // Exit early if no components have changed - if (Object.keys(data.before.components).length === 0 || - Object.keys(data.after.components).length === 0) return - - const params = context.issue({body: changeComment(data)}) + // Determine if there is already a comment on this PR from ci-reporter + const comments = await context.github.issues.getComments(context.issue({ number: context.payload.pull_request.number })) + const comment = comments.data.find(comment => comment.user.login === 'figma-diff[bot]') + // If there is, edit that one + if (comment) { + const params = context.issue({id: comment.id, body: message}) + return context.github.issues.editComment(params) + } else { + const params = context.issue({body: message}) return context.github.issues.createComment(params) } + }) } diff --git a/package.json b/package.json index dd80177..c2ca90e 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ }, "dependencies": { "got": "^8.3.0", - "probot": "^6.0.0" + "probot": "^6.1.0" }, "devDependencies": { "jest": "^21.2.1",