diff --git a/.github/api-server/Dockerfile b/.github/api-server/Dockerfile new file mode 100644 index 000000000..cb96ca6a0 --- /dev/null +++ b/.github/api-server/Dockerfile @@ -0,0 +1,47 @@ +ARG BRANCH=main +ARG ROS_DISTRO=jazzy +ARG BASE_IMAGE + +FROM $BASE_IMAGE as base + +ARG BRANCH + +# fetch sources +RUN mkdir -p /ws \ + && curl -L https://github.com/open-rmf/rmf-web/archive/$BRANCH.tar.gz -o rmf_web.tar.gz \ + && tar zxf rmf_web.tar.gz -C /ws --strip-components=1 + +# install deps +RUN cd /ws \ + && pnpm install --filter api-server... + +# cleanup +RUN rm -rf \ + /var/lib/apt/lists \ + /dist + +### Set up minimal image +FROM docker.io/library/ros:$ROS_DISTRO-ros-core + +ARG ROS_DISTRO + +RUN apt update && apt install -y ros-$ROS_DISTRO-rmw-cyclonedds-cpp + +# according to rosdep, the messages have no deps so we can just copy the files directly in! +# this reduces the image size by ~50%. +COPY --from=base /opt/rmf/include /opt/ros/$ROS_DISTRO/include +COPY --from=base /opt/rmf/lib /opt/ros/$ROS_DISTRO/lib +COPY --from=base /opt/rmf/share /opt/ros/$ROS_DISTRO/share + +# Copy over ws alongside the python virtual environment +RUN mkdir /ws +COPY --from=base /ws /ws + +# cleanup +RUN rm -rf \ + /var/lib/apt/lists \ + /dist + +ENV RMF_API_SERVER_CONFIG /ws/packages/api-server/sqlite_local_config.py +WORKDIR /ws/packages/api-server +ENTRYPOINT ["bash", "-c", ". /opt/ros/$ROS_DISTRO/setup.bash && mkdir -p run/cache && ../../.venv/bin/pipenv run python -m api_server"] diff --git a/.github/dashboard/Dockerfile b/.github/dashboard/Dockerfile new file mode 100644 index 000000000..6700897e0 --- /dev/null +++ b/.github/dashboard/Dockerfile @@ -0,0 +1,41 @@ +ARG BASE_IMAGE +FROM $BASE_IMAGE +ARG BRANCH=main + +### Build dashboard + +# fetch sources +RUN mkdir -p /ws \ + && curl -L https://github.com/open-rmf/rmf-web/archive/$BRANCH.tar.gz -o rmf_web.tar.gz \ + && tar zxf rmf_web.tar.gz -C /ws --strip-components=1 + +# install deps +RUN cd /ws \ + && pnpm install --filter rmf-dashboard... + +# replace configs and build +COPY app-config.json /ws/packages/dashboard/app-config.json +RUN cd /ws/packages/dashboard \ + && pnpm run build + +### Set up bare minimum dashboard image + +FROM docker.io/ubuntu:24.04 +COPY --from=0 /ws/packages/dashboard/dist /opt/dashboard + +RUN apt update && apt install -y curl + +RUN curl -fsSL https://get.pnpm.io/install.sh | bash - +# shell runs in non-interactive mode, which does not source .bashrc so we need to set the PATH manually +ENV PNPM_HOME /root/.local/share/pnpm +ENV PATH "$PNPM_HOME:$PATH" + +# nodejs seems to have changed the official mirror, the default in pnpm is very slow now +RUN pnpm config -g set 'node-mirror:release' https://nodejs.org/dist && pnpm env use --global lts + +RUN npm install --global serve +ENV PATH "$(npm bin -g):$PATH" + +COPY inject-env.sh /opt/inject-env.sh + +ENTRYPOINT ["bash", "-c", ". /opt/inject-env.sh && npx serve -s /opt/dashboard"] diff --git a/.github/dashboard/app-config.json b/.github/dashboard/app-config.json new file mode 100644 index 000000000..84626aeca --- /dev/null +++ b/.github/dashboard/app-config.json @@ -0,0 +1,42 @@ +{ + "$schema": "https://raw.githubusercontent.com/open-rmf/rmf-web/main/packages/dashboard/app-config.schema.json", + "rmfServerUrl": "__RMF_SERVER_URL__", + "trajectoryServerUrl": "__TRAJECTORY_SERVER_URL__", + "authConfig": {}, + "helpLink": "https://osrf.github.io/ros2multirobotbook/rmf-core.html", + "reportIssue": "https://github.com/open-rmf/rmf-web/issues", + "pickupZones": [], + "defaultZoom": 20, + "defaultRobotZoom": 6, + "attributionPrefix": "OSRC-SG", + "defaultMapLevel": "L1", + "allowedTasks": [ + { + "taskDefinitionId": "patrol" + }, + { + "taskDefinitionId": "delivery" + }, + { + "taskDefinitionId": "compose-clean" + }, + { + "taskDefinitionId": "custom_compose" + } + ], + "resources": { + "default": { + "fleets": {}, + "logos": { + "header": "/resources/defaultLogo.png" + } + } + }, + "cartIds": [], + "buildConfig": { + "baseUrl": "/", + "authProvider": "stub", + "customTabs": false, + "adminTab": false + } +} diff --git a/.github/dashboard/inject-env.sh b/.github/dashboard/inject-env.sh new file mode 100644 index 000000000..4284492cf --- /dev/null +++ b/.github/dashboard/inject-env.sh @@ -0,0 +1,5 @@ +#!/usr/bin/bash +set -e + +sed -i "s,__RMF_SERVER_URL__,${RMF_SERVER_URL},g" /opt/dashboard/index.html +sed -i "s,__TRAJECTORY_SERVER_URL__,${TRAJECTORY_SERVER_URL},g" /opt/dashboard/index.html diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index e916601f7..164e2aec9 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -7,8 +7,8 @@ concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: - build-docker-images: - name: Push Docker images to GitHub Packages + build-minimal-rmf-docker-images: + name: Push minimal-rmf Docker image to GitHub Packages runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 @@ -20,12 +20,43 @@ jobs: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - - name: Build and push + - name: Build and push minimal-rmf uses: docker/build-push-action@v5 with: push: true tags: ghcr.io/${{ github.repository }}/minimal-rmf context: .github/minimal-rmf + build-docker-images: + needs: build-minimal-rmf-docker-images + name: Push Docker images to GitHub Packages + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + - name: Login to docker + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: Build and push dashboard + uses: docker/build-push-action@v5 + with: + push: true + build-args: | + BASE_IMAGE=ghcr.io/${{ github.repository }}/minimal-rmf:latest + tags: ghcr.io/${{ github.repository }}/dashboard + context: .github/dashboard + - name: Build and push api-server + uses: docker/build-push-action@v5 + with: + push: true + build-args: | + BASE_IMAGE=ghcr.io/${{ github.repository }}/minimal-rmf:latest + ROS_DISTRO=jazzy + tags: ghcr.io/${{ github.repository }}/api-server + context: .github/api-server # dashboard-e2e: # strategy: # matrix: diff --git a/README.md b/README.md index fd57be786..a214d1a62 100644 --- a/README.md +++ b/README.md @@ -6,15 +6,46 @@ Open-RMF Web is a collection of packages that provide a web-based interface for users to visualize and control all aspects of Open-RMF deployments. -- [Getting started](#getting-started) +- [Quick start with docker](#quick-start-with-docker) +- [Getting started from source](#getting-started-from-source) - [API server](packages/api-server) - [API client](packages/api-client) - [Dashboard](packages/dashboard) - [Configuration](#configuration) - [Contribution guide](#contribution-guide) -- [Roadmap](https://github.com/open-rmf/rmf-web/wiki/Open-RMF-Web-Dashboard) +- [Roadmap](https://github.com/orgs/open-rmf/projects/10) -# Getting started +# Quick start with docker + +These docker images are useful when trying out [`rmf_demos`](https://github.com/open-rmf/rmf_demos). + +Start the dashboard with host network access, `RMF_SERVER_URL` and `TRAJECTORY_SERVER_URL` configured accordingly. The dashboard will then accessible on `localhost:3000` by default. + +```bash +docker run \ + --network host -it --rm \ + -e RMF_SERVER_URL=http://localhost:8000 \ + -e TRAJECTORY_SERVER_URL=ws://localhost:8006 \ + ghcr.io/open-rmf/rmf-web/dashboard:latest +``` + +> **Note** +> The values provided for `RMF_SERVER_URL` and `TRAJECTORY_SERVER_URL` are default values when running the API server and `rmf_demos`, and can be modified to suit different setups. + +Start the API server with host network access, and set up the correct `ROS_DOMAIN_ID` and ROS 2 RMW implementation that will be used in the rest of the Open-RMF system. The API server will use the default port at `localhost:8000`. + +```bash +docker run \ + --network host -it --rm \ + -e ROS_DOMAIN_ID= \ + -e RMW_IMPLEMENTATION= \ + ghcr.io/open-rmf/rmf-web/api-server:latest +``` + +> **Note** +> Users can also [configure the API server](packages/api-server/README.md/#configuration) using a mounted configuration file and setting the environment variable `RMF_API_SERVER_CONFIG`. In the default scenario, the API server will use an internal non-persistent database. + +# Getting started from source ### Prerequisites @@ -56,7 +87,7 @@ You may also install dependencies for only a subset of the packages pnpm install -w --filter ... ``` -### Launching +### Launching for development Source Open-RMF and launch the dashboard in development mode, @@ -75,25 +106,21 @@ This starts up the API server (by default at port 8000) which sets up endpoints If presented with a login screen, use `user=admin password=admin`. -Ensure that the fleet adapters in the Open-RMF deployment is configured to use the endpoints of the API server. By default it is `http://localhost:8000/_internal`. Launching a simulation from `rmf_demos_gz` for example, the command would be, +Ensure that the fleet adapters in the Open-RMF deployment is configured to use the endpoints of the API server. By default it is `http://localhost:8000/_internal`. Launching a simulation from [`rmf_demos_gz`](https://github.com/open-rmf/rmf_demos) for example, the command would be, ```bash ros2 launch rmf_demos_gz office.launch.xml server_uri:="http://localhost:8000/_internal" ``` -### Launching for development +### Launching for development separately -For development purposes, it might be useful to start all the individual components separately, +When developing individual components, it may be useful to start the dashboard and api-server separately, ```bash # Start the dashboard in dev, this monitors for changes in the dashboard package and performs rebuilds. A browser refresh is required after all automated builds. cd packages/dashboard pnpm run start:react -# Start react-components in dev, this monitors for changes in react-components, which will in turn trigger a re-build in dashboard. -cd packages/react-components -pnpm run build:watch - # Start the API server, this will need to be restarted for any changes to be reflected cd packages/api-server pnpm run start