Skip to content

Commit

Permalink
Refactor shellcheck feature (#5)
Browse files Browse the repository at this point in the history
  • Loading branch information
jgarber623 committed Mar 1, 2024
2 parents 3ca31c4 + 5354528 commit 7c022aa
Show file tree
Hide file tree
Showing 10 changed files with 212 additions and 86 deletions.
2 changes: 1 addition & 1 deletion src/shellcheck/devcontainer-feature.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "ShellCheck",
"id": "shellcheck",
"version": "1.0.0",
"version": "1.1.0",
"description": "Install ShellCheck, a static analysis tool for shell scripts.",
"options": {
"version": {
Expand Down
60 changes: 32 additions & 28 deletions src/shellcheck/install.sh
Original file line number Diff line number Diff line change
@@ -1,53 +1,57 @@
#!/usr/bin/env sh
#!/usr/bin/env bash

set -e

SHELLCHECK_VERSION="${VERSION:-"os-provided"}"
INSTALL_PATH="${INSTALLPATH:-"/usr/local/bin"}"

if [ "$(id -u)" -ne 0 ]; then
printf 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.'
exit 1
fi
SHELLCHECK_INSTALL_PATH="${INSTALLPATH:-"/usr/local/bin"}"
SHELLCHECK_REPOSITORY="https://github.com/koalaman/shellcheck"

DIRNAME=$(dirname -- "${0}")
SCRIPT_DIR=$(cd -- "${DIRNAME}" > /dev/null 2>&1 && pwd)

if [ "${SHELLCHECK_VERSION}" = "os-provided" ]; then
apt update --yes
apt install --no-install-recommends --yes shellcheck
# shellcheck source=./src/shellcheck/shared.lib.sh
. "${SCRIPT_DIR}"/shared.lib.sh

if type shellcheck > /dev/null 2>&1; then
echo "Detected existing system install: $(shellcheck --version)"
clean_up
exit 0
fi

curl_installed=""

if ! type curl >/dev/null 2>&1; then
apt update --yes
apt install --no-install-recommends --yes curl ca-certificates xz-utils
check_packages curl ca-certificates xz-utils

curl_installed="true"
if [[ "${SHELLCHECK_VERSION}" = "os-provided" ]]; then
check_packages shellcheck
exit 0
fi

if [ "${SHELLCHECK_VERSION}" = "latest" ]; then
SHELLCHECK_VERSION="$(curl -s --head https://github.com/koalaman/shellcheck/releases/latest | sed -nr 's/location:.*\/v(.+)/\1/ip' | tr -d '\r')"
if [[ "${SHELLCHECK_VERSION}" = "latest" ]]; then
SHELLCHECK_VERSION=$(set -e; latest_release_version "${SHELLCHECK_REPOSITORY}")
fi

machine="$(uname -m)"
case "${machine}" in
aarch64) arch="aarch64" ;;
arm*) arch="armv6" ;;
x86_64) arch="x86_64" ;;
aarch64)
arch="aarch64"
;;
arm*)
arch="armv6"
;;
x86_64)
arch="x86_64"
;;
*)
echo "Could not determine arch from machine hardware name '${machine}'" >&2
exit 1
;;
;;
esac

# https://github.com/koalaman/shellcheck/releases/download/v0.9.0/shellcheck-v0.9.0.linux.aarch64.tar.xz
file="shellcheck-v${SHELLCHECK_VERSION}.linux.${arch}.tar.xz"
url="https://github.com/koalaman/shellcheck/releases/download/v${SHELLCHECK_VERSION}/${file}"
url="${SHELLCHECK_REPOSITORY}/releases/download/v${SHELLCHECK_VERSION}/shellcheck-v${SHELLCHECK_VERSION}.linux.${arch}.tar.xz"

curl -sSL "${url}" | tar --strip-components=1 -Jxvf - -C "${INSTALL_PATH}" "shellcheck-v${SHELLCHECK_VERSION}/shellcheck"
echo "Downloading ${url} with curl..."

if [ -n "${curl_installed}" ]; then
apt purge curl xz-utils --autoremove --yes
fi
# curl -L "${url}" | tar xvf -C "${SHELLCHECK_INSTALL_PATH}" shellcheck
curl -L "${url}" | tar --strip-components=1 -Jxvf - -C "${SHELLCHECK_INSTALL_PATH}" "shellcheck-v${SHELLCHECK_VERSION}/shellcheck"

