Skip to content

Commit 3ca31c4

Browse files
Refactor actionlint feature (#4)
Now that I've built a few of these things and had more time to reference existing projects, I've tried out these updates with a focus on what could be made reusable. Especially that new `shared.lib.sh` file that extracts _stuff_ out that'll be common across Features. The script itself will need to be duplicated because of the way in which Features work and are built and deployed. But, at least it tidies up the actual script needed to install a thing.
2 parents 99659fe + 28ca9e7 commit 3ca31c4

12 files changed

+227
-91
lines changed

src/actionlint/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,6 @@ Install [actionlint](https://github.com/rhysd/actionlint), a static checker for
1919

2020
## OS Support
2121

22-
This Feature should work on recent versions of Debian/Ubuntu and Linux distributions using the [apt](https://wiki.debian.org/AptCLI) management tool.
22+
This Feature should work on recent versions of Debian/Ubuntu, RedHat Enterprise Linux, Fedora, Alma, and RockyLinux distributions with the `apt`, `yum`, `dnf`, or `microdnf` package manager installed.
2323

2424
`bash` is required to execute the `install.sh` script.

src/actionlint/devcontainer-feature.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "actionlint",
33
"id": "actionlint",
4-
"version": "1.0.0",
4+
"version": "1.1.0",
55
"description": "Install actionlint, a static checker for GitHub Actions workflow files.",
66
"options": {
77
"version": {

src/actionlint/install.sh

Lines changed: 43 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,54 @@
1-
#!/usr/bin/env sh
1+
#!/usr/bin/env bash
22

33
set -e
44

55
ACTIONLINT_VERSION="${VERSION:-"latest"}"
6-
INSTALL_PATH="${INSTALLPATH:-"/usr/local/bin"}"
6+
ACTIONLINT_INSTALL_PATH="${INSTALLPATH:-"/usr/local/bin"}"
7+
ACTIONLINT_REPOSITORY="https://github.com/rhysd/actionlint"
78

8-
if [ "$(id -u)" -ne 0 ]; then
9-
printf 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.'
10-
exit 1
11-
fi
12-
13-
curl_installed=""
9+
DIRNAME=$(dirname -- "${0}")
10+
SCRIPT_DIR=$(cd -- "${DIRNAME}" > /dev/null 2>&1 && pwd)
1411

15-
if ! type curl >/dev/null 2>&1; then
16-
apt update --yes
17-
apt install --no-install-recommends --yes curl ca-certificates
12+
# shellcheck source=./src/actionlint/shared.lib.sh
13+
. "${SCRIPT_DIR}"/shared.lib.sh
1814

19-
curl_installed="true"
15+
if type actionlint > /dev/null 2>&1; then
16+
echo "Detected existing system install: $(actionlint --version)"
17+
clean_up
18+
exit 0
2019
fi
2120

22-
curl -sSL https://raw.githubusercontent.com/rhysd/actionlint/main/scripts/download-actionlint.bash | \
23-
/bin/bash -s -- "${ACTIONLINT_VERSION}" "${INSTALL_PATH}"
21+
check_packages curl ca-certificates
2422

25-
if ! [ -z $curl_installed ]; then
26-
apt purge curl --autoremove --yes
23+
if [[ "${ACTIONLINT_VERSION}" = "latest" ]]; then
24+
ACTIONLINT_VERSION=$(set -e; latest_release_version "${ACTIONLINT_REPOSITORY}")
2725
fi
26+
27+
machine="$(uname -m)"
28+
case "${machine}" in
29+
x86_64)
30+
arch="amd64"
31+
;;
32+
i?86)
33+
arch="386"
34+
;;
35+
aarch64|arm64)
36+
arch="arm64"
37+
;;
38+
arm*)
39+
arch="armv6"
40+
;;
41+
*)
42+
echo "Could not determine arch from machine hardware name '${machine}'" >&2
43+
exit 1
44+
;;
45+
esac
46+
47+
# https://github.com/rhysd/actionlint/releases/download/v1.0.0/actionlint_1.0.0_linux_386.tar.gz
48+
url="${ACTIONLINT_REPOSITORY}/releases/download/v${ACTIONLINT_VERSION}/actionlint_${ACTIONLINT_VERSION}_linux_${arch}.tar.gz"
49+
50+
echo "Downloading ${url} with curl..."
51+
52+
curl -L "${url}" | tar xvz -C "${ACTIONLINT_INSTALL_PATH}" actionlint
53+
54+
echo "Done!"

