diff --git a/.devcontainer/scripts/postCreate.sh b/.devcontainer/scripts/postCreate.sh index 4cec9c9..9508113 100755 --- a/.devcontainer/scripts/postCreate.sh +++ b/.devcontainer/scripts/postCreate.sh @@ -4,7 +4,7 @@ set -euo pipefail echo "🔧 Installing devcontainer CLI..." npm install -g @devcontainers/cli -FEATURES=("amazon-q-cli") +FEATURES=("amazon-q-cli" "zip") BASE_IMAGES=("debian:latest" "ubuntu:latest" "mcr.microsoft.com/devcontainers/base:ubuntu") # Run autogenerated tests for each image diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 2276743..25ae45f 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -14,6 +14,7 @@ jobs: matrix: features: - amazon-q-cli + - zip baseImage: - debian:latest - ubuntu:latest @@ -34,6 +35,7 @@ jobs: matrix: features: - amazon-q-cli + - zip steps: - uses: actions/checkout@v4 diff --git a/README.md b/README.md index 454f01c..bf48d8b 100644 --- a/README.md +++ b/README.md @@ -5,12 +5,25 @@ This repository contains following features: - [amazon-q-cli](./src/amazon-q-cli/README.md): Install Amazon Q CLI for AWS development +- [zip](./src/zip/README.md): Installs zip and unzip CLI tools for compression and extraction ## Usage To use the features from this repository, add the desired features to devcontainer.json. -This example uses amazon-q-cli feature on devcontainer: +These examples show how to use features from this repository in a devcontainer: + +```jsonc +{ + "image": "mcr.microsoft.com/devcontainers/base:ubuntu", + "features": { + "ghcr.io/jajera/features/amazon-q-cli:1": {}, + "ghcr.io/jajera/features/zip:1": {} + } +} +``` + +Or use individual features: ```jsonc { @@ -29,7 +42,15 @@ Similar to the [`devcontainers/features`](https://github.com/devcontainers/featu ├── src │ ├── amazon-q-cli │ │ ├── devcontainer-feature.json -│ │ └── install.sh +│ │ ├── install.sh +│ │ └── README.md +│ ├── zip +│ │ ├── devcontainer-feature.json +│ │ ├── install.sh +│ │ └── README.md +├── test +│ ├── amazon-q-cli +│ └── zip ... ``` diff --git a/src/zip/README.md b/src/zip/README.md new file mode 100644 index 0000000..98c531b --- /dev/null +++ b/src/zip/README.md @@ -0,0 +1,67 @@ +# Zip Utility (zip) + +Installs zip and unzip CLI tools for compression and extraction. + +## Example Usage + +```json +"features": { + "ghcr.io/jajera/features/zip:1": {} +} +``` + +## Options + +This feature has no configurable options. + +## Description + +This feature installs the `zip` and `unzip` command-line utilities for creating and extracting ZIP archives. The installation is compatible with multiple Linux distributions and package managers including: + +- **Debian/Ubuntu**: Uses `apt-get` +- **RHEL/CentOS/Fedora**: Uses `yum`/`dnf` +- **Alpine Linux**: Uses `apk` +- **Arch Linux**: Uses `pacman` +- **openSUSE**: Uses `zypper` + +## Features + +- ✅ Cross-platform support for major Linux distributions +- ✅ Automatic package manager detection +- ✅ Retry logic for package updates +- ✅ Privilege escalation handling (sudo when needed) +- ✅ Comprehensive error handling +- ✅ Installation verification + +## Usage Examples + +After installation, you can use the zip utilities: + +```bash +# Create a zip archive +zip archive.zip file1.txt file2.txt + +# Extract a zip archive +unzip archive.zip + +# View zip archive contents +unzip -l archive.zip + +# Create zip with compression +zip -9 archive.zip file.txt + +# Extract to specific directory +unzip archive.zip -d /target/directory +``` + +## Verification + +The feature automatically verifies successful installation by: + +- Checking if `zip` command is available +- Checking if `unzip` command is available +- Running version checks for both utilities + +--- + +_Note, this file was auto-generated from the [devcontainer-feature.json](https://github.com/jajera/features/blob/main/src/zip/devcontainer-feature.json). Add additional notes to a `NOTES.md`._ diff --git a/src/zip/devcontainer-feature.json b/src/zip/devcontainer-feature.json new file mode 100644 index 0000000..b81f1c8 --- /dev/null +++ b/src/zip/devcontainer-feature.json @@ -0,0 +1,7 @@ +{ + "name": "Zip Utility", + "id": "zip", + "version": "1.0.0", + "description": "Installs zip and unzip CLI tools for compression and extraction.", + "documentationURL": "https://linux.die.net/man/1/zip" +} diff --git a/src/zip/install.sh b/src/zip/install.sh new file mode 100755 index 0000000..19d7b37 --- /dev/null +++ b/src/zip/install.sh @@ -0,0 +1,119 @@ +#!/bin/sh +set -e + +echo "Activating feature 'zip'" + +# Detect OS and architecture +OS="$(uname -s)" +ARCH="$(uname -m)" + +echo "✅ Detected OS: $OS" +echo "✅ Detected ARCH: $ARCH" + +# Skip install if already present +if command -v zip >/dev/null 2>&1 && command -v unzip >/dev/null 2>&1; then + echo "✅ Zip utilities are already installed. Skipping install." + exit 0 +fi + +echo "Installing required dependencies..." + +# Function to run apt-get with appropriate privileges +run_apt() { + if [ "$(id -u)" -eq 0 ]; then + "$@" + elif command -v sudo >/dev/null 2>&1; then + sudo "$@" + else + echo "⚠️ Warning: Running as non-root user without sudo. Package installation may fail." + "$@" + fi +} + +# Retry apt-get update up to 3 times +try_apt_update() { + for i in 1 2 3; do + echo "Running apt-get update (attempt $i)..." + if run_apt apt-get update -y; then + return 0 + fi + echo "apt-get update failed, retrying in 2 seconds..." + sleep 2 + done + echo "ERROR: apt-get update failed after multiple attempts." + return 1 +} + +# Function to install packages based on the OS/package manager +install_zip_packages() { + if command -v apt-get >/dev/null 2>&1; then + # Debian/Ubuntu + echo "📦 Installing zip utilities via apt-get..." + if ! try_apt_update; then + echo "⚠️ Warning: Could not update package lists. Proceeding anyway..." + fi + run_apt apt-get install -y zip unzip + elif command -v yum >/dev/null 2>&1; then + # RHEL/CentOS/Fedora (older) + echo "📦 Installing zip utilities via yum..." + run_apt yum install -y zip unzip + elif command -v dnf >/dev/null 2>&1; then + # Fedora (newer) + echo "📦 Installing zip utilities via dnf..." + run_apt dnf install -y zip unzip + elif command -v apk >/dev/null 2>&1; then + # Alpine Linux + echo "📦 Installing zip utilities via apk..." + run_apt apk add --no-cache zip unzip + elif command -v pacman >/dev/null 2>&1; then + # Arch Linux + echo "📦 Installing zip utilities via pacman..." + run_apt pacman -S --noconfirm zip unzip + elif command -v zypper >/dev/null 2>&1; then + # openSUSE + echo "📦 Installing zip utilities via zypper..." + run_apt zypper install -y zip unzip + else + echo "❌ ERROR: No supported package manager found (apt-get, yum, dnf, apk, pacman, zypper)" + echo "Please install zip and unzip manually" + exit 1 + fi +} + +# Install zip utilities +if ! command -v zip >/dev/null 2>&1 || ! command -v unzip >/dev/null 2>&1; then + echo "Installing zip and unzip..." + if ! install_zip_packages; then + echo "⚠️ Warning: Could not install zip utilities via package manager. Checking if already available..." + if ! command -v zip >/dev/null 2>&1; then + echo "❌ ERROR: zip is required but not available" + exit 1 + fi + if ! command -v unzip >/dev/null 2>&1; then + echo "❌ ERROR: unzip is required but not available" + exit 1 + fi + fi +else + echo "✅ zip and unzip are already available" +fi + +# Verify installation +echo "🔍 Verifying installation..." +if command -v zip >/dev/null 2>&1; then + echo "✅ zip installed successfully." + zip --version | head -n 1 +else + echo "❌ ERROR: 'zip' command not found in PATH" + exit 1 +fi + +if command -v unzip >/dev/null 2>&1; then + echo "✅ unzip installed successfully." + unzip -v | head -n 1 +else + echo "❌ ERROR: 'unzip' command not found in PATH" + exit 1 +fi + +echo "✅ Zip utilities installation complete!" diff --git a/test/zip/test.sh b/test/zip/test.sh new file mode 100755 index 0000000..1fb430e --- /dev/null +++ b/test/zip/test.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +set -e + +# Import test library bundled with the devcontainer CLI +source dev-container-features-test-lib + +# Feature-specific tests +check "zip command exists" bash -c "command -v zip" +check "unzip command exists" bash -c "command -v unzip" + +# Test basic zip functionality +check "zip can create archive" bash -c "echo 'test content' > test.txt && zip test.zip test.txt && ls test.zip" +check "unzip can extract archive" bash -c "rm test.txt && unzip test.zip && cat test.txt | grep 'test content'" +check "zip version" bash -c "zip --version" +check "unzip version" bash -c "unzip -v" + +# Clean up +rm -f test.txt test.zip + +# Report results +reportResults