From efad3b5ea01436492a4e95165e47c56bd26aa9ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20Canouil?= <8896044+mcanouil@users.noreply.github.com> Date: Wed, 5 Nov 2025 21:57:11 +0100 Subject: [PATCH] feat: add cleanup feature for user caches and temporary files --- .../cleanup/devcontainer-feature.json | 16 +++++ .github/.devcontainer/cleanup/install.sh | 68 +++++++++++++++++++ .github/.devcontainer/devcontainer.json | 45 ++++++++---- 3 files changed, 114 insertions(+), 15 deletions(-) create mode 100644 .github/.devcontainer/cleanup/devcontainer-feature.json create mode 100644 .github/.devcontainer/cleanup/install.sh diff --git a/.github/.devcontainer/cleanup/devcontainer-feature.json b/.github/.devcontainer/cleanup/devcontainer-feature.json new file mode 100644 index 0000000..a34bc76 --- /dev/null +++ b/.github/.devcontainer/cleanup/devcontainer-feature.json @@ -0,0 +1,16 @@ +{ + "id": "cleanup", + "version": "1.0.0", + "name": "Cleanup", + "description": "Remove user caches and temporary files (for example ~/.cache/R). Intended to run last.", + "installsAfter": [ + "ghcr.io/devcontainers/features/common-utils", + "./quarto-computing-dependencies", + "./uv", + "./chrome", + "./decktape", + "./tinytex", + "ghcr.io/rocker-org/devcontainer-features/quarto-cli", + "ghcr.io/devcontainers/features/github-cli" + ] +} diff --git a/.github/.devcontainer/cleanup/install.sh b/.github/.devcontainer/cleanup/install.sh new file mode 100644 index 0000000..a99d6dd --- /dev/null +++ b/.github/.devcontainer/cleanup/install.sh @@ -0,0 +1,68 @@ +#!/usr/bin/env bash + +set -euo pipefail + +USERNAME=${USERNAME:-${_REMOTE_USER:-"automatic"}} + +# Resolve username +if [ "${USERNAME}" = "auto" ] || [ "${USERNAME}" = "automatic" ]; then + USERNAME="" + POSSIBLE_USERS=("vscode" "node" "codespace" "$(awk -v val=1000 -F":" '$3==val{print $1}' /etc/passwd)") + for CURRENT_USER in "${POSSIBLE_USERS[@]}"; do + if id -u "${CURRENT_USER}" >/dev/null 2>&1; then + USERNAME=${CURRENT_USER} + break + fi + done + if [ "${USERNAME}" = "" ]; then + USERNAME=root + fi +elif ! id -u "${USERNAME}" >/dev/null 2>&1; then + USERNAME=root +fi + +echo "[cleanup] Running cleanup feature as user: ${USERNAME}" + +# Determine home directory for the target user +if [ "${USERNAME}" = "root" ]; then + USER_HOME="/root" +else + USER_HOME=$(eval echo "~${USERNAME}") +fi + +echo "[cleanup] Target home: ${USER_HOME}" + +cleanup_paths=( + "${USER_HOME}/.cache" + "${USER_HOME}/.local/share/Trash" + "${USER_HOME}/tmp" + "${USER_HOME}/.npm/_cacache" +) + +for path in "${cleanup_paths[@]}"; do + if [ -e "${path}" ]; then + echo "[cleanup] Removing: ${path}" + rm -rf "${path}" || true + else + echo "[cleanup] Not found: ${path}" + fi +done + +echo "[cleanup] Cleaning system temporary files" +if [ -d "/tmp" ]; then + echo "[cleanup] Removing: /tmp/*" + rm -rf /tmp/* || true +fi + +echo "[cleanup] Cleaning package manager caches" +if command -v apt-get >/dev/null 2>&1; then + echo "[cleanup] Running: apt-get clean" + apt-get clean || true + + if [ -d "/var/lib/apt/lists" ]; then + echo "[cleanup] Removing: /var/lib/apt/lists/*" + rm -rf /var/lib/apt/lists/* || true + fi +fi + +echo "[cleanup] Done." diff --git a/.github/.devcontainer/devcontainer.json b/.github/.devcontainer/devcontainer.json index b6cda0e..caefbfc 100644 --- a/.github/.devcontainer/devcontainer.json +++ b/.github/.devcontainer/devcontainer.json @@ -7,20 +7,34 @@ "IMAGE": "${localEnv:IMAGE}" }, "options": [ - "--label", "org.opencontainers.image.title=${localEnv:ANNOTATION_TITLE}", - "--annotation", "org.opencontainers.image.title=${localEnv:ANNOTATION_TITLE}", - "--label", "org.opencontainers.image.description=${localEnv:ANNOTATION_DESCRIPTION}", - "--annotation", "org.opencontainers.image.description=${localEnv:ANNOTATION_DESCRIPTION}", - "--label", "org.opencontainers.image.authors=${localEnv:ANNOTATION_AUTHORS}", - "--annotation", "org.opencontainers.image.authors=${localEnv:ANNOTATION_AUTHORS}", - "--label", "org.opencontainers.image.url=${localEnv:ANNOTATION_URL}", - "--annotation", "org.opencontainers.image.url=${localEnv:ANNOTATION_URL}", - "--label", "org.opencontainers.image.source=${localEnv:ANNOTATION_URL}", - "--annotation", "org.opencontainers.image.source=${localEnv:ANNOTATION_URL}", - "--label", "org.opencontainers.image.version=${localEnv:ANNOTATION_VERSION}", - "--annotation", "org.opencontainers.image.version=${localEnv:ANNOTATION_VERSION}", - "--label", "org.opencontainers.image.licenses=${localEnv:ANNOTATION_LICENSE}", - "--annotation", "org.opencontainers.image.licenses=${localEnv:ANNOTATION_LICENSE}" + "--label", + "org.opencontainers.image.title=${localEnv:ANNOTATION_TITLE}", + "--annotation", + "org.opencontainers.image.title=${localEnv:ANNOTATION_TITLE}", + "--label", + "org.opencontainers.image.description=${localEnv:ANNOTATION_DESCRIPTION}", + "--annotation", + "org.opencontainers.image.description=${localEnv:ANNOTATION_DESCRIPTION}", + "--label", + "org.opencontainers.image.authors=${localEnv:ANNOTATION_AUTHORS}", + "--annotation", + "org.opencontainers.image.authors=${localEnv:ANNOTATION_AUTHORS}", + "--label", + "org.opencontainers.image.url=${localEnv:ANNOTATION_URL}", + "--annotation", + "org.opencontainers.image.url=${localEnv:ANNOTATION_URL}", + "--label", + "org.opencontainers.image.source=${localEnv:ANNOTATION_URL}", + "--annotation", + "org.opencontainers.image.source=${localEnv:ANNOTATION_URL}", + "--label", + "org.opencontainers.image.version=${localEnv:ANNOTATION_VERSION}", + "--annotation", + "org.opencontainers.image.version=${localEnv:ANNOTATION_VERSION}", + "--label", + "org.opencontainers.image.licenses=${localEnv:ANNOTATION_LICENSE}", + "--annotation", + "org.opencontainers.image.licenses=${localEnv:ANNOTATION_LICENSE}" ] }, "remoteUser": "${localEnv:USER}", @@ -55,6 +69,7 @@ "installTinyTex": "false", "installChromium": "false" }, - "ghcr.io/devcontainers/features/github-cli:1": {} + "ghcr.io/devcontainers/features/github-cli:1": {}, + "./cleanup": {} } }