Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions .github/workflows/justina-colombia.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
name: Validate JUSTINA Colombia proposal

on:
pull_request:
paths:
- "catkin_ws/Justina.workspace"
- "dockers/justina-colombia/**"
- ".github/workflows/justina-colombia.yml"
workflow_dispatch:

permissions:
contents: read

jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Verify ROS workspace distribution
shell: bash
run: grep -Fq '<Distribution name="kinetic"/>' catkin_ws/Justina.workspace

- name: Verify Colombia locale override
shell: bash
run: grep -Fq 'LC_ALL=es_CO.UTF-8' dockers/justina-colombia/Dockerfile

- name: Check shell scripts
shell: bash
run: |
bash -n dockers/justina-colombia/container-entrypoint.sh
bash -n dockers/justina-colombia/build-workspace.sh
shellcheck dockers/justina-colombia/container-entrypoint.sh
shellcheck dockers/justina-colombia/build-workspace.sh

- name: Reject unsafe legacy patterns
shell: bash
run: |
! grep -RE -- '--privileged|apt-key|nvidia-docker|chown[[:space:]]+-R[[:space:]]+/home|rm[[:space:]]+-rf[[:space:]]+/opt/ros' \
dockers/justina-colombia/Dockerfile \
dockers/justina-colombia/compose.yaml \
dockers/justina-colombia/container-entrypoint.sh

