Skip to content

Commit

Permalink
Merge pull request #881 from ZeLonewolf/zlw-enhanced-stats
Browse files Browse the repository at this point in the history
Move PR preview to Checks tab and add statistics
  • Loading branch information
ZeLonewolf authored Sep 22, 2023
2 parents 5842f91 + ec438b1 commit 675dbe2
Show file tree
Hide file tree
Showing 6 changed files with 384 additions and 18 deletions.
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
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

0 comments on commit 675dbe2

Please sign in to comment.