Skip to content

feat: added in logic to update notion status by PR number #16

New issue

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

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

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 90 additions & 11 deletions update_notion/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ try {
'refs/heads/dev',
]

if (allowedBranches.indexOf(GITHUB_REF) !== -1) {
if (allowedBranches.indexOf(GITHUB_REF) !== -1) {
const branchName = GITHUB_REF.split('/').pop()
_updateNotionStatuses(branchName)
}
Expand All @@ -24,15 +24,94 @@ try {
}

function extractPrNumber (commitMessage) {
const match = commitMessage
.match(/#[0-9]{1,4}/)
// get pr number from commit message
const match = commitMessage.match(/#(\d+)/)

if (match && match.length) {
return match[0].substring(1)
return Number(match[0].substring(1))
}
return undefined
}

const repoNameToNotionDatabaseProperty = {
'coursedogv3': 'CoursedogV3 PR',
'coursedog-catalog': 'Coursedog Catalog PR',
}

const repoNameToPRStatusLink = {
'coursedogv3': {
Open: '951fe09381834d8eb24a500537b5a5ca',
Merged: '85e90beb439c4897badd4e5effb73a89',
},
'coursedog-catalog': {
Open: '6d90bd1de3b64b09ac082f87e899c5bc',
Merged: '49e183df17dd4995bac9edac14e1ac5c',
},
}

async function updatePRStatus (prNumber, status) {
const NOTION_DATABASE_TOKEN = core.getInput('NOTION_DATABASE_TOKEN')
const NOTION_API_KEY = core.getInput('NOTION_API_KEY')
const NOTION_PR_DATABASE_TOKEN = core.getInput('NOTION_PR_DATABASE_TOKEN') || 'd1a47b75a15c438ebae10cd57c8f1101'
const { GITHUB_REPOSITORY } = process.env
const [ repositoryName ] = GITHUB_REPOSITORY.split('/')

const masterTaskDatabase = new Notion({
apiKey: NOTION_API_KEY,
databaseToken: NOTION_DATABASE_TOKEN,
})

const linkToPR = `${repositoryName}/pull/${prNumber}`
// Check if there is a task with the PR number
// If there is, update the status of the task
const taskWithPRNumber = await masterTaskDatabase.getTaskByGithubPRInput(linkToPR)
if (taskWithPRNumber && taskWithPRNumber.results.length) {
await masterTaskDatabase.updateByPR(linkToPR, status)
return
}

const coursedogV3PRDatabaseNotionUtil = new Notion({
apiKey: NOTION_API_KEY,
databaseToken: NOTION_PR_DATABASE_TOKEN,
})
// If there isn't take the following steps:
// 1. Search with the PR number in the PR database
// 2. Get the relevant task IDs from the PR database
// 3. Get the details of the tasks from the master task database
// 4. Get the list of PRs from the task
// 5. Check the status of the PRs
// 6. If all the PR statuses are merged, update the status of the task
const taskWithPRNumberFromMasterTask = await coursedogV3PRDatabaseNotionUtil.getPageByPRNumber(prNumber)
const taskIds = taskWithPRNumberFromMasterTask.properties['Task']?.['relation'].map(
(item) => item.id
)
const listOfTasks = await Promise.all(taskIds.map((eachTaskId) => masterTaskDatabase.getPageById(eachTaskId)))
for (let index = 0; index < listOfTasks.length; index++) {
const eachTask = listOfTasks[index]
const listOfLinkedPRPageIds = eachTask.properties[repoNameToNotionDatabaseProperty[repositoryName]]?.['relation'].map(
(item) => item.id
)

const listOfLinkedPRPages = await Promise
.all(listOfLinkedPRPageIds
.map((eachPRPageId) => coursedogV3PRDatabaseNotionUtil.getPageById(eachPRPageId))
)

const PRStatuses = listOfLinkedPRPages
.map((eachPRPage) => eachPRPage
.properties['State']
.relation
.map((item) => item.id)
)
.flat()
.map((eachPRStatusId) => eachPRStatusId.replace(/-/g, ''))

if (PRStatuses.every((status)=> status === repoNameToPRStatusLink[repositoryName]['Open'])) {
await masterTaskDatabase.updateTaskStatusById(eachTask.id, status)
}
}
}

/**
* Function to update the status of the tasks based on
* the recent commit is getting merged to which branch
Expand All @@ -59,7 +138,7 @@ async function _updateNotionStatuses (branch) {
})

const [ githubOwner, repositoryName ] = GITHUB_REPOSITORY.split('/')

// Get most recent commit to branch
const { data } = await octokit.rest.repos.getCommit({
owner: githubOwner,
Expand All @@ -80,34 +159,34 @@ async function _updateNotionStatuses (branch) {
case 'main':
if (commitMessage.includes('from coursedog/staging')) {
// Update all tasks that are in Completed Staging to Completed Prod
notionUtil.updateByStatus('Completed (Staging)', 'Completed (Production)')
await notionUtil.updateByStatus('Completed (Staging)', 'Completed (Production)')
} else if (commitMessage.match(/#+[0-9]/)) {
// direct from open PR to staging
const prNumber = extractPrNumber(commitMessage)
if (!prNumber) return
notionUtil.updateByPR(`${repositoryName}/pull/${prNumber}`, 'Completed (Production)')
await updatePRStatus(prNumber, 'Completed (Production)')
}
break
case 'staging':
if (commitMessage.includes('from coursedog/dev')) {
// Update all tasks that are in Completed Dev to Completed Staging
notionUtil.updateByStatus('Completed (Dev)', 'Completed (Staging)')
await notionUtil.updateByStatus('Completed (Dev)', 'Completed (Staging)')
} else if (commitMessage.match(/#+[0-9]/)) {
// direct from open PR to staging
const prNumber = extractPrNumber(commitMessage)
if (!prNumber) return
notionUtil.updateByPR(`${repositoryName}/pull/${prNumber}`, 'Completed (Staging)')
await updatePRStatus(prNumber, 'Completed (Staging)')
}
break
case 'dev':
if (commitMessage.match(/#+[0-9]/)) {
// direct from open PR to dev
const prNumber = extractPrNumber(commitMessage)
if (!prNumber) return
notionUtil.updateByPR(`${repositoryName}/pull/${prNumber}`, 'Completed (Dev)')
await updatePRStatus(prNumber, 'Completed (Dev)')
}
break

default:
break
}
Expand Down
82 changes: 73 additions & 9 deletions utils/notion.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
const fs = require('fs')
const { Client }= require('@notionhq/client')
const { Client } = require('@notionhq/client')

class Notion {
constructor ({ apiKey, databaseToken, testDatabase }) {
// Retrieving all the input parameters relevant to notion
this.notionDatabaseToken = databaseToken
this.testDatabase = testDatabase

// Initializing the notion client
this.client = new Client({ auth: apiKey })
this.labels = {
GITHUB_PR: 'GitHub PR',
STATUS: 'Status',
DATE_COMPLETED: 'Date Completed',
PR_NUMBER: 'PR Number',
}
}

Expand Down Expand Up @@ -64,6 +65,69 @@ class Notion {
}
}

async getPageById (pageId) {
return this.client.pages.retrieve({
page_id: pageId,
})
}

async getPageByPRNumber (prNumber) {
const databaseId = this.notionDatabaseToken
const listOfTasks = await this.client.databases.query({
database_id: databaseId,
filter: {
and: [
{
property: this.labels.PR_NUMBER,
number: {
equals: prNumber,
},
},
],
},
})
return listOfTasks.results?.[0]
}

async getTaskByGithubPRInput (prLink) {
const databaseId = this.notionDatabaseToken

const listOfTasks = await this.client.databases.query({
database_id: databaseId,
filter: {
and: [
{
property: this.labels.GITHUB_PR,
text: {
contains: prLink,
},
},
],
},
})

return listOfTasks
}

async updateTaskStatusById (taskId, newStatus) {
const updatedTasks = await this.client.pages.update({
page_id: taskId,
properties: {
[this.labels.STATUS]: {
select: {
name: newStatus,
},
},
[this.labels.DATE_COMPLETED]: {
date: {
start: new Date().toISOString(),
},
},
},
})
console.log('Updated', updatedTasks)
}

/**
* Function to promote the task by the Github PR field
*
Expand Down Expand Up @@ -173,7 +237,7 @@ class Notion {
],
})
}

/**
* Function to update an existing feature block
*
Expand Down Expand Up @@ -217,7 +281,7 @@ class Notion {
},
},
})

const pageBlocks = await this.client.blocks.children.list({
block_id: card.id,
page_size: 100,
Expand All @@ -226,9 +290,9 @@ class Notion {
const dividerIndex = pageBlocks.results
.reverse()
.findIndex(block => block.type === 'unsupported')

const blocksToDelete = pageBlocks.results.slice(0, dividerIndex)

// NOTE: Delete all blocks after the last unsupported block (likely the divider)
if (blocksToDelete.length) {
for (const block of blocksToDelete) {
Expand All @@ -237,7 +301,7 @@ class Notion {
})
}
}

// NOTE: Restore the feature block
await this.client.blocks.children.append({
block_id: card.id,
Expand All @@ -261,7 +325,7 @@ class Notion {
* @returns {String} Name of the product which is to be used to tag the file
*/
__getProduct (filePath) {

const {
GITHUB_REPOSITORY,
} = process.env
Expand Down Expand Up @@ -358,7 +422,7 @@ class Notion {
})
}
}

}

module.exports = Notion