From 963ff8d1ac339e988525784c95c087ec16d75238 Mon Sep 17 00:00:00 2001 From: emawby Date: Fri, 24 Mar 2023 13:19:30 -0700 Subject: [PATCH] Setting issue response time when an issue is closed or commented on by a OneSignal team member The action is triggered when an issue is closed or it is commented on by a OneSignal employee. This action sets the response time in business days for that issue inside the issue html as a comment. This is based on https://github.com/probot/metadata This PR does not include the script to calculate the response time --- .github/os_probot_metadata.js | 58 +++++++++++++++++++++++++ .github/set_response_times.js | 47 ++++++++++++++++++++ .github/workflows/set_response_time.yml | 32 ++++++++++++++ 3 files changed, 137 insertions(+) create mode 100644 .github/os_probot_metadata.js create mode 100644 .github/set_response_times.js create mode 100644 .github/workflows/set_response_time.yml diff --git a/.github/os_probot_metadata.js b/.github/os_probot_metadata.js new file mode 100644 index 00000000..9708a592 --- /dev/null +++ b/.github/os_probot_metadata.js @@ -0,0 +1,58 @@ +/** + * Based on probot-metadata - https://github.com/probot/metadata + */ +const regex = /\n\n/ + +const { Octokit } = require("@octokit/action") + +const octokit = new Octokit() + +module.exports = (context, issue = null) => { + console.log(context) + const prefix = "onesignal-probot" + + if (!issue) issue = context.payload.issue + + return { + async get (key = null) { + let body = issue.body + + if (!body) { + body = (await octokit.issues.get(issue)).data.body || '' + } + + const match = body.match(regex) + + if (match) { + const data = JSON.parse(match[1])[prefix] + return key ? data && data[key] : data + } + }, + + async set (key, value) { + let body = issue.body + let data = {} + + if (!body) body = (await octokit.issues.get(issue)).data.body || '' + + body = body.replace(regex, (_, json) => { + data = JSON.parse(json) + return '' + }) + + if (!data[prefix]) data[prefix] = {} + + if (typeof key === 'object') { + Object.assign(data[prefix], key) + } else { + data[prefix][key] = value + } + + body = `${body}\n\n` + + const [owner, repo] = process.env.GITHUB_REPOSITORY.split("/") + const issue_number = context.payload.issue.number + return octokit.issues.update({ owner, repo, issue_number, body }) + } + } +} diff --git a/.github/set_response_times.js b/.github/set_response_times.js new file mode 100644 index 00000000..5bcac449 --- /dev/null +++ b/.github/set_response_times.js @@ -0,0 +1,47 @@ +function calcResponseTimeForIssueCreatedAt(createdAt) { + const issueOpenedDate = new Date(createdAt); + const issueTriagedDate = new Date(); + const businessDaysResponseTime = calcBusinessDaysBetweenDates(issueOpenedDate, issueTriagedDate); + return businessDaysResponseTime; +} + +function calcBusinessDaysBetweenDates(openedDate, triagedDate) { + let differenceInWeeks, responseTime; + if (triagedDate < openedDate) + return -1; // error code if dates transposed + let openedDay = openedDate.getDay(); // day of week + let triagedDay = triagedDate.getDay(); + openedDay = (openedDay == 0) ? 7 : openedDay; // change Sunday from 0 to 7 + triagedDay = (triagedDay == 0) ? 7 : triagedDay; + openedDay = (openedDay > 5) ? 5 : openedDay; // only count weekdays + triagedDay = (triagedDay > 5) ? 5 : triagedDay; + // calculate differnece in weeks (1000mS * 60sec * 60min * 24hrs * 7 days = 604800000) + differenceInWeeks = Math.floor((triagedDate.getTime() - openedDate.getTime()) / 604800000); + if (openedDay < triagedDay) { //Equal to makes it reduce 5 days + responseTime = (differenceInWeeks * 5) + (triagedDay - openedDay); + } + else if (openedDay == triagedDay) { + responseTime = differenceInWeeks * 5; + } + else { + responseTime = ((differenceInWeeks + 1) * 5) - (openedDay - triagedDay); + } + return (responseTime); +} + +module.exports = async(context, osmetadata) => { + const foundResponseTime = await osmetadata(context).get('response_time_in_business_days'); + if (foundResponseTime) { + const foundString = "already found response time in business days: " + foundResponseTime + console.log(foundString); + return foundString; + } + if (context.payload.comment && context.payload.comment.author_association != "MEMBER" && context.payload.comment.author_association != "OWNER" && context.payload.comment.author_association != "CONTRIBUTOR") { + return; + } + const businessDaysResponseTime = calcResponseTimeForIssueCreatedAt(context.payload.issue.created_at); + console.log("response time in business days: " + businessDaysResponseTime); + const result = osmetadata(context, context.payload.issue).set('response_time_in_business_days', businessDaysResponseTime) + console.log("osmetadata update result: " + result); + return "set response time in business days: " + businessDaysResponseTime; +} diff --git a/.github/workflows/set_response_time.yml b/.github/workflows/set_response_time.yml new file mode 100644 index 00000000..e77fc84d --- /dev/null +++ b/.github/workflows/set_response_time.yml @@ -0,0 +1,32 @@ +name: Set Response Time +on: + issue_comment: + types: + - created + issues: + types: + - closed +jobs: + calculate: + name: set reponse time for the issue + if: github.event.issue.pull_request == null + runs-on: ubuntu-latest + permissions: + issues: write + steps: + - uses: actions/checkout@v3 + with: + token: ${{ secrets.GITHUB_TOKEN }} + - run: npm install @octokit/action + - uses: actions/github-script@v6 + id: set-time + with: + result-encoding: string + script: | + const os_probot_metadata = require('./.github/os_probot_metadata.js') + const set_response_time = require('./.github/set_response_times.js') + return await set_response_time(context, os_probot_metadata) + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Get result + run: echo "${{steps.set-time.outputs.result}}" >> $GITHUB_STEP_SUMMARY