Skip to content

Commit 89161bb

Browse files
authored
Merge pull request #563 from github/mattcosta7/describe
Mattcosta7: Add `describe-assets` option
2 parents 2045e9c + 2309ff9 commit 89161bb

File tree

10 files changed

+307
-27
lines changed

10 files changed

+307
-27
lines changed

.github/workflows/test.yml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,17 @@ jobs:
5454
base-stats-json-path: ./__tests__/__mocks__/old-stats-assets.json
5555
github-token: ${{ secrets.GITHUB_TOKEN }}
5656
title: No changes
57+
- uses: ./
58+
with:
59+
current-stats-json-path: ./__tests__/__mocks__/new-stats-assets.json
60+
base-stats-json-path: ./__tests__/__mocks__/old-stats-assets.json
61+
github-token: ${{ secrets.GITHUB_TOKEN }}
62+
title: "With describe-assets: 'none'"
63+
describe-assets: none
64+
- uses: ./
65+
with:
66+
current-stats-json-path: ./__tests__/__mocks__/old-stats-assets.json
67+
base-stats-json-path: ./__tests__/__mocks__/old-stats-assets.json
68+
github-token: ${{ secrets.GITHUB_TOKEN }}
69+
title: "With describe-assets: 'changed-only'"
70+
describe-assets: changed-only

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,8 @@ This action requires the `write` permission for the [`permissions.pull-requests`
110110
| github-token | The Github token | true | string |
111111
| title | An optional addition to the title, which also helps key comments, useful if running more than 1 copy of this action | false | string |
112112

113+
| describe-assets | Option for asset description output. One of "all" (default), "changed-only", or "none". | false | string |
114+
113115
## Example PR Comment
114116

115117
https://github.com/github/webpack-bundlesize-compare-action/pull/50#issuecomment-1054919780

__tests__/main.test.ts

Lines changed: 127 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,23 @@
1-
import {expect, test} from '@jest/globals'
1+
import {expect, describe, test, beforeAll} from '@jest/globals'
22
import {getStatsDiff} from '../src/get-stats-diff'
33
import {getChunkModuleDiff} from '../src/get-chunk-module-diff'
44
import {
55
printAssetTablesByGroup,
66
printChunkModulesTable,
77
printTotalAssetTable
88
} from '../src/print-markdown'
9-
import {AssetDiff} from '../src/types'
9+
import {
10+
AssetDiff,
11+
DescribeAssetsOptions,
12+
DescribeAssetsSection,
13+
WebpackStatsDiff,
14+
describeAssetsSections
15+
} from '../src/types'
1016
import {readFile} from 'node:fs/promises'
1117
import {resolve} from 'node:path'
1218
import {StatsCompilation} from 'webpack'
19+
import {getDescribeAssetsOptions} from '../src/main'
20+
import {fail} from 'node:assert'
1321

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

122130
expect(printChunkModulesTable(statsDiff)).toMatchSnapshot()
123131
})
132+
133+
describe('printAssetTablesByGroup describes asset sections as requested', () => {
134+
// generate all combinations of sections
135+
const cases: DescribeAssetsOptions[] = []
136+
for (let i = 0; i < Math.pow(2, describeAssetsSections.length); i++) {
137+
const options = {} as DescribeAssetsOptions
138+
for (let n = 0; n < describeAssetsSections.length; n++) {
139+
if ((i >> n) & 1) {
140+
options[describeAssetsSections[n]] = true
141+
} else {
142+
options[describeAssetsSections[n]] = false
143+
}
144+
}
145+
cases.push(options)
146+
}
147+
148+
let statsDiff: WebpackStatsDiff
149+
beforeAll(async () => {
150+
statsDiff = getStatsDiff(
151+
await readJsonFile('./__mocks__/old-stats-assets.json'),
152+
await readJsonFile('./__mocks__/new-stats-assets.json')
153+
)
154+
})
155+
156+
test.each(cases)(
157+
'printAssetTablesByGroup: %j',
158+
(options: DescribeAssetsOptions) => {
159+
const assetTables = printAssetTablesByGroup(statsDiff, options)
160+
for (const [section, included] of Object.entries(options)) {
161+
const sectionHeader = `**${section[0].toUpperCase()}${section.slice(
162+
1
163+
)}**`
164+
if (included) {
165+
expect(assetTables).toContain(sectionHeader)
166+
} else {
167+
expect(assetTables).not.toContain(sectionHeader)
168+
}
169+
}
170+
if (Object.entries(options).every(([, included]) => included === false)) {
171+
expect(assetTables).toBe('')
172+
}
173+
}
174+
)
175+
})
176+
177+
describe('getDescribeAssetsOptions', () => {
178+
test(`getDescribeAssetsOptions: "all"`, () => {
179+
const generatedOptions = getDescribeAssetsOptions('all')
180+
for (const section of describeAssetsSections) {
181+
expect(generatedOptions[section]).toBe(true)
182+
}
183+
})
184+
185+
test(`getDescribeAssetsOptions: "none"`, () => {
186+
const generatedOptions = getDescribeAssetsOptions('none')
187+
for (const section of describeAssetsSections) {
188+
expect(generatedOptions[section]).toBe(false)
189+
}
190+
})
191+
192+
test(`getDescribeAssetsOptions: "changed-only"`, () => {
193+
const generatedOptions = getDescribeAssetsOptions('changed-only')
194+
for (const section of describeAssetsSections) {
195+
if (section === 'unchanged') {
196+
expect(generatedOptions[section]).toBe(false)
197+
} else {
198+
expect(generatedOptions[section]).toBe(true)
199+
}
200+
}
201+
})
202+
203+
test('getDescribeAssetsOptions: handles keyword with spaces', () => {
204+
const generatedOptions = getDescribeAssetsOptions(' all ')
205+
for (const section of describeAssetsSections) {
206+
expect(generatedOptions[section]).toBe(true)
207+
}
208+
})
209+
210+
test('getDescribeAssetsOptions: unsupported option throws', () => {
211+
expect(() => getDescribeAssetsOptions('unsupported options')).toThrow()
212+
})
213+
214+
// generate all combinations of sections as string
215+
const cases: string[] = []
216+
for (let i = 0; i < Math.pow(2, describeAssetsSections.length); i++) {
217+
const options: string[] = []
218+
for (let n = 0; n < describeAssetsSections.length; n++) {
219+
if ((i >> n) & 1) {
220+
options.push(describeAssetsSections[n])
221+
}
222+
}
223+
if (options.length > 0) {
224+
cases.push(options.join(' '))
225+
}
226+
}
227+
228+
test.each(cases)(`getDescribeAssetsOptions: %j`, (optionString: string) => {
229+
const generatedOptions = getDescribeAssetsOptions(optionString)
230+
const providedOptions = optionString.split(' ')
231+
for (const section of providedOptions) {
232+
expect(generatedOptions[section as DescribeAssetsSection]).toBe(true)
233+
}
234+
for (const section of describeAssetsSections.filter(
235+
s => !providedOptions.includes(s)
236+
)) {
237+
expect(generatedOptions[section]).toBe(false)
238+
}
239+
})
240+
241+
test('getDescribeAssetsOptions: handles sections with spaces', () => {
242+
const optionString = ' added removed bigger'
243+
const generatedOptions = getDescribeAssetsOptions(optionString)
244+
for (const section of describeAssetsSections) {
245+
expect(generatedOptions[section]).toBe(optionString.includes(section))
246+
}
247+
})
248+
})

