Skip to content

Commit b9d6369

Browse files
Merge pull request #9322 from ThomasWaldmann/linux-container-testing-master
linux-run: run commands (e.g. tox) in a podman linux container
2 parents 632893b + 40a2bb7 commit b9d6369

File tree

3 files changed

+184
-0
lines changed

3 files changed

+184
-0
lines changed

docs/development.rst

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,50 @@ Usage::
405405
# To copy files from the VM (in this case, the generated binary):
406406
vagrant scp OS:/vagrant/borg/borg.exe .
407407

408+
Using Podman
409+
------------
410+
411+
macOS-based developers (and others who prefer containers) can run the Linux test suite locally using Podman.
412+
413+
Prerequisites:
414+
415+
- Install Podman (e.g., ``brew install podman``).
416+
- Initialize the Podman machine, only once: ``podman machine init``.
417+
- Start the Podman machine, before using it: ``podman machine start``.
418+
419+
Usage::
420+
421+
# Open an interactive shell in the container (default if no command given):
422+
./scripts/linux-run
423+
424+
# Run the default tox environment:
425+
./scripts/linux-run tox
426+
427+
# Run a specific tox environment:
428+
./scripts/linux-run tox -e py311-pyfuse3
429+
430+
# Pass arguments to pytest (e.g., run specific tests):
431+
./scripts/linux-run tox -e py313-pyfuse3 -- -k mount
432+
433+
# Switch base image (temporarily):
434+
./scripts/linux-run --image python:3.11-bookworm tox
435+
436+
Resource Usage
437+
~~~~~~~~~~~~~~
438+
439+
The default Podman VM uses 2GB RAM and half your CPUs.
440+
For heavy tests (parallel execution), this might be tight.
441+
442+
- **Check usage:** Run ``podman stats`` in another terminal while tests are running.
443+
- **Increase resources:**
444+
445+
::
446+
447+
podman machine stop
448+
podman machine set --cpus 6 --memory 4096
449+
podman machine start
450+
451+
408452
Creating standalone binaries
409453
----------------------------
410454

scripts/Dockerfile.linux-tox

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
ARG BASE_IMAGE=python:3.13
2+
FROM ${BASE_IMAGE}
3+
4+
# Install system dependencies
5+
# These match the dependencies installed in CI for Linux (Debian/Ubuntu)
6+
RUN apt-get update && apt-get install -y --no-install-recommends \
7+
build-essential \
8+
pkg-config \
9+
libssl-dev \
10+
libacl1-dev \
11+
libxxhash-dev \
12+
liblz4-dev \
13+
libzstd-dev \
14+
libfuse3-dev \
15+
fuse3 \
16+
python3-dev \
17+
git \
18+
&& rm -rf /var/lib/apt/lists/*
19+
20+
# Install tox
21+
RUN pip install tox
22+
23+
# Set working directory
24+
WORKDIR /app
25+
26+
# Check that we have the expected python version
27+
RUN python3 --version
28+
29+
# Default command (can be overridden)
30+
CMD ["tox"]

scripts/linux-run

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
#!/bin/bash
2+
# run commands in a linux container, e.g. for testing - for more info, see docs/development.rst.
3+
4+
set -euo pipefail
5+
# set -x # Uncomment for debugging
6+
7+
# Default configuration
8+
BASE_IMAGE="python:3.13"
9+
IMAGE_NAME="borg-test-env"
10+
CONTAINER_NAME="borg-test-runner"
11+
12+
usage() {
13+
echo "Usage: $0 [options] [command [args...]]"
14+
echo ""
15+
echo "Options:"
16+
echo " --image IMAGE Base Docker image to use (default: $BASE_IMAGE)"
17+
echo " --rebuild Force rebuild of the container image"
18+
echo " --help Show this help message"
19+
echo ""
20+
echo "Examples:"
21+
echo " $0 # Open interactive shell (default)"
22+
echo " $0 tox -e py313-pyfuse3 # Run tox in the container"
23+
echo " $0 --image python:3.11 tox -e py311-none # Run with specific image"
24+
echo " $0 ls -la # Run arbitrary command"
25+
exit 1
26+
}
27+
28+
# Parse specific arguments
29+
REBUILD=false
30+
31+
# We use an array to store the command and its arguments.
32+
COMMAND=()
33+
34+
while [[ $# -gt 0 ]]; do
35+
case $1 in
36+
--image)
37+
BASE_IMAGE="$2"
38+
shift 2
39+
;;
40+
--rebuild)
41+
REBUILD=true
42+
shift
43+
;;
44+
--help)
45+
usage
46+
;;
47+
--)
48+
# Stop option parsing and treat the rest as command
49+
shift
50+
COMMAND+=("$@")
51+
break
52+
;;
53+
*)
54+
# Stop option parsing and treat this and the rest as command
55+
COMMAND+=("$@")
56+
break
57+
;;
58+
esac
59+
done
60+
61+
# Ensure Podman is available
62+
if ! command -v podman &> /dev/null; then
63+
echo "Error: podman is not installed. Please run 'brew install podman' and initialize it."
64+
exit 1
65+
fi
66+
67+
# Build the image if needed or requested.
68+
# We tag the image with the base image name to allow multiple versions.
69+
TAG_SUFFIX=$(echo "$BASE_IMAGE" | tr ':' '-')
70+
FULL_IMAGE_NAME="${IMAGE_NAME}:${TAG_SUFFIX}"
71+
72+
if [[ "$REBUILD" == "true" ]] || ! podman image exists "$FULL_IMAGE_NAME"; then
73+
echo "Building test image based on $BASE_IMAGE..."
74+
podman build \
75+
--build-arg BASE_IMAGE="$BASE_IMAGE" \
76+
-t "$FULL_IMAGE_NAME" \
77+
-f scripts/Dockerfile.linux-tox .
78+
fi
79+
80+
echo "Running in container..."
81+
echo "Base Image: $BASE_IMAGE"
82+
if [[ ${#COMMAND[@]} -gt 0 ]]; then
83+
echo "Command: ${COMMAND[*]}"
84+
else
85+
echo "Command: /bin/bash (default)"
86+
fi
87+
88+
# Run the container
89+
# --userns=keep-id: Maps the container user to the host user (Crucial for macOS volume mounts)
90+
# --security-opt label=disable: Disables SELinux separation if active (harmless on macOS)
91+
# --device /dev/fuse: Required for FUSE filesystem support (borg mount tests)
92+
# --volume $(pwd):/app: Mounts current directory to /app
93+
# --mount type=volume,dst=/tmp: Using a volume for /tmp to prevent issues with tmp files from different users
94+
95+
CMD=(podman run --rm -it \
96+
--name "$CONTAINER_NAME" \
97+
--userns=keep-id \
98+
--cap-add SYS_ADMIN \
99+
--security-opt label=disable \
100+
--device /dev/fuse \
101+
--volume "$(pwd):/app" \
102+
--mount type=volume,dst=/tmp \
103+
--workdir /app \
104+
"$FULL_IMAGE_NAME")
105+
106+
if [[ ${#COMMAND[@]} -gt 0 ]]; then
107+
"${CMD[@]}" "${COMMAND[@]}"
108+
else
109+
"${CMD[@]}" /bin/bash
110+
fi

0 commit comments

Comments
 (0)