Skip to content

Commit

Permalink
[GHA] Add license header check
Browse files Browse the repository at this point in the history
# Motivation

We need to make sure all code files have the appropriate license headers in place. This is currently part of the soundness check and we need to replace this with a GH action.

# Modification

Adds a new job to the reusable workflow the check all files for license headers. Since some files are ignored every repo can specify a `.licenseignore` file.

# Result

Last part of the soundness script migrated.
  • Loading branch information
FranzBusch committed Jul 11, 2024
1 parent 8631602 commit d18de7d
Show file tree
Hide file tree
Showing 5 changed files with 143 additions and 15 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/pull_request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ jobs:
name: Checks
uses: ./.github/workflows/reusable_pull_request.yml
with:
benchmarks_linux_package_path: "Benchmarks"
benchmarks_linux_package_path: "Benchmarks"
license_header_check_project_name: "SwiftNIO"
21 changes: 20 additions & 1 deletion .github/workflows/reusable_pull_request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,14 @@ on:
type: string
description: "List of unacceptable words. Defaults to a sensible list of words."
default: "blacklist whitelist slave master sane sanity insane insanity kill killed killing hang hung hanged hanging" #ignore-unacceptable-language
license_header_check_enabled:
type: boolean
description: "Boolean to enable the license header check job. Defaults to true."
default: true
license_header_check_project_name:
type: boolean
description: "Name of the project called out in the license header."
required: true

## We are cancelling previously triggered workflow runs
concurrency:
Expand Down Expand Up @@ -135,4 +143,15 @@ jobs:
- name: Run unacceptable language check
env:
UNACCEPTABLE_WORD_LIST: ${{ inputs.unacceptable_language_check_word_list}}
run: ./scripts/check-unacceptable-language.sh
run: ./scripts/check-unacceptable-language.sh

license-header-check:
name: License headers check
if: ${{ inputs.license_header_check_enabled }}
runs-on: ubuntu-latest
timeout-minutes: 1
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Run license header check
run: ./scripts/check-license-header.sh
16 changes: 16 additions & 0 deletions .licenseignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
Sources/CNIOAtomics/src/cpp_magic.h
Sources/CNIOLLHTTP/LICENSE-MIT
Sources/CNIOLLHTTP/c_nio_api.c
Sources/CNIOLLHTTP/c_nio_http.c
Sources/CNIOLLHTTP/c_nio_llhttp.c
Sources/CNIOLLHTTP/include/c_nio_llhttp.h
Sources/CNIOSHA1/c_nio_sha1.c
Sources/CNIOSHA1/include/CNIOSHA1.h
dev/alloc-limits-from-test-output
dev/boxed-existentials.d
dev/git.commit.template
dev/lldb-smoker
dev/make-single-file-spm
dev/malloc-aggregation.d
dev/update-alloc-limits-to-last-completed-ci-build
scripts/nio-diagnose
13 changes: 0 additions & 13 deletions Benchmarks/Package.swift
Original file line number Diff line number Diff line change
@@ -1,17 +1,4 @@
// swift-tools-version: 5.7
//===----------------------------------------------------------------------===//
//
// This source file is part of the SwiftCertificates open source project
//
// Copyright (c) 2023 Apple Inc. and the SwiftCertificates project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of SwiftCertificates project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//

import PackageDescription

Expand Down
105 changes: 105 additions & 0 deletions scripts/check-license-header.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
#!/bin/bash
##===----------------------------------------------------------------------===##
##
## This source file is part of the SwiftNIO open source project
##
## Copyright (c) 2024 Apple Inc. and the SwiftNIO project authors
## Licensed under Apache License v2.0
##
## See LICENSE.txt for license information
## See CONTRIBUTORS.txt for the list of SwiftNIO project authors
##
## SPDX-License-Identifier: Apache-2.0
##
##===----------------------------------------------------------------------===##
set -euo pipefail

log() { printf -- "** %s\n" "$*" >&2; }
error() { printf -- "** ERROR: %s\n" "$*" >&2; }
fatal() { error "$@"; exit 1; }