src/actionlint/shared.lib.sh

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
#!/usr/bin/env bash
2+
3+
if [[ "$(id -u)" -ne 0 ]]; then
4+
printf 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.'
5+
exit 1
6+
fi
7+
8+
# Bring in ID, ID_LIKE, VERSION_ID, VERSION_CODENAME
9+
. /etc/os-release
10+
# Get an adjusted ID independent of distro variants
11+
# shellcheck disable=SC2154
12+
if [[ "${ID}" = "debian" ]] || [[ "${ID_LIKE}" = "debian" ]]; then
13+
ADJUSTED_ID="debian"
14+
elif [[ "${ID}" = "rhel" || "${ID}" = "fedora" || "${ID}" = "mariner" || "${ID_LIKE}" = *"rhel"* || "${ID_LIKE}" = *"fedora"* || "${ID_LIKE}" = *"mariner"* ]]; then
15+
ADJUSTED_ID="rhel"
16+
# shellcheck disable=SC2034
17+
VERSION_CODENAME="${ID}${VERSION_ID}"
18+
else
19+
echo "Linux distro ${ID} not supported."
20+
exit 1
21+
fi
22+
23+
if type apt-get > /dev/null 2>&1; then
24+
INSTALL_CMD="apt-get"
25+
elif type microdnf > /dev/null 2>&1; then
26+
INSTALL_CMD="microdnf"
27+
elif type dnf > /dev/null 2>&1; then
28+
INSTALL_CMD="dnf"
29+
elif type yum > /dev/null 2>&1; then
30+
INSTALL_CMD="yum"
31+
else
32+
echo "Unable to find a supported package manager."
33+
exit 1
34+
fi
35+
36+
clean_up() {
37+
case ${ADJUSTED_ID} in
38+
debian)
39+
rm -rf /var/lib/apt/lists/*
40+
;;
41+
rhel)
42+
rm -rf /var/cache/dnf/*
43+
rm -rf /var/cache/yum/*
44+
;;
45+
*)
46+
;;
47+
esac
48+
}
49+
50+
pkg_mgr_update() {
51+
if [[ "${INSTALL_CMD}" = "apt-get" ]]; then
52+
if [[ "$(find /var/lib/apt/lists/* | wc -l)" = "0" ]]; then
53+
echo "Running apt-get update..."
54+
${INSTALL_CMD} update -y
55+
fi
56+
elif [[ ${INSTALL_CMD} = "dnf" ]] || [[ ${INSTALL_CMD} = "yum" ]]; then
57+
if [[ "$(find /var/cache/"${INSTALL_CMD}"/* | wc -l)" = "0" ]]; then
58+
echo "Running ${INSTALL_CMD} check-update..."
59+
${INSTALL_CMD} check-update
60+
fi
61+
fi
62+
}
63+
64+
check_packages() {
65+
if [[ "${INSTALL_CMD}" = "apt-get" ]]; then
66+
if ! dpkg -s "$@" > /dev/null 2>&1; then
67+
pkg_mgr_update
68+
${INSTALL_CMD} -y install --no-install-recommends "$@"
69+
fi
70+
elif [[ "${INSTALL_CMD}" = "dnf" ]] || [[ "${INSTALL_CMD}" = "yum" ]]; then
71+
_num_pkgs=$(echo "$@" | tr ' ' \\012 | wc -l)
72+
_num_installed=$(${INSTALL_CMD} -C list installed "$@" | sed '1,/^Installed/d' | wc -l)
73+
if [[ "${_num_pkgs}" != "${_num_installed}" ]]; then
74+
pkg_mgr_update
75+
${INSTALL_CMD} -y install "$@"
76+
fi
77+
elif [[ "${INSTALL_CMD}" = "microdnf" ]]; then
78+
${INSTALL_CMD} -y install \
79+
--refresh \
80+
--best \
81+
--nodocs \
82+
--noplugins \
83+
--setopt=install_weak_deps=0 \
84+
"$@"
85+
else
86+
echo "Linux distro ${ID} not supported."
87+
exit 1
88+
fi
89+
}
90+
91+
latest_release_version() {
92+
if [[ $# -eq 0 ]]; then
93+
echo "No repository URL provided."
94+
exit 1
95+
fi
96+
97+
curl -s --head "${1}"/releases/latest | sed -nr 's/location:.*\/v(.+)/\1/ip' | tr -d '\r'
98+
}
99+
100+
export DEBIAN_FRONTEND="noninteractive"

test/actionlint/actionlint-install-path.sh

Lines changed: 0 additions & 17 deletions
This file was deleted.

test/actionlint/actionlint-version.sh

Lines changed: 0 additions & 17 deletions
This file was deleted.
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#!/usr/bin/env bash
2+
3+
set -e
4+
5+
# Optional: Import test library bundled with the devcontainer CLI
6+
# shellcheck source=/dev/null
7+
source dev-container-features-test-lib
8+
9+
# Feature-specific tests
10+
check "version" bash -c "actionlint --version | grep 1.6.20"
11+
check "which actionlint" bash -c "which actionlint | grep /usr/bin/actionlint"
12+
13+
# Report result
14+
reportResults

test/actionlint/install-bookworm.sh

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#!/usr/bin/env bash
2+
3+
set -e
4+
5+
# Optional: Import test library bundled with the devcontainer CLI
6+
# shellcheck source=/dev/null
7+
source dev-container-features-test-lib
8+
9+
# Feature-specific tests
10+
check "version" actionlint --version
11+
check "which actionlint" bash -c "which actionlint | grep /usr/local/bin/actionlint"
12+
13+
# Report result
14+
reportResults
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#!/usr/bin/env bash
2+
3+
set -e
4+
5+
# Optional: Import test library bundled with the devcontainer CLI
6+
# shellcheck source=/dev/null
7+
source dev-container-features-test-lib
8+
9+
# Feature-specific tests
10+
check "version" bash -c "actionlint --version | grep 1.6.20"
11+
check "which actionlint" bash -c "which actionlint | grep /usr/bin/actionlint"
12+
13+
# Report result
14+
reportResults

test/actionlint/install-jammy.sh

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#!/usr/bin/env bash
2+
3+
set -e
4+
5+
# Optional: Import test library bundled with the devcontainer CLI
6+
# shellcheck source=/dev/null
7+
source dev-container-features-test-lib
8+
9+
# Feature-specific tests
10+
check "version" actionlint --version
11+
check "which actionlint" bash -c "which actionlint | grep /usr/local/bin/actionlint"
12+
13+
# Report result
14+
reportResults

test/actionlint/scenarios.json

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,37 @@
11
{
2-
"actionlint-version": {
3-
"image": "debian:latest",
2+
"install-bookworm": {
3+
"image": "debian:bookworm",
44
"features": {
55
"actionlint": {
6-
"version": "1.6.20"
6+
"version": "latest"
77
}
88
}
99
},
1010

11-
"actionlint-install-path": {
12-
"image": "debian:latest",
11+
"install-bookworm-with-settings": {
12+
"image": "debian:bookworm",
1313
"features": {
1414
"actionlint": {
15+
"version": "1.6.20",
16+
"installPath": "/usr/bin"
17+
}
18+
}
19+
},
20+
21+
"install-jammy": {
22+
"image": "ubuntu:jammy",
23+
"features": {
24+
"actionlint": {
25+
"version": "latest"
26+
}
27+
}
28+
},
29+
30+
"install-jammy-with-settings": {
31+
"image": "ubuntu:jammy",
32+
"features": {
33+
"actionlint": {
34+
"version": "1.6.20",
1535
"installPath": "/usr/bin"
1636
}
1737
}

test/actionlint/test.sh

Lines changed: 1 addition & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,14 @@
11
#!/usr/bin/env bash
22

3-
# This test file will be executed against an auto-generated devcontainer.json that
4-
# includes the 'actionlint' Feature with no options.
5-
#
6-
# For more information, see: https://github.com/devcontainers/cli/blob/main/docs/features/test.md
7-
#
8-
# Eg:
9-
# {
10-
# "image": "<..some-base-image...>",
11-
# "features": {
12-
# "actionlint": {}
13-
# },
14-
# "remoteUser": "root"
15-
# }
16-
#
17-
# Thus, the value of all options will fall back to the default value in the
18-
# Feature's 'devcontainer-feature.json'.
19-
#
20-
# These scripts are run as 'root' by default. Although that can be changed
21-
# with the '--remote-user' flag.
22-
#
23-
# This test can be run with the following command:
24-
#
25-
# devcontainer features test \
26-
# --features actionlint \
27-
# --remote-user root \
28-
# --skip-scenarios \
29-
# --base-image mcr.microsoft.com/devcontainers/base:ubuntu \
30-
# /path/to/this/repo
31-
323
set -e
334

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

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

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

0 commit comments

Comments
 (0)