@andrian.yablonskyy/thub-agent 1.1.1 → 1.1.2

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.
package/README.md CHANGED
@@ -14,7 +14,7 @@ npx -y @andrian.yablonskyy/thub-agent run --type sw --download-file "$IMAGE_URL"
14
14
 
15
15
  ## Configuration
16
16
 
17
- Read from flags (`--url`, `--key`), then environment (`THUB_URL`, `THUB_KEY`, `THUB_GROUP`, `THUB_USER`; the old names `--token`/`THUB_TOKEN` still work), then `~/.config/thub/agent.json`, then a bundled default. `url`/`token` are required by the time a command actually talks to the Coordinator; `group`/`user` are optional everywhere.
17
+ Read from flags (`--url`, `--key`), then environment (`THUB_URL`, `THUB_KEY`, `THUB_USER`; the old names `--token`/`THUB_TOKEN` still work), then `~/.config/thub/agent.json`, then a bundled default. `url`/`token` are required by the time a command actually talks to the Coordinator; `group`/`user` are optional everywhere.
18
18
 
19
19
  `npm install -g` creates `~/.config/thub/agent.json` for you (blank `url`/`token`, so nothing works until you set them) if it doesn't already exist — a re-install never overwrites it. Fill it in with `thub config set`:
20
20
 
@@ -24,7 +24,6 @@ thub config set key thk_... # your access key: from an admin (Users), or y
24
24
  thub whoami # jane (user) <jane@example.com>
25
25
  thub key show # its last characters, created, last used
26
26
  thub key rotate # a new key; the old one stops at once (saved here if it came from here)
27
- thub config set group 548ae4ae-... # optional default --group
28
27
  thub config set user "Your Name" # optional default --user
29
28
  ```
30
29
 
@@ -36,7 +35,7 @@ thub status <jobId> Show status; follow log if running, verdict, test
36
35
  thub cancel <jobId> Cancel a job
37
36
  thub resources List resources and their status
38
37
  thub jobs [--mine] [--state <s>] List recent jobs (a cli token: only its own; a ci token: all, or its own with --mine)
39
- thub config set <key> <value> Save coordinator URL / token / default group / default user locally
38
+ thub config set <key> <value> Save coordinator URL / key / default user locally
40
39
  thub check-update Compare this Agent with the latest published version
41
40
  thub self-update [--to <x.y.z>] Update this Agent with npm i -g
42
41
  thub --version
@@ -50,7 +49,6 @@ Key options for `thub run`. **On the Client** names the environment variable the
50
49
  |---|---|---|
51
50
  | `--type hw\|sw` | Required resource type. | `JOB_TYPE` |
52
51
  | `--board <name>` / `--label <l>` | Required labels (repeatable). | `JOB_BOARD`; `JOB_LABEL`, `JOB_LABEL_<n>` |
53
- | `--group <groupId>` | Restrict scheduling to resources that are members of this group. Falls back to `THUB_GROUP` / `thub config set group <id>`. | `JOB_GROUP` |
54
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` |
55
53
  | `--user <name>` | Free-text job owner — a label, not an identity. Falls back to `THUB_USER` / `thub config set user <name>`. | `JOB_USER` |
56
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` |
@@ -122,12 +120,7 @@ thub run --type sw --download-file https://does-not-exist.invalid/app.bin \
122
120
  --command ./ci/test.sh --dry-run --wait
123
121
  ```
124
122
 
125
- **Run on a specific resource group only:**
126
-
127
- ```bash
128
- thub run --type sw --git-repo "$TESTS_REPO" --command ./ci/test.sh \
129
- --group 548ae4ae-ac5b-401f-acaa-24bbe790e62d --wait
130
- ```
123
+ **Run in a resource group:** there's no `--group` option. An admin or maintainer gives your user (or a CI token) one group on the dashboard, and every job it submits runs only on that group's resources; `thub whoami` shows it.
131
124
 
132
125
  **Label a job with its owner** — purely informational, shows up on the dashboard, in `thub jobs`, and on the Client's own console:
133
126
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@andrian.yablonskyy/thub-agent",
3
- "version": "1.1.1",
3
+ "version": "1.1.2",
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"
@@ -12,7 +12,7 @@
12
12
  "lint:fix": "eslint . --fix"
13
13
  },
14
14
  "dependencies": {
15
- "@andrian.yablonskyy/thub-common": "^1.1.1",
15
+ "@andrian.yablonskyy/thub-common": "^1.1.2",
16
16
  "commander": "^13.1.0"
17
17
  },
18
18
  "devDependencies": {
package/src/cli.js CHANGED
@@ -21,7 +21,7 @@ const { Command, Option } = require('commander'),
21
21
  splitArgs,
22
22
  parseEnvList
23
23
  } = require('@andrian.yablonskyy/thub-common'),
24
- { resolveConnection, resolveGroup, resolveUser, writeConfigFile, readConfigFile, CONFIG_PATH } = require('./config'),
24
+ { resolveConnection, resolveUser, writeConfigFile, readConfigFile, CONFIG_PATH } = require('./config'),
25
25
  { parseDurationSec } = require('./duration'),
26
26
  { followJob } = require('./streaming'),
27
27
  { applyRequestedUpdate, installAgent, version } = require('./self-update');
@@ -140,11 +140,6 @@ program
140
140
  .requiredOption('--type <hw|sw>', 'Required resource type')
141
141
  .option('--board <name>', 'Shorthand for --label board:<name>')
