@andrian.yablonskyy/thub-coordinator 1.1.12 → 1.1.13

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.
@@ -14,7 +14,7 @@
14
14
  strong Install a Client
15
15
  | on each lab machine, with the same join key (#[a(href="#client-setup") Client setup]):
16
16
  +code('Lab machine (Ubuntu 26.04)').
17
- sudo apt install -y nodejs npm docker.io # + stlink-tools openocd for HW
17
+ sudo apt install -y nodejs npm # + your jobs' tools: stlink-tools openocd, git, docker.io…
18
18
  sudo npm i -g @andrian.yablonskyy/thub-client
19
19
  nano ~/.config/thub/client.json # coordinatorUrl, type, joinKey
20
20
  sudo systemctl enable --now thub-client@client
@@ -8,7 +8,9 @@
8
8
  ['Name already in use (`409`)', 'Another live Client holds that name. Rename one of them in its config or from the runner card. A name held by an `OUT_OF_SERVICE` runner is reclaimed automatically.'],
9
9
  ['The job is rejected with `422`', 'No registered Client can ever match its type, labels, group or client. Compare `thub resources` with your `--type` and `--label`s; your group (set on the dashboard, see `thub whoami`) must have a Client of that kind.'],
10
10
  ['The job stays `QUEUED`', 'Matching Clients are all `BUSY`, locked (`local`), in `MAINTENANCE` or offline, or the job is pinned with `--client`. It times out after `--timeout`.'],
11
- ['`ERROR` during prepare', 'The clone, download or DUT image pull failed; the job log names the reason. For git, check the Client user\'s keys and `known_hosts` (`ssh -T git@<host>` as that user). For images, check the Client user\'s `docker login`.'],
11
+ ['`ERROR` during prepare', 'A download failed; the job log names the URL and the reason.'],
12
+ ['A git clone or docker pull in the command fails', 'They run in your `--command`, with the credentials you pass as `--env` (see Using git / Using Docker). `git` or `docker` must be installed on that Client host; the Client itself needs neither. Try the command with `--dry-run` to see its environment.'],
13
+ ['`--git-repo` / `--docker-image`: unknown option, or the job is refused', 'They were removed: clone the repository and run containers in `--command`, passing tokens with `--env`. An older Agent that still sends them is refused with that message; update it (`thub self-update`).'],
12
14
  ['Permission denied on `/dev/ttyUSB*` or `docker.sock`', 'Docker or the device groups were added after the Client was installed. Re-run `sudo npm i -g @andrian.yablonskyy/thub-client` so the unit gets the `dialout`/`plugdev`/`docker` groups, then restart.'],
13
15
  ['A configured device is shown as missing', 'Check the `devpath` with `udevadm info -a -n <dev>`, then `thub-client udev --print`; restart the Client to regenerate the udev rules.'],
14
16
  ['Job `LOST`', 'The Client missed 3 heartbeats (network, reboot, crash). With `requeueOnLost` the job is retried once on another Client.'],
@@ -11,8 +11,8 @@ block content
11
11
  { id: 'agent-setup', label: 'Agent setup' },
12
12
  { id: 'client-setup', label: 'Client setup' },
13
13
  { id: 'client-machines', label: 'Client machines (HW / SW)' },
14
- { id: 'docker', label: 'Docker registry' },
15
- { id: 'git', label: 'Git repositories' },
14
+ { id: 'docker', label: 'Using Docker' },
15
+ { id: 'git', label: 'Using git' },
16
16
  { id: 'agent-cli', label: 'Agent CLI reference' },
17
17
  { id: 'env', label: 'Environment variables' },
18
18
  { id: 'ci', label: 'CI/CD (GitHub Actions)' },
package/views/index.pug CHANGED
@@ -49,6 +49,7 @@ block scripts
49
49
  script(src="/js/resource-card.js")
50
50
  script(src="/js/remove-resource.js")
51
51
  script(src="/js/client-config.js")
52
+ script(src="/js/tag-picker.js")
52
53
  script(src="/js/usb-scan.js")
53
54
  script(src="/js/usb-parse.js")
54
55
  script(src="/js/usb-import.js")
@@ -183,19 +183,35 @@ mixin groupsPane(r, returnTo, groupsById)
183
183
  data-confirm-tone="primary"
184
184
  )
