-
Notifications
You must be signed in to change notification settings - Fork 582
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore: util script for exporting notion cards to jira (#10983)
* skeleton script for fetching from notion * create tickets in jira * fix linking * add explanatory comment * fix usage error * bump
- Loading branch information
1 parent
655d1ad
commit 4eee9bc
Showing
2 changed files
with
146 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
#!/usr/bin/env node | ||
/// <reference types="node" /> | ||
// @ts-check | ||
"use strict" | ||
|
||
import { resolve } from "path" | ||
import chalk from "chalk" | ||
import { config } from "dotenv" | ||
import { hideBin } from "yargs/helpers" | ||
import yargs from "yargs/yargs" | ||
|
||
config({ path: resolve(__dirname, "../../.env.releases") }) | ||
|
||
/** | ||
* | ||
* Convenience script for fetching notion cards from our mobile QA and creating Jira issues for them. | ||
* Usage: yarn export-notion-to-jira <databaseId> | ||
* To get the database id, go to the latest Mobile QA page, scroll to the bugs section, | ||
* click on the dots next to "Board View" and select "Copy Link". | ||
* The link should be of format: https://www.notion.so/artsy/<databaseId>?v=<version>&pvs=<pvs> | ||
* | ||
*/ | ||
|
||
const NOTION_API_TOKEN = process.env.NOTION_API_TOKEN | ||
const JIRA_BASE_URL = process.env.JIRA_BASE_URL | ||
const JIRA_EMAIL = process.env.JIRA_EMAIL | ||
const JIRA_API_TOKEN = process.env.JIRA_API_TOKEN | ||
|
||
if (!NOTION_API_TOKEN) { | ||
console.error(chalk.bold.red("Missing NOTION_API_TOKEN in environment variables.")) | ||
process.exit(1) | ||
} | ||
|
||
if (!JIRA_BASE_URL || !JIRA_EMAIL || !JIRA_API_TOKEN) { | ||
console.error(chalk.bold.red("Missing Jira credentials in environment variables.")) | ||
process.exit(1) | ||
} | ||
|
||
const argv = yargs(hideBin(process.argv)).argv as any | ||
const databaseId = argv._[0] | ||
|
||
if (!databaseId) { | ||
console.error(chalk.bold.red("Usage: yarn export-notion-to-jira <databaseId>")) | ||
process.exit(1) | ||
} | ||
|
||
async function fetchNotionDatabase(databaseId: string) { | ||
try { | ||
const response = await fetch(`https://api.notion.com/v1/databases/${databaseId}/query`, { | ||
method: "POST", | ||
headers: { | ||
Authorization: `Bearer ${NOTION_API_TOKEN}`, | ||
"Content-Type": "application/json", | ||
"Notion-Version": "2022-06-28", | ||
}, | ||
}) | ||
|
||
if (!response.ok) { | ||
throw new Error(`Failed to fetch database: ${response.status} ${response.statusText}`) | ||
} | ||
|
||
const data = await response.json() | ||
console.log(chalk.bold.green("Successfully fetched Notion database")) | ||
return data | ||
} catch (error) { | ||
console.error(chalk.bold.red("Error fetching Notion database:")) | ||
console.error(error) | ||
} | ||
} | ||
|
||
async function createJiraIssue(issueSummary: string, issueLink: string) { | ||
try { | ||
const auth = Buffer.from(`${JIRA_EMAIL}:${JIRA_API_TOKEN}`).toString("base64") | ||
const response = await fetch(`${JIRA_BASE_URL}/rest/api/3/issue`, { | ||
method: "POST", | ||
headers: { | ||
Authorization: `Basic ${auth}`, | ||
"Content-Type": "application/json", | ||
}, | ||
body: JSON.stringify({ | ||
fields: { | ||
project: { | ||
key: "APPL", | ||
}, | ||
summary: issueSummary, | ||
description: { | ||
type: "doc", | ||
version: 1, | ||
content: [ | ||
{ | ||
type: "paragraph", | ||
content: [ | ||
{ | ||
type: "text", | ||
text: "Auto-generated from mobile QA Notion card ", | ||
}, | ||
{ | ||
type: "text", | ||
text: "here", | ||
marks: [ | ||
{ | ||
type: "link", | ||
attrs: { | ||
href: issueLink, | ||
}, | ||
}, | ||
], | ||
}, | ||
], | ||
}, | ||
], | ||
}, | ||
issuetype: { | ||
name: "Bug", | ||
}, | ||
}, | ||
}), | ||
}) | ||
|
||
if (!response.ok) { | ||
console.log(await response.text()) | ||
throw new Error(`Failed to create Jira issue: ${response.status} ${response.statusText}`) | ||
} | ||
|
||
const data = await response.json() | ||
console.log(chalk.bold.green("Successfully created Jira issue:")) | ||
console.log(JSON.stringify(data, null, 2)) | ||
} catch (error) { | ||
console.error(chalk.bold.red("Error creating Jira issue:")) | ||
console.error(error) | ||
} | ||
} | ||
|
||
async function main() { | ||
const notionData = await fetchNotionDatabase(databaseId) | ||
if (notionData && notionData.results) { | ||
for (const page of notionData.results) { | ||
const issueSummary = page.properties.Name.title[0]?.plain_text || "No Title" | ||
const notionPageUrl = page.url | ||
await createJiraIssue(issueSummary, notionPageUrl) | ||
} | ||
} | ||
} | ||
|
||
main().catch((err) => console.error(chalk.bold.red(err))) |