From a8abcd5e087a36178d306db9bf639188b13930e6 Mon Sep 17 00:00:00 2001 From: lalten Date: Fri, 3 Apr 2026 16:06:09 +0200 Subject: [PATCH 1/4] Add `prek` --- src/prek/README.md | 39 +++++++ src/prek/devcontainer-feature.json | 20 ++++ src/prek/install.sh | 49 +++++++++ src/prek/library_scripts.sh | 170 +++++++++++++++++++++++++++++ test/prek/scenarios.json | 8 ++ test/prek/test_defaults_debian.sh | 9 ++ 6 files changed, 295 insertions(+) create mode 100644 src/prek/README.md create mode 100644 src/prek/devcontainer-feature.json create mode 100755 src/prek/install.sh create mode 100644 src/prek/library_scripts.sh create mode 100644 test/prek/scenarios.json create mode 100755 test/prek/test_defaults_debian.sh diff --git a/src/prek/README.md b/src/prek/README.md new file mode 100644 index 00000000..9cc9bc69 --- /dev/null +++ b/src/prek/README.md @@ -0,0 +1,39 @@ + +# prek (via Github Releases) + +prek is a faster, dependency-free alternative to pre-commit, re-engineered in Rust. + +## Example Usage + +```json +"features": { + "ghcr.io/devcontainers-extra/features/prek:1": {} +} +``` + +## Options + +| Options Id | Description | Type | Default Value | +|-----|-----|-----|-----| +| version | Select the version to install. | string | latest | + +## About prek + +[prek](https://github.com/j178/prek) is a reimagined version of pre-commit, built in Rust. It is designed to be a faster, dependency-free and drop-in alternative, while also providing some additional long-requested features. + +### Key Features + +- A single binary with no dependencies, does not require Python or any other runtime +- Multiple times faster than `pre-commit` and takes up half the disk space +- Fully compatible with the original pre-commit configurations and hooks +- Built-in support for monorepos (workspace mode) +- Integration with uv for managing Python virtual environments and dependencies +- Built-in Rust-native implementation of some common hooks + +## Installation + +This feature installs prek from GitHub releases based on your system architecture (x86_64 or aarch64) and C library type (glibc or musl). + +--- + +_Note: This file was auto-generated from the [devcontainer-feature.json](devcontainer-feature.json)._ diff --git a/src/prek/devcontainer-feature.json b/src/prek/devcontainer-feature.json new file mode 100644 index 00000000..876381d0 --- /dev/null +++ b/src/prek/devcontainer-feature.json @@ -0,0 +1,20 @@ +{ + "id": "prek", + "version": "1.0.0", + "name": "prek (via Github Releases)", + "documentationURL": "http://github.com/devcontainers-extra/features/tree/main/src/prek", + "description": "prek is a faster, dependency-free alternative to pre-commit, re-engineered in Rust.", + "options": { + "version": { + "default": "latest", + "description": "Select the version to install.", + "proposals": [ + "latest" + ], + "type": "string" + } + }, + "installsAfter": [ + "ghcr.io/devcontainers-extra/features/gh-release" + ] +} diff --git a/src/prek/install.sh b/src/prek/install.sh new file mode 100755 index 00000000..5d4c435b --- /dev/null +++ b/src/prek/install.sh @@ -0,0 +1,49 @@ +#!/usr/bin/env bash + +set -e + +source ./library_scripts.sh + +# nanolayer is a cli utility which keeps container layers as small as possible +# source code: https://github.com/devcontainers-extra/nanolayer +# `ensure_nanolayer` is a bash function that will find any existing nanolayer installations, +# and if missing - will download a temporary copy that automatically get deleted at the end +# of the script +ensure_nanolayer nanolayer_location "v0.5.6" + +# Detect C library type (musl for Alpine, gnu for Debian/Ubuntu) +if [ -f "/lib/ld-musl-x86_64.so.1" ] || [ -f "/lib/ld-musl-aarch64.so.1" ]; then + clib_type=musl +else + clib_type=gnu +fi + +# Detect architecture +architecture="$(uname -m)" +case $architecture in + x86_64) + arch="x86_64" + ;; + aarch64) + arch="aarch64" + ;; + *) + echo "(!) Architecture ${architecture} is not supported" + exit 1 + ;; +esac + +# Build asset regex to match prek release binaries +# Example: prek-x86_64-unknown-linux-gnu.tar.gz +asset_regex="^prek-${arch}-unknown-linux-${clib_type}\\.tar\\.gz$" + +$nanolayer_location \ + install \ + devcontainer-feature \ + "ghcr.io/devcontainers-extra/features/gh-release:1.0.26" \ + --option repo='j178/prek' \ + --option binaryNames='prek' \ + --option version="$VERSION" \ + --option assetRegex="$asset_regex" + +echo 'Done!' diff --git a/src/prek/library_scripts.sh b/src/prek/library_scripts.sh new file mode 100644 index 00000000..d8354337 --- /dev/null +++ b/src/prek/library_scripts.sh @@ -0,0 +1,170 @@ + +clean_download() { + # The purpose of this function is to download a file with minimal impact on container layer size + # this means if no valid downloader is found (curl or wget) then we install a downloader (currently wget) in a + # temporary manner, and making sure to + # 1. uninstall the downloader at the return of the function + # 2. revert back any changes to the package installer database/cache (for example apt-get lists) + # The above steps will minimize the leftovers being created while installing the downloader + # Supported distros: + # debian/ubuntu/alpine + + url=$1 + output_location=$2 + tempdir=$(mktemp -d) + downloader_installed="" + + _apt_get_install() { + tempdir=$1 + + # copy current state of apt list - in order to revert back later (minimize contianer layer size) + cp -p -R /var/lib/apt/lists $tempdir + apt-get update -y + apt-get -y install --no-install-recommends wget ca-certificates + } + + _apt_get_cleanup() { + tempdir=$1 + + echo "removing wget" + apt-get -y purge wget --auto-remove + + echo "revert back apt lists" + rm -rf /var/lib/apt/lists/* + rm -r /var/lib/apt/lists && mv $tempdir/lists /var/lib/apt/lists + } + + _apk_install() { + tempdir=$1 + # copy current state of apk cache - in order to revert back later (minimize contianer layer size) + cp -p -R /var/cache/apk $tempdir + + apk add --no-cache wget + } + + _apk_cleanup() { + tempdir=$1 + + echo "removing wget" + apk del wget + } + # try to use either wget or curl if one of them already installer + if type curl >/dev/null 2>&1; then + downloader=curl + elif type wget >/dev/null 2>&1; then + downloader=wget + else + downloader="" + fi + + # in case none of them is installed, install wget temporarly + if [ -z $downloader ] ; then + if [ -x "/usr/bin/apt-get" ] ; then + _apt_get_install $tempdir + elif [ -x "/sbin/apk" ] ; then + _apk_install $tempdir + else + echo "distro not supported" + exit 1 + fi + downloader="wget" + downloader_installed="true" + fi + + if [ $downloader = "wget" ] ; then + wget -q $url -O $output_location + else + curl -sfL $url -o $output_location + fi + + # NOTE: the cleanup procedure was not implemented using `trap X RETURN` only because + # alpine lack bash, and RETURN is not a valid signal under sh shell + if ! [ -z $downloader_installed ] ; then + if [ -x "/usr/bin/apt-get" ] ; then + _apt_get_cleanup $tempdir + elif [ -x "/sbin/apk" ] ; then + _apk_cleanup $tempdir + else + echo "distro not supported" + exit 1 + fi + fi + +} + + +ensure_nanolayer() { + # Ensure existance of the nanolayer cli program + local variable_name=$1 + + local required_version=$2 + + local __nanolayer_location="" + + # If possible - try to use an already installed nanolayer + if [ -z "${NANOLAYER_FORCE_CLI_INSTALLATION}" ]; then + if [ -z "${NANOLAYER_CLI_LOCATION}" ]; then + if type nanolayer >/dev/null 2>&1; then + echo "Found a pre-existing nanolayer in PATH" + __nanolayer_location=nanolayer + fi + elif [ -f "${NANOLAYER_CLI_LOCATION}" ] && [ -x "${NANOLAYER_CLI_LOCATION}" ] ; then + __nanolayer_location=${NANOLAYER_CLI_LOCATION} + echo "Found a pre-existing nanolayer which were given in env variable: $__nanolayer_location" + fi + + # make sure its of the required version + if ! [ -z "${__nanolayer_location}" ]; then + local current_version + current_version=$($__nanolayer_location --version) + + + if ! [ $current_version == $required_version ]; then + echo "skipping usage of pre-existing nanolayer. (required version $required_version does not match existing version $current_version)" + __nanolayer_location="" + fi + fi + + fi + + # If not previuse installation found, download it temporarly and delete at the end of the script + if [ -z "${__nanolayer_location}" ]; then + + if [ "$(uname -sm)" = 'Linux x86_64' ] || [ "$(uname -sm)" = "Linux aarch64" ]; then + tmp_dir=$(mktemp -d -t nanolayer-XXXXXXXXXX) + + clean_up () { + ARG=$? + rm -rf $tmp_dir + exit $ARG + } + trap clean_up EXIT + + + if [ -x "/sbin/apk" ] ; then + clib_type=musl + else + clib_type=gnu + fi + + tar_filename=nanolayer-"$(uname -m)"-unknown-linux-$clib_type.tgz + + # clean download will minimize leftover in case a downloaderlike wget or curl need to be installed + clean_download https://github.com/devcontainers-extra/nanolayer/releases/download/$required_version/$tar_filename $tmp_dir/$tar_filename + + tar xfzv $tmp_dir/$tar_filename -C "$tmp_dir" + chmod a+x $tmp_dir/nanolayer + __nanolayer_location=$tmp_dir/nanolayer + + + else + echo "No binaries compiled for non-x86-linux architectures yet: $(uname -m)" + exit 1 + fi + fi + + # Expose outside the resolved location + export ${variable_name}=$__nanolayer_location + +} + diff --git a/test/prek/scenarios.json b/test/prek/scenarios.json new file mode 100644 index 00000000..d7d1daef --- /dev/null +++ b/test/prek/scenarios.json @@ -0,0 +1,8 @@ +{ + "test_defaults_debian": { + "image": "mcr.microsoft.com/devcontainers/base:debian", + "features": { + "prek": {} + } + } +} diff --git a/test/prek/test_defaults_debian.sh b/test/prek/test_defaults_debian.sh new file mode 100755 index 00000000..2f7b21a3 --- /dev/null +++ b/test/prek/test_defaults_debian.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +set -e + +source dev-container-features-test-lib + +check "prek --version" prek --version + +reportResults From 2a2d3a55ea281059e4a2a2287ef3fbb9e6a91e58 Mon Sep 17 00:00:00 2001 From: lalten Date: Fri, 3 Apr 2026 16:22:14 +0200 Subject: [PATCH 2/4] Remove leading newlines from prek files --- src/prek/README.md | 1 - src/prek/library_scripts.sh | 1 - 2 files changed, 2 deletions(-) diff --git a/src/prek/README.md b/src/prek/README.md index 9cc9bc69..5d9d6127 100644 --- a/src/prek/README.md +++ b/src/prek/README.md @@ -1,4 +1,3 @@ - # prek (via Github Releases) prek is a faster, dependency-free alternative to pre-commit, re-engineered in Rust. diff --git a/src/prek/library_scripts.sh b/src/prek/library_scripts.sh index d8354337..08abda9c 100644 --- a/src/prek/library_scripts.sh +++ b/src/prek/library_scripts.sh @@ -1,4 +1,3 @@ - clean_download() { # The purpose of this function is to download a file with minimal impact on container layer size # this means if no valid downloader is found (curl or wget) then we install a downloader (currently wget) in a From 18e4df83fad0c3c483ce3772acf5709e740619e0 Mon Sep 17 00:00:00 2001 From: lalten Date: Sat, 4 Apr 2026 01:46:14 +0200 Subject: [PATCH 3/4] add specific version test --- test/prek/scenarios.json | 8 ++++++++ test/prek/test_specific_version.sh | 9 +++++++++ 2 files changed, 17 insertions(+) create mode 100755 test/prek/test_specific_version.sh diff --git a/test/prek/scenarios.json b/test/prek/scenarios.json index d7d1daef..ce24f007 100644 --- a/test/prek/scenarios.json +++ b/test/prek/scenarios.json @@ -4,5 +4,13 @@ "features": { "prek": {} } + }, + "test_specific_version": { + "image": "mcr.microsoft.com/devcontainers/base:debian", + "features": { + "prek": { + "version": "0.3.7" + } + } } } diff --git a/test/prek/test_specific_version.sh b/test/prek/test_specific_version.sh new file mode 100755 index 00000000..69bf613d --- /dev/null +++ b/test/prek/test_specific_version.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +set -e + +source dev-container-features-test-lib + +check "prek version is equal to 0.3.7" sh -c "prek --version | grep '0.3.7'" + +reportResults From 061fa63f4e5ff58df1e4388a98109aff46c03df9 Mon Sep 17 00:00:00 2001 From: Laurenz Date: Sat, 4 Apr 2026 10:26:33 +0200 Subject: [PATCH 4/4] test with `0.3.6` --- test/prek/scenarios.json | 2 +- test/prek/test_specific_version.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/prek/scenarios.json b/test/prek/scenarios.json index ce24f007..995efe31 100644 --- a/test/prek/scenarios.json +++ b/test/prek/scenarios.json @@ -9,7 +9,7 @@ "image": "mcr.microsoft.com/devcontainers/base:debian", "features": { "prek": { - "version": "0.3.7" + "version": "0.3.6" } } } diff --git a/test/prek/test_specific_version.sh b/test/prek/test_specific_version.sh index 69bf613d..6fefebb5 100755 --- a/test/prek/test_specific_version.sh +++ b/test/prek/test_specific_version.sh @@ -4,6 +4,6 @@ set -e source dev-container-features-test-lib -check "prek version is equal to 0.3.7" sh -c "prek --version | grep '0.3.7'" +check "prek version is equal to 0.3.6" sh -c "prek --version | grep '0.3.6'" reportResults