Skip to content

Commit bbb1d5a

Browse files
authored
Merge pull request #36788 from vespa-engine/laura/VESPANG-3162
add nightly attribution workflow and ATTRIBUTIONS.md
2 parents 81e1c8a + 45e7073 commit bbb1d5a

3 files changed

Lines changed: 1310 additions & 0 deletions

File tree

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
#!/usr/bin/env bash
2+
# Build a deduplicated ATTRIBUTIONS.md from one or more inventory JSON files.
3+
#
4+
# Usage: build-attribution.sh <inventory.json> [<inventory.json> ...]
5+
# Output: markdown attribution document on stdout.
6+
#
7+
# Each input is expected in the wrapped shape produced by the
8+
# vespa-engine/gh-actions/mend-inventory action:
9+
# { response: [ { component, license, copyrights, extraData, ... }, ... ],
10+
# additionalData: { totalItems: N } }
11+
set -euo pipefail
12+
13+
today=$(date -u +"%Y-%m-%d")
14+
15+
cat <<EOF
16+
# Third-Party Software Attributions
17+
18+
This file is auto-generated nightly and lists the open-source software
19+
dependencies of Vespa detected by scanning package manifests.
20+
21+
For the hand-maintained list of vendored C/C++ libraries (Boost, OpenSSL,
22+
ICU, etc.), see [\`NOTICES\`](NOTICES).
23+
24+
Last updated: $today
25+
EOF
26+
27+
# Skip entries that don't have an identified license (the scanner couldn't
28+
# determine one, or the entry has no package identity to attribute).
29+
skipped=$(jq -s '
30+
[.[] | (.response // [])[]
31+
| select(.license.name == "Requires Review" or (.component.groupId // "") == "")]
32+
| length
33+
' "$@")
34+
jq -s -r '
35+
[ .[] | (.response // [])[]
36+
| select(.license.name != "Requires Review" and (.component.groupId // "") != "")
37+
]
38+
| group_by([.component.groupId, .component.version, .license.name])
39+
| map(.[0])
40+
| sort_by([((.component.groupId // "") | ascii_downcase), (.component.version // "")])
41+
| map(
42+
[
43+
"",
44+
"---",
45+
"",
46+
("## " + .component.groupId + " " + .component.version + " — " + .license.name),
47+
""
48+
]
49+
+ (if ((.extraData.homepage // "") | length) > 0
50+
then ["- Homepage: <" + .extraData.homepage + ">"]
51+
else [] end)
52+
+ ((.copyrights // []) | map("- " + .))
53+
| join("\n")
54+
)
55+
| join("\n")
56+
' "$@"
57+
58+
# Trailing newline so the file ends cleanly.
59+
echo

.github/workflows/attribution.yml

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
name: Update Third-Party Attributions
2+
3+
on:
4+
workflow_dispatch:
5+
schedule:
6+
- cron: "0 3 * * *" # nightly 03:00 UTC
7+
pull_request:
8+
branches: [master]
9+
paths:
10+
- .github/workflows/attribution.yml
11+
- .github/scripts/build-attribution.sh
12+
- ATTRIBUTIONS.md
13+
14+
permissions:
15+
contents: write
16+
pull-requests: write
17+
18+
jobs:
19+
attribution:
20+
runs-on: ubuntu-latest
21+
steps:
22+
- name: Checkout
23+
uses: actions/checkout@v6
24+
25+
- name: Fetch dependency inventory
26+
uses: vespa-engine/gh-actions/mend-inventory@217825ab3497a98c67134a9e8bb30f04329e82fe # v1
27+
with:
28+
mend-project-name: GH_vespa_master
29+
mend-project-uuid: dbdbea81-7f52-426c-974f-975c2848770d
30+
mend-user: ${{ vars.MEND_ATTRIBUTION_USER_EMAIL }}
31+
mend-api-key: ${{ secrets.MEND_ATTRIBUTION_USER_KEY }}
32+
output-path: build/inventory.json
33+
34+
- name: Build ATTRIBUTIONS.md
35+
run: |
36+
./.github/scripts/build-attribution.sh build/inventory.json > ATTRIBUTIONS.md
37+
echo "Wrote $(wc -l < ATTRIBUTIONS.md) lines to ATTRIBUTIONS.md"
38+
39+
# Only uploaded on failure so the raw response is available for debugging
40+
# without bloating the artifact list on every successful run.
41+
- name: Upload raw inventory JSON (debug, on failure)
42+
if: ${{ failure() }}
43+
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
44+
with:
45+
name: inventory-debug
46+
path: build/inventory.json
47+
retention-days: 7
48+
if-no-files-found: warn
49+
50+
- name: Upload ATTRIBUTIONS.md
51+
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
52+
with:
53+
name: attributions
54+
path: ATTRIBUTIONS.md
55+
retention-days: 14
56+
57+
- name: Open PR if changed
58+
if: ${{ github.event_name != 'pull_request' }}
59+
env:
60+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
61+
run: |
62+
set -euo pipefail
63+
git config user.email "github-actions[bot]@users.noreply.github.com"
64+
git config user.name "github-actions[bot]"
65+
66+
git add ATTRIBUTIONS.md
67+
if git diff --cached --quiet; then
68+
echo "ATTRIBUTIONS.md is up to date — nothing to do."
69+
exit 0
70+
fi
71+
72+
BRANCH="chore/update-attributions"
73+
git checkout -B "$BRANCH"
74+
git commit -m "chore: update third-party attributions"
75+
git push --force --set-upstream origin "$BRANCH"
76+
77+
if gh pr view "$BRANCH" --json state --jq .state 2>/dev/null | grep -q OPEN; then
78+
echo "PR for $BRANCH already open — pushed update to existing PR."
79+
else
80+
gh pr create \
81+
--base master \
82+
--head "$BRANCH" \
83+
--title "chore: update third-party attributions" \
84+
--body "Auto-generated update of ATTRIBUTIONS.md."
85+
fi

0 commit comments

Comments
 (0)