hector-cli 0.6.0__tar.gz → 0.7.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. {hector_cli-0.6.0 → hector_cli-0.7.0}/PKG-INFO +8 -5
  2. {hector_cli-0.6.0 → hector_cli-0.7.0}/README.md +7 -4
  3. {hector_cli-0.6.0 → hector_cli-0.7.0}/hector/commands/base.py +2 -2
  4. {hector_cli-0.6.0 → hector_cli-0.7.0}/hector/core.py +20 -13
  5. {hector_cli-0.6.0 → hector_cli-0.7.0}/hector/docker.py +1 -1
  6. {hector_cli-0.6.0 → hector_cli-0.7.0}/hector/pipeline.py +16 -3
  7. {hector_cli-0.6.0 → hector_cli-0.7.0}/hector_cli.egg-info/PKG-INFO +8 -5
  8. {hector_cli-0.6.0 → hector_cli-0.7.0}/tests/test_pipeline_helpers.py +29 -0
  9. {hector_cli-0.6.0 → hector_cli-0.7.0}/LICENSE +0 -0
  10. {hector_cli-0.6.0 → hector_cli-0.7.0}/hector/__init__.py +0 -0
  11. {hector_cli-0.6.0 → hector_cli-0.7.0}/hector/__main__.py +0 -0
  12. {hector_cli-0.6.0 → hector_cli-0.7.0}/hector/commands/__init__.py +0 -0
  13. {hector_cli-0.6.0 → hector_cli-0.7.0}/hector/commands/clean.py +0 -0
  14. {hector_cli-0.6.0 → hector_cli-0.7.0}/hector/commands/export.py +0 -0
  15. {hector_cli-0.6.0 → hector_cli-0.7.0}/hector/commands/init.py +0 -0
  16. {hector_cli-0.6.0 → hector_cli-0.7.0}/hector/commands/run.py +0 -0
  17. {hector_cli-0.6.0 → hector_cli-0.7.0}/hector/commands/test.py +0 -0
  18. {hector_cli-0.6.0 → hector_cli-0.7.0}/hector/commands/validate.py +0 -0
  19. {hector_cli-0.6.0 → hector_cli-0.7.0}/hector/connections.py +0 -0
  20. {hector_cli-0.6.0 → hector_cli-0.7.0}/hector/dependencies.py +0 -0
  21. {hector_cli-0.6.0 → hector_cli-0.7.0}/hector/generator.py +0 -0
  22. {hector_cli-0.6.0 → hector_cli-0.7.0}/hector/hubs.py +0 -0
  23. {hector_cli-0.6.0 → hector_cli-0.7.0}/hector/mappings.py +0 -0
  24. {hector_cli-0.6.0 → hector_cli-0.7.0}/hector/modules.py +0 -0
  25. {hector_cli-0.6.0 → hector_cli-0.7.0}/hector/peripherals.py +0 -0
  26. {hector_cli-0.6.0 → hector_cli-0.7.0}/hector/reporters.py +0 -0
  27. {hector_cli-0.6.0 → hector_cli-0.7.0}/hector/runners.py +0 -0
  28. {hector_cli-0.6.0 → hector_cli-0.7.0}/hector/scaffold.py +0 -0
  29. {hector_cli-0.6.0 → hector_cli-0.7.0}/hector/validator.py +0 -0
  30. {hector_cli-0.6.0 → hector_cli-0.7.0}/hector_cli.egg-info/SOURCES.txt +0 -0
  31. {hector_cli-0.6.0 → hector_cli-0.7.0}/hector_cli.egg-info/dependency_links.txt +0 -0
  32. {hector_cli-0.6.0 → hector_cli-0.7.0}/hector_cli.egg-info/entry_points.txt +0 -0
  33. {hector_cli-0.6.0 → hector_cli-0.7.0}/hector_cli.egg-info/requires.txt +0 -0
  34. {hector_cli-0.6.0 → hector_cli-0.7.0}/hector_cli.egg-info/top_level.txt +0 -0
  35. {hector_cli-0.6.0 → hector_cli-0.7.0}/setup.cfg +0 -0
  36. {hector_cli-0.6.0 → hector_cli-0.7.0}/setup.py +0 -0
  37. {hector_cli-0.6.0 → hector_cli-0.7.0}/tests/test_arguments.py +0 -0
  38. {hector_cli-0.6.0 → hector_cli-0.7.0}/tests/test_clean.py +0 -0
  39. {hector_cli-0.6.0 → hector_cli-0.7.0}/tests/test_cli_smoke.py +0 -0
  40. {hector_cli-0.6.0 → hector_cli-0.7.0}/tests/test_connections.py +0 -0
  41. {hector_cli-0.6.0 → hector_cli-0.7.0}/tests/test_core_paths.py +0 -0
  42. {hector_cli-0.6.0 → hector_cli-0.7.0}/tests/test_core_registry.py +0 -0
  43. {hector_cli-0.6.0 → hector_cli-0.7.0}/tests/test_core_text.py +0 -0
  44. {hector_cli-0.6.0 → hector_cli-0.7.0}/tests/test_docker_argv.py +0 -0
  45. {hector_cli-0.6.0 → hector_cli-0.7.0}/tests/test_generator.py +0 -0
  46. {hector_cli-0.6.0 → hector_cli-0.7.0}/tests/test_hubs.py +0 -0
  47. {hector_cli-0.6.0 → hector_cli-0.7.0}/tests/test_mappings.py +0 -0
  48. {hector_cli-0.6.0 → hector_cli-0.7.0}/tests/test_matrix.py +0 -0
  49. {hector_cli-0.6.0 → hector_cli-0.7.0}/tests/test_needs_renode_source.py +0 -0
  50. {hector_cli-0.6.0 → hector_cli-0.7.0}/tests/test_peripherals.py +0 -0
  51. {hector_cli-0.6.0 → hector_cli-0.7.0}/tests/test_reporters.py +0 -0
  52. {hector_cli-0.6.0 → hector_cli-0.7.0}/tests/test_runners.py +0 -0
  53. {hector_cli-0.6.0 → hector_cli-0.7.0}/tests/test_scaffold.py +0 -0
  54. {hector_cli-0.6.0 → hector_cli-0.7.0}/tests/test_validator.py +0 -0
  55. {hector_cli-0.6.0 → hector_cli-0.7.0}/tests/test_version.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hector-cli
