|
1 | 1 | #!/bin/bash |
| 2 | +# |
| 3 | +# Generate license files for all platform/arch combinations. |
| 4 | +# This script handles architecture-specific dependency differences by: |
| 5 | +# 1. Generating separate license reports per GOOS/GOARCH combination |
| 6 | +# 2. Grouping identical reports together (comma-separated arch names) |
| 7 | +# 3. Creating an index at the top of each platform file |
| 8 | +# 4. Copying all license files to third-party/ |
| 9 | +# |
| 10 | +# Note: third-party/ is a union of all license files across all architectures. |
| 11 | +# This means that license files for dependencies present in only some architectures |
| 12 | +# may still appear in third-party/. This is intentional and ensures compliance. |
| 13 | +# |
| 14 | +# Note: we ignore warnings because we want the command to succeed, however the output should be checked |
| 15 | +# for any new warnings, and potentially we may need to add license information. |
| 16 | +# |
| 17 | +# Normally these warnings are packages containing non go code, which may or may not require explicit attribution, |
| 18 | +# depending on the license. |
| 19 | + |
| 20 | +set -e |
2 | 21 |
|
3 | 22 | go install github.com/google/go-licenses@latest |
4 | 23 |
|
| 24 | +# actions/setup-go does not setup the installed toolchain to be preferred over the system install, |
| 25 | +# which causes go-licenses to raise "Package ... does not have module info" errors in CI. |
| 26 | +# For more information, https://github.com/google/go-licenses/issues/244#issuecomment-1885098633 |
| 27 | +if [ "$CI" = "true" ]; then |
| 28 | + export GOROOT=$(go env GOROOT) |
| 29 | + export PATH=${GOROOT}/bin:$PATH |
| 30 | +fi |
| 31 | + |
5 | 32 | rm -rf third-party |
6 | 33 | mkdir -p third-party |
7 | 34 | export TEMPDIR="$(mktemp -d)" |
8 | 35 |
|
9 | 36 | trap "rm -fr ${TEMPDIR}" EXIT |
10 | 37 |
|
11 | | -for goos in linux darwin windows ; do |
12 | | - # Note: we ignore warnings because we want the command to succeed, however the output should be checked |
13 | | - # for any new warnings, and potentially we may need to add license information. |
14 | | - # |
15 | | - # Normally these warnings are packages containing non go code, which may or may not require explicit attribution, |
16 | | - # depending on the license. |
17 | | - GOOS="${goos}" GOFLAGS=-mod=mod go-licenses save ./... --save_path="${TEMPDIR}/${goos}" --force || echo "Ignore warnings" |
18 | | - GOOS="${goos}" GOFLAGS=-mod=mod go-licenses report ./... --template .github/licenses.tmpl > third-party-licenses.${goos}.md || echo "Ignore warnings" |
19 | | - cp -fR "${TEMPDIR}/${goos}"/* third-party/ |
| 38 | +# Cross-platform hash function (works on both Linux and macOS) |
| 39 | +compute_hash() { |
| 40 | + if command -v md5sum >/dev/null 2>&1; then |
| 41 | + md5sum | cut -d' ' -f1 |
| 42 | + elif command -v md5 >/dev/null 2>&1; then |
| 43 | + md5 -q |
| 44 | + else |
| 45 | + # Fallback to cksum if neither is available |
| 46 | + cksum | cut -d' ' -f1 |
| 47 | + fi |
| 48 | +} |
| 49 | + |
| 50 | +# Function to get architectures for a given OS |
| 51 | +get_archs() { |
| 52 | + case "$1" in |
| 53 | + linux) echo "386 amd64 arm64" ;; |
| 54 | + darwin) echo "amd64 arm64" ;; |
| 55 | + windows) echo "386 amd64 arm64" ;; |
| 56 | + esac |
| 57 | +} |
| 58 | + |
| 59 | +# Generate reports for each platform/arch combination |
| 60 | +for goos in darwin linux windows; do |
| 61 | + echo "Processing ${goos}..." |
| 62 | + |
| 63 | + archs=$(get_archs "$goos") |
| 64 | + |
| 65 | + for goarch in $archs; do |
| 66 | + echo " Generating for ${goos}/${goarch}..." |
| 67 | + |
| 68 | + # Generate the license report for this arch |
| 69 | + report_file="${TEMPDIR}/${goos}_${goarch}_report.md" |
| 70 | + GOOS="${goos}" GOARCH="${goarch}" GOFLAGS=-mod=mod go-licenses report ./... --template .github/licenses.tmpl > "${report_file}" 2>/dev/null || echo " (warnings ignored for ${goos}/${goarch})" |
| 71 | + |
| 72 | + # Save licenses to temp directory |
| 73 | + GOOS="${goos}" GOARCH="${goarch}" GOFLAGS=-mod=mod go-licenses save ./... --save_path="${TEMPDIR}/${goos}_${goarch}" --force 2>/dev/null || echo " (warnings ignored for ${goos}/${goarch})" |
| 74 | + |
| 75 | + # Copy to third-party (accumulate all - union of all architectures for compliance) |
| 76 | + if [ -d "${TEMPDIR}/${goos}_${goarch}" ]; then |
| 77 | + cp -fR "${TEMPDIR}/${goos}_${goarch}"/* third-party/ 2>/dev/null || true |
| 78 | + fi |
| 79 | + |
| 80 | + # Extract just the package list (skip header), sort it, and hash it |
| 81 | + # Use LC_ALL=C for consistent sorting across different systems |
| 82 | + packages_file="${TEMPDIR}/${goos}_${goarch}_packages.txt" |
| 83 | + if [ -s "${report_file}" ] && grep -qE '^ - \[' "${report_file}" 2>/dev/null; then |
| 84 | + grep -E '^ - \[' "${report_file}" | LC_ALL=C sort > "${packages_file}" |
| 85 | + hash=$(cat "${packages_file}" | compute_hash) |
| 86 | + else |
| 87 | + echo "(FAILED TO GENERATE LICENSE REPORT FOR ${goos}/${goarch})" > "${packages_file}" |
| 88 | + hash="FAILED_${goos}_${goarch}" |
| 89 | + fi |
| 90 | + |
| 91 | + # Store hash for grouping |
| 92 | + echo "${hash}" > "${TEMPDIR}/${goos}_${goarch}_hash.txt" |
| 93 | + done |
| 94 | + |
| 95 | + # Group architectures with identical reports (deterministic order) |
| 96 | + # Create groups file: hash -> comma-separated archs |
| 97 | + groups_file="${TEMPDIR}/${goos}_groups.txt" |
| 98 | + rm -f "${groups_file}" |
| 99 | + |
| 100 | + # Process architectures in order to build groups |
| 101 | + for goarch in $archs; do |
| 102 | + hash=$(cat "${TEMPDIR}/${goos}_${goarch}_hash.txt") |
| 103 | + # Check if we've seen this hash before |
| 104 | + if grep -q "^${hash}:" "${groups_file}" 2>/dev/null; then |
| 105 | + # Append to existing group |
| 106 | + existing=$(grep "^${hash}:" "${groups_file}" | cut -d: -f2) |
| 107 | + sed -i.bak "s/^${hash}:.*/${hash}:${existing}, ${goarch}/" "${groups_file}" |
| 108 | + rm -f "${groups_file}.bak" |
| 109 | + else |
| 110 | + # New group |
| 111 | + echo "${hash}:${goarch}" >> "${groups_file}" |
| 112 | + fi |
| 113 | + done |
| 114 | + |
| 115 | + # Generate the combined report for this platform |
| 116 | + output_file="third-party-licenses.${goos}.md" |
| 117 | + |
| 118 | + cat > "${output_file}" << 'EOF' |
| 119 | +# GitHub MCP Server dependencies |
| 120 | +
|
| 121 | +The following open source dependencies are used to build the [github/github-mcp-server][] GitHub Model Context Protocol Server. |
| 122 | +
|
| 123 | +## Table of Contents |
| 124 | +
|
| 125 | +EOF |
| 126 | + |
| 127 | + # Build table of contents (sorted for determinism) |
| 128 | + # Use LC_ALL=C for consistent sorting across different systems |
| 129 | + LC_ALL=C sort "${groups_file}" | while IFS=: read -r hash group_archs; do |
| 130 | + # Create anchor-friendly name |
| 131 | + anchor=$(echo "${group_archs}" | tr ', ' '-' | tr -s '-') |
| 132 | + echo "- [${group_archs}](#${anchor})" >> "${output_file}" |
| 133 | + done |
| 134 | + |
| 135 | + echo "" >> "${output_file}" |
| 136 | + echo "---" >> "${output_file}" |
| 137 | + echo "" >> "${output_file}" |
| 138 | + |
| 139 | + # Add each unique report section (sorted for determinism) |
| 140 | + # Use LC_ALL=C for consistent sorting across different systems |
| 141 | + LC_ALL=C sort "${groups_file}" | while IFS=: read -r hash group_archs; do |
| 142 | + # Get the packages from the first arch in this group |
| 143 | + first_arch=$(echo "${group_archs}" | cut -d',' -f1 | tr -d ' ') |
| 144 | + packages=$(cat "${TEMPDIR}/${goos}_${first_arch}_packages.txt") |
| 145 | + |
| 146 | + cat >> "${output_file}" << EOF |
| 147 | +## ${group_archs} |
| 148 | +
|
| 149 | +The following packages are included for the ${group_archs} architectures. |
| 150 | +
|
| 151 | +${packages} |
| 152 | +
|
| 153 | +EOF |
| 154 | + done |
| 155 | + |
| 156 | + # Add footer |
| 157 | + echo "[github/github-mcp-server]: https://github.com/github/github-mcp-server" >> "${output_file}" |
| 158 | + |
| 159 | + echo "Generated ${output_file}" |
20 | 160 | done |
21 | 161 |
|
| 162 | +echo "Done! License files generated." |
| 163 | + |
0 commit comments