forked from All-Hands-AI/OpenHands
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
build a runner container for us to use (#14)
- Loading branch information
Showing
3 changed files
with
152 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -89,6 +89,66 @@ jobs: | |
echo "hash_from_app_image=$hash_from_app_image" >> $GITHUB_OUTPUT | ||
echo "Hash from app image: $hash_from_app_image" | ||
# Builds the replay.io runner image | ||
ghcr_build_runner: | ||
name: Build Runner Image | ||
runs-on: ubuntu-latest | ||
permissions: | ||
contents: read | ||
packages: write | ||
outputs: | ||
hash_from_runner_image: ${{ steps.get_hash_in_runner_image.outputs.hash_from_runner_image }} | ||
steps: | ||
- name: Checkout | ||
uses: actions/checkout@v4 | ||
- name: Free Disk Space (Ubuntu) | ||
uses: jlumbroso/free-disk-space@main | ||
with: | ||
# this might remove tools that are actually needed, | ||
# if set to "true" but frees about 6 GB | ||
tool-cache: true | ||
# all of these default to true, but feel free to set to | ||
# "false" if necessary for your workflow | ||
android: true | ||
dotnet: true | ||
haskell: true | ||
large-packages: true | ||
docker-images: false | ||
swap-storage: true | ||
- name: Set up QEMU | ||
uses: docker/[email protected] | ||
with: | ||
image: tonistiigi/binfmt:latest | ||
- name: Login to GHCR | ||
uses: docker/login-action@v3 | ||
with: | ||
registry: ghcr.io | ||
username: ${{ github.repository_owner }} | ||
password: ${{ secrets.GITHUB_TOKEN }} | ||
- name: Set up Docker Buildx | ||
id: buildx | ||
uses: docker/setup-buildx-action@v3 | ||
- name: Build and push runner image | ||
if: "!github.event.pull_request.head.repo.fork" | ||
run: | | ||
./containers/build.sh -i runner -o ${{ github.repository_owner }} --push | ||
- name: Build runner image | ||
if: "github.event.pull_request.head.repo.fork" | ||
run: | | ||
./containers/build.sh -i runner -o ${{ github.repository_owner }} --load | ||
- name: Get hash in Runner Image | ||
id: get_hash_in_runner_image | ||
run: | | ||
# Lowercase the repository owner | ||
export REPO_OWNER=${{ github.repository_owner }} | ||
REPO_OWNER=$(echo $REPO_OWNER | tr '[:upper:]' '[:lower:]') | ||
# Run the build script in the runner image | ||
docker run -e SANDBOX_USER_ID=0 -v /var/run/docker.sock:/var/run/docker.sock ghcr.io/${REPO_OWNER}/runner:${{ env.RELEVANT_SHA }} /bin/bash -c "mkdir -p containers/runtime; python3 openhands/runtime/utils/runtime_build.py --base_image ${{ env.BASE_IMAGE_FOR_HASH_EQUIVALENCE_TEST }} --build_folder containers/runtime --force_rebuild" 2>&1 | tee docker-outputs.txt | ||
# Get the hash from the build script | ||
hash_from_runner_image=$(cat docker-outputs.txt | grep "Hash for docker build directory" | awk -F "): " '{print $2}' | uniq | head -n1) | ||
echo "hash_from_runner_image=$hash_from_runner_image" >> $GITHUB_OUTPUT | ||
echo "Hash from runner image: $hash_from_runner_image" | ||
# Builds the runtime Docker images | ||
ghcr_build_runtime: | ||
name: Build Image | ||
|
@@ -169,10 +229,10 @@ jobs: | |
name: runtime-${{ matrix.base_image.tag }} | ||
path: /tmp/runtime-${{ matrix.base_image.tag }}.tar | ||
|
||
verify_hash_equivalence_in_runtime_and_app: | ||
name: Verify Hash Equivalence in Runtime and Docker images | ||
verify_hash_equivalence_in_runtime_and_runner_and_app: | ||
name: Verify Hash Equivalence in App, Runner, and Runtime images | ||
runs-on: ubuntu-latest | ||
needs: [ghcr_build_runtime, ghcr_build_app] | ||
needs: [ghcr_build_runtime, ghcr_build_runner, ghcr_build_app] | ||
strategy: | ||
fail-fast: false | ||
matrix: | ||
|
@@ -200,6 +260,10 @@ jobs: | |
run: | | ||
echo "Hash from app image: ${{ needs.ghcr_build_app.outputs.hash_from_app_image }}" | ||
echo "hash_from_app_image=${{ needs.ghcr_build_app.outputs.hash_from_app_image }}" >> $GITHUB_ENV | ||
- name: Get hash in Runner Image | ||
run: | | ||
echo "Hash from runner image: ${{ needs.ghcr_build_runner.outputs.hash_from_runner_image }}" | ||
echo "hash_from_runner_image=${{ needs.ghcr_build_runner.outputs.hash_from_runner_image }}" >> $GITHUB_ENV | ||
- name: Get hash using code (development mode) | ||
run: | | ||
|
@@ -211,8 +275,9 @@ jobs: | |
- name: Compare hashes | ||
run: | | ||
echo "Hash from App Image: ${{ env.hash_from_app_image }}" | ||
echo "Hash from Runner Image: ${{ env.hash_from_runner_image }}" | ||
echo "Hash from Code: ${{ env.hash_from_code }}" | ||
if [ "${{ env.hash_from_app_image }}" = "${{ env.hash_from_code }}" ]; then | ||
if [ "${{ env.hash_from_app_image }}" = "${{ env.hash_from_code }}" -a "${{ env.hash_from_runner_image }}" = "${{ env.hash_from_code }}"]; then | ||
echo "Hashes match!" | ||
else | ||
echo "Hashes do not match!" | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
ARG OPENHANDS_BUILD_VERSION=dev | ||
|
||
FROM python:3.12.3-slim AS backend-builder | ||
|
||
WORKDIR /runner | ||
ENV PYTHONPATH='/runner' | ||
|
||
ENV POETRY_NO_INTERACTION=1 \ | ||
POETRY_VIRTUALENVS_IN_PROJECT=1 \ | ||
POETRY_VIRTUALENVS_CREATE=1 \ | ||
POETRY_CACHE_DIR=/tmp/poetry_cache | ||
|
||
RUN apt-get update -y \ | ||
&& apt-get install -y curl make git build-essential \ | ||
&& python3 -m pip install poetry==1.8.2 --break-system-packages | ||
|
||
COPY ./pyproject.toml ./poetry.lock ./ | ||
RUN touch README.md | ||
RUN export POETRY_CACHE_DIR && poetry install --without evaluation,llama-index --no-root && rm -rf $POETRY_CACHE_DIR | ||
|
||
FROM python:3.12.3-slim AS openhands-runner | ||
|
||
WORKDIR /runner | ||
|
||
ARG OPENHANDS_BUILD_VERSION #re-declare for this section | ||
|
||
ENV RUN_AS_OPENHANDS=true | ||
# A random number--we need this to be different from the user's UID on the host machine | ||
ENV OPENHANDS_USER_ID=42420 | ||
ENV SANDBOX_LOCAL_RUNTIME_URL=http://host.docker.internal | ||
ENV USE_HOST_NETWORK=false | ||
ENV WORKSPACE_BASE=/opt/workspace_base | ||
ENV OPENHANDS_BUILD_VERSION=$OPENHANDS_BUILD_VERSION | ||
ENV SANDBOX_USER_ID=0 | ||
RUN mkdir -p $WORKSPACE_BASE | ||
|
||
RUN apt-get update -y \ | ||
&& apt-get install -y curl ssh sudo | ||
|
||
# Default is 1000, but OSX is often 501 | ||
RUN sed -i 's/^UID_MIN.*/UID_MIN 499/' /etc/login.defs | ||
# Default is 60000, but we've seen up to 200000 | ||
RUN sed -i 's/^UID_MAX.*/UID_MAX 1000000/' /etc/login.defs | ||
|
||
RUN groupadd runner | ||
RUN useradd -l -m -u $OPENHANDS_USER_ID -s /bin/bash openhands && \ | ||
usermod -aG runner openhands && \ | ||
usermod -aG sudo openhands && \ | ||
echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers | ||
RUN chown -R openhands:runner /runner && chmod -R 770 /runner | ||
RUN sudo chown -R openhands:runner $WORKSPACE_BASE && sudo chmod -R 770 $WORKSPACE_BASE | ||
USER openhands | ||
|
||
ENV VIRTUAL_ENV=/runner/.venv \ | ||
PATH="/runner/.venv/bin:$PATH" \ | ||
PYTHONPATH='/runner' | ||
|
||
COPY --chown=openhands:runner --chmod=770 --from=backend-builder ${VIRTUAL_ENV} ${VIRTUAL_ENV} | ||
|
||
COPY --chown=openhands:runner --chmod=770 ./openhands ./openhands | ||
COPY --chown=openhands:runner --chmod=777 ./openhands/runtime/plugins ./openhands/runtime/plugins | ||
COPY --chown=openhands:runner --chmod=770 ./openhands/agenthub ./openhands/agenthub | ||
COPY --chown=openhands:runner ./pyproject.toml ./pyproject.toml | ||
COPY --chown=openhands:runner ./poetry.lock ./poetry.lock | ||
COPY --chown=openhands:runner ./README.md ./README.md | ||
COPY --chown=openhands:runner ./MANIFEST.in ./MANIFEST.in | ||
COPY --chown=openhands:runner ./LICENSE ./LICENSE | ||
|
||
# This is run as "openhands" user, and will create __pycache__ with openhands:openhands ownership | ||
RUN python openhands/core/download.py # No-op to download assets | ||
# Add this line to set group ownership of all files/directories not already in "runner" group | ||
# openhands:openhands -> openhands:runner | ||
RUN find /runner \! -group runner -exec chgrp runner {} + | ||
|
||
USER root | ||
|
||
WORKDIR /runner | ||
|
||
CMD [ "sleep", "infinity" ] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
DOCKER_REGISTRY=ghcr.io | ||
DOCKER_ORG=all-hands-ai | ||
DOCKER_IMAGE=runner | ||
DOCKER_BASE_DIR="." |