U-Boot Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v1 0/8] This series introduces U-Boot tests with tbot on real hardware.
@ 2025-04-05 18:46 Heiko Schocher
  2025-04-05 18:46 ` [PATCH v1 1/8] test/py/requirements.txt: update coverage Heiko Schocher
                   ` (7 more replies)
  0 siblings, 8 replies; 9+ messages in thread
From: Heiko Schocher @ 2025-04-05 18:46 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Heiko Schocher, Caleb Connolly, Greg Malysa, Heiko Schocher,
	Heinrich Schuchardt, Ilias Apalodimas, Jerome Forissier,
	Love Kumar, Mattijs Korpershoek, Nathan Barrett-Morrison,
	Oliver Gaskell, Robert Marko, Sam Protsenko, Simon Glass,
	Tom Rini


add U-Boot tests on real hardware with tbot, which is
started from gitlab CI (or other CI implementations like
jenkins, github,...)

Currently only one board in my lab@hungary is implemented, if series
gets accepted more will follow. May others are interested too,
and prepare also such setups ... or simply send me hardware, I can
add to my setup.

Current board is the imx8qxp based cxg3 board. To build and get a
working image you need some binary blobs, which are copied from the
lab host to the "CI host". After successfull build the resulting
images are copied to the lab host, and new flash.bin is booted
with uuu tool in USB SDP bootmode, and than installed with fastboot
to the emmc. Than power is switched off, bootmode set to emmc
and it gets checked, that U-Boot boots from emmc now.

Than test/py gets configured and started on the CI host which
runs the tests on the board in tha lab.

Hopefully the approach is generic enough to get other hardware
easy integrated, but if there are problems, just contact me,
if stuff is missing.

You can find a working example @gitlab in my i2c custodian branch
here:

https://source.denx.de/u-boot/custodians/u-boot-i2c/-/jobs/1081203
(If you have no access rights, look below for a test started @github)

I dropped from above repo/branch the following commits in this series:

- tbottest: add github example
  as it is not interesting for U-Boot mainline (or?)

  Just for interest, with that the same test is started from repo @github, example:
  https://github.com/hsdenx/u-boot-test/actions/runs/14212012371/job/39821029362
  to see the full logs open there (Run U-Boot test)

- .gitlab-ci.yml: only start tbot tests
- remove .azure-pipelines.yml
  as this changes are only for speeding up my local testing.

The patches in this series:

- test/py/requirements.txt: update coverage
- tools/buildman/requirements.txt: update coverage
- test/py/requirements.txt: increase filelock version
- test/py/requirements.txt: remove unittest2 and testtools
- test: increase timeouts

are fixing small common issues I found with test/py setup ...
which could be go seperate into mainline, but in the first
shot, I want to have all patches in one series.

- CI: add U-Boot testing on real HW with tbot

  adds all the config needed for testing the imx8qxp based cxg3
  board with tbot in tbottest subdirectory. We should discuss where
  to put this code!

  May into u-boot:/test/tbottest ?

  This setup not only runs on gitlab, it also runs from github,
  jenkins ... or from a local shell without any changes in code. So you
  can use it for your normal development process (what was the goal from
  tbot at the beginning, to be more precise, it was may laziness to type
  a lot of commands on different machines again and again). So if you use
  this setup for your daily work you get the CI integration for free!

- .gitlab-ci.yml: add tbot-lab

  finally integrates the tbot test setup into .gitlab-ci.yml

  This works currently for my I2C custodian repo, with some CI secrets
  stored... we have to add this secrets to u-boot repo to get it up
  and running.

  If this is not possible may I should setup a gitlab runner?
  (Which I would like to prevent... but possible of course, and this
   would prevent the timing issues I fixed when tbot is started somewhere
   in the world)

Bonus patch with an idea for custodians I want to implement, if code
gets accepted:

- scripts: add helper for getting infos from your patchwork ToDo list

  is a preparation for activating my 8 year old setup, which
  downloaded patches from my Patchwork ToDo list, checked them
  with checkpatch.pl script  and applied them with git am, fully
  automated from within the CI !

  With that script it is very easy to reactivate this now again,
  if this is interesting for others. Currently I have not a clean
  patchwork ToDo list, which is the reson for adding this not yet.

  My plan is also to reactivate an automated git bisect session,
  in case there are problems with that patches, so test shows the
  problematic patch at the end... which I think would be a great
  feature and benefit to have in mainline CI.

  For reference an old video on youtube how this worked 8 years ago:

  https://www.youtube.com/watch?v=PhaYfqOrQOg

  It would be nice, we can make such a step configurable through
  a switch we can enable/disable before starting a gitlab CI run.

May time is now ready for it, that people have interests in such
a setup?



Heiko Schocher (8):
  test/py/requirements.txt: update coverage
  tools/buildman/requirements.txt: update coverage
  test/py/requirements.txt: increase filelock version
  test/py/requirements.txt: remove unittest2 and testtools
  test: increase timeouts
  [RFC] CI: add U-Boot testing on real HW with tbot
  .gitlab-ci.yml: add tbot-lab
  scripts: add helper for getting infos from your patchwork ToDo list

 .gitlab-ci.yml                                |  74 ++++
 MAINTAINERS                                   |   6 +
 scripts/getpatchlist.py                       | 126 +++++++
 tbottesting/README.md                         | 323 ++++++++++++++++++
 tbottesting/boardtestconfig.py                |  18 +
 tbottesting/boardtests.py                     |  50 +++
 tbottesting/preparetbot.sh                    |   5 +
 tbottesting/tbotboardtests.py                 | 127 +++++++
 tbottesting/tbotconfig-hs/boardspecific.py    | 111 ++++++
 tbottesting/tbotconfig-hs/hs/README.cxg3      |  28 ++
 tbottesting/tbotconfig-hs/hs/args/argsbase    |  11 +
 tbottesting/tbotconfig-hs/hs/args/argshs      |   1 +
 .../tbotconfig-hs/hs/args/argshs-github-ci    |   7 +
 .../tbotconfig-hs/hs/args/argshs-noeth        |   3 +
 .../tbotconfig-hs/hs/args/argshs-noeth-ssh    |   5 +
 tbottesting/tbotconfig-hs/hs/cxg3.ini         | 106 ++++++
 tbottesting/tbotconfig-hs/hs/tbot.ini         | 117 +++++++
 tbottesting/tbotconfig-hs/interactive.py      |  59 ++++
 tbottesting/tbotconfig-hs/labcallbacks.py     |  76 +++++
 tbottesting/tbotconfig-hs/tc_cxg3.py          |  82 +++++
 test/py/requirements.txt                      |   6 +-
 test/py/u_boot_console_base.py                |   4 +-
 tools/buildman/requirements.txt               |   2 +-
 23 files changed, 1340 insertions(+), 7 deletions(-)
 create mode 100755 scripts/getpatchlist.py
 create mode 100644 tbottesting/README.md
 create mode 100644 tbottesting/boardtestconfig.py
 create mode 100644 tbottesting/boardtests.py
 create mode 100755 tbottesting/preparetbot.sh
 create mode 100644 tbottesting/tbotboardtests.py
 create mode 100644 tbottesting/tbotconfig-hs/boardspecific.py
 create mode 100644 tbottesting/tbotconfig-hs/hs/README.cxg3
 create mode 100644 tbottesting/tbotconfig-hs/hs/args/argsbase
 create mode 100644 tbottesting/tbotconfig-hs/hs/args/argshs
 create mode 100644 tbottesting/tbotconfig-hs/hs/args/argshs-github-ci
 create mode 100644 tbottesting/tbotconfig-hs/hs/args/argshs-noeth
 create mode 100644 tbottesting/tbotconfig-hs/hs/args/argshs-noeth-ssh
 create mode 100644 tbottesting/tbotconfig-hs/hs/cxg3.ini
 create mode 100644 tbottesting/tbotconfig-hs/hs/tbot.ini
 create mode 100644 tbottesting/tbotconfig-hs/interactive.py
 create mode 100644 tbottesting/tbotconfig-hs/labcallbacks.py
 create mode 100644 tbottesting/tbotconfig-hs/tc_cxg3.py

-- 
2.20.1


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v1 1/8] test/py/requirements.txt: update coverage
  2025-04-05 18:46 [PATCH v1 0/8] This series introduces U-Boot tests with tbot on real hardware Heiko Schocher
@ 2025-04-05 18:46 ` Heiko Schocher
  2025-04-05 18:46 ` [PATCH v1 2/8] tools/buildman/requirements.txt: " Heiko Schocher
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Heiko Schocher @ 2025-04-05 18:46 UTC (permalink / raw)
  To: U-Boot Mailing List; +Cc: Heiko Schocher, Heiko Schocher, Simon Glass, Tom Rini

From: Heiko Schocher <hs@nabladev.com>

-coverage==6.2
+coverage==7.6.2

Signed-off-by: Heiko Schocher <hs@nabladev.com>
Signed-off-by: Heiko Schocher <hs@denx.de>
---

 test/py/requirements.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/test/py/requirements.txt b/test/py/requirements.txt
index 75760f96e5..9b15e97f51 100644
--- a/test/py/requirements.txt
+++ b/test/py/requirements.txt
@@ -1,7 +1,7 @@
 atomicwrites==1.4.1
 attrs==19.3.0
 concurrencytest==0.1.2
