diff --git a/.github/workflows/nix-changes-comment.yml b/.github/workflows/nix-changes-comment.yml
index 371ed669d1f..fc642dee29b 100644
--- a/.github/workflows/nix-changes-comment.yml
+++ b/.github/workflows/nix-changes-comment.yml
@@ -16,6 +16,7 @@ jobs:
runs-on: ubuntu-slim
permissions:
pull-requests: write
+ statuses: write
steps:
- name: Download artefacts
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
@@ -41,7 +42,7 @@ jobs:
set -x
> requisites-before.list
> requisites-after.list
- TABLE=$(
+ {
echo '| Platform | Number of requisites | Proportion of new derivations |'
echo '| :-: | -: | -: |'
TOTAL_BEFORE=0
@@ -49,13 +50,17 @@ jobs:
TOTAL_CHANGED=0
QUOTE='`'
for PLATFORM in x86_64-linux aarch64-linux x86_64-darwin aarch64-darwin; do
+ if [ ! -f "requisites-${PLATFORM}-before.list" ] || [ ! -f "requisites-${PLATFORM}-after.list" ]; then
+ echo "| ${QUOTE}${PLATFORM}${QUOTE} | _missing data_ | _missing data_ |"
+ continue
+ fi
BEFORE=$(wc -l < "requisites-${PLATFORM}-before.list")
TOTAL_BEFORE=$(($TOTAL_BEFORE + $BEFORE))
AFTER=$(wc -l < "requisites-${PLATFORM}-after.list")
TOTAL_AFTER=$(($TOTAL_AFTER + $AFTER))
DIFF="_no changes_"
[ "$BEFORE" = "$AFTER" ] || DIFF="**$([ "$AFTER" -lt "$BEFORE" ] || echo '+')$(($AFTER - $BEFORE))**"
- CHANGED=$(git diff --no-index "requisites-${PLATFORM}-before.list" "requisites-${PLATFORM}-after.list" | grep -c '^+[^+]')
+ CHANGED=$(git diff --no-index "requisites-${PLATFORM}-before.list" "requisites-${PLATFORM}-after.list" | grep -c '^+[^+]' || true)
TOTAL_CHANGED=$(($TOTAL_CHANGED + $CHANGED))
PERCENT=100
[ "$CHANGED" = "$AFTER" ] || {
@@ -63,8 +68,24 @@ jobs:
PERCENT="$((PERMILLE / 10)).$((PERMILLE % 10))"
}
echo "| ${QUOTE}${PLATFORM}${QUOTE} | $BEFORE -> $AFTER => $DIFF | $CHANGED / $AFTER = $PERCENT% |"
- awk '{ print $0 " ('"$PLATFORM"')" }' "requisites-${PLATFORM}-before.list" >> requisites-before.list
- awk '{ print $0 " ('"$PLATFORM"')" }' "requisites-${PLATFORM}-after.list" >> requisites-after.list
+ for STATE in before after; do
+ # Split store paths into package name, output (or source archive extension), and version.
+ awk -v OFS='\t' -v PLATFORM="$PLATFORM" '{
+ name = substr($0, 45)
+ pname = name
+ output = "out"
+ version = "_unversioned_"
+ if (match(name, /-[^A-Za-z]/)) {
+ pname = substr(name, 1, RSTART - 1)
+ version = substr(name, RSTART + 1)
+ if (match(version, /-[a-z]+$/) || match(version, /\.(tar(\.[a-z0-9]+)?|tgz|tbz2?|txz|zip|patch|diff)$/)) {
+ output = substr(version, RSTART + 1)
+ version = substr(version, 1, RSTART - 1)
+ }
+ }
+ print pname, output, version, PLATFORM, $0
+ }' "requisites-${PLATFORM}-${STATE}.list" >> "requisites-${STATE}.list"
+ done
done
DIFF="_no changes_"
@@ -75,24 +96,87 @@ jobs:
PERCENT="$((PERMILLE / 10)).$((PERMILLE % 10))"
}
echo "| **Total** | $TOTAL_BEFORE -> $TOTAL_AFTER => $DIFF | $TOTAL_CHANGED / $TOTAL_AFTER = $PERCENT% |"
- )
- sort -k1.45 requisites-before.list > requisites-before.sort
- sort -k1.45 requisites-after.list > requisites-after.sort
+ } > comment.md
+ sort requisites-before.list > requisites-before.sort
+ sort requisites-after.list > requisites-after.sort
if git diff -U0 --no-color --no-index requisites-before.sort requisites-after.sort > requisites.diff; then
echo 'No changes detected.'
else
- {
- echo "$TABLE"
- echo
- echo 'Changelog
'
- echo
- echo '```diff'
- tail -n +5 requisites.diff
- echo '```'
- echo
- echo ' '
- } | gh pr comment -R "$GITHUB_REPOSITORY" "$PR_NUMBER" -F -
+ awk -F '\t' '
+ function insert(list, v, n, a, i, out, done) {
+ n = split(list, a, " ")
+ for (i = 1; i <= n; i++) if (a[i] == v) return list
+ out = ""; done = 0
+ for (i = 1; i <= n; i++) {
+ if (!done && v < a[i]) { out = out " " v; done = 1 }
+ out = out " " a[i]
+ }
+ if (!done) out = out " " v
+ return substr(out, 2)
+ }
+ function join(list, pre, post, s) {
+ s = pre list post
+ gsub(/ /, post ", " pre, s)
+ return s
+ }
+ /^[-+]/ && NF == 5 {
+ key = substr($1, 2) SUBSEP $2 SUBSEP $4
+ if (substr($1, 1, 1) == "-") removed[key] = insert(removed[key], $3)
+ else added[key] = insert(added[key], $3)
+ }
+ END {
+ for (key in removed) if (!(key in added)) added[key] = ""
+ for (key in added) {
+ split(key, k, SUBSEP)
+ r = (key in removed) ? removed[key] : ""
+ a = added[key]
+ if (r == a) change = "_no version change_: " join(a)
+ else if (r == "") change = "_added_: " join(a, "**", "**")
+ else if (a == "") change = "_removed_: " join(r)
+ else change = join(r) " -> " join(a, "**", "**")
+ platforms[k[1] SUBSEP k[2] SUBSEP change] = insert(platforms[k[1] SUBSEP k[2] SUBSEP change], k[3])
+ }
+ for (key in platforms) {
+ split(key, k, SUBSEP)
+ row = k[1] SUBSEP k[3] SUBSEP join(platforms[key])
+ outputs[row] = insert(outputs[row], k[2])
+ }
+ for (row in outputs) {
+ split(row, k, SUBSEP)
+ n = split(outputs[row], o, " ")
+ name = ""
+ for (i = 1; i <= n; i++) name = name ", `" k[1] (o[i] == "out" ? "" : "." o[i]) "`"
+ rank = k[2] ~ /^_added_/ ? 0 : k[2] ~ /^_removed_/ ? 2 : k[2] ~ /^_no version change_/ ? 3 : 1
+ print rank "\t| " substr(name, 3) " | " k[2] " | " k[3] " |"
+ }
+ }
+ ' requisites.diff > versions.tsv
+ {
+ echo
+ echo 'Version changes
'
+ echo
+ echo '| Package | Version | Platforms |'
+ echo '| :- | :- | :- |'
+ LC_ALL=C sort -t '`' -k1,1 -k2,2 -k3 versions.tsv | cut -f2-
+ echo
+ echo ' '
+ } >> comment.md
+ gh pr comment -R "$GITHUB_REPOSITORY" "$PR_NUMBER" -F comment.md
fi
env:
GH_TOKEN: ${{ github.token }}
PR_NUMBER: ${{ steps.pr-data.outputs.NUMBER }}
+
+ - name: Report status on the PR
+ if: ${{ always() }}
+ run: |
+ gh api --method POST "repos/${GITHUB_REPOSITORY}/statuses/${HEAD_SHA}" \
+ -f state="$STATE" \
+ -f context="$GITHUB_WORKFLOW" \
+ -f description="$DESCRIPTION" \
+ -f target_url="${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}"
+ env:
+ GH_TOKEN: ${{ github.token }}
+ HEAD_SHA: ${{ github.event.workflow_run.head_sha }}
+ STATE: ${{ job.status == 'success' && 'success' || 'failure' }}
+ DESCRIPTION: ${{ job.status == 'success' && 'Nix requisites changes aggregated' || 'Failed to aggregate Nix requisites changes' }}