diff --git a/.github/scripts/check-licenses.sh b/.github/scripts/check-licenses.sh new file mode 100644 index 000000000..33882e607 --- /dev/null +++ b/.github/scripts/check-licenses.sh @@ -0,0 +1,72 @@ +#!/bin/bash +# This file is synced from the `.github` repository, do not modify it directly. + +set -euo pipefail + +if [[ ! -f .github/denied-licenses.txt ]] +then + echo "::error::.github/denied-licenses.txt is required." + exit 1 +fi +denied="$(sed -E \ + '/^[[:space:]]*(#|$)/d; s/^[[:space:]]*//; s/[[:space:]]*$//' \ + .github/denied-licenses.txt | paste -sd, -)" +if [[ -z "${denied}" ]] +then + echo "::error::.github/denied-licenses.txt must contain at least one licence." + exit 1 +fi +echo "Denied licences: ${denied}" + +export GIT_PKGS_DB="${RUNNER_TEMP:?}/git-pkgs/metadata.db" +output="${RUNNER_TEMP}/licenses.json" +stderr="${RUNNER_TEMP}/licenses.stderr" +check_licenses() { + local label="$1" status=0 violations count + shift + "$@" --format=json --deny="${denied}" \ + >"${output}" 2>"${stderr}" || status="$?" + if ! jq -e 'type == "array"' "${output}" &>/dev/null + then + echo "git pkgs licenses failed:" + cat "${stderr}" + cat "${output}" + if ((status == 0)) + then + exit 1 + fi + exit "${status}" + fi + + violations="$(jq -r \ + '.[] | select(.flagged) | . as $dep | + "\($dep.name) (\($dep.ecosystem)) \($dep.version // "?"): \($dep.licenses | join(", ")) - \($dep.flag_reason)"' \ + "${output}")" + if [[ -n "${violations}" ]] + then + echo "Dependencies with denied licences:" + echo "${violations}" + exit 1 + fi + if ((status != 0)) + then + cat "${stderr}" + exit "${status}" + fi + count="$(jq length "${output}")" + echo "${label}: No denied licences found in ${count} dependencies." +} + +check_licenses Non-Swift git \ + -c pkgs.ecosystems=cargo \ + -c pkgs.ecosystems=docker \ + -c pkgs.ecosystems=rubygems \ + -c pkgs.ecosystems=github-actions \ + -c pkgs.ecosystems=npm \ + -c pkgs.ecosystems=pypi \ + pkgs licenses + +# Keep Swift's filtered snapshots separate from the other ecosystems. +# Include transitive dependencies and Xcode lockfiles without a Package.swift. +GIT_PKGS_DB="${RUNNER_TEMP}/git-pkgs/swift.db" \ + check_licenses Swift git -c pkgs.ecosystems=swift pkgs licenses --dependencies=all diff --git a/.github/workflows/licenses.yml b/.github/workflows/licenses.yml index 0d4d17e67..e3d6fb62d 100644 --- a/.github/workflows/licenses.yml +++ b/.github/workflows/licenses.yml @@ -11,10 +11,13 @@ on: - "**/Cargo.lock" - "**/Cargo.toml" - "**/Gemfile.lock" + - "**/Package.resolved" + - "**/Package.swift" - "**/package-lock.json" - "**/package.json" - "**/requirements.txt" - .github/denied-licenses.txt + - .github/scripts/check-licenses.sh - .github/workflows/licenses.yml merge_group: @@ -45,61 +48,12 @@ jobs: uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: path: ${{ runner.temp }}/git-pkgs - key: git-pkgs-metadata-v1-${{ hashFiles('**/Gemfile.lock', '**/Cargo.toml', '**/Cargo.lock', '**/package.json', '**/package-lock.json', '**/requirements.txt') }} + key: git-pkgs-metadata-v1-${{ hashFiles('**/Gemfile.lock', '**/Cargo.toml', '**/Cargo.lock', '**/Package.resolved', '**/Package.swift', '**/package.json', '**/package-lock.json', '**/requirements.txt') }} restore-keys: git-pkgs-metadata-v1- - - name: Read denied licences - run: | - if [[ ! -f .github/denied-licenses.txt ]]; then - echo "::error::.github/denied-licenses.txt is required." - exit 1 - fi - denied="$(sed -E \ - '/^[[:space:]]*(#|$)/d; s/^[[:space:]]*//; s/[[:space:]]*$//' \ - .github/denied-licenses.txt | paste -sd, -)" - if [[ -z "${denied}" ]]; then - echo "::error::.github/denied-licenses.txt must contain at least one licence." - exit 1 - fi - echo "Denied licences: ${denied}" - echo "DENIED_LICENSES=${denied}" >> "${GITHUB_ENV}" - - name: Check licences env: - GIT_PKGS_DB: ${{ runner.temp }}/git-pkgs/metadata.db # Identify ecosyste.ms requests for its polite pool: # https://github.com/git-pkgs/git-pkgs#configuration GIT_PKGS_ECOSYSTEMS_FROM: leads@brew.sh - run: | - output="${RUNNER_TEMP}/licenses.json" - stderr="${RUNNER_TEMP}/licenses.stderr" - status=0 - git \ - -c pkgs.ecosystems=cargo \ - -c pkgs.ecosystems=docker \ - -c pkgs.ecosystems=rubygems \ - -c pkgs.ecosystems=github-actions \ - -c pkgs.ecosystems=npm \ - -c pkgs.ecosystems=pypi \ - pkgs licenses --format=json --deny="${DENIED_LICENSES}" \ - > "${output}" 2> "${stderr}" || status="$?" - if ! jq -e 'type == "array"' "${output}" &>/dev/null; then - echo "git pkgs licenses failed:" - cat "${stderr}" - cat "${output}" - if ((status == 0)); then - exit 1 - fi - exit "${status}" - fi - - violations="$(jq -r \ - '.[] | select(.flagged) | . as $dep | - "\($dep.name) (\($dep.ecosystem)) \($dep.version // "?"): \($dep.licenses | join(", ")) - \($dep.flag_reason)"' \ - "${output}")" - if [ -n "${violations}" ]; then - echo "Dependencies with denied licences:" - echo "${violations}" - exit 1 - fi - echo "No denied licences found in $(jq length "${output}") dependencies." + run: bash .github/scripts/check-licenses.sh