142
142
  .option('--label <label>', 'Required label the resource must have (repeatable)', collectRepeatable, [])
143
- .option(
144
- '--group <groupId>',
145
- 'Restrict scheduling to resources that are members of this group (§13.1). ' +
146
- 'Overrides THUB_GROUP / config file; leave unset for an unconstrained run.'
147
- )
148
143
  .option(
149
144
  '--client <nameOrId>',
150
145
  'Run on this specific Client (resource name or id) only; the job waits in that Client\'s queue ' +
@@ -218,11 +213,11 @@ program
218
213
  c = client(),
219
214
  labels = [...(opts.board ? [`board:${opts.board}`] : []), ...opts.label],
220
215
  meta = Object.fromEntries(opts.meta.map((kv) => kv.split(/=(.*)/s).slice(0, 2))),
221
- group = resolveGroup({ group: opts.group }),
222
216
  user = resolveUser({ user: opts.user }),
223
217
 
224
218
  spec = {
225
- target: { type: opts.type, labels, ...(group ? { group } : {}), ...(opts.client ? { client: opts.client } : {}) },
219
+ // No group: the Coordinator uses this key's, set on the dashboard (§13.1).
220
+ target: { type: opts.type, labels, ...(opts.client ? { client: opts.client } : {}) },
226
221
  ...task,
227
222
  timeoutSec: parseDurationSec(opts.timeout),
228
223
  ...(opts.priority !== undefined ? { priority: opts.priority } : {}),
@@ -375,13 +370,15 @@ function formatBytes(bytes){
375
370
  const config = program.command('config').description('Manage local Agent configuration');
376
371
  config
377
372
  .command('set')
378
- .argument('<name>', 'url | key | group | user')
373
+ .argument('<name>', 'url | key | user')
379
374
  .argument('<value>')
380
375
  .action((name, value) => {
381
376
  // `token` is the old name of `key`.
382
377
  const setting = name === 'token' ? 'key' : name;
383
- if (!['url', 'key', 'group', 'user'].includes(setting)){
384
- console.error('Error: the setting must be "url", "key", "group", or "user"');
378
+ if (!['url', 'key', 'user'].includes(setting)){
379
+ console.error(setting === 'group'
380
+ ? 'Error: a job\'s group is set on the dashboard now (Users / CI tokens), not in the Agent'
381
+ : 'Error: the setting must be "url", "key", or "user"');
385
382
  process.exit(EXIT_CODES.USAGE);
386
383
  }
387
384
  const { token: _old, ...current } = readConfigFile();
@@ -391,8 +388,10 @@ config
391
388
 
392
389
  // Who this access key belongs to (§10.3).
393
390
  function describeMe(me){
394
- const role = me.user?.role ? me.user.role.charAt(0).toUpperCase() + me.user.role.slice(1) : '';
395
- return me.user ? `${me.user.username} (${role})${me.user.email ? ` <${me.user.email}>` : ''}` : `CI token "${me.name}"`;
391
+ const role = me.user?.role ? me.user.role.charAt(0).toUpperCase() + me.user.role.slice(1) : '',
392
+ who = me.user ? `${me.user.username} (${role})${me.user.email ? ` <${me.user.email}>` : ''}` : `CI token "${me.name}"`;
393
+ // Older Coordinators don't say: then nothing about groups.
394
+ return me.group === undefined ? who : `${who}\nJobs run in: ${me.group ? `group ${me.group}` : 'any resource (no group)'}`;
396
395
  }
397
396
 
398
397
  program
package/src/config.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @file packages/agent/src/config.js
3
- * @description Agent config resolution: flags > env > config file > bundled default (url/token/group/user)
3
+ * @description Agent config resolution: flags > env > config file > bundled default (url/token/user)
4
4
  *
5
5
  * @author Andrian Yablonskyy
6
6
  * @copyright Copyright (c) 2026 Andrian Yablonskyy. All rights reserved.
@@ -65,16 +65,8 @@ function resolveConnection(flags = {}){
65
65
  return { url, token, keySource };
66
66
  }
67
67
 
68
- // Optional default for `--group` (§4.3/§7.1) — same flags > env > file
69
- // precedence as url/token, but unset is fine: a job just runs unconstrained
70
- // by group, same as if `groups` had never been used at all.
71
- function resolveGroup(flags = {}){
72
- const file = { ...readJsonFile(PACKAGE_DEFAULT_CONFIG_PATH), ...readConfigFile() };
73
- return flags.group || process.env.THUB_GROUP || file.group || undefined;
74
- }
75
-
76
- // Optional default for `--user` (§4.3/§7.1) — same flags > env > file
77
- // precedence as group. Purely a label (who submitted this job), not an
68
+ // Optional default for `--user` (§4.3/§7.1) — flags > env > file, like
69
+ // url/token. Purely a label (who submitted this job), not an
78
70
  // identity: unset is fine, and nothing on the Coordinator side enforces
79
71
  // or authenticates it.
80
72
  function resolveUser(flags = {}){
@@ -82,4 +74,4 @@ function resolveUser(flags = {}){
82
74
  return flags.user || process.env.THUB_USER || file.user || undefined;
83
75
  }
84
76
 
85
- module.exports = { CONFIG_PATH, readConfigFile, writeConfigFile, resolveConnection, resolveGroup, resolveUser };
77
+ module.exports = { CONFIG_PATH, readConfigFile, writeConfigFile, resolveConnection, resolveUser };