From 4b9271f11b91fb9ce80bf2a7d3fb915bf437326c Mon Sep 17 00:00:00 2001 From: Matej Focko Date: Wed, 8 Jul 2026 21:42:13 +0200 Subject: [PATCH] feat!(WIP): migrate to just Signed-off-by: Matej Focko --- AGENTS.md | 28 +-- CONTRIBUTING.md | 4 +- Makefile | 359 -------------------------------- Makefile.tests | 66 ------ README-agents.md | 32 +-- README.md | 4 +- justfile | 262 +++++++++++++++++++++++ ymir/agents/tests/e2e/README.md | 6 +- 8 files changed, 299 insertions(+), 462 deletions(-) delete mode 100644 Makefile delete mode 100644 Makefile.tests create mode 100644 justfile diff --git a/AGENTS.md b/AGENTS.md index 7835daee9..72ef49adf 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -25,13 +25,13 @@ Five agents process tasks through Redis queues (see [README-agents.md](README-ag 1. **Edit agent code** in `ymir/agents/` 2. **Run dry-run test**: ```bash - make run-triage-agent-standalone JIRA_ISSUE=RHEL-12345 DRY_RUN=true MOCK_JIRA=true +just run-triage-agent RHEL-12345 DRY_RUN=true MOCK_JIRA=true ``` 3. **Use mock Jira** (from `git@gitlab.cee.redhat.com:jotnar-project/testing-jiras.git`) for consistent test data 4. **Verify with full pipeline**: ```bash - make start DRY_RUN=true - make trigger-pipeline JIRA_ISSUE=RHEL-12345 +just start DRY_RUN=true +just trigger-pipeline RHEL-12345 ``` 5. **Check agent logs**: Review output to ensure logic works as expected @@ -43,7 +43,7 @@ Tools in `ymir/tools/privileged/` require special care: 2. **Test against actual repos** (dist-git clones) when possible 3. **Run full test suite before submitting**: ```bash - make check-in-container + just check-in-container ``` 4. **Key file**: `ymir/tools/privileged/distgit.py` — handles clone/checkout for dist-git @@ -53,24 +53,24 @@ Tools in `ymir/tools/privileged/` require special care: ### Unit Tests ```bash # All tests in containers -make check-in-container +just check-in-container # Specific components in containers -make check-agents-in-container -make check-privileged-tools-in-container -make check-unprivileged-tools-in-container +just check-agents-in-container +just check-privileged-tools-in-container +just check-unprivileged-tools-in-container ``` > **Rootless podman**: if the build step fails with "cannot re-exec process to join the existing user namespace", skip the image build and run the container directly with `--privileged`: > ```bash -> podman run --rm --privileged -v $(pwd):/src:z beeai-tests make -f Makefile.tests check-privileged-tools +> podman run --rm --privileged -v $(pwd):/src:z beeai-tests just check-privileged-tools > ``` ### Manual Testing with Real Data Flow -1. Start full pipeline: `make start DRY_RUN=true` +1. Start full pipeline: `just start DRY_RUN=true` 2. Monitor traces: http://localhost:6006/ (Phoenix) 3. Monitor queues: http://localhost:8081/ (Redis) -4. Trigger: `make trigger-pipeline JIRA_ISSUE=RHEL-12345` +4. Trigger: `just trigger-pipeline RHEL-12345` 5. Review agent logs to see decision-making ## Common Issues & Gotchas @@ -114,7 +114,7 @@ For detailed deployment info: see [openshift/README.md](openshift/README.md) ## Code Changes Checklist - [ ] Write tests first (especially for tools/git operations) -- [ ] Run `make check-in-container` — all tests pass +- [ ] Run `just check-in-container` — all tests pass - [ ] Test with `DRY_RUN=true` — don't touch real Jira/git - [ ] Use rebase merge (see [CONTRIBUTING.md](CONTRIBUTING.md)) - [ ] Don't modify `.env`, `.secrets/`, keytab files in PRs @@ -127,10 +127,10 @@ For detailed deployment info: see [openshift/README.md](openshift/README.md) uv sync --extra test # Run all tests in containers -make check-in-container +just check-in-container # Test single agent -make run-triage-agent-standalone JIRA_ISSUE=RHEL-12345 DRY_RUN=true MOCK_JIRA=true +just run-triage-agent RHEL-12345 DRY_RUN=true MOCK_JIRA=true # Run full pipeline with monitoring make start DRY_RUN=true diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 94a8b40f4..2c6fdbd24 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -28,8 +28,8 @@ only need to clone it once; the tests run entirely offline against the local cop ### Running ```bash -make run-triage-agent-e2e-tests -make run-backport-agent-e2e-tests +just run-triage-agent-e2e-tests +just run-backport-agent-e2e-tests ``` Both targets hardcode `MOCK_JIRA=true` and `DRY_RUN=true`. The mock Jira files are writable, diff --git a/Makefile b/Makefile deleted file mode 100644 index 92b52397f..000000000 --- a/Makefile +++ /dev/null @@ -1,359 +0,0 @@ -IMAGE_NAME ?= beeai-agent -COMPOSE_FILE ?= compose.yaml -DRY_RUN ?= false -MOCK_JIRA ?= false -JIRA_DRY_RUN ?= false -JIRA_ALLOW_STATUS_CHANGES ?= false -ERRATA_ALLOW_STATUS_CHANGES ?= false -AUTO_CHAIN ?= true -FORCE_CVE_TRIAGE ?= false -RUN_LLM_JUDGE ?= true - -COMPOSE ?= $(shell if podman compose ls >/dev/null 2>&1; then echo "podman compose"; elif command -v podman-compose >/dev/null 2>&1; then echo "podman-compose"; else echo "docker-compose"; fi) -COMPOSE_AGENTS=$(COMPOSE) -f $(COMPOSE_FILE) --profile=agents -COMPOSE_SUPERVISOR=$(COMPOSE) -f $(COMPOSE_FILE) --profile=supervisor - -# Extract container tool (podman or docker) from COMPOSE -CONTAINER_TOOL ?= $(shell command -v podman >/dev/null 2>&1 && echo "podman" || echo "docker") -REGISTRY ?= quay.io/jotnar - -.PHONY: build -build: - @if [ -f .secrets/build.env ]; then echo "Warning: .secrets/build.env is deprecated, please move its contents to .env"; fi - if [ -f .secrets/build.env ] && [ ! -f .env ]; then set -a && . ./.secrets/build.env && set +a; fi && \ - $(COMPOSE) -f $(COMPOSE_FILE) --profile=agents --profile=supervisor build - -.PHONY: push -push: - @echo "Pushing images to $(REGISTRY)..." - $(CONTAINER_TOOL) push $(REGISTRY)/phoenix:latest - $(CONTAINER_TOOL) push $(REGISTRY)/redis-commander:latest - @echo "All images pushed successfully!" - -.PHONY: build-and-push -build-and-push: build push - -.PHONY: run-beeai-bash -run-beeai-bash: - $(COMPOSE_AGENTS) run --rm triage-agent /bin/bash - -.PHONY: run-triage-agent-standalone -run-triage-agent-standalone: - $(COMPOSE_AGENTS) run --rm \ - -e JIRA_ISSUE=$(JIRA_ISSUE) \ - -e DRY_RUN=$(DRY_RUN) \ - -e MOCK_JIRA=$(MOCK_JIRA) \ - -e JIRA_DRY_RUN=$(JIRA_DRY_RUN) \ - -e FORCE_CVE_TRIAGE=$(FORCE_CVE_TRIAGE) \ - triage-agent - -.PHONY: run-triage-agent-e2e-tests -run-triage-agent-e2e-tests: - # SAFETY: MOCK_JIRA=true and DRY_RUN=true prevent writes to production Jira. - # These are REQUIRED — tests use real issue keys and would otherwise post - # comments to production. Setting them in the environment (not just -e flags) - # ensures dependent services like mcp-gateway pick them up via ${VAR:-default}. - # The conftest.py enforces this in the test container itself. - MOCK_JIRA=true DRY_RUN=true $(COMPOSE) -f $(COMPOSE_FILE) --profile=e2e-test run --rm \ - -e MOCK_JIRA="true" \ - -e DRY_RUN="true" \ - triage-agent-e2e-tests - -.PHONY: run-backport-agent-e2e-tests -run-backport-agent-e2e-tests: - # SAFETY: MOCK_JIRA=true and DRY_RUN=true prevent writes to production Jira. - # Setting them in the environment ensures mcp-gateway picks them up. - MOCK_JIRA=true DRY_RUN=true $(COMPOSE) -f $(COMPOSE_FILE) --profile=e2e-test run --rm \ - -e MOCK_JIRA="true" \ - -e DRY_RUN="true" \ - -e RUN_LLM_JUDGE=$(RUN_LLM_JUDGE) \ - backport-agent-e2e-tests - - -.PHONY: run-rebase-agent-c9s-standalone -run-rebase-agent-c9s-standalone: - $(COMPOSE_AGENTS) run --rm \ - -e PACKAGE=$(PACKAGE) \ - -e VERSION=$(VERSION) \ - -e JIRA_ISSUE=$(JIRA_ISSUE) \ - -e BRANCH=$(BRANCH) \ - -e DRY_RUN=$(DRY_RUN) \ - -e MOCK_JIRA=$(MOCK_JIRA) \ - -e JIRA_DRY_RUN=$(JIRA_DRY_RUN) \ - -e "JUSTIFICATION=$(JUSTIFICATION)" \ - rebase-agent-c9s - -.PHONY: run-rebase-agent-c10s-standalone -run-rebase-agent-c10s-standalone: - $(COMPOSE_AGENTS) run --rm \ - -e PACKAGE=$(PACKAGE) \ - -e VERSION=$(VERSION) \ - -e JIRA_ISSUE=$(JIRA_ISSUE) \ - -e BRANCH=$(BRANCH) \ - -e DRY_RUN=$(DRY_RUN) \ - -e MOCK_JIRA=$(MOCK_JIRA) \ - -e JIRA_DRY_RUN=$(JIRA_DRY_RUN) \ - -e "JUSTIFICATION=$(JUSTIFICATION)" \ - rebase-agent-c10s - -.PHONY: run-rebase-agent-standalone -run-rebase-agent-standalone: run-rebase-agent-c10s-standalone - - - - - -.PHONY: run-backport-agent-c9s-standalone -run-backport-agent-c9s-standalone: - $(COMPOSE_AGENTS) run --rm \ - -e PACKAGE=$(PACKAGE) \ - -e UPSTREAM_PATCHES=$(UPSTREAM_PATCHES) \ - -e JIRA_ISSUE=$(JIRA_ISSUE) \ - -e BRANCH=$(BRANCH) \ - -e DRY_RUN=$(DRY_RUN) \ - -e MOCK_JIRA=$(MOCK_JIRA) \ - -e JIRA_DRY_RUN=$(JIRA_DRY_RUN) \ - -e CVE_ID=$(CVE_ID) \ - -e "JUSTIFICATION=$(JUSTIFICATION)" \ - backport-agent-c9s - -.PHONY: run-backport-agent-c10s-standalone -run-backport-agent-c10s-standalone: - $(COMPOSE_AGENTS) run --rm \ - -e PACKAGE=$(PACKAGE) \ - -e UPSTREAM_PATCHES=$(UPSTREAM_PATCHES) \ - -e JIRA_ISSUE=$(JIRA_ISSUE) \ - -e BRANCH=$(BRANCH) \ - -e DRY_RUN=$(DRY_RUN) \ - -e MOCK_JIRA=$(MOCK_JIRA) \ - -e JIRA_DRY_RUN=$(JIRA_DRY_RUN) \ - -e CVE_ID=$(CVE_ID) \ - -e "JUSTIFICATION=$(JUSTIFICATION)" \ - backport-agent-c10s - -.PHONY: run-backport-agent-standalone -run-backport-agent-standalone: run-backport-agent-c10s-standalone - - -.PHONY: run-rebuild-agent-c9s-standalone -run-rebuild-agent-c9s-standalone: - $(COMPOSE_AGENTS) run --rm \ - -e PACKAGE=$(PACKAGE) \ - -e JIRA_ISSUE=$(JIRA_ISSUE) \ - -e BRANCH=$(BRANCH) \ - -e DRY_RUN=$(DRY_RUN) \ - -e MOCK_JIRA=$(MOCK_JIRA) \ - -e DEPENDENCY_ISSUE=$(DEPENDENCY_ISSUE) \ - -e DEPENDENCY_COMPONENT=$(DEPENDENCY_COMPONENT) \ - -e CONSOLIDATED_ISSUES=$(CONSOLIDATED_ISSUES) \ - -e JIRA_DRY_RUN=$(JIRA_DRY_RUN) \ - -e "JUSTIFICATION=$(JUSTIFICATION)" \ - rebuild-agent-c9s - -.PHONY: run-rebuild-agent-c10s-standalone -run-rebuild-agent-c10s-standalone: - $(COMPOSE_AGENTS) run --rm \ - -e PACKAGE=$(PACKAGE) \ - -e JIRA_ISSUE=$(JIRA_ISSUE) \ - -e BRANCH=$(BRANCH) \ - -e DRY_RUN=$(DRY_RUN) \ - -e MOCK_JIRA=$(MOCK_JIRA) \ - -e DEPENDENCY_ISSUE=$(DEPENDENCY_ISSUE) \ - -e DEPENDENCY_COMPONENT=$(DEPENDENCY_COMPONENT) \ - -e CONSOLIDATED_ISSUES=$(CONSOLIDATED_ISSUES) \ - -e JIRA_DRY_RUN=$(JIRA_DRY_RUN) \ - -e "JUSTIFICATION=$(JUSTIFICATION)" \ - rebuild-agent-c10s - -.PHONY: run-rebuild-agent-standalone -run-rebuild-agent-standalone: run-rebuild-agent-c10s-standalone - -.PHONY: run-mr-agent-c9s-standalone -run-mr-agent-c9s-standalone: - $(COMPOSE_AGENTS) run --rm \ - -e MERGE_REQUEST_URL=$(MERGE_REQUEST_URL) \ - mr-agent-c9s - -.PHONY: run-mr-agent-c10s-standalone -run-mr-agent-c10s-standalone: - $(COMPOSE_AGENTS) run --rm \ - -e MERGE_REQUEST_URL=$(MERGE_REQUEST_URL) \ - mr-agent-c10s - -.PHONY: run-mr-agent-standalone -run-mr-agent-standalone: run-mr-agent-c10s-standalone - - -.PHONY: run-jira-issue-fetcher -run-jira-issue-fetcher: - @echo "Running Jira Issue Fetcher..." - @if [ ! -f .secrets/jira-issue-fetcher.env ]; then \ - echo "Error: .secrets/jira-issue-fetcher.env not found"; \ - echo "Copy the template: cp templates/jira-issue-fetcher.env .secrets/jira-issue-fetcher.env"; \ - echo "Then edit it with your credentials"; \ - exit 1; \ - fi - @echo "Ensuring Redis is available (don't use depends_on otherwise it will kill agents already running)..." - @$(COMPOSE) -f $(COMPOSE_FILE) up -d valkey || true # Don't fail if valkey is already running - @echo "Running jira-issue-fetcher..." - $(COMPOSE) -f $(COMPOSE_FILE) --profile manual run --rm jira-issue-fetcher - -.PHONY: build-jira-issue-fetcher -build-jira-issue-fetcher: - $(COMPOSE) --profile manual build jira-issue-fetcher - - - - -# Essential 3-Agent Architecture Targets - -.PHONY: start -start: - DRY_RUN=$(DRY_RUN) MOCK_JIRA=$(MOCK_JIRA) JIRA_DRY_RUN=$(JIRA_DRY_RUN) JIRA_ALLOW_STATUS_CHANGES=$(JIRA_ALLOW_STATUS_CHANGES) ERRATA_ALLOW_STATUS_CHANGES=$(ERRATA_ALLOW_STATUS_CHANGES) AUTO_CHAIN=$(AUTO_CHAIN) $(COMPOSE_AGENTS) up - -.PHONY: start-detached -start-detached: - DRY_RUN=$(DRY_RUN) MOCK_JIRA=$(MOCK_JIRA) JIRA_DRY_RUN=$(JIRA_DRY_RUN) JIRA_ALLOW_STATUS_CHANGES=$(JIRA_ALLOW_STATUS_CHANGES) ERRATA_ALLOW_STATUS_CHANGES=$(ERRATA_ALLOW_STATUS_CHANGES) AUTO_CHAIN=$(AUTO_CHAIN) $(COMPOSE_AGENTS) up -d - -.PHONY: stop -stop: - $(COMPOSE_AGENTS) stop - $(COMPOSE_AGENTS) down - -.PHONY: clean -clean: - $(COMPOSE) -f $(COMPOSE_FILE) down --volumes - - -.PHONY: logs-triage -logs-triage: - $(COMPOSE_AGENTS) logs -f triage-agent - -.PHONY: logs-backport -logs-backport: - $(COMPOSE_AGENTS) logs -f backport-agent - -.PHONY: logs-rebase -logs-rebase: - $(COMPOSE_AGENTS) logs -f rebase-agent - -.PHONY: logs-rebuild -logs-rebuild: - $(COMPOSE_AGENTS) logs -f rebuild-agent - -.PHONY: logs-jira-issue-fetcher -logs-jira-issue-fetcher: - $(COMPOSE) -f $(COMPOSE_FILE) --profile manual logs -f jira-issue-fetcher - - -.PHONY: trigger-pipeline -trigger-pipeline: - @if [ -z "$(JIRA_ISSUE)" ]; then \ - echo "Usage: make trigger-pipeline JIRA_ISSUE=RHEL-12345 [FORCE_CVE_TRIAGE=true]"; \ - exit 1; \ - fi - @echo "Triggering pipeline for issue: $(JIRA_ISSUE) (force_cve_triage=$(FORCE_CVE_TRIAGE))" - $(COMPOSE_AGENTS) exec valkey redis-cli LPUSH triage_queue '{"metadata": {"issue": "$(JIRA_ISSUE)", "force_cve_triage": $(FORCE_CVE_TRIAGE)}}' - - -# Testing and Release Supervisor - -DEBUG_LOWER := $(shell echo $(DEBUG) | tr '[:upper:]' '[:lower:]') -ifeq ($(DEBUG_LOWER),true) -DEBUG_FLAG := --debug -else -DEBUG_FLAG := -endif - -DRY_RUN_LOWER := $(shell echo $(DRY_RUN) | tr '[:upper:]' '[:lower:]') -ifeq ($(DRY_RUN_LOWER),true) -DRY_RUN_FLAG := --dry-run -else -DRY_RUN_FLAG := -endif - -IGNORE_NEEDS_ATTENTION_LOWER := $(shell echo $(IGNORE_NEEDS_ATTENTION) | tr '[:upper:]' '[:lower:]') -ifeq ($(IGNORE_NEEDS_ATTENTION_LOWER),true) -IGNORE_NEEDS_ATTENTION_FLAG := --ignore-needs-attention -else -IGNORE_NEEDS_ATTENTION_FLAG := -endif - -.PHONY: supervisor-clear-queue -supervisor-clear-queue: - $(COMPOSE_SUPERVISOR) run --rm \ - supervisor python -m ymir.supervisor.main $(DEBUG_FLAG) clear-queue - -.PHONY: supervisor-collect -supervisor-collect: - $(COMPOSE_SUPERVISOR) run --rm \ - supervisor python -m ymir.supervisor.main $(DEBUG_FLAG) collect --no-repeat - -.PHONY: process-issue -process-issue: - $(COMPOSE_SUPERVISOR) run --rm \ - supervisor python -m ymir.supervisor.main $(DEBUG_FLAG) $(IGNORE_NEEDS_ATTENTION_FLAG) $(DRY_RUN_FLAG) process-issue $(JIRA_ISSUE) - -.PHONY: process-erratum -process-erratum: - $(COMPOSE_SUPERVISOR) run --rm \ - supervisor python -m ymir.supervisor.main $(DEBUG_FLAG) $(IGNORE_NEEDS_ATTENTION_FLAG) $(DRY_RUN_FLAG) process-erratum $(ERRATA_ID) - -.PHONY: run-issue-verification-agent-standalone -run-issue-verification-agent-standalone: - $(COMPOSE_AGENTS) run --rm \ - -e JIRA_ISSUE=$(JIRA_ISSUE) \ - -e DRY_RUN=$(DRY_RUN) \ - -e IGNORE_NEEDS_ATTENTION=$(IGNORE_NEEDS_ATTENTION) \ - issue-verification-agent - -.PHONY: run-errata-workflow-agent-standalone -run-errata-workflow-agent-standalone: - $(COMPOSE_AGENTS) run --rm \ - -e ERRATUM_ID=$(ERRATUM_ID) \ - -e DRY_RUN=$(DRY_RUN) \ - -e IGNORE_NEEDS_ATTENTION=$(IGNORE_NEEDS_ATTENTION) \ - -e ERRATA_ALLOW_STATUS_CHANGES=$(ERRATA_ALLOW_STATUS_CHANGES) \ - errata-workflow-agent - -.PHONY: run-preliminary-testing-agent-standalone -run-preliminary-testing-agent-standalone: - $(COMPOSE_AGENTS) run --rm \ - -e JIRA_ISSUE=$(JIRA_ISSUE) \ - -e DRY_RUN=$(DRY_RUN) \ - -e IGNORE_NEEDS_ATTENTION=$(IGNORE_NEEDS_ATTENTION) \ - preliminary-testing-agent - - -# Common utility targets - -.PHONY: status -status: - $(COMPOSE) -f $(COMPOSE_FILE) ps - -.PHONY: redis-cli -redis-cli: - $(COMPOSE_AGENTS) exec valkey redis-cli - - -.PHONY: build-test-image -build-test-image: - $(MAKE) -f Makefile.tests build-test-image - -.PHONY: check-in-container check-agents-in-container check-unprivileged-tools-in-container check-privileged-tools-in-container check-jira-issue-fetcher-in-container check-ymir-common-in-container check-supervisor-in-container check-mcp-install-in-container -check-in-container: build-test-image - $(MAKE) -f Makefile.tests check-in-container -check-agents-in-container: build-test-image - $(MAKE) -f Makefile.tests check-agents-in-container -check-unprivileged-tools-in-container: build-test-image - $(MAKE) -f Makefile.tests check-unprivileged-tools-in-container -check-privileged-tools-in-container: build-test-image - $(MAKE) -f Makefile.tests check-privileged-tools-in-container -check-jira-issue-fetcher-in-container: build-test-image - $(MAKE) -f Makefile.tests check-jira-issue-fetcher-in-container -check-ymir-common-in-container: build-test-image - $(MAKE) -f Makefile.tests check-ymir-common-in-container -check-supervisor-in-container: build-test-image - $(MAKE) -f Makefile.tests check-supervisor-in-container -check-mcp-install-in-container: build-test-image - $(MAKE) -f Makefile.tests check-mcp-install-in-container diff --git a/Makefile.tests b/Makefile.tests deleted file mode 100644 index 83f6ba751..000000000 --- a/Makefile.tests +++ /dev/null @@ -1,66 +0,0 @@ -TEST_IMAGE ?= beeai-tests -TEST_IMAGE_C9S ?= beeai-tests-c9s -TEST_TARGET ?= ./tests/unit - -CONTAINER_ENGINE ?= $(shell command -v podman 2>/dev/null || echo "docker") - -.PHONY: build-test-image build-test-image-fedora build-test-image-c9s -ifndef SKIP_IMG_BUILD -build-test-image: build-test-image-fedora build-test-image-c9s -endif - -build-test-image-fedora: - $(CONTAINER_ENGINE) build --rm --tag $(TEST_IMAGE) -f Containerfile.tests - -build-test-image-c9s: - $(CONTAINER_ENGINE) build --rm --tag $(TEST_IMAGE_C9S) -f Containerfile.c9s-tests - -.PHONY: check check-agents check-unprivileged-tools check-privileged-tools check-jira-issue-fetcher check-ymir-common \ - check-supervisor check-mcp-install check-in-container check-agents-in-container check-unprivileged-tools-in-container \ - check-privileged-tools-in-container check-jira-issue-fetcher-in-container check-ymir-common-in-container \ - check-supervisor-in-container check-mcp-install-in-container - -define RUN_TESTS - PYTHONPATH=$(CURDIR) PYTHONDONTWRITEBYTECODE=1 python3 -m pytest --verbose --showlocals $(addprefix $(1),$(TEST_TARGET)) -endef - -check-agents: - $(call RUN_TESTS,ymir/agents/) -check-unprivileged-tools: - $(call RUN_TESTS,ymir/tools/unprivileged/) -check-privileged-tools: - $(call RUN_TESTS,ymir/tools/privileged/) -check-jira-issue-fetcher: - $(call RUN_TESTS,ymir/jira_issue_fetcher/) -check-ymir-common: - $(call RUN_TESTS,ymir/common/) -check-supervisor: - $(call RUN_TESTS,ymir/supervisor/) - -check-mcp-install: - PYTHONPATH= bash scripts/test_mcp_install.sh - -check: check-agents check-unprivileged-tools check-privileged-tools check-jira-issue-fetcher check-ymir-common check-supervisor check-mcp-install - -define RUN_TESTS_IN_CONTAINER - $(CONTAINER_ENGINE) run --rm -it -v $(CURDIR):/src:z --env TEST_TARGET $(1) make -f Makefile.tests $(2) -endef - -check-agents-in-container: - $(call RUN_TESTS_IN_CONTAINER,$(TEST_IMAGE_C9S),check-agents) -check-unprivileged-tools-in-container: - $(call RUN_TESTS_IN_CONTAINER,$(TEST_IMAGE_C9S),check-unprivileged-tools) -check-privileged-tools-in-container: - $(call RUN_TESTS_IN_CONTAINER,$(TEST_IMAGE),check-privileged-tools) -check-jira-issue-fetcher-in-container: - $(call RUN_TESTS_IN_CONTAINER,$(TEST_IMAGE),check-jira-issue-fetcher) -check-ymir-common-in-container: - $(call RUN_TESTS_IN_CONTAINER,$(TEST_IMAGE_C9S),check-ymir-common) -check-supervisor-in-container: - $(call RUN_TESTS_IN_CONTAINER,$(TEST_IMAGE_C9S),check-supervisor) -check-mcp-install-in-container: - $(call RUN_TESTS_IN_CONTAINER,$(TEST_IMAGE),check-mcp-install) - -check-in-container: check-agents-in-container check-unprivileged-tools-in-container check-privileged-tools-in-container \ - check-jira-issue-fetcher-in-container check-ymir-common-in-container check-supervisor-in-container \ - check-mcp-install-in-container diff --git a/README-agents.md b/README-agents.md index b651dc59d..67ff69416 100644 --- a/README-agents.md +++ b/README-agents.md @@ -51,14 +51,14 @@ you can use them to work with pre-downloaded jira content instead of real Jira s Example: -`make run-triage-agent-standalone JIRA_ISSUE=RHEL-15216 MOCK_JIRA=true` +`just run-triage-agent RHEL-15216 MOCK_JIRA=true` If used together with `DRY_RUN`, the agents won't edit the Jira files, otherwise they will. Example: -`make run-triage-agent-standalone JIRA_ISSUE=RHEL-15216 DRY_RUN=true MOCK_JIRA=true` +`just run-triage-agent RHEL-15216 DRY_RUN=true MOCK_JIRA=true` ## Setup @@ -99,23 +99,23 @@ To be able to access internal RHEL dist-git with your identity, update the `User ## Running the System -Please do not run `podman-compose up` directly; use the provided Makefile instead. +Please do not run `podman-compose up` directly; use the provided justfile instead. ### Full Pipeline (Production) ```bash # Start all agents and services -make start +just start # With options: -make start DRY_RUN=true # Skip Jira writes and git pushes -make start AUTO_CHAIN=false # Disable downstream queue routing (triage only) -make start DRY_RUN=true AUTO_CHAIN=false # Combine both +just start DRY_RUN=true # Skip Jira writes and git pushes +just start AUTO_CHAIN=false # Disable downstream queue routing (triage only) +just start DRY_RUN=true AUTO_CHAIN=false # Combine both # Process a JIRA issue -make trigger-pipeline JIRA_ISSUE=RHEL-12345 +just trigger-pipeline RHEL-12345 # Force triage of Y-stream CVEs (normally skipped) -make trigger-pipeline JIRA_ISSUE=RHEL-12345 FORCE_CVE_TRIAGE=true +just trigger-pipeline RHEL-12345 FORCE_CVE_TRIAGE=true ``` **Environment variables:** @@ -131,15 +131,15 @@ make trigger-pipeline JIRA_ISSUE=RHEL-12345 FORCE_CVE_TRIAGE=true ```bash # Test specific agents standalone make JIRA_ISSUE=RHEL-12345 run-triage-agent-standalone -make PACKAGE=httpd VERSION=2.4.62 JIRA_ISSUE=RHEL-12345 BRANCH=c10s run-rebase-agent-standalone -make PACKAGE=httpd UPSTREAM_PATCHES=https://github.com/... JIRA_ISSUE=RHEL-12345 BRANCH=c10s run-backport-agent-standalone -make PACKAGE=httpd JIRA_ISSUE=RHEL-12345 BRANCH=c10s run-rebuild-agent-standalone +just run-rebase-agent c10s httpd 2.4.62 RHEL-12345 c10s "Initial rebase" +just run-backport-agent c10s httpd https://github.com/... RHEL-12345 c10s "Initial backport" +just run-rebuild-agent c10s httpd RHEL-12345 c10s "Initial rebuild" # Or with dry-run -DRY_RUN=true make JIRA_ISSUE=RHEL-12345 run-triage-agent-standalone +DRY_RUN=true just run-triage-agent RHEL-12345 # Force triage of a Y-stream CVE -make JIRA_ISSUE=RHEL-12345 FORCE_CVE_TRIAGE=true run-triage-agent-standalone +FORCE_CVE_TRIAGE=true just run-triage-agent RHEL-12345 ``` Use commas to delimit multiple patch/commit URLs in `UPSTREAM_PATCHES`. @@ -278,6 +278,6 @@ unused columns, so this is generally safe. ```bash # Setup automatic issue fetching from JIRA cp templates/jira-issue-fetcher.env .secrets/jira-issue-fetcher.env -make build-jira-issue-fetcher -make run-jira-issue-fetcher +just build-jira-issue-fetcher +just run-jira-issue-fetcher ``` diff --git a/README.md b/README.md index e13b04f85..88f50659a 100644 --- a/README.md +++ b/README.md @@ -89,7 +89,7 @@ Then, use the provided stub pyproject.toml file to set up the development enviro ``` uv sync --extra test -uv run make -f Makefile.tests check +uv run just check ``` You'll also need to have `python3-rpm` installed on the host system - @@ -104,7 +104,7 @@ to this upstream repository. To include them in your local container builds: 1. Copy the template: `cp -n templates/build.env .env` (or append its contents to your existing `.env` file) 2. Fill in the internal repo URLs and package names in `.env` -3. Run `make build` or `podman-compose build` — podman-compose automatically +3. Run `just build` or `podman-compose build` — podman-compose automatically loads `.env` and passes the values as build args to the Containerfiles. Without `.env`, containers build normally but without any diff --git a/justfile b/justfile new file mode 100644 index 000000000..a3991bfe8 --- /dev/null +++ b/justfile @@ -0,0 +1,262 @@ +#!/usr/bin/env just --justfile + +#------------------------------------------------------------------------------ +# Justfile for BeeAI Agent Development +# +# This file replaces Makefile and Makefile.tests, providing a single, +# consistent interface for building, running, and testing the BeeAI agents. +# +# USAGE: +# 1. Create a .env file to store your local configuration. You can start by +# copying .env.example if it exists. +# 2. Run recipes using `just [arguments...]`. +# 3. For a list of all available recipes, run `just` or `just --list`. +#------------------------------------------------------------------------------ + +set unstable +set lists + +# --- Default Variables and Environment --- + +# Use .env file for environment variables +# See https://just.systems/man/en/chapter_26.html +set export + +# Shell variables, will be evaluated for every command that needs them +compose := shell('if podman compose ls >/dev/null 2>&1; then echo "podman compose"; elif command -v podman-compose >/dev/null 2>&1; then echo "podman-compose"; else echo "docker-compose"; fi') +container_tool := shell('command -v podman >/dev/null 2>&1 && echo "podman" || echo "docker"') + +# Variables with defaults. These can be overridden in .env or on the command line +IMAGE_NAME := "beeai-agent" +compose_file := "compose.yaml" +DRY_RUN := "false" +MOCK_JIRA := "false" +JIRA_DRY_RUN := "false" +JIRA_ALLOW_STATUS_CHANGES := "false" +ERRATA_ALLOW_STATUS_CHANGES := "false" +AUTO_CHAIN := "true" +FORCE_CVE_TRIAGE := "false" +RUN_LLM_JUDGE := "true" +REGISTRY := "quay.io/jotnar" +TEST_IMAGE := "beeai-tests" +TEST_IMAGE_C9S := "beeai-tests-c9s" + +# Internal compose commands +compose_agents := compose + ' -f ' + compose_file + ' --profile=agents' +compose_supervisor := compose + ' -f ' + compose_file + ' --profile=supervisor' + +# --- Build and Push Images --- + +# Build all service images (agents and supervisor) +build: + @if [ -f .secrets/build.env ]; then echo "Warning: .secrets/build.env is deprecated, please move its contents to .env"; fi + @if [ -f .secrets/build.env ] && [ ! -f .env ]; then set -a && . ./.secrets/build.env && set +a; fi && \ + {{compose}} -f {{compose_file}} --profile=agents --profile=supervisor build + +# Push common images to the registry +push: + @echo "Pushing images to {{REGISTRY}}..." + {{container_tool}} push {{REGISTRY}}/phoenix:latest + {{container_tool}} push {{REGISTRY}}/redis-commander:latest + @echo "All images pushed successfully!" + +# Build and push all images +build-and-push: build push + +# --- Agent Standalone Runners --- + +# Run the Triage Agent +run-triage-agent jira_issue: + {{compose_agents}} run --rm \ + -e JIRA_ISSUE="{{jira_issue}}" \ + -e DRY_RUN={{DRY_RUN}} \ + -e MOCK_JIRA={{MOCK_JIRA}} \ + -e JIRA_DRY_RUN={{JIRA_DRY_RUN}} \ + -e FORCE_CVE_TRIAGE={{FORCE_CVE_TRIAGE}} \ + triage-agent + +# Run the Rebase Agent for a given stream (c9s or c10s) +run-rebase-agent stream package version jira_issue branch justification: + {{compose_agents}} run --rm \ + -e PACKAGE="{{package}}" \ + -e VERSION="{{version}}" \ + -e JIRA_ISSUE="{{jira_issue}}" \ + -e BRANCH="{{branch}}" \ + -e DRY_RUN={{DRY_RUN}} \ + -e MOCK_JIRA={{MOCK_JIRA}} \ + -e JIRA_DRY_RUN={{JIRA_DRY_RUN}} \ + -e "JUSTIFICATION={{justification}}" \ + rebase-agent-{{stream}} + +# Run the Backport Agent for a given stream (c9s or c10s) +run-backport-agent stream package upstream_patches jira_issue branch justification cve_id='': + {{compose_agents}} run --rm \ + -e PACKAGE="{{package}}" \ + -e UPSTREAM_PATCHES="{{upstream_patches}}" \ + -e JIRA_ISSUE="{{jira_issue}}" \ + -e BRANCH="{{branch}}" \ + -e DRY_RUN={{DRY_RUN}} \ + -e MOCK_JIRA={{MOCK_JIRA}} \ + -e JIRA_DRY_RUN={{JIRA_DRY_RUN}} \ + -e CVE_ID="{{cve_id}}" \ + -e "JUSTIFICATION={{justification}}" \ + backport-agent-{{stream}} + +# Run the Rebuild Agent for a given stream (c9s or c10s) +run-rebuild-agent stream package jira_issue branch justification dependency_issue='' dependency_component='' consolidated_issues='': + {{compose_agents}} run --rm \ + -e PACKAGE="{{package}}" \ + -e JIRA_ISSUE="{{jira_issue}}" \ + -e BRANCH="{{branch}}" \ + -e DRY_RUN={{DRY_RUN}} \ + -e MOCK_JIRA={{MOCK_JIRA}} \ + -e DEPENDENCY_ISSUE="{{dependency_issue}}" \ + -e DEPENDENCY_COMPONENT="{{dependency_component}}" \ + -e CONSOLIDATED_ISSUES="{{consolidated_issues}}" \ + -e JIRA_DRY_RUN={{JIRA_DRY_RUN}} \ + -e "JUSTIFICATION={{justification}}" \ + rebuild-agent-{{stream}} + +# Run the MR Agent for a given stream (c9s or c10s) +run-mr-agent stream merge_request_url: + {{compose_agents}} run --rm \ + -e MERGE_REQUEST_URL="{{merge_request_url}}" \ + mr-agent-{{stream}} + +# --- E2E Tests --- + +# Run Triage Agent E2E tests +run-triage-agent-e2e-tests: + @echo "SAFETY: MOCK_JIRA=true and DRY_RUN=true are enforced for E2E tests." + MOCK_JIRA=true DRY_RUN=true {{compose}} -f {{compose_file}} --profile=e2e-test run --rm \ + -e MOCK_JIRA="true" \ + -e DRY_RUN="true" \ + triage-agent-e2e-tests + +# Run Backport Agent E2E tests +run-backport-agent-e2e-tests: + @echo "SAFETY: MOCK_JIRA=true and DRY_RUN=true are enforced for E2E tests." + MOCK_JIRA=true DRY_RUN=true {{compose}} -f {{compose_file}} --profile=e2e-test run --rm \ + -e MOCK_JIRA="true" \ + -e DRY_RUN="true" \ + -e RUN_LLM_JUDGE={{RUN_LLM_JUDGE}} \ + backport-agent-e2e-tests + +# --- Development Lifecycle --- + +# Start all agent services in the foreground +start: + DRY_RUN={{DRY_RUN}} MOCK_JIRA={{MOCK_JIRA}} JIRA_DRY_RUN={{JIRA_DRY_RUN}} JIRA_ALLOW_STATUS_CHANGES={{JIRA_ALLOW_STATUS_CHANGES}} ERRATA_ALLOW_STATUS_CHANGES={{ERRATA_ALLOW_STATUS_CHANGES}} AUTO_CHAIN={{AUTO_CHAIN}} {{compose_agents}} up + +# Start all agent services in detached mode +start-detached: + DRY_RUN={{DRY_RUN}} MOCK_JIRA={{MOCK_JIRA}} JIRA_DRY_RUN={{JIRA_DRY_RUN}} JIRA_ALLOW_STATUS_CHANGES={{JIRA_ALLOW_STATUS_CHANGES}} ERRATA_ALLOW_STATUS_CHANGES={{ERRATA_ALLOW_STATUS_CHANGES}} AUTO_CHAIN={{AUTO_CHAIN}} {{compose_agents}} up -d + +# Stop and remove all services +stop: + {{compose_agents}} stop + {{compose_agents}} down + +# Stop and remove all services, including volumes +clean: + {{compose}} -f {{compose_file}} down --volumes + +# View the status of running services +status: + {{compose}} -f {{compose_file}} ps + +# --- Logging --- + +# Follow logs for a specific agent +logs agent: + {{compose_agents}} logs -f {{agent}} + +# --- Pipeline and Supervisor --- + +# Trigger a pipeline for a Jira issue +trigger-pipeline jira_issue: + @echo "Triggering pipeline for issue: {{jira_issue}} (force_cve_triage={{FORCE_CVE_TRIAGE}})" + {{compose_agents}} exec valkey redis-cli LPUSH triage_queue '{"metadata": {"issue": "{{jira_issue}}", "force_cve_triage": {{FORCE_CVE_TRIAGE}}}}' + +# Clear the supervisor queue +supervisor-clear-queue debug='false': + {{compose_supervisor}} run --rm \ + supervisor python -m ymir.supervisor.main {{ (if debug == 'true' { '--debug' }) }} clear-queue + +# Collect issues/errata for processing +supervisor-collect debug='false': + {{compose_supervisor}} run --rm \ + supervisor python -m ymir.supervisor.main {{ (if debug == 'true' { '--debug' }) }} collect --no-repeat + +# Process a single Jira issue +process-issue jira_issue ignore_needs_attention='false' dry_run_flag='true' debug='false': + {{compose_supervisor}} run --rm \ + supervisor python -m ymir.supervisor.main {{ (if debug == 'true' { '--debug' }) }} {{ (if ignore_needs_attention == 'true' { '--ignore-needs-attention' }) }} {{ (if dry_run_flag == 'true' { '--dry-run' }) }} process-issue {{jira_issue}} + +# Process a single Erratum +process-erratum errata_id ignore_needs_attention='false' dry_run_flag='true' debug='false': + {{compose_supervisor}} run --rm \ + supervisor python -m ymir.supervisor.main {{ (if debug == 'true' { '--debug' }) }} {{ (if ignore_needs_attention == 'true' { '--ignore-needs-attention' }) }} {{ (if dry_run_flag == 'true' { '--dry-run' }) }} process-erratum {{errata_id}} + +# --- Testing (from Makefile.tests) --- + +# Build the test images +build-test-images: build-test-image-fedora build-test-image-c9s + +# Build the Fedora test image +build-test-image-fedora: + {{container_tool}} build --rm --tag {{TEST_IMAGE}} -f Containerfile.tests + +# Build the CentOS Stream 9 test image +build-test-image-c9s: + {{container_tool}} build --rm --tag {{TEST_IMAGE_C9S}} -f Containerfile.c9s-tests + +# Run all local tests +check: check-agents check-unprivileged-tools check-privileged-tools check-jira-issue-fetcher check-ymir-common check-supervisor check-mcp-install + +# Run tests for a specific component locally +check-agents: (_run-tests 'ymir/agents/') +check-unprivileged-tools: (_run-tests 'ymir/tools/unprivileged/') +check-privileged-tools: (_run-tests 'ymir/tools/privileged/') +check-jira-issue-fetcher: (_run-tests 'ymir/jira_issue_fetcher/') +check-ymir-common: (_run-tests 'ymir/common/') +check-supervisor: (_run-tests 'ymir/supervisor/') +check-mcp-install: + @PYTHONPATH= bash scripts/test_mcp_install.sh + +# [Internal] Helper to run pytest +_run-tests test_path: + PYTHONPATH=. PYTHONDONTWRITEBYTECODE=1 python3 -m pytest --verbose --showlocals {{test_path}}tests/unit + +# Run all tests in their respective containers +check-in-container: build-test-images + just check-agents-in-container + just check-unprivileged-tools-in-container + just check-privileged-tools-in-container + just check-jira-issue-fetcher-in-container + just check-ymir-common-in-container + just check-supervisor-in-container + just check-mcp-install-in-container + +# Run component tests in containers +check-agents-in-container: (_run-tests-in-container TEST_IMAGE_C9S 'check-agents') +check-unprivileged-tools-in-container: (_run-tests-in-container TEST_IMAGE_C9S 'check-unprivileged-tools') +check-privileged-tools-in-container: (_run-tests-in-container TEST_IMAGE 'check-privileged-tools') +check-jira-issue-fetcher-in-container: (_run-tests-in-container TEST_IMAGE 'check-jira-issue-fetcher') +check-ymir-common-in-container: (_run-tests-in-container TEST_IMAGE_C9S 'check-ymir-common') +check-supervisor-in-container: (_run-tests-in-container TEST_IMAGE_C9S 'check-supervisor') +check-mcp-install-in-container: (_run-tests-in-container TEST_IMAGE 'check-mcp-install') + +# [Internal] Helper to run tests in a container +_run-tests-in-container image recipe: + {{container_tool}} run --rm -it -v $(pwd):/src:z -w /src --env TEST_TARGET {{image}} just {{recipe}} + +# --- Utilities --- + +# Open a bash shell in the triage-agent container +bash: + {{compose_agents}} run --rm triage-agent /bin/bash + +# Open a redis-cli session +redis-cli: + {{compose_agents}} exec valkey redis-cli diff --git a/ymir/agents/tests/e2e/README.md b/ymir/agents/tests/e2e/README.md index 5abc974b5..e2fa81158 100644 --- a/ymir/agents/tests/e2e/README.md +++ b/ymir/agents/tests/e2e/README.md @@ -21,10 +21,10 @@ The Makefile automatically sets both safety vars: ```bash # Triage agent E2E tests -make run-triage-agent-e2e-tests +just run-triage-agent-e2e-tests # Backport agent E2E tests -make run-backport-agent-e2e-tests +just run-backport-agent-e2e-tests ``` #### Manual Execution @@ -63,5 +63,5 @@ SAFETY CHECK FAILED: E2E tests MUST run with production Jira writes disabled. **Do NOT disable the check.** Instead: 1. Set `MOCK_JIRA=true DRY_RUN=true` when invoking pytest -2. Use `make run-triage-agent-e2e-tests` instead of direct pytest +2. Use `just run-triage-agent-e2e-tests` instead of direct pytest 3. Check if your shell has stray env vars overriding the defaults