echo "Done!"
100 changes: 100 additions & 0 deletions src/shellcheck/shared.lib.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
#!/usr/bin/env bash

if [[ "$(id -u)" -ne 0 ]]; then
printf 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.'
exit 1
fi

# Bring in ID, ID_LIKE, VERSION_ID, VERSION_CODENAME
. /etc/os-release
# Get an adjusted ID independent of distro variants
# shellcheck disable=SC2154
if [[ "${ID}" = "debian" ]] || [[ "${ID_LIKE}" = "debian" ]]; then
ADJUSTED_ID="debian"
elif [[ "${ID}" = "rhel" || "${ID}" = "fedora" || "${ID}" = "mariner" || "${ID_LIKE}" = *"rhel"* || "${ID_LIKE}" = *"fedora"* || "${ID_LIKE}" = *"mariner"* ]]; then
ADJUSTED_ID="rhel"
# shellcheck disable=SC2034
VERSION_CODENAME="${ID}${VERSION_ID}"
else
echo "Linux distro ${ID} not supported."
exit 1
fi

if type apt-get > /dev/null 2>&1; then
INSTALL_CMD="apt-get"
elif type microdnf > /dev/null 2>&1; then
INSTALL_CMD="microdnf"
elif type dnf > /dev/null 2>&1; then
INSTALL_CMD="dnf"
elif type yum > /dev/null 2>&1; then
INSTALL_CMD="yum"
else
echo "Unable to find a supported package manager."
exit 1
fi

