blob: 09e6c2372614d8363145fc71437e0b70ca81e515 [file]
#!/usr/bin/env bash
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
SPARK_PROFILES=${1:-"-Pkubernetes -Pyarn -Pspark-ganglia-lgpl -Pkinesis-asl -Phive-thriftserver -Phive -Pvolcano -Pjvm-profiler -Phadoop-cloud -Pdocker-integration-tests -Pkubernetes-integration-tests"}
# NOTE: echo "q" is needed because SBT prompts the user for input on encountering a build file
# with failure (either resolution or compilation); the "q" makes SBT quit.
ERRORS=$(echo -e "q\n" \
| build/sbt \
${SPARK_PROFILES} \
scalastyle test:scalastyle \
| awk '{if($1~/error/)print}' \
)
if test ! -z "$ERRORS"; then
echo -e "Scalastyle checks failed at following occurrences:\n$ERRORS"
# When running under GitHub Actions, also emit each scalastyle violation as
# a workflow `::error` annotation so it appears inline on the PR's "Files
# changed" tab. Without this, a violation cascades into ~7 red CI checks
# (Linters, Java 17/25 Maven build, Documentation generation, sparkr,
# Docker integration, TPC-DS) -- all needing catalyst to compile -- and
# each only surfaces a generic "exit code 1" with no file/line, forcing
# the user to download a full job log to find the actual violation.
if [[ "${GITHUB_ACTIONS:-}" == "true" ]]; then
# Strip ANSI color codes from the captured output before regex
# matching. Today sbt under awk's pipe is not a TTY and skips color,
# so the input is already plain. But if sbt color is ever forced
# (`-Dsbt.color=always`, custom CI shell), `\e[31m` would silently
# break every regex below. Cheap to harden.
ERRORS_PLAIN=$(printf '%s' "$ERRORS" | sed -E $'s/\x1b\\[[0-9;]*[A-Za-z]//g')
# Helper: emit one `::error` annotation. Centralised so the two regex
# branches below stay short.
emit_annotation() {
local file="$1" lineno="$2" msg="$3"
# Strip the GitHub Actions workspace prefix so the annotation
# references the path as it appears in the repo.
local file_rel="${file#${GITHUB_WORKSPACE:-}/}"
# Escape the few characters GitHub reserves in annotation values:
# %, \r, \n. (`,` and `:` need not be escaped in the message body,
# only inside parameter values, which we don't use.)
local msg_escaped="${msg//%/%25}"
msg_escaped="${msg_escaped//$'\r'/%0D}"
msg_escaped="${msg_escaped//$'\n'/%0A}"
printf '::error file=%s,line=%s,title=Scalastyle::%s\n' \
"$file_rel" "$lineno" "$msg_escaped"
}
printf '%s\n' "$ERRORS_PLAIN" | while IFS= read -r raw; do
# Two scalastyle output formats reach us:
#
# (a) scalastyle's native console writer (`Tasks.doScalastyle` when
# invoked by the explicit `scalastyle` / `test:scalastyle`
# tasks):
# error file=<path> message=<text> line=<n> [column=<n>]
# The path has no spaces, the message can; `column=<n>` is
# appended for checkers that report a column (e.g.
# `WhitespaceEndOfLineChecker`) and absent otherwise.
#
# (b) sbt's logger format, used when `Tasks.doScalastyle` writes
# through `streams.value.log.error(...)` -- which is what the
# explicit `scalastyle` / `test:scalastyle` tasks invoked by
# this script do, and so this is the format we see in CI:
# [error] <path>:<line>: <message>
# The leading `[error] ` plus a single `:<line>:` (with no
# `:<col>:` follow-up) is what tells it apart from a regular
# Scala compile error of shape `[error] <path>:<line>:<col>: <msg>`.
if [[ "$raw" =~ ^error[[:space:]]+file=([^[:space:]]+)[[:space:]]+message=(.*)[[:space:]]+line=([0-9]+)([[:space:]]+column=[0-9]+)?$ ]]; then
emit_annotation "${BASH_REMATCH[1]}" "${BASH_REMATCH[3]}" "${BASH_REMATCH[2]}"
elif [[ "$raw" =~ ^\[error\][[:space:]]+(/[^:[:space:]]+):([0-9]+):[[:space:]]+(.+)$ ]]; then
emit_annotation "${BASH_REMATCH[1]}" "${BASH_REMATCH[2]}" "${BASH_REMATCH[3]}"
fi
done
fi
exit 1
else
echo -e "Scalastyle checks passed."
fi