@@ -238,47 +238,150 @@ jobs:
238238 description : " Download firmware-${{matrix.arch}}-${{ needs.version.outputs.long }}.zip. This artifact will be available for 90 days from creation"
239239 github-token : ${{ secrets.GITHUB_TOKEN }}
240240
241- shame :
241+ firmware-size-report :
242242 if : github.repository == 'meshtastic/firmware'
243243 continue-on-error : true
244+ permissions :
245+ contents : read
246+ pull-requests : write
247+ actions : read
244248 runs-on : ubuntu-latest
245249 needs : [build]
246250 steps :
247251 - uses : actions/checkout@v6
248- if : github.event_name == 'pull_request_target'
249252 with :
250- filter : blob:none # means we download all the git history but none of the commit (except ones with checkout like the head)
251- fetch-depth : 0
252- - name : Download the current manifests
253+ ref : ${{github.event.pull_request.head.ref}}
254+ repository : ${{github.event.pull_request.head.repo.full_name}}
255+
256+ - name : Download current manifests
253257 uses : actions/download-artifact@v8
254258 with :
255- path : ./manifests-new /
259+ path : ./manifests/
256260 pattern : manifest-*
257261 merge-multiple : true
258- - name : Upload combined manifests for later commit and global stats crunching.
262+
263+ - name : Collect current firmware sizes
264+ run : python3 bin/collect_sizes.py ./manifests/ ./current-sizes.json
265+
266+ - name : Upload size report artifact
259267 uses : actions/upload-artifact@v7
260- id : upload-manifest
261268 with :
262- name : manifests -${{ github.sha }}
269+ name : firmware-sizes -${{ github.sha }}
263270 overwrite : true
264- path : manifests-new/*.mt.json
265- - name : Find the merge base
271+ path : ./current-sizes.json
272+ retention-days : 90
273+
274+ - name : Download baseline sizes from develop
266275 if : github.event_name == 'pull_request_target'
267- run : echo "MERGE_BASE=$(git merge-base "origin/$base" "$head")" >> $GITHUB_ENV
276+ continue-on-error : true
277+ id : baseline-develop
268278 env :
269- base : ${{ github.base_ref }}
270- head : ${{ github.sha }}
271- # Currently broken (for-loop through EVERY artifact -- rate limiting)
272- # - name: Download the old manifests
273- # if: github.event_name == 'pull_request_target'
274- # run: gh run download -R "$repo" --name "manifests-$merge_base" --dir manifest-old/
275- # env:
276- # GH_TOKEN: ${{ github.token }}
277- # merge_base: ${{ env.MERGE_BASE }}
278- # repo: ${{ github.repository }}
279- # - name: Do scan and post comment
280- # if: github.event_name == 'pull_request_target'
281- # run: python3 bin/shame.py ${{ github.event.pull_request.number }} manifests-old/ manifests-new/
279+ GH_TOKEN : ${{ github.token }}
280+ run : |
281+ # Find the latest successful CI run on develop and get its firmware-sizes artifact
282+ RUN_ID=$(gh run list -R "${{ github.repository }}" \
283+ --workflow CI --branch develop --status success \
284+ --limit 1 --json databaseId --jq '.[0].databaseId')
285+ if [ -n "$RUN_ID" ]; then
286+ ARTIFACT_NAME=$(gh api "repos/${{ github.repository }}/actions/runs/${RUN_ID}/artifacts" \
287+ --jq '.artifacts[] | select(.name | startswith("firmware-sizes-")) | .name' | head -1)
288+ if [ -n "$ARTIFACT_NAME" ]; then
289+ gh run download "$RUN_ID" -R "${{ github.repository }}" \
290+ --name "$ARTIFACT_NAME" --dir ./baseline-develop/
291+ cp ./baseline-develop/current-sizes.json ./develop-sizes.json
292+ echo "found=true" >> "$GITHUB_OUTPUT"
293+ else
294+ echo "found=false" >> "$GITHUB_OUTPUT"
295+ fi
296+ else
297+ echo "found=false" >> "$GITHUB_OUTPUT"
298+ fi
299+
300+ - name : Download baseline sizes from master
301+ if : github.event_name == 'pull_request_target'
302+ continue-on-error : true
303+ id : baseline-master
304+ env :
305+ GH_TOKEN : ${{ github.token }}
306+ run : |
307+ RUN_ID=$(gh run list -R "${{ github.repository }}" \
308+ --workflow CI --branch master --status success \
309+ --limit 1 --json databaseId --jq '.[0].databaseId')
310+ if [ -n "$RUN_ID" ]; then
311+ ARTIFACT_NAME=$(gh api "repos/${{ github.repository }}/actions/runs/${RUN_ID}/artifacts" \
312+ --jq '.artifacts[] | select(.name | startswith("firmware-sizes-")) | .name' | head -1)
313+ if [ -n "$ARTIFACT_NAME" ]; then
314+ gh run download "$RUN_ID" -R "${{ github.repository }}" \
315+ --name "$ARTIFACT_NAME" --dir ./baseline-master/
316+ cp ./baseline-master/current-sizes.json ./master-sizes.json
317+ echo "found=true" >> "$GITHUB_OUTPUT"
318+ else
319+ echo "found=false" >> "$GITHUB_OUTPUT"
320+ fi
321+ else
322+ echo "found=false" >> "$GITHUB_OUTPUT"
323+ fi
324+
325+ - name : Generate size comparison report
326+ if : github.event_name == 'pull_request_target'
327+ id : report
328+ run : |
329+ ARGS="./current-sizes.json"
330+ if [ -f ./develop-sizes.json ]; then
331+ ARGS="$ARGS --baseline develop:./develop-sizes.json"
332+ fi
333+ if [ -f ./master-sizes.json ]; then
334+ ARGS="$ARGS --baseline master:./master-sizes.json"
335+ fi
336+ REPORT=$(python3 bin/size_report.py $ARGS)
337+ if [ -z "$REPORT" ]; then
338+ echo "has_report=false" >> "$GITHUB_OUTPUT"
339+ else
340+ echo "has_report=true" >> "$GITHUB_OUTPUT"
341+ {
342+ echo '<!-- firmware-size-report -->'
343+ echo '# Firmware Size Report'
344+ echo ''
345+ echo "$REPORT"
346+ echo ''
347+ echo '---'
348+ echo "*Updated for ${{ github.sha }}*"
349+ } > ./size-report.md
350+ cat ./size-report.md >> "$GITHUB_STEP_SUMMARY"
351+ fi
352+
353+ - name : Post or update PR comment
354+ if : github.event_name == 'pull_request_target' && steps.report.outputs.has_report == 'true'
355+ uses : actions/github-script@v8
356+ with :
357+ script : |
358+ const fs = require('fs');
359+ const marker = '<!-- firmware-size-report -->';
360+ const body = fs.readFileSync('./size-report.md', 'utf8');
361+ const prNumber = context.payload.pull_request.number;
362+
363+ const { data: comments } = await github.rest.issues.listComments({
364+ owner: context.repo.owner,
365+ repo: context.repo.repo,
366+ issue_number: prNumber,
367+ });
368+
369+ const existing = comments.find(c => c.body.includes(marker));
370+ if (existing) {
371+ await github.rest.issues.updateComment({
372+ owner: context.repo.owner,
373+ repo: context.repo.repo,
374+ comment_id: existing.id,
375+ body,
376+ });
377+ } else {
378+ await github.rest.issues.createComment({
379+ owner: context.repo.owner,
380+ repo: context.repo.repo,
381+ issue_number: prNumber,
382+ body,
383+ });
384+ }
282385
283386 release-artifacts :
284387 runs-on : ubuntu-latest
0 commit comments