Skip to content

Commit f06ef01

Browse files
authored
Merge branch 'main' into telemetry-component-job-template
2 parents 70657f8 + fb5b90c commit f06ef01

13 files changed

Lines changed: 1054 additions & 25 deletions

File tree

‎build.sh‎

Lines changed: 425 additions & 17 deletions
Large diffs are not rendered by default.

‎docs/developer-guide.md‎

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,28 @@ These auto-cloned repos are tracked and **removed automatically on exit**
9393
(via an EXIT trap), so `src/` directories stay clean in the repo (only a
9494
`.gitkeep` is committed).
9595

96+
Git source caching is optional and is separate from the package caches
97+
described below. Enable it for local source operations with:
98+
99+
```bash
100+
SOURCE_CACHE=true STREAM=master tox -ebuild -- nova
101+
```
102+
103+
When enabled, repository objects are retained as bare repositories under
104+
`.tmp/source_cache/<host>/<organization>/<repository>.git`. Branch and tag refs
105+
are refreshed once per repository in each `build.sh` invocation, then a fast
106+
local clone is materialized at the exact pinned commit. The disposable clone is
107+
removed on exit while the bare cache remains for later invocations. Set
108+
`SOURCE_CACHE_DIR` to override the cache location. Source caching defaults to
109+
`false`; direct temporary clones retain the previous behavior when disabled.
110+
111+
To discard all cached Git objects and make the next cached source operation
112+
fetch them again, remove the cache directory:
113+
114+
```bash
115+
rm -rf .tmp/source_cache
116+
```
117+
96118
If a checkout already exists in `src/` (e.g., a local development clone),
97119
`build.sh` uses it as-is and does **not** remove it on exit. This lets you
98120
work on a local branch without `build.sh` overwriting it.
@@ -288,6 +310,67 @@ STREAM=stable tox -ecustom -- build watcher/watcher-base
288310
tox -ecustom -- list
289311
```
290312

313+
### Optional local package caches
314+
315+
A developer-only Compose stack under `tools/local-package-cache/` provides
316+
[Proxpi](https://github.com/EpicWink/proxpi) for Python downloads and
317+
Squid for plain-HTTP RPM repository traffic. Package caching is disabled
318+
by default and affects only local `build` and `build-parallel` actions when
319+
`LOCAL_PACKAGE_CACHE=true`. Normal builds and Konflux builds remain unchanged.
320+
The cache-service lifecycle is intentionally separate from `build.sh`.
321+
322+
`podman compose` requires a Compose provider. On CentOS Stream, install and
323+
verify `podman-compose` with:
324+
325+
```bash
326+
sudo dnf install podman-compose
327+
podman compose version
328+
```
329+
330+
Start the services, verify them, and opt a build into package caching:
331+
332+
```bash
333+
LOCAL_CACHE_BIND_ADDRESS=0.0.0.0 \
334+
podman compose -f tools/local-package-cache/compose.yaml up -d
335+
podman compose -f tools/local-package-cache/compose.yaml ps
336+
LOCAL_PACKAGE_CACHE=true STREAM=master tox -ebuild -- glance
337+
```
338+
339+
Compose creates and manages the named Proxpi and Squid volumes declared
340+
in `compose.yaml`; do not create those volumes manually. They persist downloaded
341+
content across container replacement and ordinary `down`/`up` cycles.
342+
343+
Build containers reach the published ports through
344+
`host.containers.internal`. Rootless containers generally cannot reach services
345+
bound only to host loopback, so the example publishes on all host interfaces.
346+
Binding to `0.0.0.0` can expose unauthenticated cache services to the local
347+
network; use host firewall rules or set `LOCAL_CACHE_BIND_ADDRESS` to a more
348+
specific reachable host address when possible. The Compose file defaults to
349+
`127.0.0.1` for safety when no address is specified.
350+
351+
The build fails before invoking Buildah when `LOCAL_PACKAGE_CACHE=true` and
352+
either service is unavailable. Endpoint overrides are available through
353+
`LOCAL_PYPI_INDEX_URL`, `LOCAL_PYPI_TRUSTED_HOST`, `LOCAL_RPM_PROXY`,
354+
`LOCAL_PYPI_HEALTH_URL`, and `LOCAL_RPM_HEALTH_URL`.
355+
356+
Stop the services while retaining downloaded packages:
357+
358+
```bash
359+
podman compose -f tools/local-package-cache/compose.yaml down
360+
```
361+
362+
Delete the services and their package-cache volumes for a cold package fetch:
363+
364+
```bash
365+
podman compose -f tools/local-package-cache/compose.yaml down -v
366+
```
367+
368+
This proof of concept caches external downloads only. It does not cache wheels
369+
built from the OpenStack source checkouts. HTTPS repositories normally pass
370+
through without TLS interception. Squid fetches the HTTPS origin behind
371+
`mirror.stream.centos.org` itself so the existing HTTP repository URLs remain
372+
cacheable.
373+
291374
### Initial setup
292375

293376
1. Create `containers/<project>/sources.txt` with entries for each stream. Add
@@ -437,6 +520,37 @@ validation, builds, publication, result generation, and cleanup target that
437520
host explicitly. The Zuul executor controls Ansible but does not perform those
438521
mutations.
439522

523+
The provider copies the RDO base job's `/etc/pip.conf` into a job-local file
524+
and mounts it into Buildah so Python downloads use the provider mirror. It also
525+
can run an ephemeral Squid container directly with Podman. Squid caches direct
526+
upstream HTTP traffic or can sit in front of the provider's CentOS mirror. The
527+
cache is published on the disposable builder and Buildah RUN steps reach it through
528+
`host.containers.internal`. Proxy values are passed as build arguments so
529+
host-side base-image pulls are not routed through the package cache. The cache
530+
intentionally listens without authentication on all interfaces of the
531+
disposable CI builder. Plain-HTTP CentOS Stream requests can be remapped to the
532+
provider's CentOS mirror. Otherwise, Squid rewrites plain-HTTP CentOS requests
533+
to the upstream HTTPS origin before fetching them, without intercepting client
534+
TLS. The job does not consume host RPM repository files or require
535+
`podman-compose`. Post-run cleanup
536+
removes the cache container, its volumes, and generated configuration.
537+
Persistent source caching is explicitly disabled
538+
because Zuul already stages speculative source trees and the builder is
539+
disposable.
540+
541+
`s2i_ci_use_provider_pip_mirror` controls whether the parent-provided
542+
`pip.conf` is mounted, `s2i_ci_enable_rpm_cache` controls the RPM proxy, and
543+
`s2i_ci_rpm_cache_use_provider_mirror` controls its optional CentOS Stream
544+
backend remap. Disabling Squid leaves RPM repository access unchanged;
545+
the provider mirror still applies to Python downloads when its pip option is
546+
enabled. The content-provider currently disables the RPM backend remap because
547+
the Vexxhost mirror does not carry the CentOS Stream 10 SIG repositories used
548+
by these images. Squid therefore caches their original repository URLs.
549+
Collapsed forwarding combines concurrent requests for the same object, and
550+
`repomd.xml` remains fresh for the two-hour job despite DNF cache-bypass
551+
headers. Squid access and error logs are staged under
552+
`zuul-output/logs/squid/` for troubleshooting.
553+
440554
In this repository the provider defaults to `all`, so every maintained image
441555
is built from its exact `sources.txt` pins. A child job can set `s2i_ci_images`
442556
to an explicit list of image targets; the provider resolves the selection

‎playbooks/container-ci/shared/run.yaml‎

Lines changed: 50 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,25 @@
77
s2i_ci_registry_connection_file: >-
88
{{ s2i_ci_output_dir }}/.s2i-ci-registry-connection.json
99
s2i_ci_workspace_root: "{{ zuul_user_dir | default(ansible_user_dir) }}"
10+
s2i_ci_package_cache_dir: >-
11+
{{ ansible_user_dir }}/.cache/s2i-ci-package-cache
12+
s2i_ci_pip_config_file: "{{ s2i_ci_package_cache_dir }}/pip.conf"
13+
s2i_ci_package_proxy: http://host.containers.internal:3142
14+
s2i_ci_mirror_fqdn: >-
15+
mirror.{{ nodepool.region | lower }}.{{ nodepool.cloud | lower }}.rdoproject.org
16+
s2i_ci_build_no_proxy: >-
17+
{{
18+
(
19+
['localhost', '127.0.0.1', 'host.containers.internal',
20+
s2i_ci_registry.public_host]
21+
+ ([s2i_ci_mirror_fqdn]
22+
if ((s2i_ci_use_provider_pip_mirror | default(true) | bool) or
23+
((s2i_ci_enable_rpm_cache | default(true) | bool) and
24+
(s2i_ci_rpm_cache_use_provider_mirror |
25+
default(true) | bool)))
26+
else [])
27+
) | join(',')
28+
}}
1029
1130
tasks:
1231
- name: Default optional selective provider inputs
@@ -210,6 +229,7 @@
210229
environment:
211230
STREAM: "{{ s2i_ci_stream }}"
212231
REQUIREMENTS_SRC: "{{ s2i_ci_requirements_src | default('') }}"
232+
SOURCE_CACHE: "false"
213233
register: s2i_ci_sync_locks
214234
changed_when: true
215235
always:
@@ -222,20 +242,43 @@
222242
{{ s2i_ci_sync_locks.stdout | default('') }}
223243
{{ s2i_ci_sync_locks.stderr | default('') }}
224244
245+
- name: Prepare the build command environment
246+
ansible.builtin.set_fact:
247+
s2i_ci_build_environment: >-
248+
{{
249+
{
250+
'STREAM': s2i_ci_stream,
251+
'REGISTRY': s2i_ci_registry.endpoint,
252+
'NAMESPACE': s2i_ci_namespace,
253+
'TAG': s2i_ci_tag,
254+
'PARALLEL': s2i_ci_parallel | string,
255+
'BUILD_LOGS_DIR': s2i_ci_log_dir,
256+
'SOURCE_CACHE': 'false'
257+
}
258+
| combine(
259+
{'BUILD_PIP_CONFIG_FILE': s2i_ci_pip_config_file}
260+
if s2i_ci_use_provider_pip_mirror | default(true) | bool
261+
else {}
262+
)
263+
| combine(
264+
{
265+
'BUILD_HTTP_PROXY': s2i_ci_package_proxy,
266+
'BUILD_HTTPS_PROXY': s2i_ci_package_proxy,
267+
'BUILD_NO_PROXY': s2i_ci_build_no_proxy
268+
}
269+
if s2i_ci_enable_rpm_cache | default(true) | bool
270+
else {}
271+
)
272+
}}
273+
225274
- name: Build selected images
226275
ansible.builtin.command:
227276
argv:
228277
- "{{ s2i_ci_container_repo }}/build.sh"
229278
- build-parallel
230279
- "{{ s2i_ci_target_expression }}"
231280
chdir: "{{ s2i_ci_container_repo }}"
232-
environment:
233-
STREAM: "{{ s2i_ci_stream }}"
234-
REGISTRY: "{{ s2i_ci_registry.endpoint }}"
235-
NAMESPACE: "{{ s2i_ci_namespace }}"
236-
TAG: "{{ s2i_ci_tag }}"
237-
PARALLEL: "{{ s2i_ci_parallel | string }}"
238-
BUILD_LOGS_DIR: "{{ s2i_ci_log_dir }}"
281+
environment: "{{ s2i_ci_build_environment }}"
239282
register: s2i_ci_build
240283
changed_when: s2i_ci_build.rc == 0
241284

‎playbooks/container-ci/zuul/post.yaml‎

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
vars:
66
s2i_ci_output_dir: "{{ ansible_user_dir }}/zuul-output"
77
s2i_ci_log_dir: "{{ s2i_ci_output_dir }}/logs/container-build"
8+
s2i_ci_squid_log_dir: >-
9+
{{ ansible_user_dir }}/.cache/s2i-ci-package-cache/squid
810
911
tasks:
1012
- name: Ensure the container build log directory exists
@@ -14,6 +16,21 @@
1416
mode: "0755"
1517
failed_when: false
1618

19+
- name: Stage Squid file logs
20+
when: s2i_ci_enable_rpm_cache | default(true) | bool
21+
block:
22+
- name: Run the trusted output staging role
23+
ansible.builtin.include_role:
24+
name: stage-output
25+
vars:
26+
stage_dir: "{{ s2i_ci_output_dir }}"
27+
zuul_copy_output:
28+
"{{ s2i_ci_squid_log_dir }}": logs
29+
rescue:
30+
- name: Report non-fatal Squid log staging failure
31+
ansible.builtin.debug:
32+
msg: Squid file log staging failed; cleanup will continue
33+
1734
- name: Collect registry and build container logs
1835
block:
1936
- name: Run the trusted container log collection role
@@ -24,7 +41,7 @@
2441
rescue:
2542
- name: Report non-fatal Zuul container log collection failure
2643
ansible.builtin.debug:
27-
msg: Container log collection failed; registry cleanup will continue
44+
msg: Container log collection failed; cache cleanup will continue
2845

2946
- name: Remove exact workflow images
3047
ansible.builtin.import_playbook: ../shared/cleanup-images.yaml
@@ -45,6 +62,20 @@
4562
changed_when: s2i_ci_removed_registry.stdout | length > 0
4663
failed_when: false
4764

65+
- name: Remove the RPM package-cache container and anonymous volumes
66+
ansible.builtin.command:
67+
argv: [podman, rm, --force, --volumes, s2i_squid]
68+
register: s2i_ci_removed_package_cache
69+
changed_when: s2i_ci_removed_package_cache.rc == 0
70+
failed_when: false
71+
72+
- name: Remove the job-local package-cache configuration
73+
become: true
74+
ansible.builtin.file:
75+
path: "{{ ansible_user_dir }}/.cache/s2i-ci-package-cache"
76+
state: absent
77+
failed_when: false
78+
4879
- name: Remove persisted registry connection data
4980
ansible.builtin.file:
5081
path: "{{ s2i_ci_registry_connection_file }}"

‎playbooks/container-ci/zuul/pre.yaml‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
- name: Prepare shared build tools
33
ansible.builtin.import_playbook: ../shared/prepare-host.yaml
44

5+
- name: Prepare package caches for container builds
6+
ansible.builtin.import_playbook: prepare-mirrors.yaml
7+
58
- name: Deploy a plain Docker registry on the builder
69
hosts: builder
710
vars:

0 commit comments

Comments
 (0)