3
- Version: 0.6.0
3
+ Version: 0.7.0
4
4
  Summary: YAML-driven Renode + Verilator simulation orchestrator for embedded hardware CI
5
5
  Home-page: https://hector-ci.com
6
6
  Author: Nemesis
@@ -210,7 +210,7 @@ the CLI natively with `pip` and let hector launch real per-step containers.
210
210
  | `hector run --renode-dir /cache/renode` | Use/cache the Renode source checkout at this path (only fetched when needed) |
211
211
  | `hector run --renode-integration-dir /cache/integration` | Likewise for the verilator-integration checkout |
212
212
  | `hector run --no-docker` | Use locally installed `renode` / `renode-test` instead of Docker |
213
- | `hector run --workspace-mount /mnt` | Override the container path the project root is mounted at |
213
+ | `hector run --workspace-mount /mnt` | Mount the hectorfile's folder at this container path and execute there |
214
214
  | `hector run --snapshot path/to/snapshot.save` | Load a snapshot instead of booting from the resc |
215
215
  | `hector run --snapshot snap.save --renode-version 1.16.1` | Load a snapshot without a `.hector.yaml` |
216
216
  | `hector test` | Run the `tests:` section; exit 1 on any failure |
@@ -487,7 +487,7 @@ hector run --renode-args '--hide-log --config my.conf'
487
487
 
