diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index d75b5d3f7a048..f337989a42a7c 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,3 +1,6 @@ +# Ignore CHANGELOG.md files to prevent Danger.js from triggering code owner reviews +/packages/**/CHANGELOG.md @ghost + /packages/@unimodules/core @sjchmiela @tsapeta /packages/@unimodules/react-native-adapter @sjchmiela @tsapeta /packages/babel-preset-expo @brentvatne diff --git a/dangerfile.ts b/dangerfile.ts index ffa8ccc6a6e19..03a80e8e7beb8 100644 --- a/dangerfile.ts +++ b/dangerfile.ts @@ -2,7 +2,7 @@ import { checkChangelog } from '@expo/danger'; const allowedUsers = ['lukmccall', 'sjchmiela', 'tsapeta', 'bbarthec', 'mczernek']; // eslint-disable-next-line no-undef -const prAuthor = danger.github.pr.base.user.login; +const prAuthor = danger.github.pr.user.login; if (allowedUsers.includes(prAuthor)) { checkChangelog(); } diff --git a/packages/danger/build/ChangelogChecker.js b/packages/danger/build/ChangelogChecker.js index 475f131aeaf1a..455c3bfc9bd1b 100644 --- a/packages/danger/build/ChangelogChecker.js +++ b/packages/danger/build/ChangelogChecker.js @@ -18,7 +18,7 @@ const PullRequestManager_1 = require("./PullRequestManager"); const Utils_1 = require("./Utils"); // Setup const pr = danger.github.pr; -const prAuthor = pr.base.user.login; +const prAuthor = pr.user.login; const pullRequestManager = PullRequestManager_1.createPullRequestManager(danger.github.api, pr); async function getFileDiffAsync(path) { const { stdout } = await spawn_async_1.default('git', ['diff', '--', path], { diff --git a/packages/danger/build/ChangelogChecker.js.map b/packages/danger/build/ChangelogChecker.js.map index eb0d8a4cf9a89..e6e08eba1eedc 100644 --- a/packages/danger/build/ChangelogChecker.js.map +++ b/packages/danger/build/ChangelogChecker.js.map @@ -1 +1 @@ -{"version":3,"file":"ChangelogChecker.js","sourceRoot":"","sources":["../src/ChangelogChecker.ts"],"names":[],"mappings":"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","sourcesContent":["import spawnAsync from '@expo/spawn-async';\nimport * as fs from 'fs';\nimport { groupBy } from 'lodash';\nimport * as path from 'path';\n\nimport {\n createPullRequestManager,\n ChangelogEntry,\n ChangelogEntryType,\n DEFAULT_CHANGELOG_ENTRY_KEY,\n} from './PullRequestManager';\nimport {\n getExpoRepositoryRootDir,\n getFileContentAsync,\n getPackageChangelogRelativePath,\n} from './Utils';\n\nexport type PackageChangelogEntry = ChangelogEntry & {\n packageName: string;\n};\n\nexport type FixedChangelogEntry = PackageChangelogEntry & { content: string; diff: string };\n\n// Setup\nconst pr = danger.github.pr;\nconst prAuthor = pr.base.user.login;\nconst pullRequestManager = createPullRequestManager(danger.github.api, pr);\n\nasync function getFileDiffAsync(path): Promise {\n const { stdout } = await spawnAsync('git', ['diff', '--', path], {\n cwd: getExpoRepositoryRootDir(),\n });\n return stdout;\n}\n\n/**\n * @returns `false` if `CHANGELOG.md` doesn't exist in provided package.\n */\nfunction isChangelogModified(packageName: string, modifiedFiles: string[]): boolean {\n const changelogPath = getPackageChangelogRelativePath(packageName);\n\n return (\n modifiedFiles.includes(changelogPath) ||\n !fs.existsSync(path.join(getExpoRepositoryRootDir(), changelogPath))\n );\n}\n\nfunction getSuggestedChangelogEntries(packageNames: string[]): PackageChangelogEntry[] {\n const {\n [DEFAULT_CHANGELOG_ENTRY_KEY]: defaultEntry,\n ...suggestedEntries\n } = pullRequestManager.parseChangelogSuggestionFromDescription();\n return packageNames.map(packageName => {\n const message = suggestedEntries[packageName]?.message ?? defaultEntry.message;\n const type = suggestedEntries[packageName]?.type ?? defaultEntry.type;\n return {\n packageName,\n message,\n type,\n };\n });\n}\n\nasync function runAddChangelogCommandAsync(\n suggestedEntries: PackageChangelogEntry[]\n): Promise {\n for (const entry of suggestedEntries) {\n await spawnAsync('et', [\n `add-changelog`,\n `--package`,\n entry.packageName,\n `--entry`,\n entry.message,\n `--author`,\n prAuthor,\n `--type`,\n entryTypeToString(entry.type),\n `--pull-request`,\n `${pr.number}`,\n ]);\n }\n\n return Promise.all(\n suggestedEntries.map(async entry => {\n const changelogPath = path.join(\n getExpoRepositoryRootDir(),\n getPackageChangelogRelativePath(entry.packageName)\n );\n return {\n ...entry,\n content: await getFileContentAsync(changelogPath),\n diff: await getFileDiffAsync(changelogPath),\n };\n })\n );\n}\n\nfunction generateReport(\n missingEntries: { packageName: string; diff: string }[],\n url?: string | null\n) {\n const message = missingEntries\n .map(\n entry =>\n `- ${danger.github.utils.fileLinks(\n [getPackageChangelogRelativePath(entry.packageName)],\n false\n )}`\n )\n .join('\\n');\n\n const diff = '```diff\\n' + missingEntries.map(entry => entry.diff).join('\\n') + '```\\n';\n const pr = url ? `#### or merge this pull request: ${url}` : '';\n fail(`\nšŸ“‹ **Missing Changelog**\n------\nšŸ›  Add missing entires to:\n${message}`);\n\n markdown(\n `\n### šŸ›  Suggested fixes:\n\n
\n šŸ“‹ Missing changelog\n\n #### Apply suggested changes:\n${diff}\n${pr} \n
`\n );\n}\n\n/**\n * This function checks if the changelog was modified, doing the following steps:\n * - get packages which were modified but don't have changes in `CHANGELOG.md`\n * - parse PR body to get suggested entries for those packages\n * - run `et add-changelog` for each package to apply the suggestion\n * - create a new PR\n * - add a comment to inform about missing changelog\n * - fail CI job\n */\nexport async function checkChangelog(): Promise {\n const modifiedPackages = groupBy(\n danger.git.modified_files.filter(file => file.startsWith('packages')),\n file => file.split(path.sep)[1]\n );\n\n const packagesWithoutChangelog = Object.entries(modifiedPackages)\n .filter(([packageName, files]) => !isChangelogModified(packageName, files))\n .map(([packageName]) => packageName);\n if (packagesWithoutChangelog.length === 0) {\n message(`āœ… **Changelog**`);\n return;\n }\n\n // gets suggested entries based on pull request\n const suggestedEntries = getSuggestedChangelogEntries(packagesWithoutChangelog);\n\n // applies suggested fixes using `et add-changelog` command\n const fixedEntries = await runAddChangelogCommandAsync(suggestedEntries);\n\n // creates/updates PR form result of `et` command - it will be merged to the current PR\n const { html_url } = (await pullRequestManager.createOrUpdatePRAsync(fixedEntries)) || {};\n\n // generates danger report. It will contain result of `et` command as a git diff and link to created PR\n await generateReport(fixedEntries, html_url);\n}\n\nfunction entryTypeToString(type: ChangelogEntryType): string {\n switch (type) {\n case ChangelogEntryType.BUG_FIXES:\n return 'bug-fix';\n case ChangelogEntryType.NEW_FEATURES:\n return 'new-feature';\n case ChangelogEntryType.BREAKING_CHANGES:\n return 'breaking-change';\n }\n\n throw new Error(`Unknown entry type ${type}.`);\n}\n"]} \ No newline at end of file +{"version":3,"file":"ChangelogChecker.js","sourceRoot":"","sources":["../src/ChangelogChecker.ts"],"names":[],"mappings":"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","sourcesContent":["import spawnAsync from '@expo/spawn-async';\nimport * as fs from 'fs';\nimport { groupBy } from 'lodash';\nimport * as path from 'path';\n\nimport {\n createPullRequestManager,\n ChangelogEntry,\n ChangelogEntryType,\n DEFAULT_CHANGELOG_ENTRY_KEY,\n} from './PullRequestManager';\nimport {\n getExpoRepositoryRootDir,\n getFileContentAsync,\n getPackageChangelogRelativePath,\n} from './Utils';\n\nexport type PackageChangelogEntry = ChangelogEntry & {\n packageName: string;\n};\n\nexport type FixedChangelogEntry = PackageChangelogEntry & { content: string; diff: string };\n\n// Setup\nconst pr = danger.github.pr;\nconst prAuthor = pr.user.login;\nconst pullRequestManager = createPullRequestManager(danger.github.api, pr);\n\nasync function getFileDiffAsync(path): Promise {\n const { stdout } = await spawnAsync('git', ['diff', '--', path], {\n cwd: getExpoRepositoryRootDir(),\n });\n return stdout;\n}\n\n/**\n * @returns `false` if `CHANGELOG.md` doesn't exist in provided package.\n */\nfunction isChangelogModified(packageName: string, modifiedFiles: string[]): boolean {\n const changelogPath = getPackageChangelogRelativePath(packageName);\n\n return (\n modifiedFiles.includes(changelogPath) ||\n !fs.existsSync(path.join(getExpoRepositoryRootDir(), changelogPath))\n );\n}\n\nfunction getSuggestedChangelogEntries(packageNames: string[]): PackageChangelogEntry[] {\n const {\n [DEFAULT_CHANGELOG_ENTRY_KEY]: defaultEntry,\n ...suggestedEntries\n } = pullRequestManager.parseChangelogSuggestionFromDescription();\n return packageNames.map(packageName => {\n const message = suggestedEntries[packageName]?.message ?? defaultEntry.message;\n const type = suggestedEntries[packageName]?.type ?? defaultEntry.type;\n return {\n packageName,\n message,\n type,\n };\n });\n}\n\nasync function runAddChangelogCommandAsync(\n suggestedEntries: PackageChangelogEntry[]\n): Promise {\n for (const entry of suggestedEntries) {\n await spawnAsync('et', [\n `add-changelog`,\n `--package`,\n entry.packageName,\n `--entry`,\n entry.message,\n `--author`,\n prAuthor,\n `--type`,\n entryTypeToString(entry.type),\n `--pull-request`,\n `${pr.number}`,\n ]);\n }\n\n return Promise.all(\n suggestedEntries.map(async entry => {\n const changelogPath = path.join(\n getExpoRepositoryRootDir(),\n getPackageChangelogRelativePath(entry.packageName)\n );\n return {\n ...entry,\n content: await getFileContentAsync(changelogPath),\n diff: await getFileDiffAsync(changelogPath),\n };\n })\n );\n}\n\nfunction generateReport(\n missingEntries: { packageName: string; diff: string }[],\n url?: string | null\n) {\n const message = missingEntries\n .map(\n entry =>\n `- ${danger.github.utils.fileLinks(\n [getPackageChangelogRelativePath(entry.packageName)],\n false\n )}`\n )\n .join('\\n');\n\n const diff = '```diff\\n' + missingEntries.map(entry => entry.diff).join('\\n') + '```\\n';\n const pr = url ? `#### or merge this pull request: ${url}` : '';\n fail(`\nšŸ“‹ **Missing Changelog**\n------\nšŸ›  Add missing entires to:\n${message}`);\n\n markdown(\n `\n### šŸ›  Suggested fixes:\n\n
\n šŸ“‹ Missing changelog\n\n #### Apply suggested changes:\n${diff}\n${pr} \n
`\n );\n}\n\n/**\n * This function checks if the changelog was modified, doing the following steps:\n * - get packages which were modified but don't have changes in `CHANGELOG.md`\n * - parse PR body to get suggested entries for those packages\n * - run `et add-changelog` for each package to apply the suggestion\n * - create a new PR\n * - add a comment to inform about missing changelog\n * - fail CI job\n */\nexport async function checkChangelog(): Promise {\n const modifiedPackages = groupBy(\n danger.git.modified_files.filter(file => file.startsWith('packages')),\n file => file.split(path.sep)[1]\n );\n\n const packagesWithoutChangelog = Object.entries(modifiedPackages)\n .filter(([packageName, files]) => !isChangelogModified(packageName, files))\n .map(([packageName]) => packageName);\n if (packagesWithoutChangelog.length === 0) {\n message(`āœ… **Changelog**`);\n return;\n }\n\n // gets suggested entries based on pull request\n const suggestedEntries = getSuggestedChangelogEntries(packagesWithoutChangelog);\n\n // applies suggested fixes using `et add-changelog` command\n const fixedEntries = await runAddChangelogCommandAsync(suggestedEntries);\n\n // creates/updates PR form result of `et` command - it will be merged to the current PR\n const { html_url } = (await pullRequestManager.createOrUpdatePRAsync(fixedEntries)) || {};\n\n // generates danger report. It will contain result of `et` command as a git diff and link to created PR\n await generateReport(fixedEntries, html_url);\n}\n\nfunction entryTypeToString(type: ChangelogEntryType): string {\n switch (type) {\n case ChangelogEntryType.BUG_FIXES:\n return 'bug-fix';\n case ChangelogEntryType.NEW_FEATURES:\n return 'new-feature';\n case ChangelogEntryType.BREAKING_CHANGES:\n return 'breaking-change';\n }\n\n throw new Error(`Unknown entry type ${type}.`);\n}\n"]} \ No newline at end of file diff --git a/packages/danger/src/ChangelogChecker.ts b/packages/danger/src/ChangelogChecker.ts index 9da9f1043b57f..3f0d8b3029178 100644 --- a/packages/danger/src/ChangelogChecker.ts +++ b/packages/danger/src/ChangelogChecker.ts @@ -23,7 +23,7 @@ export type FixedChangelogEntry = PackageChangelogEntry & { content: string; dif // Setup const pr = danger.github.pr; -const prAuthor = pr.base.user.login; +const prAuthor = pr.user.login; const pullRequestManager = createPullRequestManager(danger.github.api, pr); async function getFileDiffAsync(path): Promise {