From 6e41708a76e3605844fdf3b65eecf3dedcd650d7 Mon Sep 17 00:00:00 2001 From: Denys Fedoryshchenko Date: Wed, 15 Jan 2025 20:03:00 +0200 Subject: [PATCH 1/3] fix(bisect.py): Fix initial tree creation If linux tree source code doesn't exist (workdir), bisection will fail due wrong sequence of commands. Signed-off-by: Denys Fedoryshchenko --- kcidev/subcommands/bisect.py | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/kcidev/subcommands/bisect.py b/kcidev/subcommands/bisect.py index 514bad8..c239899 100644 --- a/kcidev/subcommands/bisect.py +++ b/kcidev/subcommands/bisect.py @@ -133,6 +133,20 @@ def init_bisect(state): return commitid +def update_tree(workdir, branch, giturl): + if not os.path.exists(workdir): + click.secho( + "Cloning repository (this might take significant time!)", fg="green" + ) + repo = Repo.clone_from(giturl, workdir) + repo.git.checkout(branch) + else: + click.secho("Pulling repository", fg="green") + repo = Repo(workdir) + repo.git.checkout(branch) + repo.git.pull() + + def bisection_loop(state): olddir = os.getcwd() os.chdir(state["workdir"]) @@ -258,20 +272,11 @@ def bisect( state["platformfilter"] = platformfilter state["test"] = test state["workdir"] = workdir + update_tree(workdir, branch, giturl) save_state(state, state_file) else: print_state(state) - - # if workdir doesnt exist, clone the repository - if not os.path.exists(workdir): - click.secho("Cloning repository", fg="green") - repo = Repo.clone_from(giturl, workdir) - repo.git.checkout(branch) - else: - click.secho("Pulling repository", fg="green") - repo = Repo(workdir) - repo.git.checkout(branch) - repo.git.pull() + update_tree(workdir, branch, giturl) if not state["bisect_init"]: state["next_commit"] = init_bisect(state) From 7e569ddde13610d69fc2b580d1662281f124a895 Mon Sep 17 00:00:00 2001 From: Denys Fedoryshchenko Date: Wed, 15 Jan 2025 21:28:28 +0200 Subject: [PATCH 2/3] feat(bisect.py): Add more verbosity in case of failure Make git bisection failure more verbose, to understand what is happening on error. Signed-off-by: Denys Fedoryshchenko --- kcidev/subcommands/bisect.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/kcidev/subcommands/bisect.py b/kcidev/subcommands/bisect.py index c239899..4d1a5d7 100644 --- a/kcidev/subcommands/bisect.py +++ b/kcidev/subcommands/bisect.py @@ -76,7 +76,9 @@ def git_exec_getcommit(cmd): click.secho("Executing git command: " + " ".join(cmd), fg="green") result = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) if result.returncode != 0: - click.secho("git command return failed", fg="red") + click.secho("git command return failed. Error:", fg="red") + click.secho(result.stderr, fg="red") + click.secho(result.stdout, fg="red") sys.exit(1) lines = result.stdout.split(b"\n") if len(lines) < 2: From c5b6427259756296fb525d9381ad7fc4f66faa48 Mon Sep 17 00:00:00 2001 From: Denys Fedoryshchenko Date: Thu, 16 Jan 2025 17:57:02 +0200 Subject: [PATCH 3/3] update: Add dash in platformfilter and jobfilter platformfilter and jobfilter a bit difficult to read, so let's change parameters to job-filter and platform-filter. Updating documentation accordingly. Signed-off-by: Denys Fedoryshchenko --- docs/checkout.md | 20 ++++++++-------- kcidev/subcommands/bisect.py | 38 ++++++++++++++--------------- kcidev/subcommands/checkout.py | 44 +++++++++++++++++----------------- 3 files changed, 51 insertions(+), 51 deletions(-) diff --git a/docs/checkout.md b/docs/checkout.md index 4452a1f..64208d8 100644 --- a/docs/checkout.md +++ b/docs/checkout.md @@ -10,21 +10,21 @@ This might be useful in several cases: - You want to create snapshot of the test results on specific tags (releases, etc). - Use this command for regression bisection -This command can execute all tests configured for particular tree/branch, or you can provide jobfilter to execute specific tests and builds. +This command can execute all tests configured for particular tree/branch, or you can provide job-filter to execute specific tests and builds. Example: ```sh -kci-dev checkout --giturl https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git --branch master --commit f06021a18fcf8d8a1e79c5e0a8ec4eb2b038e153 --jobfilter "kbuild-gcc-12-x86" +kci-dev checkout --giturl https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git --branch master --commit f06021a18fcf8d8a1e79c5e0a8ec4eb2b038e153 --job-filter "kbuild-gcc-12-x86" ``` Where: - `giturl` is the URL of the git repository to test. - `branch` is the branch of the git repository to test. - `commit` is the commit hash to test. -- `jobfilter` is the job filter to use for the test (optional parameter) -- `platformfilter` is the platform filter (usually it is name of hardware platform for group of devices) to use for the test (optional parameter) +- `job-filter` is the job filter to use for the test (optional parameter) +- `platform-filter` is the platform filter (usually it is name of hardware platform for group of devices) to use for the test (optional parameter) -To figure out correct jobfilter and platformfilter, you need to check test json node. For example: +To figure out correct job-filter and platform-filter, you need to check test json node. For example: ```json { "id": "670f0c27493b6b8188c7667c", @@ -81,7 +81,7 @@ To figure out correct jobfilter and platformfilter, you need to check test json "kernel_type": "image" }, "debug": null, - "jobfilter": null, + "job-filter": null, "platform_filter": null, "created": "2024-10-16T00:43:19.079000", "updated": "2024-10-16T02:22:58.113000", @@ -94,9 +94,9 @@ To figure out correct jobfilter and platformfilter, you need to check test json } ``` -In this example, the jobfilter is `tast-mm-misc-arm64-qualcomm` for test, if you look into path, you can figure out also build job named and the platformfilter is `kbuild-gcc-12-arm64-chromeos-qualcomm` and in data/platform: `sc7180-trogdor-lazor-limozeen`. So complete command to test this job would be: +In this example, the job-filter is `tast-mm-misc-arm64-qualcomm` for test, if you look into path, you can figure out also build job named and the platform-filter is `kbuild-gcc-12-arm64-chromeos-qualcomm` and in data/platform: `sc7180-trogdor-lazor-limozeen`. So complete command to test this job would be: ```sh -kci-dev checkout --giturl https://github.com/kernelci/linux.git --branch staging-mainline --commit c862449c840a37bbe797a0b719881449beac75ca --jobfilter tast-mm-misc-arm64-qualcomm --jobfilter kbuild-gcc-12-arm64-chromeos-qualcomm --platformfilter sc7180-trogdor-lazor-limozeen +kci-dev checkout --giturl https://github.com/kernelci/linux.git --branch staging-mainline --commit c862449c840a37bbe797a0b719881449beac75ca --job-filter tast-mm-misc-arm64-qualcomm --job-filter kbuild-gcc-12-arm64-chromeos-qualcomm --platform-filter sc7180-trogdor-lazor-limozeen ``` Other options: @@ -111,7 +111,7 @@ Additionally, you can use --watch option to watch the progress of the test. After executing the command, you will see the output similar to the following: ```sh -./kci-dev.py checkout --giturl https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git --branch master --tipoftree --jobfilter baseline-nfs-arm64-qualcomm --jobfilter kbuild-gcc-12-arm64-chromeos-qualcomm --watch +./kci-dev.py checkout --giturl https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git --branch master --tipoftree --job-filter baseline-nfs-arm64-qualcomm --job-filter kbuild-gcc-12-arm64-chromeos-qualcomm --watch api connect: https://staging.kernelci.org:9100/ Retrieving latest commit on tree: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git branch: master Commit to checkout: d3d1556696c1a993eec54ac585fe5bf677e07474 @@ -170,7 +170,7 @@ Together with --watch option, you can use --test option to wait for particular t For example: ```sh -kci-dev.py checkout --giturl https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git --branch master --tipoftree --jobfilter baseline-nfs-arm64-qualcomm --jobfilter kbuild-gcc-12-arm64-chromeos-qualcomm --platformfilter sc7180-trogdor-kingoftown --watch --test crit +kci-dev.py checkout --giturl https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git --branch master --tipoftree --job-filter baseline-nfs-arm64-qualcomm --job-filter kbuild-gcc-12-arm64-chromeos-qualcomm --platform-filter sc7180-trogdor-kingoftown --watch --test crit ``` This command will wait for the test results of the test with the name `crit`. diff --git a/kcidev/subcommands/bisect.py b/kcidev/subcommands/bisect.py index 4d1a5d7..334acc6 100644 --- a/kcidev/subcommands/bisect.py +++ b/kcidev/subcommands/bisect.py @@ -29,8 +29,8 @@ "good": "", "bad": "", "history": [], - "jobfilter": [], - "platformfilter": [], + "job_filter": [], + "platform_filter": [], "test": "", "workdir": "", "bisect_init": False, @@ -59,8 +59,8 @@ def print_state(state): click.secho("bad: " + state["bad"], fg="green") click.secho("retryfail: " + str(state["retryfail"]), fg="green") click.secho("history: " + str(state["history"]), fg="green") - click.secho("jobfilter: " + str(state["jobfilter"]), fg="green") - click.secho("platformfilter: " + str(state["platformfilter"]), fg="green") + click.secho("job_filter: " + str(state["job_filter"]), fg="green") + click.secho("platform_filter: " + str(state["platform_filter"]), fg="green") click.secho("test: " + state["test"], fg="green") click.secho("workdir: " + state["workdir"], fg="green") click.secho("bisect_init: " + str(state["bisect_init"]), fg="green") @@ -170,12 +170,12 @@ def bisection_loop(state): commit, "--watch", ] - # jobfilter is array, so we need to add each element as a separate argument - for job in state["jobfilter"]: - cmd.append("--jobfilter") + # job_filter is array, so we need to add each element as a separate argument + for job in state["job_filter"]: + cmd.append("--job_filter") cmd.append(job) - for platform in state["platformfilter"]: - cmd.append("--platformfilter") + for platform in state["platform_filter"]: + cmd.append("--platform_filter") cmd.append(platform) result = kcidev_exec(cmd) try: @@ -215,8 +215,8 @@ def bisection_loop(state): @click.option("--workdir", help="define the repository origin", default="kcidev-src") @click.option("--ignorestate", help="ignore save state", is_flag=True) @click.option("--statefile", help="state file", default="state.json") -@click.option("--jobfilter", help="filter the job", multiple=True) -@click.option("--platformfilter", help="filter the platform", multiple=True) +@click.option("--job-filter", help="filter the job", multiple=True) +@click.option("--platform-filter", help="filter the platform", multiple=True) @click.option("--test", help="Test expected to fail") # test @@ -231,8 +231,8 @@ def bisect( workdir, ignorestate, statefile, - jobfilter, - platformfilter, + job_filter, + platform_filter, test, ): config = ctx.obj.get("CFG") @@ -255,11 +255,11 @@ def bisect( if not bad: click.secho("--bad is required", fg="red") return - if not jobfilter: - click.secho("--jobfilter is required", fg="red") + if not job_filter: + click.secho("--job_filter is required", fg="red") return - if not platformfilter: - click.secho("--platformfilter is required", fg="red") + if not platform_filter: + click.secho("--platform_filter is required", fg="red") return if not test: click.secho("--test is required", fg="red") @@ -270,8 +270,8 @@ def bisect( state["good"] = good state["bad"] = bad state["retryfail"] = retryfail - state["jobfilter"] = jobfilter - state["platformfilter"] = platformfilter + state["job_filter"] = job_filter + state["platform_filter"] = platform_filter state["test"] = test state["workdir"] = workdir update_tree(workdir, branch, giturl) diff --git a/kcidev/subcommands/checkout.py b/kcidev/subcommands/checkout.py index ac21adf..12e4f54 100644 --- a/kcidev/subcommands/checkout.py +++ b/kcidev/subcommands/checkout.py @@ -41,10 +41,10 @@ def send_checkout_full(baseurl, token, **kwargs): "url": kwargs["giturl"], "branch": kwargs["branch"], "commit": kwargs["commit"], - "jobfilter": kwargs["jobfilter"], + "jobfilter": kwargs["job_filter"], } - if "platformfilter" in kwargs: - data["platformfilter"] = kwargs["platformfilter"] + if "platform_filter" in kwargs: + data["platformfilter"] = kwargs["platform_filter"] jdata = json.dumps(data) print(jdata) try: @@ -107,13 +107,13 @@ def check_node(node): return "FAIL" -def watch_jobs(baseurl, token, treeid, jobfilter, test): - # we need to add to jobfilter "checkout" node - jobfilter = list(jobfilter) - jobfilter.append("checkout") +def watch_jobs(baseurl, token, treeid, job_filter, test): + # we need to add to job_filter "checkout" node + job_filter = list(job_filter) + job_filter.append("checkout") while True: inprogress = 0 - joblist = jobfilter.copy() + joblist = job_filter.copy() nodes = retrieve_treeid_nodes(baseurl, token, treeid) if not nodes: click.secho("No nodes found. Retrying...", fg="yellow") @@ -122,17 +122,17 @@ def watch_jobs(baseurl, token, treeid, jobfilter, test): time_local = time.localtime() click.echo(f"Current time: {time.strftime('%Y-%m-%d %H:%M:%S', time_local)}") click.secho( - f"Total tree nodes {len(nodes)} found. Jobfilter: {jobfilter}", fg="green" + f"Total tree nodes {len(nodes)} found. job_filter: {job_filter}", fg="green" ) - # Tricky part in watch is that we might have one item in jobfilter (job, test), + # Tricky part in watch is that we might have one item in job_filter (job, test), # but it might spawn multiple nodes with same name test_result = None jobs_done_ts = None for node in nodes: if node["name"] == test: test_result = node["result"] - if node["name"] in jobfilter: + if node["name"] in job_filter: result = check_node(node) if result == "DONE": if isinstance(joblist, list) and node["name"] in joblist: @@ -219,17 +219,17 @@ def retrieve_tot_commit(repourl, branch): ) @click.option( "--watch", - help="Interactively watch for a tasks in jobfilter", + help="Interactively watch for a tasks in job-filter", is_flag=True, ) -# jobfilter is a list, might be one or more jobs +# job_filter is a list, might be one or more jobs @click.option( - "--jobfilter", + "--job-filter", help="Job filter to trigger", multiple=True, ) @click.option( - "--platformfilter", + "--platform-filter", help="Platform filter to trigger", multiple=True, ) @@ -239,17 +239,17 @@ def retrieve_tot_commit(repourl, branch): ) @click.pass_context def checkout( - ctx, giturl, branch, commit, jobfilter, platformfilter, tipoftree, watch, test + ctx, giturl, branch, commit, job_filter, platform_filter, tipoftree, watch, test ): cfg = ctx.obj.get("CFG") instance = ctx.obj.get("INSTANCE") url = api_connection(cfg[instance]["pipeline"]) apiurl = cfg[instance]["api"] token = cfg[instance]["token"] - if not jobfilter: - jobfilter = None + if not job_filter: + job_filter = None click.secho("No job filter defined. All jobs will be triggered!", fg="yellow") - if watch and not jobfilter: + if watch and not job_filter: click.secho("No job filter defined. Can't watch for a job(s)!", fg="red") return if test and not watch: @@ -275,8 +275,8 @@ def checkout( giturl=giturl, branch=branch, commit=commit, - jobfilter=jobfilter, - platformfilter=platformfilter, + job_filter=job_filter, + platform_filter=platform_filter, watch=watch, ) if resp and "message" in resp: @@ -292,7 +292,7 @@ def checkout( if test: click.secho(f"Watching for test result: {test}", fg="green") # watch for jobs - watch_jobs(apiurl, token, treeid, jobfilter, test) + watch_jobs(apiurl, token, treeid, job_filter, test) if __name__ == "__main__":