diff --git a/.claude/commands/ci/analyze-failures.md b/.claude/commands/ci/analyze-failures.md index a8d5118e72f3..56dc80fae092 100644 --- a/.claude/commands/ci/analyze-failures.md +++ b/.claude/commands/ci/analyze-failures.md @@ -29,10 +29,11 @@ https://prow.ci.openshift.org/view/gs/origin-ci-test/logs/periodic-ci-openshift- **Example Jenkins URLs**: ``` -https://jenkins-csb-openshift-qe-mastern.dno.corp.redhat.com/job/image-consistency-check/3436/ https://jenkins-csb-openshift-qe-mastern.dno.corp.redhat.com/job/zstreams/job/Stage-Pipeline/1413/ ``` +> **Note:** Image consistency check has been migrated from Jenkins to Prow. Prow job URLs follow the Prow URL pattern above. + ## Action to Take **Step 1**: Analyze the provided URL against the detection rules above. @@ -54,7 +55,7 @@ https://jenkins-csb-openshift-qe-mastern.dno.corp.redhat.com/job/zstreams/job/St Please specify which type of CI job this is: 1. **Prow job** - OpenShift CI Prow jobs (from qe-private-deck or prow.ci.openshift.org) - 2. **Jenkins job** - Jenkins jobs (image-consistency-check, stage-testing, etc.) + 2. **Jenkins job** - Jenkins jobs (stage-testing, etc.) Or provide a more complete URL if the one given was truncated. ``` diff --git a/.claude/commands/ci/analyze-jenkins-failures.md b/.claude/commands/ci/analyze-jenkins-failures.md index f397b2b9a159..96d4b7960189 100644 --- a/.claude/commands/ci/analyze-jenkins-failures.md +++ b/.claude/commands/ci/analyze-jenkins-failures.md @@ -1,17 +1,20 @@ --- -description: Analyze Jenkins job failures (image-consistency-check, stage-testing) using AI +description: Analyze Jenkins job failures (stage-testing) using AI --- -You are helping the user analyze failures from a Jenkins job run (typically image-consistency-check or stage-testing jobs used in z-stream release testing). +You are helping the user analyze failures from a Jenkins job run (typically stage-testing jobs used in z-stream release testing). + +> **Note:** Image-consistency-check has been migrated from Jenkins to Prow. For Prow job failures, use `/ci:analyze-failures` instead. The user has provided a Jenkins job URL: {{args}} ## Overview Jenkins jobs used in OAR z-stream release workflow: -- **image-consistency-check**: Verifies payload image consistency - **stage-testing** (Stage-Pipeline): Runs E2E tests for optional operators shipped with Openshift +> **Note:** image-consistency-check has been migrated to Prow and is no longer a Jenkins job. + Each job has its own custom console log format. This command fetches the raw console log and analyzes it based on the job type. ## Steps @@ -23,7 +26,7 @@ Expected URL patterns: Extract: - **Base URL**: e.g., `https://jenkins-csb-openshift-qe-mastern.dno.corp.redhat.com` -- **Job name**: e.g., `image-consistency-check` or `zstreams/Stage-Pipeline` +- **Job name**: e.g., `zstreams/Stage-Pipeline` - **Build number**: e.g., `3436` ### 2. Fetch Job Parameters via API @@ -908,7 +911,7 @@ Present findings in a clear, actionable format: # Jenkins Job Failure Analysis Summary ## Job Details -- **Type**: {image-consistency-check | stage-testing} +- **Type**: stage-testing - **Build**: #{build_number} - **Status**: {status} - **URL**: {jenkins_url} @@ -995,7 +998,6 @@ No critical actions required. Monitor for: **Context**: - These jobs are part of OAR z-stream release workflow - Triggered by commands like: - - `oar -r 4.19.1 image-consistency-check` - `oar -r 4.19.1 stage-testing` - Failures may block release approval @@ -1008,11 +1010,11 @@ No critical actions required. Monitor for: ## Example Usage ```bash -/ci:analyze-jenkins-failures https://jenkins-csb-openshift-qe-mastern.dno.corp.redhat.com/job/image-consistency-check/3436/ +/ci:analyze-jenkins-failures https://jenkins-csb-openshift-qe-mastern.dno.corp.redhat.com/job/zstreams/job/Stage-Pipeline/1413/ ``` The command will: 1. Fetch console log from public endpoint -2. Detect it's an image-consistency-check job +2. Detect it's a stage-testing job 3. Parse the structured output sections 4. Provide analysis and recommendation \ No newline at end of file diff --git a/.claude/commands/release/drive.md b/.claude/commands/release/drive.md index be45f94ab006..08fb0cbc43d9 100644 --- a/.claude/commands/release/drive.md +++ b/.claude/commands/release/drive.md @@ -253,7 +253,7 @@ For complete step-by-step logic, read **`docs/KONFLUX_RELEASE_FLOW.md`**: **Async Task Monitoring:** - Re-execute the same MCP tool to check status -- Example: `oar_image_consistency_check(release, build_number=123)` to check progress +- Example: `oar_image_consistency_check(release, job_id="uuid")` to check progress ## Key Decision Points @@ -384,7 +384,7 @@ state = oar_get_release_status(release="4.20.1") "status": "In Progress", "started_at": "2025-01-15T14:00:00Z", "completed_at": null, - "result": "Jenkins job #123 triggered..." + "result": "Prow job triggered..." } ], "issues": [ @@ -459,17 +459,18 @@ elif task["status"] == "Pass": Continue to next task elif task["status"] == "In Progress": - # Check if async task (Jenkins jobs) + # Check if async task (Prow/Jenkins jobs) if task_name in ["image-consistency-check", "stage-testing"]: - # Extract build number from task result - build_number = extract_from_result(task["result"], r"Build number: (\d+)") + # Extract job ID from task result + # image-consistency-check uses Prow job ID, stage-testing uses Jenkins build number + job_id = extract_from_result(task["result"], r"job ID: (\S+)") or extract_from_result(task["result"], r"Build number: (\d+)") - if not build_number: - Log: f"⚠ {task_name} in progress but no build number found, retrying..." + if not job_id: + Log: f"⚠ {task_name} in progress but no job ID found, retrying..." Execute task_name else: - # Query Jenkins job status - result = execute_mcp_tool(task_name, build_number=build_number) + # Query job status (Prow or Jenkins depending on task) + result = execute_mcp_tool(task_name, job_id=job_id) if "status is changed to [Pass]" in result: Log: f"✓ {task_name} completed successfully" @@ -478,7 +479,7 @@ elif task["status"] == "In Progress": Log: f"✗ {task_name} failed" STOP pipeline else: - Log: f"⏳ {task_name} still running (job #{build_number})" + Log: f"⏳ {task_name} still running (job {job_id})" Ask user to check back later RETURN else: @@ -506,36 +507,36 @@ elif task["status"] == "Fail": ### Async Task Monitoring -**For long-running Jenkins tasks:** +**For long-running async tasks:** ```python -# Initial trigger (when task doesn't exist or has no build number) +# Initial trigger (when task doesn't exist or has no job ID) result = oar_image_consistency_check(release=release) -if "Build number:" in result: - build_number = extract_build_number(result) - Log: f"⏳ Jenkins job #{build_number} triggered" +if "Prow job" in result: + job_id = extract_job_id(result) + Log: f"⏳ Prow job {job_id} triggered" Log: "Check back in 20-30 minutes with: /release:drive {release}" RETURN -# Status check on resume (when task has build number in result) -result = oar_image_consistency_check(release=release, build_number=build_number) +# Status check on resume (when task has job ID in result) +result = oar_image_consistency_check(release=release, job_id=job_id) if "status is changed to [Pass]" in result: - Log: f"✓ Job #{build_number} completed successfully" + Log: f"✓ Job {job_id} completed successfully" Continue to next task elif "status is changed to [Fail]" in result: # Add issue to StateBox oar_add_issue( release=release, - issue=f"image-consistency-check job #{build_number} failed: {extract_failure_reason(result)}", + issue=f"image-consistency-check Prow job {job_id} failed: {extract_failure_reason(result)}", blocker=True, related_tasks=["image-consistency-check"] ) Log: "✗ Job failed, blocker added to StateBox" STOP pipeline else: - Log: f"⏳ Job #{build_number} still running..." + Log: f"⏳ Job {job_id} still running..." RETURN ``` @@ -645,8 +646,8 @@ AI: Resuming from PHASE 2... AI: ✓ Skipping 2 completed tasks (take-ownership, check-cve-tracker-bug) AI: ⏳ push-to-cdn-staging still running (job #456) AI: ✓ Build promoted! Phase: PHASE 3 - Test Evaluation -AI: ⏳ image-consistency-check triggered (job #789) -AI: ⏳ stage-testing triggered (job #790) +AI: ⏳ image-consistency-check triggered (Prow job abc-123-def) +AI: ⏳ stage-testing triggered (Jenkins job #790) AI: Waiting for test results, check back in 1 hour ``` @@ -657,8 +658,8 @@ AI: Loading StateBox state for 4.20.1... AI: Resuming from PHASE 4... AI: ✓ Skipping 4 completed tasks AI: ✓ push-to-cdn-staging completed (job #456) -AI: ✓ image-consistency-check completed (job #789) -AI: ✓ stage-testing completed (job #790) +AI: ✓ image-consistency-check completed (Prow job abc-123-def) +AI: ✓ stage-testing completed (Jenkins job #790) AI: Analyzing promoted build test results... AI: ✓ All tests passed, proceeding to PHASE 5 AI: ✓ image-signed-check completed diff --git a/.claude/skills/release-workflow/SKILL.md b/.claude/skills/release-workflow/SKILL.md index 51dec057fe42..bace4c7361f8 100644 --- a/.claude/skills/release-workflow/SKILL.md +++ b/.claude/skills/release-workflow/SKILL.md @@ -168,7 +168,7 @@ WHEN trigger phase: Report: "Task triggered, check status in X minutes" WHEN check phase: - Execute command with build_number + Execute command with job ID (Prow job ID or Jenkins build number) IF status == "In Progress": Report: "Task still running" ELSE IF status == "Pass": diff --git a/AGENTS.md b/AGENTS.md index e21e21e4a86f..84f71c6a1d44 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -403,23 +403,24 @@ oar -r [OPTIONS] COMMAND [ARGS] **Command:** ```bash oar -r image-consistency-check -oar -r image-consistency-check -n +oar -r image-consistency-check -i ``` -**Purpose:** Verifies that images in the release payload are consistent with advisory contents. +**Purpose:** Verifies that images in the release payload are consistent with images in the shipment. **Options:** -- `-n, --build-number` - Jenkins build number to check status (for subsequent runs) +- `-i, --job-id` - Prow job ID to check status (for subsequent runs) **What it does:** -- Triggers a Jenkins job to verify image consistency -- Compares images in release payload with images in advisories -- Returns build number on first run -- Can check job status on subsequent runs with build number +- Triggers a Prow job via Gangway API to verify image consistency +- Compares images in release payload with images in shipment MR +- Returns Prow job ID on first run +- Can check job status on subsequent runs with job ID +- Requires `APITOKEN` environment variable for Prow authentication **Workflow:** -1. First run: Triggers job, returns build number -2. Subsequent runs: Check status using `-n ` +1. First run: Triggers Prow job, returns job ID +2. Subsequent runs: Check status using `-i ` --- @@ -792,18 +793,17 @@ All core modules follow a consistent pattern: **Key Functionality:** - Trigger stage testing pipeline -- Trigger image consistency check jobs - Monitor job queue and execution - Validate job parameters match release version - Get build status with detailed error handling **Supported Jobs:** - `stage-pipeline` - Stage environment testing -- `image-consistency-check` - Verify payload images match advisories + +**Note:** Image consistency check has been migrated to Prow (see `prow/job/job.py` `run_image_consistency_check`). **Key Methods:** - `call_stage_job()` - Trigger stage testing -- `call_image_consistency_job()` - Trigger image consistency validation - `get_build_status()` - Check job status by build number - `is_job_enqueue()` - Check if job is queued @@ -1124,5 +1124,5 @@ When adding support for new OpenShift versions, update: 2. Job registry configurations 3. Test report templates 4. Add new ci-profile for stage-testing pipeline -5. Add new release version to parameter `VERSION` of image-consistency-check job +5. Update Prow job configuration for image-consistency-check 6. Update configstore config to add new test template doc ID and slack group alias for release leads diff --git a/CLAUDE.md b/CLAUDE.md index 664ab5ffff6c..78e309b3f3b2 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -201,7 +201,7 @@ The MCP (Model Context Protocol) server (`mcp_server/server.py`) exposes OAR com **Categories of tools:** 1. **Read-only tools** - Safe query operations (check-greenwave-cvp-tests, check-cve-tracker-bug, image-signed-check, is-release-shipped) -2. **Status check tools** - Query job status (image-consistency-check -n, stage-testing -n) +2. **Status check tools** - Query job status (image-consistency-check -i, stage-testing -n) 3. **Write operations** - Modify state (create-test-report, update-bug-list, take-ownership) 4. **Critical operations** - Production impact (push-to-cdn-staging, change-advisory-status) 5. **Controller tools** - Background agents (start-release-detector, jira-notificator) @@ -463,7 +463,7 @@ oar -r 4.19.1 update-bug-list # 4. Verify payload images oar -r 4.19.1 image-consistency-check -oar -r 4.19.1 image-consistency-check -n # Check status +oar -r 4.19.1 image-consistency-check -i # Check status # 5. Validate CVP tests oar -r 4.19.1 check-greenwave-cvp-tests @@ -510,8 +510,9 @@ When adding new version support, update: 1. Jira query filters (`oar/notificator/jira_notificator.py`) 2. Job registry configurations 3. Test report templates -4. Jenkins job parameters (stage-testing, image-consistency-check) -5. ConfigStore config (test template doc ID, Slack group alias) +4. Jenkins job parameters (stage-testing) +5. Prow job configuration (image-consistency-check) +6. ConfigStore config (test template doc ID, Slack group alias) ## Authentication Notes diff --git a/Dockerfile b/Dockerfile index 104554f7701d..6d019d19f457 100644 --- a/Dockerfile +++ b/Dockerfile @@ -41,8 +41,10 @@ RUN case ${TARGETARCH} in \ # Install OAR CLI WORKDIR /usr/src/release-tests COPY . . -RUN uv pip install --python ${PY_BIN} --system . && \ +RUN uv pip install --python ${PY_BIN} --system . ./prow && \ oar --help && \ - oarctl --help + oarctl --help && \ + job --help && \ + jobctl --help CMD [ "/bin/bash" ] diff --git a/docs/KONFLUX_RELEASE_FLOW.md b/docs/KONFLUX_RELEASE_FLOW.md index 9f6973fb2b54..7338f5642194 100644 --- a/docs/KONFLUX_RELEASE_FLOW.md +++ b/docs/KONFLUX_RELEASE_FLOW.md @@ -649,11 +649,11 @@ OR **Purpose:** Verify image consistency across architectures -**MCP Tool:** `oar_image_consistency_check(release, build_number=None)` +**MCP Tool:** `oar_image_consistency_check(release, job_id=None)` **Input:** - `release`: Z-stream version -- `build_number`: Optional Jenkins build number (for status check) +- `job_id`: Optional Prow job ID (for status check) **Prerequisites:** - Build promotion detected (phase == "Accepted") @@ -667,10 +667,10 @@ Execute: oar_image_consistency_check(release) # Possible outcomes: -# Success - Jenkins job triggered: +# Success - Prow job triggered: stdout contains: "task [Image consistency check] status is changed to [In Progress]" AND -Capture Jenkins build number from stdout pattern +Capture Prow job ID from stdout pattern # OR @@ -696,10 +696,10 @@ IF stage-release pipeline error detected: RETURN (do not mark as failed - this is a prerequisite wait state) ``` -**Phase 2 - Check Status (when build_number available):** +**Phase 2 - Check Status (when job_id available):** ```python When user invokes /release:drive: - Execute: oar_image_consistency_check(release, build_number={captured_build_number}) + Execute: oar_image_consistency_check(release, job_id={captured_job_id}) Check stdout for status update ``` @@ -1177,13 +1177,13 @@ Report to user: "Build promoted (phase: Accepted)! Triggering async tasks now... oar_image_consistency_check(release="4.20.1") oar_stage_testing(release="4.20.1") -# Capture Jenkins build numbers -consistency_build = parse_build_number(stdout) -stage_build = parse_build_number(stdout) +# Capture job IDs +consistency_job_id = parse_job_id(stdout) # Prow job ID +stage_build = parse_build_number(stdout) # Jenkins build number Report to user: """ 2 async tasks triggered: -- image-consistency-check (build #{consistency_build}) +- image-consistency-check (Prow job ID: {consistency_job_id}) - stage-testing (build #{stage_build}) These tasks are now running in parallel with test result analysis. @@ -1198,7 +1198,7 @@ RETURN ```python # First check async task status oar_push_to_cdn_staging(release="4.20.1") # Check status -oar_image_consistency_check(release="4.20.1", build_number=consistency_build) +oar_image_consistency_check(release="4.20.1", job_id=consistency_job_id) oar_stage_testing(release="4.20.1", build_number=stage_build) async_tasks_status = { diff --git a/mcp_server/server.py b/mcp_server/server.py index c400cf0b9029..5b28c73e4cc2 100644 --- a/mcp_server/server.py +++ b/mcp_server/server.py @@ -690,23 +690,26 @@ async def oar_image_signed_check(release: str) -> str: # ============================================================================ @mcp.tool() -async def oar_image_consistency_check(release: str, build_number: str = None) -> str: +async def oar_image_consistency_check(release: str, job_id: str = None) -> str: """ Check status of image consistency check or start new check. - If build_number is provided, queries existing job status (READ-ONLY). - If build_number is not provided, starts new consistency check (WRITE). + Triggers a Prow job via Gangway API to verify payload images match shipment. + Requires APITOKEN environment variable for Prow authentication. + + If job_id is provided, queries existing Prow job status (READ-ONLY). + If job_id is not provided, starts new consistency check (WRITE). Args: release: Z-stream release version (e.g., "4.19.1") - build_number: Optional specific build number to check status + job_id: Optional Prow job ID to check status Returns: Job status information or new job details """ args = [] - if build_number is not None and build_number != "": - args.extend(["-n", build_number]) + if job_id is not None and job_id != "": + args.extend(["-i", job_id]) result = await invoke_oar_command_async(release, "image-consistency-check", args) return format_result(result) @@ -1480,7 +1483,7 @@ async def oar_add_issue( oar_add_issue("4.19.1", "ART build pipeline down - ETA: 2025-01-16", True, None) # Non-blocking issue (automation improvement) - oar_add_issue("4.19.1", "Jenkins job timeout - retry succeeded", False, "image-consistency-check") + oar_add_issue("4.19.1", "Prow job timeout - retry succeeded", False, "image-consistency-check") """ try: cs = get_cached_configstore(release) diff --git a/oar/README.md b/oar/README.md index 7380c655ef97..bc9858e18d39 100644 --- a/oar/README.md +++ b/oar/README.md @@ -43,7 +43,7 @@ Commands: create-test-report Create test report for z-stream release take-ownership Take ownership for advisory and jira subtasks update-bug-list Update bug status listed in report, update... - image-consistency-check Check if images in advisories and payload... + image-consistency-check Check if images in payload and shipment... check-greenwave-cvp-tests Check Greenwave CVP test results for all... check-cve-tracker-bug Check if there is any missed CVE tracker bug push-to-cdn-staging Trigger push job for cdn stage targets @@ -72,10 +72,10 @@ $ oar -r $release-version take-ownership -e foo@bar.com ``` $ oar -r $release-version update-bug-list ``` -4. This command triggers image-consistency-check jenkins job to verify images in release payload. The build number is returned with the first run. The build number can be used as an option for subsequent run to check jenkins job status +4. This command triggers image-consistency-check Prow job via Gangway API to verify images in release payload match images in shipment. The Prow job ID is returned with the first run. The job ID can be used as an option for subsequent run to check job status ``` $ oar -r $release-version image-consistency-check -$ oar -r $release-version image-consistency-check -n 123 +$ oar -r $release-version image-consistency-check -i ``` 5. This command checks all Greenwave CVP tests of all advisories. Expected result is that all tests finish with status `PASSED/WAIVED`. If any of the tests failed, you can trigger `Refetch` with the test id and corresponding advisory number. You can get those parameters from this command output. If the test is still failing after refetch, contact CVP team via Google Spaces [CVP] ``` diff --git a/oar/cli/cmd_image_consistency_check.py b/oar/cli/cmd_image_consistency_check.py index 0dbbde2dabc5..27f0a6135fd7 100644 --- a/oar/cli/cmd_image_consistency_check.py +++ b/oar/cli/cmd_image_consistency_check.py @@ -1,9 +1,9 @@ import logging import click + +from job.job import Jobs from oar.core.const import * -from oar.core.exceptions import JenkinsHelperException -from oar.core.jenkins import JenkinsHelper from oar.core.notification import NotificationManager from oar.core.operators import ImageHealthOperator from oar.core.statebox import StateBox @@ -11,89 +11,87 @@ logger = logging.getLogger(__name__) + class ImageConsistencyChecker: def __init__(self, cs): self.cs = cs - self.jh = JenkinsHelper(cs) self.nm = NotificationManager(cs) self.io = ImageHealthOperator(cs) self.statebox = StateBox(cs) + self.jobs = Jobs() - def trigger_job(self, for_nightly): - """ - Trigger image consistency check job if needed - - Args: - for_nightly (bool): Whether to use nightly build or stable build - """ - # Check task status from StateBox + def trigger_job(self): + """Trigger image consistency check Prow job.""" task_status = self.statebox.get_task_status(TASK_IMAGE_CONSISTENCY_CHECK) if task_status in [TASK_STATUS_PASS, TASK_STATUS_INPROGRESS]: logger.info(f"Image consistency check already {task_status}, skipping") return - if self.jh.is_job_enqueue(JENKINS_JOB_IMAGE_CONSISTENCY_CHECK): - logger.warning("There is pending job in the queue, please try again later") - return - try: - # Log in-progress status for cli_result_callback parsing util.log_task_status(TASK_IMAGE_CONSISTENCY_CHECK, TASK_STATUS_INPROGRESS) - pull_spec = self._get_pull_spec(for_nightly) - build_info = self.jh.call_image_consistency_job(pull_spec) - logger.info(f"Triggered image consistency check job: {build_info}") + payload_url = f"quay.io/openshift-release-dev/ocp-release:{self.cs.release}-x86_64" + mr_url = self.cs.get_shipment_mr() + if not mr_url: + raise Exception( + f"No shipment MR found for release {self.cs.release}. " + "Image consistency check requires Konflux flow with a shipment MR." + ) + _, mr_id = util.parse_mr_url(mr_url) + + job_status = self.jobs.run_image_consistency_check(payload_url, mr_id) + job_url = job_status.get("jobURL") + job_id = job_status.get("jobID") + logger.info(f"Triggered image consistency check Prow job: {job_id}") + logger.info(f"Prow job URL: {job_url}") - self.nm.share_jenkins_build_url(JENKINS_JOB_IMAGE_CONSISTENCY_CHECK, build_info) - except JenkinsHelperException as je: - logger.error(f"Failed to trigger image-consistency-check job: {str(je)}") - # Log fail status for cli_result_callback parsing + self.nm.share_prow_job_url(Jobs.IMAGE_CONSISTENCY_CHECK_JOB_NAME, job_url) + except Exception as e: + logger.error(f"Failed to trigger image consistency check Prow job: {e}") util.log_task_status(TASK_IMAGE_CONSISTENCY_CHECK, TASK_STATUS_FAIL) raise - def _get_pull_spec(self, for_nightly): - """Get pull spec based on build type""" - if for_nightly: - if "x86_64" not in self.cs.get_candidate_builds(): - raise JenkinsHelperException("No candidate nightly build for architecture x86_64") - return f"registry.ci.openshift.org/ocp/release:{self.cs.get_candidate_builds().get('x86_64')}" - return f"quay.io/openshift-release-dev/ocp-release:{self.cs.release}-x86_64" - - def check_job_status(self, build_number): - """Check job status and update report accordingly""" - logger.info(f"Checking image-consistency-check job status with job id: {build_number}") - - job_status = self.jh.get_build_status("image-consistency-check", build_number) - if job_status == JENKINS_JOB_STATUS_SUCCESS: - # call ImageHealthOperator to check container health, it can handle errata or konflux flow automatically + def check_job_status(self, job_id): + """Check Prow job status and update report accordingly.""" + logger.info(f"Checking image consistency check Prow job status for job ID: {job_id}") + + job_info = self.jobs.get_job_results(job_id) + if job_info is None: + logger.error(f"Could not retrieve job info for job ID: {job_id}") + util.log_task_status(TASK_IMAGE_CONSISTENCY_CHECK, TASK_STATUS_FAIL) + raise Exception(f"Job {job_id} not found or Prow API error") + + job_state = job_info.get("jobState") + job_url = job_info.get("jobURL") + logger.info(f"Job state: {job_state}, URL: {job_url}") + + if job_state == "success": healthy = self.io.check_image_health() task_status = TASK_STATUS_PASS if healthy else TASK_STATUS_FAIL - elif job_status == JENKINS_JOB_STATUS_IN_PROGRESS: + elif job_state in ("pending", "triggered", ""): task_status = TASK_STATUS_INPROGRESS else: task_status = TASK_STATUS_FAIL - # Log status for cli_result_callback parsing util.log_task_status(TASK_IMAGE_CONSISTENCY_CHECK, task_status) + @click.command() @click.pass_context -@click.option("-n", "--build_number", - type=int, - help="Build number to check job status") -@click.option("--for_nightly", - is_flag=True, - help="Use candidate nightly build instead of stable build") -def image_consistency_check(ctx, build_number, for_nightly): +@click.option( + "-i", "--job-id", + type=str, + help="Prow job ID to check status", +) +def image_consistency_check(ctx, job_id): """ - Check if images in advisories and payload are consistent + Check if images in payload are consistent with images in shipment. + + Triggers a Prow job via Gangway API or checks the status of an existing job. """ - if build_number and for_nightly: - raise click.UsageError("Cannot use --for_nightly with build number") - checker = ImageConsistencyChecker(ctx.obj["cs"]) - - if build_number: - checker.check_job_status(build_number) + + if job_id: + checker.check_job_status(job_id) else: - checker.trigger_job(for_nightly) + checker.trigger_job() diff --git a/oar/core/jenkins.py b/oar/core/jenkins.py index 4c483313e663..cbd365d76009 100644 --- a/oar/core/jenkins.py +++ b/oar/core/jenkins.py @@ -45,17 +45,6 @@ def call_stage_job(self): "call stage pipeline job failed") from ej return build_url - def call_image_consistency_job(self, pull_spec): - try: - logger.info(f"triggered a job with {pull_spec}") - build_url = self.call_build_job( - "image-consistency-check", pull_spec) - except (JenkinsException, JenkinsHelperException) as ej: - raise JenkinsHelperException( - "call image-consistency-check pipeline job failed" - ) from ej - return build_url - def get_build_status(self, job_name, build_number): """ get job status via build_number @@ -141,17 +130,7 @@ def call_build_job(self, job_name, pull_spec): build_info = "" try: - if (job_name == JENKINS_JOB_IMAGE_CONSISTENCY_CHECK): - parameters_value = { - "VERSION": "v" + self.version, - "PAYLOAD_URL": pull_spec, - } - # Add SHIPMENT_MR_ID if shipment MR is available - if self.mr_id: - parameters_value["SHIPMENT_MR_ID"] = self.mr_id - else: - parameters_value["ERRATA_NUMBERS"] = self.errata_numbers - elif (job_name == JENKINS_JOB_STAGE_PIPELINE): + if (job_name == JENKINS_JOB_STAGE_PIPELINE): parameters_value = { "VERSION": self.version, "PULL_SPEC": pull_spec, diff --git a/oar/core/notification.py b/oar/core/notification.py index 46cc771e345a..6c55e97d283a 100644 --- a/oar/core/notification.py +++ b/oar/core/notification.py @@ -279,6 +279,20 @@ def share_jenkins_build_url(self, job_name, build_url): raise NotificationException( "share jenkins build url failed") from e + def share_prow_job_url(self, job_name, job_url): + """ + Share notification for new Prow job + """ + try: + slack_msg = self.mh.get_slack_message_for_prow_job( + job_name, job_url) + if len(slack_msg): + self.sc.post_message(self.cs.get_slack_channel_from_contact( + "qe-release"), slack_msg) + except Exception as e: + raise NotificationException( + "share prow job url failed") from e + def share_greenwave_cvp_failures(self, jira_key): """ Share greenwave cvp failures @@ -968,6 +982,25 @@ def get_slack_message_for_jenkins_build(self, job_name, build_info): return message + def get_slack_message_for_prow_job(self, job_name, job_url): + """ + Format slack message for Prow job + + Args: + job_name (str): Prow job name + job_url (str): Prow job url + + Returns: + str: slack message + """ + gid = self.sc.get_group_id_by_name( + self.cs.get_slack_user_group_from_contact( + "qe-release", util.get_y_release(self.cs.release) + ) + ) + + return f"[{self.cs.release}] Hello {gid}, triggered Prow job [{job_name}], url is {job_url}" + def get_slack_message_for_failed_cvp(self, jira_key): """ Get Slack message for failed Greenwave CVP tests diff --git a/oar/core/statebox.py b/oar/core/statebox.py index 64dab4157561..bf1c8efa7dc6 100644 --- a/oar/core/statebox.py +++ b/oar/core/statebox.py @@ -50,7 +50,7 @@ statebox.update_task( "image-consistency-check", status="Pass", - result="Jenkins job completed successfully. All images verified." + result="Prow job completed successfully. All images verified." ) # Add blocking issue (task-specific) diff --git a/tests/test_jenkins.py b/tests/test_jenkins.py index 71df25ce3116..567ec283f27d 100644 --- a/tests/test_jenkins.py +++ b/tests/test_jenkins.py @@ -16,8 +16,3 @@ def test_call_stage_job(self): result = self.jh.call_stage_job() self.assertIsNotNone(result) self.assertIn("Stage-Pipeline", result) - - def test_call_image_consistency_job(self): - result = self.jh.call_image_consistency_job(self.jh.pull_spec) - self.assertIsNotNone(result) - self.assertIn("image-consistency-check", result)