From 1365c490412f3d0c8d1576af169306793591cd02 Mon Sep 17 00:00:00 2001
From: Sebastian Steins <592313+sebst@users.noreply.github.com>
Date: Sat, 12 Oct 2024 21:19:52 +0200
Subject: [PATCH 1/2] feat(`zellij.dev`): Add feature.

---
 src/zellij.dev/devcontainer-feature.json |  17 +++
 src/zellij.dev/install.sh                | 143 +++++++++++++++++++++++
 test/zellij.dev/test.sh                  |  18 +++
 3 files changed, 178 insertions(+)
 create mode 100644 src/zellij.dev/devcontainer-feature.json
 create mode 100755 src/zellij.dev/install.sh
 create mode 100755 test/zellij.dev/test.sh

diff --git a/src/zellij.dev/devcontainer-feature.json b/src/zellij.dev/devcontainer-feature.json
new file mode 100644
index 0000000..62035a8
--- /dev/null
+++ b/src/zellij.dev/devcontainer-feature.json
@@ -0,0 +1,17 @@
+{
+    "name": "zellij.dev",
+    "id": "zellij.dev",
+    "version": "1.0.0",
+    "description": "Install \"zellij\" binary",
+    "documentationURL": "https://github.com/devcontainer-community/devcontainer-features/tree/main/src/zellij.dev",
+    "options": {
+        "version": {
+            "type": "string",
+            "default": "latest",
+            "proposals": [
+                "latest"
+            ],
+            "description": "Version of \"zellij\" to install."
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/zellij.dev/install.sh b/src/zellij.dev/install.sh
new file mode 100755
index 0000000..2d44771
--- /dev/null
+++ b/src/zellij.dev/install.sh
@@ -0,0 +1,143 @@
+#!/bin/bash
+set -o errexit
+set -o pipefail
+set -o noclobber
+set -o nounset
+set -o allexport
+readonly githubRepository='zellij-org/zellij'
+readonly binaryName='zellij'
+readonly versionArgument='--version'
+readonly downloadUrlTemplate='https://github.com/${githubRepository}/releases/download/v${version}/${name}-${architecture}-unknown-linux-musl.tar.gz'
+readonly binaryTargetFolder='/usr/local/bin'
+readonly name="${githubRepository##*/}"
+apt_get_update() {
+    if [ "$(find /var/lib/apt/lists/* | wc -l)" = "0" ]; then
+        echo "Running apt-get update..."
+        apt-get update -y
+    fi
+}
+apt_get_checkinstall() {
+    if ! dpkg -s "$@" >/dev/null 2>&1; then
+        apt_get_update
+        DEBIAN_FRONTEND=noninteractive apt-get -y install --no-install-recommends --no-install-suggests --option 'Debug::pkgProblemResolver=true' --option 'Debug::pkgAcquire::Worker=1' "$@"
+    fi
+}
+apt_get_cleanup() {
+    apt-get clean
+    rm -rf /var/lib/apt/lists/*
+}
+check_curl_envsubst_file_tar_installed() {
+    declare -a requiredAptPackagesMissing=()
+    if ! [ -r '/etc/ssl/certs/ca-certificates.crt' ]; then
+        requiredAptPackagesMissing+=('ca-certificates')
+    fi
+    if ! command -v curl >/dev/null 2>&1; then
+        requiredAptPackagesMissing+=('curl')
+    fi
+    if ! command -v envsubst >/dev/null 2>&1; then
+        requiredAptPackagesMissing+=('gettext-base')
+    fi
+    if ! command -v file >/dev/null 2>&1; then
+        requiredAptPackagesMissing+=('file')
+    fi
+    if ! command -v tar >/dev/null 2>&1; then
+        requiredAptPackagesMissing+=('tar')
+    fi
+    declare -i requiredAptPackagesMissingCount=${#requiredAptPackagesMissing[@]}
+    if [ $requiredAptPackagesMissingCount -gt 0 ]; then
+        apt_get_update
+        apt_get_checkinstall "${requiredAptPackagesMissing[@]}"
+        apt_get_cleanup
+    fi
+}
+curl_check_url() {
+    local url=$1
+    local status_code
+    status_code=$(curl -s -o /dev/null -w '%{http_code}' "$url")
+    if [ "$status_code" -ne 200 ] && [ "$status_code" -ne 302 ]; then
+        echo "Failed to download '$url'. Status code: $status_code."
+        return 1
+    fi
+}
+curl_download_stdout() {
+    local url=$1
+    curl \
+        --silent \
+        --location \
+        --output '-' \
+        --connect-timeout 5 \
+        "$url"
+}
+curl_download_untar() {
+    local url=$1
+    local strip=$2
+    local target=$3
+    local bin_path=$4
+    curl_download_stdout "$url" | tar \
+        -xz \
+        -f '-' \
+        --strip-components="$strip" \
+        -C "$target" \
+        "$bin_path"
+}
+debian_get_arch() {
+    echo "$(dpkg --print-architecture)"
+}
+debian_get_target_arch() {
+    case $(debian_get_arch) in
+    amd64) echo 'x86_64' ;;
+    arm64) echo 'aarch64' ;;
+    armhf) echo 'armv7' ;;
+    i386) echo 'i686' ;;
+    *) echo 'unknown' ;;
+    esac
+}
+echo_banner() {
+    local text="$1"
+    echo -e "\e[1m\e[97m\e[41m$text\e[0m"
+}
+github_list_releases() {
+    if [ -z "$1" ]; then
+        echo "Usage: list_github_releases <owner/repo>"
+        return 1
+    fi
+    local repo="$1"
+    local url="https://api.github.com/repos/$repo/releases"
+    curl -s "$url" | grep -Po '"tag_name": "\K.*?(?=")' | grep -E '^v?[0-9]+\.[0-9]+\.[0-9]+$' | sed 's/^v//'
+}
+github_get_latest_release() {
+    if [ -z "$1" ]; then
+        echo "Usage: get_latest_github_release <owner/repo>"
+        return 1
+    fi
+    github_list_releases "$1" | head -n 1
+}
+utils_check_version() {
+    local version=$1
+    if ! [[ "${version:-}" =~ ^(latest|[0-9]+\.[0-9]+\.[0-9]+)$ ]]; then
+        printf >&2 '=== [ERROR] Option "version" (value: "%s") is not "latest" or valid semantic version format "X.Y.Z" !\n' \
+            "$version"
+        exit 1
+    fi
+}
+install() {
+    utils_check_version "$VERSION"
+    check_curl_envsubst_file_tar_installed
+    readonly architecture="$(debian_get_target_arch)"
+    readonly binaryTargetPathTemplate='${binaryTargetFolder}/${binaryName}'
+    if [ "$VERSION" == 'latest' ] || [ -z "$VERSION" ]; then
+        VERSION=$(github_get_latest_release "$githubRepository")
+    fi
+    readonly version="${VERSION:?}"
+    readonly downloadUrl="$(echo -n "$downloadUrlTemplate" | envsubst)"
+    curl_check_url "$downloadUrl"
+    readonly binaryPathInArchive="$binaryName"
+    readonly stripComponents="$(echo -n "$binaryPathInArchive" | awk -F'/' '{print NF-1}')"
+    readonly binaryTargetPath="$(echo -n "$binaryTargetPathTemplate" | envsubst)"
+    curl_download_untar "$downloadUrl" "$stripComponents" "$binaryTargetFolder" "$binaryPathInArchive"
+    chmod 755 "$binaryTargetPath"
+}
+echo_banner "devcontainer.community"
+echo "Installing $name..."
+install "$@"
+echo "(*) Done!"
diff --git a/test/zellij.dev/test.sh b/test/zellij.dev/test.sh
new file mode 100755
index 0000000..2466041
--- /dev/null
+++ b/test/zellij.dev/test.sh
@@ -0,0 +1,18 @@
+#!/bin/bash
+
+
+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.
+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 "execute command" bash -c "zellij --version | grep 'zellij'"
+
+# Report results
+# If any of the checks above exited with a non-zero exit code, the test will fail.
+reportResults 
\ No newline at end of file

From 2d8017f0f9d6435bf4178f5eef81c0952cc02c3f Mon Sep 17 00:00:00 2001
From: Sebastian Steins <592313+sebst@users.noreply.github.com>
Date: Sat, 12 Oct 2024 21:21:00 +0200
Subject: [PATCH 2/2] feat(`zellij.dev`): Add test.

---
 .github/workflows/test.yaml | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml
index b3fb566..f9a5058 100644
--- a/.github/workflows/test.yaml
+++ b/.github/workflows/test.yaml
@@ -19,6 +19,7 @@ jobs:
           - pkgx.sh
           - smallstep.com
           - starship.rs
+          - zellij.dev
         baseImage:
           - debian:latest
           - ubuntu:latest
@@ -44,6 +45,7 @@ jobs:
           - pkgx.sh
           - smallstep.com
           - starship.rs
+          - zellij.dev
     steps:
       - uses: actions/checkout@v4