Skip to content

Conversation

@panyamkeerthana
Copy link
Collaborator

@panyamkeerthana panyamkeerthana commented Nov 25, 2025

this script replaces the manual workflow of:
bkr workflow-tomorrow --errata --tps-rhnqa
bkr job-watch J:<job_id>
tps-results --errata= --job=<job_id> --rhnqa

  • fetches errata info and TPS jobs from Errata Tool API
  • generates Beaker XML matching workflow-tomorrow format (check-install, errata/setup, errata/tps, errata/cleanup tasks)
  • gubmits jobs to Beaker and monitors completion
  • parses Beaker job results from XML
  • uploads results to Errata Tool

this implementation avoids the dependency on qa-tools-workstation package (workflow-tomorrow and tps-results) by using public beaker-client library(PyPI) for XML generation and job submission,calling Errata Tool REST/XML-RPC APIs directly, and reverse engineering behavior from workflow-tomorrow and tps-results.

resolves https://github.com/packit/jotnar/issues/266

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a new Python script to automate the TPS RHNQA workflow, which is a significant improvement over the manual process. The script integrates with Errata Tool and Beaker, handling job submission, monitoring, and result uploading. The addition of beaker-client to pyproject.toml is appropriate for this new functionality. Overall, the script provides a valuable automation solution.

However, there are several areas for improvement, particularly regarding error handling, configuration management, and argument parsing. The current implementation uses direct sys.argv access and hardcoded values for critical settings like dry-run flags and URLs, which reduces flexibility and maintainability. Additionally, the SSL verification default behavior and generic exception handling could be improved for robustness and security.

I've provided specific comments on these points to help enhance the script's reliability, configurability, and adherence to best practices.

try:
user = hub.auth.who_am_i()
print(f"authenticated as: {user['username']}")
except Exception as e:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The DRY_RUN flag is hardcoded to True. This should be a command-line argument to allow for actual job submission without modifying the code. This is crucial for the script's utility in a production environment.

    job_id = submit_beaker_job(hub, beaker_xml, dry_run=args.dry_run_submit)

run_tps_rhnqa.py Outdated
print(f"\nStep 8:uploading results to Errata Tool")

#Set to True to test without actually uploading
UPLOAD_DRY_RUN = True
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Similar to DRY_RUN, the UPLOAD_DRY_RUN flag is hardcoded to True. This should also be a command-line argument to enable actual result uploads to Errata Tool.

    uploaded = upload_tps_results(tps_jobs, recipe_list, dry_run=args.dry_run_upload)

run_tps_rhnqa.py Outdated
Comment on lines 31 to 36
def ET_verify() -> bool | str:
verify = os.getenv("REDHAT_IT_CA_BUNDLE")
if verify:
return verify
else:
return False
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The ET_verify function defaults to False for SSL verification if REDHAT_IT_CA_BUNDLE is not set. Disabling SSL verification by default can expose the application to security vulnerabilities like Man-in-the-Middle attacks. It's safer to either:

  1. Default to True (meaning requests will use its default CA bundle).
  2. Raise an error if the bundle is expected but not found, forcing explicit configuration.

If REDHAT_IT_CA_BUNDLE is truly optional, ensure the security implications of verify=False are understood and accepted.

Suggested change
def ET_verify() -> bool | str:
verify = os.getenv("REDHAT_IT_CA_BUNDLE")
if verify:
return verify
else:
return False
@cache
def ET_verify() -> bool | str:
verify = os.getenv("REDHAT_IT_CA_BUNDLE")
if verify:
return verify
# Default to True for secure connections if no custom bundle is provided
return True

Copy link
Collaborator Author

@panyamkeerthana panyamkeerthana Nov 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To run locally I was setting the CA bundle to False otherwise getting a SSL cert error