488
488
  Everything a hectorfile executes — `build:` steps, `shell` tests, Renode and `renode-test` — runs **in the hectorfile's folder**, and paths written in the file (`firmware:`, `platform:`, module `source:`, test `file:` / `snapshot:`, `file:` mappings, `artifacts:`, paths inside scripts and `commands:`) are **relative to that folder**. So `hector test -f boards/nucleo/.hector.yaml` behaves the same as running `hector test` inside `boards/nucleo/`.
489
489
 
490
- The directory you run hector from is mounted into the container (at the same path), and the container's working directory (`-w`) is the hectorfile's folder. If the hectorfile lives **outside** the directory you run from (`hector test -f ../other/.hector.yaml`), its folder is mounted as well, at its own path. A path like `../shared/board.repl` works as long as it lands inside one of those mounts — for anything else, add a mount with [`docker_args`](#extra-docker-flags---docker-args). Under `--no-docker` the processes simply run with the hectorfile's folder as their cwd.
490
+ The directory you run hector from is mounted into the container (at the same path), and the container's working directory (`-w`) is the hectorfile's folder. If the hectorfile lives **outside** the directory you run from (`hector test -f ../other/.hector.yaml`), its folder is mounted as well, at its own path. (With [`--workspace-mount`](#overriding-the-workspace-mount-path---workspace-mount) the hectorfile's folder is mounted at the given path instead.) A path like `../shared/board.repl` works as long as it lands inside one of those mounts — for anything else, add a mount with [`docker_args`](#extra-docker-flags---docker-args). Under `--no-docker` the processes simply run with the hectorfile's folder as their cwd.
491
491
 
492
492
  Paths given on the **command line** (`--output`, `--snapshot`, `--test-file`, `--artifacts`, `--renode-dir`, …) stay relative to where you run hector, and `.hector/` is still created there.
493
493
 
@@ -572,12 +572,15 @@ An existing directory is reused as-is; a missing one is cloned into. The locatio
572
572
 
573
573
  #### Overriding the workspace mount path (`--workspace-mount`)
574
574
 
575
- By default the project root is bind-mounted into the container at the **same absolute path** as on the host (e.g. `/home/user/projects/myboard`), so paths look identical inside and outside the container. Override this only if the host path is unavailable at that location inside the image:
575
+ By default everything is bind-mounted into the container at the **same absolute path** as on the host (e.g. `/home/user/projects/myboard`), so paths look identical inside and outside the container. `--workspace-mount PATH` instead mounts the **hectorfile's folder** at `PATH`, and that's where every step, Renode and `renode-test` execute:
576
576
 
577
577
  ```bash
578
- hector run --workspace-mount /workspace
578
+ hector run --workspace-mount /workspace # . → /workspace
579
+ hector test -f boards/nucleo/.hector.yaml --workspace-mount /workspace # boards/nucleo → /workspace
579
580
  ```
580
581
 
582
+ When you run from a different folder than the hectorfile's (the second line), that folder — where `.hector/` and `--output` live — is additionally mounted at its own path, unless it's already inside the hectorfile's folder.
583
+
581
584
  **Cannot be combined with `--no-docker`** — if you are running locally there is no container mount to configure.
582
585
 
583
586
  ### Selecting a matrix combination (`--job`)
@@ -180,7 +180,7 @@ the CLI natively with `pip` and let hector launch real per-step containers.
180
180
  | `hector run --renode-dir /cache/renode` | Use/cache the Renode source checkout at this path (only fetched when needed) |
181
181
  | `hector run --renode-integration-dir /cache/integration` | Likewise for the verilator-integration checkout |
182
182
  | `hector run --no-docker` | Use locally installed `renode` / `renode-test` instead of Docker |
183
- | `hector run --workspace-mount /mnt` | Override the container path the project root is mounted at |
183
+ | `hector run --workspace-mount /mnt` | Mount the hectorfile's folder at this container path and execute there |
184
184
  | `hector run --snapshot path/to/snapshot.save` | Load a snapshot instead of booting from the resc |
185
185
  | `hector run --snapshot snap.save --renode-version 1.16.1` | Load a snapshot without a `.hector.yaml` |
186
186
  | `hector test` | Run the `tests:` section; exit 1 on any failure |
@@ -457,7 +457,7 @@ hector run --renode-args '--hide-log --config my.conf'
457
457
 
458
458
  Everything a hectorfile executes — `build:` steps, `shell` tests, Renode and `renode-test` — runs **in the hectorfile's folder**, and paths written in the file (`firmware:`, `platform:`, module `source:`, test `file:` / `snapshot:`, `file:` mappings, `artifacts:`, paths inside scripts and `commands:`) are **relative to that folder**. So `hector test -f boards/nucleo/.hector.yaml` behaves the same as running `hector test` inside `boards/nucleo/`.
459
459
 
460
- The directory you run hector from is mounted into the container (at the same path), and the container's working directory (`-w`) is the hectorfile's folder. If the hectorfile lives **outside** the directory you run from (`hector test -f ../other/.hector.yaml`), its folder is mounted as well, at its own path. A path like `../shared/board.repl` works as long as it lands inside one of those mounts — for anything else, add a mount with [`docker_args`](#extra-docker-flags---docker-args). Under `--no-docker` the processes simply run with the hectorfile's folder as their cwd.
460
+ The directory you run hector from is mounted into the container (at the same path), and the container's working directory (`-w`) is the hectorfile's folder. If the hectorfile lives **outside** the directory you run from (`hector test -f ../other/.hector.yaml`), its folder is mounted as well, at its own path. (With [`--workspace-mount`](#overriding-the-workspace-mount-path---workspace-mount) the hectorfile's folder is mounted at the given path instead.) A path like `../shared/board.repl` works as long as it lands inside one of those mounts — for anything else, add a mount with [`docker_args`](#extra-docker-flags---docker-args). Under `--no-docker` the processes simply run with the hectorfile's folder as their cwd.
461
461
 
462
462
  Paths given on the **command line** (`--output`, `--snapshot`, `--test-file`, `--artifacts`, `--renode-dir`, …) stay relative to where you run hector, and `.hector/` is still created there.
463
463
 
@@ -542,12 +542,15 @@ An existing directory is reused as-is; a missing one is cloned into. The locatio
542
542
 
543
543
  #### Overriding the workspace mount path (`--workspace-mount`)
544
544
 
545
- By default the project root is bind-mounted into the container at the **same absolute path** as on the host (e.g. `/home/user/projects/myboard`), so paths look identical inside and outside the container. Override this only if the host path is unavailable at that location inside the image:
545
+ By default everything is bind-mounted into the container at the **same absolute path** as on the host (e.g. `/home/user/projects/myboard`), so paths look identical inside and outside the container. `--workspace-mount PATH` instead mounts the **hectorfile's folder** at `PATH`, and that's where every step, Renode and `renode-test` execute:
546
546
 
547
547
  ```bash
548
- hector run --workspace-mount /workspace
548
+ hector run --workspace-mount /workspace # . → /workspace
549
+ hector test -f boards/nucleo/.hector.yaml --workspace-mount /workspace # boards/nucleo → /workspace
549
550
  ```
550
551
 
552
+ When you run from a different folder than the hectorfile's (the second line), that folder — where `.hector/` and `--output` live — is additionally mounted at its own path, unless it's already inside the hectorfile's folder.
553
+
551
554
  **Cannot be combined with `--no-docker`** — if you are running locally there is no container mount to configure.
552
555
 
553
556
  ### Selecting a matrix combination (`--job`)
@@ -110,8 +110,8 @@ def add_common_arguments(parser):
110
110
  )
111
111
  docker_mode.add_argument(
112
112
  "--workspace-mount", metavar="PATH", dest="workspace_mount", default=None,
113
- help="Container path where the project root is bind-mounted "
114
- "(default: same absolute path as on the host).",
113
+ help="Mount the hectorfile's folder at this container path and execute there "
114
+ "(default: everything is mounted at its own host path).",
115
115
  )
116
116
 
117
117
 
@@ -67,7 +67,7 @@ class Registry:
67
67
  # ==========================================================================
68
68
  # CONSTANTS
69
69
  # ==========================================================================
70
- TOOL_VERSION = "0.6.0"
70
+ TOOL_VERSION = "0.7.0"
71
71
  SUPPORTED_SCHEMA_VERSIONS = {"0.1"}
72
72
 
73
73
  RENODE_REPO_URL = "https://github.com/renode/renode.git"
@@ -78,7 +78,10 @@ ARTIFACTS_DIR = ".hector" # everything we generate/clone lives here (gi
78
78
  # hosts we mirror the host cwd, so paths look identical in and out; on Windows the host
79
79
  # path (C:\...) is not a valid Linux path, so use a fixed POSIX mount point and translate.
80
80
  WORKSPACE_MOUNT = "/workspace" if os.name == "nt" else os.getcwd()
81
- NO_DOCKER = False # when True, call renode/renode-test directly on host
81
+ # Host directory bind-mounted at WORKSPACE_MOUNT. None = the cwd; --workspace-mount
82
+ # sets it to the config's directory, so the mount point is where execution happens.
83
+ WORKSPACE_ROOT = None
84
+ NO_DOCKER = False # when True, call renode/renode-test directly on host
82
85
  EXTRA_MOUNTS = [] # dep dirs outside the workspace, bind-mounted 1:1 into every container
83
86
  DOCKER_ARGS = [] # user flags (docker_args: + --docker-args) added to every `docker run`
84
87
  # Host directory of the config file being executed. Paths written in the config resolve
@@ -124,12 +127,17 @@ def host_uid_gid():
124
127
  return None
125
128
 
126
129
 
130
+ def workspace_root():
131
+ """Host directory mounted at WORKSPACE_MOUNT (see WORKSPACE_ROOT)."""
132
+ return os.path.realpath(WORKSPACE_ROOT or os.getcwd())
133
+
134
+
127
135
  def to_container_path(host_path):
128
136
  abs_path = os.path.realpath(host_path)
129
- root = os.path.realpath(os.getcwd())
137
+ root = workspace_root()
130
138
  if os.path.commonpath([abs_path, root]) != root:
131
- # Out-of-tree dirs registered in EXTRA_MOUNTS (the config's dir, a shared
132
- # Renode cache) are mounted 1:1, so their paths are valid as-is.
139
+ # Dirs outside the workspace registered in EXTRA_MOUNTS (the config's dir or the
140
+ # cwd, a shared Renode cache) are mounted 1:1, so their paths are valid as-is.
133
141
  for m in EXTRA_MOUNTS:
134
142
  if os.path.commonpath([abs_path, m]) == m:
135
143
  return abs_path
@@ -150,13 +158,12 @@ def register_dependency_mount(host_dir):
150
158
  Dirs under the workspace are already covered by the workspace mount, so they map via
151
159
  to_container_path. An out-of-tree dir (e.g. a shared cache) is registered in
152
160
  EXTRA_MOUNTS and used at its own absolute path inside the container."""
153
- abs_dir = os.path.realpath(host_dir)
154
- root = os.path.realpath(os.getcwd())
155
- if os.path.commonpath([abs_dir, root]) == root:
156
- return to_container_path(host_dir)
157
- if abs_dir not in EXTRA_MOUNTS:
161
+ try:
162
+ return to_container_path(host_dir) # already reachable through some mount
163
+ except ValueError:
164
+ abs_dir = os.path.realpath(host_dir)
158
165
  EXTRA_MOUNTS.append(abs_dir)
159
- return abs_dir
166
+ return abs_dir
160
167
 
161
168
 
162
169
  def container_path_for(host_path):
@@ -176,8 +183,8 @@ def container_to_host(container_path):
176
183
  if container_path != WORKSPACE_MOUNT and not container_path.startswith(WORKSPACE_MOUNT + "/"):
177
184
  raise ValueError(f"'{container_path}' is not under {WORKSPACE_MOUNT}.")
178
185
  rel = posixpath.relpath(container_path, WORKSPACE_MOUNT).replace("/", os.sep)
179
- host = os.path.realpath(os.path.join(os.getcwd(), rel))
180
- root = os.path.realpath(os.getcwd())
186
+ root = workspace_root()
187
+ host = os.path.realpath(os.path.join(root, rel))
181
188
  if os.path.commonpath([host, root]) != root:
182
189
  raise ValueError(f"'{container_path}' maps outside the project root.")
183
190
  return host
@@ -48,7 +48,7 @@ def _user_flags():
48
48
 
49
49
 
50
50
  def _workspace_mount():
51
- return ["-v", f"{os.getcwd()}:{core.WORKSPACE_MOUNT}", "-w", core.execution_dir()]
51
+ return ["-v", f"{core.workspace_root()}:{core.WORKSPACE_MOUNT}", "-w", core.execution_dir()]
52
52
 
53
53
 
54
54
  def _extra_mounts():
@@ -47,6 +47,9 @@ from .validator import print_issues, validate_config
47
47
  # The config file every command reads/writes. Overridable with -f/--file; set by
48
48
  # apply_global_flags before any config is loaded.
49
49
  CONFIG_PATH = ".hector.yaml"
50
+ # --workspace-mount given: mount the config's directory (where execution happens) at
51
+ # that path, instead of the cwd. Set by apply_global_flags, applied once the config loads.
52
+ MOUNT_CONFIG_DIR = False
50
53
 
51
54
 
52
55
  def apply_global_flags(args):
@@ -60,7 +63,9 @@ def apply_global_flags(args):
60
63
  global CONFIG_PATH
61
64
  CONFIG_PATH = path
62
65
  if getattr(args, "workspace_mount", None):
66
+ global MOUNT_CONFIG_DIR
63
67
  _core.WORKSPACE_MOUNT = args.workspace_mount
68
+ MOUNT_CONFIG_DIR = True
64
69
  if getattr(args, "no_docker", False) or os.environ.get("HECTOR_NO_DOCKER"):
65
70
  _core.NO_DOCKER = True
66
71
  _core.WORKSPACE_MOUNT = os.getcwd()
@@ -110,10 +115,18 @@ def load_config_or_exit():
110
115
 
111
116
  def _set_config_dir(config_path):
112
117
  """Make the config's directory the base for its paths and the working directory of
113
- everything executed (see core.CONFIG_DIR). The cwd stays the workspace mount; a
114
- config outside it gets its directory bind-mounted 1:1 as well, so it's reachable."""
118
+ everything executed (see core.CONFIG_DIR), and make sure both it and the cwd (where
119
+ .hector/ and --output live) are reachable from the container.
120
+
121
+ By default the cwd is the workspace mount and a config dir outside it is mounted
122
+ 1:1 as well. With --workspace-mount, the config dir is mounted at that path instead
123
+ (so execution happens there) and a cwd outside it is the one mounted 1:1."""
115
124
  _core.CONFIG_DIR = os.path.realpath(os.path.dirname(os.path.abspath(config_path)))
116
- _core.register_dependency_mount(_core.CONFIG_DIR)
125
+ if MOUNT_CONFIG_DIR:
126
+ _core.WORKSPACE_ROOT = _core.CONFIG_DIR
127
+ _core.register_dependency_mount(os.getcwd())
128
+ else:
129
+ _core.register_dependency_mount(_core.CONFIG_DIR)
117
130
 
118
131
 
119
132
  _VERSION_TAG_RE = re.compile(r"^v?\d+\.\d+\.\d+$")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hector-cli
3
- Version: 0.6.0
3
+ Version: 0.7.0
4
4
  Summary: YAML-driven Renode + Verilator simulation orchestrator for embedded hardware CI
5
5
  Home-page: https://hector-ci.com
6
6
  Author: Nemesis
@@ -210,7 +210,7 @@ the CLI natively with `pip` and let hector launch real per-step containers.
210
210
  | `hector run --renode-dir /cache/renode` | Use/cache the Renode source checkout at this path (only fetched when needed) |
211
211
  | `hector run --renode-integration-dir /cache/integration` | Likewise for the verilator-integration checkout |
212
212
  | `hector run --no-docker` | Use locally installed `renode` / `renode-test` instead of Docker |
213
- | `hector run --workspace-mount /mnt` | Override the container path the project root is mounted at |
213
+ | `hector run --workspace-mount /mnt` | Mount the hectorfile's folder at this container path and execute there |
214
214
  | `hector run --snapshot path/to/snapshot.save` | Load a snapshot instead of booting from the resc |
215
215
  | `hector run --snapshot snap.save --renode-version 1.16.1` | Load a snapshot without a `.hector.yaml` |
216
216
  | `hector test` | Run the `tests:` section; exit 1 on any failure |
@@ -487,7 +487,7 @@ hector run --renode-args '--hide-log --config my.conf'
487
487
 
488
488
  Everything a hectorfile executes — `build:` steps, `shell` tests, Renode and `renode-test` — runs **in the hectorfile's folder**, and paths written in the file (`firmware:`, `platform:`, module `source:`, test `file:` / `snapshot:`, `file:` mappings, `artifacts:`, paths inside scripts and `commands:`) are **relative to that folder**. So `hector test -f boards/nucleo/.hector.yaml` behaves the same as running `hector test` inside `boards/nucleo/`.
489
489
 
490
- The directory you run hector from is mounted into the container (at the same path), and the container's working directory (`-w`) is the hectorfile's folder. If the hectorfile lives **outside** the directory you run from (`hector test -f ../other/.hector.yaml`), its folder is mounted as well, at its own path. A path like `../shared/board.repl` works as long as it lands inside one of those mounts — for anything else, add a mount with [`docker_args`](#extra-docker-flags---docker-args). Under `--no-docker` the processes simply run with the hectorfile's folder as their cwd.
490
+ The directory you run hector from is mounted into the container (at the same path), and the container's working directory (`-w`) is the hectorfile's folder. If the hectorfile lives **outside** the directory you run from (`hector test -f ../other/.hector.yaml`), its folder is mounted as well, at its own path. (With [`--workspace-mount`](#overriding-the-workspace-mount-path---workspace-mount) the hectorfile's folder is mounted at the given path instead.) A path like `../shared/board.repl` works as long as it lands inside one of those mounts — for anything else, add a mount with [`docker_args`](#extra-docker-flags---docker-args). Under `--no-docker` the processes simply run with the hectorfile's folder as their cwd.
491
491
 
492
492
  Paths given on the **command line** (`--output`, `--snapshot`, `--test-file`, `--artifacts`, `--renode-dir`, …) stay relative to where you run hector, and `.hector/` is still created there.
493
493
 
@@ -572,12 +572,15 @@ An existing directory is reused as-is; a missing one is cloned into. The locatio
572
572
 
573
573
  #### Overriding the workspace mount path (`--workspace-mount`)
574
574
 
575
- By default the project root is bind-mounted into the container at the **same absolute path** as on the host (e.g. `/home/user/projects/myboard`), so paths look identical inside and outside the container. Override this only if the host path is unavailable at that location inside the image:
575
+ By default everything is bind-mounted into the container at the **same absolute path** as on the host (e.g. `/home/user/projects/myboard`), so paths look identical inside and outside the container. `--workspace-mount PATH` instead mounts the **hectorfile's folder** at `PATH`, and that's where every step, Renode and `renode-test` execute:
576
576
 
577
577
  ```bash
578
- hector run --workspace-mount /workspace
578
+ hector run --workspace-mount /workspace # . → /workspace
579
+ hector test -f boards/nucleo/.hector.yaml --workspace-mount /workspace # boards/nucleo → /workspace
579
580
  ```
580
581
 
582
+ When you run from a different folder than the hectorfile's (the second line), that folder — where `.hector/` and `--output` live — is additionally mounted at its own path, unless it's already inside the hectorfile's folder.
583
+
581
584
  **Cannot be combined with `--no-docker`** — if you are running locally there is no container mount to configure.
582
585
 
583
586
  ### Selecting a matrix combination (`--job`)
@@ -46,6 +46,8 @@ def config_in_subdir(tmp_path, monkeypatch):
46
46
  monkeypatch.setattr(core, "NO_DOCKER", False)
47
47
  monkeypatch.setattr(core, "CONFIG_DIR", None)
48
48
  monkeypatch.setattr(core, "EXTRA_MOUNTS", [])
49
+ monkeypatch.setattr(core, "WORKSPACE_ROOT", None)
50
+ monkeypatch.setattr(pipeline, "MOUNT_CONFIG_DIR", False)
49
51
  (tmp_path / "board").mkdir()
50
52
  (tmp_path / "board" / ".hector.yaml").write_text("renode_version: '1.16.1'\n")
51
53
  return pipeline, core, tmp_path
@@ -75,6 +77,33 @@ def test_load_config_outside_cwd_is_mounted_too(config_in_subdir, monkeypatch):
75
77
  assert core.to_container_path(core.from_config("fw.elf")) == f"{board}/fw.elf"
76
78
 
77
79
 
80
+ def test_workspace_mount_mounts_config_dir_there(config_in_subdir, monkeypatch):
81
+ # Run from the parent with --workspace-mount /workspace: the config's dir is what's
82
+ # mounted there and where execution happens; the cwd (.hector/, --output) is 1:1.
83
+ pipeline, core, root = config_in_subdir
84
+ monkeypatch.setattr(core, "WORKSPACE_MOUNT", "/workspace")
85
+ monkeypatch.setattr(pipeline, "MOUNT_CONFIG_DIR", True)
86
+ monkeypatch.setattr(pipeline, "CONFIG_PATH", "board/.hector.yaml")
87
+ pipeline.load_config_or_exit()
88
+ board, cwd = str((root / "board").resolve()), str(root.resolve())
89
+ assert core.workspace_root() == board
90
+ assert core.execution_dir() == "/workspace"
91
+ assert core.to_container_path(core.from_config("fw/app.elf")) == "/workspace/fw/app.elf"
92
+ assert core.EXTRA_MOUNTS == [cwd]
93
+ assert core.to_container_path(".hector/resc/job_1.resc") == f"{cwd}/.hector/resc/job_1.resc"
94
+
95
+
96
+ def test_workspace_mount_from_config_dir_needs_no_extra_mount(config_in_subdir, monkeypatch):
97
+ pipeline, core, root = config_in_subdir
98
+ monkeypatch.chdir(root / "board")
99
+ monkeypatch.setattr(core, "WORKSPACE_MOUNT", "/workspace")
100
+ monkeypatch.setattr(pipeline, "MOUNT_CONFIG_DIR", True)
101
+ monkeypatch.setattr(pipeline, "CONFIG_PATH", ".hector.yaml")
102
+ pipeline.load_config_or_exit()
103
+ assert core.execution_dir() == "/workspace"
104
+ assert core.EXTRA_MOUNTS == []
105
+
106
+
78
107
  # ---- apply_docker_args ----
79
108
 
80
109
  @pytest.mark.parametrize("cfg,flag,expected", [
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes