Skip to content

Commit

Permalink
Merge pull request #563 from github/mattcosta7/describe
Browse files Browse the repository at this point in the history
Mattcosta7: Add `describe-assets` option
  • Loading branch information
mattcosta7 authored Jun 3, 2024
2 parents 2045e9c + 2309ff9 commit 89161bb
Show file tree
Hide file tree
Showing 10 changed files with 307 additions and 27 deletions.
14 changes: 14 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,17 @@ jobs:
base-stats-json-path: ./__tests__/__mocks__/old-stats-assets.json
github-token: ${{ secrets.GITHUB_TOKEN }}
title: No changes
- uses: ./
with:
current-stats-json-path: ./__tests__/__mocks__/new-stats-assets.json
base-stats-json-path: ./__tests__/__mocks__/old-stats-assets.json
github-token: ${{ secrets.GITHUB_TOKEN }}
title: "With describe-assets: 'none'"
describe-assets: none
- uses: ./
with:
current-stats-json-path: ./__tests__/__mocks__/old-stats-assets.json
base-stats-json-path: ./__tests__/__mocks__/old-stats-assets.json
github-token: ${{ secrets.GITHUB_TOKEN }}
title: "With describe-assets: 'changed-only'"
describe-assets: changed-only
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ This action requires the `write` permission for the [`permissions.pull-requests`
| github-token | The Github token | true | string |
| title | An optional addition to the title, which also helps key comments, useful if running more than 1 copy of this action | false | string |

| describe-assets | Option for asset description output. One of "all" (default), "changed-only", or "none". | false | string |

## Example PR Comment

https://github.com/github/webpack-bundlesize-compare-action/pull/50#issuecomment-1054919780
129 changes: 127 additions & 2 deletions __tests__/main.test.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,23 @@
import {expect, test} from '@jest/globals'
import {expect, describe, test, beforeAll} from '@jest/globals'
import {getStatsDiff} from '../src/get-stats-diff'
import {getChunkModuleDiff} from '../src/get-chunk-module-diff'
import {
printAssetTablesByGroup,
printChunkModulesTable,
printTotalAssetTable
} from '../src/print-markdown'
import {AssetDiff} from '../src/types'
import {
AssetDiff,
DescribeAssetsOptions,
DescribeAssetsSection,
WebpackStatsDiff,
describeAssetsSections
} from '../src/types'
import {readFile} from 'node:fs/promises'
import {resolve} from 'node:path'
import {StatsCompilation} from 'webpack'
import {getDescribeAssetsOptions} from '../src/main'
import {fail} from 'node:assert'

async function readJsonFile(path: string): Promise<StatsCompilation> {
const data = await readFile(resolve(__dirname, path), 'utf8')
Expand Down Expand Up @@ -121,3 +129,120 @@ test('does not display module information when it does not exist', async () => {

expect(printChunkModulesTable(statsDiff)).toMatchSnapshot()
})

describe('printAssetTablesByGroup describes asset sections as requested', () => {
// generate all combinations of sections
const cases: DescribeAssetsOptions[] = []
for (let i = 0; i < Math.pow(2, describeAssetsSections.length); i++) {
const options = {} as DescribeAssetsOptions
for (let n = 0; n < describeAssetsSections.length; n++) {
if ((i >> n) & 1) {
options[describeAssetsSections[n]] = true
} else {
options[describeAssetsSections[n]] = false
}
}
cases.push(options)
}

let statsDiff: WebpackStatsDiff
beforeAll(async () => {
statsDiff = getStatsDiff(
await readJsonFile('./__mocks__/old-stats-assets.json'),
await readJsonFile('./__mocks__/new-stats-assets.json')
)
})

test.each(cases)(
'printAssetTablesByGroup: %j',
(options: DescribeAssetsOptions) => {
const assetTables = printAssetTablesByGroup(statsDiff, options)
for (const [section, included] of Object.entries(options)) {
const sectionHeader = `**${section[0].toUpperCase()}${section.slice(
1
)}**`
if (included) {
expect(assetTables).toContain(sectionHeader)
} else {
expect(assetTables).not.toContain(sectionHeader)
}
}
if (Object.entries(options).every(([, included]) => included === false)) {
expect(assetTables).toBe('')
}
}
)
})

describe('getDescribeAssetsOptions', () => {
test(`getDescribeAssetsOptions: "all"`, () => {
const generatedOptions = getDescribeAssetsOptions('all')
for (const section of describeAssetsSections) {
expect(generatedOptions[section]).toBe(true)
}
})

test(`getDescribeAssetsOptions: "none"`, () => {
const generatedOptions = getDescribeAssetsOptions('none')
for (const section of describeAssetsSections) {
expect(generatedOptions[section]).toBe(false)
}
})

test(`getDescribeAssetsOptions: "changed-only"`, () => {
const generatedOptions = getDescribeAssetsOptions('changed-only')
for (const section of describeAssetsSections) {
if (section === 'unchanged') {
expect(generatedOptions[section]).toBe(false)
} else {
expect(generatedOptions[section]).toBe(true)
}
}
})

test('getDescribeAssetsOptions: handles keyword with spaces', () => {
const generatedOptions = getDescribeAssetsOptions(' all ')
for (const section of describeAssetsSections) {
expect(generatedOptions[section]).toBe(true)
}
})

test('getDescribeAssetsOptions: unsupported option throws', () => {
expect(() => getDescribeAssetsOptions('unsupported options')).toThrow()
})

// generate all combinations of sections as string
const cases: string[] = []
for (let i = 0; i < Math.pow(2, describeAssetsSections.length); i++) {
const options: string[] = []
for (let n = 0; n < describeAssetsSections.length; n++) {
if ((i >> n) & 1) {
options.push(describeAssetsSections[n])
}
}
if (options.length > 0) {
cases.push(options.join(' '))
}
}

test.each(cases)(`getDescribeAssetsOptions: %j`, (optionString: string) => {
const generatedOptions = getDescribeAssetsOptions(optionString)
const providedOptions = optionString.split(' ')
for (const section of providedOptions) {
expect(generatedOptions[section as DescribeAssetsSection]).toBe(true)
}
for (const section of describeAssetsSections.filter(
s => !providedOptions.includes(s)
)) {
expect(generatedOptions[section]).toBe(false)
}
})

test('getDescribeAssetsOptions: handles sections with spaces', () => {
const optionString = ' added removed bigger'
const generatedOptions = getDescribeAssetsOptions(optionString)
for (const section of describeAssetsSections) {
expect(generatedOptions[section]).toBe(optionString.includes(section))
}
})
})
14 changes: 14 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,20 @@ inputs:
title:
description: 'An optional addition to the title, which also helps key comments, useful if running more than 1 copy of this action'
required: false
describe-assets:
description: |
Optional specification describing asset changes. May be one of the convenience
keywords "all", "none", or "changed-only" (for all except the unchanged section), OR
a string of space-separated section names, e.g. "added bigger unchanged", where
all sections are:
- added
- removed
- bigger
- smaller
- unchanged
If not provided, "all" is used (equivalent to "added removed bigger smaller unchanged")
required: false
default: 'all'

runs:
using: 'node20'
Expand Down
78 changes: 67 additions & 11 deletions dist/index.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dist/index.js.map

Large diffs are not rendered by default.

48 changes: 47 additions & 1 deletion src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,43 @@ import {getChunkModuleDiff} from './get-chunk-module-diff'
import {getStatsDiff} from './get-stats-diff'
import {parseStatsFileToJson} from './parse-stats-file-to-json'
import {getCommentBody, getIdentifierComment} from './to-comment-body'
import {
isDescribeAssetsSection,
DescribeAssetsSection,
DescribeAssetsOptions
} from './types'

export function getDescribeAssetsOptions(
optionString: string
): DescribeAssetsOptions {
optionString = optionString.trim().toLowerCase()
if (optionString === 'all') {
optionString = 'bigger smaller added removed unchanged'
} else if (optionString === 'none') {
optionString = ''
} else if (optionString === 'changed-only') {
optionString = 'bigger smaller added removed'
}
const options = {
added: false,
removed: false,
bigger: false,
smaller: false,
unchanged: false
}
if (optionString) {
const sections = optionString.split(' ').filter(s => !!s)
if (sections.some(s => !isDescribeAssetsSection(s))) {
throw new Error(
`Unsupported options for 'describe-assets': '${optionString}' contains unexpected sections`
)
}
for (const s of sections as DescribeAssetsSection[]) {
options[s] = true
}
}
return options
}

async function run(): Promise<void> {
try {
Expand All @@ -22,6 +59,10 @@ async function run(): Promise<void> {
const token = core.getInput('github-token')
const currentStatsJsonPath = core.getInput('current-stats-json-path')
const baseStatsJsonPath = core.getInput('base-stats-json-path')
const describeAssetsOptionString = core.getInput('describe-assets')
const describeAssetsOptions = getDescribeAssetsOptions(
describeAssetsOptionString
)
const title = core.getInput('title') ?? ''
const {rest} = getOctokit(token)

Expand All @@ -48,7 +89,12 @@ async function run(): Promise<void> {
const statsDiff = getStatsDiff(baseStatsJson, currentStatsJson)
const chunkModuleDiff = getChunkModuleDiff(baseStatsJson, currentStatsJson)

const commentBody = getCommentBody(statsDiff, chunkModuleDiff, title)
const commentBody = getCommentBody(
statsDiff,
chunkModuleDiff,
title,
describeAssetsOptions
)

const promises: Promise<unknown>[] = []

Expand Down
Loading

0 comments on commit 89161bb

Please sign in to comment.