Skip to content

Commit 3aa20e1

Browse files
authored
Merge pull request #23 from halfline/transitive-deps
reverse-dependencies: Compute indirect dependents
2 parents 4536ba0 + b001572 commit 3aa20e1

File tree

8 files changed

+3925
-27
lines changed

8 files changed

+3925
-27
lines changed

Makefile

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
.PHONY: help
44
.PHONY:
55
.PHONY: # Manage container image
6-
.PHONY: clean build config
6+
.PHONY: clean build debug-build config
77
.PHONY:
88
.PHONY: # Manage MCP server for JIRA
99
.PHONY: stop-mcp-atlassian run-mcp-atlassian logs-mcp-atlassian
@@ -20,8 +20,12 @@
2020
.PHONY: rebase-package
2121
.PHONY: reverse-dependencies
2222
.PHONY: test-package
23+
.PHONY: test-reverse-dependencies
2324
.PHONY: triage-issue
2425
.PHONY: backport-fix
26+
.PHONY:
27+
.PHONY: # Development and testing
28+
.PHONY: check check-find-package-dependents-script
2529

2630
## Defaults
2731
COMPOSE ?= podman compose
@@ -35,19 +39,30 @@ rebase-package: PACKAGE ?= cockpit
3539
rebase-package: VERSION ?= 339
3640
rebase-package: JIRA_ISSUES ?= "RHEL-123"
3741

42+
reverse-dependencies: ARCH ?= x86_64
3843
reverse-dependencies: PACKAGE ?= podman
3944

4045
test-package: PACKAGE ?= podman
4146
test-package: DIST_GIT_BRANCH ?= c10s
4247
test-package: GIT_URL ?= https://gitlab.com/redhat/centos-stream/rpms
4348
test-package: RPM_COMPOSE ?= CentOS-Stream-10
4449

50+
test-reverse-dependencies: ARCH ?= x86_64
51+
test-reverse-dependencies: PACKAGE ?= podman
52+
test-reverse-dependencies: CHANGE ?=
53+
test-reverse-dependencies: DIST_GIT_BRANCH ?= c10s
54+
test-reverse-dependencies: GIT_URL ?= https://gitlab.com/redhat/centos-stream/rpms
55+
test-reverse-dependencies: RPM_COMPOSE ?= CentOS-Stream-10
56+
4557
triage-issue: ISSUE ?= RHEL-78418
4658

4759
## Operations
4860
build:
4961
$(COMPOSE) build
5062

63+
debug-build:
64+
BUILD_TARGET=debug $(COMPOSE) build
65+
5166
run-mcp-atlassian:
5267
$(COMPOSE) up -d mcp-atlassian
5368

@@ -129,6 +144,7 @@ reverse-dependencies:
129144
$(COMPOSE) run --rm \
130145
--entrypoint /bin/sh goose \
131146
-c "/usr/local/bin/goose run --recipe recipes/reverse-dependencies.yaml \
147+
--params arch=$(ARCH) \
132148
--params package=$(PACKAGE)"
133149

134150
test-package:
@@ -140,6 +156,17 @@ test-package:
140156
--params dist_git_branch=$(DIST_GIT_BRANCH) \
141157
--params compose=$(RPM_COMPOSE)"
142158

