Skip to content
This repository has been archived by the owner on Jul 30, 2024. It is now read-only.

Launch reproducer wrapper #35

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,26 @@ options:
The number of builds to fetch when searching for a reproducer.
```

### `squad-create-reproducer-from-testrun`: Get a reproducer for a given TestRun ID.

This script fetches the build or test reproducer for a given TestRun ID.

```
usage: squad-create-reproducer-from-testrun [-h] --testrun TESTRUN [--debug]
[--filename FILENAME] [--local | --plan]

Provide a SQUAD TestRun ID to download the build or test reproducer for that TestRun. The
reproducer will be printed to the terminal and written to a file.

optional arguments:
-h, --help show this help message and exit
--testrun TESTRUN The TestRun ID of the build or test to fetch the reproducer for.
--debug Display debug messages.
--filename FILENAME Name for the reproducer file, 'reproducer' by default.
--local Fetch a TuxRun or TuxMake reproducer rather than a TuxSuite reproducer.
--plan Fetch a TuxPlan reproducer rather than a TuxTest of TuxBuild reproducer.
```

### `squad-create-skipfile-reproducers`: Creating skipfile reproducers

The `squad-create-skipfile-reproducers` script can be used to create TuxRun or
Expand Down
11 changes: 11 additions & 0 deletions fetch-and-launch-reproducer.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Environment variables needed:
# - TUXSUITE_TOKEN - the token to submit tuxsuite reproducer

TESTRUN=$1
REPRODUCER=$2
pip install -r requirements.txt
inputs="--testrun $TESTRUN --filename $REPRODUCER"
echo $inputs
python validate-inputs.py $inputs
python squad-create-reproducer-from-testrun $inputs --plan
tuxsuite plan $REPRODUCER
100 changes: 100 additions & 0 deletions squad-create-reproducer-from-testrun
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# vim: set ts=4
#
# Copyright 2023-present Linaro Limited
#
# SPDX-License-Identifier: MIT


from argparse import ArgumentParser
from logging import INFO, basicConfig, getLogger
from os import chmod, getenv
from stat import S_IRUSR, S_IWUSR, S_IXUSR
from sys import exit

from squad_client.core.api import SquadApi

from squadutilslib import (
ReproducerNotFound,
get_reproducer_from_testrun,
)

squad_host_url = "https://qa-reports.linaro.org/"
SquadApi.configure(cache=3600, url=getenv("SQUAD_HOST", squad_host_url))

basicConfig(level=INFO)
logger = getLogger(__name__)


def parse_args(raw_args):
parser = ArgumentParser(
description="Provide a SQUAD TestRun ID to download the build or test reproducer for that TestRun."
+ " The reproducer will be printed to the terminal and written to a file."
)

parser.add_argument(
"--testrun",
required=True,
help="The TestRun ID of the build or test to fetch the reproducer for.",
)

# Optional arguments:
parser.add_argument(
"--debug",
required=False,
action="store_true",
default=False,
help="Display debug messages.",
)

parser.add_argument(
"--filename",
required=False,
default="reproducer",
help="Name for the reproducer file, 'reproducer' by default.",
)

group = parser.add_mutually_exclusive_group()

group.add_argument(
"--local",
required=False,
action="store_true",
default=False,
help="Fetch a TuxRun or TuxMake reproducer rather than a TuxSuite reproducer.",
)

group.add_argument(
"--plan",
required=False,
action="store_true",
default=False,
help="Fetch a TuxPlan reproducer rather than a TuxTest of TuxBuild reproducer.",
)

return parser.parse_args(raw_args)


def run(raw_args=None):
args = parse_args(raw_args)

try:
reproducer, is_test_reproducer = get_reproducer_from_testrun(
args.testrun, args.filename, args.plan, args.local
)

except ReproducerNotFound as e:
logger.error(f"No reproducer could be found for TestRun {args.testrun}")
logger.error(f"{e}")
return -1

print(reproducer)

# Make the script executable
chmod(args.filename, S_IXUSR | S_IRUSR | S_IWUSR)
logger.info(f"file created: {args.filename}")


if __name__ == "__main__":
exit(run())
73 changes: 60 additions & 13 deletions squadutilslib.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,62 @@ def get_file(path, filename=None):
raise Exception(f"Path {path} not found")


def get_reproducer_from_testrun(testrun_id, filename, plan=False, local=False):
"""Given a testrun, download its reproducer."""
testrun = TestRun(testrun_id)
is_test_reproducer = None
reproducer = None

if local and plan:
logger.error("Error: not valid to request both plan=True and local=True.")
raise ReproducerNotFound

# If there is a download_url try to treat it as a build
if testrun.metadata.download_url:
try:
if local:
reproducer_file = get_file(
testrun.metadata.download_url + "/tuxmake_reproducer.sh", filename
)
elif plan:
reproducer_file = get_file(
testrun.metadata.download_url + "/tux_plan.yaml", filename
)
else:
reproducer_file = get_file(
testrun.metadata.download_url + "/tuxsuite_reproducer.sh", filename
)
is_test_reproducer = False
with open(reproducer_file) as f:
reproducer = f.read()
except HTTPError:
pass

if not reproducer:
# If no build reproducer was found, treat it as a test
try:
if local:
reproducer_file = get_file(
testrun.metadata.job_url + "/reproducer", filename
)
elif plan:
reproducer_file = get_file(
testrun.metadata.job_url + "/tux_plan", filename
)
else:
reproducer_file = get_file(
testrun.metadata.job_url + "/tuxsuite_reproducer", filename
)
is_test_reproducer = True
with open(reproducer_file) as f:
reproducer = f.read()
except HTTPError:
logger.error("No build or test reproducer found.")
raise ReproducerNotFound

return reproducer, is_test_reproducer


def filter_projects(projects, pattern):
filtered = []
for p in projects:
Expand Down Expand Up @@ -193,20 +249,11 @@ def get_reproducer(
# In theory there should only be one of those
logger.debug(f"Testrun id: {testrun.id}")

try:
if local:
reproducer = get_file(
f"{testrun.job_url}/reproducer", filename=filename
)
else:
reproducer = get_file(
f"{testrun.job_url}/tuxsuite_reproducer", filename=filename
)
except HTTPError:
logger.error(f"Reproducer not found at {testrun.job_url}!")
raise ReproducerNotFound
reproducer, is_test_reproducer = get_reproducer_from_testrun(
testrun_id=testrun.id, filename=filename, plan=False, local=local
)
return (
Path(reproducer).read_text(encoding="utf-8"),
reproducer,
Build(getid(testrun.build)).metadata.git_describe,
testrun.metadata.build_name,
)
Expand Down
44 changes: 44 additions & 0 deletions validate-inputs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
from argparse import ArgumentParser
import logging


logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)


def parse_args(raw_args):
parser = ArgumentParser()

parser.add_argument(
"--testrun",
required=True,
help="The ID of the TestRun.",
)

parser.add_argument(
"--filename",
required=True,
help="The reproducer file.",
)

parser.add_argument(
"--plan",
required=False,
action="store_true",
default=False,
help="Fetch a TuxPlan reproducer rather than a TuxTest of TuxBuild reproducer.",
)

return parser.parse_args(raw_args)


def run(raw_args=None):
args = parse_args(raw_args)

logger.debug(args)

return 0


if __name__ == "__main__":
exit(run())
Loading