-
Notifications
You must be signed in to change notification settings - Fork 39
ENT-13777: Added container-based CFEngine package builder #2146
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
larsewi
wants to merge
1
commit into
cfengine:master
Choose a base branch
from
larsewi:container
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+590
−0
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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,113 @@ | ||
| #!/bin/bash | ||
| set -e | ||
|
|
||
| # Configuration via environment variables: | ||
| # PROJECT, BUILD_TYPE, EXPLICIT_ROLE, BUILD_NUMBER, EXPLICIT_VERSION | ||
|
|
||
| BASEDIR=/home/builder/build | ||
| export BASEDIR | ||
| export AUTOBUILD_PATH="$BASEDIR/buildscripts" | ||
|
|
||
| mkdir -p "$BASEDIR" | ||
|
|
||
| # Bind-mounted directories may be owned by the host user's UID. | ||
| # Fix ownership so builder can write to them. | ||
| sudo chown -R "$(id -u):$(id -g)" "$HOME/.cache" /output | ||
|
|
||
| # Prevent git "dubious ownership" errors | ||
| git config --global --add safe.directory '*' | ||
|
|
||
| # === Sync source repos === | ||
| repos="buildscripts core masterfiles" | ||
| if [ "$PROJECT" = "nova" ]; then | ||
| repos="$repos enterprise nova mission-portal" | ||
| fi | ||
|
|
||
| for repo in $repos; do | ||
| src="/srv/source/$repo" | ||
| # Use rsync -aL to follow symlinks during copy. | ||
| # The source dir may use symlinks (e.g., core -> cfengine/core/). | ||
| # -L resolves them at copy time, so the destination gets real files | ||
| # regardless of the host directory layout. | ||
| # Exclude acceptance test workdirs — they contain broken symlinks left | ||
| # over from previous test runs and are not needed for building. | ||
| if [ -d "$src" ] || [ -L "$src" ]; then | ||
| echo "Syncing $repo..." | ||
| sudo rsync -aL --exclude='config.cache' --exclude='workdir' --chown="$(id -u):$(id -g)" "$src/" "$BASEDIR/$repo/" | ||
| else | ||
| echo "ERROR: Required repository $repo not found" >&2 | ||
| exit 1 | ||
| fi | ||
| done | ||
|
|
||
| install_mission_portal_deps() ( | ||
| set -e | ||
|
|
||
| if [ -f "$BASEDIR/mission-portal/public/scripts/package.json" ]; then | ||
| echo "Installing npm dependencies..." | ||
| npm ci --prefix "$BASEDIR/mission-portal/public/scripts/" | ||
| echo "Building react components..." | ||
| npm run build --prefix "$BASEDIR/mission-portal/public/scripts/" | ||
| rm -rf "$BASEDIR/mission-portal/public/scripts/node_modules" | ||
| fi | ||
|
|
||
| if [ -f "$BASEDIR/mission-portal/composer.json" ]; then | ||
| echo "Installing Mission Portal PHP dependencies..." | ||
| (cd "$BASEDIR/mission-portal" && php /usr/bin/composer.phar install --no-dev --ignore-platform-reqs) | ||
| fi | ||
|
|
||
| if [ -f "$BASEDIR/nova/api/http/composer.json" ]; then | ||
| echo "Installing Nova API PHP dependencies..." | ||
| (cd "$BASEDIR/nova/api/http" && php /usr/bin/composer.phar install --no-dev --ignore-platform-reqs) | ||
| fi | ||
|
|
||
| if [ -f "$BASEDIR/mission-portal/public/themes/default/bootstrap/cfengine_theme.less" ]; then | ||
| echo "Compiling Mission Portal styles..." | ||
| mkdir -p "$BASEDIR/mission-portal/public/themes/default/bootstrap/compiled/css" | ||
| (cd "$BASEDIR/mission-portal/public/themes/default/bootstrap" && | ||
| lessc --compress ./cfengine_theme.less ./compiled/css/cfengine.less.css) | ||
| fi | ||
|
|
||
| if [ -f "$BASEDIR/mission-portal/ldap/composer.json" ]; then | ||
| echo "Installing LDAP API PHP dependencies..." | ||
| (cd "$BASEDIR/mission-portal/ldap" && php /usr/bin/composer.phar install --no-dev --ignore-platform-reqs) | ||
| fi | ||
| ) | ||
|
|
||
| # === Step runner with failure reporting === | ||
| # Disable set -e so we can capture exit codes and report which step failed. | ||
| set +e | ||
| run_step() { | ||
| local name="$1" | ||
| shift | ||
| echo "=== Running $name ===" | ||
| "$@" | ||
| local rc=$? | ||
| if [ $rc -ne 0 ]; then | ||
| echo "" | ||
| echo "=== FAILED: $name (exit code $rc) ===" | ||
| exit $rc | ||
| fi | ||
| } | ||
|
|
||
| # === Build steps === | ||
| run_step "01-autogen" "$BASEDIR/buildscripts/build-scripts/autogen" | ||
| run_step "02-install-dependencies" "$BASEDIR/buildscripts/build-scripts/install-dependencies" | ||
| if [ "$EXPLICIT_ROLE" = "hub" ]; then | ||
| run_step "03-mission-portal-deps" install_mission_portal_deps | ||
| fi | ||
| run_step "04-configure" "$BASEDIR/buildscripts/build-scripts/configure" | ||
| run_step "05-compile" "$BASEDIR/buildscripts/build-scripts/compile" | ||
| run_step "06-package" "$BASEDIR/buildscripts/build-scripts/package" | ||
|
|
||
| # === Copy output packages === | ||
| # Packages are created under $BASEDIR/<project>/ by dpkg-buildpackage / rpmbuild. | ||
| # Exclude deps-packaging to avoid copying dependency packages. | ||
| find "$BASEDIR" -maxdepth 4 \ | ||
| -path "$BASEDIR/buildscripts/deps-packaging" -prune -o \ | ||
| \( -name '*.deb' -o -name '*.rpm' -o -name '*.pkg.tar.gz' \) -print \ | ||
| -exec cp {} /output/ \; | ||
|
|
||
| echo "" | ||
| echo "=== Build complete ===" | ||
| ls -lh /output/ | ||
This file contains hidden or 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,117 @@ | ||
| # build-in-container | ||
|
|
||
| Build CFEngine packages inside Docker containers using build scripts. Requires | ||
| only Docker and Python 3 on the host. | ||
|
|
||
| ## Quick start | ||
|
|
||
| ```bash | ||
| # Build a community agent .deb for Ubuntu 22 | ||
| ./build-in-container.py --platform ubuntu-22 --project community --role agent --build-type DEBUG | ||
|
|
||
| # Build a nova hub release package for Debian 12 | ||
| ./build-in-container.py --platform debian-12 --project nova --role hub --build-type RELEASE | ||
| ``` | ||
|
|
||
| In the examples above, we run the script from inside `buildscripts/` (with | ||
| `buildscripts` as our current working directory). This is not required — if not | ||
| specified, defaults will: | ||
|
|
||
| - Look for sources relative to the script (parent directory of | ||
| `build-in-container.py`). | ||
| - Place cache files in the user's home directory | ||
| (`~/.cache/cfengine/buildscripts`). | ||
| - Use the current working directory for output packages (`./output/`). | ||
|
|
||
| ## Usage | ||
|
|
||
| ``` | ||
| ./build-in-container.py --platform PLATFORM --project PROJECT --role ROLE --build-type TYPE [OPTIONS] | ||
| ``` | ||
|
|
||
| ### Required arguments | ||
|
|
||
| | Option | Description | | ||
| |--------------------|-------------------------------------------------| | ||
| | `--platform` | Target platform (e.g. `ubuntu-22`, `debian-12`) | | ||
| | `--project` | `community` or `nova` | | ||
| | `--role` | `agent` or `hub` | | ||
| | `--build-type` | `DEBUG` or `RELEASE` | | ||
|
|
||
| ### Optional arguments | ||
|
|
||
| | Option | Default | Description | | ||
| |--------------------|----------------------------------|-------------------------------------------------------------| | ||
| | `--output-dir` | `./output` | Where to write output packages | | ||
| | `--cache-dir` | `~/.cache/cfengine/buildscripts` | Dependency cache directory | | ||
| | `--build-number` | `1` | Build number for package versioning | | ||
| | `--version` | auto | Override version string | | ||
| | `--rebuild-image` | | Force rebuild of Docker image (bypasses Docker layer cache) | | ||
| | `--shell` | | Drop into a bash shell inside the container for debugging | | ||
| | `--list-platforms` | | List available platforms and exit | | ||
| | `--source-dir` | parent of `buildscripts/` | Root directory containing repos | | ||
|
|
||
| ## Supported platforms | ||
|
|
||
| | Name | Base image | | ||
| |-------------|----------------| | ||
| | `ubuntu-20` | `ubuntu:20.04` | | ||
| | `ubuntu-22` | `ubuntu:22.04` | | ||
| | `ubuntu-24` | `ubuntu:24.04` | | ||
| | `debian-11` | `debian:11` | | ||
| | `debian-12` | `debian:12` | | ||
|
|
||
| Adding a new Debian/Ubuntu platform requires only a new entry in the `PLATFORMS` | ||
| dict in `build-in-container.py`. Adding a non-debian based platform (e.g., | ||
| RHEL/CentOS) requires a new `container/Dockerfile.rhel` plus platform entries. | ||
|
|
||
| ## How it works | ||
|
|
||
| The system has three components: | ||
|
|
||
| 1. **`build-in-container.py`** (Python) -- the orchestrator that runs on the host. | ||
| Parses arguments, builds the Docker image, and launches the container with | ||
| the correct mounts and environment variables. | ||
|
|
||
| 2. **`build-in-container-inner.sh`** (Bash) -- runs inside the container. Copies | ||
| source repos from the read-only mount, then calls the existing build scripts | ||
| in order. | ||
|
|
||
| 3. **`container/Dockerfile.debian`** -- parameterized Dockerfile shared by all | ||
| Debian/Ubuntu platforms via a `BASE_IMAGE` build arg. | ||
|
|
||
| ### Container mounts | ||
|
|
||
| | Host path | Container path | Mode | Purpose | | ||
| |------------------------------------------|-------------------------------------------|------------|---------------------------------------| | ||
| | Source repos (parent of `buildscripts/`) | `/srv/source` | read-only | Protects host repos from modification | | ||
| | `~/.cache/cfengine/buildscripts/` | `/home/builder/.cache/buildscripts_cache` | read-write | Dependency cache shared across builds | | ||
| | `./output/` | `/output` | read-write | Output packages copied here | | ||
|
|
||
| ### Build steps | ||
|
|
||
| The inner script runs these steps in order: | ||
|
|
||
| 1. **autogen** -- runs `autogen.sh` in each repo | ||
| 2. **install-dependencies** -- builds and installs bundled dependencies | ||
| 3. **mission-portal-deps** -- (hub only) installs PHP/npm/LESS assets | ||
| 4. **configure** -- runs `./configure` with platform-appropriate flags | ||
| 5. **compile** -- compiles and installs to the dist tree | ||
| 6. **package** -- creates `.deb` or `.rpm` packages | ||
|
|
||
| ## Docker image management | ||
|
|
||
| The Docker image is tagged `cfengine-builder-{platform}` and rebuilt | ||
| automatically when the Dockerfile changes (tracked via a content hash stored as | ||
| an image label). Use `--rebuild-image` to force a full rebuild bypassing the | ||
| Docker layer cache (useful when upstream packages change). | ||
|
|
||
| ## Debugging | ||
|
|
||
| ```bash | ||
| # Drop into a shell inside the container | ||
| ./build-in-container.py --platform ubuntu-22 --project community --role agent --build-type DEBUG --shell | ||
| ``` | ||
|
|
||
| The shell session has the same mounts and environment as a build run. The | ||
| container is ephemeral (`--rm`), so any changes are lost on exit. |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like we should rename
build-scriptsfolder to steps / build-steps 😅.