Add initial DevContainer setup and configuration files (#1)
- Create .devcontainer/devcontainer.json for container environment setup - Add postStartCommand.sh for provisioning system dependencies and configuration - Include .gitignore to exclude task-related files - Create .taskrc.yml to enable experimental features - Add Taskfile.yml for task management and configuration - Set up VSCode settings for integrated terminal using zsh Co-authored-by: Thomas <thomas.hochstrasser@gmx.net> Reviewed-on: #1
This commit was merged in pull request #1.
This commit is contained in:
51
.devcontainer/devcontainer.json
Normal file
51
.devcontainer/devcontainer.json
Normal file
@@ -0,0 +1,51 @@
|
||||
{
|
||||
"image": "ubuntu:24.04",
|
||||
"containerEnv": {
|
||||
"CONAN_USR": "", // need to be filled
|
||||
"CONAN_PSW": "" // need to be filled,
|
||||
},
|
||||
"features": {
|
||||
"ghcr.io/devcontainers/features/git:1": {},
|
||||
"ghcr.io/devcontainers/features/git-lfs:1": {},
|
||||
"ghcr.io/devcontainers/features/python:1": {
|
||||
"toolsToInstall": "flake8,autopep8,black,yapf,mypy,pydocstyle,pycodestyle,bandit,pipenv,virtualenv,pytest,pylint,uv,copier,conan"
|
||||
}
|
||||
},
|
||||
"customizations": {
|
||||
"vscode": {
|
||||
"settings": {
|
||||
"git.path": "/usr/bin/git"
|
||||
},
|
||||
"extensions": [
|
||||
"ms-python.python",
|
||||
"ms-python.vscode-pylance",
|
||||
"GitHub.copilot-chat",
|
||||
"njqdev.vscode-python-typehint",
|
||||
"ms-python.debugpy",
|
||||
"mhutchie.git-graph",
|
||||
"ms-vscode.cpptools-themes",
|
||||
"tamasfe.even-better-toml",
|
||||
"moshfeu.compare-folders",
|
||||
"njpwerner.autodocstring",
|
||||
"ms-python.black-formatter",
|
||||
"ms-python.isort",
|
||||
"ms-vscode.live-server",
|
||||
"yzhang.markdown-all-in-one",
|
||||
"bierner.markdown-mermaid",
|
||||
"charliermarsh.ruff",
|
||||
"shardulm94.trailing-spaces",
|
||||
"redhat.vscode-yaml",
|
||||
"ninoseki.vscode-mogami",
|
||||
"twxs.cmake",
|
||||
"cheshirekow.cmake-format",
|
||||
"wholroyd.jinja"
|
||||
]
|
||||
}
|
||||
},
|
||||
"runArgs": [
|
||||
"--network=host",
|
||||
"-e HOST_UID=$(id -u)",
|
||||
"-e HOST_GID=$(id -g)"
|
||||
],
|
||||
"postStartCommand": ".devcontainer/postStartCommand.sh"
|
||||
}
|
||||
180
.devcontainer/postStartCommand.sh
Normal file
180
.devcontainer/postStartCommand.sh
Normal file
@@ -0,0 +1,180 @@
|
||||
#!/bin/bash
|
||||
|
||||
# ==============================================================================
|
||||
# Conan2 Development Environment Setup
|
||||
#
|
||||
# Description: Provisions system dependencies, shell configuration, and Conan2.
|
||||
# Designed for Debian/Ubuntu-based DevContainers or CI Runners.
|
||||
# Usage: CONAN_USR=x CONAN_PSW=y ./postStartCommand.sh
|
||||
# ==============================================================================
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# --- Configuration ------------------------------------------------------------
|
||||
# Versions & Remote Resources
|
||||
TASK_VERSION="v3.45.5"
|
||||
GLOW_VERSION="2.1.1"
|
||||
CONAN_CONFIG_URL="https://package-cloud.dns.army/ros2/conan2-config.git"
|
||||
CONAN_REMOTE_NAME="package-cloud-ros2-conan2"
|
||||
|
||||
# Localization
|
||||
TIMEZONE="Europe/Berlin"
|
||||
|
||||
# Paths
|
||||
LOCAL_BIN="$HOME/.local/bin"
|
||||
ZSH_CUSTOM="${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}"
|
||||
|
||||
# --- Helpers ------------------------------------------------------------------
|
||||
|
||||
log() {
|
||||
echo -e "\033[1;34m>>> [SETUP] $1\033[0m"
|
||||
}
|
||||
|
||||
error() {
|
||||
echo -e "\033[1;31m!!! [ERROR] $1\033[0m" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
cleanup() {
|
||||
# Remove temp files on exit (successful or not)
|
||||
rm -f glow.deb install_task.sh
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
ensure_env_vars() {
|
||||
if [[ -z "${CONAN_USR:-}" ]] || [[ -z "${CONAN_PSW:-}" ]]; then
|
||||
error "CONAN_USR and CONAN_PSW environment variables are required."
|
||||
fi
|
||||
}
|
||||
|
||||
detect_arch() {
|
||||
local arch
|
||||
arch=$(dpkg --print-architecture)
|
||||
case "$arch" in
|
||||
amd64) echo "amd64" ;;
|
||||
arm64) echo "arm64" ;;
|
||||
*) error "Unsupported architecture: $arch" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# --- Installation Functions ---------------------------------------------------
|
||||
|
||||
install_system_dependencies() {
|
||||
log "Installing system dependencies..."
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
apt-get update -q
|
||||
apt-get install -y -q --no-install-recommends \
|
||||
tzdata curl git zsh python3 python3-pip python3-venv \
|
||||
ca-certificates gnupg pipx
|
||||
|
||||
# Ensure pipx path is available immediately for this script
|
||||
export PATH="$LOCAL_BIN:$PATH"
|
||||
pipx ensurepath
|
||||
}
|
||||
|
||||
configure_timezone() {
|
||||
log "Configuring timezone ($TIMEZONE)..."
|
||||
local tz_path="/usr/share/zoneinfo/$TIMEZONE"
|
||||
|
||||
# Validation: Ensure the requested timezone actually exists
|
||||
if [ ! -f "$tz_path" ]; then
|
||||
error "Timezone data not found at '$tz_path'. Please check the TIMEZONE variable."
|
||||
fi
|
||||
|
||||
ln -fs "$tz_path" /etc/localtime
|
||||
echo "$TIMEZONE" >/etc/timezone
|
||||
dpkg-reconfigure -f noninteractive tzdata
|
||||
}
|
||||
|
||||
install_shell_tools() {
|
||||
log "Setting up Shell (Oh My Zsh)..."
|
||||
if [ ! -d "$HOME/.oh-my-zsh" ]; then
|
||||
sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" "" --unattended
|
||||
else
|
||||
log "Oh My Zsh already installed. Skipping."
|
||||
fi
|
||||
}
|
||||
|
||||
install_conan() {
|
||||
log "Installing Conan via pipx (Isolated)..."
|
||||
|
||||
# Config
|
||||
log "Installing Conan Config..."
|
||||
# Force allows overwriting existing configs which is usually desired in setup scripts
|
||||
conan config install "$CONAN_CONFIG_URL" --type git --args="--branch main"
|
||||
|
||||
log "Authenticating Conan..."
|
||||
conan remote login "$CONAN_REMOTE_NAME" "$CONAN_USR" -p "$CONAN_PSW"
|
||||
}
|
||||
|
||||
install_utilities() {
|
||||
local arch
|
||||
arch=$(detect_arch)
|
||||
|
||||
# 1. Taskfile
|
||||
log "Installing Taskfile ($TASK_VERSION)..."
|
||||
curl -sL -o install_task.sh https://taskfile.dev/install.sh
|
||||
sh install_task.sh -d -b "$LOCAL_BIN" "$TASK_VERSION"
|
||||
|
||||
# 2. Glow
|
||||
log "Installing Glow ($GLOW_VERSION for $arch)..."
|
||||
local glow_url="https://github.com/charmbracelet/glow/releases/download/v${GLOW_VERSION}/glow_${GLOW_VERSION}_${arch}.deb"
|
||||
|
||||
curl -L -o glow.deb "$glow_url"
|
||||
dpkg -i glow.deb
|
||||
}
|
||||
|
||||
configure_persistence() {
|
||||
log "Persisting configurations..."
|
||||
|
||||
local zshrc="$HOME/.zshrc"
|
||||
touch "$zshrc"
|
||||
|
||||
# Helper to append if missing
|
||||
append_if_missing() {
|
||||
local file="$1"
|
||||
local content="$2"
|
||||
if ! grep -Fxq "$content" "$file"; then
|
||||
echo "$content" >>"$file"
|
||||
fi
|
||||
}
|
||||
|
||||
# Add Local Bin to Path
|
||||
local path_export='export PATH="$HOME/.local/bin:$PATH"'
|
||||
append_if_missing "$HOME/.bashrc" "$path_export"
|
||||
append_if_missing "$zshrc" "$path_export"
|
||||
|
||||
# Shell Completions
|
||||
append_if_missing "$zshrc" 'eval "$(task --completion zsh)"'
|
||||
append_if_missing "$zshrc" 'eval "$(glow completion zsh)"'
|
||||
|
||||
# Git Safe Directory
|
||||
git config --global --add safe.directory /workspaces/conan2-ros2-hesai-lidar
|
||||
}
|
||||
|
||||
run_tasks() {
|
||||
if [ -f "Taskfile.yml" ] || [ -f "Taskfile.yaml" ]; then
|
||||
log "Running default Task..."
|
||||
"$LOCAL_BIN/task" --yes
|
||||
else
|
||||
log "No Taskfile found. Skipping 'task --yes'."
|
||||
fi
|
||||
}
|
||||
|
||||
# --- Main Execution -----------------------------------------------------------
|
||||
|
||||
main() {
|
||||
ensure_env_vars
|
||||
install_system_dependencies
|
||||
configure_timezone
|
||||
install_shell_tools
|
||||
install_utilities # Task & Glow
|
||||
install_conan
|
||||
configure_persistence
|
||||
run_tasks
|
||||
|
||||
log "Setup complete successfully."
|
||||
}
|
||||
|
||||
main
|
||||
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
.task/
|
||||
3
.taskrc.yml
Normal file
3
.taskrc.yml
Normal file
@@ -0,0 +1,3 @@
|
||||
# Enable experimental features
|
||||
experiments:
|
||||
REMOTE_TASKFILES: 1
|
||||
3
.vscode/settings.json
vendored
Normal file
3
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"terminal.integrated.defaultProfile.linux": "zsh"
|
||||
}
|
||||
44
Taskfile.yml
Normal file
44
Taskfile.yml
Normal file
@@ -0,0 +1,44 @@
|
||||
# https://taskfile.dev
|
||||
|
||||
version: "3"
|
||||
|
||||
vars:
|
||||
# Global Configuration
|
||||
CONAN2_CONFIG_URL: https://package-cloud.dns.army/ros2/conan2-config
|
||||
CONAN2_CONFIG_BRANCH: main
|
||||
CONAN2_CONFIG_TASKFILE_PATH: Taskfile.yml
|
||||
CONAN_BUILD_VERSION: latest
|
||||
|
||||
includes:
|
||||
# Remote includes
|
||||
conan2-config: "{{.CONAN2_CONFIG_URL}}/raw/branch/{{.CONAN2_CONFIG_BRANCH}}/{{.CONAN2_CONFIG_TASKFILE_PATH}}"
|
||||
|
||||
# Local modules
|
||||
|
||||
tasks:
|
||||
default:
|
||||
desc: Show available tasks
|
||||
silent: true
|
||||
cmds:
|
||||
- task: version
|
||||
- task --list
|
||||
|
||||
version:
|
||||
desc: Display component version information
|
||||
silent: true
|
||||
vars:
|
||||
NAME_COMPONENT: repo-templates
|
||||
URL_COMPONENT: https://package-cloud.dns.army/ros2/repo-templates
|
||||
GIT_SHA:
|
||||
sh: git rev-parse --short HEAD
|
||||
GIT_REF:
|
||||
sh: git rev-parse --abbrev-ref HEAD
|
||||
cmds:
|
||||
- printf "{{.B_MAGENTA}}Component{{.RESET}} - {{.CYAN}}{{.NAME_COMPONENT}}{{.RESET}}\n"
|
||||
- printf "{{.B_MAGENTA}}URL{{.RESET}} - {{.CYAN}}{{.URL_COMPONENT}}{{.RESET}}\n"
|
||||
- printf "{{.B_MAGENTA}}Branch{{.RESET}} - {{.CYAN}}{{.GIT_REF}} {{.B_WHITE}}{{.RESET}} - {{.B_MAGENTA}}Hash{{.RESET}} - {{.GREEN}}{{.GIT_SHA}}{{.RESET}}\n"
|
||||
|
||||
init:
|
||||
desc: Sync dependencies
|
||||
cmds:
|
||||
- uv sync
|
||||
51
template/.devcontainer/devcontainer.json
Normal file
51
template/.devcontainer/devcontainer.json
Normal file
@@ -0,0 +1,51 @@
|
||||
{
|
||||
"image": "ubuntu:24.04",
|
||||
"containerEnv": {
|
||||
"CONAN_USR": "", // need to be filled
|
||||
"CONAN_PSW": "" // need to be filled,
|
||||
},
|
||||
"features": {
|
||||
"ghcr.io/devcontainers/features/git:1": {},
|
||||
"ghcr.io/devcontainers/features/git-lfs:1": {},
|
||||
"ghcr.io/devcontainers/features/python:1": {
|
||||
"toolsToInstall": "flake8,autopep8,black,yapf,mypy,pydocstyle,pycodestyle,bandit,pipenv,virtualenv,pytest,pylint,uv,copier,conan"
|
||||
}
|
||||
},
|
||||
"customizations": {
|
||||
"vscode": {
|
||||
"settings": {
|
||||
"git.path": "/usr/bin/git"
|
||||
},
|
||||
"extensions": [
|
||||
"ms-python.python",
|
||||
"ms-python.vscode-pylance",
|
||||
"GitHub.copilot-chat",
|
||||
"njqdev.vscode-python-typehint",
|
||||
"ms-python.debugpy",
|
||||
"mhutchie.git-graph",
|
||||
"ms-vscode.cpptools-themes",
|
||||
"tamasfe.even-better-toml",
|
||||
"moshfeu.compare-folders",
|
||||
"njpwerner.autodocstring",
|
||||
"ms-python.black-formatter",
|
||||
"ms-python.isort",
|
||||
"ms-vscode.live-server",
|
||||
"yzhang.markdown-all-in-one",
|
||||
"bierner.markdown-mermaid",
|
||||
"charliermarsh.ruff",
|
||||
"shardulm94.trailing-spaces",
|
||||
"redhat.vscode-yaml",
|
||||
"ninoseki.vscode-mogami",
|
||||
"twxs.cmake",
|
||||
"cheshirekow.cmake-format",
|
||||
"wholroyd.jinja"
|
||||
]
|
||||
}
|
||||
},
|
||||
"runArgs": [
|
||||
"--network=host",
|
||||
"-e HOST_UID=$(id -u)",
|
||||
"-e HOST_GID=$(id -g)"
|
||||
],
|
||||
"postStartCommand": ".devcontainer/postStartCommand.sh"
|
||||
}
|
||||
180
template/.devcontainer/postStartCommand.sh
Normal file
180
template/.devcontainer/postStartCommand.sh
Normal file
@@ -0,0 +1,180 @@
|
||||
#!/bin/bash
|
||||
|
||||
# ==============================================================================
|
||||
# Conan2 Development Environment Setup
|
||||
#
|
||||
# Description: Provisions system dependencies, shell configuration, and Conan2.
|
||||
# Designed for Debian/Ubuntu-based DevContainers or CI Runners.
|
||||
# Usage: CONAN_USR=x CONAN_PSW=y ./postStartCommand.sh
|
||||
# ==============================================================================
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# --- Configuration ------------------------------------------------------------
|
||||
# Versions & Remote Resources
|
||||
TASK_VERSION="v3.45.5"
|
||||
GLOW_VERSION="2.1.1"
|
||||
CONAN_CONFIG_URL="https://package-cloud.dns.army/ros2/conan2-config.git"
|
||||
CONAN_REMOTE_NAME="package-cloud-ros2-conan2"
|
||||
|
||||
# Localization
|
||||
TIMEZONE="Europe/Berlin"
|
||||
|
||||
# Paths
|
||||
LOCAL_BIN="$HOME/.local/bin"
|
||||
ZSH_CUSTOM="${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}"
|
||||
|
||||
# --- Helpers ------------------------------------------------------------------
|
||||
|
||||
log() {
|
||||
echo -e "\033[1;34m>>> [SETUP] $1\033[0m"
|
||||
}
|
||||
|
||||
error() {
|
||||
echo -e "\033[1;31m!!! [ERROR] $1\033[0m" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
cleanup() {
|
||||
# Remove temp files on exit (successful or not)
|
||||
rm -f glow.deb install_task.sh
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
ensure_env_vars() {
|
||||
if [[ -z "${CONAN_USR:-}" ]] || [[ -z "${CONAN_PSW:-}" ]]; then
|
||||
error "CONAN_USR and CONAN_PSW environment variables are required."
|
||||
fi
|
||||
}
|
||||
|
||||
detect_arch() {
|
||||
local arch
|
||||
arch=$(dpkg --print-architecture)
|
||||
case "$arch" in
|
||||
amd64) echo "amd64" ;;
|
||||
arm64) echo "arm64" ;;
|
||||
*) error "Unsupported architecture: $arch" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# --- Installation Functions ---------------------------------------------------
|
||||
|
||||
install_system_dependencies() {
|
||||
log "Installing system dependencies..."
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
apt-get update -q
|
||||
apt-get install -y -q --no-install-recommends \
|
||||
tzdata curl git zsh python3 python3-pip python3-venv \
|
||||
ca-certificates gnupg pipx
|
||||
|
||||
# Ensure pipx path is available immediately for this script
|
||||
export PATH="$LOCAL_BIN:$PATH"
|
||||
pipx ensurepath
|
||||
}
|
||||
|
||||
configure_timezone() {
|
||||
log "Configuring timezone ($TIMEZONE)..."
|
||||
local tz_path="/usr/share/zoneinfo/$TIMEZONE"
|
||||
|
||||
# Validation: Ensure the requested timezone actually exists
|
||||
if [ ! -f "$tz_path" ]; then
|
||||
error "Timezone data not found at '$tz_path'. Please check the TIMEZONE variable."
|
||||
fi
|
||||
|
||||
ln -fs "$tz_path" /etc/localtime
|
||||
echo "$TIMEZONE" >/etc/timezone
|
||||
dpkg-reconfigure -f noninteractive tzdata
|
||||
}
|
||||
|
||||
install_shell_tools() {
|
||||
log "Setting up Shell (Oh My Zsh)..."
|
||||
if [ ! -d "$HOME/.oh-my-zsh" ]; then
|
||||
sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" "" --unattended
|
||||
else
|
||||
log "Oh My Zsh already installed. Skipping."
|
||||
fi
|
||||
}
|
||||
|
||||
install_conan() {
|
||||
log "Installing Conan via pipx (Isolated)..."
|
||||
|
||||
# Config
|
||||
log "Installing Conan Config..."
|
||||
# Force allows overwriting existing configs which is usually desired in setup scripts
|
||||
conan config install "$CONAN_CONFIG_URL" --type git --args="--branch main"
|
||||
|
||||
log "Authenticating Conan..."
|
||||
conan remote login "$CONAN_REMOTE_NAME" "$CONAN_USR" -p "$CONAN_PSW"
|
||||
}
|
||||
|
||||
install_utilities() {
|
||||
local arch
|
||||
arch=$(detect_arch)
|
||||
|
||||
# 1. Taskfile
|
||||
log "Installing Taskfile ($TASK_VERSION)..."
|
||||
curl -sL -o install_task.sh https://taskfile.dev/install.sh
|
||||
sh install_task.sh -d -b "$LOCAL_BIN" "$TASK_VERSION"
|
||||
|
||||
# 2. Glow
|
||||
log "Installing Glow ($GLOW_VERSION for $arch)..."
|
||||
local glow_url="https://github.com/charmbracelet/glow/releases/download/v${GLOW_VERSION}/glow_${GLOW_VERSION}_${arch}.deb"
|
||||
|
||||
curl -L -o glow.deb "$glow_url"
|
||||
dpkg -i glow.deb
|
||||
}
|
||||
|
||||
configure_persistence() {
|
||||
log "Persisting configurations..."
|
||||
|
||||
local zshrc="$HOME/.zshrc"
|
||||
touch "$zshrc"
|
||||
|
||||
# Helper to append if missing
|
||||
append_if_missing() {
|
||||
local file="$1"
|
||||
local content="$2"
|
||||
if ! grep -Fxq "$content" "$file"; then
|
||||
echo "$content" >>"$file"
|
||||
fi
|
||||
}
|
||||
|
||||
# Add Local Bin to Path
|
||||
local path_export='export PATH="$HOME/.local/bin:$PATH"'
|
||||
append_if_missing "$HOME/.bashrc" "$path_export"
|
||||
append_if_missing "$zshrc" "$path_export"
|
||||
|
||||
# Shell Completions
|
||||
append_if_missing "$zshrc" 'eval "$(task --completion zsh)"'
|
||||
append_if_missing "$zshrc" 'eval "$(glow completion zsh)"'
|
||||
|
||||
# Git Safe Directory
|
||||
git config --global --add safe.directory /workspaces/conan2-ros2-hesai-lidar
|
||||
}
|
||||
|
||||
run_tasks() {
|
||||
if [ -f "Taskfile.yml" ] || [ -f "Taskfile.yaml" ]; then
|
||||
log "Running default Task..."
|
||||
"$LOCAL_BIN/task" --yes
|
||||
else
|
||||
log "No Taskfile found. Skipping 'task --yes'."
|
||||
fi
|
||||
}
|
||||
|
||||
# --- Main Execution -----------------------------------------------------------
|
||||
|
||||
main() {
|
||||
ensure_env_vars
|
||||
install_system_dependencies
|
||||
configure_timezone
|
||||
install_shell_tools
|
||||
install_utilities # Task & Glow
|
||||
install_conan
|
||||
configure_persistence
|
||||
run_tasks
|
||||
|
||||
log "Setup complete successfully."
|
||||
}
|
||||
|
||||
main
|
||||
3
template/.taskrc.yml
Normal file
3
template/.taskrc.yml
Normal file
@@ -0,0 +1,3 @@
|
||||
# Enable experimental features
|
||||
experiments:
|
||||
REMOTE_TASKFILES: 1
|
||||
Reference in New Issue
Block a user