-coverage==6.2
+coverage==7.6.2
 extras==1.0.0
 filelock==3.0.12
 fixtures==3.0.0
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v1 2/8] tools/buildman/requirements.txt: update coverage
  2025-04-05 18:46 [PATCH v1 0/8] This series introduces U-Boot tests with tbot on real hardware Heiko Schocher
  2025-04-05 18:46 ` [PATCH v1 1/8] test/py/requirements.txt: update coverage Heiko Schocher
@ 2025-04-05 18:46 ` Heiko Schocher
  2025-04-05 18:46 ` [PATCH v1 3/8] test/py/requirements.txt: increase filelock version Heiko Schocher
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Heiko Schocher @ 2025-04-05 18:46 UTC (permalink / raw)
  To: U-Boot Mailing List; +Cc: Heiko Schocher, Heiko Schocher, Simon Glass, Tom Rini

From: Heiko Schocher <hs@nabladev.com>

-coverage==6.2
+coverage==7.6.2

Signed-off-by: Heiko Schocher <hs@nabladev.com>
Signed-off-by: Heiko Schocher <hs@denx.de>
---

 tools/buildman/requirements.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/buildman/requirements.txt b/tools/buildman/requirements.txt
index 052d0ed5c6..50231d1756 100644
--- a/tools/buildman/requirements.txt
+++ b/tools/buildman/requirements.txt
@@ -1,4 +1,4 @@
-coverage==6.2
+coverage==7.6.2
 jsonschema==4.17.3
 pycryptodome==3.20
 pyyaml==6.0
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v1 3/8] test/py/requirements.txt: increase filelock version
  2025-04-05 18:46 [PATCH v1 0/8] This series introduces U-Boot tests with tbot on real hardware Heiko Schocher
  2025-04-05 18:46 ` [PATCH v1 1/8] test/py/requirements.txt: update coverage Heiko Schocher
  2025-04-05 18:46 ` [PATCH v1 2/8] tools/buildman/requirements.txt: " Heiko Schocher
@ 2025-04-05 18:46 ` Heiko Schocher
  2025-04-05 18:46 ` [PATCH v1 4/8] test/py/requirements.txt: remove unittest2 and testtools Heiko Schocher
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Heiko Schocher @ 2025-04-05 18:46 UTC (permalink / raw)
  To: U-Boot Mailing List; +Cc: Heiko Schocher, Heiko Schocher, Simon Glass, Tom Rini

From: Heiko Schocher <hs@nabladev.com>

building on gitlab with

image: ${MIRROR_DOCKER}/trini/u-boot-gitlab-ci-runner:jammy-20240911.1-08Dec2024

drops error:

ERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts.
virtualenv 20.13.0+ds requires filelock<4,>=3.2, but you have filelock 3.0.12 which is incompatible.

Increase to version 3.2.0

Signed-off-by: Heiko Schocher <hs@nabladev.com>
Signed-off-by: Heiko Schocher <hs@denx.de>
---

 test/py/requirements.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/test/py/requirements.txt b/test/py/requirements.txt
index 9b15e97f51..22315b4ed5 100644
--- a/test/py/requirements.txt
+++ b/test/py/requirements.txt
@@ -3,7 +3,7 @@ attrs==19.3.0
 concurrencytest==0.1.2
 coverage==7.6.2
 extras==1.0.0
-filelock==3.0.12
+filelock==3.2.0
 fixtures==3.0.0
 importlib-metadata==0.23
 linecache2==1.0.0
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v1 4/8] test/py/requirements.txt: remove unittest2 and testtools
  2025-04-05 18:46 [PATCH v1 0/8] This series introduces U-Boot tests with tbot on real hardware Heiko Schocher
                   ` (2 preceding siblings ...)
  2025-04-05 18:46 ` [PATCH v1 3/8] test/py/requirements.txt: increase filelock version Heiko Schocher
@ 2025-04-05 18:46 ` Heiko Schocher
  2025-04-05 18:46 ` [PATCH v1 5/8] test: increase timeouts Heiko Schocher
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Heiko Schocher @ 2025-04-05 18:46 UTC (permalink / raw)
  To: U-Boot Mailing List; +Cc: Heiko Schocher, Heiko Schocher, Simon Glass, Tom Rini

From: Heiko Schocher <hs@nabladev.com>

unittest2 and testtools leads in:

Collecting argparse (from unittest2>=1.0.0->testtools==2.3.0->-r /builds/u-boot/custodians/u-boot-i2c/tbottesting/../test/py/requirements.txt (line 26))
  Downloading argparse-1.4.0-py2.py3-none-any.whl.metadata (2.8 kB)

which breaks pytest 6.2.5 with

  File "/home/uboot/.local/lib/python3.10/site-packages/_pytest/config/argparsing.py", line 381, in __init__
    argparse.ArgumentParser.__init__(
TypeError: ArgumentParser.__init__() got an unexpected keyword argument 'allow_abbrev'

Signed-off-by: Heiko Schocher <hs@nabladev.com>
Signed-off-by: Heiko Schocher <hs@denx.de>
---

 test/py/requirements.txt | 2 --
 1 file changed, 2 deletions(-)

diff --git a/test/py/requirements.txt b/test/py/requirements.txt
index 22315b4ed5..26412ac0b3 100644
--- a/test/py/requirements.txt
+++ b/test/py/requirements.txt
@@ -23,8 +23,6 @@ python-subunit==1.3.0
 requests==2.32.3
 setuptools==70.3.0
 six==1.16.0
-testtools==2.3.0
 traceback2==1.4.0
-unittest2==1.1.0
 wcwidth==0.1.7
 zipp==3.19.2
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v1 5/8] test: increase timeouts
  2025-04-05 18:46 [PATCH v1 0/8] This series introduces U-Boot tests with tbot on real hardware Heiko Schocher
                   ` (3 preceding siblings ...)
  2025-04-05 18:46 ` [PATCH v1 4/8] test/py/requirements.txt: remove unittest2 and testtools Heiko Schocher
@ 2025-04-05 18:46 ` Heiko Schocher
  2025-04-05 18:46 ` [PATCH v1 6/8] [RFC] CI: add U-Boot testing on real HW with tbot Heiko Schocher
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Heiko Schocher @ 2025-04-05 18:46 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Heiko Schocher, Heiko Schocher, Heinrich Schuchardt, Love Kumar,
	Simon Glass, Tom Rini

From: Heiko Schocher <hs@nabladev.com>

running tests on github/gitlab while board is somewhere in
the wide world, needs bigger command and standard timeouts.

Increase them to:

TIMEOUT_MS = 60000                  # Standard timeout
TIMEOUT_CMD_MS = 45000              # Command-echo timeout

Signed-off-by: Heiko Schocher <hs@nabladev.com>
Signed-off-by: Heiko Schocher <hs@denx.de>
---

 test/py/u_boot_console_base.py | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/test/py/u_boot_console_base.py b/test/py/u_boot_console_base.py
index 7eaceb39d9..0aabedc394 100644
--- a/test/py/u_boot_console_base.py
+++ b/test/py/u_boot_console_base.py
@@ -30,8 +30,8 @@ PAT_ID = 0
 PAT_RE = 1
 
 # Timeout before expecting the console to be ready (in milliseconds)
-TIMEOUT_MS = 30000                  # Standard timeout
-TIMEOUT_CMD_MS = 10000              # Command-echo timeout
+TIMEOUT_MS = 60000                  # Standard timeout
+TIMEOUT_CMD_MS = 45000              # Command-echo timeout
 
 # Timeout for board preparation in lab mode. This needs to be enough to build
 # U-Boot, write it to the board and then boot the board. Since this process is
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v1 6/8] [RFC] CI: add U-Boot testing on real HW with tbot
  2025-04-05 18:46 [PATCH v1 0/8] This series introduces U-Boot tests with tbot on real hardware Heiko Schocher
                   ` (4 preceding siblings ...)
  2025-04-05 18:46 ` [PATCH v1 5/8] test: increase timeouts Heiko Schocher
@ 2025-04-05 18:46 ` Heiko Schocher
  2025-04-05 18:46 ` [PATCH v1 7/8] .gitlab-ci.yml: add tbot-lab Heiko Schocher
  2025-04-05 18:46 ` [PATCH v1 8/8] scripts: add helper for getting infos from your patchwork ToDo list Heiko Schocher
  7 siblings, 0 replies; 9+ messages in thread
From: Heiko Schocher @ 2025-04-05 18:46 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Heiko Schocher, Heiko Schocher, Caleb Connolly, Greg Malysa,
	Ilias Apalodimas, Jerome Forissier, Mattijs Korpershoek,
	Nathan Barrett-Morrison, Oliver Gaskell, Robert Marko,
	Sam Protsenko, Simon Glass, Tom Rini

From: Heiko Schocher <hs@nabladev.com>

add U-Boot tests on real hardware with tbot, which is started
from gitlab CI (no idea where it runs).

Currently one board is implemented (imx8qxp based cxg3 board).

This is a good example, as we need to get some binary blobs
for the build to get a working bootloader binary. This blobs
are stored in the tftp directory on the lab host, to which the
hardware is connected to. Tbot copies them from the lab host
to the CI host.

After build has finished, tbot copies the resulting bootloader
binaries to the lab host where with, the help of USB SDP bootmode
and uuu tool, the new flash.bin image is booted, and with USB
fastboot mode flashed into the emmc. After that worked, bootmode
is switched to emmc and the new flash.bin gets bootet (and tbot
checks the bootmode output, so we can be sure, that really the
new image boots from the correct bootdevice). A simple tbot
testcase for a ping over ethernet is done and ut command is called.

After that the test/py framework is started (from the CI host),
no external scripts are necessary for this, as all "scripts"
needed for this framework are created from tbot at runtime.

