diff --git a/src/aider/CHANGELOG.md b/src/aider/CHANGELOG.md new file mode 100644 index 0000000..522060c --- /dev/null +++ b/src/aider/CHANGELOG.md @@ -0,0 +1,21 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +### Added + +- Support for installing dependencies like Playwright and browser dependencies to enable Aider's web scraping functionality. +- Logic to clean up caches and other temporary files after installation to optimize performance and reduce disk usage. + +## [1.0.0] - 2024-12-18 + +### Added + +- Initial implementation of Aider devcontainer feature with support for Debian and Ubuntu. + +[Unreleased]: https://github.com/ivy/devcontainer-features/commits/main/src/aider +[1.0.0]: https://github.com/ivy/devcontainer-features/commits/main/src/aider?since=2024-12-18&until=2024-12-19 diff --git a/src/aider/devcontainer-feature.json b/src/aider/devcontainer-feature.json index 389eef6..aafd45c 100644 --- a/src/aider/devcontainer-feature.json +++ b/src/aider/devcontainer-feature.json @@ -14,6 +14,28 @@ "0.69.1" ], "description": "Select an Aider version to install." + }, + "installPlaywright": { + "type": "boolean", + "default": true, + "description": "Install Playwright for the best web scraping." + }, + "installPlaywrightBrowsers": { + "type": "string", + "default": "chromium", + "proposals": [ + "chromium", + "chromium-headless-shell", + "chrome", + "chrome-beta", + "msedge", + "msedge-beta", + "msedge-dev", + "bidi-chromium", + "firefox", + "webkit" + ], + "description": "Select the browsers to install for Playwright (comma-delimit for multiple)." } }, "dependsOn": { diff --git a/src/aider/install.sh b/src/aider/install.sh index 55c8362..48a2625 100644 --- a/src/aider/install.sh +++ b/src/aider/install.sh @@ -14,9 +14,35 @@ set -o pipefail # Version of Aider to install. AIDER_VERSION="${VERSION:-latest}" +# Whether to install Playwright for web scraping. +INSTALLPLAYWRIGHT="${INSTALLPLAYWRIGHT:-true}" + +# Browsers to install for Playwright. +INSTALLPLAYWRIGHTBROWSERS="${INSTALLPLAYWRIGHTBROWSERS:-chromium}" + # Username to install Aider for. USERNAME="${USERNAME:-"${_REMOTE_USER:-automatic}"}" +# Detect the Linux distribution ID. Adjust to account for derivatives. +detect_adjusted_id() { + if [ ! -r /etc/os-release ]; then + echo "WARN: Unable to detect the OS release." >&2 + return + fi + + # shellcheck disable=SC1091 + source /etc/os-release + + case "${ID:-unknown}" in + debian|ubuntu) + ADJUSTED_ID=debian + ;; + *) + ADJUSTED_ID="${ID:-unknown}" + ;; + esac +} + # Detect the username to use for the installation. This code is adapted from the # official devcontainer Python feature. detect_username() { @@ -49,6 +75,55 @@ detect_username() { fi } +as_user() { + # HACK(ivy): PS1=true works around an edge case where pipx isn't added + # to the PATH. This happens with the `mcr.microsoft.com/devcontainers/base:ubuntu` + # image which includes a check at the top of /etc/bash.bashrc which + # returns in non-interactive shells. + if [ "$USERNAME" = root ]; then + bash -c "PS1=true; . /etc/bash.bashrc || true; $1" + else + su - "$USERNAME" bash -c "PS1=true; . /etc/bash.bashrc || true; $1" + fi +} + +# Install Aider using pipx. +install_aider() { + if [ "$AIDER_VERSION" = latest ]; then + as_user 'pipx install aider-chat' + else + as_user "pipx install aider-chat==${AIDER_VERSION}" + fi +} + +install_playwright() { + local browsers + + if [ "$INSTALLPLAYWRIGHT" != true ]; then + return + fi + + as_user 'pipx inject --include-apps --include-deps aider-chat playwright' + + if [ -n "$INSTALLPLAYWRIGHTBROWSERS" ]; then + # Split $INSTALLPLAYWRIGHTBROWSERS by comma into an array and bind it to $browsers. + IFS=, read -r -a browsers <<< "$INSTALLPLAYWRIGHTBROWSERS" + + echo "Installing Playwright browsers: $INSTALLPLAYWRIGHTBROWSERS..." + as_user "playwright install --with-deps ${browsers[*]}" + fi +} + +# Clean up caches and temporary files. +clean_up() { + # Clean up pipx cache. + as_user 'pipx runpip aider-chat cache purge' + + if [ "$ADJUSTED_ID" = debian ]; then + rm -fr /var/lib/apt/lists/* + fi +} + # Main entrypoint main() { if [ "$(id -u)" -ne 0 ]; then @@ -56,22 +131,11 @@ main() { exit 1 fi + detect_adjusted_id detect_username - if [ "$AIDER_VERSION" = latest ]; then - echo "Installing latest Aider..." - # NOTE(ivy): PS1=true works around an edge case where pipx isn't added - # to the PATH. This happens with the `mcr.microsoft.com/devcontainers/base:ubuntu` - # image which includes a check at the top of /etc/bash.bashrc which - # returns in non-interactive shells. - su - "$USERNAME" bash -c "PS1=true; . /etc/bash.bashrc || true; pipx install aider-chat" - else - echo "Installing Aider version $AIDER_VERSION..." - # NOTE(ivy): PS1=true works around an edge case where pipx isn't added - # to the PATH. This happens with the `mcr.microsoft.com/devcontainers/base:ubuntu` - # image which includes a check at the top of /etc/bash.bashrc which - # returns in non-interactive shells. - su - "$USERNAME" bash -c "PS1=true; . /etc/bash.bashrc || true; pipx install aider-chat==${AIDER_VERSION}" - fi + install_aider + install_playwright + clean_up echo "Aider has been installed!" } diff --git a/test/aider/scenarios.json b/test/aider/scenarios.json index 4883b76..021abbf 100644 --- a/test/aider/scenarios.json +++ b/test/aider/scenarios.json @@ -16,5 +16,21 @@ "version": "0.69.0" } } + }, + "without_playwright": { + "image": "mcr.microsoft.com/devcontainers/base:debian", + "features": { + "aider": { + "installPlaywright": false + } + } + }, + "with_playwright_browsers": { + "image": "mcr.microsoft.com/devcontainers/base:debian", + "features": { + "aider": { + "installPlaywrightBrowsers": "chromium,firefox" + } + } } } diff --git a/test/aider/test.sh b/test/aider/test.sh index 35fec20..2dee510 100644 --- a/test/aider/test.sh +++ b/test/aider/test.sh @@ -42,6 +42,7 @@ source dev-container-features-test-lib # The 'check' command comes from the dev-container-features-test-lib. Syntax is... # check