185
185
  input(type="hidden" name="returnTo" value=returnTo)
186
- fieldset(disabled=!canEdit || r.config_support !== 'file')
187
- .list-group.mb-2
188
- each g in all
189
- label.list-group-item.d-flex.gap-2.align-items-start
190
- input.form-check-input.flex-shrink-0.mt-1(type="checkbox" name="groups" value=g.id checked=r.group_ids.includes(g.id))
191
- span
192
- span.fw-medium= g.name
193
- if g.comment
194
- span.small.text-body-secondary= ` — ${g.comment}`
195
- each id in unknown
196
- label.list-group-item.d-flex.gap-2.align-items-start
197
- input.form-check-input.flex-shrink-0.mt-1(type="checkbox" name="groups" value=id checked)
198
- span.text-body-secondary (a deleted group)
186
+ - const editable = canEdit && r.config_support === 'file'
187
+ fieldset(disabled=!editable)
188
+ //- Chips for its groups, a search box to add more (public/js/tag-picker.js):
189
+ //- each chip carries its hidden `groups` input; ✕ removes it.
190
+ .thub-tags.mb-2(data-tag-picker data-tag-name="groups" data-options=JSON.stringify(all.map((g) => ({ value: g.id, label: g.name, hint: g.comment || '' }))))
191
+ .thub-tags-box.form-control(data-tag-box)
192
+ each id in r.group_ids
193
+ span.thub-tag(data-tag=id)
194
+ span= groupsById[id] ? groupsById[id].name : '(a deleted group)'
195
+ input(type="hidden" name="groups" value=id)
196
+ if editable
197
+ button.thub-tag-remove(type="button" data-tag-remove aria-label=`Remove ${groupsById[id] ? groupsById[id].name : 'deleted group'}`)
198
+ i.bi.bi-x
199
+ if editable
200
+ input.thub-tags-input(
201
+ type="text"
202
+ data-tag-input
203
+ placeholder="Add a group…"
204
+ aria-label=`Add a group to ${r.name}`
205
+ role="combobox"
206
+ aria-autocomplete="list"
207
+ aria-expanded="false"
208
+ aria-controls=`${p}-groups-menu`
209
+ autocomplete="off"
210
+ spellcheck="false"
211
+ )
212
+ ul.dropdown-menu.thub-tags-menu(id=`${p}-groups-menu` role="listbox" data-tag-menu)
213
+ if !r.group_ids.length && !editable
214
+ span.small.text-body-secondary none
199
215
  .form-text An agent given a group (on Users or CI tokens) runs its jobs only on Clients in it; an agent without one, on any Client.
200
216
  if canEdit && r.config_support === 'file'
201
217
  .d-flex.justify-content-end.mt-3
@@ -135,12 +135,12 @@ mixin capDevice(d, detail)
135
135
  ) missing
136
136
 
137
137
  //- What the Client reported it can drive at registration (HW: udev
138
- //- devices; SW: nothing of its own — it runs each job's DUT image).
138
+ //- devices; SW: nothing of its own — a job's command brings what it runs).
139
139
  mixin capabilitiesList(caps)
140
140
  if !caps
141
141
  span.text-body-secondary —
142
142
  else if caps.sw
143
- span.text-body-secondary Runs each job's own DUT image (--docker-image), 2 CPUs / 2 GB
143
+ span.text-body-secondary Runs each job's command — nothing of its own to drive
144
144
  else if caps.hw
145
145
  - const kinds = [['stlinks', 'ST-Link'], ['uarts', 'UART'], ['usbs', 'USB']]
146
146
  - const empty = kinds.every(([k]) => !(caps.hw[k] || []).length)
@@ -67,6 +67,7 @@ block scripts
67
67
  script(src="/js/resource-card.js")
68
68
  script(src="/js/remove-resource.js")
69
69
  script(src="/js/client-config.js")
70
+ script(src="/js/tag-picker.js")
70
71
  script(src="/js/usb-scan.js")
71
72
  script(src="/js/usb-parse.js")
72
73
  script(src="/js/usb-import.js")