Signed-off-by: Heiko Schocher <hs@nabladev.com>
Signed-off-by: Heiko Schocher <hs@denx.de>
---

 MAINTAINERS                                   |   5 +
 tbottesting/README.md                         | 323 ++++++++++++++++++
 tbottesting/boardtestconfig.py                |  18 +
 tbottesting/boardtests.py                     |  50 +++
 tbottesting/preparetbot.sh                    |   5 +
 tbottesting/tbotboardtests.py                 | 127 +++++++
 tbottesting/tbotconfig-hs/boardspecific.py    | 111 ++++++
 tbottesting/tbotconfig-hs/hs/README.cxg3      |  28 ++
 tbottesting/tbotconfig-hs/hs/args/argsbase    |  11 +
 tbottesting/tbotconfig-hs/hs/args/argshs      |   1 +
 .../tbotconfig-hs/hs/args/argshs-github-ci    |   7 +
 .../tbotconfig-hs/hs/args/argshs-noeth        |   3 +
 .../tbotconfig-hs/hs/args/argshs-noeth-ssh    |   5 +
 tbottesting/tbotconfig-hs/hs/cxg3.ini         | 106 ++++++
 tbottesting/tbotconfig-hs/hs/tbot.ini         | 117 +++++++
 tbottesting/tbotconfig-hs/interactive.py      |  59 ++++
 tbottesting/tbotconfig-hs/labcallbacks.py     |  76 +++++
 tbottesting/tbotconfig-hs/tc_cxg3.py          |  82 +++++
 18 files changed, 1134 insertions(+)
 create mode 100644 tbottesting/README.md
 create mode 100644 tbottesting/boardtestconfig.py
 create mode 100644 tbottesting/boardtests.py
 create mode 100755 tbottesting/preparetbot.sh
 create mode 100644 tbottesting/tbotboardtests.py
 create mode 100644 tbottesting/tbotconfig-hs/boardspecific.py
 create mode 100644 tbottesting/tbotconfig-hs/hs/README.cxg3
 create mode 100644 tbottesting/tbotconfig-hs/hs/args/argsbase
 create mode 100644 tbottesting/tbotconfig-hs/hs/args/argshs
 create mode 100644 tbottesting/tbotconfig-hs/hs/args/argshs-github-ci
 create mode 100644 tbottesting/tbotconfig-hs/hs/args/argshs-noeth
 create mode 100644 tbottesting/tbotconfig-hs/hs/args/argshs-noeth-ssh
 create mode 100644 tbottesting/tbotconfig-hs/hs/cxg3.ini
 create mode 100644 tbottesting/tbotconfig-hs/hs/tbot.ini
 create mode 100644 tbottesting/tbotconfig-hs/interactive.py
 create mode 100644 tbottesting/tbotconfig-hs/labcallbacks.py
 create mode 100644 tbottesting/tbotconfig-hs/tc_cxg3.py

diff --git a/MAINTAINERS b/MAINTAINERS
index 042d3f6160..90a54deedb 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1675,6 +1675,11 @@ F:	cmd/broadcom/chimp_boot.c
 F:	cmd/broadcom/nitro_image_load.c
 F:	cmd/broadcom/chimp_handshake.c
 
