The license bot service (Dcntrlized/license-bot) is authoritative: it amends missing AGPL headers into the PR head commit, including for fork PRs, and reports the license-bot / addlicense commit status. This workflow now only reports an honest advisory signal, holds no secrets and never writes.
109 lines
3.9 KiB
YAML
109 lines
3.9 KiB
YAML
name: license-headers
|
|
|
|
# Advisory license check.
|
|
#
|
|
# The Dcntrlized license bot (the webhook service in this repository) is the
|
|
# authority: it amends the missing AGPL headers into the pull request's head
|
|
# commit and reports the `license-bot / addlicense` commit status. This workflow
|
|
# duplicates the check read-only so a pull request still shows an honest signal
|
|
# when the bot is unavailable. It holds no secrets, never writes, and must not
|
|
# be made a required check: Gitea evaluates a pull request's workflows from the
|
|
# head branch, so any context this job reports can be reproduced by a
|
|
# contributor who edits the workflow.
|
|
|
|
on:
|
|
pull_request:
|
|
types: [opened, synchronize, reopened, ready_for_review]
|
|
|
|
permissions:
|
|
contents: read
|
|
pull-requests: read
|
|
|
|
concurrency:
|
|
group: license-headers-${{ gitea.event.pull_request.number }}
|
|
cancel-in-progress: true
|
|
|
|
defaults:
|
|
run:
|
|
shell: sh
|
|
|
|
jobs:
|
|
addlicense:
|
|
name: addlicense
|
|
runs-on: alpine-latest
|
|
steps:
|
|
- name: Prerequisites
|
|
run: apk add --no-cache git curl ca-certificates jq
|
|
|
|
- name: Install addlicense
|
|
run: |
|
|
set -e
|
|
curl -fsSL -o /tmp/addlicense.tgz \
|
|
https://github.com/google/addlicense/releases/download/v1.2.0/addlicense_v1.2.0_Linux_x86_64.tar.gz
|
|
tar -xzf /tmp/addlicense.tgz -C /tmp
|
|
install -m 0755 /tmp/addlicense /usr/local/bin/addlicense
|
|
|
|
- name: Check added files for an AGPL header
|
|
env:
|
|
TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
SERVER: ${{ gitea.server_url }}
|
|
REPO: ${{ gitea.repository }}
|
|
NUM: ${{ gitea.event.pull_request.number }}
|
|
HEAD_REPO: ${{ gitea.event.pull_request.head.repo.full_name }}
|
|
HEAD_REF: ${{ gitea.event.pull_request.head.ref }}
|
|
run: |
|
|
set -e
|
|
SCHEME="${SERVER%%://*}"
|
|
HOST="${SERVER#*://}"
|
|
api() { curl -fsS -H "Authorization: token $TOKEN" "$@"; }
|
|
|
|
# Every file this pull request added (paginated).
|
|
page=1
|
|
: > /tmp/added.txt
|
|
while :; do
|
|
batch="$(api "$SERVER/api/v1/repos/$REPO/pulls/$NUM/files?limit=50&page=$page")"
|
|
printf '%s' "$batch" | jq -r '.[] | select(.status=="added") | .filename' >> /tmp/added.txt
|
|
[ "$(printf '%s' "$batch" | jq 'length')" -lt 50 ] && break
|
|
page=$((page + 1))
|
|
done
|
|
|
|
if [ ! -s /tmp/added.txt ]; then
|
|
echo "This pull request adds no files; nothing to check."
|
|
exit 0
|
|
fi
|
|
|
|
# The head may be a fork: the per-run token is read-only and can
|
|
# still clone it. The scheme comes from gitea.server_url because the
|
|
# instance may be plain HTTP.
|
|
git clone --quiet --depth 1 --branch "$HEAD_REF" \
|
|
"$SCHEME://oauth2:$TOKEN@$HOST/$HEAD_REPO.git" /tmp/pr
|
|
cd /tmp/pr
|
|
|
|
# .licenseignore holds doublestar globs, not prefixes.
|
|
set --
|
|
while IFS= read -r pattern; do
|
|
case "$pattern" in ''|\#*) continue ;; esac
|
|
set -- "$@" -ignore "$pattern"
|
|
done < .licenseignore
|
|
|
|
year="$(date +%Y)"
|
|
: > /tmp/missing.txt
|
|
while IFS= read -r file; do
|
|
[ -z "$file" ] && continue
|
|
[ -e "$file" ] || continue
|
|
if ! addlicense -check -f .license-header.tpl -c Dcntrlized -y "$year" "$@" "$file" >/dev/null 2>&1; then
|
|
printf ' - %s\n' "$file" >> /tmp/missing.txt
|
|
fi
|
|
done < /tmp/added.txt
|
|
|
|
if [ -s /tmp/missing.txt ]; then
|
|
echo "::error::This pull request adds files without an AGPL-3.0 header:"
|
|
cat /tmp/missing.txt
|
|
echo ""
|
|
echo "The license bot normally amends these into your commit automatically."
|
|
echo "If it did not, copy the header from .license-header.tpl and push again."
|
|
exit 1
|
|
fi
|
|
|
|
echo "All added files carry an AGPL-3.0 header."
|