diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0774adb..9e7ac46 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -66,6 +66,7 @@ jobs: - name: Save Artifacts uses: actions/upload-artifact@v3 + if: always() with: name: tbdocs-reporter-output path: ./.tbdocs diff --git a/.github/workflows/tbdocs-commenter.yml b/.github/workflows/tbdocs-commenter.yml new file mode 100644 index 0000000..b251399 --- /dev/null +++ b/.github/workflows/tbdocs-commenter.yml @@ -0,0 +1,51 @@ +name: TBDocs Commenter + +on: + workflow_run: + workflows: ['Continuous Integration'] + types: + - completed + +jobs: + comment-action: + name: TBDocs PR Comment + runs-on: ubuntu-latest + # runs only if it's triggered from a PR + if: github.event.workflow_run.pull_requests[0].number != null + + steps: + - name: Download TBDocs Report + uses: dawidd6/action-download-artifact@v2 + with: + run_id: ${{ github.event.workflow_run.id }} + name: tbdocs-reporter-output + path: ./.tbdocs + + - name: Report Aux Vars + id: report + run: | + content=$(cat .tbdocs/docs-report.md) + echo "::set-output name=content::$content" + + timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ") + echo "::set-output name=updated-at::$timestamp" + + - name: Find Comment + uses: peter-evans/find-comment@v2 + id: fc + with: + issue-number: ${{ github.event.workflow_run.pull_requests[0].number }} + comment-author: 'github-actions[bot]' + body-includes: TBDocs Report + + # Comment content of the report.md file on the PR + - name: Comment on PR + uses: peter-evans/create-or-update-comment@v3 + with: + comment-id: ${{ steps.fc.outputs.comment-id }} + issue-number: ${{ github.event.workflow_run.pull_requests[0].number }} + # body with the content of the downloaded artifact report.md file + body: | + ${{ steps.report.outputs.content }} + --- + TBDocs Report Updated at ${{ steps.report.outputs.timestamp }} - [${{ github.event.workflow_run.pull_requests[0].head_sha }}](https://github.com/${{ github.repository }}/commit/${{ github.event.workflow_run.pull_requests[0].head_sha }}) diff --git a/badges/coverage.svg b/badges/coverage.svg index 802feab..26bb91d 100644 --- a/badges/coverage.svg +++ b/badges/coverage.svg @@ -1 +1 @@ -Coverage: 39.28%Coverage39.28% \ No newline at end of file +Coverage: 40.11%Coverage40.11% \ No newline at end of file diff --git a/src/docs-report/index.ts b/src/docs-report/index.ts index a5ba3a1..5602547 100644 --- a/src/docs-report/index.ts +++ b/src/docs-report/index.ts @@ -3,6 +3,7 @@ import { EntryPoint } from '../interfaces' import { generateApiExtractorReport } from './api-extractor' import { DocsReport } from './interfaces' +export * from './report-markdown' export * from './interfaces' /** diff --git a/src/github/comment-report.ts b/src/docs-report/report-markdown.ts similarity index 83% rename from src/github/comment-report.ts rename to src/docs-report/report-markdown.ts index a53004c..4087100 100644 --- a/src/github/comment-report.ts +++ b/src/docs-report/report-markdown.ts @@ -4,28 +4,29 @@ import { EntryPoint } from '../interfaces' import { DocsReport, ReportMessage } from '../docs-report' import { getGithubContext } from '../utils' -import { commentPr } from './comment-pr' -import { annotateCode } from './annotate-code' - -const REPORT_HEADER_PREFIX = `**TBDocs Report**` const MISC_MESSAGES_GROUP = '_misc_group' +const REPORT_HEADER_PREFIX = `**TBDocs Report**` -export const submitReportsSummaryComment = async ( +/** + * Formats the docs reporter results into a markdown summary + * @public + */ +export const generateReportMarkdown = async ( entryPoints: EntryPoint[] -): Promise => { +): Promise => { const totalCounts = { errors: 0, warnings: 0 } - const projectsComments = entryPoints + const projectsReports = entryPoints .filter(hasPresentKey('report')) .map(ep => processReport(ep.projectName, ep.report, ep.file, totalCounts)) - const finalCommentBody = getTotalReportsSummaryCommentBody( - projectsComments, + const reportMarkdown = summarizeAllReports( + projectsReports, totalCounts.errors, totalCounts.warnings ) - await commentPr(finalCommentBody, REPORT_HEADER_PREFIX) + return reportMarkdown } /** Annotate report files and generate the comment summary */ @@ -36,13 +37,12 @@ const processReport = ( totalReportsAccumulator: { errors: number; warnings: number } ): string => { console.info(`${projectName} Report: ${JSON.stringify(report, undefined, 2)}`) - annotateCode(report.messages) totalReportsAccumulator.errors += report.errorsCount totalReportsAccumulator.warnings += report.warningsCount return getCommentReportSummary(report, projectName, file) } -export const getCommentReportSummary = ( +const getCommentReportSummary = ( report: DocsReport, projectName: string, entryPointFile: string @@ -54,7 +54,7 @@ export const getCommentReportSummary = ( return commentBody } -export const getTotalReportsSummaryCommentBody = ( +const summarizeAllReports = ( reportsComments: string[], errorsCount: number, warningsCount: number @@ -68,10 +68,11 @@ export const getTotalReportsSummaryCommentBody = ( const filesTables = reportsComments.join('\n\n') - const { shortSha, commitUrl } = getGithubContext() - const updateFooterText = `_Updated @ ${new Date().toISOString()} - Commit: [\`${shortSha}\`](${commitUrl})_` + // const { shortSha, commitUrl } = getGithubContext() + // const updateFooterText = `_Updated @ ${new Date().toISOString()} - Commit: [\`${shortSha}\`](${commitUrl})_` - return `${headerText}\n\n${subHeaderText}\n\n${filesTables}\n\n---\n${updateFooterText}` + return `${headerText}\n\n${subHeaderText}\n\n${filesTables}` + // \n\n---\n${updateFooterText} } const generateFilesTable = (report: DocsReport): string => { diff --git a/src/github/comment-pr.ts b/src/github/comment-pr.ts deleted file mode 100644 index 5c9c145..0000000 --- a/src/github/comment-pr.ts +++ /dev/null @@ -1,87 +0,0 @@ -import { Octokit } from '@octokit/rest' - -import { configInputs } from '../config' -import { getGithubContext, getOctokit } from '../utils' - -const BOT_NAME = 'github-actions[bot]' // TODO: handle botAppId - -export const commentPr = async ( - commentBody: string, - commentPrefix: string -): Promise => { - if (!configInputs.token && !configInputs.botAppId) { - console.info( - '>>> Skipping pushing comment. Missing credentials (token or botAppId)...' - ) - return - } - - const octokit = getOctokit() - - const { owner, repo, issueNumber, actor } = getGithubContext() - console.info('>>> Pushing comment to', { - owner, - repo, - issueNumber, - actor - }) - - if (owner && repo && issueNumber) { - // create a comment on the issue - const comment = await createOrUpdateComment( - octokit, - owner, - repo, - issueNumber, - commentBody, - commentPrefix - ) - - if (comment) { - console.info(`Comment: ${comment?.data.url}`) - } - } else { - console.info('>>> Skipping comment. Missing owner, repo or issueNumber') - } -} - -const createOrUpdateComment = async ( - octokit: Octokit, - owner: string, - repo: string, - issueNumber: number, - commentBody: string, - commentPrefix: string -): Promise<{ data: { url: string } } | undefined> => { - // check if the comment exist - const comments = await octokit.rest.issues.listComments({ - owner, - repo, - issue_number: issueNumber - }) - - const existingComment = comments.data.find( - comment => - comment.body?.includes(commentPrefix) && comment.user?.login === BOT_NAME - ) - - if (existingComment) { - console.info( - `>>> Updating existing comment ${existingComment.id} for the report` - ) - return octokit.rest.issues.updateComment({ - owner, - repo, - comment_id: existingComment.id, - body: commentBody - }) - } else { - console.info(`>>> Creating a brand new comment for the report`) - return octokit.rest.issues.createComment({ - owner, - repo, - issue_number: issueNumber, - body: commentBody - }) - } -} diff --git a/src/github/index.ts b/src/github/index.ts index 0a80d01..6eda83d 100644 --- a/src/github/index.ts +++ b/src/github/index.ts @@ -1,9 +1,9 @@ -import { setOutput, warning } from '@actions/core' +import { setOutput, warning, summary } from '@actions/core' import { EntryPoint } from '../interfaces' -import { submitReportsSummaryComment } from './comment-report' import { DocsReport } from '../docs-report' import { pushDocsPr } from './docs-pr' +import { annotateCode } from './annotate-code' export const handleGithubGeneratedDocs = async ( entryPoints: EntryPoint[] @@ -13,10 +13,21 @@ export const handleGithubGeneratedDocs = async ( export const handleGithubDocsReport = async ( entryPoints: EntryPoint[], + reportMarkdown: string, failOnError: boolean, failOnWarnings: boolean ): Promise => { - await submitReportsSummaryComment(entryPoints) + // annotate code in github + for (const { report } of entryPoints) { + if (report) { + annotateCode(report.messages) + } + } + + // generate job summary markdown + await summary.addRaw(reportMarkdown).write() + + // handle reports summary errors and warnings logs getReportResults(entryPoints, failOnError, failOnWarnings) } diff --git a/src/run.ts b/src/run.ts index 22f328a..b5008b9 100644 --- a/src/run.ts +++ b/src/run.ts @@ -1,7 +1,8 @@ import * as core from '@actions/core' import { configInputs, getInputEntryPoints } from './config' -import { runDocsReport } from './docs-report' +import { runDocsReport, generateReportMarkdown } from './docs-report' +import { writeFileSync } from 'fs' import { generateDocs } from './docs-generator' import { getFilesDiffs } from './utils' @@ -53,7 +54,15 @@ export async function run(): Promise { ) } - await handleGithubDocsReport(entryPoints, failOnError, failOnWarnings) + const reportMarkdown = await generateReportMarkdown(entryPoints) + writeFileSync('.tbdocs/docs-report.md', reportMarkdown) + + await handleGithubDocsReport( + entryPoints, + reportMarkdown, + failOnError, + failOnWarnings + ) if (docsTargetOwnerRepo) { await handleGithubGeneratedDocs(entryPoints)