From 1cd4cb3115b134d9c0b91ec1afe2fd550dbeb1b7 Mon Sep 17 00:00:00 2001 From: Michael Zhang <31636398+michaelzhang114@users.noreply.github.com> Date: Fri, 2 Oct 2026 09:42:11 -0700 Subject: [PATCH] Document build and test targets, and make local test runs self-contained by default (.test-data) (#2288) --- .gitignore | 4 +++ BUILDING.md | 78 +++++++++++++++++++++++++++++++++++++++++++++++++---- Makefile | 28 +++++++++++++++++-- 3 files changed, 103 insertions(+), 7 deletions(-) diff --git a/.gitignore b/.gitignore index f9a1f743..2d3d82e2 100644 --- a/.gitignore +++ b/.gitignore @@ -32,3 +32,7 @@ coverage-reports/ # API docs for local preview only. _site/ _serve/ + +# Default APP_ROOT and SCRATCH_ROOT for local test runs. +.test-data/ +.test-scratch/ diff --git a/BUILDING.md b/BUILDING.md index 8a7e1ce3..76f2429e 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -11,13 +11,71 @@ To build the `container` project, you need: ## Compile and test -Build `container` and the background services from source, and run basic and integration tests in an isolated application data directory: +Build `container` and the background services from source, then run the unit and integration tests in an isolated application data directory: ```bash -rm -rf test-data -make APP_ROOT=test-data all test integration +make verify ``` +This is the quickest way to verify your toolchain after cloning. `make verify` runs the `all`, `test`, and `integration` targets. The integration suite boots virtual machines and downloads a kernel and images, so the first run takes a while. + +> [!IMPORTANT] +> `make integration` stops any `container` services you already have running and leaves them stopped when it finishes; run `container system start` afterward to get back to your own installation. + +### Build and test targets + +| Target | What it does | +| --- | --- | +| `make verify` | Runs `all`, `test`, and `integration`. | +| `make all` | Compiles, then installs the binaries into `bin/` and `libexec/` in your project directory. | +| `make test` | Runs the unit tests. | +| `make integration` | Runs the CLI and integration test suites. These start the `container` services, create containers, and boot virtual machines. | +| `make install` | Builds an installer package and installs it to `/usr/local`. | +| `make clean` | Runs `cleantest`, then `cleanbuild`. | +| `make cleanbuild` | Removes `bin/`, `libexec/`, generated docs, and coverage output. | +| `make cleantest` | Stops the `container` services and removes the `APP_ROOT` and `SCRATCH_ROOT` directories. | + +### Isolating test data with `APP_ROOT` + +By default, the test targets use `.test-data` in your project directory, so they do not disturb the images, containers, and volumes you use day to day, which live in `~/Library/Application Support/com.apple.container`. + +`APP_ROOT` sets that directory, and is passed as `--app-root` to the services the test targets start. + +How `make integration` treats `APP_ROOT`: +- It erases the directory's contents before each run. +- Set `APP_ROOT=` (empty) to run against `~/Library/Application Support/com.apple.container` instead. The tests will not erase it, but they will create and delete containers in it. Use this when you want the tests to exercise a realistic installation. + +### Recommended iteration loop + +> [!IMPORTANT] +> If you have an instance of `container` running, stop it using `container system stop` before starting the dev CLI. Each user account has a single set of `com.apple.container.*` services, so a test run cannot coexist with an installation you are using. + +```bash +# 1. Build +make all + +# 2. Unit tests +make test + +# 3. Test the dev CLI +./bin/container system start --app-root .test-data +``` + +### Integration test options + +| Variable | Default | Effect | +| --- | --- | --- | +| `PRESERVE_KERNELS` | `false` | Set to `true` to keep the `kernels` directory when the run clears `APP_ROOT`, so repeated runs do not download the kernel again. | +| `LOG_ROOT` | unset | Passes `--log-root` to the services, and writes swift-testing event streams to the given path. | + +A typical iteration on the integration tests: + +```bash +make PRESERVE_KERNELS=true LOG_ROOT=.test-data/logs integration +``` + +### Build installer package + Copy the binaries to `/usr/local/bin` and `/usr/local/libexec` (requires entering an administrator password): ```bash @@ -27,10 +85,20 @@ make install Or to install a release build, with better performance than the debug build: ```bash -BUILD_CONFIGURATION=release make all test integration +BUILD_CONFIGURATION=release make verify BUILD_CONFIGURATION=release make install ``` +### Clean up + +Stop the services, remove the build outputs, and delete the test directories: + +```bash +make clean +``` + +Use `make cleanbuild` to remove only the build outputs, or `make cleantest` to stop the services and remove only the `APP_ROOT` and `SCRATCH_ROOT` directories. + ## Compile protobufs `container` uses gRPC to communicate to the builder virtual machine that creates images from `Dockerfile`s, and depends on specific versions of `grpc-swift` and `swift-protobuf`. If you make changes to the gRPC APIs in the [container-builder-shim](https://github.com/apple/container-builder-shim) project, install the tools and re-generate the gRPC code in this project using: @@ -91,7 +159,7 @@ to prepare your build environment. 6. Build `container`. ``` - make clean all + make APP_ROOT= clean all ``` 7. Restart the `container` services. diff --git a/Makefile b/Makefile index ef90124b..e8c353c8 100644 --- a/Makefile +++ b/Makefile @@ -36,6 +36,10 @@ DSYM_DIR := bin/$(BUILD_CONFIGURATION)/bundle/container-dSYM DSYM_PATH := bin/$(BUILD_CONFIGURATION)/bundle/container-dSYM.zip CODESIGN_OPTS ?= --force --sign - --timestamp=none +# Default isolated application data root under the project directory so test runs do not touch your +# own installation. Override with APP_ROOT=/your/path, or APP_ROOT= (empty) to run against +# the default ~/Library/Application Support/com.apple.container. +APP_ROOT ?= $(ROOT_DIR)/.test-data # Conditionally use a temporary data directory for integration tests SYSTEM_START_OPTS := @@ -63,6 +67,9 @@ SUDO ?= sudo include Protobuf.Makefile +.PHONY: verify +verify: all test integration + .PHONY: all all: container all: init-block @@ -312,7 +319,12 @@ define RUN_INTEGRATION endef .PHONY: integration -integration: init-block +integration: container init-block + @echo "HOSTNAME: $$(hostname)" + $(RUN_INTEGRATION) + +.PHONY: integration-only +integration-only: init-block @echo "HOSTNAME: $$(hostname)" $(RUN_INTEGRATION) @@ -423,10 +435,22 @@ cleancontent: @rm -rf ~/Library/Application\ Support/com.apple.container .PHONY: clean -clean: +clean: cleantest cleanbuild + +.PHONY: cleanbuild +cleanbuild: @echo Cleaning build files... @rm -rf bin/ libexec/ @rm -rf _site _serve @rm -f $(COV_REPORT_FILE) @rm -rf $(COVERAGE_OUTPUT_DIR) @$(SWIFT) package clean + +.PHONY: cleantest +cleantest: + @echo Stopping container services... + @bin/container system stop 2>/dev/null || true + @scripts/ensure-container-stopped.sh -a || true + @if [ -n "$(APP_ROOT)" ]; then echo "Removing $(APP_ROOT)..." ; rm -rf "$(APP_ROOT)" ; fi + @echo "Removing $(SCRATCH_ROOT)..." + @rm -rf "$(SCRATCH_ROOT)"