-
-
Notifications
You must be signed in to change notification settings - Fork 315
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add CI workflow to compute diff between files dist files
- Loading branch information
Showing
2 changed files
with
196 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
/** | ||
* Generate a markdown table with the difference in size of the dist files between the base and the PR. | ||
*/ | ||
|
||
/* | ||
Usage: | ||
```shell | ||
BASE_DIST_FILES='{"src/Autocomplete/assets/dist/controller.js":{"size":15382,"size_gz":3716,"size_brotli":3125},"src/Chartjs/assets/dist/controller.js":{"size":2281,"size_gz":771,"size_brotli":642},"src/Cropperjs/assets/dist/controller.js":{"size":1044,"size_gz":475,"size_brotli":371}}' \ | ||
PR_DIST_FILES='{"src/Chartjs/assets/dist/controller.js":{"size":2281,"size_gz":771,"size_brotli":642},"src/Cropperjs/assets/dist/controller.js":{"size":1044,"size_gz":475,"size_brotli":371},"src/Cropperjs/assets/dist/style.min.css":{"size":32,"size_gz":66,"size_brotli":34},"src/Dropzone/assets/dist/controller.js":{"size":3199,"size_gz":816,"size_brotli":634}}' \ | ||
node .github/generate-dist-files-size-diff.mjs | ||
``` | ||
*/ | ||
|
||
if (!process.env.BASE_DIST_FILES) { | ||
throw new Error('Missing or invalid "BASE_DIST_FILES" env variable.'); | ||
} | ||
|
||
if (!process.env.PR_DIST_FILES) { | ||
throw new Error('Missing or invalid "PR_DIST_FILES" env variable.'); | ||
} | ||
|
||
/** | ||
* Adapted from https://gist.github.com/zentala/1e6f72438796d74531803cc3833c039c?permalink_comment_id=4455218#gistcomment-4455218 | ||
* @param {number} bytes | ||
* @param {number} digits | ||
* @returns {string} | ||
*/ | ||
function formatBytes(bytes, digits = 2) { | ||
if (bytes === 0) { | ||
return '0 B'; | ||
} | ||
const sizes = [`B`, 'kB', 'MB']; | ||
const i = Math.floor(Math.log(bytes) / Math.log(1024)); | ||
|
||
return parseFloat((bytes / Math.pow(1024, i)).toFixed(digits)) + ' ' + sizes[i]; | ||
} | ||
|
||
/** | ||
* @param {number} from | ||
* @param {number} to | ||
* @returns {number} | ||
*/ | ||
function computeDiffPercent(from, to) { | ||
if (from === to) { | ||
return 0; | ||
} | ||
|
||
return Number(((from - to) / to * -100).toFixed(2)); | ||
} | ||
|
||
/** | ||
* @param {number} percent | ||
* @returns {string} | ||
*/ | ||
function formatDiffPercent(percent) { | ||
return percent > 0 ? `+${percent}% 📈` : percent < 0 ? `${percent}% 📉` : `${percent}%`; | ||
} | ||
|
||
export function main() { | ||
let base = JSON.parse(process.env.BASE_DIST_FILES); | ||
let pr = JSON.parse(process.env.PR_DIST_FILES); | ||
let output = '<h1>📊 Dist files size difference</h1>\n\n'; | ||
|
||
const files = [...new Set([...Object.keys(pr), ...Object.keys(base)])].sort().reduce((acc, file) => { | ||
const added = !base[file] && pr[file]; | ||
const removed = base[file] && !pr[file]; | ||
const diff_percent_size = removed ? -100 : (added ? 100 : (computeDiffPercent(base[file].size, pr[file].size))); | ||
const diff_percent_size_gz = removed ? -100 : (added ? 100 : (computeDiffPercent(base[file].size_gz, pr[file].size_gz))); | ||
const diff_percent_size_brotli = removed ? -100 : (added ? 100 : (computeDiffPercent(base[file].size_brotli, pr[file].size_brotli))); | ||
|
||
if (diff_percent_size !== 0 && diff_percent_size_gz !== 0 && diff_percent_size_brotli !== 0) { | ||
acc.set(file, { | ||
state: added ? 'added' : (removed ? 'removed' : 'changed'), | ||
diff_percent_size, | ||
diff_percent_size_gz, | ||
diff_percent_size_brotli | ||
}); | ||
} | ||
|
||
return acc; | ||
}, new Map); | ||
|
||
if (files.size === 0) { | ||
output += 'ℹ️ No difference in dist files.\n'; | ||
return output; | ||
} | ||
|
||
output += 'Thanks for the PR! Here is the difference in size of the dist files between the base and the PR.\n'; | ||
output += 'Please review the changes and make sure they are expected.\n\n'; | ||
output += `<table> | ||
<thead><tr><th>File</th><th>Diff (B)</th><th>Diff (%)</th></tr></thead> | ||
<tbody>`; | ||
for (const [file, details] of files.entries()) { | ||
output += `<tr> | ||
<td><code>${file}</code> ${details.state === 'added' ? '(new)' : (details.state === 'removed' ? '(deleted)' : '')}</td> | ||
<td> | ||
Size: <code>${formatBytes(base[file]?.size || 0)}</code> → <code>${formatBytes(pr[file]?.size || 0)}</code><br> | ||
Gzip: <code>${formatBytes(base[file]?.size_gz || 0)}</code> → <code>${formatBytes(pr[file]?.size_gz || 0)}</code><br> | ||
Brotli: <code>${formatBytes(base[file]?.size_brotli || 0)}</code> → <code>${formatBytes(pr[file]?.size_brotli || 0)}</code> | ||
</td> | ||
<td align="right"> | ||
Size: <b>${formatDiffPercent(details.diff_percent_size)}</b><br> | ||
Gzip: <b>${formatDiffPercent(details.diff_percent_size_gz)}</b><br> | ||
Brotli: <b>${formatDiffPercent(details.diff_percent_size_brotli)}</b> | ||
</td> | ||
</tr> | ||
`; | ||
} | ||
output += `</tbody> | ||
</table> | ||
`; | ||
|
||
return output; | ||
} | ||
|
||
if (!process.env.CI) { | ||
console.log(main()); | ||
} |
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,78 @@ | ||
name: Dist Files Size Diff | ||
|
||
on: | ||
pull_request: | ||
paths: | ||
- 'src/*/**' | ||
- '!src/*/doc/**' | ||
- '.github/**' | ||
|
||
jobs: | ||
dist-files-size-diff: | ||
runs-on: ubuntu-latest | ||
permissions: | ||
pull-requests: write # for marocchino/sticky-pull-request-comment@v2 | ||
steps: | ||
- name: Configure git | ||
run: | | ||
git config --global user.email "" | ||
git config --global user.name "github-action[bot]" | ||
- uses: marocchino/sticky-pull-request-comment@v2 | ||
with: | ||
message: | | ||
⏳ The dist files size difference is being calculated... | ||
- uses: actions/checkout@v4 | ||
with: | ||
ref: ${{ github.base_ref }} | ||
|
||
- name: Get dist files size (from base branch) | ||
id: base-dist-files | ||
run: | | ||
set -e | ||
FILES=$(find src -mindepth 2 -path '*/assets/dist/*' \( -name "*.js" -o -name "*.css" \) -not \( -path '*/tests/*' -o -path '*/public/*' -o -path '*/vendor/*' \) | sort | while read -r file; do | ||
echo "{\"$file\": {\"size\": $(wc -c < "$file"), \"size_gz\": $(gzip -c "$file" | wc -c), \"size_brotli\": $(brotli -c "$file" | wc -c)}}" | ||
done | jq -s 'add' -c) | ||
echo "files=$FILES" >> $GITHUB_OUTPUT | ||
- uses: actions/checkout@v4 | ||
|
||
- name: Get dist files size (from pull request) | ||
id: pr-dist-files | ||
run: | | ||
set -e | ||
FILES=$(find src -mindepth 2 -path '*/assets/dist/*' \( -name "*.js" -o -name "*.css" \) -not \( -path '*/tests/*' -o -path '*/public/*' -o -path '*/vendor/*' \) | sort | while read -r file; do | ||
echo "{\"$file\": {\"size\": $(wc -c < "$file"), \"size_gz\": $(gzip -c "$file" | wc -c), \"size_brotli\": $(brotli -c "$file" | wc -c)}}" | ||
done | jq -s 'add' -c) | ||
echo "files=$FILES" >> $GITHUB_OUTPUT | ||
- name: Generate the diff | ||
id: diff | ||
uses: actions/github-script@v7 | ||
env: | ||
BASE_DIST_FILES: ${{ steps.base-dist-files.outputs.files }} | ||
PR_DIST_FILES: ${{ steps.pr-dist-files.outputs.files }} | ||
with: | ||
result-encoding: string | ||
script: | | ||
const { main } = await import('${{ github.workspace }}/.github/generate-dist-files-size-diff.mjs') | ||
return await main() | ||
- name: Comment on the pull request (if any failure) | ||
if: ${{ failure() }} | ||
uses: marocchino/sticky-pull-request-comment@v2 | ||
with: | ||
message: | | ||
❌ The dist files size difference could not be calculated. Please check the logs for more details. | ||
- name: Comment on the pull request (if success) | ||
if: ${{ always() && steps.diff.conclusion == 'success' }} | ||
uses: marocchino/sticky-pull-request-comment@v2 | ||
with: | ||
message: ${{ steps.diff.outputs.result }} |