159+
test-reverse-dependencies:
160+
$(COMPOSE) run --rm \
161+
--entrypoint /bin/sh goose \
162+
-c "/usr/local/bin/goose run --recipe recipes/test-reverse-dependencies.yaml \
163+
--params arch=$(ARCH) \
164+
--params package=$(PACKAGE) \
165+
--params change='$(CHANGE)' \
166+
--params git_url=$(GIT_URL) \
167+
--params dist_git_branch=$(DIST_GIT_BRANCH) \
168+
--params compose=$(RPM_COMPOSE)"
169+
143170
config: GLOBAL_TEMPLATE = templates/compose.env
144171
config: SECRET_TEMPLATES = $(filter-out $(GLOBAL_TEMPLATE), $(wildcard templates/*))
145172
config:
@@ -151,10 +178,16 @@ clean:
151178
$(COMPOSE) down
152179
podman volume prune -f
153180

181+
check: check-find-package-dependents-script
182+
183+
check-find-package-dependents-script:
184+
cd scripts && python tests/test-find-package-dependents.py
185+
154186
help:
155187
@echo "Available targets:"
156188
@echo " config - Copy config templates to .secrets/ and .env"
157189
@echo " build - Build all images"
190+
@echo " debug-build - Build all images and rebuild goose from source"
158191
@echo " run-mcp-atlassian - Start Atlassian MCP server in background"
159192
@echo " stop-mcp-atlassian - Stop Atlassian MCP server"
160193
@echo " logs-mcp-atlassian - Show Atlassian MCP server logs"
@@ -164,5 +197,7 @@ help:
164197
@echo " run-goose - Run goose interactively"
165198
@echo " run-goose-bash - Run goose with bash shell"
166199
@echo " test-package - Submit package testing request to testing farm"
200+
@echo " test-reverse-dependencies - Test all reverse dependencies of a package"
167201
@echo " <recipe> - To run the recipes/<recipe>.yaml"
202+
@echo " check - Run all development tests"
168203
@echo " clean - Stop all services and clean volumes"

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ If you need to change the llm provider and model, they are stored in the Goose c
1717

1818
## Build
1919

20-
`make build`
21-
20+
- `make build` This builds the goose image using an officially released goose binaries
21+
- `make debug-build` This builds the goose image using a rebuild of goose from git. `*.patch` in `goose-container/` are applied to the git tree before building.
2222
## Run Goose - interactively - with the MCP Atlassian server
2323

2424
To run goose interactively, don't be tempted to run `podman compose up` or similar, because input from your terminal might not be directed to the Goose container. Instead use:

compose.yaml

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,19 @@ services:
3737
mcp-testing-farm: { condition: service_healthy }
3838
image: goose-container
3939
build:
40-
context: ./goose-container
41-
dockerfile: Containerfile
40+
context: .
41+
dockerfile: ./goose-container/Containerfile
42+
target: ${BUILD_TARGET:-production}
43+
args:
44+
BASE_IMAGE: registry.fedoraproject.org/fedora@sha256:3b94b23378c64850f5e2a83d0da4471fab0716d35a2662a794cfeb63b5e6fccd
45+
GOOSE_VERSION: v1.1.3
4246
env_file:
4347
- .secrets/goose.env
4448
volumes:
4549
- home-goose-persistent:/home/goose
4650
- ./goose-recipes:/home/goose/recipes:ro,z
4751
- ./goose-container/goose-config.yaml:/home/goose/.config/goose/config.yaml:ro,z
52+
- ./scripts:/home/goose/scripts:ro,z
4853
stdin_open: true
4954
tty: true
5055
restart: "no"

goose-container/Containerfile

Lines changed: 97 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,107 @@
1-
FROM fedora:42
1+
# This Containerfile contains several stages:
2+
#
3+
# runtime-platform: Fedora base image with the required dependencies
4+
# added on top to run goose.
5+
#
6+
# production: Official goose builds installed on top of runtime-platform
7+
#
8+
# source-build: Fedora base image with goose built from
9+
# git on top. It applies all the patches in goose-container
10+
# as well. This is useful for instrumenting goose with
11+
# extra debug logging, etc.
12+
#
13+
# debug: Custom built Goose installed on top of runtime-platform
14+
# This is useful for trying out the instrumented goose builds.
215

3-
RUN dnf install -y libxcb python3 gh glab rpmbuild spectool rpmlint centpkg
16+
ARG BASE_IMAGE=registry.fedoraproject.org/fedora:42
17+
ARG GOOSE_VERSION=v1.1.3
418

5-
RUN curl -fsSL https://github.com/block/goose/releases/download/stable/download_cli.sh | GOOSE_BIN_DIR=/usr/local/bin CONFIGURE=false bash
19+
#
20+
# runtime-platform: Fedora base image with the required dependencies to added to
21+
# run goose.
22+
#
23+
FROM ${BASE_IMAGE} AS runtime-platform
624

7-
RUN useradd -m -G wheel goose && echo '%wheel ALL=(ALL) NOPASSWD: ALL' > /etc/sudoers.d/wheel-nopasswd
25+
RUN dnf install -y \
26+
libxcb \
27+
python3 \
28+
gh \
29+
glab \
30+
rpmbuild \
31+
spectool \
32+
rpmlint \
33+
centpkg \
34+
wget
835

9-
RUN mkdir -p /home/goose/.config/goose /home/goose/recipes
10-
COPY ./goose-config.yaml /home/goose/.config/goose/config.yaml
11-
RUN chown -R goose:goose /home/goose/.config
36+
RUN useradd -m -G wheel goose \
37+
&& echo '%wheel ALL=(ALL) NOPASSWD: ALL' > /etc/sudoers.d/wheel-nopasswd \
38+
&& mkdir -p /home/goose/.config/goose /home/goose/recipes /home/goose/scripts \
39+
&& chown -R goose:goose /home/goose
40+
41+
COPY --chown=goose:goose \
42+
goose-container/goose-config.yaml \
43+
/home/goose/.config/goose/config.yaml
44+
COPY --chown=goose:goose \
45+
goose-recipes/ \
46+
/home/goose/recipes/
47+
COPY --chown=goose:goose \
48+
scripts/ \
49+
/home/goose/scripts/
1250

1351
USER goose
1452
WORKDIR /home/goose
1553

54+
#
55+
# production: Official goose builds installed on top of runtime-platform
56+
#
57+
FROM runtime-platform AS production
58+
59+
USER root
60+
61+
RUN curl -fsSL https://github.com/block/goose/releases/download/${GOOSE_VERSION}/download_cli.sh | \
62+
GOOSE_BIN_DIR=/usr/local/bin CONFIGURE=false bash
63+
64+
USER goose
65+
66+
ENTRYPOINT ["/usr/local/bin/goose"]
67+
68+
FROM ${BASE_IMAGE} AS source-build
69+
70+
RUN dnf install -y \
71+
git \
72+
rust \
73+
cargo \
74+
protobuf-compiler \
75+
protobuf-devel \
76+
libxcb-devel
77+
78+
ARG GOOSE_REPO=https://github.com/block/goose.git
79+
ARG GOOSE_VERSION
80+
81+
WORKDIR /usr/src
82+
RUN git clone --depth 1 \
83+
--branch "${GOOSE_VERSION}" \
84+
"${GOOSE_REPO}" \
85+
goose-src
86+
87+
WORKDIR /usr/src/goose-src
88+
COPY goose-container/*.patch patches/
89+
90+
RUN cargo fetch --locked
91+
92+
RUN git config --global user.email "[email protected]" \
93+
&& git config --global user.name "RHEL Packaging Agent"
94+
95+
RUN cargo build --release -p goose-cli
96+
97+
RUN git am patches/*.patch \
98+
&& cargo build --release -p goose-cli
99+
100+
#
101+
# debug: Custom built Goose installed on top of runtime-platform
102+
#
103+
FROM runtime-platform AS debug
104+
COPY --from=source-build /usr/src/goose-src/target/release/goose /usr/local/bin/goose
105+
16106
ENTRYPOINT ["/usr/bin/bash"]
17107
CMD ["-c", ". ~/.bashrc; /usr/local/bin/goose"]
Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,49 @@
11
version: 0.1.0
22
title: "Find reverse dependencies of an RPM package"
3-
description: "Find the reverse dependencies of the {{ package }} package. That is all packages that directly or transitively depend on the {{ package }} package."
3+
description: "Find the reverse dependencies of the {{ package }} package for the architecture {{ arch }}. That is all packages that directly or transitively depend on the {{ package }} package on the architecture {{ arch }}."
44

55
instructions: |
6-
A couple of rules that you must follow and useful information for you:
7-
* Work only in a temporary directory that you can create with the mktemp tool.
8-
* Run `dnf repoquery --whatdepends` to determine the direct reverse dependencies of a package.
9-
* Download the RPM .repo files with curl and make sure to ignore certificates.
10-
* Before executing any command, print the plan and the steps you want to take.
6+
* Before starting, create a temporary directory via mktemp that will be your working directory.
7+
* For clarity, always use full, absolute paths for file I/O.
8+
* Run all steps in a single shell command, so they share an environment
119
1210
parameters:
11+
- key: arch
12+
input_type: string
13+
requirement: required
14+
description: The architecture of the platform to look for dependencies in
1315
- key: package
1416
input_type: string
1517
requirement: required
1618
description: The package for which to find reverse dependencies.
1719

1820
prompt: |
19-
You are an AI agent to list all direct and transitive reverse dependencies of a given RPM package. As input you will receive the name of the package. A reverse dependency package is one that depends on the input package. As output you must print one list for the direct reverse dependencies, and another list for the transitive reverse dependencies. Follow the below steps in the given order:
21+
You are an AI agent to list direct and transitive reverse dependencies of a given RPM package. As input, receive the package name and target architecture. Output two files and print their contents: `{{ package }}-reverse-deps.txt` and `{{ package }}-all-reverse-deps.json`.
22+
23+
Steps:
24+
25+
1. Save the location of the `scripts/` directory for later use in an environment variable, and then create and enter a unique working directory:
26+
```bash
27+
scriptsdir=$(pwd)/scripts
28+
workingdir=$(realpath $(mktemp -d "{{ package }}.XXXXX"))
29+
cd "$workingdir"
30+
```
31+
32+
2. Define the repository URL:
33+
```bash
34+
baseurl=http://download.devel.redhat.com/rhel-10/nightly/RHEL-10/latest-RHEL-10/
35+
```
2036
21-
1. First, remove all other .repo files in /etc/yum.repos.d/. That will implicitly disable all of them.
37+
3. Query direct-only reverse dependencies as a flat list by running the helper script:
38+
```bash
39+
$scriptsdir/find-package-dependents.py --base-url $baseurl --format plain '{{ package }}' \
40+
--output-file "$workingdir/{{ package }}-reverse-deps.txt"
41+
```
2242
23-
2. Then download the RPM .repo file from the following source: https://download.devel.redhat.com/rhel-10/nightly/RHEL-10/latest-RHEL-10/repofile.repo
24-
* Use curl and the -k flag to ignore certificates.
25-
* If you face errors during the download, print them and exit.
26-
* Do not attempt to download any other file.
27-
* Copy the file to the /etc/yum/repos.d directory.
43+
4. Query all direct and indirect reverse dependencies as JSON by running the helper script:
44+
```bash
45+
$scriptsdir/find-package-dependents.py --base-url $baseurl --all --format=json '{{ package }}' \
46+
--output-file "$workingdir/{{ package }}-all-reverse-deps.json"
47+
```
2848
29-
# TODO: experiment with this first and then tackle transitive dependencies later
30-
2. Find the direct reverse dependencies of {{ package }} and print them in a pretty list.
49+
5. Read the output files "$workingdir/{{ package }}-reverse-deps.txt" and "$workingdir/{{ package }}-all-reverse-deps.json" and read them back to me.
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
version: 0.1.0
2+
title: "Test reverse dependencies of an RPM package"
3+
description: >-
4+
Find all reverse dependencies of the {{ package }} package for architecture {{ arch }},
5+
convert them to source packages, and run Testing Farm tests for each source package
6+
on branch {{ dist_git_branch }} against compose {{ compose }}.
7+
8+
instructions: |
9+
* Before starting, create a temporary directory via mktemp that will be your working directory.
10+
* For clarity, always use full, absolute paths for file I/O.
11+
* Run all steps that need to share an environment in a single shell command session.
12+
* First find all reverse dependencies and convert them to source packages.
13+
* Then submit Testing Farm requests for the selected subset of those source packages.
14+
15+
parameters:
16+
- key: arch
17+
input_type: string
18+
requirement: required
19+
description: The architecture of the platform to look for dependencies in
20+
- key: package
21+
input_type: string
22+
requirement: required
23+
description: The package for which to find reverse dependencies and test them
24+
- key: git_url
25+
input_type: string
26+
requirement: required
27+
description: Base URL of the dist-git project
28+
- key: baseurl
29+
input_type: string
30+
requirement: optional
31+
default: http://download.devel.redhat.com/rhel-10/nightly/RHEL-10/latest-RHEL-10/
32+
description: Location of repos to query for dependencies
33+
- key: dist_git_branch
34+
input_type: string
35+
requirement: required
36+
description: Branch in the dist-git repository
37+
- key: compose
38+
input_type: string
39+
requirement: required
40+
description: Testing Farm compose to use
41+
- key: max_results
42+
input_type: string
43+
requirement: optional
44+
default: 50
45+
description: Maximum number of reverse dependencies to fetch from repeated dnf queries
46+
- key: number_of_requests
47+
input_type: string
48+
requirement: optional
49+
default: 10
50+
description: The number of testing farm requests to initiate
51+
- key: change
52+
input_type: string
53+
requirement: optional
54+
default: (no relevant changes)
55+
description: A pertinent change to the package relevant to which dependent tests should run
56+
57+
prompt: |
58+
You are an AI agent to find reverse dependencies of a given RPM package and test each source package. Please follow the following steps:
59+
60+
1. Query the first {{ max_results }} direct and indirect reverse dependencies as source packages along with their descriptions by running the helper script:
61+
```bash
62+
workingdir=$(mktemp "$PWD/{{ package }}.reverse-deps-tests.XXXXXX")
63+
$(pwd)/scripts/find-package-dependents.py --base-url {{ baseurl }} --all --describe --max-results {{ max_results }} --source-packages --format=plain '{{ package }}' \
64+
--filter-command 'wget --spider -q https://gitlab.com/redhat/centos-stream/rpms/$PACKAGE/-/raw/{{ dist_git_branch }}/.fmf/version' \
65+
--log-file "$workingdir/{{ package }}-logs.txt" \
66+
--verbose \
67+
--output-file "$workingdir/{{ package }}-source-deps.txt"
68+
```
69+
Read the source packages list from "$workingdir/{{ package }}-source-deps.txt" and read it back to me.
70+
71+
2. Select no more than {{ number_of_requests }} source packages from the list that would be good candidates for testing. Use your pre-existing knowledge of what the packages do, along with their provided descriptions, and how they relate to {{ package }} to make selections. Also, consider this relevant change to {{ package }} when deciding which dependents to test:
72+
73+
```text
74+
{{ change }}
75+
```
76+
77+
3. For each selected source package, submit a Testing Farm request using the git url {{ git_url }}/<source package>.git and the branch {{ dist_git_branch }} and the compose {{ compose }}.
78+
79+
4. Track the job IDs and write the results as JSON in a file called "$workingdir/jobs.json". The jobs should be of the form `[{ package: "<package-name>", jobId: "<uuid>" }, ... ]`. Use those object properties specifically and exactly, so it can be machine parsed later.
80+
81+
5. Finally, as a last step, Tell me where $workingdir is on the filesystem and read back "$workingdir/jobs.json" to me. Do not clean up the contents of $workingdir. They will be harvested as workflow artifacts.

0 commit comments

Comments
 (0)