Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move PR preview to Checks tab and add statistics #881

Merged
merged 25 commits into from
Sep 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
b9551db
Add statistics check
ZeLonewolf Jun 23, 2023
61ef4f3
Merge branch 'main' into zlw-enhanced-stats
ZeLonewolf Jun 23, 2023
f7cf152
Generate PR preview
ZeLonewolf Jun 23, 2023
c653d1e
Move preview to tab
ZeLonewolf Jun 23, 2023
c73f446
Convert to img tags
ZeLonewolf Jun 23, 2023
735ddc6
Wait for image upload
ZeLonewolf Jun 23, 2023
887b567
Merge branch 'main' into zlw-enhanced-stats
ZeLonewolf Jun 27, 2023
f917df8
Merge branch 'main' into zlw-enhanced-stats
ZeLonewolf Jun 27, 2023
fdf509e
Merge branch 'main' into zlw-enhanced-stats
ZeLonewolf Jul 4, 2023
257db07
Merge branch 'main' into zlw-enhanced-stats
ZeLonewolf Jul 9, 2023
9e97c42
Remove old dev artifact
ZeLonewolf Jul 9, 2023
41fa076
Merge branch 'main' into zlw-enhanced-stats
ZeLonewolf Jul 18, 2023
def2586
Improve compare function and add test cases
ZeLonewolf Jul 20, 2023
51dc895
Improve readability of stats generator
ZeLonewolf Jul 20, 2023
88525a4
Fix row join
ZeLonewolf Jul 20, 2023
7d2bb69
fix NPE bug
ZeLonewolf Jul 20, 2023
93b2b55
Remove stray code
ZeLonewolf Jul 20, 2023
a1b9dee
Refactor out table row creation and test
ZeLonewolf Jul 21, 2023
e69886b
Refactor
ZeLonewolf Jul 21, 2023
d04da3f
Consolidate table output
ZeLonewolf Jul 21, 2023
9eee050
Remove unused code
ZeLonewolf Jul 21, 2023
9500d15
Merge branch 'main' into zlw-enhanced-stats
ZeLonewolf Aug 1, 2023
72479c7
Merge branch 'main' into zlw-enhanced-stats
ZeLonewolf Aug 1, 2023
3d028db
Merge branch 'main' into zlw-enhanced-stats
ZeLonewolf Sep 19, 2023
ec438b1
Merge branch 'main' into zlw-enhanced-stats
ZeLonewolf Sep 22, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 44 additions & 1 deletion .github/workflows/build-preview.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,31 @@ permissions:
pages: write
pull-requests: write
id-token: write
checks: write
concurrency: preview-${{ github.ref }}
jobs:
deploy-preview:
runs-on: ubuntu-latest
steps:
- name: Checkout 🛎️
- name: Checkout Main Branch 🛎️
uses: actions/checkout@v3
with:
ref: main
- name: Install and Build Main Branch 🔧
run: |
npm ci --include=dev
npm run build
npm run style
npm run shields
cp src/configs/config.aws.js src/config.js
- name: Capture main branch usage statistics
id: main-stats
run: |
MAIN_STATS=$(node scripts/stats.js -j)
echo "MAIN_STATS<<EOF" >> $GITHUB_ENV
echo -e "$MAIN_STATS" >> $GITHUB_ENV
echo "EOF" >> $GITHUB_ENV
- name: Checkout PR Branch 🛎️
uses: actions/checkout@v3
- name: Use Node.js 18.16.1
uses: actions/setup-node@v3
Expand All @@ -42,6 +61,30 @@ jobs:
npm run style
npm run shields
cp src/configs/config.aws.js src/config.js
- name: Capture PR branch usage statistics
id: pr-stats
run: |
PR_STATS=$(node scripts/stats.js -j)
echo "PR_STATS<<EOF" >> $GITHUB_ENV
echo -e "$PR_STATS" >> $GITHUB_ENV
echo "EOF" >> $GITHUB_ENV
- name: Compare Stats
id: compare-stats
run: |
mkdir stats
echo '${{ env.MAIN_STATS }}'
echo '${{ env.PR_STATS }}'
npm exec ts-node scripts/stats_compare '${{ env.MAIN_STATS }}' '${{ env.PR_STATS }}' > stats/stats-difference.md
- name: Print Stats to GitHub Checks
uses: LouisBrunner/[email protected]
if: always()
with:
token: ${{ secrets.GITHUB_TOKEN }}
name: Performance Metrics
conclusion: neutral
output: |
{"summary":"Style size changes introduced by this PR"}
output_text_description_file: stats/stats-difference.md
- name: Upload Build artifact
uses: actions/upload-artifact@v3
with:
Expand Down
53 changes: 53 additions & 0 deletions .github/workflows/pr-preview-check.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
name: Generate PR Preview Check
on:
pull_request:
branches: [main]
types:
- opened
- reopened
- synchronize
workflow_dispatch:
permissions:
checks: write
jobs:
deploy-preview:
runs-on: ubuntu-latest
steps:
- name: Wait for PR Preview Upload (1x Sprite)
uses: cygnetdigital/[email protected]
with:
url: "https://preview.ourmap.us/pr/${{ github.event.pull_request.number }}/sprites/sprite.png"
responseCode: "200"
timeout: 120000
interval: 500
- name: Wait for PR Preview Upload (2x Sprite)
uses: cygnetdigital/[email protected]
with:
url: "https://preview.ourmap.us/pr/${{ github.event.pull_request.number }}/sprites/[email protected]"
responseCode: "200"
timeout: 120000
interval: 500
- name: Generate Preview text
run: |
echo "## PR Preview:
* [Map](https://preview.ourmap.us/pr/${{ github.event.pull_request.number }}/)
* [Shield Test](https://preview.ourmap.us/pr/${{ github.event.pull_request.number }}/shieldtest.html)
* [style.json](https://preview.ourmap.us/pr/${{ github.event.pull_request.number }}/style.json)
* [shields.json](https://preview.ourmap.us/pr/${{ github.event.pull_request.number }}/shields.json)
* [taginfo.json](https://preview.ourmap.us/pr/${{ github.event.pull_request.number }}/taginfo.json)

## Sprite Sheets:

<img src="https://preview.ourmap.us/pr/${{ github.event.pull_request.number }}/sprites/sprite.png" />
<img src="https://preview.ourmap.us/pr/${{ github.event.pull_request.number }}/sprites/[email protected]" />
" > pr_preview.md
- name: Print Preview Links to GitHub Checks
uses: LouisBrunner/[email protected]
if: always()
with:
token: ${{ secrets.GITHUB_TOKEN }}
name: PR Preview
conclusion: neutral
output: |
{"summary":"Preview map changes introduced by this PR"}
output_text_description_file: pr_preview.md
17 changes: 0 additions & 17 deletions .github/workflows/s3-upload.yml
Original file line number Diff line number Diff line change
Expand Up @@ -72,20 +72,3 @@ jobs:
AWS_REGION: ${{ secrets.AWS_REGION }}
SOURCE_DIR: "./dist"
DEST_DIR: pr/${{ env.PR_NUM }}
- name: Comment Pull Request
uses: thollander/[email protected]
with:
message: |
PR Preview:
* [Map](https://preview.ourmap.us/pr/${{ env.PR_NUM }}/)
* [Shield Test](https://preview.ourmap.us/pr/${{ env.PR_NUM }}/shieldtest.html)
* [style.json](https://preview.ourmap.us/pr/${{ env.PR_NUM }}/style.json)
* [shields.json](https://preview.ourmap.us/pr/${{ env.PR_NUM }}/shields.json)
* [taginfo.json](https://preview.ourmap.us/pr/${{ env.PR_NUM }}/taginfo.json)

Sprite Sheets:

![Sprites 1x](https://preview.ourmap.us/pr/${{ env.PR_NUM }}/sprites/sprite.png)
![Sprites 2x](https://preview.ourmap.us/pr/${{ env.PR_NUM }}/sprites/[email protected])
comment_tag: pr_preview
pr_number: ${{ env.PR_NUM }}
145 changes: 145 additions & 0 deletions scripts/object_compare.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
/**
* Calculates the difference between two objects by comparing their properties.
* If a property value is an object, it recursively calls itself to calculate the difference.
* Positive numbers for a property means that property is greater in object2 than object1.
* @param {Object|null} object1 - The first object to compare.
* @param {Object|null} object2 - The second object to compare.
* @returns {Object} - An object containing the differences between object2 and object1.
*/
export function calculateDifference(
object1: object | null,
object2: object | null
): object {
// If one object exists and the other doesn't, return the difference
if (object1 === null && object2 !== null) {
return object2;
} else if (object2 === null && object1 !== null) {
return negate(object1);
}

const difference = {};

// Iterate through each property in object1
for (const key in object1) {
if (typeof object1[key] === "object" && typeof object2![key] === "object") {
// Recursively calculate the difference for nested objects
difference[key] = calculateDifference(object1[key], object2![key]);
} else if (
typeof object1[key] === "number" &&
typeof object2![key] === "number"
) {
// Calculate the difference for numeric properties
difference[key] = object2![key] - object1[key];
} else {
// If the property exists in object1 but not in object2, include it in the result
difference[key] = negate(object1![key]);
}
}

// Include properties that exist in object2 but not in object1
for (const key in object2!) {
if (!(key in object1!)) {
difference[key] = object2[key];
}
}

return difference;
}

/**
* Negate all numeric properties of this object.
* @param {Object} object - The object to process.
*/
function negate(object: object) {
if (typeof object === "number") {
return -object;
}

// Create a new object to store the result
const result = {};

for (const key in object) {
if (typeof object[key] === "object" && object[key] !== null) {
// If the property value is an object (and not null), recursively process it
result[key] = negate(object[key]);
} else if (typeof object[key] === "number") {
// If the property value is a number, multiply it by the multiplier
ZeLonewolf marked this conversation as resolved.
Show resolved Hide resolved
result[key] = -object[key];
}
}

return result;
}

// "| | main | this PR | change | % change |",
export type ComparedStats = {
name: string;
beforeValue: number | null;
afterValue: number | null;
change: number;
pctChange: number | null;
};

export function statsComparisonRow(
name: string,
val1: number | null,
val2: number | null,
change: number
): ComparedStats {
let pctChange: number | null;

if (val1 !== null) {
if (val2 !== null) {
pctChange = change / val1;
} else {
pctChange = -1;
}
} else {
pctChange = null;
}

return {
name,
beforeValue: val1,
afterValue: val2,
change,
pctChange,
};
}

const pctFormat: Intl.NumberFormatOptions = {
style: "percent",
minimumFractionDigits: 1,
maximumFractionDigits: 1,
signDisplay: "exceptZero",
};

function naLocString(val: number | null) {
return val !== null ? val.toLocaleString("en") : "N/A";
}

/**
* produce a markdown row of statistics comparison
*/
export function mdStringValues(stats: ComparedStats): string[] {
const beforeValueStr = naLocString(stats.beforeValue);
const afterValueStr = naLocString(stats.afterValue);
const changeStr = naLocString(stats.change);
const pctChangeStr =
stats.pctChange !== null
? stats.pctChange.toLocaleString("en", pctFormat)
: "N/A";

return [stats.name, beforeValueStr, afterValueStr, changeStr, pctChangeStr];
}

export function mdCompareRow(
name: string,
val1: number | null,
val2: number | null,
change: number
): string {
return mdStringValues(statsComparisonRow(name, val1, val2, change)).join(
" | "
);
}
81 changes: 81 additions & 0 deletions scripts/stats_compare.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import { calculateDifference, mdCompareRow } from "./object_compare";

const stats1 = JSON.parse(process.argv[2]);
const stats2 = JSON.parse(process.argv[3]);

const difference = calculateDifference(stats1, stats2);

const diffHeaderRow = [
"| | main | this PR | change | % change |",
"|-----------|--------------:|-------------:|----------------:|----------------:|",
];

/**
* Show comparison of overall aggregate statistics between this PR and previous
*/

const layersRow = mdCompareRow(
"Layers",
stats1.layerCount,
stats2.layerCount,
difference.layerCount
);

const sizeRow = mdCompareRow(
"Size (b)",
stats1.styleSize,
stats2.styleSize,
difference.styleSize
);

printTable("Style size statistics", [layersRow, sizeRow]);

/**
* Show comparison of the number of layers in each group before and after
*/

const layerCountChangeRows = [];

for (const layer in difference.layerGroup) {
layerCountChangeRows.push(
mdCompareRow(
layer,
stats1.layerGroup[layer]?.layerCount,
stats2.layerGroup[layer]?.layerCount,
difference.layerGroup[layer]?.layerCount
)
);
}

printTable("Layer count comparison", layerCountChangeRows);

/**
* Show comparison of the aggregate size of layers in each group before and after
*/

const layerSizeChangeRows = [];

for (const layer in difference.layerGroup) {
layerSizeChangeRows.push(
mdCompareRow(
layer,
stats1.layerGroup[layer]?.size,
stats2.layerGroup[layer]?.size,
difference.layerGroup[layer]?.size
)
);
}

printTable("Layer size comparison", layerSizeChangeRows);

function printTable(headingText, rows) {
const table = [...diffHeaderRow, ...rows].join("\n");
const text = `

## ${headingText}

${table}
`;

console.log(text);
}
Loading