diff --git a/.hooks/pre-commit b/.hooks/pre-commit index d2d52a71ab..0b4d6e0c94 100755 --- a/.hooks/pre-commit +++ b/.hooks/pre-commit @@ -35,7 +35,7 @@ block() { # Add all check functions to this space separated list. # They are executed in this order (see end of file). -CHECKS="ui_lint backend_lint" +CHECKS="ui_lint ui_copywrite backend_lint" # Run ui linter if changes in that dir detected. ui_lint() { @@ -72,6 +72,79 @@ backend_lint() { ./scripts/gofmtcheck.sh "${staged}" || block "Backend linting failed; run 'make fmt' to fix." } +ui_copywrite() { + DIR=ui + BINARY_DIR=$DIR/.copywrite + DOWNLOAD_ERR="==> Copywrite tool not found and failed to downloaded. Please download manually and extract to ui/.copywrite directory to utilize in pre-commit hook." + + # silently succeed if no changes staged for $DIR + if git diff --name-only --cached --exit-code -- $DIR/; then + return 0 + fi + + echo "==> Changes detected in $DIR/: Checking copyright headers..." + + # download latest version of hashicorp/copywrite if necessary + if [ ! -x $BINARY_DIR/copywrite ]; then + local REPO_URL=https://github.com/hashicorp/copywrite + # get the latest version tag + local LATEST_RELEASE_JSON=$(curl -L -s -H 'Accept: application/json' $REPO_URL/releases/latest); + local LATEST_TAG=$(echo $LATEST_RELEASE_JSON | sed -e 's/.*"tag_name":"\([^"]*\)".*/\1/') + + if [ ! $LATEST_TAG ]; then + echo $DOWNLOAD_ERR + return 0; + fi + + # get the OS/Architecture specifics to build the filename + # eg. copywrite_0.16.6_darwin_x86_64.tar.gz + case "$OSTYPE" in + linux*) OS='linux' ;; + darwin*) OS='darwin' ;; + msys*) OS='windows';; + esac + local ARCH=$([ $(uname -m) == arm* ] && echo 'arm64' || echo 'x86_64') + local EXT=$([ $OSTYPE == "msys" ] && echo '.zip' || echo '.tar.gz') + local FILENAME=copywrite_"${LATEST_TAG:1}"_"$OS"_"$ARCH""$EXT" + + mkdir -p $BINARY_DIR + echo "==> Copywrite tool not found, downloading version $LATEST_TAG from $REPO_URL..." + curl -L -s $REPO_URL/releases/download/$LATEST_TAG/$FILENAME | tar -xz - -C $BINARY_DIR || { echo $DOWNLOAD_ERR; return 0; }; + fi + + # run the copywrite tool + # if a --path option is added we could apply the headers to only the staged files much easier + # as of the latest version 0.16.6 there is only support for --dirPath + STAGED_FILES=($(git diff --name-only --cached)) + + rm -rf $BINARY_DIR/.staged + mkdir $BINARY_DIR/.staged + + # copy staged files to .staged directory + echo $STAGED_FILES; + for FILE_PATH in "${STAGED_FILES[@]}"; do + cp $FILE_PATH $BINARY_DIR/.staged + done + + COPYWRITE_LOG_LEVEL=info + COPY_CMD="$BINARY_DIR/copywrite headers -d $BINARY_DIR/.staged --config $DIR/.copywrite.hcl" + + # if staged files are missing header run the tool on .staged directory + VALIDATE=$(eval $COPY_CMD --plan) # assigning to var so output is suppressed since it is repeated during second run + if [ $(echo $?) == 1 ]; then + eval $COPY_CMD || { echo "==> Copyright check failed. Please review and add headers manually."; return 0; }; + + # copy files back to original locations and stage changes + local TMP_FILES=$(ls $BINARY_DIR/.staged) + i=0 + for FILE in $TMP_FILES; do + cp $BINARY_DIR/.staged/$FILE "${STAGED_FILES[$i]}" + git add "${STAGED_FILES[$i]}" + i=$(( i + 1 )) + done + fi +} + for CHECK in $CHECKS; do # Force each check into a subshell to avoid crosstalk. ( $CHECK ) || exit $? diff --git a/ui/.copywrite.hcl b/ui/.copywrite.hcl new file mode 100644 index 0000000000..935bc238e4 --- /dev/null +++ b/ui/.copywrite.hcl @@ -0,0 +1,33 @@ +# (OPTIONAL) Overrides the copywrite config schema version +# Default: 1 +schema_version = 1 + +project { + # (OPTIONAL) SPDX-compatible license identifier + # Leave blank if you don't wish to license the project + # Default: "MPL-2.0" + license = "BUSL-1.1" + + # (OPTIONAL) Represents the copyright holder used in all statements + # Default: HashiCorp, Inc. + # copyright_holder = "" + + # (OPTIONAL) Represents the year that the project initially began + # Default: + # copyright_year = 0 + + # (OPTIONAL) A list of globs that should not have copyright or license headers . + # Supports doublestar glob patterns for more flexibility in defining which + # files or folders should be ignored + # Default: [] + header_ignore = [ + "node_modules/**" + ] + + # (OPTIONAL) Links to an upstream repo for determining repo relationships + # This is for special cases and should not normally be set. + # Default: "" + # upstream = "hashicorp/" +} + + diff --git a/ui/.gitignore b/ui/.gitignore index f51263f3dd..5ba1567f70 100644 --- a/ui/.gitignore +++ b/ui/.gitignore @@ -38,3 +38,7 @@ package-lock.json !.yarn/releases !.yarn/sdks !.yarn/versions + +# copywrite tool used in pre-commit hook +.copywrite +