test -n "${PROJECT_NAME:-}" || fatal "PROJECT_NAME unset"

expected_file_header_template="@@===----------------------------------------------------------------------===@@
@@
@@ This source file is part of the ${PROJECT_NAME} open source project
@@
@@ Copyright (c) YEARS Apple Inc. and the ${PROJECT_NAME} project authors
@@ Licensed under Apache License v2.0
@@
@@ See LICENSE.txt for license information
@@ See CONTRIBUTORS.txt for the list of ${PROJECT_NAME} project authors
@@
@@ SPDX-License-Identifier: Apache-2.0
@@
@@===----------------------------------------------------------------------===@@"

paths_with_missing_license=( )

file_paths=$(git ls-files \
":(exclude).gitignore" \
":(exclude)**/.gitignore" \
":(exclude).licenseignore" \
":(exclude).gitattributes" \
":(exclude).mailfilter" \
":(exclude).mailmap" \
":(exclude).spi.yml" \
":(exclude).swift-format" \
":(exclude).github/*" \
":(exclude)*.md" \
":(exclude)*.txt" \
":(exclude)*.yaml" \
":(exclude)*.json" \
":(exclude)Package.swift" \
":(exclude)**/Package.swift" \
":(exclude)Package.resolved" \
":(exclude)**/Package.resolved" \
":(exclude)Makefile" \
":(exclude)*.modulemap" \
":(exclude)**/*.modulemap" \
":(exclude)**/*.docc/*" \
":(exclude)*.xcprivacy" \
":(exclude)**/*.xcprivacy" \
":(exclude)*.symlink" \
":(exclude)**/*.symlink" \
":(exclude)Dockerfile" \
":(exclude)**/Dockerfile" \
":(exclude)Snippets/*" \
$(printf ":(exclude)%s " $(cat .licenseignore))
)

while IFS= read -r file_path; do
file_basename=$(basename -- "${file_path}")
file_extension="${file_basename##*.}"

case "${file_extension}" in
swift) expected_file_header=$(sed -e 's|@@|//|g' <<<"${expected_file_header_template}") ;;
h) expected_file_header=$(sed -e 's|@@|//|g' <<<"${expected_file_header_template}") ;;
c) expected_file_header=$(sed -e 's|@@|//|g' <<<"${expected_file_header_template}") ;;
yml) expected_file_header=$(sed -e 's|@@|##|g' <<<"${expected_file_header_template}") ;;
sh) expected_file_header=$(cat <(echo '#!/bin/bash') <(sed -e 's|@@|##|g' <<<"${expected_file_header_template}")) ;;
py) expected_file_header=$(cat <(echo '#!/usr/bin/env python3') <(sed -e 's|@@|##|g' <<<"${expected_file_header_template}")) ;;
rb) expected_file_header=$(cat <(echo '#!/usr/bin/env ruby') <(sed -e 's|@@|##|g' <<<"${expected_file_header_template}")) ;;
*) fatal "Unsupported file extension for file (exclude or update this script): ${file_path}" ;;
esac
expected_file_header_linecount=$(wc -l <<<"${expected_file_header}")

file_header=$(head -n "${expected_file_header_linecount}" "${file_path}")
normalized_file_header=$(
echo "${file_header}" \
| sed -e 's/20[12][0123456789]-20[12][0123456789]/YEARS/' -e 's/20[12][0123456789]/YEARS/' \
)

if ! diff -u \
--label "Expected header" <(echo "${expected_file_header}") \
--label "${file_path}" <(echo "${normalized_file_header}")
then
paths_with_missing_license+=("${file_path} ")
fi
done <<< "$file_paths"

if [ "${#paths_with_missing_license[@]}" -gt 0 ]; then
fatal "❌ Found missing license header in files: ${paths_with_missing_license[*]}."
fi

log "✅ Found no files with missing license header."

0 comments on commit d18de7d

Please sign in to comment.