Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce shellcheck to lint shell scripts #15169

Merged
merged 18 commits into from
Feb 22, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions .github/workflows/lint-shellcheck.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
on:
push:
paths:
- '**/*.{sh,bash,fish}'
- './bin/*'
- './scripts/git/pre-commit'
- '.github/workflows/lint-shellcheck.yml'
pull_request:
paths:
- '**/*.{sh,bash,fish}'
- './bin/*'
- './scripts/git/pre-commit'
- '.github/workflows/lint-shellcheck.yml'

name: "Lint Shellcheck"
permissions: {}

jobs:
shellcheck:
name: Shellcheck
runs-on: ubuntu-24.04
steps:
- run: shellcheck --version
- uses: actions/checkout@v4
- run: make lint-shellcheck
6 changes: 6 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,12 @@ interpreter_spec: $(O)/interpreter_spec$(EXE) ## Run interpreter specs
smoke_test: ## Build specs as a smoke test
smoke_test: $(O)/std_spec$(EXE) $(O)/compiler_spec$(EXE) $(O)/$(CRYSTAL_BIN)

SHELLCHECK_SOURCES := $(wildcard **/*.sh) bin/crystal bin/ci bin/check-compiler-flag scripts/git/pre-commit

.PHONY: lint-shellcheck
lint-shellcheck:
shellcheck --severity=warning $(SHELLCHECK_SOURCES)

.PHONY: all_spec
all_spec: $(O)/all_spec$(EXE) ## Run all specs (note: this builds a huge program; `test` recipe builds individual binaries and is recommended for reduced resource usage)
$(O)/all_spec$(EXE) $(SPEC_FLAGS)
Expand Down
35 changes: 18 additions & 17 deletions bin/ci
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
#!/bin/sh

fail() {
echo "${@}" >&2
echo "${*}" >&2
exit 1
}

on_tag() {
if [ -n "$CURRENT_TAG" ]; then
echo "${@}"
eval "${@}"
echo "${*}"
eval "${*}"
return $?
else
return 0
Expand All @@ -20,7 +20,7 @@ fail_on_error() {

exit=$?
if [ "$exit" -ne "0" ]; then
fail "${@} exited with $exit"
fail "${*} exited with $exit"
fi

return 0
Expand Down Expand Up @@ -50,8 +50,8 @@ on_os() {
verify_environment

if [ "$TRAVIS_OS_NAME" = "$os" ]; then
echo "${@}"
eval "${@}"
echo "${*}"
eval "${*}"
return $?
else
return 0
Expand All @@ -62,30 +62,30 @@ on_os() {
}

on_linux() {
fail_on_error on_os "linux" "${@}"
fail_on_error on_os "linux" "${*}"
}

on_osx() {
fail_on_error on_os "osx" "${@}"
fail_on_error on_os "osx" "${*}"
}

on_nix_shell_eval() {
if [ -n "$CI_NIX_SHELL" ]; then
echo "${@}"
eval "${@}"
echo "${*}"
eval "${*}"
return $?
else
return 0
fi
}

on_nix_shell() {
fail_on_error on_nix_shell_eval "${@}"
fail_on_error on_nix_shell_eval "${*}"
}

on_github() {
if [ "$GITHUB_ACTIONS" = "true" ]; then
eval "${@}"
eval "${*}"
return $?
else
return 0
Expand Down Expand Up @@ -153,7 +153,7 @@ prepare_build() {

# Install a recent bash version for nix-shell.
# macos ships with an ancient one.
if [ `uname` = "Darwin" ]; then
if [ "$(uname)" = "Darwin" ]; then
on_nix_shell "brew install bash"
fi
# initialize nix environment
Expand All @@ -172,7 +172,7 @@ prepare_build() {

verify_version() {
# If building a tag, check it matches with file
FILE_VERSION=`cat ./src/VERSION`
FILE_VERSION=$(cat ./src/VERSION)

if [ "$FILE_VERSION" != "$CURRENT_TAG" ]
then
Expand Down Expand Up @@ -205,8 +205,8 @@ with_build_env() {

on_linux docker run \
--rm -t \
-u $(id -u) \
-v $PWD:/mnt \
-u "$(id -u)" \
-v "$PWD":/mnt \
-v /etc/passwd:/etc/passwd \
-v /etc/group:/etc/group \
-w /mnt \
Expand All @@ -222,6 +222,7 @@ with_build_env() {
CRYSTAL_CACHE_DIR="/tmp/crystal" \
/bin/sh -c "'$command'"

# shellcheck disable=SC2086
on_nix_shell nix-shell --pure $CI_NIX_SHELL_ARGS --run "'TZ=$TZ $command'"

on_github echo "::endgroup::"
Expand Down Expand Up @@ -254,7 +255,7 @@ case $command in
prepare_build
;;
with_build_env)
target_command="${@}"
target_command="${*}"
with_build_env "$target_command"
;;
build)
Expand Down
2 changes: 1 addition & 1 deletion bin/crystal
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ fi
# CRYSTAL_PATH has all symlinks resolved. In order to avoid issues with duplicate file
# paths when the working directory is a symlink, we cd into the current directory
# with symlinks resolved as well (see https://github.com/crystal-lang/crystal/issues/12969).
cd "$(realpath "$(pwd)")"
cd "$(realpath "$(pwd)")" || exit

case "$(uname -s)" in
CYGWIN*|MSYS_NT*|MINGW32_NT*|MINGW64_NT*)
Expand Down
2 changes: 2 additions & 0 deletions scripts/git/pre-commit
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ changed_cr_files=$(git diff --cached --name-only --diff-filter=ACM | grep '\.cr$

if [ -x bin/crystal ]; then
# use bin/crystal wrapper when available to run local compiler build
# shellcheck disable=SC2086
exec bin/crystal tool format --check $changed_cr_files >&2
else
# shellcheck disable=SC2086
exec crystal tool format --check $changed_cr_files >&2
fi
4 changes: 2 additions & 2 deletions scripts/release-update.sh
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,13 @@ sed -i -E "s|crystal: \"[0-9.]+\"|crystal: \"$CRYSTAL_VERSION\"|g" .github/workf

# Edit shell.nix latestCrystalBinary using nix-prefetch-url --unpack <url>
darwin_url="https://github.com/crystal-lang/crystal/releases/download/$CRYSTAL_VERSION/crystal-$CRYSTAL_VERSION-1-darwin-universal.tar.gz"
darwin_sha=$(nix-prefetch-url --unpack $darwin_url)
darwin_sha=$(nix-prefetch-url --unpack "$darwin_url")

sed -i -E "s|https://github.com/crystal-lang/crystal/releases/download/[0-9.]+/crystal-[0-9.]+-[0-9]-darwin-universal.tar.gz|$darwin_url|" shell.nix
sed -i -E "/darwin-universal\.tar\.gz/ {n;s|sha256:[^\"]+|sha256:$darwin_sha|}" shell.nix

linux_url="https://github.com/crystal-lang/crystal/releases/download/$CRYSTAL_VERSION/crystal-$CRYSTAL_VERSION-1-linux-x86_64.tar.gz"
linux_sha=$(nix-prefetch-url --unpack $linux_url)
linux_sha=$(nix-prefetch-url --unpack "$linux_url")

sed -i -E "s|https://github.com/crystal-lang/crystal/releases/download/[0-9.]+/crystal-[0-9.]+-[0-9]-linux-x86_64.tar.gz|$linux_url|" shell.nix
sed -i -E "/linux-x86_64\.tar\.gz/ {n;s|sha256:[^\"]+|sha256:$linux_sha|}" shell.nix
10 changes: 5 additions & 5 deletions scripts/update-changelog.sh
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,10 @@ branch="changelog/$VERSION"
current_changelog="CHANGELOG.$VERSION.md"

echo "Generating $current_changelog..."
scripts/github-changelog.cr $VERSION > $current_changelog
scripts/github-changelog.cr "$VERSION" > "$current_changelog"

echo "Switching to branch $branch"
git switch $branch 2>/dev/null || git switch -c $branch;
git switch "$branch" 2>/dev/null || git switch -c "$branch";

# Write release version into src/VERSION
echo "${VERSION}" > src/VERSION
Expand All @@ -49,8 +49,8 @@ sed -i -E "s/version: .*/version: ${VERSION}/" shard.yml
git add shard.yml

# Write release date into src/SOURCE_DATE_EPOCH
release_date=$(head -n1 $current_changelog | grep -o -P '(?<=\()[^)]+')
echo "$(date --utc --date="${release_date}" +%s)" > src/SOURCE_DATE_EPOCH
release_date=$(head -n1 "$current_changelog" | grep -o -P '(?<=\()[^)]+')
date --utc --date="${release_date}" +%s > src/SOURCE_DATE_EPOCH
git add src/SOURCE_DATE_EPOCH

if grep --silent -E "^## \[$VERSION\]" CHANGELOG.md; then
Expand All @@ -70,7 +70,7 @@ else

git add CHANGELOG.md
git commit -m "Add changelog for $VERSION"
git push -u upstream $branch
git push -u upstream "$branch"

gh pr create --draft --base "$base_branch" \
--body "Preview: https://github.com/crystal-lang/crystal/blob/$branch/CHANGELOG.md" \
Expand Down
4 changes: 2 additions & 2 deletions scripts/update-distribution-scripts.sh
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,14 @@ branch="${2:-"ci/update-distribution-scripts"}"
git switch -C "$branch" master

old_reference=$(sed -n "/distribution-scripts-version:/{n;n;n;p}" .circleci/config.yml | grep -o -P '(?<=default: ")[^"]+')
echo $old_reference..$reference
echo "$old_reference".."$reference"

sed -i -E "/distribution-scripts-version:/{n;n;n;s/default: \".*\"/default: \"$reference\"/}" .circleci/config.yml

git add .circleci/config.yml

message="Updates \`distribution-scripts\` dependency to https://github.com/crystal-lang/distribution-scripts/commit/$reference"
log=$($GIT_DS log $old_reference..$reference --format="%s" | sed "s/.*(/crystal-lang\/distribution-scripts/;s/^/* /;s/)$//")
log=$($GIT_DS log "$old_reference".."$reference" --format="%s" | sed "s/.*(/crystal-lang\/distribution-scripts/;s/^/* /;s/)$//")
message=$(printf "%s\n\nThis includes the following changes:\n\n%s" "$message" "$log")

git commit -m "Update distribution-scripts" -m "$message"
Expand Down
2 changes: 1 addition & 1 deletion scripts/update-shards.sh
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,4 @@ if [ -z "$SHARDS_VERSION" ]; then
fi

# Update shards ref in mingw64 and win-msvc build actions
sed -i "/repository: crystal-lang\/shards/{n;s/ref: .*/ref: ${shards_version}/}" .github/workflows/mingw-w64.yml .github/workflows/win_build_portable.yml
sed -i "/repository: crystal-lang\/shards/{n;s/ref: .*/ref: ${SHARDS_VERISON}/}" .github/workflows/mingw-w64.yml .github/workflows/win_build_portable.yml
14 changes: 7 additions & 7 deletions spec/debug/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,11 @@ BUILD_DIR=$SCRIPT_ROOT/../../.build
crystal=${CRYSTAL_SPEC_COMPILER_BIN:-$SCRIPT_ROOT/../../bin/crystal}
debugger=${1:-lldb}
driver=$BUILD_DIR/debug_driver
mkdir -p $BUILD_DIR
"$crystal" build $SCRIPT_ROOT/driver.cr -o $driver
mkdir -p "$BUILD_DIR"
"$crystal" build "$SCRIPT_ROOT"/driver.cr -o "$driver"

$driver $SCRIPT_ROOT/top_level.cr $debugger
$driver $SCRIPT_ROOT/strings.cr $debugger
$driver $SCRIPT_ROOT/arrays.cr $debugger
$driver $SCRIPT_ROOT/blocks.cr $debugger
$driver $SCRIPT_ROOT/large_enums.cr $debugger
$driver "$SCRIPT_ROOT"/top_level.cr "$debugger"
$driver "$SCRIPT_ROOT"/strings.cr "$debugger"
$driver "$SCRIPT_ROOT"/arrays.cr "$debugger"
$driver "$SCRIPT_ROOT"/blocks.cr "$debugger"
$driver "$SCRIPT_ROOT"/large_enums.cr "$debugger"
6 changes: 3 additions & 3 deletions spec/generate_wasm32_spec.sh
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ set +x

WORK_DIR=$(mktemp -d)
function cleanup {
rm -rf $WORK_DIR
rm -rf "$WORK_DIR"
}
trap cleanup EXIT

Expand All @@ -39,8 +39,8 @@ echo

for spec in $(find "spec/std" -type f -iname "*_spec.cr" | LC_ALL=C sort); do
require="require \"./${spec##spec/}\""
target=$WORK_DIR"/"$spec".wasm"
mkdir -p $(dirname "$target")
target="$WORK_DIR/$spec.wasm"
mkdir -p "$(dirname "$target")"

if ! output=$(bin/crystal build "$spec" -o "$target" --target wasm32-wasi 2>&1); then
if [[ "$output" =~ "execution of command failed" ]]; then
Expand Down
19 changes: 10 additions & 9 deletions spec/llvm-ir/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,31 +9,32 @@ SCRIPT_PATH="$(realpath "$0")"
SCRIPT_ROOT="$(dirname "$SCRIPT_PATH")"

BUILD_DIR=$SCRIPT_ROOT/../../.build
LLVM_CONFIG="$(basename $($SCRIPT_ROOT/../../src/llvm/ext/find-llvm-config.sh))"
LLVM_CONFIG="$(basename $("$SCRIPT_ROOT"/../../src/llvm/ext/find-llvm-config.sh))"
FILE_CHECK=FileCheck-"${LLVM_CONFIG#llvm-config-}"
crystal=${CRYSTAL_SPEC_COMPILER_BIN:-$SCRIPT_ROOT/../../bin/crystal}

mkdir -p $BUILD_DIR
mkdir -p "$BUILD_DIR"

function test() {
echo "test: $@"
echo "test: $*"

input_cr="$SCRIPT_ROOT/$1"
output_ll="$BUILD_DIR/${1%.cr}.ll"
compiler_options="$2"
# FIXME: unused variable
# compiler_options="$2"
check_prefix="${3+--check-prefix $3}"

# $BUILD_DIR/test-ir is never used
# pushd $BUILD_DIR + $output_ll is a workaround due to the fact that we can't control
# the filename generated by --emit=llvm-ir
"$crystal" build --single-module --no-color --emit=llvm-ir $2 -o $BUILD_DIR/test-ir $input_cr
$FILE_CHECK $input_cr --input-file $output_ll $check_prefix
"$crystal" build --single-module --no-color --emit=llvm-ir "$2" -o "$BUILD_DIR"/test-ir "$input_cr"
$FILE_CHECK "$input_cr" --input-file "$output_ll" "$check_prefix"

rm $BUILD_DIR/test-ir.o
rm $output_ll
rm "$BUILD_DIR"/test-ir.o
rm "$output_ll"
}

pushd $BUILD_DIR >/dev/null
pushd "$BUILD_DIR" >/dev/null

test argless-initialize-debug-loc.cr "--cross-compile --target x86_64-unknown-linux-gnu --prelude=empty"
test proc-call-debug-loc.cr "--cross-compile --target x86_64-unknown-linux-gnu --prelude=empty"
Expand Down
19 changes: 10 additions & 9 deletions src/llvm/ext/find-llvm-config.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@

if ! LLVM_CONFIG=$(command -v "$LLVM_CONFIG"); then
llvm_config_version=$(llvm-config --version 2>/dev/null)
for version in $(cat "$(dirname $0)/llvm-versions.txt"); do
# shellcheck disable=SC2013
for version in $(cat "$(dirname "$0")/llvm-versions.txt"); do
LLVM_CONFIG=$(
([ "${llvm_config_version#$version}" != "$llvm_config_version" ] && command -v llvm-config) || \
command -v llvm-config-${version%.*} || \
command -v llvm-config-$version || \
command -v llvm-config${version%.*}${version#*.} || \
command -v llvm-config${version%.*} || \
command -v llvm-config$version || \
command -v llvm${version%.*}-config)
([ "${llvm_config_version#"$version"}" != "$llvm_config_version" ] && command -v llvm-config) || \
command -v llvm-config-"${version%.*}" || \
command -v llvm-config-"$version" || \
command -v "llvm-config${version%.*}${version#*.}" || \
command -v llvm-config"${version%.*}" || \
command -v llvm-config"$version" || \
command -v llvm"${version%.*}"-config)
[ "$LLVM_CONFIG" ] && break
done
fi
Expand All @@ -26,6 +27,6 @@ if [ "$LLVM_CONFIG" ]; then
esac
else
printf "Error: Could not find location of llvm-config. Please specify path in environment variable LLVM_CONFIG.\n" >&2
printf "Supported LLVM versions: $(cat "$(dirname $0)/llvm-versions.txt" | sed 's/\.0//g')\n" >&2
printf "Supported LLVM versions: %s\n" "$(sed 's/\.0//g' "$(dirname "$0")/llvm-versions.txt")" >&2
exit 1
fi