-
Notifications
You must be signed in to change notification settings - Fork 40
ENT-14361, ENT-14362: Preparing build scripts for running build-in-container in Jenkins #2395
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
Merged
larsewi
merged 20 commits into
cfengine:master
from
larsewi:container-packages-build-host
Aug 12, 2026
Merged
Changes from 6 commits
Commits
Show all changes
20 commits
Select commit
Hold shift + click to select a range
a6334c1
Fixed empty $my_dir outside the centos-7 branch
larsewi f20c738
Moved the pinned SSH host keys into ci/known_hosts
larsewi dddcd8b
Added a docker-host role to setup-ci-host.sh
larsewi 805a0b9
Now uses same labels as testing-pr for buildcache
larsewi d96122e
Stopped syncing stale revision files into the container
larsewi e8a0dc2
Added --sftp-key to reach the remote dependency cache
larsewi 0242ae4
build-in-container.md: made it more concise and less of a maintanance…
larsewi 37a370d
Put built packages in a directory named after the label
larsewi 8e4b327
Passed check explicitly to subprocess.run
larsewi 3767869
Used max instead of sorting to find the newest image tag
larsewi 5115f0e
Stopped building the source tarballs in every platform build
larsewi 13a2b74
Added an image for building the source tarballs
larsewi e4a7a61
Stopped syncing output directories into the container
larsewi 38bbb2c
Added --tarballs for building the source tarballs
larsewi 8ec2d64
Now writes a checksum list for the packages too
larsewi d1766de
Made the generic tar package reproducible
larsewi 76873f1
revision-file: moved logic checking for hash collisions to a function
larsewi 5a78f51
Gave each dependency its own revision and timestamp
larsewi 21cf501
Stopped using git -C, which rhel-7 is too old for
larsewi a76c622
Added rhel-7 to the platforms built in containers
larsewi 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
Some comments aren't visible on the classic Files Changed page.
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
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
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 |
|---|---|---|
|
|
@@ -22,6 +22,12 @@ | |
| IMAGE_REGISTRY = "ghcr.io/cfengine" | ||
| CONFIG_PATH = Path(__file__).resolve().parent / "platforms.json" | ||
|
|
||
| # Where --sftp-key is mounted. It cannot be mounted onto ~/.ssh/id_rsa directly: | ||
| # ssh rejects a key owned by neither the current user nor root, and the host file | ||
| # belongs to jenkins while the container runs as builder. The inner script copies | ||
| # it into place instead. | ||
| SFTP_KEY_PATH = "/run/secrets/sftp-cache-key" | ||
|
|
||
| # Architectures registry images are published for, unless a platform overrides | ||
| # it with an "architectures" list in platforms.json (e.g. the mingw cross-build, | ||
| # which always targets Windows x64 and only makes sense on amd64). | ||
|
|
@@ -152,22 +158,26 @@ def host_docker_arch(): | |
| return result.stdout.strip() | ||
|
|
||
|
|
||
| def image_arch(ref): | ||
| """Return the architecture of a locally-present image, or None if absent.""" | ||
| result = subprocess.run( | ||
| ["docker", "image", "inspect", "--format", "{{.Architecture}}", ref], | ||
| capture_output=True, | ||
| text=True, | ||
| ) | ||
| if result.returncode != 0: | ||
| return None | ||
| return result.stdout.strip() | ||
|
|
||
|
|
||
| def image_provides_arch(ref, arch): | ||
| """Check whether a locally-present image matches the requested arch. | ||
|
|
||
| `arch` may be a full docker platform string ("linux/arm64") or a bare | ||
| architecture ("arm64"); we compare its architecture component against the | ||
| image's own reported architecture. | ||
| """ | ||
| want = arch.rsplit("/", 1)[-1] | ||
| result = subprocess.run( | ||
| ["docker", "image", "inspect", "--format", "{{.Architecture}}", ref], | ||
| capture_output=True, | ||
| text=True, | ||
| ) | ||
| if result.returncode != 0: | ||
| return False | ||
| return result.stdout.strip() == want | ||
| return image_arch(ref) == arch.rsplit("/", 1)[-1] | ||
|
|
||
|
|
||
| def pull_image(platform_name, arch=None): | ||
|
|
@@ -345,6 +355,28 @@ def update_base_image_shas(platform_name=None): | |
| CONFIG_PATH.write_text(json.dumps(config, indent=2) + "\n") | ||
|
|
||
|
|
||
| def cache_label(platform_name, role, arch): | ||
| """Return the dependency cache namespace for a build. | ||
|
|
||
| deps-packaging/pkg-cache namespaces cached dependencies by JOB_BASE_NAME, | ||
| which a testing-pr matrix cell exports as "label=<axis value>". Building the | ||
| same string here puts container-built dependencies in the same namespace as | ||
| the ones testing-pr builds, so both jobs share buildcache. | ||
| """ | ||
| hub = "_HUB" if role == "hub" else "" | ||
| # The labels spell the architectures x86_64 and arm_64. See labels.txt. | ||
| arch_token = {"amd64": "x86_64", "arm64": "arm_64"}[arch.rsplit("/", 1)[-1]] | ||
|
|
||
| # The cross target's label carries neither an OS version nor _linux. | ||
| if get_config()[platform_name].get("cross_target"): | ||
| return f"PACKAGES{hub}_{arch_token}_mingw" | ||
|
|
||
| # Platform names are <os>-<version>, matching the labels once the separator | ||
| # is swapped, except that the labels say redhat where we say rhel. | ||
| label_os = platform_name.replace("-", "_").replace("rhel_", "redhat_") | ||
| return f"PACKAGES{hub}_{arch_token}_linux_{label_os}" | ||
|
|
||
|
|
||
| def run_container(args, image_tag, source_dir, script_dir): | ||
| """Run the build inside a Docker container.""" | ||
| output_dir = Path(args.output_dir).resolve() | ||
|
|
@@ -377,7 +409,9 @@ def run_container(args, image_tag, source_dir, script_dir): | |
| # Environment variables | ||
| # JOB_BASE_NAME is used by deps-packaging/pkg-cache to derive the cache | ||
| # label. Format: "label=<value>". Without it, all platforms share NO_LABEL. | ||
| cache_label = f"label=container_{args.platform}" | ||
| # The image's arch, not the host's: an amd64-only platform runs under | ||
| # emulation on an arm64 host, and the label has to say what it built as. | ||
| label = cache_label(args.platform, args.role, image_arch(image_tag)) | ||
| cmd.extend( | ||
| [ | ||
| "-e", | ||
|
|
@@ -396,12 +430,20 @@ def run_container(args, image_tag, source_dir, script_dir): | |
| "-e", | ||
| f"HOST_GID={os.getgid()}", | ||
| "-e", | ||
| f"JOB_BASE_NAME={cache_label}", | ||
| "-e", | ||
| "CACHE_IS_ONLY_LOCAL=yes", | ||
| f"JOB_BASE_NAME=label={label}", | ||
| ] | ||
| ) | ||
|
|
||
| # The remote dependency cache is reachable by publickey only, and pkg-cache | ||
| # aborts the build if an upload fails, so it stays off unless a key was | ||
| # passed. Note that the key is readable by everything the build runs, | ||
| # including each dependency's own build system. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Seems we should log a follow up security ticket to isolate the key to only our trusted scripts.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Any ideas how we could do this? |
||
| if args.sftp_key: | ||
| key = Path(args.sftp_key).resolve() | ||
| cmd.extend(["-v", f"{key}:{SFTP_KEY_PATH}:ro"]) | ||
| else: | ||
| cmd.extend(["-e", "CACHE_IS_ONLY_LOCAL=yes"]) | ||
|
|
||
| if args.version: | ||
| cmd.extend(["-e", f"EXPLICIT_VERSION={args.version}"]) | ||
|
|
||
|
|
@@ -473,6 +515,12 @@ def parse_args(): | |
| default=str(Path.home() / ".cache" / "cfengine" / "buildscripts"), | ||
| help="Dependency cache directory", | ||
| ) | ||
| parser.add_argument( | ||
| "--sftp-key", | ||
| dest="sftp_key", | ||
| help="Private key for the remote dependency cache. Without it the build " | ||
| "only uses the local cache under --cache-dir.", | ||
| ) | ||
| parser.add_argument( | ||
| "--rebuild-image", | ||
| action="store_true", | ||
|
|
||
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
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,16 @@ | ||
| # Pinned SSH host keys for the hosts CI connects to. Consumers grep out the | ||
| # host they need: github.com for source checkouts on an agent, and | ||
| # build-artifacts-cache for the dependency cache (used inside the build | ||
| # container and by ci/fix-buildhost.sh on the build hosts). | ||
| # | ||
| # All key types each host offers are listed, since which one is used depends on | ||
| # the client's HostKeyAlgorithms preference. | ||
| # | ||
| # ci/cfengine-build-host-setup.cf holds its own inline copy. That policy is being | ||
| # replaced by these scripts (ENT-14330), so it is not worth coupling to. | ||
| github.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl | ||
| github.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEmKSENjQEezOmxkZMy7opKgwFB9nkt5YRrYMjNuG5N87uRgg6CLrbo5wAdT/y6v0mKV0U2w0WZ2YB/++Tpockg= | ||
| github.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk= | ||
| build-artifacts-cache.cloud.cfengine.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGahpsY8Phk2+isBmuJQjjQVlh6BNL/Qetc14g26gowV | ||
| build-artifacts-cache.cloud.cfengine.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCdv55BmDmwEjN3izaL8intrSRJQglkv++TaQppopKCh5VkYuSpNj/W+x0vjxwL3+NNp4CAhOLYuGTFuUL8zz/H0kwWE06c3WjghpHS3NS1usiamVZN6uaJMGwDaq8fPB3WiiI/L5lLM8/ubXxfmta0UlVufHCiBH8pBQarAY5rdPDtITXzu56qIa3k9Ou7Si2r/1n37espzwsPxoBqVJg7BvzMV28MzxdmQpGP6puuPfi9tvYbtnF788le3jvGOc+3GOiwtXsv44y/PCJNhi7sFeUfxocuNbWXZ3x/UEfbN8IiUVZsUAuLQFeqr3pv4w28D+SvJHBMCFudygenmLc3th+typiFRmqam7UQif9Pa3e2FxX4ghTp1KNXBoCQluIk2j7wX9zXppSyUG6d7tPDzfu81lImuW34+bsZvYq+s+25vbAhSDdQe1lqG0Fdvvi+zbqrMYQuMfnInDrK52xNSZcfATWjudhmY6wiwdSS0XsBADmZsy3qf3ErdEabqQk= | ||
| build-artifacts-cache.cloud.cfengine.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBIzU5+SoC4gbtV3Wfw4oB6oMs5RYKGFCiS0lVeN4XQlAM8UjvyUUSflytf/vQEANv1OJs5vicslRn/iPlrvF8Mk= |
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
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
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.
So in order to use this it must be a file yes? Would be nice to have it flow from mystiko as content for a local developer maybe so it is never written to a file on the build host.
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.
Can you elaborate on this?