action.yml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,20 @@ inputs:
1313
title:
1414
description: 'An optional addition to the title, which also helps key comments, useful if running more than 1 copy of this action'
1515
required: false
16+
describe-assets:
17+
description: |
18+
Optional specification describing asset changes. May be one of the convenience
19+
keywords "all", "none", or "changed-only" (for all except the unchanged section), OR
20+
a string of space-separated section names, e.g. "added bigger unchanged", where
21+
all sections are:
22+
- added
23+
- removed
24+
- bigger
25+
- smaller
26+
- unchanged
27+
If not provided, "all" is used (equivalent to "added removed bigger smaller unchanged")
28+
required: false
29+
default: 'all'
1630

1731
runs:
1832
using: 'node20'

dist/index.js

Lines changed: 67 additions & 11 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/index.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/main.ts

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,43 @@ import {getChunkModuleDiff} from './get-chunk-module-diff'
44
import {getStatsDiff} from './get-stats-diff'
55
import {parseStatsFileToJson} from './parse-stats-file-to-json'
66
import {getCommentBody, getIdentifierComment} from './to-comment-body'
7+
import {
8+
isDescribeAssetsSection,
9+
DescribeAssetsSection,
10+
DescribeAssetsOptions
11+
} from './types'
12+
13+
export function getDescribeAssetsOptions(
14+
optionString: string
15+
): DescribeAssetsOptions {
16+
optionString = optionString.trim().toLowerCase()
17+
if (optionString === 'all') {
18+
optionString = 'bigger smaller added removed unchanged'
19+
} else if (optionString === 'none') {
20+
optionString = ''
21+
} else if (optionString === 'changed-only') {
22+
optionString = 'bigger smaller added removed'
23+
}
24+
const options = {
25+
added: false,
26+
removed: false,
27+
bigger: false,
28+
smaller: false,
29+
unchanged: false
30+
}
31+
if (optionString) {
32+
const sections = optionString.split(' ').filter(s => !!s)
33+
if (sections.some(s => !isDescribeAssetsSection(s))) {
34+
throw new Error(
35+
`Unsupported options for 'describe-assets': '${optionString}' contains unexpected sections`
36+
)
37+
}
38+
for (const s of sections as DescribeAssetsSection[]) {
39+
options[s] = true
40+
}
41+
}
42+
return options
43+
}
744

845
async function run(): Promise<void> {
946
try {
@@ -22,6 +59,10 @@ async function run(): Promise<void> {
2259
const token = core.getInput('github-token')
2360
const currentStatsJsonPath = core.getInput('current-stats-json-path')
2461
const baseStatsJsonPath = core.getInput('base-stats-json-path')
62+
const describeAssetsOptionString = core.getInput('describe-assets')
63+
const describeAssetsOptions = getDescribeAssetsOptions(
64+
describeAssetsOptionString
65+
)
2566
const title = core.getInput('title') ?? ''
2667
const {rest} = getOctokit(token)
2768

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

51-
const commentBody = getCommentBody(statsDiff, chunkModuleDiff, title)
92+
const commentBody = getCommentBody(
93+
statsDiff,
94+
chunkModuleDiff,
95+
title,
96+
describeAssetsOptions
97+
)
5298

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

0 commit comments

Comments
 (0)