Comment on lines +249 to +253
except Exception as e:
print(f"job submission failed. Error: {e}")

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Catching a generic Exception can hide underlying issues and make debugging difficult. It's better to catch more specific exceptions (e.g., bkr.client.errors.BeakerError or requests.exceptions.RequestException if the hub.jobs.upload could raise network errors) and handle them appropriately. This allows for more precise error reporting and recovery.

Suggested change
except Exception as e:
print(f"job submission failed. Error: {e}")
except bkr.client.errors.BeakerError as e:
print(f"job submission failed. Beaker error: {e}")
except Exception as e:
print(f"job submission failed. Unexpected error: {e}")

Comment on lines +480 to +484
#workaround for nonexisting ET status Error
if errata_status == 'ERROR':
errata_status = 'BAD'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This 'workaround for nonexisting ET status Error' indicates a potential mismatch between Beaker's result states and Errata Tool's expected statuses. While the workaround addresses the immediate problem, it might be worth investigating if a more direct mapping or a new status in Errata Tool could be introduced to accurately reflect 'Error' states from Beaker.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment on lines +524 to +527
if len(sys.argv) < 2:
sys.exit(1)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using sys.argv directly for command-line arguments is less robust than using a dedicated argument parsing library like argparse. argparse provides features like help messages, type checking, and default values, making the script more user-friendly and maintainable.

Suggested change
if len(sys.argv) < 2:
sys.exit(1)
import argparse
parser = argparse.ArgumentParser(description="Automate TPS RHNQA workflow.")
parser.add_argument("errata_id", type=str, help="Errata ID to process.")
parser.add_argument("--dry-run-submit", action="store_true", help="Perform a dry run for job submission to Beaker.")
parser.add_argument("--dry-run-upload", action="store_true", help="Perform a dry run for uploading results to Errata Tool.")
args = parser.parse_args()
errata_id = args.errata_id

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great suggestion! I'll look into this

Comment on lines +19 to +28
ERRATA_URL = "https://errata.devel.redhat.com"
ERRATA_XMLRPC = "https://errata.devel.redhat.com/errata/errata_service"
ERRATA_TPS_XMLRPC = "https://errata.devel.redhat.com/tps/tps_service"
BEAKER_URL = "https://beaker.engineering.redhat.com"
CHECK_INSTALL_TASK = "/distribution/check-install"
SETUP_TASK = "/distribution/errata/setup"
TPS_TASK = "/distribution/errata/tps"
CLEANUP_TASK = "/distribution/errata/cleanup"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

These URLs and task paths are currently hardcoded. While they might be stable for the current environment, it's generally better to make such configurations external (e.g., environment variables, a dedicated config file, or command-line arguments). This allows for easier adaptation to different environments (e.g., staging, production, local development) without modifying the code.

Consider using os.getenv() for URLs or argparse for command-line options.

@panyamkeerthana panyamkeerthana force-pushed the panyamkeerthana/tps-rhnqa-automation branch from 35406f5 to 4ec5a1d Compare November 25, 2025 16:22
this script replaces the manual workflow of:
  bkr workflow-tomorrow --errata <id> --tps-rhnqa
  bkr job-watch J:<job_id>
  tps-results --errata=<id> --job=<job_id> --rhnqa

- fetches errata info and TPS jobs from Errata Tool API
- generates Beaker XML matching workflow-tomorrow format
  (check-install, errata/setup, errata/tps, errata/cleanup tasks)
- gubmits jobs to Beaker and monitors completion
- parses Beaker job results from XML
- uploads results to Errata Tool

this implementation avoids the dependency on qa-tools-workstation package
(workflow-tomorrow and tps-results) by using public beaker-client
library(PyPI) for XML generation and job submission,calling Errata Tool
REST/XML-RPC APIs directly, and reverse engineering behavior from
workflow-tomorrow and tps-results
@panyamkeerthana panyamkeerthana force-pushed the panyamkeerthana/tps-rhnqa-automation branch from 6efa56b to 8238fa0 Compare November 25, 2025 17:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant