diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index ad3b09e..fc209fc 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -6,47 +6,45 @@ on: pull_request: workflow_dispatch: +permissions: + contents: read + jobs: + get-changed-features: + runs-on: ubuntu-latest + outputs: + features: ${{ steps.filter.outputs.features }} + has-features: ${{ steps.filter.outputs.has-features }} + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: "Detect changed features" + id: filter + run: | + if [ "${{ github.event_name }}" == "pull_request" ]; then + git fetch origin ${{ github.base_ref }} + FEATURES=$(git diff --name-only origin/${{ github.base_ref }}...HEAD \ + | grep -E '^(src|test)/' \ + | sed -E 's#^(src|test)/([^/]+)/.*#\2#' \ + | sort -u \ + | jq -R -s -c 'split("\n") | map(select(length > 0))') + else + FEATURES=$(ls src/ | sort | jq -R -s -c 'split("\n") | map(select(length > 0))') + fi + echo "features=$FEATURES" >> $GITHUB_OUTPUT + echo "has-features=$(echo "$FEATURES" | jq '. | length > 0')" >> $GITHUB_OUTPUT + test-autogenerated: + needs: get-changed-features + if: needs.get-changed-features.outputs.has-features == 'true' runs-on: ubuntu-latest + timeout-minutes: 60 continue-on-error: true strategy: matrix: - features: - - asdf-vm.com - - astral.sh-uv - - atuin.sh - - aws-cli - - biomejs.dev - - btop - - bun.sh - - charmbracelet-gum - - chezmoi.io - - cloudflare.com-warp-cli - - deno.com - - dozzle.dev - - devenv.sh - - feature-installer - - helix-editor.com - - jj-vcs.dev - - mosh.org - - keybase.io - - neovim.io - - nixos.org - - nvidia.com-cuda - - opencode.ai - - pi.dev - - pkgx.sh - - pulumi.com - - rclone.org - - restic.net - - smallstep.com - - starship.rs - - swc.rs - - tailscale.com - - webinstall.dev - - zellij.dev - - zyedidia-eget + features: ${{ fromJson(needs.get-changed-features.outputs.features) }} baseImage: - debian:latest - ubuntu:latest @@ -61,44 +59,14 @@ jobs: run: devcontainer features test --skip-scenarios -f ${{ matrix.features }} -i ${{ matrix.baseImage }} . test-scenarios: + needs: get-changed-features + if: needs.get-changed-features.outputs.has-features == 'true' runs-on: ubuntu-latest + timeout-minutes: 60 continue-on-error: true strategy: matrix: - features: - - asdf-vm.com - - astral.sh-uv - - atuin.sh - - biomejs.dev - - btop - - bun.sh - - charmbracelet-gum - - chezmoi.io - - cloudflare.com-warp-cli - - deno.com - - dozzle.dev - - devenv.sh - - feature-installer - - helix-editor.com - - jj-vcs.dev - - mosh.org - - keybase.io - - neovim.io - - nixos.org - - nvidia.com-cuda - - opencode.ai - - pi.dev - - pkgx.sh - - pulumi.com - - rclone.org - - restic.net - - smallstep.com - - starship.rs - - swc.rs - - tailscale.com - - webinstall.dev - - zellij.dev - - zyedidia-eget + features: ${{ fromJson(needs.get-changed-features.outputs.features) }} steps: - uses: actions/checkout@v4 @@ -110,6 +78,7 @@ jobs: test-global: runs-on: ubuntu-latest + timeout-minutes: 60 continue-on-error: true steps: - uses: actions/checkout@v4 diff --git a/README.md b/README.md index 44e6d67..9aa09d7 100644 --- a/README.md +++ b/README.md @@ -7,3 +7,62 @@ [Code of Conduct](https://github.com/devcontainer-community/code-of-conduct) + +| Feature | Description | Install method | Version | +| ------- | ----------- | -------------- | ------- | +| [alexpasmantier-television](https://github.com/devcontainer-community/devcontainer-features/tree/main/src/alexpasmantier-television) | `tv` — fuzzy finder for files, text, and more | gh release | 1.0.0 | +| [asdf-vm.com](https://github.com/devcontainer-community/devcontainer-features/tree/main/src/asdf-vm.com) | `asdf` — multi-runtime version manager | gh release | 1.0.2 | +| [astral.sh/uv](https://github.com/devcontainer-community/devcontainer-features/tree/main/src/astral.sh-uv) | `uv`/`uvx` — fast Python package and project manager | gh release | 1.0.3 | +| [atuin.sh](https://github.com/devcontainer-community/devcontainer-features/tree/main/src/atuin.sh) | `atuin` — shell history sync and search | gh release | 1.0.2 | +| [AWS CLI](https://github.com/devcontainer-community/devcontainer-features/tree/main/src/aws-cli) | `aws` — official AWS command-line interface | curl | 1.1.2 | +| [basecamp-fizzy-cli](https://github.com/devcontainer-community/devcontainer-features/tree/main/src/basecamp-fizzy-cli) | `fizzy` — CLI for Basecamp | gh release | 1.0.0 | +| [bat](https://github.com/devcontainer-community/devcontainer-features/tree/main/src/bat) | `bat` — cat with syntax highlighting and git integration | gh release | 1.0.0 | +| [biomejs.dev](https://github.com/devcontainer-community/devcontainer-features/tree/main/src/biomejs.dev) | `biome` — fast JS/TS formatter and linter | gh release | 1.0.0 | +| [btop](https://github.com/devcontainer-community/devcontainer-features/tree/main/src/btop) | `btop` — resource monitor (CPU, memory, network, processes) | gh release | 1.0.2 | +| [bun.sh](https://github.com/devcontainer-community/devcontainer-features/tree/main/src/bun.sh) | `bun` — fast JS runtime and package manager | curl | 1.0.0 | +| [charmbracelet/gum](https://github.com/devcontainer-community/devcontainer-features/tree/main/src/charmbracelet-gum) | `gum` — building blocks for shell scripts | gh release | 1.0.3 | +| [chezmoi.io](https://github.com/devcontainer-community/devcontainer-features/tree/main/src/chezmoi.io) | `chezmoi` — dotfiles manager across machines | gh release | 1.0.1 | +| [cloudflare.com-warp-cli](https://github.com/devcontainer-community/devcontainer-features/tree/main/src/cloudflare.com-warp-cli) | `warp-cli` — Cloudflare WARP VPN client | curl | 1.0.0 | +| [critique.work](https://github.com/devcontainer-community/devcontainer-features/tree/main/src/critique.work) | `critique` — AI-powered code review | bun | 1.0.0 | +| [delta](https://github.com/devcontainer-community/devcontainer-features/tree/main/src/delta) | `delta` — syntax-highlighting pager for git diffs | gh release | 1.0.0 | +| [deno.com](https://github.com/devcontainer-community/devcontainer-features/tree/main/src/deno.com) | `deno` — secure TypeScript/JavaScript runtime | curl | 1.0.0 | +| [devenv.sh](https://github.com/devcontainer-community/devcontainer-features/tree/main/src/devenv.sh) | `devenv` — reproducible developer environments via Nix | nix | 1.0.0 | +| [diffity.com](https://github.com/devcontainer-community/devcontainer-features/tree/main/src/diffity.com) | `diffity` — agent-agnostic GitHub-style diff viewer and code review tool | npm | 1.0.0 | +| [dozzle.dev](https://github.com/devcontainer-community/devcontainer-features/tree/main/src/dozzle.dev) | `dozzle` — real-time Docker container log viewer | curl | 1.0.0 | +| [fd](https://github.com/devcontainer-community/devcontainer-features/tree/main/src/fd) | `fd` — fast and user-friendly file finder | gh release | 1.0.0 | +| [feature-installer](https://github.com/devcontainer-community/devcontainer-features/tree/main/src/feature-installer) | `feature-installer` — install devcontainer features at runtime | curl | 0.0.4 | +| [fzf](https://github.com/devcontainer-community/devcontainer-features/tree/main/src/fzf) | `fzf` — general-purpose command-line fuzzy finder | gh release | 1.0.0 | +| [github.com-cli](https://github.com/devcontainer-community/devcontainer-features/tree/main/src/github.com-cli) | `gh` — GitHub CLI | curl | 1.0.0 | +| [helix-editor.com](https://github.com/devcontainer-community/devcontainer-features/tree/main/src/helix-editor.com) | `hx` — modal text editor with built-in LSP | gh release | 1.0.0 | +| [icholy/ttygif](https://github.com/devcontainer-community/devcontainer-features/tree/main/src/icholy-ttygif) | `ttygif` — convert ttyrec recordings to animated GIFs | gh release | 1.0.0 | +| [jj-vcs.dev](https://github.com/devcontainer-community/devcontainer-features/tree/main/src/jj-vcs.dev) | `jj` — Git-compatible distributed VCS | gh release | 1.0.1 | +| [jnsahaj/lumen](https://github.com/devcontainer-community/devcontainer-features/tree/main/src/jnsahaj-lumen) | `lumen` — AI-powered commit message generator | cargo | 1.0.0 | +| [joelhooks-agent-secrets](https://github.com/devcontainer-community/devcontainer-features/tree/main/src/joelhooks-agent-secrets) | `secrets` — manage secrets for AI agents | gh release | 1.0.0 | +| [jq](https://github.com/devcontainer-community/devcontainer-features/tree/main/src/jq) | `jq` — command-line JSON processor | apt | 1.0.0 | +| [k9scli.io](https://github.com/devcontainer-community/devcontainer-features/tree/main/src/k9scli.io) | `k9s` — terminal UI for Kubernetes clusters | gh release | 1.0.0 | +| [keybase.io](https://github.com/devcontainer-community/devcontainer-features/tree/main/src/keybase.io) | `keybase` — cryptographic identity and encrypted file sharing | curl | 1.2.0 | +| [lazygit](https://github.com/devcontainer-community/devcontainer-features/tree/main/src/lazygit) | `lazygit` — terminal UI for git | gh release | 1.0.0 | +| [memvid.com](https://github.com/devcontainer-community/devcontainer-features/tree/main/src/memvid.com) | `memvid` — video-based memory for AI applications | npm | 1.0.0 | +| [mosh.org](https://github.com/devcontainer-community/devcontainer-features/tree/main/src/mosh.org) | `mosh` — SSH replacement with roaming support | apt | 1.0.0 | +| [neovim.io](https://github.com/devcontainer-community/devcontainer-features/tree/main/src/neovim.io) | `nvim` — hyperextensible Vim-based text editor | gh release | 1.0.0 | +| [nixos.org](https://github.com/devcontainer-community/devcontainer-features/tree/main/src/nixos.org) | `nix` — the Nix package manager | curl | 1.0.0 | +| [nvidia.com/cuda](https://github.com/devcontainer-community/devcontainer-features/tree/main/src/nvidia.com-cuda) | NVIDIA CUDA Toolkit for GPU computing | curl | 1.0.0 | +| [opencode.ai](https://github.com/devcontainer-community/devcontainer-features/tree/main/src/opencode.ai) | `opencode` — AI coding agent in the terminal | gh release | 1.0.3 | +| [pi.dev](https://github.com/devcontainer-community/devcontainer-features/tree/main/src/pi.dev) | `pi` — package manager for devcontainer features | gh release | 1.0.0 | +| [pkgx.sh](https://github.com/devcontainer-community/devcontainer-features/tree/main/src/pkgx.sh) | `pkgx` — run any package without installing | curl | 1.0.0 | +| [pulumi.com](https://github.com/devcontainer-community/devcontainer-features/tree/main/src/pulumi.com) | `pulumi` — infrastructure as code in any language | gh release | 1.0.0 | +| [rclone](https://github.com/devcontainer-community/devcontainer-features/tree/main/src/rclone.org) | `rclone` — sync files to/from cloud storage | gh release | 1.0.0 | +| [restic.net](https://github.com/devcontainer-community/devcontainer-features/tree/main/src/restic.net) | `restic` — fast, encrypted, deduplicated backups | gh release | 1.0.0 | +| [ripgrep](https://github.com/devcontainer-community/devcontainer-features/tree/main/src/ripgrep) | `rg` — fast grep alternative (ripgrep) | gh release | 1.0.0 | +| [schpet-linear-cli](https://github.com/devcontainer-community/devcontainer-features/tree/main/src/schpet-linear-cli) | `linear` — CLI to access linear.com issue tracker | gh release | 1.0.0 | +| [smallstep.com](https://github.com/devcontainer-community/devcontainer-features/tree/main/src/smallstep.com) | `step` — zero-trust security toolkit and CA | gh release | 1.0.1 | +| [sshd](https://github.com/devcontainer-community/devcontainer-features/tree/main/src/sshd) | `sshd` — OpenSSH server running inside the container | apt | 1.0.0 | +| [starship.rs](https://github.com/devcontainer-community/devcontainer-features/tree/main/src/starship.rs) | `starship` — minimal, fast cross-shell prompt | gh release | 1.0.1 | +| [swc.rs](https://github.com/devcontainer-community/devcontainer-features/tree/main/src/swc.rs) | `swc` — ultra-fast JS/TS compiler | gh release | 1.0.0 | +| [tailscale.com](https://github.com/devcontainer-community/devcontainer-features/tree/main/src/tailscale.com) | `tailscale` — zero-config mesh VPN | curl | 1.0.0 | +| [tmux](https://github.com/devcontainer-community/devcontainer-features/tree/main/src/tmux) | `tmux` — terminal multiplexer | source build | 1.0.0 | +| [webinstall.dev](https://github.com/devcontainer-community/devcontainer-features/tree/main/src/webinstall.dev) | `webi` — install packages without sudo | curl | 1.0.1 | +| [yakitrak/notesmd-cli](https://github.com/devcontainer-community/devcontainer-features/tree/main/src/yakitrak-notesmd-cli) | `notesmd-cli` — manage Obsidian vaults from the terminal | gh release | 1.0.0 | +| [yq](https://github.com/devcontainer-community/devcontainer-features/tree/main/src/yq) | `yq` — command-line YAML/JSON/XML processor | gh release | 1.0.0 | +| [zellij.dev](https://github.com/devcontainer-community/devcontainer-features/tree/main/src/zellij.dev) | `zellij` — terminal workspace with multiplexer and layouts | gh release | 1.0.1 | +| [zyedidia/eget](https://github.com/devcontainer-community/devcontainer-features/tree/main/src/zyedidia-eget) | `eget` — easily install prebuilt binaries from GitHub releases | gh release | 1.0.1 | diff --git a/src/tmux/NOTES.md b/src/tmux/NOTES.md new file mode 100644 index 0000000..6a57d7c --- /dev/null +++ b/src/tmux/NOTES.md @@ -0,0 +1,17 @@ +# tmux + +## Project + +- [tmux](https://github.com/tmux/tmux) + +## Description + +A terminal multiplexer. `tmux` lets you switch easily between several programs in one terminal, detach them (they keep running in the background), and reattach them to a different terminal. + +## Installation Method + +Built from source using the [GitHub releases page](https://github.com/tmux/tmux/releases) source tarball. Build dependencies (`build-essential`, `pkg-config`, `libevent-dev`, `libncurses-dev`, `bison`) are installed temporarily and cleaned up after the build. + +## Other Notes + +_No additional notes._ diff --git a/src/tmux/README.md b/src/tmux/README.md new file mode 100644 index 0000000..aef990e --- /dev/null +++ b/src/tmux/README.md @@ -0,0 +1,41 @@ + +# tmux (tmux) + +Install "tmux" terminal multiplexer + +## Example Usage + +```json +"features": { + "ghcr.io/devcontainer-community/devcontainer-features/tmux:1": {} +} +``` + +## Options + +| Options Id | Description | Type | Default Value | +|-----|-----|-----|-----| +| version | Version of "tmux" to install (e.g. "latest", "3.5a", "3.4"). | string | latest | + +# tmux + +## Project + +- [tmux](https://github.com/tmux/tmux) + +## Description + +A terminal multiplexer. `tmux` lets you switch easily between several programs in one terminal, detach them (they keep running in the background), and reattach them to a different terminal. + +## Installation Method + +Built from source using the [GitHub releases page](https://github.com/tmux/tmux/releases) source tarball. Build dependencies (`build-essential`, `pkg-config`, `libevent-dev`, `libncurses-dev`, `bison`) are installed temporarily and cleaned up after the build. + +## Other Notes + +_No additional notes._ + + +--- + +_Note: This file was auto-generated from the [devcontainer-feature.json](https://github.com/devcontainer-community/devcontainer-features/blob/main/src/tmux/devcontainer-feature.json). Add additional notes to a `NOTES.md`._ diff --git a/src/tmux/devcontainer-feature.json b/src/tmux/devcontainer-feature.json new file mode 100644 index 0000000..4edcb10 --- /dev/null +++ b/src/tmux/devcontainer-feature.json @@ -0,0 +1,17 @@ +{ + "name": "tmux", + "id": "tmux", + "version": "1.0.0", + "description": "Install \"tmux\" terminal multiplexer", + "documentationURL": "https://github.com/devcontainer-community/devcontainer-features/tree/main/src/tmux", + "options": { + "version": { + "type": "string", + "default": "latest", + "proposals": [ + "latest" + ], + "description": "Version of \"tmux\" to install (e.g. \"latest\", \"3.5a\", \"3.4\")." + } + } +} diff --git a/src/tmux/install.sh b/src/tmux/install.sh new file mode 100755 index 0000000..bd39ca7 --- /dev/null +++ b/src/tmux/install.sh @@ -0,0 +1,135 @@ +#!/bin/bash +set -o errexit +set -o pipefail +set -o noclobber +set -o nounset +set -o allexport +readonly githubRepository='tmux/tmux' +readonly binaryName='tmux' +readonly versionArgument='-V' +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_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 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" +} +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 " + 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 '^[0-9]+\.[0-9]+[a-z]?$' +} +github_get_latest_release() { + if [ -z "$1" ]; then + echo "Usage: get_latest_github_release " + return 1 + fi + github_list_releases "$1" | head -n 1 +} +github_get_tag_for_version() { + if [ -z "$1" ] || [ -z "$2" ]; then + echo "Usage: github_get_tag_for_version " + return 1 + fi + local repo="$1" + local version="$2" + local url="https://api.github.com/repos/$repo/releases" + local escaped_version + escaped_version="$(printf '%s' "$version" | sed 's/\./\\./g')" + curl -s "$url" | grep -Po '"tag_name": "\K.*?(?=")' | grep -E "^${escaped_version}$" | head -n 1 +} +utils_check_version() { + local version=$1 + if ! [[ "${version:-}" =~ ^(latest|[0-9]+\.[0-9]+[a-z]?)$ ]]; then + printf >&2 '=== [ERROR] Option "version" (value: "%s") is not "latest" or valid tmux version format "X.Y[a]" !\n' \ + "$version" + exit 1 + fi +} +install() { + utils_check_version "$VERSION" + check_curl_file_tar_installed + apt_get_checkinstall build-essential pkg-config libevent-dev libncurses-dev bison + if [ "$VERSION" == 'latest' ] || [ -z "$VERSION" ]; then + VERSION=$(github_get_latest_release "$githubRepository") + fi + readonly version="${VERSION:?}" + readonly releaseTag="$(github_get_tag_for_version "$githubRepository" "$version")" + if [ -z "$releaseTag" ]; then + printf >&2 '=== [ERROR] Could not find release tag for version "%s" in "%s"!\n' "$version" "$githubRepository" + exit 1 + fi + readonly downloadUrl="https://github.com/${githubRepository}/releases/download/${releaseTag}/${name}-${version}.tar.gz" + curl_check_url "$downloadUrl" + local tmpDir + tmpDir=$(mktemp -d) + curl_download_stdout "$downloadUrl" | tar -xz -f '-' -C "$tmpDir" --strip-components=1 + cd "$tmpDir" + ./configure --prefix=/usr/local + make install + cd / + rm -rf "$tmpDir" + apt_get_cleanup +} +echo_banner "devcontainer.community" +echo "Installing $name..." +install "$@" +echo "(*) Done!" diff --git a/test/tmux/test.sh b/test/tmux/test.sh new file mode 100644 index 0000000..b790219 --- /dev/null +++ b/test/tmux/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