- name: Validate Compose configuration
working-directory: dockers/justina-colombia
env:
JUSTINA_REPO_PATH: ${{ github.workspace }}
run: docker compose config
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
*.swn
catkin_ws/devel/
catkin_ws/build/
catkin_ws/logs/
catkin_ws/.catkin_tools/
catkin_ws/src/CMakeLists.txt
catkin_ws/src/hri/justina_gui/src/justina_gui-release/*
!catkin_ws/src/hri/justina_gui/src/justina_gui-release/ui_MainWindow.h
Expand Down Expand Up @@ -81,3 +83,6 @@ catkin_ws/src/vision/obj_reco_plastic_tray/\.kdev4/
catkin_ws/src/src\.kdev4

catkin_ws/src/\.kdev4/

# Local container configuration
dockers/justina-colombia/.env
2 changes: 1 addition & 1 deletion catkin_ws/Justina.workspace
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0"?>
<Workspace>
<Distribution name="indigo"/>
<Distribution name="kinetic"/>
<DefaultBuildSystem value="0"/>
<WatchDirectories>
<Directory>src</Directory>
Expand Down
4 changes: 4 additions & 0 deletions catkin_ws/src/hardware/head/package.xml
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,15 @@
<!-- <test_depend>gtest</test_depend> -->
<buildtool_depend>catkin</buildtool_depend>
<build_depend>geometry_msgs</build_depend>
<build_depend>hardware_tools</build_depend>
<build_depend>message_generation</build_depend>
<build_depend>roscpp</build_depend>
<build_depend>rospy</build_depend>
<build_depend>std_msgs</build_depend>
<build_depend>sensor_msgs</build_depend>
<run_depend>geometry_msgs</run_depend>
<run_depend>hardware_tools</run_depend>
<run_depend>message_runtime</run_depend>
<run_depend>roscpp</run_depend>
<run_depend>rospy</run_depend>
<run_depend>std_msgs</run_depend>
Expand Down
11 changes: 11 additions & 0 deletions dockers/justina-colombia/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Ruta absoluta al clon local de RobotJustina/JUSTINA.
JUSTINA_REPO_PATH=/ruta/a/JUSTINA

# Imagen conservadora por defecto. Puede apuntar a un registro interno.
ROS_BASE_IMAGE=ros:kinetic-ros-base-xenial

# Use los identificadores del usuario anfitrión para evitar archivos propiedad de root.
USER_UID=1000
USER_GID=1000

ROS_MASTER_URI=http://localhost:11311
66 changes: 66 additions & 0 deletions dockers/justina-colombia/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
ARG ROS_BASE_IMAGE=ros:kinetic-ros-base-xenial
FROM ${ROS_BASE_IMAGE}

ARG DEBIAN_FRONTEND=noninteractive
ARG USERNAME=justina
ARG USER_UID=1000
ARG USER_GID=1000

ENV TZ=America/Bogota \
LANG=es_CO.UTF-8 \
LANGUAGE=es_CO:es \
LC_ALL=es_CO.UTF-8 \
LC_TIME=es_CO.UTF-8 \
ROS_DISTRO=kinetic \
JUSTINA_WS=/workspace/JUSTINA/catkin_ws

RUN apt-get update \
&& apt-get install -y --no-install-recommends \
bash-completion \
build-essential \
ca-certificates \
git \
libjack-jackd2-dev \
libopencv-dev \
libpcl-dev \
locales \
python-catkin-tools \
python-rosdep \
qtbase5-dev \
ros-kinetic-amcl \
ros-kinetic-desktop-full \
ros-kinetic-dynamixel-sdk \
ros-kinetic-fake-localization \
ros-kinetic-gmapping \
ros-kinetic-joy \
ros-kinetic-laser-geometry \
ros-kinetic-map-server \
ros-kinetic-pcl-ros \
ros-kinetic-pointcloud-to-laserscan \
ros-kinetic-serial \
ros-kinetic-sound-play \
ros-kinetic-tf \
ros-kinetic-tf2-bullet \
ros-kinetic-tf-conversions \
ros-kinetic-urg-node \
sudo \
tzdata \
&& locale-gen es_CO.UTF-8 \
&& update-locale LANG=es_CO.UTF-8 LANGUAGE=es_CO:es LC_TIME=es_CO.UTF-8 \
&& ln -snf /usr/share/zoneinfo/America/Bogota /etc/localtime \
&& echo America/Bogota > /etc/timezone \
&& groupadd --gid "${USER_GID}" "${USERNAME}" \
&& useradd --uid "${USER_UID}" --gid "${USER_GID}" --create-home --shell /bin/bash "${USERNAME}" \
&& echo "${USERNAME} ALL=(ALL) NOPASSWD:ALL" > "/etc/sudoers.d/${USERNAME}" \
&& chmod 0440 "/etc/sudoers.d/${USERNAME}" \
&& rm -rf /var/lib/apt/lists/*

COPY container-entrypoint.sh /usr/local/bin/container-entrypoint
COPY build-workspace.sh /usr/local/bin/build-justina-workspace
RUN chmod 0755 /usr/local/bin/container-entrypoint /usr/local/bin/build-justina-workspace

USER justina
WORKDIR /workspace/JUSTINA

ENTRYPOINT ["/usr/local/bin/container-entrypoint"]
CMD ["bash"]
82 changes: 82 additions & 0 deletions dockers/justina-colombia/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# Propuesta de contenedor JUSTINA para Colombia

Esta propuesta conserva Ubuntu 16.04 y ROS Kinetic dentro de un contenedor. No
ejecuta los instaladores heredados ni modifica paquetes del equipo anfitrión.

## Alcance

- Usa la imagen legada `ros:kinetic-ros-base-xenial` e instala el entorno
completo `ros-kinetic-desktop-full`.
- Declara explícitamente la plataforma `linux/amd64`.
- Configura `America/Bogota` y `es_CO.UTF-8`.
- Monta el clon de JUSTINA en `/workspace/JUSTINA`.
- Ejecuta como usuario sin privilegios.
- No incluye CUDA, cámaras, USB ni acceso privilegiado por defecto.

La imagen depende de componentes sin soporte. Debe usarse para recuperación,
evaluación y migración, no como plataforma nueva de producción.
Si la imagen pública deja de estar disponible, configure `ROS_BASE_IMAGE` para
usar una copia aprobada en un registro interno.

## Uso

1. Entre a `dockers/justina-colombia`.
2. Cree la configuración local:

```bash
cd dockers/justina-colombia
cp .env.example .env
```

3. Cambie `JUSTINA_REPO_PATH` en `.env` por la ruta absoluta del repositorio.
4. Construya y abra el entorno:

```bash
docker compose build
docker compose run --rm justina
```

5. Dentro del contenedor, prepare dependencias y compile el workspace:

```bash
build-justina-workspace
```

El comando incluye distribuciones ROS fuera de soporte al actualizar `rosdep`,
instala las dependencias declaradas, limpia resultados anteriores y compila.
Omite `libopenni-sensor-primesense-dev` porque ya no está disponible en los
repositorios de Ubuntu Xenial. Los módulos compilan con `libopenni`, pero usar
un sensor PrimeSense antiguo requiere instalar su controlador manualmente.

En Windows, después de aplicar la propuesta, valide los archivos con:

```powershell
.\dockers\justina-colombia\validate-proposal.ps1 -RepositoryPath .
```

## Issue #13

El archivo `catkin_ws/Justina.workspace` declara ROS Indigo, mientras los scripts
del repositorio instalan ROS Kinetic. Esta propuesta actualiza esa metadata a
Kinetic.

## Hardware y GPU

No habilite `--privileged` como solución general. Agregue dispositivos concretos
solo después de identificarlos, por ejemplo `/dev/video0` o un puerto serial.

Para GPU, instale NVIDIA Container Toolkit en el anfitrión y cree una variante
separada de Compose. CUDA 8 y las GPU modernas pueden ser incompatibles.

## Validación antes de revisión

```bash
docker compose config
docker build --check .
shellcheck container-entrypoint.sh
grep -Fq '<Distribution name="kinetic"/>' ../../catkin_ws/Justina.workspace
```

Estas validaciones requieren Docker Compose v2 y un anfitrión Linux. Docker
Desktop para Windows puede inspeccionar el archivo, pero `network_mode: host` y
el montaje de X11 están diseñados para Linux.
21 changes: 21 additions & 0 deletions dockers/justina-colombia/build-workspace.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#!/usr/bin/env bash
set -Eeuo pipefail

source "/opt/ros/${ROS_DISTRO}/setup.bash"

if [[ ! -f /etc/ros/rosdep/sources.list.d/20-default.list ]]; then
sudo rosdep init
fi

rosdep update --include-eol-distros
rosdep install \
--from-paths "${JUSTINA_WS}/src" \
--ignore-src \
--rosdistro "${ROS_DISTRO}" \
--skip-keys "libopenni-sensor-primesense-dev" \
-r \
-y

cd "${JUSTINA_WS}"
catkin clean -y
catkin build
23 changes: 23 additions & 0 deletions dockers/justina-colombia/compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
services:
justina:
platform: linux/amd64
build:
context: .
dockerfile: Dockerfile
args:
ROS_BASE_IMAGE: "${ROS_BASE_IMAGE:-ros:kinetic-ros-base-xenial}"
USER_UID: "${USER_UID:-1000}"
USER_GID: "${USER_GID:-1000}"
image: justina-colombia:kinetic
container_name: justina-colombia
environment:
DISPLAY: "${DISPLAY:-}"
ROS_MASTER_URI: "${ROS_MASTER_URI:-http://localhost:11311}"
TZ: America/Bogota
network_mode: host
stdin_open: true
tty: true
volumes:
- "${JUSTINA_REPO_PATH:?Defina JUSTINA_REPO_PATH}:/workspace/JUSTINA"
- "/tmp/.X11-unix:/tmp/.X11-unix:rw"
working_dir: /workspace/JUSTINA
10 changes: 10 additions & 0 deletions dockers/justina-colombia/container-entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/usr/bin/env bash
set -Eeuo pipefail

source "/opt/ros/${ROS_DISTRO}/setup.bash"

if [[ -f "${JUSTINA_WS}/devel/setup.bash" ]]; then
source "${JUSTINA_WS}/devel/setup.bash"
fi

exec "$@"
57 changes: 57 additions & 0 deletions dockers/justina-colombia/validate-proposal.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
[CmdletBinding()]
param(
[string]$RepositoryPath = (Resolve-Path (Join-Path $PSScriptRoot '..\..')).Path
)

$ErrorActionPreference = 'Stop'
$proposalDirectory = $PSScriptRoot
$workspaceFile = Join-Path $RepositoryPath 'catkin_ws\Justina.workspace'
$composeFile = Join-Path $proposalDirectory 'compose.yaml'
$dockerfile = Join-Path $proposalDirectory 'Dockerfile'

if (-not (Test-Path -LiteralPath $workspaceFile -PathType Leaf)) {
throw "No se encontró el workspace: $workspaceFile"
}

[xml]$workspace = Get-Content -Raw -LiteralPath $workspaceFile
$distribution = $workspace.Workspace.Distribution.name
if ($distribution -ne 'kinetic') {
throw "Se esperaba ROS Kinetic en Justina.workspace; se encontró: $distribution"
}

$dockerfileContent = Get-Content -Raw -LiteralPath $dockerfile
if ($dockerfileContent -notmatch 'LC_ALL=es_CO\.UTF-8') {
throw 'El Dockerfile no configura LC_ALL=es_CO.UTF-8.'
}

$unsafePatterns = @('--privileged', 'apt-key', 'nvidia-docker', 'chown\s+-R\s+/home', 'rm\s+-rf\s+/opt/ros')
$implementationFiles = @(
$composeFile,
$dockerfile,
(Join-Path $proposalDirectory 'container-entrypoint.sh'),
(Join-Path $proposalDirectory 'build-workspace.sh')
)
foreach ($pattern in $unsafePatterns) {
if (Select-String -Path $implementationFiles -Pattern $pattern) {
throw "Se encontró un patrón heredado no permitido: $pattern"
}
}

$previousRepoPath = $env:JUSTINA_REPO_PATH
try {
$env:JUSTINA_REPO_PATH = $RepositoryPath
if (Get-Command docker-compose -ErrorAction SilentlyContinue) {
& docker-compose -f $composeFile config | Out-Null
}
else {
& docker compose -f $composeFile config | Out-Null
}
if ($LASTEXITCODE -ne 0) {
throw 'La validación de Docker Compose falló.'
}
}
finally {
$env:JUSTINA_REPO_PATH = $previousRepoPath
}

Write-Host 'Validación de la propuesta JUSTINA Colombia: correcta.'