clean_up() {
case ${ADJUSTED_ID} in
debian)
rm -rf /var/lib/apt/lists/*
;;
rhel)
rm -rf /var/cache/dnf/*
rm -rf /var/cache/yum/*
;;
*)
;;
esac
}

pkg_mgr_update() {
if [[ "${INSTALL_CMD}" = "apt-get" ]]; then
if [[ "$(find /var/lib/apt/lists/* | wc -l)" = "0" ]]; then
echo "Running apt-get update..."
${INSTALL_CMD} update -y
fi
elif [[ ${INSTALL_CMD} = "dnf" ]] || [[ ${INSTALL_CMD} = "yum" ]]; then
if [[ "$(find /var/cache/"${INSTALL_CMD}"/* | wc -l)" = "0" ]]; then
echo "Running ${INSTALL_CMD} check-update..."
${INSTALL_CMD} check-update
fi
fi
}

check_packages() {
if [[ "${INSTALL_CMD}" = "apt-get" ]]; then
if ! dpkg -s "$@" > /dev/null 2>&1; then
pkg_mgr_update
${INSTALL_CMD} -y install --no-install-recommends "$@"
fi
elif [[ "${INSTALL_CMD}" = "dnf" ]] || [[ "${INSTALL_CMD}" = "yum" ]]; then
_num_pkgs=$(echo "$@" | tr ' ' \\012 | wc -l)
_num_installed=$(${INSTALL_CMD} -C list installed "$@" | sed '1,/^Installed/d' | wc -l)
if [[ "${_num_pkgs}" != "${_num_installed}" ]]; then
pkg_mgr_update
${INSTALL_CMD} -y install "$@"
fi
elif [[ "${INSTALL_CMD}" = "microdnf" ]]; then
${INSTALL_CMD} -y install \
--refresh \
--best \
--nodocs \
--noplugins \
--setopt=install_weak_deps=0 \
"$@"
else
echo "Linux distro ${ID} not supported."
exit 1
fi
}

latest_release_version() {
if [[ $# -eq 0 ]]; then
echo "No repository URL provided."
exit 1
fi

curl -s --head "${1}"/releases/latest | sed -nr 's/location:.*\/v(.+)/\1/ip' | tr -d '\r'
}

export DEBIAN_FRONTEND="noninteractive"
14 changes: 14 additions & 0 deletions test/shellcheck/install-bookworm-with-options.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/usr/bin/env bash

set -e

# Optional: Import test library bundled with the devcontainer CLI
# shellcheck source=/dev/null
source dev-container-features-test-lib

# Feature-specific tests
check "version" bash -c "shellcheck --version | grep 0.8.0"
check "which shellcheck" bash -c "which shellcheck | grep /usr/bin/shellcheck"

# Report result
reportResults
14 changes: 14 additions & 0 deletions test/shellcheck/install-bookworm.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/usr/bin/env bash

set -e

# Optional: Import test library bundled with the devcontainer CLI
# shellcheck source=/dev/null
source dev-container-features-test-lib

# Feature-specific tests
check "version" shellcheck --version
check "which shellcheck" bash -c "which shellcheck | grep /usr/bin/shellcheck"

# Report result
reportResults
14 changes: 14 additions & 0 deletions test/shellcheck/install-jammy-with-options.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/usr/bin/env bash

set -e

# Optional: Import test library bundled with the devcontainer CLI
# shellcheck source=/dev/null
source dev-container-features-test-lib

# Feature-specific tests
check "version" bash -c "shellcheck --version | grep 0.8.0"
check "which shellcheck" bash -c "which shellcheck | grep /usr/bin/shellcheck"

# Report result
reportResults
14 changes: 14 additions & 0 deletions test/shellcheck/install-jammy.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/usr/bin/env bash

set -e

# Optional: Import test library bundled with the devcontainer CLI
# shellcheck source=/dev/null
source dev-container-features-test-lib

# Feature-specific tests
check "version" shellcheck --version
check "which shellcheck" bash -c "which shellcheck | grep /usr/local/bin/shellcheck"

# Report result
reportResults
28 changes: 23 additions & 5 deletions test/shellcheck/scenarios.json
Original file line number Diff line number Diff line change
@@ -1,17 +1,35 @@
{
"shellcheck-version": {
"image": "debian:latest",
"install-bookworm": {
"image": "debian:bookworm",
"features": {
"shellcheck": {}
}
},

"install-bookworm-with-options": {
"image": "debian:bookworm",
"features": {
"shellcheck": {
"version": "0.8.0",
"installPath": "/usr/bin"
}
}
},

"install-jammy": {
"image": "ubuntu:jammy",
"features": {
"shellcheck": {
"version": "0.8.0"
"version": "latest"
}
}
},

"shellcheck-install-path": {
"image": "debian:latest",
"install-jammy-with-options": {
"image": "ubuntu:jammy",
"features": {
"shellcheck": {
"version": "0.8.0",
"installPath": "/usr/bin"
}
}
Expand Down
18 changes: 0 additions & 18 deletions test/shellcheck/shellcheck-version.sh

This file was deleted.

34 changes: 0 additions & 34 deletions test/shellcheck/test.sh
Original file line number Diff line number Diff line change
@@ -1,48 +1,14 @@
#!/usr/bin/env bash

# This test file will be executed against an auto-generated devcontainer.json that
# includes the 'shellcheck' Feature with no options.
#
# For more information, see: https://github.com/devcontainers/cli/blob/main/docs/features/test.md
#
# Eg:
# {
# "image": "<..some-base-image...>",
# "features": {
# "shellcheck": {}
# },
# "remoteUser": "root"
# }
#
# Thus, the value of all options will fall back to the default value in the
# Feature's 'devcontainer-feature.json'.
#
# These scripts are run as 'root' by default. Although that can be changed
# with the '--remote-user' flag.
#
# This test can be run with the following command:
#
# devcontainer features test \
# --features shellcheck \
# --remote-user root \
# --skip-scenarios \
# --base-image mcr.microsoft.com/devcontainers/base:ubuntu \
# /path/to/this/repo

set -e

# Optional: Import test library bundled with the devcontainer CLI
# See https://github.com/devcontainers/cli/blob/HEAD/docs/features/test.md#dev-container-features-test-lib
# Provides the 'check' and 'reportResults' commands.
# shellcheck source=/dev/null
source dev-container-features-test-lib

# Feature-specific tests
# The 'check' command comes from the dev-container-features-test-lib. Syntax is...
# check <LABEL> <cmd> [args...]
check "version" shellcheck --version
check "which shellcheck" bash -c "which shellcheck | grep /usr/bin/shellcheck"

# Report result
# If any of the checks above exited with a non-zero exit code, the test will fail.
reportResults

0 comments on commit 7c022aa

Please sign in to comment.