+TBOTTEST
+M:	Heiko Schocher <hs@nabladev.com>
+S:	Maintained
+F:	tbottesting/*
+
 TDA19988 HDMI ENCODER
 M:	Liviu Dudau <liviu.dudau@foss.arm.com>
 S:	Maintained
diff --git a/tbottesting/README.md b/tbottesting/README.md
new file mode 100644
index 0000000000..c36e089b64
--- /dev/null
+++ b/tbottesting/README.md
@@ -0,0 +1,323 @@
+# testing U-Boot with tbot
+
+This subdirectory contains a full tbot test setup for
+building, installing and running U-Boot tests in
+the U-Boot shell on the hardware. The setup here in this
+subdirectory is used with our CI in gitlab, but the same
+code runs at for example my u-boot repo @github:
+
+https://github.com/hsdenx/u-boot-test/actions
+
+(with an additional patch which configures github workflows)
+
+and at least, as tbot is a tool, you can start from shell, so of
+course you can simply call:
+
+	$ python3 boardtests.py --usetbotflags
+
+to run the same steps as gitlab CI do, which is very useful for
+testing your stuff before pushing it to your CI. So you can use
+all of this for your daily work and automate a lot of your boring
+developers task, and get the CI integration for free!
+
+Look into
+
+	tbottest/tbotconfig/interactive.py
+
+where you find examples for all "interactive" testcases, which means
+you can call:
+
+	(ubtestenv) hs@asuslap:tbottesting  [tbottesting] $ ./tbottest/newtbot_starter.py @tbotconfig-hs/hs/args/argshs-github-ci tbotconfig-hs.interactive.uboot
+	[...]
+	│   ├─[cxg3-uboot] printenv end
+	│   │    ## end=end
+	│   ├─Entering interactive shell...
+	│   ├─Press CTRL+] three times within 1 second to exit.
+	 
+	U-Boot# 
+
+and you land in the U-Boot shell on the same hardware which your CI uses.
+
+Or, if setup, you land in linux shell on the board, build host shell, or
+
+in the kas-container shell if you have setup a yocto project build with kas
+tool (Yes, as tbot handles machines you have access to all of this machines
+and can automate on them whatever you need!).
+
+
+You find all boards which are integrated in our mainline tests here
+
+[boards](./boardtestconfig.py)
+
+which is a simple list of a dictionary, short explanation of the keys:
+
+[config options](#boards_config_options)
+
+| key                | description                                                                                                                    |
+| ---                | ---                                                                                                                            |
+| boardname          | Name of the board in your lab                                                                                                  |
+| ubootpatchsubpath  | subdir on your lab hosts tftp path for your board with downstream U-Boot patches, tbot copies them from lab host to build host |
+| binsubpath         | subdir on your lab hosts tftp path for your board with binary blobs, needed for full U-Boot build                              |
+| defconfig          | defconfig name for your board                                                                                                  |
+| resultbinaries     | list of binaries, tbot transfers after successful build to your lab hosts tftp directory                                      |
+| makelist           | U-Boot is builded with buildman, but may you want to call after that some make commands too, list them here                    |
+| install            | functionname, which installs U-Boot on the board                                                                               |
+| boottest           | functionname, which boots and tests the new installed U-Boot                                                                   |
+
+If you have a full working tbot setup, [boardtests.py](./boardtests.py)
+will make the following
+
+- create the build dir on build host
+- copy the binaries found on lab hosts tftpdirectory in subdirectory ```binsubpath```
+  to the build directory on the build host
+- copy downstream U-Boot patches found on lab hosts tftpdirectory in subdirectory ```ubootpatchsubpath```
+  to the U-Boot source directory on the build host, and apply them
+- build U-Boot with buildman
+- call make target defined in ```makelist``` if needed
+- copy resulting binaries defined in ```resultbinaries``` from build host builddir
+  to lab hosts tftp directory.
+- call tbot testcase name defined ```install``` for installing the new U-Boot image
+
+  example cxg3 board:
+  set bootmode USB SDP, load SPL / U-Boot with ```uuu``` tool enter ```fastboot``` mode
+  and install SPL/U-Boot image with ```uuu``` tool.
+
+- call tbot testcase name defined ```boottest``` for booting the new U-Boot image
+
+  example cxg3 board:
+  enter emmc bootmode and boot into U-Boot, make there a ```ping``` test and
+  start ```ut``` U-Boot command.
+
+- call U-Boot test framework (in u-boot:/test/py)
+
+
+# Adding new boards
+
+in theory it should be enough to add your board here:
+
+[boardconfig](./boardtestconfig.py)
+
+and add your tbotconfig in subdirectory [tbottesting}(.)
+see as an example [tbotconfig-hs](./tbotconfig-hs)
+
+Of course, you need to add your ssh secrets to github, so contact
+me.
+
+Heiko Schocher <hs@nabladev.com>
+
+Heiko Schocher <hs@emblux.org>
+
+If you have not yet a tbotconfig, there are 2 options:
+
+- Send me the board and I add it in my lab
+
+or
+
+- create a tbotconfig
+
+  may the easiest approach to copy above folder and
+  rename it too ```tbotconfig-foobar``` and make some adaptions, described in the
+  following sections. It may help if you read [1](https://tbot.tools) and [3](https://hsdenx.github.io/tbottest/quickstart.html)
+
+
+The following sections exaplain how to adapt ```tbotconfig-hs```
+subdirectory, but please do it in your own new created ```tbotconfig-foobar```!
+
+[!NOTE]
+May we can add a script which does this automagically.
+
+If you have any issues, feel free to contact me.
+
+## setup new boards
+
+give the board a name, lets say ```foobar```
+
+add your board now in
+
+tbottesting/boardtestconfig.py
+
+(copy and paste the lines 5-15)
+
+Add replace the old boardname ```cxg3``` with the new name ```foobar```
+
+[boardname](./boardtestconfig.py#L6)
+
+Adapt also there the U-Boot build configs, see table #boards_config_options
+
+so, that this fits with the needs for your board
+
+### adapt board config in tbot.ini
+
+Keep in mind, that you can add in ```tbot.ini``` as much boards as you want!
+The following chapters are only an example for one board in tbot.ini
+
+For full explanation read:
+
+[tbottest doc: tbot.ini](https://hsdenx.github.io/tbottest/generic.html#tbot-ini-sections)
+
+
+#### adapt lab host setup
+
+adapt section [LABHOST] in
+
+[LABHOST](./tbotconfig-hs/hs/tbot.ini)
+
+to your local lab host setup, see full doc:
+
+[tbottest doc: labhost setup](https://hsdenx.github.io/tbottest/generic.html#labhost)
+
+check that you have working ssh access to your lab host!
+
+#### adapt build host setup
+
+starting tbot from github means, that we use ```[BUILDHOST_local]```
+for our U-Boot build, so you do not need to change here in this
+section anything. But if you are interested, you can add as many
+build hosts here as you have (for example big machines which do
+for you a whole yocto project build...)
+
+[tbottest doc: build host setup](https://hsdenx.github.io/tbottest/generic.html#buildhost)
+
+#### setup serial console on lab host
+
+change in [tbot.ini](tbotconfig-hs/hs/tbot.ini#L67) ```PICOCOM_cxg3```
+to ```PICOCOM_foobar```
+
+and adapt the serial device in [tbot.ini](tbotconfig-hs/hs/tbot.ini#L69)
+
+If you do not want to use ```picocom``` see doc for:
+
+[tbottest doc: kermit](https://hsdenx.github.io/tbottest/generic.html#kermit-boardname)
+[tbottest doc: script](https://hsdenx.github.io/tbottest/generic.html#scriptcom-boardname)
+
+You do not need to adapt ```tbot.flags``` for this, as
+tbottest tries to autodetect the used terminal tool:
+
+[autodetect terminal tool](https://github.com/hsdenx/tbottest/blob/master/tbottest/labgeneric.py#L269)
+
+As you see in code, you can force it with setting it in ```tbot.flags```
+
+#### setup power off / on
+
+change in [tbot.ini](tbotconfig-hs/hs/tbot.ini#L67) ```SISPMCTRL_cxg3```
+to ```SISPMCTRL_foobar```
+
+and adapt the address in [tbot.ini](tbotconfig-hs/hs/tbot.ini#L79)
+
+If you do not have a sispmctrl based controller, see doc for other
+supported devices:
+
+[gpio](https://hsdenx.github.io/tbottest/generic.html#gpiopmctrl-boardname)
+[script](https://hsdenx.github.io/tbottest/generic.html#powershellscript-boardname)
+[tinkerforge](https://hsdenx.github.io/tbottest/generic.html#tf-boardname)
+
+replace section ```SISPMCTRL_foobar``` with the power controller
+you own. You do not need to adapt tbot.flags for this, as
+tbottest tries to autodetect the used power controller:
+
+[autodetect powercontroller](https://github.com/hsdenx/tbottest/blob/master/tbottest/labgeneric.py#L161)
+
+As you see in code, you can force it with setting it in ```tbot.flags```
+
+#### bootmode setup
+
+you can setup different bootmodes for your board with section
+
+[BOOTMODE_foobar](https://hsdenx.github.io/tbottest/generic.html#bootmode-boardname)
+
+example config:
+
+[bootmode](./tbotconfig-hs/hs/tbot.ini#L109)
+
+see therefore also below section labcallbacks.py
+
+#### ethernet setup
+
+see doc:
+
+[ethernet config](https://hsdenx.github.io/tbottest/generic.html#ipsetup-boardname-ethdevice-board)
+
+example for cxg3 board and ethernet device eth0:
+
+[ethernet](./tbotconfig-hs/hs/tbot.ini#L90)
+
+adapt it to your needs!
+
+#### U-Boot Environment setup
+
+You can define a board specific U-Boot Environment in section ```[TC]```
+in your boardname.ini file through key ```ub_env```, see as an example
+
+[U-Boot Environment](tbotconfig-hs/hs/cxg3.ini#L37)
+
+Setup there all stuff you need for your tests (may, you want to boot
+linux with different setups like tftp fitImage and boot with_nfs rootfs)
+
+pattern_lab_mode = re.compile('{lab mode.*}')
+
+### boardspecific code
+
+#### labcallbacks.py
+
+There you find the functions:
+
+cxg3_ub_install
+
+  -> execute the commands, which are needed to update U-Boot on your board
+
+  This functions is called from your [boardconfig](./boardtestconfig.py#L13)
+
+cxg3_ub_boot_and_test
+
+  -> boot installed U-Boot and test. Do here tests, you want to see
+     additionally.
+
+  This functions is called from your [boardconfig](./boardtestconfig.py#L14)
+
+So this both functions depends highly on your board! Hope this example helps!
+
+cxg3_setbootmode_usb
+
+  -> function which runs on lab host. Sets USB SDP bootmode
+
+  This functions is called through tbot flag ```bootmode:usb``` and
+  your [bootmode](./tbotconfig-hs/hs/tbot.ini#L109)
+
+cxg3_setbootmode_emmc
+
+  -> function which runs on lab host. Sets emmc bootmode
+
+  This functions is called through tbot flag ```bootmode:emmc``` and
+  your [bootmode](./tbotconfig-hs/hs/tbot.ini#L109)
+
+
+So this both functions depends highly on your lab setup!
+Hope this example helps!
+
+To be continued! Bugfixes, Ideas are welcome!
+
+# Ideas / Todo
+
+- test and fix errros
+-  add more than one lab
+- add more boards to the hs lab
+- implement for custodians the old patchwork ToDo list setup
+
+  There I had a tbot setup which I started in nightly cron job,
+  which downloaded all patches from my Patchwork ToDo list, checked
+  them with checpatch.pl script, applied it to current HEAD and
+  builded for all boards in the lab U-Boot, installed it and started
+  all tests. And optionally if the tests fail, start an automated
+  git bisect session and find out, which patch breaks!
+
+  For reference an old video on youtube how this worked 8 years ago:
+
+  https://www.youtube.com/watch?v=PhaYfqOrQOg
+
+# Links
+
+[1] https://tbot.tools
+
+[2] https://tbot.tools/recipes.html
+
+[3] https://hsdenx.github.io/tbottest/quickstart.html
diff --git a/tbottesting/boardtestconfig.py b/tbottesting/boardtestconfig.py
new file mode 100644
index 0000000000..b8b370dfd9
--- /dev/null
+++ b/tbottesting/boardtestconfig.py
@@ -0,0 +1,18 @@
+# SPDX-License-Identifier: GPL-2.0+
+
+import os
+import sys
+
+boards = [
+        {
+            "boardname" : "cxg3",
+            "tbotargs"  : "@tbotconfig/hs/args/argshs-github-ci",
+            "ubootpatchsubpath": "uboot-patches",
+            "binsubpath":"binaries",
+            "defconfig":"capricorn_cxg3",
+            "resultbinaries":["flash.bin"],
+            "makelist":["flash.bin"],
+            "install":"cxg3_ub_install",
+            "boottest":"cxg3_ub_boot_and_test",
+        },
+        ]
diff --git a/tbottesting/boardtests.py b/tbottesting/boardtests.py
new file mode 100644
index 0000000000..7dbb29dd9d
--- /dev/null
+++ b/tbottesting/boardtests.py
@@ -0,0 +1,50 @@
+#!/usr/bin/python3
+# SPDX-License-Identifier: GPL-2.0+
+
+# -*- coding: utf-8 -*-
+
+import inspect
+import os
+import sys
+currentdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
+sys.path.insert(0, currentdir + "/tbot")
+sys.path.insert(0, currentdir + "/tbottest")
+
+from tbot.newbot import main  # noqa: E402
+
+from boardtestconfig import boards as B
+
+if __name__ == "__main__":
+    """
+    Build, install and test U-Boot for all boards
+    """
+    failed = 0
+    success = 0
+    count = 0
+    tests = len(B)
+    orgargv = sys.argv.copy()
+    for b in B:
+        count += 1
+        print(f"--------- start test {b['boardname']} {count} / {tests} suc: {success} fail: {failed} ---------")
+        newargv = orgargv.copy()
+        newargv = newargv[1:]
+        newargv.append(b['tbotargs'])
+        newargv.remove("--usetbotflags")
+        newargv.append("-f")
+        newargv.append(f"boardname:{b['boardname']}")
+        newargv.append("tbotboardtests.tbottest_one_board")
+
+        try:
+            # call tbot
+            main(newargv)
+            print(f"test {b['boardname']} succeeded")
+            success += 1
+        except Exception as e:
+            print(f"test {b['boardname']} failed with exception " + str(e))
+            failed += 1
+
+    print(f"--------- tests {count} / {tests} suc: {success} fail: {failed} ---------")
+    if failed:
+        sys.exit(1)
+
+    sys.exit(0)
diff --git a/tbottesting/preparetbot.sh b/tbottesting/preparetbot.sh
new file mode 100755
index 0000000000..8465aa3626
--- /dev/null
+++ b/tbottesting/preparetbot.sh
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0+
+
+wget -q https://github.com/hsdenx/tbottest/raw/master/scripts/create_setup.sh
+chmod 777 create_setup.sh
+./create_setup.sh
diff --git a/tbottesting/tbotboardtests.py b/tbottesting/tbotboardtests.py
new file mode 100644
index 0000000000..cbc8f2b57a
--- /dev/null
+++ b/tbottesting/tbotboardtests.py
@@ -0,0 +1,127 @@
+# SPDX-License-Identifier: GPL-2.0+
+
+import os
+import sys
+
+import tbot
+
+from tbot.context import Optional
+from tbot.machine import linux
+from tbot.machine import board
+
+from tbottest.common.ubootbuild import UBBUILDMAN
+from tbotconfig import labcallbacks
+
+from boardtestconfig import boards as B
+
+@tbot.testcase
+def tbottest_install_board(b) -> int:  # noqa: D107
+    """
+    Install the new U-Boot image on the board b
+    """
+    try:
+        tbot.log.message(tbot.log.c(f"Install bootloader image").green)
+        funcname = b['install']
+        func = getattr(labcallbacks, funcname)
+        ret = func()
+        if ret != True:
+            tbot.log.message(tbot.log.c(f"calling bootloader install failed {b['install']} with {ret}").yellow)
+            return 1
+    except Exception as e:
+        tbot.log.message(tbot.log.c(f"calling bootloader install failed {b['install']} with exception " + str(e)).yellow)
+        return 1
+
+    return 0
+
+from tbot_contrib import uboot
+
+@tbot.testcase
+def run_testpy(b, bmcfg) -> None:
+    with tbot.ctx.request(tbot.role.BuildHost) as h:
+        # location of the U-Boot paths (source and build)
+        uboot_sources = bmcfg.basedir
+        uboot_builddir = bmcfg.builddirbuildman
+
+        h.exec0("pip", "install", "-r", uboot_sources / "test/py/requirements.txt")
+        # subshell for the build environment
+        with h.subshell():
+            uboot.testpy(
+                uboot_sources,
+                testpy_args=["--maxfail", "6", f"--junitxml=/{bmcfg.builddirbuildman._local_str()}/{b['boardname']}/results.xml"],
+                uboot_builddir = uboot_builddir,
+            )
+        td = f"{uboot_sources._local_str()}/results/{b['boardname']}"
+        h.exec0("mkdir", "-p", td)
+        h.exec("cp", f"{bmcfg.builddirbuildman._local_str()}/{b['boardname']}/results.xml", f"{td}/results.xml")
+        h.exec("cp", f"{bmcfg.builddirbuildman._local_str()}/multiplexed_log.css", f"{td}/multiplexed_log.css")
+        h.exec("cp", f"{bmcfg.builddirbuildman._local_str()}/test-log.html", f"{td}/test-log.html")
+
+@tbot.testcase
+def tbottest_test_board(b, bmcfg) -> int:  # noqa: D107
+    """
+    Test the new installed U-Boot on the board b
+    """
+    try:
+        tbot.log.message(tbot.log.c(f"Boot and Test bootloader image").green)
+        funcname = b['boottest']
+        func = getattr(labcallbacks, funcname)
+        ret = func()
+        if ret != True:
+            tbot.log.message(tbot.log.c(f"calling Boot and Test failed {b['boottest']} with {ret}").yellow)
+    except Exception as e:
+        tbot.log.message(tbot.log.c(f"calling Boot and Test failed {b['boottest']} with exception " + str(e)).yellow)
+        return 1
+
+    run_testpy(b, bmcfg)
+
+    return 0
+
+@tbot.testcase
+def _tbottest_one_board(
+    lab: linux.LinuxShell = None,
+    bh: linux.LinuxShell = None,
+    b = None,
+) -> int:  # noqa: D107
+    """
+    Build, install and test U-Boot for board b
+    """
+    bmcfg = UBBUILDMAN(lab, bh, b['ubootpatchsubpath'], b["binsubpath"],
+                        b["defconfig"],
+                        b["resultbinaries"],
+                        b["makelist"])
+
+    bmcfg.bm_build_board()
+    bmcfg.bm_copy_results2lab()
+
+    if tbottest_install_board(b):
+        return 1
+
+    return tbottest_test_board(b, bmcfg)
+
+from tbottest.initconfig import generic_get_boardname
+
+@tbot.testcase
+def tbottest_one_board(
+    lab: linux.LinuxShell = None,
+    bh: linux.LinuxShell = None,
+    boardname: str = None,
+) -> int:  # noqa: D107
+    """
+    Build, install and test U-Boot for board b
+    """
+    with tbot.ctx() as cx:
+        if bh is None:
+            bh = cx.request(tbot.role.BuildHost)
+
+        if lab is None:
+            lab = cx.request(tbot.role.LabHost)
+
+        bname = generic_get_boardname()
+        for bi in B:
+            if bi['boardname'] == bname:
+                b = bi
+
+        if _tbottest_one_board(lab, bh, b):
+            raise RuntimeError(f"Testing {bname} failed")
+
+    return 0
diff --git a/tbottesting/tbotconfig-hs/boardspecific.py b/tbottesting/tbotconfig-hs/boardspecific.py
new file mode 100644
index 0000000000..c35e0ce03b
--- /dev/null
+++ b/tbottesting/tbotconfig-hs/boardspecific.py
@@ -0,0 +1,111 @@
+# SPDX-License-Identifier: GPL-2.0+
+
+import configparser
+from configparser import ExtendedInterpolation
+
+import tbot
+
+from tbottest.initconfig import generic_get_boardname
+from tbottest.initconfig import replace_in_file
+from tbottest.initconfig import find_in_file_and_delete
+
+
+SERVERIP = None
+
+
+def cxg3_get_lab_serverip(filename: str = None):
+    """
+    helper to save ini file reads
+    """
+    global SERVERIP
+
+    if SERVERIP is not None:
+        return SERVERIP
+
+    if filename is None:
+        raise RuntimeError("serverip not setup")
+
+    # read from ini file
+    config_parser = configparser.RawConfigParser(interpolation=ExtendedInterpolation())
+    config_parser.read(filename)
+    for s in config_parser.sections():
+        if "IPSETUP" in s:
+            nm = s.split("_")[1]
+            dev = s.split("_")[2]
+
+            if nm == generic_get_boardname() and dev == "eth0":
+                SERVERIP = config_parser.get(s, "serverip")
+                return SERVERIP
+
+    raise RuntimeError("serverip setup not found")
+
+
+IPADDR = None
+
+
+def cxg3_get_board_ipaddr(filename: str = None):
+    """
+    helper to save ini file reads
+    """
+    global IPADDR
+
+    if IPADDR is not None:
+        return IPADDR
+
+    if filename is None:
+        raise RuntimeError("ipaddr not setup")
+
+    # read from ini file
+    config_parser = configparser.RawConfigParser(interpolation=ExtendedInterpolation())
+    config_parser.read(filename)
+    for s in config_parser.sections():
+        if "IPSETUP" in s:
+            nm = s.split("_")[1]
+            dev = s.split("_")[2]
+
+            if nm == generic_get_boardname() and dev == "eth0":
+                IPADDR = config_parser.get(s, "ipaddr")
+                return IPADDR
+
+    raise RuntimeError("ipaddr not found")
+
+
+def print_log(msg):
+    try:
+        if tbot.selectable.printed:
+            return
+    except:
+        pass
+
+    tbot.log.message(tbot.log.c(msg).yellow)
+
+
+def set_ub_board_specific(self):  # noqa: C901
+    """
+    sample implementation for changing U-Boot setup dependent on tbot.flags
+    """
+    if "silent" in tbot.flags:
+        self.env("console", "silent")
+
+
+def set_board_cfg(temp: str = None, filename: str = None):  # noqa: C901
+    """
+    setup board specific stuff in ini files before they get parsed
+    """
+    # print big fat warning, that example is used
+    print_log(f"TBOT.FLAGS {sorted(tbot.flags)}")
+
+    replace_in_file(filename, "@@TBOTDATE@@", "20250208")
+    boardname = generic_get_boardname()
+    print_log(f"boardname now {boardname}")
+
+    tftpsubdir = "${board}/${date}"
+    replace_in_file(filename, "@@TBOTBOARD@@", boardname)
+    replace_in_file(filename, "@@TFTPSUBDIR@@", tftpsubdir)
+    replace_in_file(filename, "@@TBOTSERVERIP@@", cxg3_get_lab_serverip(filename))
+    replace_in_file(filename, "@@TBOTIPADDR@@", cxg3_get_board_ipaddr(filename))
+    replace_in_file(filename, "@@PICOCOMDELAY@@", "3")
+
+FLAGS = {
+    "boardname": "set theboardname of the board format boardname:<name>",
+}
diff --git a/tbottesting/tbotconfig-hs/hs/README.cxg3 b/tbottesting/tbotconfig-hs/hs/README.cxg3
new file mode 100644
index 0000000000..9cc9f0a198
--- /dev/null
+++ b/tbottesting/tbotconfig-hs/hs/README.cxg3
@@ -0,0 +1,28 @@
+README
+======
+
+commandline completions
+-----------------------
+
+	$ source tbottest/completions.sh
+
+log into U-Boot
+---------------
+
+	$ ./tbottest/newtbot_starter.py @tbotconfig/cxg3/args/argscxg3-noeth tbotconfig.interactive.uboot
+
+build U-Boot
+------------
+
+	$ ./tbottest/newtbot_starter.py -f uuuloader -f buildername:local @tbotconfig/cxg3/args/argscxg3-noeth tbotconfig.tc_cxg3.tbottest_build_board
+
+bootmodes
+---------
+
+to boot from emmc pass
+
+	-f bootmode:emmc
+
+to boot with NXPs uuu tool in USB SDP mode pass
+
+	-f bootmode:usb
diff --git a/tbottesting/tbotconfig-hs/hs/args/argsbase b/tbottesting/tbotconfig-hs/hs/args/argsbase
new file mode 100644
index 0000000000..ef3e09c0a4
--- /dev/null
+++ b/tbottesting/tbotconfig-hs/hs/args/argsbase
@@ -0,0 +1,11 @@
+-c
+tbottest.labgeneric
+-c
+tbottest.boardgeneric
+-fdo_power
+-f
+inifile:tbotconfig/hs/tbot.ini
+-f
+boardfile:tbotconfig/hs/cxg3.ini
+-f
+useifconfig
diff --git a/tbottesting/tbotconfig-hs/hs/args/argshs b/tbottesting/tbotconfig-hs/hs/args/argshs
new file mode 100644
index 0000000000..e65062f59e
--- /dev/null
+++ b/tbottesting/tbotconfig-hs/hs/args/argshs
@@ -0,0 +1 @@
+@tbotconfig/hs/args/argsbase
diff --git a/tbottesting/tbotconfig-hs/hs/args/argshs-github-ci b/tbottesting/tbotconfig-hs/hs/args/argshs-github-ci
new file mode 100644
index 0000000000..95b8f313ee
--- /dev/null
+++ b/tbottesting/tbotconfig-hs/hs/args/argshs-github-ci
@@ -0,0 +1,7 @@
+@tbotconfig/hs/args/argshs-noeth
+-f
+buildername:local
+-f
+uuuloader
+-f
+selectableboardname:cxg3
diff --git a/tbottesting/tbotconfig-hs/hs/args/argshs-noeth b/tbottesting/tbotconfig-hs/hs/args/argshs-noeth
new file mode 100644
index 0000000000..b2d53e273e
--- /dev/null
+++ b/tbottesting/tbotconfig-hs/hs/args/argshs-noeth
@@ -0,0 +1,3 @@
+@tbotconfig/hs/args/argshs
+-fnoethinit
+-fnoboardethinit
diff --git a/tbottesting/tbotconfig-hs/hs/args/argshs-noeth-ssh b/tbottesting/tbotconfig-hs/hs/args/argshs-noeth-ssh
new file mode 100644
index 0000000000..a5d7673fc1
--- /dev/null
+++ b/tbottesting/tbotconfig-hs/hs/args/argshs-noeth-ssh
@@ -0,0 +1,5 @@
+@tbotconfig/hs/args/argshs-noeth
+-fnopoweroff
+-falways-on
+-fssh
+-fnouboot
diff --git a/tbottesting/tbotconfig-hs/hs/cxg3.ini b/tbottesting/tbotconfig-hs/hs/cxg3.ini
new file mode 100644
index 0000000000..44e958f6a0
--- /dev/null
+++ b/tbottesting/tbotconfig-hs/hs/cxg3.ini
@@ -0,0 +1,106 @@
+# you can replace strings in this file on boot
+# in set_board_cfg() in boardspecific.py
+#
+# see example `set-board-cfg-temp-str-none-filename-str-none`_
+[default]
+user = @@USERNAME@@
+date = @@TBOTDATE@@
+board = @@TBOTBOARD@@
+postbuild = local
+serverip = @@TBOTSERVERIP@@
+ipaddr = @@TBOTIPADDR@@
+machine = @@TBOTMACHINE@@
+denxlayer = meta-denx-kas
+denxlayerbranch = master
+vendor = denx
+tftp_subdir = @@TFTPSUBDIR@@
+deploydir = tmp/deploy/images/${machine}
+nfs_path = @@TBOTLABBASENFSPATH@@/${machine}/${postbuild}
+subdir = ${vendor}/${machine}
+rootfsname = @@ROOTFSNAME@@
+sdk_bin = name_of_sdk_shell_script
+
+[TC]
+    uboot_death_strings = ['Kernel panic']
+    tmpdir = /tmp
+    ignore_hostkey = True
+
+    ############################################
+    # U-Boot
+    ############################################
+    uboot_boot_timeout = None
+    uboot_autoboot_timeout = 0.2
+    #uboot_autoboot_prompt = Autobooting in \d{0,3} seconds, press "<Esc><Esc>" to stop
+    uboot_autoboot_prompt = Autobooting in \d{0,3}.{0,80}
+    uboot_autoboot_keys = bytearray:1b1b
+    uboot_prompt = "U-Boot# "
+    ub_env = [{"name":"serverip", "val":"${default:serverip}"}, \
+      {"name":"ipaddr", "val":"${default:ipaddr}"}, \
+      {"name":"netmask", "val":"255.255.255.0"}, \
+      {"name":"date", "val":"${default:date}"}, \
+      {"name":"end", "val":"end"}]
+
+    ############################################
+    # Linux
+    ############################################
+    linux_user = root
+    linux_password = root
+
+    linux_boot_timeout = 200
+    linux_login_delay = 3
+    linux_init_timeout = "2"
+
+    linux_init = [ \
+        {"cmd":"cat /proc/cmdline"}, \
+        {"cmd":"uname -a"}, \
+        ]
+
+    dmesg = [
+       ]
+
+    dmesg_false = [
+       "crash",
+       ]
+
+    ############################################
+    # swupdate
+    ############################################
+    swuethdevice = eth0
+    swuimage = swu-image.swu
+
+    ############################################
+    # kas
+    ############################################
+    kas = {
+       "kasurl" : "https://github.com/siemens/kas.git",
+       "kasversion" : "4.0",
+       "build_machine" : "${default:machine}",
+       "subdir" : "${default:subdir}",
+       "kascontainer" : False,
+       "git_credential_store" : "/home/${default:user}/.git-credentials",
+       "ssh_dir" : "/home/${default:user}/.ssh",
+       "kaslayer" : "git@gitlab.denx.de:denx/${default:denxlayer}",
+       "kaslayername" : "${default:denxlayer}",
+       "kaslayerbranch" : "master",
+       "kasconfigfile" : "${default:denxlayer}/kas-denx.yml",
+       "bitbakeenvinit" : "source/poky/oe-init-build-env",
+       "envinit" : ["export PATH=/home/hs/data/bins/make-4.3/bin:$${PATH}"],
+       "buildtargets" : [
+           "core-image-minimal",
+           "meta-toolchain-qt5",
+           "bitbake -c populate_sdk core-image-dev",
+           ],
+       "bitbakeoptions" : ["-q", "-q"],
+       }
+
+    kas_check_files = [
+       "${default:deploydir}/SPL",
+       "${default:deploydir}/u-boot.img",
+       "${default:deploydir}/fitImage",
+       "tmp/deploy/sdk/${default:sdk_bin}",
+       ]
+    kas_results = [
+       "SPL",
+       "u-boot.img",
+       "fitImage",
+       ]
diff --git a/tbottesting/tbotconfig-hs/hs/tbot.ini b/tbottesting/tbotconfig-hs/hs/tbot.ini
new file mode 100644
index 0000000000..a3c2daa531
--- /dev/null
+++ b/tbottesting/tbotconfig-hs/hs/tbot.ini
@@ -0,0 +1,117 @@
+# generic lab config for tbot
+#
+# ssh access to lab host / build host only through ssh keys without
+# any passwords.
+#
+# Variables which get substituted when running tbot
+
+[LABHOST]
+labname = ubmainlinelab
+hostname = ubtestinglab
+username = pi
+sshkeyfile = /home/${username}/.ssh/id_rsa
+date = @@TBOTDATE@@
+board = @@TBOTBOARD@@
+# where does tbot find tools installed on lab host
+toolsdir = /home/${username}/source
+# path to tftp directory where tftp server looks in
+# This directory is not only used for tftp.
+tftproot = /srv/tftpboot
+# or ${board}/${date}
+tftpsubdir = @@TFTPSUBDIR@@
+workdir = /work/${username}/tbot-workdir/${board}
+tmpdir = /tmp/tbot/${username}/${board}
+proxyjump = <configure proxyjumps here>
+usernamessh = <Username on ssh machine>
+labinit = ["sudo systemctl --all --no-pager restart tftpd-hpa", "sudo systemctl stop NetworkManager"]
+seggercmd = "sudo /home/pi/source/JLink_Linux_V686e_arm/JLinkExe"
+nfs_base_path = /work/pi/tbot-workdir/nfs
+shelltype = bash
+uselocking = no
+
+[BUILDHOST]
+name = threadripper-big-build
+username = hs
+hostname = 192.168.1.120
+dl_dir = /work/downloads
+sstate_dir = /work2/${username}/tbot2go/yocto-sstate
+kas_ref_dir = /work/${username}/src
+workdir = /work/big/${username}/tbot2go
+authenticator = /home/${username}/.ssh/id_rsa
+shelltype = bash
+
+[BUILDHOST_local]
+name = local-build
+username = hs
+hostname = localmachine
+# intentionally without leading "/", so tbot works in the dir, it is started
+dl_dir = work/tbottest/dl_dir
+sstate_dir = work/tbottest/yocto-sstate
+kas_ref_dir = work/tbottest/kas-ref-dir
+workdir = work/tbottest/work
+shelltype = bash
+initcmd = ["uname -a"]
+
+[BUILDHOST_someotherbuildmachine]
+name = powerfullmachine
+username = hs
+hostname = <set here the hostname of it>
+port = 22
+dl_dir = /opt/downloads
+sstate_dir = /work/${username}/yocto/yocto-sstate
+workdir = /work/${username}/yocto
+authenticator = /home/${username}/.ssh/id_rsa
+initcmd = ["cat /etc/os-release"]
+shelltype = bash
+
+[PICOCOM_cxg3]
+baudrate = 115200
+device = /dev/serial/by-id/usb-Siemens_FitzRoy_CES3088-if01-port0
+delay = 3
+noreset = True
+
+[SDWIRE]
+serial = da23
+
+# powercontrol config
+
+[SISPMCTRL_cxg3]
+device = 01:01:60:e5:e9
+port = 4
+
+[UBCFG_cxg3]
+ethintf = eth0
+
+# board ip setup
+# !! One board can have more than one ethernet device
+# so after boardname add "_<ethdevicename>"
+# and write a section for each ethernet device on the board
+
+[IPSETUP_cxg3_eth0]
+# ethernet device used on lab host
+labdevice = eth0
+netmask = 255.255.255.0
+ethaddr = 00:30:D6:2C:A6:3D
+ipaddr = 192.168.3.40
+serverip = 192.168.3.1
+
+[UUU_CONFIG_cxg3]
+cmd = SDPS: boot -f LBD/flash.bin-githubci,
+    SDPV: delay 1000,SDPV: write -f LBD/flash.bin-githubci -skipspl,
+    SDPV: jump,
+    FB: ucmd env default -a,FB: ucmd setenv fastboot_dev mmc,
+    FB: flash bootloader LBD/flash.bin-githubci,
+    FB: ucmd mmc dev 0 2,
+    FB: ucmd mmc erase 0 3000,
+    FB: ucmd saveenv,FB: ucmd saveenv,FB: Done
+
+[BOOTMODE_cxg3]
+modes = [{"name":"bootmode:usb", "func":"cxg3_setbootmode_usb"}, {"name":"bootmode:emmc", "func":"cxg3_setbootmode_emmc"} ]
+
+[SSHMACHINE]
+name = laptop-machine
+username = ${usernamessh}
+port = <add here the port you use>
+hostname = <add the hostname or ip address>
+workdir = /tmp
+toolsdir = /home/${usernamessh}/source
diff --git a/tbottesting/tbotconfig-hs/interactive.py b/tbottesting/tbotconfig-hs/interactive.py
new file mode 100644
index 0000000000..b4c1fe13c0
--- /dev/null
+++ b/tbottesting/tbotconfig-hs/interactive.py
@@ -0,0 +1,59 @@
+# SPDX-License-Identifier: GPL-2.0+
+
+import tbot
+from tbottest.boardgeneric import cfggeneric
+from tbottest.tc.kas import KAS
+
+
+# only to have interactive commands handy and do not use the ones
+# from tbot, see https://tbot.tools/quickstart.html#directory-structure
+
+
+@tbot.testcase
+def board() -> None:
+    """Open an interactive session on the board's serial console."""
+    with tbot.ctx.request(tbot.role.Board) as b:
+        b.interactive()
+
+
+@tbot.testcase
+def linux() -> None:
+    """Open an interactive session on the board's Linux shell."""
+    with tbot.ctx.request(tbot.role.BoardLinux) as lnx:
+        lnx.interactive()
+
+
+@tbot.testcase
+def uboot() -> None:
+    """Open an interactive session on the board's U-Boot shell."""
+    tbot.ctx.teardown_if_alive(tbot.role.BoardLinux)
+    with tbot.ctx.request(tbot.role.BoardUBoot) as ub:
+        ub.interactive()
+
+
+@tbot.testcase
+def lab() -> None:
+    """Start an interactive shell on the lab-host."""
+    with tbot.ctx.request(tbot.role.LabHost) as lh:
+        lh.interactive()
+
+
+@tbot.testcase
+def build() -> None:
+    """Start an interactive shell on the build-host."""
+    with tbot.ctx.request(tbot.role.BuildHost) as bh:
+        bh.exec0("cd", bh.workdir)
+        bh.interactive()
+
+
+@tbot.testcase
+def kas() -> None:
+    """Start an interactive shell on the build-host kas container"""
+    with tbot.ctx.request(tbot.role.BuildHost) as bh:
+        lab = tbot.ctx.request(tbot.role.LabHost)
+
+        cfggeneric.kas["labhost"] = lab
+        cfggeneric.kas["buildhost"] = bh
+        kas = KAS(cfggeneric.kas)
+
+        kas.kas_shell()
diff --git a/tbottesting/tbotconfig-hs/labcallbacks.py b/tbottesting/tbotconfig-hs/labcallbacks.py
new file mode 100644
index 0000000000..3c13020359
--- /dev/null
+++ b/tbottesting/tbotconfig-hs/labcallbacks.py
@@ -0,0 +1,76 @@
+# SPDX-License-Identifier: GPL-2.0+
+
+import tbot
+import time
+
+from tbot.context import Optional
+from tbot.machine import board
+from tbot.machine import linux
+
+from tbotconfig.tc_cxg3 import _cxg3_ub_install
+from tbotconfig.tc_cxg3 import _cxg3_ub_boot_and_test
+
+################################################
+## Lab specific
+################################################
+
+fitzroyinstallpath = "/home/pi/source/fitzroy-command"
+fitzroyserial = "CES3088"
+bootmode = "notset"
+
+def cxg3_lab_run_fitzroy(
+    lab: linux.LinuxShell = None,
+    mode: str = None,
+) -> None:  # noqa: D107
+    """
+    """
+    global bootmode
+
+    if bootmode != mode:
+        lab.exec0(f"{fitzroyinstallpath}/fitzroy", "-s", fitzroyserial, "bootmode", mode)
+        #lab.exec0(f"{fitzroyinstallpath}/fitzroy", "-s", fitzroyserial, "frontend", "program")
+        lab.exec0(f"{fitzroyinstallpath}/fitzroy", "-s", fitzroyserial, "reset")
+        bootmode = mode
+        time.sleep(2)
+
+
+################################################
+## callback called from ./tbottest/labgeneric.py
+################################################
+def cxg3_setbootmode_usb(
+    lab: linux.LinuxShell = None,
+) -> None:  # noqa: D107
+    """
+    set cxg3 board into bootmode USB SDP
+    """
+    cxg3_lab_run_fitzroy(lab, "usb")
+    return True
+
+def cxg3_setbootmode_emmc(
+    lab: linux.LinuxShell = None,
+) -> None:  # noqa: D107
+    """
+    set cxg3 board into bootmode emmc
+    """
+    cxg3_lab_run_fitzroy(lab, "emmc")
+    return True
+
+################################################
+## callback called from ./tbottesting/boardtests.py
+################################################
+@tbot.testcase
+def cxg3_ub_install(
+    lab: Optional[linux.LinuxShell]=None,
+    ub: Optional[board.UBootShell]=None,
+) -> bool:  # noqa: D107
+    """
+    install U-Boot with uuu tool
+    """
+    return _cxg3_ub_install(lab, ub)
+
+@tbot.testcase
+def cxg3_ub_boot_and_test(
+    lab: Optional[linux.LinuxShell]=None,
+    ub: Optional[board.UBootShell]=None,
+) -> bool:  # noqa: D107
+    return _cxg3_ub_boot_and_test(lab, ub)
diff --git a/tbottesting/tbotconfig-hs/tc_cxg3.py b/tbottesting/tbotconfig-hs/tc_cxg3.py
new file mode 100644
index 0000000000..f30b6e516b
--- /dev/null
+++ b/tbottesting/tbotconfig-hs/tc_cxg3.py
@@ -0,0 +1,82 @@
+# SPDX-License-Identifier: GPL-2.0+
+
+import os
+import re
+import sys
+import tbot
+import time
+from tbot.context import Optional
+
+from tbot.machine import linux
+from tbot.machine import board
+from tbot.machine import connector
+
+from tbottest.boardgeneric import cfggeneric
+from tbottest.tc.uboot import board_ub_unit_test
+
+cfg = cfggeneric
+si = cfg.get_default_config("serverip", "None")
+
+
+################################################
+# U-Boot
+################################################
+@tbot.testcase
+def _cxg3_ub_install(
+    lab: Optional[linux.LinuxShell]=None,
+    ub: Optional[board.UBootShell]=None,
+) -> bool:  # noqa: D107
+    """
+    install U-Boot with uuu tool
+    """
+    # install U-Boot with uuu tool
+    tbot.log.message(tbot.log.c("----------- request U-Boot from USB SDP -----------").yellow)
+    oldflags = tbot.flags.copy()
+    try:
+        tbot.flags.remove("bootmode:emmc")
+    except:
+        pass
+    tbot.flags.add("bootmode:usb")
+    tbot.flags.add("uuuloader")
+
+    with tbot.ctx() as cx:
+        if lab is None:
+            lab = cx.request(tbot.role.LabHost)
+
+        ub = cx.request(tbot.role.BoardUBoot)
+
+        if "Boot:  USB" not in ub.bootlog:
+            raise RuntimeError(f"Boot:  USB not found in U-Boot bootlog")
+
+    return True
+
+@tbot.testcase
+def _cxg3_ub_boot_and_test(
+    lab: Optional[linux.LinuxShell]=None,
+    ub: Optional[board.UBootShell]=None,
+) -> bool:  # noqa: D107
+    """
+    boot the new U-Boot from emmc and test it.
+    """
+    tbot.log.message(tbot.log.c("----------- request U-Boot from emmc-----------").yellow)
+    try:
+        tbot.flags.add("bootmode:emmc")
+        tbot.flags.remove("bootmode:usb")
+        tbot.flags.remove("uuuloader")
+    except:
+        pass
+
+    with tbot.ctx() as cx:
+        lab = cx.request(tbot.role.LabHost)
+        ub = cx.request(tbot.role.BoardUBoot)
+
+        if "Boot:  MMC0" not in ub.bootlog:
+            raise RuntimeError(f"Boot:  MMC0 not found in U-Boot bootlog")
+
+        # just a fast ethernet test, more later
+        ub.exec0("ping", si)
+
+        # may unit test command is activated, so call it
+        return board_ub_unit_test(ub)
+
+    return False
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v1 7/8] .gitlab-ci.yml: add tbot-lab
  2025-04-05 18:46 [PATCH v1 0/8] This series introduces U-Boot tests with tbot on real hardware Heiko Schocher
                   ` (5 preceding siblings ...)
  2025-04-05 18:46 ` [PATCH v1 6/8] [RFC] CI: add U-Boot testing on real HW with tbot Heiko Schocher
@ 2025-04-05 18:46 ` Heiko Schocher
  2025-04-05 18:46 ` [PATCH v1 8/8] scripts: add helper for getting infos from your patchwork ToDo list Heiko Schocher
  7 siblings, 0 replies; 9+ messages in thread
From: Heiko Schocher @ 2025-04-05 18:46 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Heiko Schocher, Heiko Schocher, Ilias Apalodimas,
	Jerome Forissier, Simon Glass, Tom Rini

From: Heiko Schocher <hs@nabladev.com>

add testing real hardware with tbot.

Signed-off-by: Heiko Schocher <hs@nabladev.com>
Signed-off-by: Heiko Schocher <hs@denx.de>
---

 .gitlab-ci.yml | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 74 insertions(+)

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 46226eb2fc..f5c24ca30c 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -27,6 +27,7 @@ stages:
   - testsuites
   - test.py
   - sjg-lab
+  - tbot-lab
   - world build
 
 .buildman_and_testpy_template: &buildman_and_testpy_dfn
@@ -693,3 +694,76 @@ vf2:
   variables:
     ROLE: vf2
   <<: *lab_dfn
+
+tbottest-test-all-boards:
+  stage: tbot-lab
+  before_script:
+    # install tbot dependencies
+    - python -m pip install --upgrade pip
+    - pip3 install --user pytest mypy paramiko termcolor2 pyserial coverage pytest-cov
+    - pip3 list
+    - python3 --version
+    # configure ssh
+    - mkdir -p ~/.ssh
+    - chmod 700 ~/.ssh
+    - echo "$SSH_UB_PRIVATE_KEY" | tr -d '\r' > ~/.ssh/staging.key
+    - chmod 600 ~/.ssh/staging.key
+    - git config --global user.email "hs@nabladev.com"
+    - git config --global user.name "Heiko Schocher"
+    - |
+      cat >>~/.ssh/config <<END
+        Host $SSH_UB_HOST
+          HostName $SSH_UB_HOST
+          User $SSH_UB_USER
+          IdentityFile ~/.ssh/staging.key
+          StrictHostKeyChecking no
+
+        Host ubtestinglab
+          HostName ubtestinglab
+          User $SSH_UB_USER
+          ProxyJump $SSH_UB_HOST
+          IdentityFile ~/.ssh/staging.key
+          StrictHostKeyChecking no
+
+      END
+    - export COLUMNS=160
+    - export PYTHONPATH=/home/uboot/.local/lib/python3.10/site-packages
+  script:
+    # install tbot dependencies
+    - python -m pip install --upgrade pip
+    - pip3 install --user pytest mypy paramiko termcolor2 pyserial coverage pytest-cov
+    - pip3 list
+    # Fix warning:
+    # The scripts coverage, coverage-3.10 and coverage3 are installed in '/home/uboot/.local/bin' which is not on PATH.
+    - export PATH=~/.local/bin:$PATH
+    # Fix warning
+    # fatal: detected dubious ownership in repository at '/builds/u-boot/custodians/u-boot-i2c'
+    - git config --global --add safe.directory /builds/u-boot/custodians/u-boot-i2c
+    # now start testing
+    - cd tbottesting
+    - echo "--------------------- test boards ------------------"
+    # set link to tbotconfig data
+    - ln -s tbotconfig-hs tbotconfig
+    # correct path to keyfile
+    - sed -i "s|~/.ssh/id_rsa|~/.ssh/staging.key|g" tbotconfig/hs/tbot.ini
+    # setup tbot
+    - ./preparetbot.sh
+    - returncode=0
+    - set +e
+    - python3 boardtests.py --usetbotflags
+    - exitcode="$?"
+    - echo "exitcode ${exitcode}"
+    - |
+      if [[ "${exitcode}" != "0" ]];then
+          echo "boardtests failed with exitcode ${exitcode}"
+          returncode=1
+      fi
+      exit "${returncode}"
+  artifacts:
+    when: always
+    paths:
+      - "./results/*"
+    reports:
+      # TODO how to report more than one board
+      junit: ./results/cxg3/results.xml
+    expire_in: 1 week
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v1 8/8] scripts: add helper for getting infos from your patchwork ToDo list
  2025-04-05 18:46 [PATCH v1 0/8] This series introduces U-Boot tests with tbot on real hardware Heiko Schocher
                   ` (6 preceding siblings ...)
  2025-04-05 18:46 ` [PATCH v1 7/8] .gitlab-ci.yml: add tbot-lab Heiko Schocher
@ 2025-04-05 18:46 ` Heiko Schocher
  7 siblings, 0 replies; 9+ messages in thread
From: Heiko Schocher @ 2025-04-05 18:46 UTC (permalink / raw)
  To: U-Boot Mailing List
  Cc: Heiko Schocher, Heiko Schocher, Caleb Connolly, Greg Malysa,
	Ilias Apalodimas, Jerome Forissier, Mattijs Korpershoek,
	Nathan Barrett-Morrison, Oliver Gaskell, Robert Marko,
	Sam Protsenko, Simon Glass, Tom Rini

From: Heiko Schocher <hs@nabladev.com>

The new script scripts/getpatchlist.py list for all patches in your
Patchworks ToDo list the PATCH ID and MESSAGE ID.

With that script you can eaysy do in your current U-Boot tree:

    MIL=$(scripts/getpatchlist.py <your username> <your patchwork password> | cut -d " " -f 2)
    for m in $MIL;do
        rm -rf mbox
        wget http://patchwork.ozlabs.org/project/uboot/patch/$m/mbox
        scripts/checkpatch.pl mbox
        git am -3 --whitespace=strip mbox
    done

And you have all your patches from your ToDo list downloaded,
checked with the checkpatch.pl script and applied to your current
branch.

Signed-off-by: Heiko Schocher <hs@nabladev.com>
Signed-off-by: Heiko Schocher <hs@denx.de>
---

 MAINTAINERS             |   1 +
 scripts/getpatchlist.py | 126 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 127 insertions(+)
 create mode 100755 scripts/getpatchlist.py

diff --git a/MAINTAINERS b/MAINTAINERS
index 90a54deedb..24238a8f5b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1678,6 +1678,7 @@ F:	cmd/broadcom/chimp_handshake.c
 TBOTTEST
 M:	Heiko Schocher <hs@nabladev.com>
 S:	Maintained
+F:	scripts/getpatchlist.py
 F:	tbottesting/*
 
 TDA19988 HDMI ENCODER
diff --git a/scripts/getpatchlist.py b/scripts/getpatchlist.py
new file mode 100755
index 0000000000..3df483b1da
--- /dev/null
+++ b/scripts/getpatchlist.py
@@ -0,0 +1,126 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: GPL-2.0+
+
+import requests
+import argparse
+from bs4 import BeautifulSoup
+
+# URLs
+LOGIN_URL = "https://patchwork.ozlabs.org/user/login/"
+TODO_LIST_URL = "https://patchwork.ozlabs.org/user/todo/uboot/"
+
+def login_and_get_cookies(username, password):
+    # Start a session to maintain cookies
+    session = requests.Session()
+
+    # Get the CSRF token by sending a GET request to the login page
+    response = session.get(LOGIN_URL)
+
+    # Check if the response is successful
+    if response.status_code != 200:
+        print(f"Error fetching login page: {response.status_code}")
+        return None, None
+
+    # Extract CSRF token from cookies or HTML
+    csrf_token = response.cookies.get('csrftoken')
+    if not csrf_token:
+        # If not found in cookies, extract it from the HTML form
+        soup = BeautifulSoup(response.text, "html.parser")
+        csrf_token = soup.find("input", {"name": "csrfmiddlewaretoken"})["value"]
+
+    #print(f"CSRF Token: {csrf_token}")
+
+    # Prepare login data
+    login_data = {
+        'username': username,
+        'password': password,
+        'csrfmiddlewaretoken': csrf_token,
+    }
+
+    # Send POST request to login
+    headers = {
+        'User-Agent': 'Mozilla/5.0',  # Common user-agent string
+        'Referer': LOGIN_URL  # Set Referer header to avoid potential issues
+    }
+
+    # Perform login
+    login_response = session.post(LOGIN_URL, data=login_data, headers=headers)
+
+    # If login is successful, extract session ID from cookies
+    if login_response.status_code == 200:
+        session_id = session.cookies.get('sessionid')  # Get session ID from cookies
+        #print(f"Session ID: {session_id}")
+        return session, session_id
+    else:
+        print(f"Login failed: {login_response.status_code}")
+        return None, None
+
+def get_todo_patch_and_message_ids(session):
+    response = session.get(TODO_LIST_URL)
+
+    if response.status_code != 200:
+        print(f"Error fetching todo list: {response.status_code}")
+        return []
+
+    soup = BeautifulSoup(response.text, "html.parser")
+
+    patch_data = []
+    for row in soup.select("tr[id^='patch_row']"):  # Identify all patch rows
+        # Extract the Patch ID from the 'id' attribute
+        patch_id = row.get("id").split(":")[1]
+
+        # Extract the Message ID from the patch URL
+        msg_id_tag = row.select_one('a[href^="/project/uboot/patch/"]')  # Look for the patch URL
+        if msg_id_tag:
+            msg_id = msg_id_tag["href"].split("/")[4]  # Extract the Message ID
+
+            patch_data.append((patch_id, msg_id))
+
+    return patch_data
+
+def main():
+    """
+    Get a list of your patches in your patchworks ToDo list. List for each patch the
+    PATCH ID and MESSAGE ID, so you can use them for example with the pwclient.py tool.
+
+    Or you can do in your current U-Boot tree:
+
+    MIL=$(scripts/getpatchlist.py <your username> <your patchwork password> | cut -d " " -f 2)
+    for m in $MIL;do
+        rm -rf mbox
+        wget http://patchwork.ozlabs.org/project/uboot/patch/$m/mbox
+        scripts/checkpatch.pl mbox
+        git am -3 --whitespace=strip mbox
+    done
+
+    And you have all your patches from your ToDo list downloaded, checked with the
+    checkpatch.pl script and applied to your current branch.
+    """
+    # Set up argument parser
+    parser = argparse.ArgumentParser(description="Login to Patchwork and get Todo list patches.")
+    parser.add_argument("username", help="Your Patchwork username")
+    parser.add_argument("password", help="Your Patchwork password")
+
+    # Parse arguments
+    args = parser.parse_args()
+
+    # Step 1: Login and get session
+    session, session_id = login_and_get_cookies(args.username, args.password)
+
+    if session:
+        # Step 2: Get patch IDs and message IDs
+        patches = get_todo_patch_and_message_ids(session)
+
+        if patches:
+            # print("Found Patch IDs and Message IDs:")
+            for patch_id, msg_id in patches:
+                print(f"{patch_id} {msg_id}")
+        else:
+            print("No patches found. Check the HTML structure!")
+            exit (1)
+    else:
+        print("Unable to login. Exiting.")
+        exit (2)
+
+if __name__ == "__main__":
+    main()
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2025-04-05 18:48 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-04-05 18:46 [PATCH v1 0/8] This series introduces U-Boot tests with tbot on real hardware Heiko Schocher
2025-04-05 18:46 ` [PATCH v1 1/8] test/py/requirements.txt: update coverage Heiko Schocher
2025-04-05 18:46 ` [PATCH v1 2/8] tools/buildman/requirements.txt: " Heiko Schocher
2025-04-05 18:46 ` [PATCH v1 3/8] test/py/requirements.txt: increase filelock version Heiko Schocher
2025-04-05 18:46 ` [PATCH v1 4/8] test/py/requirements.txt: remove unittest2 and testtools Heiko Schocher
2025-04-05 18:46 ` [PATCH v1 5/8] test: increase timeouts Heiko Schocher
2025-04-05 18:46 ` [PATCH v1 6/8] [RFC] CI: add U-Boot testing on real HW with tbot Heiko Schocher
2025-04-05 18:46 ` [PATCH v1 7/8] .gitlab-ci.yml: add tbot-lab Heiko Schocher
2025-04-05 18:46 ` [PATCH v1 8/8] scripts: add helper for getting infos from your patchwork ToDo list Heiko Schocher

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox