@andrian.yablonskyy/thub-agent 1.1.2 → 1.1.3

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 (3) hide show
  1. package/README.md +3 -3
  2. package/package.json +1 -1
  3. package/src/cli.js +18 -3
package/README.md CHANGED
@@ -48,7 +48,7 @@ Key options for `thub run`. **On the Client** names the environment variable the
48
48
  | Option | Description | On the Client |
49
49
  |---|---|---|
50
50
  | `--type hw\|sw` | Required resource type. | `JOB_TYPE` |
51
- | `--board <name>` / `--label <l>` | Required labels (repeatable). | `JOB_BOARD`; `JOB_LABEL`, `JOB_LABEL_<n>` |
51
+ | `--label <l>` | Required labels (repeatable; a board is `--label board:<name>`): the job runs only on a runner that has all of them. Each 1–64 characters, no whitespace, commas or semicolons. | `JOB_LABEL`, `JOB_LABEL_<n>` |
52
52
  | `--client <name\|id>` | Run on this specific Client (resource name or id) only; the job waits in that Client's queue even if other matching resources are idle. | `JOB_CLIENT` |
53
53
  | `--user <name>` | Free-text job owner — a label, not an identity. Falls back to `THUB_USER` / `thub config set user <name>`. | `JOB_USER` |
54
54
  | `--command <string>` | **Required.** The task's entry point: a shell command the Client runs (`sh -c`) in the task's work directory — the `--git-repo` checkout, else an empty directory — after preparing its inputs. Its exit code is the verdict. On HW it flashes the board itself (the Client doesn't); it gets `THUB_DUT_STLINK`/`_UART`/`_USB`/`_HOST`/`_CONTAINER`, `THUB_DOWNLOAD_<n>`, `THUB_DOWNLOADS_DIR`, `THUB_GIT_COMMIT`, `THUB_SUITE`, `THUB_META_*`. | `JOB_COMMAND` |
@@ -88,7 +88,7 @@ Exit codes make the Agent usable as a CI step:
88
88
  **Run a task** — download the firmware, check out the tests at a tag, flash and test (HW):
89
89
 
90
90
  ```bash
91
- thub run --type hw --board nucleo-f401re \
91
+ thub run --type hw --label board:nucleo-f401re \
92
92
  --download-file "$IMAGE_URL" \
93
93
  --git-repo https://github.com/yourorg/firmware-tests.git v1.4.0 \
94
94
  --command 'st-flash --serial "$THUB_DUT_STLINK" --reset write "$THUB_DOWNLOAD_1" 0x08000000 && ./ci/test.sh "$@"' \
@@ -125,7 +125,7 @@ thub run --type sw --download-file https://does-not-exist.invalid/app.bin \
125
125
  **Label a job with its owner** — purely informational, shows up on the dashboard, in `thub jobs`, and on the Client's own console:
126
126
 
127
127
  ```bash
128
- thub run --type hw --board nucleo-f401re \
128
+ thub run --type hw --label board:nucleo-f401re \
129
129
  --git-repo "$TESTS_REPO" --command ./ci/test.sh --user "Your Name" --wait
130
130
  ```
131
131
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@andrian.yablonskyy/thub-agent",
3
- "version": "1.1.2",
3
+ "version": "1.1.3",
4
4
  "description": "TestHub Agent CLI — the single entry point CI/CD and developers use to submit and follow test jobs",
5
5
  "bin": {
6
6
  "thub": "./src/cli.js"
package/src/cli.js CHANGED
@@ -134,12 +134,27 @@ function fail(err){
134
134
  process.exit(err.status && Number.isInteger(err.status) && err.status < 100 ? err.status : EXIT_CODES.USAGE);
135
135
  }
136
136
 
137
+ // --label: the labels a runner must all have for the job (§7.1).
138
+ // Checked here against the Coordinator's rule, so a typo fails before the
139
+ // job is sent.
140
+ const LABEL_RE = /^[^\s,;]{1,64}$/;
141
+ function requiredLabels(opts){
142
+ const labels = opts.label,
143
+ bad = labels.filter((l) => !LABEL_RE.test(l));
144
+ if (bad.length){
145
+ const err = new Error(`Invalid label: ${bad.join(', ')} — 1–64 characters, no spaces, commas or semicolons`);
146
+ err.status = EXIT_CODES.USAGE;
147
+ throw err;
148
+ }
149
+ return [...new Set(labels)];
150
+ }
151
+
137
152
  program
138
153
  .command('run')
139
154
  .description('Submit a test job and follow its log')
140
155
  .requiredOption('--type <hw|sw>', 'Required resource type')
141
- .option('--board <name>', 'Shorthand for --label board:<name>')
142
- .option('--label <label>', 'Required label the resource must have (repeatable)', collectRepeatable, [])
156
+ .option('--label <label>', 'A label the runner must have (repeatable; the job runs only on a runner with all of them). ' +
157
+ '1–64 characters, no spaces, commas or semicolons', collectRepeatable, [])
143
158
  .option(
144
159
  '--client <nameOrId>',
145
160
  'Run on this specific Client (resource name or id) only; the job waits in that Client\'s queue ' +
@@ -211,7 +226,7 @@ program
211
226
  try {
212
227
  const task = taskFromOptions(opts),
213
228
  c = client(),
214
- labels = [...(opts.board ? [`board:${opts.board}`] : []), ...opts.label],
229
+ labels = requiredLabels(opts),
215
230
  meta = Object.fromEntries(opts.meta.map((kv) => kv.split(/=(.*)/s).slice(0, 2))),
216
231
  user = resolveUser({ user: opts.user }),
217
232