Compare commits

..

311 Commits

Author SHA1 Message Date
357866e345 Example on how to test with mocks and stubs
Change-type: patch
2024-09-10 19:11:01 -03:00
629ac9e5e9 Add commands for exporting and importing app/fleet releases.
Change-type: minor
Signed-off-by: Carlo Miguel F. Cruz <carloc@balena.io>
2024-09-10 21:57:06 +08:00
2f03b24bcf v19.0.3 2024-09-05 12:34:15 +00:00
233ee990f9 Merge pull request #2823 from balena-io/reduce-require-usage
Reduce usage of not necessary CJS require()
2024-09-05 09:33:07 -03:00
facc66e9f9 Reduce use of CJS require() on automation files
Change-type: patch
2024-09-04 14:47:18 -03:00
6efd24489f Remove the use of CJS require() on test files
Change-type: patch
2024-09-04 14:33:52 -03:00
0339160a0b Remove not necessary 'import = require' syntax for js-yaml
Change-type: patch
2024-09-04 13:55:41 -03:00
0591f5edbd v19.0.2 2024-09-03 14:56:29 +00:00
c30dd323f1 Merge pull request #2821 from balena-io/bump-dev-deps
update dev dependencies
2024-09-03 14:55:19 +00:00
1640bd6457 Update devDependency patch-package to v8.0.0
Change-type: patch
2024-09-03 11:22:45 -03:00
da2ffde483 Update devDependency mkdirp to v3.0.1
Change-type: patch
2024-09-03 10:58:36 -03:00
5c9e3ad8f6 Update devDependency fs-extra(to v11) and @types/fs-extra(to v11)
Change-type: patch
2024-09-03 10:58:36 -03:00
7515d4b710 Update devDependency @types/parse-link-header to v2.0.3
Change-type: patch
2024-09-03 10:58:30 -03:00
fae5af6b75 Remove unused devDependency @types/nock
Change-type: patch
2024-09-03 10:47:23 -03:00
45aa1adacb Update devDependency klaw(to v4) and @types/klaw(to v3.0.6)
Change-type: patch
2024-09-03 10:47:23 -03:00
b34ea14413 Update husky to v9.1.5
Change-type: patch
2024-09-03 10:47:19 -03:00
90eae06017 Update devDependency @types/jsonwebtoken to v9.0.6
Change-type: patch
2024-09-03 09:35:25 -03:00
41da8f6f6f Update devDependency archiver(to v7) and @types/archiver(to v6)
Change-type: patch
2024-09-03 09:33:07 -03:00
8d706a7d81 Removes unused devDependency @types/net-keepalive
Change-type: patch
2024-09-03 09:30:33 -03:00
d67952024c Update devDependency rewire(to v7) and @types/rewire(to v2.5.30)
Change-type: patch
2024-09-03 09:28:32 -03:00
8895fc485c Update devDependency sinon(to v18) and @types/sinon(to v17)
Change-type: patch
2024-09-03 09:20:41 -03:00
c2dbcaaaf4 v19.0.1 2024-09-02 13:21:58 +00:00
52cb951e49 Merge pull request #2788 from balena-io/bump-oclif-core-v4
Bump @oclif/core from 3.27.0 to 4.0.18
2024-09-02 13:20:59 +00:00
2a357a438f Bump @oclif/core from 3.27.0 to 4.0.18
Change-type: patch
2024-09-02 09:24:08 -03:00
a9a202281d v19.0.0 2024-08-22 17:43:34 +00:00
b74979fb9e Merge pull request #2816 from balena-io/v19
v19
2024-08-22 14:42:42 -03:00
4760866c77 Update all references of lib to src
Change-type: patch
2024-08-22 13:03:37 -03:00
2b044348e0 Rename the lib folder to src
Change-type: major
2024-08-22 12:55:48 -03:00
c9fa10b9c6 Update @balena/compose to 4.0.1
Update @balena/compose from 3.2.1 to 4.0.1

Change-type: major
2024-08-22 07:44:09 -03:00
63674c8201 Use standard visuals table component for fleet/s
This effectively removes the ability to filter/sort/customize the output table.
The cli cannot properly handle this operations on all models and this one was inconsistent.
For now we recommend that users that require parsing the CLI output use the output json format and do any kind of necessary parsing on it.

Change-type: major
2024-08-07 13:14:24 -03:00
a08ac447a3 v18.2.34 2024-07-29 11:08:38 +00:00
12a338fb21 Merge pull request #2817 from balena-io/ab77/patch-1
Switch to self-hosted
2024-07-29 11:07:51 +00:00
1d70e6b4b4 Run npm dedupe commands
Change-type: patch
Signed-off-by: Kyle Harding <kyle@balena.io>
2024-07-29 07:25:13 -03:00
d3458379e6 Switch to self-hosted
change-type: patch
2024-07-23 11:10:09 -07:00
544f615ca0 v18.2.33 2024-07-17 07:46:28 +00:00
245c51d974 Merge pull request #2814 from balena-io/improve-scan-reliability
Improve discover balena os across different networks
2024-07-17 04:42:50 -03:00
03f0f11f8b Improve discover balena os across different networks
This is an improvement over the scan, join and leave commands removing flakiness when searching over different networks. In short, instead of leaving bonjour to search across all interfaces, we forcebly conduct a search on each interface, this requires mDNS binding any ipv4 interface (0.0.0.0), otherwise it would bind over the interface itself, which is not desired as it causes services to only be able to receive information over that interface, see [mafintosh/multicast-dns#53](https://github.com/mafintosh/multicast-dns/issues/53). This targeted approach enhances the reliability and accuracy of network searches, reducing instances of missed connections or network errors typically caused by flakiness when relying on bonjour's default behavior.

Change-type: patch
2024-07-16 19:01:53 -03:00
2c0c1f8fd1 v18.2.32 2024-07-16 13:10:07 +00:00
d4d7fce2c1 Merge pull request #2815 from balena-io/remove-unused-code
Remove unused code
2024-07-16 13:09:15 +00:00
0f23318367 Remove unused code
Change-type: patch
2024-07-16 07:46:18 -03:00
003d537433 v18.2.31 2024-07-15 21:17:44 +00:00
46d3497663 Merge pull request #2798 from balena-io/balena-compose-sdk-pine-instance
deploy: Use the sdk's pine instance with balena-compose
2024-07-16 00:16:55 +03:00
a39a772c9e Deduplicate dependencies 2024-07-15 18:51:16 +03:00
efa0d67f0a deploy: Use the sdk's pine instance with balena-compose
Change-type: patch
2024-07-15 18:42:51 +03:00
232b9678bc Update balena-sdk to 19.7.3
Update balena-sdk from 19.7.2 to 19.7.3

Change-type: patch
2024-07-15 16:09:51 +03:00
a8ce14b0e8 v18.2.30 2024-07-15 11:30:43 +00:00
838a36758a Merge pull request #2812 from balena-io/test-omit-escaped-chars
Omit unicode control character escapes from test logs
2024-07-15 14:29:46 +03:00
4e101e2fd9 Omit unicode control character escapes from test logs
Change-type: patch
2024-07-13 18:07:04 +03:00
9f9fd97795 Deduplicate dependencies 2024-07-13 17:44:04 +03:00
1b36dc84fc v18.2.29 2024-07-12 14:55:02 +00:00
5d6ee707ff Merge pull request #2801 from balena-io/bump-balena-preload
Update balena-preload from 15.0.5 to 15.0.6
2024-07-12 14:54:14 +00:00
3c64e13fb3 Update balena-preload from 15.0.5 to 15.0.6
Change-type: patch
2024-07-12 11:30:36 -03:00
7e41fda8d4 v18.2.28 2024-07-12 13:29:24 +00:00
5df316e9cb Merge pull request #2807 from balena-io/update-sdk-19-7-2
Update balena-sdk to 19.7.2
2024-07-12 16:28:38 +03:00
79fcd95491 Downgrade pinejs-client-request to 7.4.2 to unblock the sdk update
Change-type: patch
2024-07-12 16:02:35 +03:00
33199acbe8 Update balena-sdk to 19.7.2
Update balena-sdk from 19.5.5 to 19.7.2

Change-type: patch
2024-07-12 15:55:42 +03:00
4633c2456d v18.2.27 2024-07-12 12:45:19 +00:00
f8bc081228 Merge pull request #2804 from balena-io/update-sdk
Update balena-sdk to 19.5.5
2024-07-12 12:44:19 +00:00
1702f8ba59 Update balena-sdk to 19.5.5
Update balena-sdk from 19.4.0 to 19.5.5

Change-type: patch
2024-07-12 15:08:26 +03:00
60b0c7e346 v18.2.26 2024-07-12 12:03:32 +00:00
e95ef8b3b4 Merge pull request #2803 from balena-io/fix-dependencies
Fix dependencies
2024-07-12 12:02:39 +00:00
1bc0f7447f Drop unused dependencies
Change-type: patch
2024-07-12 08:38:49 -03:00
f65215e144 Move dependencies that should be dev only as devDependencies
Change-type: patch
2024-07-12 07:15:37 -03:00
97abc5cf1c v18.2.25 2024-07-11 10:54:49 +00:00
e64a09d2f4 Merge pull request #2800 from balena-io/bump-oclif-v4
Bump oclif v4
2024-07-11 07:54:00 -03:00
b1073ca549 Fix complete generation intermitency
Change-type: patch
2024-07-10 21:22:20 -03:00
e659e3577a Bump oclif to v4
Change-type: patch
2024-07-10 19:07:54 -03:00
f7233c5d42 v18.2.24 2024-07-10 22:06:20 +00:00
4ae2ff1740 Merge pull request #2799 from balena-io/overrides-inline-source-dev-dependency-version
Update Dependencies
2024-07-10 22:05:21 +00:00
19a60bb0ab Update mocha from 8.4.0 to 10.6.0
Change-type: patch
2024-07-10 18:25:37 -03:00
d1a6f7560c Override inline-source-cli with non-vulnerable dependency
Change-type: patch
2024-07-10 18:20:05 -03:00
4619ce7daa v18.2.23 2024-07-10 21:05:55 +00:00
7624240d5e Merge pull request #2796 from balena-io/replace-discoverable-service-for-std-bonjour-service
Replace resin-discoverable-services with bonjour-service
2024-07-10 21:04:58 +00:00
7273656d07 Replace resin-discoverable-services with bonjour-service
Instead of using the more generic resin-discoverable-services lib which is unmantained
and currently has several vulnerabilities and forks for fixing issues (that were later on fixed upstream)
we directly talk with mDNS using standard (and currently mantained) bonjour-service.

Change-type: patch
2024-07-10 16:06:19 -03:00
00bd4d5415 v18.2.22 2024-07-10 16:48:09 +00:00
c2d3c9fc71 Merge pull request #2797 from balena-io/remove-unused-depedency
Remove unused dependency minimatch
2024-07-10 16:46:45 +00:00
1749937373 Remove unused dependency minimatch
Change-type: patch
2024-07-10 12:54:52 -03:00
bcb7fb8902 v18.2.21 2024-07-09 15:10:38 +00:00
81e9601d6b Merge pull request #2794 from balena-io/bump-resin-discoverable-services
Bump resin-discoverable-services from 2.0.4 to 2.0.5
2024-07-09 15:09:34 +00:00
6c89ba4b22 Bump resin-discoverable-services from 2.0.4 to 2.0.5
Change-type: patch
2024-07-09 11:43:45 -03:00
57d3d6d537 v18.2.20 2024-07-05 21:12:48 +00:00
6330574c01 Merge pull request #2791 from balena-io/run-audit-fix
Audit fix dependencies
2024-07-05 18:11:52 -03:00
b6d1afac2d Audit fix dependencies
Change-type: patch
2024-07-05 17:41:14 -03:00
f2d0da0837 v18.2.19 2024-07-05 13:37:55 +00:00
068cd887c8 Merge pull request #2790 from balena-io/unneeded-publish-release
Remove unused package `publish-release`
2024-07-05 13:36:53 +00:00
93e597a596 Remove unused package publish-release
Change-type: patch
2024-07-05 08:56:51 -04:00
5b1d6a3190 v18.2.18 2024-07-04 21:56:19 +00:00
dba102f347 Merge pull request #2786 from balena-io/renovate/actions-setup-node-4.x
Update actions/setup-node action to v4
2024-07-04 18:55:25 -03:00
c30a1dc1ed Update actions/setup-node action to v4
Update actions/setup-node from 3 to 4

Change-type: patch
2024-07-02 13:47:56 +00:00
78368c8a51 v18.2.17 2024-07-02 13:20:43 +00:00
d7250ccc4e Merge pull request #2785 from balena-io/renovate/etcher-sdk
Update dependency etcher-sdk to v9.1.0
2024-07-02 13:19:44 +00:00
2d47eb53cd Update dependency etcher-sdk to v9.1.0
Update etcher-sdk from 9.0.11 to 9.1.0

Change-type: patch
2024-07-02 12:53:24 +00:00
b5fc97bdf9 v18.2.16 2024-07-02 12:14:25 +00:00
3472df2c04 Merge pull request #2783 from balena-io/renovate/patch-etcher-sdk
Update dependency etcher-sdk to v9.0.11
2024-07-02 12:13:18 +00:00
6b5657625a Update dependency etcher-sdk to v9.0.11
Update etcher-sdk from 9.0.8 to 9.0.11

Change-type: patch
2024-07-02 11:47:56 +00:00
dad6b23202 v18.2.15 2024-07-02 11:11:04 +00:00
6b59c06978 Merge pull request #2784 from balena-io/renovate/patch-event-stream
Update dependency event-stream to v3.3.5
2024-07-02 11:10:09 +00:00
b518067058 Update dependency event-stream to v3.3.5
Update event-stream from 3.3.4 to 3.3.5

Change-type: patch
2024-07-02 10:48:33 +00:00
bd4bdb805f v18.2.14 2024-07-02 10:14:47 +00:00
32e59eccc5 Merge pull request #2771 from balena-io/renovate/npm-jsonwebtoken-vulnerability
Update dependency jsonwebtoken to v9 [SECURITY]
2024-07-02 07:13:48 -03:00
f05e49915d Update dependency jsonwebtoken to v9 [SECURITY]
Update jsonwebtoken from 8.5.1 to 9.0.0

Change-type: patch
2024-07-02 09:48:15 +00:00
92146429c4 v18.2.13 2024-07-02 09:14:07 +00:00
40f5214317 Merge pull request #2780 from balena-io/renovate/patch-prettyjson
Update dependency @types/prettyjson to ^0.0.33
2024-07-02 09:13:04 +00:00
14e1255b5f Update dependency @types/prettyjson to ^0.0.33
Update @types/prettyjson from 0.0.30 to 0.0.33

Change-type: patch
2024-07-02 08:48:40 +00:00
15e91e95b4 v18.2.12 2024-07-02 07:50:17 +00:00
1814fe7581 Merge pull request #2782 from balena-io/npm-dd
Deduplicate dependencies
2024-07-02 10:49:11 +03:00
7325e8d9d5 Deduplicate dependencies
Change-type: patch
2024-07-01 22:51:28 +03:00
5358f92590 v18.2.11 2024-07-01 17:52:46 +00:00
fe6a7cfdba Merge pull request #2778 from balena-io/renovate/patch-fast-levenshtein
Update dependency @types/fast-levenshtein to v0.0.4
2024-07-01 17:51:45 +00:00
a29bd8d0ef Update dependency @types/fast-levenshtein to v0.0.4
Update @types/fast-levenshtein from 0.0.1 to 0.0.4

Change-type: patch
2024-06-21 20:48:02 +00:00
049e1da53e v18.2.10 2024-06-21 20:12:54 +00:00
2c0b4072ae Merge pull request #2776 from balena-io/renovate/actions-download-artifact-4.1.x
Update actions/download-artifact action to v4.1.7
2024-06-21 20:12:05 +00:00
15c0c32a01 Update actions/download-artifact action to v4.1.7
Update actions/download-artifact from 4.1.0 to 4.1.7

Change-type: patch
2024-06-21 19:48:21 +00:00
8f2c7f9dbf v18.2.9 2024-06-21 19:13:44 +00:00
90982256c7 Merge pull request #2773 from balena-io/renovate/actions-setup-python-digest
Update actions/setup-python digest to 65d7f2d
2024-06-21 19:12:42 +00:00
73220206a2 Update actions/setup-python digest to 65d7f2d
Update actions/setup-python

Change-type: patch
2024-06-21 18:48:07 +00:00
8b453aae89 v18.2.8 2024-06-21 18:13:51 +00:00
d85d5933fb Merge pull request #2775 from balena-io/renovate/actions-upload-artifact-digest
Update actions/upload-artifact digest to 6546280
2024-06-21 18:12:44 +00:00
2cd455ff81 Update actions/upload-artifact digest to 6546280
Update actions/upload-artifact

Change-type: patch
2024-06-21 17:49:06 +00:00
066cbaf35f v18.2.7 2024-06-21 17:16:21 +00:00
17fa888fea Merge pull request #2772 from balena-io/renovate/pin-dependencies
Pin dependencies
2024-06-21 17:15:25 +00:00
f50287873a Pin dependencies
Update actions/setup-node

Change-type: patch
2024-06-21 16:47:51 +00:00
edff14fa72 v18.2.6 2024-06-21 15:23:25 +00:00
9de753d9d3 Merge pull request #2770 from balena-io/bump-oclif-core
Update @oclif/core from 3.26.9 to 3.27.0
2024-06-21 15:22:19 +00:00
75d2d7d375 Update @oclif/core from 3.26.9 to 3.27.0
Change-type: patch
2024-06-21 09:49:38 -03:00
d9b193acc1 v18.2.5 2024-06-21 12:11:21 +00:00
2e42999642 Merge pull request #2769 from balena-io/bump-ts
Update TypeScript to 5.5.2
2024-06-21 12:10:18 +00:00
5a3f0ea453 Limit @oclif/core to ~3.26 so that npm dedupe doesn't auto-bump it
Change-type: patch
2024-06-21 01:37:00 +03:00
e1cd30060c Deduplicate dependencies 2024-06-21 01:31:53 +03:00
7959e23cd3 Update TypeScript to 5.5.2
Change-type: patch
2024-06-21 00:18:36 +03:00
9c4d788d6d v18.2.4 2024-05-17 12:04:11 +00:00
181f5a6a2f Merge pull request #2767 from balena-io/aethernet-patch-1
patch: fix outdated doc for "os configure"
2024-05-17 12:03:17 +00:00
163dcf596e patch: fix outdated doc for "os configure"
There were an outdated warning for `os configure` on windows.
The command actually works fine on windows.

see: https://balena.zulipchat.com/#narrow/stream/403752-channel.2Fsupport-help/topic/Cytiva.20image.20downloads/near/438786503
2024-05-17 13:39:22 +02:00
1724187466 v18.2.3 2024-05-15 13:32:53 +00:00
b27dcdd582 Merge pull request #2765 from balena-io/dfunckt-patch-1
Pluralize command categories in docs
2024-05-15 13:31:57 +00:00
c28039a3f2 Fix exitCode type 2024-05-15 16:01:38 +03:00
233bc705de Pluralize command categories in docs
Pluralize command categories, eg. "Device" -> "Devices”.

Results in much fewer categories in our docs pages and we no longer have the somewhat silly separate singular and plural categories for commands such as `devices` and `device <command>`.

Change-type: patch
2024-05-15 15:49:57 +03:00
71518678e1 v18.2.2 2024-04-30 13:57:49 +00:00
88a705c935 Merge pull request #2754 from balena-io/upgrade_dockerode
Upgrade dockerode and docker-modem dependencies
2024-04-30 13:56:52 +00:00
55d06aced2 Deduplicate npm dependencies
Signed-off-by: Ken Bannister <kb2ma@runbox.com>
2024-04-29 08:20:02 -04:00
aa9a148c46 Upgrade dockerode and docker-modem dependencies
Includes test fixes due to an interface change in docker-modem.

Change-type: patch
Signed-off-by: Ken Bannister <kb2ma@runbox.com>
2024-04-29 07:56:53 -04:00
10ca5b4f59 v18.2.1 2024-04-23 12:08:57 +00:00
47e11d5f9b Merge pull request #2758 from balena-io/kyle/actuated
Use Actuated runners for Linux test and publish
2024-04-23 12:07:47 +00:00
6fb65bcf22 Re-run npm install and npm dedupe
Signed-off-by: Kyle Harding <kyle@balena.io>
2024-04-22 17:56:20 +03:00
954de13b10 Use Actuated runners for Linux test and publish
Change-type: patch
Signed-off-by: Kyle Harding <kyle@balena.io>
2024-04-19 15:27:38 -04:00
f81a27e931 v18.2.0 2024-04-17 16:13:12 +00:00
e8815d0275 Merge pull request #2756 from balena-io/build-optional-arch
build: Auto-resolve the cpu arch when the --deviceType is provided
2024-04-17 19:12:11 +03:00
766e6d4e5e build: Auto-resolve the cpu arch when the --deviceType is provided
Change-type: minor
2024-04-17 18:10:30 +03:00
7b46f65a01 v18.1.10 2024-04-16 14:17:07 +00:00
db8df0ac35 Merge pull request #2755 from balena-io/node-20-6
Mark node 20.6.0 as the minimum working version
2024-04-16 17:16:00 +03:00
7c7f46fe2b Deduplicate dependencies 2024-04-16 16:46:25 +03:00
b29aae1821 Mark node 20.6.0 as the minimum working version
Change-type: patch
2024-04-16 15:42:41 +03:00
0b10701015 v18.1.9 2024-04-10 15:24:31 +00:00
1dbe08d7e0 Merge pull request #2748 from balena-io/kyle/renovate-npm-dedupe
Enable npm dedupe as part of Renovate postUpdateOptions
2024-04-10 18:23:33 +03:00
d01461ff3e Deduplicate dependencies 2024-04-10 17:39:18 +03:00
2a970478bd Enable npm dedupe as part of Renovate postUpdateOptions
See: https://docs.renovatebot.com/configuration-options/#postupdateoptions
Change-type: patch
Signed-off-by: Kyle Harding <kyle@balena.io>
2024-04-10 10:03:01 -04:00
ffd44d3fec v18.1.8 2024-04-09 17:29:48 +00:00
df51f87fbc Merge pull request #2752 from balena-io/shrinkwrap-v3
npm-shrinkwrap.json: Recreate with lockfileVersion 3
2024-04-09 20:28:45 +03:00
6178f34f88 Bump patch-package to 6.5.1
Change-type: patch
2024-04-09 19:25:17 +03:00
c5ecf692bb npm-shrinkwrap.json: Recreate with lockfileVersion 3
npm ci && \
  rm npm-shrinkwrap.json && \
  npm shrinkwrap

I confirmed that it generates the same
node_modules structure but cuts the
shrinkwrap file size by 43%.

Change-type: patch
See: https://docs.npmjs.com/cli/v9/configuring-npm/package-lock-json#lockfileversion
2024-04-09 19:14:11 +03:00
87f5f18721 v18.1.7 2024-04-09 16:03:36 +00:00
e33810b448 Merge pull request #2753 from balena-io/preload-drop-unused-deps
Update balena-preload to 15.0.5
2024-04-09 19:02:39 +03:00
3caf54aa16 Update balena-preload to 15.0.5
Update balena-preload from 15.0.4 to 15.0.5

Change-type: patch
2024-04-09 18:26:11 +03:00
9d3ee9eb49 v18.1.6 2024-04-09 15:04:42 +00:00
3dac94db70 Merge pull request #2751 from balena-io/drivelist-v12
Update dependencies to get node-addon-api >=7.0.0 to fix builds on node 20.12.0
2024-04-09 15:03:45 +00:00
04b4444fc2 Update expected build warning tests 2024-04-09 17:17:07 +03:00
98514cef09 Deduplicate dependencies 2024-04-09 17:17:07 +03:00
4811031172 Update @oclif/core to 3.26.2
Change-type: patch
2024-04-09 17:17:07 +03:00
be682c7426 Drop the keep-alive package in favor of node's setKeepAlive defaults
Since node 12.17.0 setKeepAlive also sets
TCP_KEEPCNT=10 (vs 5 that we had)
TCP_KEEPINTVL=1 (vs 5s that we had)

Change-type: patch
See: https://nodejs.org/docs/latest-v14.x/api/net.html#net_socket_setkeepalive_enable_initialdelay
See: https://github.com/balena-io/balena-cli/pull/1220
2024-04-09 17:17:07 +03:00
c6827ee51d Update balena-preload to v15.0.4
Change-type: patch
2024-04-09 17:17:07 +03:00
2cba3bbc22 Update resin-cli-form to v3
Change-type: patch
2024-04-09 17:17:07 +03:00
933eacf275 Update resin-cli-visuals to v2
Change-type: patch
2024-04-09 17:17:07 +03:00
e7869f4c6d Update balena-device-init to v7.0.1
Change-type: patch
2024-04-09 17:17:07 +03:00
1a246a9ba5 Update etcher-sdk to v9.0.8
Change-type: patch
2024-04-09 17:16:30 +03:00
e26895085d Mark bin/dev & bin/run as executable
Change-type: patch
2024-04-09 17:16:30 +03:00
71345a8cc1 v18.1.5 2024-03-14 15:52:40 +00:00
619f605eb2 Merge pull request #2747 from balena-io/move-claw-as-dev-dep
Move klaw library to dev dependency
2024-03-14 15:51:48 +00:00
bb4713ab9a Move klaw library to dev dependency
Change-type: patch
2024-03-14 11:41:10 -03:00
168bddf7db v18.1.4 2024-03-14 14:34:50 +00:00
24076e4f8d Merge pull request #2746 from balena-io/update-balena-lint
Update @balena/lint to 8.0.0
2024-03-14 14:33:48 +00:00
634ad156ce Update @balena/lint to 8.0.0
Change-type: patch
2024-03-14 10:00:52 -04:00
6ebeb97917 v18.1.3 2024-03-14 12:57:24 +00:00
cb444998cd Merge pull request #2742 from balena-io/adds-runjs-for-plugin-compatibility
Use standard oclif run.js & dev.js
2024-03-14 09:56:33 -03:00
742c015f21 Use standard oclif run.js & dev.js
Change-type: patch
2024-03-14 09:21:11 -03:00
556e50c87c v18.1.2 2024-03-13 13:49:11 +00:00
3294f78b00 Merge pull request #2743 from balena-io/moves-signing-to-pretarball
Move macos binary signing to oclif pretarball lifecycle
2024-03-13 10:48:14 -03:00
7f11805a7f Move macos binary signing to oclif pretarball lifecycle
Change-type: patch
2024-03-13 09:40:30 -03:00
42dd732f68 v18.1.1 2024-03-12 17:39:15 +00:00
aed50480c3 Merge pull request #2745 from balena-io/removes-tmp-workaround-for-windows-runners
Remove patching tmp for windows runners
2024-03-12 17:38:18 +00:00
6515d6ae10 Remove patching tmp for windows runners
See: https://github.com/balena-io/balena-cli/pull/1298/files#r297236577
Change-type: patch
2024-03-12 12:02:32 -03:00
7903c82821 v18.1.0 2024-03-12 14:21:30 +00:00
eee8a0ecca Merge pull request #2744 from balena-io/adds-arm64-macos-builds
Add support for macos arm64 builds
2024-03-12 11:20:36 -03:00
38a2817587 Add support for macos arm64 builds
Change-type: minor
2024-03-11 20:49:29 -03:00
2bd0641d5f v18.0.4 2024-03-11 22:19:10 +00:00
122a763f82 Merge pull request #2739 from balena-io/update-dependencies
Update dependencies
2024-03-11 22:18:03 +00:00
756f6b328b Update dependencies
Change-type: patch
2024-03-11 16:35:32 -03:00
eb9db6f7b4 v18.0.3 2024-03-11 14:25:51 +00:00
6f9e5a697c Merge pull request #2740 from balena-io/removes-signing-patches
Removes signing patches
2024-03-11 14:24:40 +00:00
f9f41eef4b Removes signing patches
Change-type: patch
2024-03-11 10:53:54 -03:00
5371fea588 v18.0.2 2024-03-07 19:40:27 +00:00
bacb55a1ea Merge pull request #2735 from balena-io/removes-patches-windows
Removes no longer needed patch
2024-03-07 19:39:38 +00:00
ecfd4a260e Remove no longer needed windows oclif patches
Change-type: patch
2024-03-07 15:51:00 -03:00
1525822239 v18.0.1 2024-03-07 16:30:17 +00:00
1614d9b2c8 Merge pull request #2733 from balena-io/fix-windows-signing
Fix windows signing
2024-03-07 16:29:07 +00:00
2e061845ae Fix windows signing
Change-type: patch
2024-03-07 13:01:08 -03:00
9e4dd3fce2 v18.0.0 2024-02-06 12:19:41 +00:00
b2590136fc Merge pull request #2720 from balena-io/bump-node-20
Update to Node 20
2024-02-06 12:18:34 +00:00
bf5e61a61c Update to Node 20
Change-type: major
2024-02-05 18:29:02 -03:00
f550d0c596 v17.5.1 2024-01-31 01:05:23 +00:00
54302669b8 Merge pull request #2725 from balena-io/livepush-fix
Fix target state construction with livepush
2024-01-30 20:04:28 -05:00
a4a4e33d7b Dedupe dependencies 2024-01-30 11:17:21 -03:00
8d6a621bfb Fix target state construction with livepush
When constructing the target state after a reported change from livepush, the
handler function would not pass all build tasks to the function that
constructs the target state, causing a TypeError when trying to obtain
the target image name for each service. This updates the handler to pass
all build tasks, ensuring the information is available to construct the
target state.

Relates-to: #2724
Change-type: patch
2024-01-30 11:03:37 -03:00
4b2602676b v17.5.0 2024-01-23 15:52:54 +00:00
b0810c0f85 Merge pull request #2722 from balena-io/draft-hup
device os-update: Enable updates to pre-release versions of higher base semver
2024-01-23 17:51:54 +02:00
97a6013537 Deduplicate dependencies 2024-01-23 16:55:36 +02:00
1ba8db1459 os versions: Add the --include-draft option
Change-type: minor
2024-01-23 16:55:36 +02:00
cdada0aec8 device os-update: Add option for including pre-release versions in the list
Change-type: minor
2024-01-23 16:55:36 +02:00
1166533482 device os-update: Enable updates to pre-release versions of higher base semver
Change-type: minor
Depends-on: https://github.com/balena-io/balena-sdk/pull/1398
See: https://balena.fibery.io/Work/Task/cli-Enable-OS-Updates-to-pre-release-OS-versions-1751
2024-01-23 16:55:36 +02:00
01538728cd Update balena-sdk to 19.4.0
Update balena-sdk from 19.0.1 to 19.4.0

Change-type: minor
2024-01-23 16:55:36 +02:00
3a7f6d78b0 v17.4.12 2024-01-18 10:55:53 +00:00
dce48c90e9 Merge pull request #2719 from balena-io/revert_dockerode
Revert upgrade to dockerode to avoid regression
2024-01-18 05:54:22 -05:00
fe70d164c1 Deduplicate dependencies 2024-01-15 22:38:12 +00:00
09e2550b32 Regression described in GitHub Issue 2715; balena push hangs in
local mode.

Change-type: patch
Signed-off-by: Ken Bannister <kb2ma@runbox.com>
2024-01-15 22:05:05 +00:00
07854c3d42 v17.4.11 2024-01-05 23:01:11 +00:00
858a455501 Merge pull request #2717 from balena-io/update-oclif-patch
Mark the oclif package patch as a dev only one
2024-01-05 23:00:17 +00:00
4e5eb4bcee Exclude the oclif package patch from the published files
Change-type: patch
2024-01-06 00:25:56 +02:00
696bad3ed6 Update the @oclif/core patch
Change-type: patch
2024-01-06 00:25:34 +02:00
9a9d0f02ef Deduplicate dependencies 2024-01-06 00:25:34 +02:00
f46d00640b v17.4.10 2024-01-02 12:41:44 +00:00
e369bd3599 Merge pull request #2716 from balena-io/normalize-v-version-prefix
Normalize v prefixes in the --version parameter of all commands
2024-01-02 14:40:45 +02:00
75b29112a7 Deduplicate dependencies 2024-01-02 13:55:40 +02:00
b7b01ecd53 Normalize v prefixes in the --version parameter of all commands
Change-type: patch
2024-01-02 13:33:38 +02:00
801a25995c v17.4.9 2023-12-19 23:02:33 +00:00
8296dea78c Merge pull request #2713 from balena-io/fix-ci
Fix publishing artifacts to gh release
2023-12-19 23:01:35 +00:00
1da5a75c14 Fix publishing artifacts to gh release
Change-type: patch
2023-12-19 19:10:06 -03:00
166de57179 v17.4.8 2023-12-19 21:59:10 +00:00
85dece9e95 Merge pull request #2714 from balena-io/kyle/patch
Remove repo config from flowzone.yml
2023-12-19 21:58:24 +00:00
bfbc71215c Remove repo config from flowzone.yml
This functionality is being deprecated in Flowzone.

See: https://github.com/product-os/flowzone/pull/833

Change-type: patch
Signed-off-by: Kyle Harding <kyle@balena.io>
2023-12-19 15:20:04 -05:00
d243c14d74 v17.4.7 2023-12-19 14:26:31 +00:00
804eb27551 Merge pull request #2712 from balena-io/add-request-rerties-to-balena-deploy
deploy: Add rate-limiting aware retries for failed requests
2023-12-19 14:25:32 +00:00
4266dc6951 deploy: Add rate-limiting aware retries for failed requests
Change-type: patch
2023-12-19 01:16:42 +02:00
0ba3522584 Update dependencies
Update @balena/compose from 3.0.5 to 3.2.0

Also updates pinejs-client-request to support
using the Retry-After header and dockerode
to 3.3.5 to be aligned with @balena/compose.

Change-type: patch
2023-12-19 01:16:42 +02:00
19b0e9489d Deduplicate node modules 2023-12-19 01:16:42 +02:00
d9fed9c34c v17.4.6 2023-12-08 15:55:53 +00:00
81ee9f397f Merge pull request #2711 from balena-io/bump-oclif-core
Bump oclif core & use default missing flag handler
2023-12-08 15:54:47 +00:00
b9722c6796 Bump oclif core & use default missing flag handler
Change-type: patch
2023-12-08 12:06:54 -03:00
29ade0f696 v17.4.5 2023-12-04 14:08:31 +00:00
d5ae612513 Merge pull request #2707 from balena-io/bump-ts
Update TypeScript to 5.3.2
2023-12-04 14:07:30 +00:00
65ba63d1a8 Stop testing dependency deduplication on the custom test runners
That's since we already run that test as part of
flowzone's default "Test npm (18.x)", and the
custom tests are using the latest node & npm
version of the selected major.

Change-type: patch
2023-12-04 15:39:10 +02:00
f5ffa7d84f Temporarily pin oclif-core to ~3.11.0 to deduplicate the dependencies
Change-type: patch
2023-12-04 15:36:43 +02:00
dac3ace61d Update TypeScript to 5.3.2
Change-type: patch
2023-11-30 00:07:17 +02:00
72459a04d1 v17.4.4 2023-11-20 17:57:23 +00:00
1e83fcf1e3 Merge pull request #2706 from balena-io/fix-balena-block-create
Fix balena block create to actually create a block
2023-11-20 17:56:32 +00:00
b8769bb9e9 Fix balena block create to actually create a block
Change-type: patch
2023-11-20 13:33:35 -03:00
9f52ee8b21 v17.4.3 2023-11-17 15:39:24 +00:00
90b65cd06b Merge pull request #2683 from balena-io/bump-oclif-core-to-v3
Bump oclif-core to v3
2023-11-17 15:38:25 +00:00
72a924f00e Bump oclif-core to v3
Change-type: patch
2023-11-16 15:06:24 -03:00
e4624eda10 v17.4.2 2023-11-15 11:02:24 +00:00
4173cd82e6 Merge pull request #2697 from balena-io/vipul/automate-capitan
Automatically generate Capitano Docs configuration
2023-11-15 11:01:38 +00:00
b393f27e1b Remove authentication directory
Signed-off-by: Vipul Gupta (@vipulgupta2048) <vipulgupta2048@gmail.com>
2023-11-15 15:55:03 +05:30
1a4a0e2439 Move auth commands into command directories
Signed-off-by: Vipul Gupta (@vipulgupta2048) <vipulgupta2048@gmail.com>
2023-11-15 15:10:22 +05:30
4cd8f4c16e Docs: Generate balena auto-completion
Signed-off-by: Vipul Gupta (@vipulgupta2048) <vipulgupta2048@gmail.com>
2023-11-15 13:08:08 +05:30
2de9d526e5 Docs: Move commands to their own directories, away from their categories
Signed-off-by: Vipul Gupta (@vipulgupta2048) <vipulgupta2048@gmail.com>
2023-11-15 13:07:34 +05:30
d9427c3c59 Docs: Generate balenaCLI with automatic configuration
Signed-off-by: Vipul Gupta (@vipulgupta2048) <vipulgupta2048@gmail.com>
2023-11-15 13:07:01 +05:30
fc0cfac475 Docs: Create version command directory
Signed-off-by: Vipul Gupta (@vipulgupta2048) <vipulgupta2048@gmail.com>
2023-11-15 13:06:45 +05:30
99094dbfda Throw error if command directory rules not followed
Signed-off-by: Vipul Gupta (@vipulgupta2048) <vipulgupta2048@gmail.com>
2023-11-15 13:06:35 +05:30
0711eefb7c Update all imports to match new command directory structure
Signed-off-by: Vipul Gupta (@vipulgupta2048) <vipulgupta2048@gmail.com>
2023-11-15 13:06:19 +05:30
dc40b0d969 Docs: Move CLI commands files to command directories
Signed-off-by: Vipul Gupta (@vipulgupta2048) <vipulgupta2048@gmail.com>
2023-11-15 13:05:58 +05:30
4b5def0a8a Docs: Automatically generate Capitano configuration
Change-type: patch
Signed-off-by: Vipul Gupta (@vipulgupta2048) <vipulgupta2048@gmail.com>
2023-11-15 13:05:39 +05:30
f44fa38113 v17.4.1 2023-11-13 19:18:47 +00:00
167dfeb269 Merge pull request #2701 from balena-io/bump-shrinkwrap
Bump shrinkwrap
2023-11-13 19:17:53 +00:00
a816548bb5 Bump shrinkwrap
Change-type: patch
2023-11-13 15:43:13 -03:00
94001efc81 v17.4.0 2023-11-10 16:28:02 +00:00
8bfafe8ecc Merge pull request #2692 from bbugh/device-json
device: Add `--json` option for JSON output
2023-11-10 13:26:59 -03:00
d78045b6ab device: Add --json option for JSON output
change-type: minor
2023-11-10 12:10:53 -03:00
11eabc4b96 v17.3.2 2023-11-10 11:03:00 +00:00
bfaa91c752 Merge pull request #2700 from balena-io/update-@balena/compose-3.0.5
Update @balena/compose to 3.0.5
2023-11-10 13:02:02 +02:00
1b615e4690 Update @balena/compose to 3.0.5
Update @balena/compose from 3.0.2 to 3.0.5

Change-type: patch
2023-11-10 11:05:42 +02:00
7954e13154 v17.3.1 2023-11-09 17:26:42 +00:00
45d8872a82 Merge pull request #2699 from balena-io/pipeline
Use `pipeline` instead of `.pipe` when downloading OS image
2023-11-09 17:25:34 +00:00
56cff46408 Use pipeline instead of .pipe when downloading OS image
Change-type: patch
2023-11-09 13:38:17 -03:00
47a1a9c6af v17.3.0 2023-11-06 20:19:10 +00:00
a434a5e657 Merge pull request #2689 from mlveggo/add_device_start_stop_service
Add device start-service and stop-service commands
2023-11-06 15:18:14 -05:00
221c213791 Add device start-service and stop-service commands
Change-type: minor
2023-11-06 16:13:51 -03:00
d2150c5cb7 v17.2.4 2023-11-06 19:12:02 +00:00
70e113152d Merge pull request #2696 from balena-io/fix-dsutils
Dedupe shrinkwrap
2023-11-06 16:11:13 -03:00
4a64102d67 Dedupe shrinkwrap
Change-type: patch
2023-11-06 14:11:38 -03:00
9bf267166e v17.2.3 2023-11-03 16:34:18 +00:00
f12249bc81 Merge pull request #2694 from balena-io/vipul/add-them-docs
Generate docs for recently supported commands
2023-11-03 16:33:14 +00:00
80d6c71b02 Update CONTRIBUTING.md with docs instructions
Signed-off-by: Vipul Gupta (@vipulgupta2048) <vipulgupta2048@gmail.com>
2023-11-03 20:39:25 +05:30
9ef4117fb8 Generate docs for recently supported commands
Added documentation for `balena fleet pin` and other recently supported commands

Change-type: patch
Signed-off-by: Vipul Gupta (@vipulgupta2048) <vipulgupta2048@gmail.com>
2023-11-03 20:28:19 +05:30
25f3bf1fbe v17.2.2 2023-10-30 12:25:19 +00:00
fe65351666 Merge pull request #2672 from balena-io/bump-eslint
Bump @balena/lint
2023-10-30 12:24:13 +00:00
7d13946c3e Bump balena-lint to 7.2.1
Change-type: patch
2023-10-30 07:45:51 -04:00
1ffa8d38f1 v17.2.1 2023-10-26 21:28:48 +00:00
6914d39370 Merge pull request #2691 from balena-io/bump-balena-sdk
Update balena-sdk and deduped dependencies
2023-10-26 21:27:22 +00:00
04db9c7a91 Update balena-sdk and deduped dependencies
Update balena-sdk from 18.0.0 to 19.0.0
Update balena-preload from 14.0.3 to 15.0.1
Update balena-image-manager from 9.0.2 to 10.0.1

Change-type: patch
2023-10-26 16:27:43 -03:00
c785d01a1c v17.2.0 2023-10-20 13:45:59 +00:00
87ba364f89 Merge pull request #2685 from bbugh/add-releases-json
Add --json option to `release` and `releases`
2023-10-20 10:44:52 -03:00
b7e5915c7a release: Add '--json' option for JSON output
change-type: minor
2023-10-20 07:42:39 -05:00
0cef6b8f87 releases: Add '--json' option for JSON output 2023-10-20 08:05:36 -03:00
71f1dbd80a v17.1.7 2023-10-20 10:49:19 +00:00
36edcf0cb8 Merge pull request #2688 from balena-io/emty-string-env-tag-values
Support empty string values for `env add` and `tag set`
2023-10-20 13:48:23 +03:00
8204dcad93 tag set: Fix using empty string as a value
Change-type: patch
2023-10-20 13:11:12 +03:00
03bcb6cff7 env add: Fix using empty string as a value
Change-type: patch
2023-10-20 13:11:12 +03:00
66b6eed57c Add tests for empty & non-provided value for the env add command
Change-type: patch
2023-10-20 13:11:12 +03:00
99b0f2c022 Add tests for the tag set command
Change-type: patch
2023-10-20 13:06:39 +03:00
947a9bade7 v17.1.6 2023-10-18 18:16:11 +00:00
15ea601d68 Merge pull request #2686 from balena-io/klutchell-patch-3
Allow custom actions for external contributors
2023-10-18 18:14:54 +00:00
ce888966dd Update npm shrinkwrap
Signed-off-by: Kyle Harding <kyle@balena.io>
2023-10-18 13:04:02 -04:00
3fc6eb7a47 Allow custom actions for external contributors
Change-type: patch
2023-10-18 12:53:43 -04:00
242 changed files with 16657 additions and 33052 deletions

2
.eslintignore Normal file
View File

@ -0,0 +1,2 @@
/completion/*
/bin/*

21
.eslintrc.js Normal file
View File

@ -0,0 +1,21 @@
module.exports = {
extends: ['./node_modules/@balena/lint/config/.eslintrc.js'],
parserOptions: {
project: 'tsconfig.dev.json',
},
root: true,
rules: {
ignoreDefinitionFiles: 0,
// to avoid the `warning Forbidden non-null assertion @typescript-eslint/no-non-null-assertion`
'@typescript-eslint/no-non-null-assertion': 'off',
'@typescript-eslint/no-shadow': 'off',
'@typescript-eslint/no-var-requires': 'off',
'no-restricted-imports': [
'error',
{
paths: ['resin-cli-visuals', 'chalk', 'common-tags', 'resin-cli-form'],
},
],
'@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
},
};

View File

@ -18,7 +18,7 @@ inputs:
default: 'accounts+apple@balena.io'
NODE_VERSION:
type: string
default: '18.x'
default: '20.x'
VERBOSE:
type: string
default: 'true'
@ -28,7 +28,7 @@ runs:
using: 'composite'
steps:
- name: Download custom source artifact
uses: actions/download-artifact@v3
uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7
with:
name: custom-${{ github.event.pull_request.head.sha || github.event.head_commit.id }}-${{ runner.os }}-${{ runner.arch }}
path: ${{ runner.temp }}
@ -39,11 +39,17 @@ runs:
run: tar -xf ${{ runner.temp }}/custom.tgz
- name: Setup Node.js
uses: actions/setup-node@v3
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4
with:
node-version: ${{ inputs.NODE_VERSION }}
cache: npm
- name: Set up Python 3.11
if: runner.os == 'macOS'
uses: actions/setup-python@65d7f2d534ac1bc67fcd62888c5f4f3d2cb2b236 # v4
with:
python-version: "3.11"
- name: Install additional tools
if: runner.os == 'Windows'
shell: bash
@ -60,7 +66,7 @@ runs:
# https://github.com/Apple-Actions/import-codesign-certs
- name: Import Apple code signing certificate
if: runner.os == 'macOS'
uses: apple-actions/import-codesign-certs@v1
uses: apple-actions/import-codesign-certs@253ddeeac23f2bdad1646faac5c8c2832e800071 # v1
with:
p12-file-base64: ${{ fromJSON(inputs.secrets).APPLE_SIGNING }}
p12-password: ${{ fromJSON(inputs.secrets).APPLE_SIGNING_PASSWORD }}
@ -69,18 +75,11 @@ runs:
if: runner.os == 'Windows'
shell: powershell
run: |
Set-Content -Path ${{ runner.temp }}/certificate.base64 -Value $env:WINDOWS_CERTIFICATE
certutil -decode ${{ runner.temp }}/certificate.base64 ${{ runner.temp }}/certificate.pfx
Set-Content -Path ${{ runner.temp }}/certificate.base64 -Value $env:SM_CLIENT_CERT_FILE_B64
certutil -decode ${{ runner.temp }}/certificate.base64 ${{ runner.temp }}/Certificate_pkcs12.p12
Remove-Item -path ${{ runner.temp }} -include certificate.base64
Import-PfxCertificate `
-FilePath ${{ runner.temp }}/certificate.pfx `
-CertStoreLocation Cert:\CurrentUser\My `
-Password (ConvertTo-SecureString -String $env:WINDOWS_CERTIFICATE_PASSWORD -Force -AsPlainText)
env:
WINDOWS_CERTIFICATE: ${{ fromJSON(inputs.secrets).WINDOWS_SIGNING }}
WINDOWS_CERTIFICATE_PASSWORD: ${{ fromJSON(inputs.secrets).WINDOWS_SIGNING_PASSWORD }}
SM_CLIENT_CERT_FILE_B64: ${{ fromJSON(inputs.secrets).SM_CLIENT_CERT_FILE_B64 }}
# https://github.com/product-os/scripts/tree/master/shared
# https://github.com/product-os/balena-concourse/blob/master/pipelines/github-events/template.yml
@ -100,12 +99,21 @@ runs:
CSC_LINK=${{ fromJSON(inputs.secrets).APPLE_SIGNING }}
elif [[ $runner_os =~ windows|win ]]; then
CSC_KEY_PASSWORD=${{ fromJSON(inputs.secrets).WINDOWS_SIGNING_PASSWORD }}
CSC_LINK='${{ runner.temp }}\certificate.pfx'
SM_HOST=${{ fromJSON(inputs.secrets).SM_HOST }}
SM_API_KEY=${{ fromJSON(inputs.secrets).SM_API_KEY }}
SM_CLIENT_CERT_FILE='${{ runner.temp }}\Certificate_pkcs12.p12'
SM_CLIENT_CERT_PASSWORD=${{ fromJSON(inputs.secrets).SM_CLIENT_CERT_PASSWORD }}
SM_CODE_SIGNING_CERT_SHA1_HASH=${{ fromJSON(inputs.secrets).SM_CODE_SIGNING_CERT_SHA1_HASH }}
# patches/all/oclif.patch
MSYSSHELLPATH="$(which bash)"
MSYSTEM=MSYS
curl --silent --retry 3 --fail https://one.digicert.com/signingmanager/api-ui/v1/releases/smtools-windows-x64.msi/download \
-H "x-api-key:$SM_API_KEY" \
-o smtools-windows-x64.msi
msiexec -i smtools-windows-x64.msi -qn
PATH="/c/Program Files/DigiCert/DigiCert One Signing Manager Tools:${PATH}"
smksp_registrar.exe list
smctl.exe keypair ls
/c/Windows/System32/certutil.exe -csp "DigiCert Signing Manager KSP" -key -user
smksp_cert_sync.exe
# (signtool.exe) https://github.com/actions/runner-images/blob/main/images/win/Windows2019-Readme.md#installed-windows-sdks
PATH="/c/Program Files (x86)/Windows Kits/10/bin/${runner_arch}:${PATH}"
@ -119,16 +127,17 @@ runs:
# https://github.blog/2020-08-03-github-actions-improvements-for-fork-and-pull-request-workflows/#improvements-for-public-repository-forks
# https://docs.github.com/en/actions/managing-workflow-runs/approving-workflow-runs-from-public-forks#about-workflow-runs-from-public-forks
CSC_FOR_PULL_REQUEST: true
# https://sectigo.com/resource-library/time-stamping-server
TIMESTAMP_SERVER: http://timestamp.sectigo.com
# https://docs.digicert.com/es/software-trust-manager/ci-cd-integrations/plugins/github-custom-action-for-keypair-signing.html
TIMESTAMP_SERVER: http://timestamp.digicert.com
# Apple notarization (automation/build-bin.ts)
XCODE_APP_LOADER_EMAIL: ${{ inputs.XCODE_APP_LOADER_EMAIL }}
XCODE_APP_LOADER_PASSWORD: ${{ fromJSON(inputs.secrets).XCODE_APP_LOADER_PASSWORD }}
XCODE_APP_LOADER_TEAM_ID: ${{ inputs.XCODE_APP_LOADER_TEAM_ID }}
- name: Upload artifacts
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4
with:
name: gh-release-${{ github.event.pull_request.head.sha || github.event.head_commit.id }}
name: gh-release-${{ github.event.pull_request.head.sha || github.event.head_commit.id }}-${{ strategy.job-index }}
path: dist
retention-days: 1
if-no-files-found: error

View File

@ -15,7 +15,7 @@ inputs:
# --- custom environment
NODE_VERSION:
type: string
default: '18.x'
default: '20.x'
VERBOSE:
type: string
default: "true"
@ -26,11 +26,17 @@ runs:
steps:
# https://github.com/actions/setup-node#caching-global-packages-data
- name: Setup Node.js
uses: actions/setup-node@v3
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4
with:
node-version: ${{ inputs.NODE_VERSION }}
cache: npm
- name: Set up Python 3.11
if: runner.os == 'macOS'
uses: actions/setup-python@65d7f2d534ac1bc67fcd62888c5f4f3d2cb2b236 # v4
with:
python-version: "3.11"
- name: Test release
shell: bash
run: |
@ -45,14 +51,14 @@ runs:
fi
npm run build
npm run test
npm run test:core
- name: Compress custom source
shell: pwsh
run: tar --exclude-vcs -acf ${{ runner.temp }}/custom.tgz .
- name: Upload custom artifact
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4
with:
name: custom-${{ github.event.pull_request.head.sha || github.event.head_commit.id }}-${{ runner.os }}-${{ runner.arch }}
path: ${{ runner.temp }}/custom.tgz

4
.github/renovate.json vendored Normal file
View File

@ -0,0 +1,4 @@
{
"extends": ["github>balena-io/renovate-config"],
"postUpdateOptions": ["npmDedupe"]
}

View File

@ -1,5 +1,4 @@
name: Flowzone
on:
pull_request:
types: [opened, synchronize, closed]
@ -7,7 +6,6 @@ on:
pull_request_target:
types: [opened, synchronize, closed]
branches: [main, master]
jobs:
flowzone:
name: Flowzone
@ -23,7 +21,25 @@ jobs:
)
secrets: inherit
with:
custom_runs_on: '[["self-hosted","Linux","distro:focal","X64"],["self-hosted","Linux","distro:focal","ARM64"],["macos-12"],["windows-2019"]]'
repo_config: true
repo_description: "The official balena CLI tool."
custom_test_matrix: >
{
"os": [
["self-hosted", "X64"],
["self-hosted", "ARM64"],
["macos-12"],
["windows-2019"],
["macos-latest-xlarge"]
]
}
custom_publish_matrix: >
{
"os": [
["self-hosted", "X64"],
["self-hosted", "ARM64"],
["macos-12"],
["windows-2019"],
["macos-latest-xlarge"]
]
}
github_prerelease: false
restrict_custom_actions: false

1
.husky/pre-commit Normal file
View File

@ -0,0 +1 @@
node automation/check-npm-version.js && ts-node automation/check-doc.ts

File diff suppressed because it is too large Load Diff

View File

@ -4,6 +4,989 @@ All notable changes to this project will be documented in this file
automatically by Versionist. DO NOT EDIT THIS FILE MANUALLY!
This project adheres to [Semantic Versioning](http://semver.org/).
## 19.0.3 - 2024-09-05
* Reduce use of CJS require() on automation files [Otavio Jacobi]
* Remove the use of CJS require() on test files [Otavio Jacobi]
* Remove not necessary 'import = require' syntax for js-yaml [Otavio Jacobi]
## 19.0.2 - 2024-09-03
* Update devDependency patch-package to v8.0.0 [Otavio Jacobi]
* Update devDependency mkdirp to v3.0.1 [Otavio Jacobi]
* Update devDependency fs-extra(to v11) and @types/fs-extra(to v11) [Otavio Jacobi]
* Update devDependency @types/parse-link-header to v2.0.3 [Otavio Jacobi]
* Remove unused devDependency @types/nock [Otavio Jacobi]
* Update devDependency klaw(to v4) and @types/klaw(to v3.0.6) [Otavio Jacobi]
* Update husky to v9.1.5 [Otavio Jacobi]
* Update devDependency @types/jsonwebtoken to v9.0.6 [Otavio Jacobi]
* Update devDependency archiver(to v7) and @types/archiver(to v6) [Otavio Jacobi]
* Removes unused devDependency @types/net-keepalive [Otavio Jacobi]
* Update devDependency rewire(to v7) and @types/rewire(to v2.5.30) [Otavio Jacobi]
* Update devDependency sinon(to v18) and @types/sinon(to v17) [Otavio Jacobi]
## 19.0.1 - 2024-09-02
* Bump @oclif/core from 3.27.0 to 4.0.18 [Otavio Jacobi]
## 19.0.0 - 2024-08-22
* Update all references of lib to src [Otavio Jacobi]
* Rename the lib folder to src [Otavio Jacobi]
* Update @balena/compose to 4.0.1 Update @balena/compose from 3.2.1 to 4.0.1 [Otavio Jacobi]
* Use standard visuals table component for fleet/s [Otavio Jacobi]
## 18.2.34 - 2024-07-29
* Run npm dedupe commands [Kyle Harding]
* Switch to self-hosted [Anton Belodedenko]
## 18.2.33 - 2024-07-17
* Improve discover balena os across different networks [Otavio Jacobi]
## 18.2.32 - 2024-07-16
* Remove unused code [Otavio Jacobi]
## 18.2.31 - 2024-07-15
* deploy: Use the sdk's pine instance with balena-compose [Thodoris Greasidis]
<details>
<summary> Update balena-sdk to 19.7.3 [Thodoris Greasidis] </summary>
> ### balena-sdk-19.7.3 - 2024-07-12
>
> * pinejs-client-core: Add some missing methods to the custom typings [Thodoris Greasidis]
>
</details>
## 18.2.30 - 2024-07-15
* Omit unicode control character escapes from test logs [Thodoris Greasidis]
## 18.2.29 - 2024-07-12
* Update balena-preload from 15.0.5 to 15.0.6 [Otavio Jacobi]
## 18.2.28 - 2024-07-12
* Downgrade pinejs-client-request to 7.4.2 to unblock the sdk update [Thodoris Greasidis]
<details>
<summary> Update balena-sdk to 19.7.2 [Thodoris Greasidis] </summary>
> ### balena-sdk-19.7.2 - 2024-07-12
>
>
> <details>
> <summary> Update balena-request from 13.3.1 to 13.3.2 [Thodoris Greasidis] </summary>
>
>> #### balena-request-13.3.2 - 2024-07-12
>>
>> * Fix always following redirects when followRedirect = false [Thodoris Greasidis]
>>
>
> </details>
>
>
> ### balena-sdk-19.7.1 - 2024-07-08
>
>
> <details>
> <summary> Limit pinejs-client-core to ~6.14.0, to fix errors in older TypeScript [Thodoris Greasidis] </summary>
>
>> #### pinejs-client-js-6.14.0 - 2023-12-05
>>
>> * Respect the Retry-After header when clients define the getRetryAfterHeader option [Thodoris Greasidis]
>>
>> #### pinejs-client-js-6.13.0 - 2023-07-11
>>
>> * Add support for $duration [Thodoris Greasidis]
>>
>> #### pinejs-client-js-6.12.4 - 2023-05-09
>>
>> * Avoid an unnecessary function creation on each get() call [Thodoris Greasidis]
>>
>> #### pinejs-client-js-6.12.3 - 2022-12-28
>>
>> * CI: Convert tests to TypeScript [Josh Bowling]
>>
>> #### pinejs-client-js-6.12.2 - 2022-11-18
>>
>> * Fix `$orderby: { a: { $count: ... }, $dir: 'asc' }` typings [Thodoris Greasidis]
>>
>> #### pinejs-client-js-6.12.1 - 2022-11-15
>>
>> * Update TypeScript to 4.9.3 [Thodoris Greasidis]
>>
>
> </details>
>
> * Fix the TypeScript incompatibility test [Thodoris Greasidis]
>
> ### balena-sdk-19.7.0 - 2024-07-05
>
> * Add identity provider & saml account model typing [Otavio Jacobi]
>
> ### balena-sdk-19.6.1 - 2024-06-20
>
> * Update TypeScript to 5.5.2 [Thodoris Greasidis]
>
> ### balena-sdk-19.6.0 - 2024-06-20
>
> * Add the application.getAllByOrganization() method [Thodoris Greasidis]
> * Deprecate the application.getAppByOwner() method [Thodoris Greasidis]
>
> ### balena-sdk-19.5.11 - 2024-05-28
>
> * tests: Make the cleanups more precise [Thodoris Greasidis]
>
> ### balena-sdk-19.5.10 - 2024-03-29
>
> * Drop the toWritable helper in favor of TypeScript's satisfies [Thodoris Greasidis]
>
> ### balena-sdk-19.5.9 - 2024-03-29
>
> * os: Update the comments on why we still need to be using the release_tags [Thodoris Greasidis]
>
> ### balena-sdk-19.5.8 - 2024-03-18
>
> * Fix `application.create` method being wrongly marked as deprecated [myarmolinsky]
>
> ### balena-sdk-19.5.7 - 2024-03-08
>
> * Fix missing underscore to describes__device property [Andrea Rosci]
>
> ### balena-sdk-19.5.6 - 2024-03-07
>
> * Update TypeScript to 5.4.2 [Thodoris Greasidis]
> * device-type.getInstructions: Convert etcher link to HTTPS [Vipul Gupta (@vipulgupta2048)]
>
</details>
## 18.2.27 - 2024-07-12
<details>
<summary> Update balena-sdk to 19.5.5 [Thodoris Greasidis] </summary>
> ### balena-sdk-19.5.5 - 2024-02-26
>
>
> <details>
> <summary> Update balena-auth to 6.0.1 [Thodoris Greasidis] </summary>
>
>> #### balena-auth-6.0.1 - 2024-02-23
>>
>> * Update jwt-decode to v3 [Thodoris Greasidis]
>>
>> #### balena-auth-6.0.0 - 2024-02-23
>>
>> * Update typescript to 5.3.3 [Thodoris Greasidis]
>> * Move the sources from lib to src [Thodoris Greasidis]
>> * Update @balena/lint to v7 [Thodoris Greasidis]
>> * Stop publishing the lib folder [Thodoris Greasidis]
>> * Drop support for nodejs < 18 [Thodoris Greasidis]
>> * Drop no longer used appveyor.yml [Thodoris Greasidis]
>>
>> #### balena-register-device-9.0.2 - 2024-02-23
>>
>> * Update @balena/lint to v7 [Thodoris Greasidis]
>> * Update balena-request to 13.3.0 [Thodoris Greasidis]
>>
>> #### balena-request-13.3.1 - 2024-02-23
>>
>> * Update balena-auth to 6.0.1 [Thodoris Greasidis]
>>
>
> </details>
>
>
> ### balena-sdk-19.5.4 - 2024-02-14
>
> * Bump balena-request Update balena-request from 13.2.0 to 13.3.0 [Otávio Jacobi]
>
> ### balena-sdk-19.5.3 - 2024-02-14
>
> * Replace deprecated flowzone input tests_run_on [Kyle Harding]
>
> ### balena-sdk-19.5.2 - 2024-02-13
>
> * tests: Reformat describe & it calls to have curly braces [Thodoris Greasidis]
>
> ### balena-sdk-19.5.1 - 2024-02-02
>
> * Update @balena/lint to 7.3.0 [Thodoris Greasidis]
>
> ### balena-sdk-19.5.0 - 2024-01-26
>
> * types: Add the `Organization.is_using__billing_version` property [Thodoris Greasidis]
>
</details>
## 18.2.26 - 2024-07-12
* Drop unused dependencies [Otavio Jacobi]
* Move dependencies that should be dev only as devDependencies [Otavio Jacobi]
## 18.2.25 - 2024-07-11
* Fix complete generation intermitency [Otavio Jacobi]
* Bump oclif to v4 [Otavio Jacobi]
## 18.2.24 - 2024-07-10
* Update mocha from 8.4.0 to 10.6.0 [Otavio Jacobi]
* Override inline-source-cli with non-vulnerable dependency [Otavio Jacobi]
## 18.2.23 - 2024-07-10
* Replace resin-discoverable-services with bonjour-service [Otavio Jacobi]
## 18.2.22 - 2024-07-10
* Remove unused dependency minimatch [Otavio Jacobi]
## 18.2.21 - 2024-07-09
* Bump resin-discoverable-services from 2.0.4 to 2.0.5 [Otavio Jacobi]
## 18.2.20 - 2024-07-05
* Audit fix dependencies [Otavio Jacobi]
## 18.2.19 - 2024-07-05
* Remove unused package `publish-release` [myarmolinsky]
## 18.2.18 - 2024-07-04
* Update actions/setup-node action to v4 [Self-hosted Renovate Bot]
## 18.2.17 - 2024-07-02
<details>
<summary> Update dependency etcher-sdk to v9.1.0 [Self-hosted Renovate Bot] </summary>
> ### etcher-sdk-9.1.0 - 2024-06-13
>
> * patch: etcher-sdk is not yet compatible with node22 [JOASSART Edwin]
> * minor: allow passing custom assets to start SB protected CM4 [Edwin Joassart]
>
</details>
## 18.2.16 - 2024-07-02
<details>
<summary> Update dependency etcher-sdk to v9.0.11 [Self-hosted Renovate Bot] </summary>
> ### etcher-sdk-9.0.11 - 2024-04-26
>
> * patch: use http2 to fix issues with url source [Edwin Joassart]
>
> ### etcher-sdk-9.0.10 - 2024-04-26
>
> * patch: remove CI workaround [Edwin Joassart]
>
> ### etcher-sdk-9.0.9 - 2024-04-24
>
> * patch: add option to allow listing virtual drive on Mac [JOASSART Edwin]
>
</details>
## 18.2.15 - 2024-07-02
* Update dependency event-stream to v3.3.5 [Self-hosted Renovate Bot]
## 18.2.14 - 2024-07-02
* Update dependency jsonwebtoken to v9 [SECURITY] [Self-hosted Renovate Bot]
## 18.2.13 - 2024-07-02
* Update dependency @types/prettyjson to ^0.0.33 [Self-hosted Renovate Bot]
## 18.2.12 - 2024-07-02
* Deduplicate dependencies [Thodoris Greasidis]
## 18.2.11 - 2024-07-01
* Update dependency @types/fast-levenshtein to v0.0.4 [Self-hosted Renovate Bot]
## 18.2.10 - 2024-06-21
* Update actions/download-artifact action to v4.1.7 [Self-hosted Renovate Bot]
## 18.2.9 - 2024-06-21
* Update actions/setup-python digest to 65d7f2d [Self-hosted Renovate Bot]
## 18.2.8 - 2024-06-21
* Update actions/upload-artifact digest to 6546280 [Self-hosted Renovate Bot]
## 18.2.7 - 2024-06-21
* Pin dependencies [Self-hosted Renovate Bot]
## 18.2.6 - 2024-06-21
* Update @oclif/core from 3.26.9 to 3.27.0 [Otavio Jacobi]
## 18.2.5 - 2024-06-21
* Limit @oclif/core to ~3.26 so that npm dedupe doesn't auto-bump it [Thodoris Greasidis]
* Update TypeScript to 5.5.2 [Thodoris Greasidis]
## 18.2.4 - 2024-05-17
* patch: fix outdated doc for "os configure" [Edwin Joassart]
## 18.2.3 - 2024-05-15
* Pluralize command categories in docs [dfunckt]
## 18.2.2 - 2024-04-30
* Upgrade dockerode and docker-modem dependencies [Ken Bannister]
## 18.2.1 - 2024-04-23
* Use Actuated runners for Linux test and publish [Kyle Harding]
## 18.2.0 - 2024-04-17
* build: Auto-resolve the cpu arch when the --deviceType is provided [Thodoris Greasidis]
## 18.1.10 - 2024-04-16
* Mark node 20.6.0 as the minimum working version [Thodoris Greasidis]
## 18.1.9 - 2024-04-10
* Enable npm dedupe as part of Renovate postUpdateOptions [Kyle Harding]
## 18.1.8 - 2024-04-09
* Bump patch-package to 6.5.1 [Thodoris Greasidis]
* npm-shrinkwrap.json: Recreate with lockfileVersion 3 [Thodoris Greasidis]
## 18.1.7 - 2024-04-09
<details>
<summary> Update balena-preload to 15.0.5 [Thodoris Greasidis] </summary>
> ### balena-preload-15.0.5 - 2024-04-09
>
> * Remove unused dependencies [Otavio Jacobi]
>
</details>
## 18.1.6 - 2024-04-09
* Update @oclif/core to 3.26.2 [Thodoris Greasidis]
* Drop the keep-alive package in favor of node's setKeepAlive defaults [Thodoris Greasidis]
* Update balena-preload to v15.0.4 [Thodoris Greasidis]
* Update resin-cli-form to v3 [Thodoris Greasidis]
* Update resin-cli-visuals to v2 [Thodoris Greasidis]
* Update balena-device-init to v7.0.1 [Thodoris Greasidis]
* Update etcher-sdk to v9.0.8 [Thodoris Greasidis]
* Mark bin/dev & bin/run as executable [Thodoris Greasidis]
## 18.1.5 - 2024-03-14
* Move klaw library to dev dependency [Otavio Jacobi]
## 18.1.4 - 2024-03-14
* Update @balena/lint to 8.0.0 [myarmolinsky]
## 18.1.3 - 2024-03-14
* Use standard oclif run.js & dev.js [Otavio Jacobi]
## 18.1.2 - 2024-03-13
* Move macos binary signing to oclif pretarball lifecycle [Otavio Jacobi]
## 18.1.1 - 2024-03-12
* Remove patching tmp for windows runners [Otavio Jacobi]
## 18.1.0 - 2024-03-12
* Add support for macos arm64 builds [Otavio Jacobi]
## 18.0.4 - 2024-03-11
* Update dependencies [Otavio Jacobi]
## 18.0.3 - 2024-03-11
* Removes signing patches [Otavio Jacobi]
## 18.0.2 - 2024-03-07
* Remove no longer needed windows oclif patches [Otavio Jacobi]
## 18.0.1 - 2024-03-07
* Fix windows signing [Otavio Jacobi]
## 18.0.0 - 2024-02-06
* Update to Node 20 [Otávio Jacobi]
## 17.5.1 - 2024-01-31
* Fix target state construction with livepush [Felipe Lalanne]
## 17.5.0 - 2024-01-23
* os versions: Add the --include-draft option [Thodoris Greasidis]
* device os-update: Add option for including pre-release versions in the list [Thodoris Greasidis]
* device os-update: Enable updates to pre-release versions of higher base semver [Thodoris Greasidis]
<details>
<summary> Update balena-sdk to 19.4.0 [Thodoris Greasidis] </summary>
> ### balena-sdk-19.4.0 - 2024-01-23
>
> * Update the deviceType.getInstructions tests [Thodoris Greasidis]
> * os.getSupportedOsUpdateVersions: Add the option to include draft releases [Thodoris Greasidis]
>
> <details>
> <summary> Enable OS Updates to pre-release versions of higher base semver [Thodoris Greasidis] </summary>
>
>> #### balena-hup-action-utils-6.1.0 - 2024-01-04
>>
>> * Enable OS Updates to pre-release versions of higher base semver [Thodoris Greasidis]
>>
>> #### balena-hup-action-utils-6.0.0 - 2023-12-20
>>
>> * Drop support for TypeScript < 5.3.3 [Thodoris Greasidis]
>> * Drop support for node < v18 [Thodoris Greasidis]
>> * Update dependencies [Thodoris Greasidis]
>> * Move the build step from prepare to prepack [Thodoris Greasidis]
>>
>> #### balena-hup-action-utils-5.0.1 - 2023-07-13
>>
>> * patch: Update flowzone.yml [Kyle Harding]
>>
>
> </details>
>
> * os.getAvailableOsVersions: Add the option to include draft releases [Thodoris Greasidis]
>
> ### balena-sdk-19.3.5 - 2023-12-21
>
> * Update date-fns to v3 [Thodoris Greasidis]
>
> ### balena-sdk-19.3.4 - 2023-12-15
>
> * types/Device: Deprecate the non-existent vpn_address property [Otávio Jacobi]
>
> ### balena-sdk-19.3.3 - 2023-12-15
>
> * types/Device: Deprecate the non-existent state & status_sort_index properties [Thodoris Greasidis]
>
> ### balena-sdk-19.3.2 - 2023-12-08
>
> * test:fast: Run the tests ignoring any linting errors [Thodoris Greasidis]
> * tests: Re-enable the explicit error checks for non-tarball DWB requests [Thodoris Greasidis]
>
> ### balena-sdk-19.3.1 - Invalid date
>
> * Update TypeScript to 5.3.2 [Thodoris Greasidis]
>
> ### balena-sdk-19.3.0 - Invalid date
>
> * tests: Remove the explicit error checks for non-tarball DWB requests [Thodoris Greasidis]
> * tests: Properly cleanup the test orgs [Thodoris Greasidis]
> * tests: Reduce the request batching chunk size to speed up tests [Thodoris Greasidis]
> * Add option for configuring the request batching chunk size [Thodoris Greasidis]
>
> ### balena-sdk-19.2.0 - 2023-11-13
>
> * Add organization logo to organization [Otávio Jacobi]
>
> ### balena-sdk-19.1.0 - 2023-11-06
>
> * Add the retryRateLimitedRequests sdk option for retrying after HTTP 429s [Thodoris Greasidis]
>
</details>
## 17.4.12 - 2024-01-18
* Regression described in GitHub Issue 2715; balena push hangs in local mode. [Ken Bannister]
## 17.4.11 - 2024-01-05
* Exclude the oclif package patch from the published files [Thodoris Greasidis]
* Update the @oclif/core patch [Thodoris Greasidis]
## 17.4.10 - 2024-01-02
* Normalize v prefixes in the --version parameter of all commands [Thodoris Greasidis]
## 17.4.9 - 2023-12-19
* Fix publishing artifacts to gh release [Otávio Jacobi]
## 17.4.8 - 2023-12-19
* Remove repo config from flowzone.yml [Kyle Harding]
## 17.4.7 - 2023-12-19
* deploy: Add rate-limiting aware retries for failed requests [Thodoris Greasidis]
<details>
<summary> Update dependencies [Thodoris Greasidis] </summary>
> ### balena-compose-3.2.0 - 2023-12-05
>
> * release/createClient: Allow specifying the "retry" options [Thodoris Greasidis]
>
> ### balena-compose-3.1.3 - 2023-11-29
>
> * Update dockerode to 3.3.5 [Pagan Gazzard]
>
> ### balena-compose-3.1.2 - 2023-11-29
>
> * Use the JSONStream typings from @types/jsonstream [Pagan Gazzard]
>
> ### balena-compose-3.1.1 - 2023-11-27
>
> * Make use of `pipeline` for piping streams together [Pagan Gazzard]
>
> ### balena-compose-3.1.0 - 2023-11-13
>
> * Allow injecting any PinejsClientCore compatible API client [Thodoris Greasidis]
>
> ### balena-compose-3.0.7 - 2023-11-10
>
> * NodeResolver: Refactor the recursion to an async-await loop [Thodoris Greasidis]
> * Drop bluebird & bluebird-lru-cache in favor of memoizee [Thodoris Greasidis]
>
> ### balena-compose-3.0.6 - 2023-11-10
>
> * Fix the remaining linting errors [Thodoris Greasidis]
> * Remove unnecessary regex escaping [Thodoris Greasidis]
> * Replace the {} type with object [Thodoris Greasidis]
> * Update TypeScript to 5.2.2 and @blaena/lint to v7.2.1 [Thodoris Greasidis]
>
</details>
## 17.4.6 - 2023-12-08
* Bump oclif core & use default missing flag handler [Otávio Jacobi]
## 17.4.5 - 2023-12-04
* Stop testing dependency deduplication on the custom test runners [Thodoris Greasidis]
* Temporarily pin oclif-core to ~3.11.0 to deduplicate the dependencies [Thodoris Greasidis]
* Update TypeScript to 5.3.2 [Thodoris Greasidis]
## 17.4.4 - 2023-11-20
* Fix balena block create to actually create a block [Otávio Jacobi]
## 17.4.3 - 2023-11-17
* Bump oclif-core to v3 [Otávio Jacobi]
## 17.4.2 - 2023-11-15
* Docs: Automatically generate Capitano configuration [Vipul Gupta (@vipulgupta2048)]
## 17.4.1 - 2023-11-13
* Bump shrinkwrap [Otávio Jacobi]
## 17.4.0 - 2023-11-10
* device: Add `--json` option for JSON output [Brian Bugh]
## 17.3.2 - 2023-11-10
<details>
<summary> Update @balena/compose to 3.0.5 [Thodoris Greasidis] </summary>
> ### balena-compose-3.0.5 - 2023-11-09
>
> * builder: Fix unawaited buildDir pack() promise [Thodoris Greasidis]
>
> ### balena-compose-3.0.4 - 2023-11-09
>
> * api: Restore the accidentally removed concurrency limits [Thodoris Greasidis]
>
> ### balena-compose-3.0.3 - 2023-11-09
>
> * .mocharc: Use "exit: true" to workaround hanging on completion on node20 [Thodoris Greasidis]
> * tests: Fix the expected error message for Dockerfile syntax errors [Thodoris Greasidis]
>
</details>
## 17.3.1 - 2023-11-09
* Use `pipeline` instead of `.pipe` when downloading OS image [Pagan Gazzard]
## 17.3.0 - 2023-11-06
* Add device start-service and stop-service commands [Morgan Larsson]
## 17.2.4 - 2023-11-06
* Dedupe shrinkwrap [myarmolinsky]
## 17.2.3 - 2023-11-03
* Generate docs for recently supported commands [Vipul Gupta (@vipulgupta2048)]
## 17.2.2 - 2023-10-30
* Bump balena-lint to 7.2.1 [myarmolinsky]
## 17.2.1 - 2023-10-26
<details>
<summary> Update balena-sdk and deduped dependencies [Otávio Jacobi] </summary>
> ### balena-sdk-19.0.0 - 2023-10-16
>
>
> <details>
> <summary> **BREAKING**: Drop support to node < 18 [Otávio Jacobi] </summary>
>
>> #### balena-register-device-9.0.1 - 2023-10-11
>>
>> * Fix balena-request peer dependency [Otávio Jacobi]
>>
>> #### balena-register-device-9.0.0 - 2023-10-11
>>
>> * Drop supoport for node 14 & 16 [Otávio Jacobi]
>>
>> #### balena-request-13.0.0 - 2023-10-11
>>
>> * Drop support for node 14 & 16 [Otávio Jacobi]
>>
>
> </details>
>
>
> ### balena-sdk-18.3.0 - 2023-10-09
>
> * jwt: Deprecate the profile fields in favor of the user_profile [Thodoris Greasidis]
> * jwt: Deprecate the intercom fields [Thodoris Greasidis]
> * jwt: Deprecate the features fields [Thodoris Greasidis]
> * jwt: Deprecate thw loginAs field [Thodoris Greasidis]
> * jwt: Deprecate username & created_at in favor of the user resource [Thodoris Greasidis]
> * Add typings for the user_profile resource [Thodoris Greasidis]
>
> ### balena-sdk-18.2.0 - 2023-09-26
>
> * Update @balena/lint to 7.2.0 [Thodoris Greasidis]
> * Deprecate the social_service_account property of the JWTUser [Thodoris Greasidis]
> * Add typings for the social_service_account resource [Thodoris Greasidis]
>
> ### balena-sdk-18.1.4 - 2023-08-24
>
> * Update TypeScript to 5.2.2 [Thodoris Greasidis]
>
> ### balena-sdk-18.1.3 - 2023-08-23
>
> * tests/os: Refactor some promise tests to async await [Thodoris Greasidis]
> * Fix os.getSupervisorReleaseByDeviceType test to work on balenaMachine [Thodoris Greasidis]
>
> <details>
> <summary> Update balena-request from 12.0.2 to 12.0.4 [Thodoris Greasidis] </summary>
>
>> #### balena-request-12.0.4 - 2023-08-23
>>
>> * Refactor the interceptors to stop using .reduce() [Thodoris Greasidis]
>>
>> #### balena-request-12.0.3 - 2023-08-09
>>
>> * Avoid deep imports from balena-auth [Thodoris Greasidis]
>> * Update balena-auth to 5.1.0 [Thodoris Greasidis]
>>
>
> </details>
>
>
> ### balena-sdk-18.1.2 - 2023-08-23
>
> * organization-invite: Fix throwing a typed error when passing an unkonwn role [Thodoris Greasidis]
> * application-invite: Fix throwing a typed error when passing an unkonwn role [Thodoris Greasidis]
> * tests: Fix bugs that linting surfaced [Thodoris Greasidis]
> * Update @balena/lint to 7.0.1 [Thodoris Greasidis]
>
> ### balena-sdk-18.1.1 - 2023-08-22
>
> * logs: Emit errors when initializing the SDK with debug: true [Thodoris Greasidis]
>
> ### balena-sdk-18.1.0 - 2023-08-22
>
> * Improve the auth.getActorId() tests [Thodoris Greasidis]
> * auth.getUserInfo: Add the actor id to the returned values [Thodoris Greasidis]
>
> ### balena-sdk-18.0.2 - 2023-08-18
>
> * patch: bump lint-staged from 13.3.0 to 14.0.0 [Thodoris Greasidis]
>
> ### balena-sdk-18.0.1 - 2023-08-18
>
> * Replace dependabot with renovate [Thodoris Greasidis]
>
> ### balena-image-manager-10.0.1 - 2023-10-26
>
>
> <details>
> <summary> Update balena-sdk to 19.0.1 [Otávio Jacobi] </summary>
>
>> #### balena-sdk-19.0.1 - 2023-10-19
>>
>> * Fix test workflow to run on node 18 [Otávio Jacobi]
>>
>> #### balena-sdk-19.0.0 - 2023-10-16
>>
>>
>> <details>
>> <summary> **BREAKING**: Drop support to node < 18 [Otávio Jacobi] </summary>
>>
>>> ##### balena-register-device-9.0.1 - 2023-10-11
>>>
>>> * Fix balena-request peer dependency [Otávio Jacobi]
>>>
>>> ##### balena-register-device-9.0.0 - 2023-10-11
>>>
>>> * Drop supoport for node 14 & 16 [Otávio Jacobi]
>>>
>>> ##### balena-request-13.0.0 - 2023-10-11
>>>
>>> * Drop support for node 14 & 16 [Otávio Jacobi]
>>>
>>
>> </details>
>>
>>
>> #### balena-sdk-18.3.0 - 2023-10-09
>>
>> * jwt: Deprecate the profile fields in favor of the user_profile [Thodoris Greasidis]
>> * jwt: Deprecate the intercom fields [Thodoris Greasidis]
>> * jwt: Deprecate the features fields [Thodoris Greasidis]
>> * jwt: Deprecate thw loginAs field [Thodoris Greasidis]
>> * jwt: Deprecate username & created_at in favor of the user resource [Thodoris Greasidis]
>> * Add typings for the user_profile resource [Thodoris Greasidis]
>>
>> #### balena-sdk-18.2.0 - 2023-09-26
>>
>> * Update @balena/lint to 7.2.0 [Thodoris Greasidis]
>> * Deprecate the social_service_account property of the JWTUser [Thodoris Greasidis]
>> * Add typings for the social_service_account resource [Thodoris Greasidis]
>>
>> #### balena-sdk-18.1.4 - 2023-08-24
>>
>> * Update TypeScript to 5.2.2 [Thodoris Greasidis]
>>
>> #### balena-sdk-18.1.3 - 2023-08-23
>>
>> * tests/os: Refactor some promise tests to async await [Thodoris Greasidis]
>> * Fix os.getSupervisorReleaseByDeviceType test to work on balenaMachine [Thodoris Greasidis]
>>
>> <details>
>> <summary> Update balena-request from 12.0.2 to 12.0.4 [Thodoris Greasidis] </summary>
>>
>>> ##### balena-request-12.0.4 - 2023-08-23
>>>
>>> * Refactor the interceptors to stop using .reduce() [Thodoris Greasidis]
>>>
>>> ##### balena-request-12.0.3 - 2023-08-09
>>>
>>> * Avoid deep imports from balena-auth [Thodoris Greasidis]
>>> * Update balena-auth to 5.1.0 [Thodoris Greasidis]
>>>
>>
>> </details>
>>
>>
>> #### balena-sdk-18.1.2 - 2023-08-23
>>
>> * organization-invite: Fix throwing a typed error when passing an unkonwn role [Thodoris Greasidis]
>> * application-invite: Fix throwing a typed error when passing an unkonwn role [Thodoris Greasidis]
>> * tests: Fix bugs that linting surfaced [Thodoris Greasidis]
>> * Update @balena/lint to 7.0.1 [Thodoris Greasidis]
>>
>> #### balena-sdk-18.1.1 - 2023-08-22
>>
>> * logs: Emit errors when initializing the SDK with debug: true [Thodoris Greasidis]
>>
>> #### balena-sdk-18.1.0 - 2023-08-22
>>
>> * Improve the auth.getActorId() tests [Thodoris Greasidis]
>> * auth.getUserInfo: Add the actor id to the returned values [Thodoris Greasidis]
>>
>> #### balena-sdk-18.0.2 - 2023-08-18
>>
>> * patch: bump lint-staged from 13.3.0 to 14.0.0 [Thodoris Greasidis]
>>
>> #### balena-sdk-18.0.1 - 2023-08-18
>>
>> * Replace dependabot with renovate [Thodoris Greasidis]
>>
>
> </details>
>
>
> ### balena-image-manager-10.0.0 - 2023-10-26
>
> * Drop support for Node.js v16 [Otávio Jacobi]
>
> ### balena-image-manager-9.0.3 - 2023-10-26
>
> * Update @balena/lint [Otávio Jacobi]
> * Bump rimraf [Otávio Jacobi]
>
> ### balena-preload-15.0.1 - 2023-10-26
>
>
> <details>
> <summary> Update balena-sdk to 19.0.1 [Otávio Jacobi] </summary>
>
>> #### balena-sdk-19.0.1 - 2023-10-19
>>
>> * Fix test workflow to run on node 18 [Otávio Jacobi]
>>
>> #### balena-sdk-19.0.0 - 2023-10-16
>>
>>
>> <details>
>> <summary> **BREAKING**: Drop support to node < 18 [Otávio Jacobi] </summary>
>>
>>> ##### balena-register-device-9.0.1 - 2023-10-11
>>>
>>> * Fix balena-request peer dependency [Otávio Jacobi]
>>>
>>> ##### balena-register-device-9.0.0 - 2023-10-11
>>>
>>> * Drop supoport for node 14 & 16 [Otávio Jacobi]
>>>
>>> ##### balena-request-13.0.0 - 2023-10-11
>>>
>>> * Drop support for node 14 & 16 [Otávio Jacobi]
>>>
>>
>> </details>
>>
>>
>> #### balena-sdk-18.3.0 - 2023-10-09
>>
>> * jwt: Deprecate the profile fields in favor of the user_profile [Thodoris Greasidis]
>> * jwt: Deprecate the intercom fields [Thodoris Greasidis]
>> * jwt: Deprecate the features fields [Thodoris Greasidis]
>> * jwt: Deprecate thw loginAs field [Thodoris Greasidis]
>> * jwt: Deprecate username & created_at in favor of the user resource [Thodoris Greasidis]
>> * Add typings for the user_profile resource [Thodoris Greasidis]
>>
>> #### balena-sdk-18.2.0 - 2023-09-26
>>
>> * Update @balena/lint to 7.2.0 [Thodoris Greasidis]
>> * Deprecate the social_service_account property of the JWTUser [Thodoris Greasidis]
>> * Add typings for the social_service_account resource [Thodoris Greasidis]
>>
>> #### balena-sdk-18.1.4 - 2023-08-24
>>
>> * Update TypeScript to 5.2.2 [Thodoris Greasidis]
>>
>> #### balena-sdk-18.1.3 - 2023-08-23
>>
>> * tests/os: Refactor some promise tests to async await [Thodoris Greasidis]
>> * Fix os.getSupervisorReleaseByDeviceType test to work on balenaMachine [Thodoris Greasidis]
>>
>> <details>
>> <summary> Update balena-request from 12.0.2 to 12.0.4 [Thodoris Greasidis] </summary>
>>
>>> ##### balena-request-12.0.4 - 2023-08-23
>>>
>>> * Refactor the interceptors to stop using .reduce() [Thodoris Greasidis]
>>>
>>> ##### balena-request-12.0.3 - 2023-08-09
>>>
>>> * Avoid deep imports from balena-auth [Thodoris Greasidis]
>>> * Update balena-auth to 5.1.0 [Thodoris Greasidis]
>>>
>>
>> </details>
>>
>>
>> #### balena-sdk-18.1.2 - 2023-08-23
>>
>> * organization-invite: Fix throwing a typed error when passing an unkonwn role [Thodoris Greasidis]
>> * application-invite: Fix throwing a typed error when passing an unkonwn role [Thodoris Greasidis]
>> * tests: Fix bugs that linting surfaced [Thodoris Greasidis]
>> * Update @balena/lint to 7.0.1 [Thodoris Greasidis]
>>
>> #### balena-sdk-18.1.1 - 2023-08-22
>>
>> * logs: Emit errors when initializing the SDK with debug: true [Thodoris Greasidis]
>>
>> #### balena-sdk-18.1.0 - 2023-08-22
>>
>> * Improve the auth.getActorId() tests [Thodoris Greasidis]
>> * auth.getUserInfo: Add the actor id to the returned values [Thodoris Greasidis]
>>
>> #### balena-sdk-18.0.2 - 2023-08-18
>>
>> * patch: bump lint-staged from 13.3.0 to 14.0.0 [Thodoris Greasidis]
>>
>> #### balena-sdk-18.0.1 - 2023-08-18
>>
>> * Replace dependabot with renovate [Thodoris Greasidis]
>>
>
> </details>
>
>
> ### balena-preload-15.0.0 - 2023-10-26
>
> * Drop support for Node.js v16 [Otávio Jacobi]
>
</details>
## 17.2.0 - 2023-10-20
* release: Add '--json' option for JSON output [Brian Bugh]
## 17.1.7 - 2023-10-20
* tag set: Fix using empty string as a value [Thodoris Greasidis]
* env add: Fix using empty string as a value [Thodoris Greasidis]
* Add tests for empty & non-provided value for the `env add` command [Thodoris Greasidis]
* Add tests for the `tag set` command [Thodoris Greasidis]
## 17.1.6 - 2023-10-18
* Allow custom actions for external contributors [Kyle Harding]
## 17.1.5 - 2023-10-05
* Fix ssh ignoreStdin device argument [Otávio Jacobi]

View File

@ -115,14 +115,28 @@ The content sources for the auto generation of `docs/balena-cli.md` are:
* [Selected
sections](https://github.com/balena-io/balena-cli/blob/v12.23.0/automation/capitanodoc/capitanodoc.ts#L199-L204)
of the README file.
* The CLI's command documentation in source code (`lib/commands/` folder), for example:
* `lib/commands/push.ts`
* `lib/commands/env/add.ts`
* The CLI's command documentation in source code (`src/commands/` folder), for example:
* `src/commands/push.ts`
* `src/commands/env/add.ts`
The README file is manually edited, but subsections are automatically extracted for inclusion in
`docs/balena-cli.md` by the `getCapitanoDoc()` function in
[`automation/capitanodoc/capitanodoc.ts`](https://github.com/balena-io/balena-cli/blob/master/automation/capitanodoc/capitanodoc.ts).
**IMPORTANT**
The file [`capitanodoc.ts`](https://github.com/balena-io/balena-cli/blob/master/automation/capitanodoc/capitanodoc.ts) lists
commands to generate documentation from. At the moment, it's manually updated and maintained alphabetically.
To add a new command to be documented,
1. Find the resource which it is part of or create a new one.
2. List the location of the build file
3. Make sure to add your files in alphabetical order
4. Resources with plural names needs to have 2 sections if they have commands like: "fleet, fleets" or "device, devices" or "tag, tags"
Once added, run the command `npm run build` to generate the documentation
The `INSTALL*.md` and `TROUBLESHOOTING.md` files are also manually edited.
## Patches folder
@ -210,7 +224,7 @@ command, or by manually editing or copying files to the `node_modules` folder.
Unexpected behavior may then be observed because of the CLI's use of the
[fast-boot2](https://www.npmjs.com/package/fast-boot2) package that caches module resolution.
`fast-boot2` is configured in `lib/fast-boot.ts` to automatically invalidate the cache if
`fast-boot2` is configured in `src/fast-boot.ts` to automatically invalidate the cache if
changes are made to the `package.json` or `npm-shrinkwrap.json` files, but the cache won't
be automatically invalidated if `npm link` is used or if manual modifications are made to the
`node_modules` folder. In this situation:

View File

@ -40,7 +40,7 @@ By default, the CLI is installed to the following folders:
OS | Folders
--- | ---
Windows: | `C:\Program Files\balena-cli\`
macOS: | `/usr/local/lib/balena-cli/` <br> `/usr/local/bin/balena`
macOS: | `/usr/local/src/balena-cli/` <br> `/usr/local/bin/balena`
## Standalone Zip Package
@ -78,8 +78,8 @@ If you are a Node.js developer, you may wish to install the balena CLI via [npm]
The npm installation involves building native (platform-specific) binary modules, which require
some development tools to be installed first, as follows.
> **The balena CLI currently requires Node.js version 18.**
> **Versions 19 and later are not yet fully supported.**
> **The balena CLI currently requires Node.js version ^20.6.0**
> **Versions 21 and later are not yet fully supported.**
### Install development tools
@ -89,7 +89,7 @@ some development tools to be installed first, as follows.
$ sudo apt-get update && sudo apt-get -y install curl python3 git make g++
$ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.38.0/install.sh | bash
$ . ~/.bashrc
$ nvm install 18
$ nvm install 20
```
The `curl` command line above uses
@ -106,7 +106,7 @@ recommended.
```sh
$ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.38.0/install.sh | bash
$ . ~/.bashrc
$ nvm install 18
$ nvm install 20
```
#### **Windows** (not WSL)
@ -114,7 +114,7 @@ $ nvm install 18
Install:
* If you'd like the ability to switch between Node.js versions, install
- Node.js v18 from the [Nodejs.org releases page](https://nodejs.org/en/download/releases/).
- Node.js v20 from the [Nodejs.org releases page](https://nodejs.org/en/download/releases/).
[nvm-windows](https://github.com/coreybutler/nvm-windows#node-version-manager-nvm-for-windows)
instead.
* The [MSYS2 shell](https://www.msys2.org/), which provides `git`, `make`, `g++` and more:

View File

@ -27,7 +27,7 @@ To update the balena CLI, repeat the steps above for the new version.
To uninstall it, run the following command on a terminal prompt:
```text
sudo /usr/local/lib/balena-cli/bin/uninstall
sudo /usr/local/src/balena-cli/bin/uninstall
```
## Additional Dependencies

View File

@ -15,17 +15,16 @@
* limitations under the License.
*/
import type { JsonVersions } from '../lib/commands/version';
import type { JsonVersions } from '../src/commands/version/index';
import { run as oclifRun } from '@oclif/core';
import * as archiver from 'archiver';
import * as Bluebird from 'bluebird';
import { execFile } from 'child_process';
import { exec, execFile } from 'child_process';
import * as filehound from 'filehound';
import { Stats } from 'fs';
import type { Stats } from 'fs';
import * as fs from 'fs-extra';
import * as klaw from 'klaw';
import * as _ from 'lodash';
import * as path from 'path';
import * as rimraf from 'rimraf';
import * as semver from 'semver';
@ -42,6 +41,7 @@ import {
} from './utils';
const execFileAsync = promisify(execFile);
const execAsync = promisify(exec);
export const packageJSON = loadPackageJson();
export const version = 'v' + packageJSON.version;
@ -61,9 +61,13 @@ const standaloneZips: PathByPlatform = {
win32: dPath(`balena-cli-${version}-windows-${arch}-standalone.zip`),
};
const oclifInstallers: PathByPlatform = {
darwin: dPath('macos', `balena-${version}.pkg`),
win32: dPath('win32', `balena-${version}-${arch}.exe`),
const getOclifInstallersOriginalNames = async (): Promise<PathByPlatform> => {
const { stdout } = await execAsync('git rev-parse --short HEAD');
const sha = stdout.trim();
return {
darwin: dPath('macos', `balena-${version}-${sha}-${arch}.pkg`),
win32: dPath('win32', `balena-${version}-${sha}-${arch}.exe`),
};
};
const renamedOclifInstallers: PathByPlatform = {
@ -156,7 +160,7 @@ ${sep}
* messages (stdout and stderr) in order to call diffPkgOutput().
*/
async function execPkg(...args: any[]) {
const { exec: pkgExec } = await import('pkg');
const { exec: pkgExec } = await import('@yao-pkg/pkg');
const outTap = new StdOutTap(true);
try {
outTap.tap();
@ -183,10 +187,10 @@ async function execPkg(...args: any[]) {
async function buildPkg() {
// https://github.com/vercel/pkg#targets
let targets = `linux-${arch}`;
// TBC: not possible to build for macOS or Windows arm64 on x64 nodes
if (process.platform === 'darwin') {
targets = `macos-x64`;
targets = `macos-${arch}`;
}
// TBC: not yet possible to build for Windows arm64 on x64 nodes
if (process.platform === 'win32') {
targets = `win-x64`;
}
@ -322,7 +326,11 @@ async function zipPkg() {
});
}
async function signFilesForNotarization() {
export async function signFilesForNotarization() {
console.log('Signing files for notarization');
if (process.platform !== 'darwin') {
return;
}
console.log('Deleting unneeded zip files...');
await new Promise((resolve, reject) => {
klaw('node_modules/')
@ -422,6 +430,7 @@ export async function buildStandaloneZip() {
}
async function renameInstallerFiles() {
const oclifInstallers = await getOclifInstallersOriginalNames();
if (await fs.pathExists(oclifInstallers[process.platform])) {
await fs.rename(
oclifInstallers[process.platform],
@ -436,18 +445,20 @@ async function renameInstallerFiles() {
* https://learn.microsoft.com/en-us/dotnet/framework/tools/signtool-exe
*/
async function signWindowsInstaller() {
if (process.env.CSC_LINK && process.env.CSC_KEY_PASSWORD) {
if (process.env.SM_CODE_SIGNING_CERT_SHA1_HASH) {
const exeName = renamedOclifInstallers[process.platform];
console.log(`Signing installer "${exeName}"`);
// trust ...
await execFileAsync('signtool.exe', [
'sign',
'-t',
'-sha1',
process.env.SM_CODE_SIGNING_CERT_SHA1_HASH,
'-tr',
process.env.TIMESTAMP_SERVER || 'http://timestamp.comodoca.com',
'-f',
process.env.CSC_LINK,
'-p',
process.env.CSC_KEY_PASSWORD,
'-td',
'SHA256',
'-fd',
'SHA256',
'-d',
`balena-cli ${version}`,
exeName,
@ -492,7 +503,7 @@ export async function buildOclifInstaller() {
let packOpts = ['-r', ROOT];
if (process.platform === 'darwin') {
packOS = 'macos';
packOpts = packOpts.concat('--targets', 'darwin-x64');
packOpts = packOpts.concat('--targets', `darwin-${arch}`);
} else if (process.platform === 'win32') {
packOS = 'win';
packOpts = packOpts.concat('--targets', 'win32-x64');
@ -508,10 +519,6 @@ export async function buildOclifInstaller() {
console.log(`rimraf(${dir})`);
await Bluebird.fromCallback((cb) => rimraf(dir, cb));
}
if (process.platform === 'darwin') {
console.log('Signing files for notarization...');
await signFilesForNotarization();
}
console.log('=======================================================');
console.log(`oclif ${packCmd} ${packOpts.join(' ')}`);
console.log(`cwd="${process.cwd()}" ROOT="${ROOT}"`);

View File

@ -17,6 +17,7 @@
import * as path from 'path';
import { MarkdownFileParser } from './utils';
import { GlobSync } from 'glob';
/**
* This is the skeleton of CLI documentation/reference web page at:
@ -24,173 +25,120 @@ import { MarkdownFileParser } from './utils';
*
* The `getCapitanoDoc` function in this module parses README.md and adds
* some content to this object.
*
* IMPORTANT
*
* All commands need to be stored under a folder in src/commands to maintain uniformity
* Generating docs will error out if directive not followed
* To add a custom heading for command docs, add the heading next to the folder name
* in the `commandHeadings` dictionary.
*
* This dictionary is the source of truth that creates the docs config which is used
* to generate the CLI documentation. By default, the folder name will be used.
*
* Resources with plural names needs to have 2 sections if they have commands like:
* "fleet, fleets" or "device, devices" or "tag, tags"
*
*/
const capitanoDoc = {
title: 'balena CLI Documentation',
introduction: '',
categories: [
{
title: 'API keys',
files: ['build/commands/api-key/generate.js'],
},
{
title: 'Fleet',
files: [
'build/commands/fleets.js',
'build/commands/fleet/index.js',
'build/commands/fleet/create.js',
'build/commands/fleet/purge.js',
'build/commands/fleet/rename.js',
'build/commands/fleet/restart.js',
'build/commands/fleet/rm.js',
],
},
{
title: 'Authentication',
files: [
'build/commands/login.js',
'build/commands/logout.js',
'build/commands/whoami.js',
],
},
{
title: 'Device',
files: [
'build/commands/devices/index.js',
'build/commands/devices/supported.js',
'build/commands/device/index.js',
'build/commands/device/deactivate.js',
'build/commands/device/identify.js',
'build/commands/device/init.js',
'build/commands/device/local-mode.js',
'build/commands/device/move.js',
'build/commands/device/os-update.js',
'build/commands/device/public-url.js',
'build/commands/device/purge.js',
'build/commands/device/reboot.js',
'build/commands/device/register.js',
'build/commands/device/rename.js',
'build/commands/device/restart.js',
'build/commands/device/rm.js',
'build/commands/device/shutdown.js',
],
},
{
title: 'Releases',
files: [
'build/commands/releases.js',
'build/commands/release/index.js',
'build/commands/release/finalize.js',
],
},
{
title: 'Environment Variables',
files: [
'build/commands/envs.js',
'build/commands/env/add.js',
'build/commands/env/rename.js',
'build/commands/env/rm.js',
],
},
{
title: 'Tags',
files: [
'build/commands/tags.js',
'build/commands/tag/rm.js',
'build/commands/tag/set.js',
],
},
{
title: 'Help and Version',
files: ['help', 'build/commands/version.js'],
},
{
title: 'Keys',
files: [
'build/commands/keys.js',
'build/commands/key/index.js',
'build/commands/key/add.js',
'build/commands/key/rm.js',
],
},
{
title: 'Logs',
files: ['build/commands/logs.js'],
},
{
title: 'Network',
files: [
'build/commands/scan.js',
'build/commands/ssh.js',
'build/commands/tunnel.js',
],
},
{
title: 'Notes',
files: ['build/commands/note.js'],
},
{
title: 'OS',
files: [
'build/commands/os/build-config.js',
'build/commands/os/configure.js',
'build/commands/os/versions.js',
'build/commands/os/download.js',
'build/commands/os/initialize.js',
],
},
{
title: 'Config',
files: [
'build/commands/config/generate.js',
'build/commands/config/inject.js',
'build/commands/config/read.js',
'build/commands/config/reconfigure.js',
'build/commands/config/write.js',
],
},
{
title: 'Preload',
files: ['build/commands/preload.js'],
},
{
title: 'Push',
files: ['build/commands/push.js'],
},
{
title: 'Settings',
files: ['build/commands/settings.js'],
},
{
title: 'Local',
files: [
'build/commands/local/configure.js',
'build/commands/local/flash.js',
],
},
{
title: 'Deploy',
files: ['build/commands/build.js', 'build/commands/deploy.js'],
},
{
title: 'Platform',
files: ['build/commands/join.js', 'build/commands/leave.js'],
},
{
title: 'Utilities',
files: ['build/commands/util/available-drives.js'],
},
{
title: 'Support',
files: ['build/commands/support.js'],
},
],
interface Category {
title: string;
files: string[];
}
interface Documentation {
title: string;
introduction: string;
categories: Category[];
}
// Mapping folders names to custom headings in the docs
const commandHeadings: { [key: string]: string } = {
'api-key': 'API Keys',
'api-keys': 'API Keys',
login: 'Authentication',
whoami: 'Authentication',
logout: 'Authentication',
env: 'Environment Variables',
envs: 'Environment Variables',
help: 'Help and Version',
key: 'SSH Keys',
keys: 'SSH Keys',
orgs: 'Organizations',
os: 'OS',
util: 'Utilities',
ssh: 'Network',
scan: 'Network',
tunnel: 'Network',
build: 'Deploy',
join: 'Platform',
leave: 'Platform',
app: 'Apps',
block: 'Blocks',
device: 'Devices',
fleet: 'Fleets',
release: 'Releases',
tag: 'Tags',
};
// Fetch all available commands
const allCommandsPaths = new GlobSync('build/commands/**/*.js', {
ignore: 'build/commands/internal/**',
}).found;
// Throw error if any commands found outside of command directories
const illegalCommandPaths = allCommandsPaths.filter((commandPath: string) =>
/^build\/commands\/[^/]+\.js$/.test(commandPath),
);
if (illegalCommandPaths.length !== 0) {
throw new Error(
`Found the following commands without a command directory: ${illegalCommandPaths}\n
To resolve this error, move the respective commands to their resource directories or create new ones.\n
Refer to the automation/capitanodoc/capitanodoc.ts file for more information.`,
);
}
// Docs config template
const capitanoDoc: Documentation = {
title: 'balena CLI Documentation',
introduction: '',
categories: [],
};
// Helper function to capitalize each word of directory name
function formatTitle(dir: string): string {
return dir.replace(/(^\w|\s\w)/g, (word) => word.toUpperCase());
}
// Create a map to track the categories for faster lookup
const categoriesMap: { [key: string]: Category } = {};
for (const commandPath of allCommandsPaths) {
const commandDir = path.basename(path.dirname(commandPath));
const heading = commandHeadings[commandDir] || formatTitle(commandDir);
if (!categoriesMap[heading]) {
categoriesMap[heading] = { title: heading, files: [] };
capitanoDoc.categories.push(categoriesMap[heading]);
}
categoriesMap[heading].files.push(commandPath);
}
// Sort Category titles alphabetically
capitanoDoc.categories = capitanoDoc.categories.sort((a, b) =>
a.title.localeCompare(b.title),
);
// Sort Category file paths alphabetically
capitanoDoc.categories.forEach((category) => {
category.files.sort((a, b) => a.localeCompare(b));
});
/**
* Modify and return the `capitanoDoc` object above in order to render the
* CLI documentation/reference web page at:
* https://www.balena.io/docs/reference/cli/
* Modify and return the `capitanoDoc` object above in order to generate the
* CLI documentation at docs/balena-cli.md
*
* This function parses the README.md file to extract relevant sections
* for the documentation web page.

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Command as OclifCommandClass } from '@oclif/core';
import type { Command as OclifCommandClass } from '@oclif/core';
type OclifCommand = typeof OclifCommandClass;

View File

@ -16,9 +16,9 @@
*/
import * as path from 'path';
import { getCapitanoDoc } from './capitanodoc';
import { Category, Document, OclifCommand } from './doc-types';
import type { Category, Document, OclifCommand } from './doc-types';
import * as markdown from './markdown';
import { stripIndent } from '../../lib/utils/lazy';
import { stripIndent } from '../../src/utils/lazy';
/**
* Generates the markdown document (as a string) for the CLI documentation
@ -39,7 +39,7 @@ export async function renderMarkdown(): Promise<string> {
};
for (const jsFilename of commandCategory.files) {
category.commands.push(...importOclifCommands(jsFilename));
category.commands.push(...(await importOclifCommands(jsFilename)));
}
result.categories.push(category);
}
@ -78,7 +78,9 @@ class FakeHelpCommand {
};
}
function importOclifCommands(jsFilename: string): OclifCommand[] {
async function importOclifCommands(
jsFilename: string,
): Promise<OclifCommand[]> {
// TODO: Currently oclif commands with no `usage` overridden will cause
// an error when parsed. This should be improved so that `usage` does not have
// to be overridden if not necessary.
@ -86,7 +88,8 @@ function importOclifCommands(jsFilename: string): OclifCommand[] {
const command: OclifCommand =
jsFilename === 'help'
? (new FakeHelpCommand() as unknown as OclifCommand)
: (require(path.join(process.cwd(), jsFilename)).default as OclifCommand);
: ((await import(path.join(process.cwd(), jsFilename)))
.default as OclifCommand);
return [command];
}
@ -104,5 +107,5 @@ async function printMarkdown() {
}
}
// tslint:disable-next-line:no-floating-promises
// eslint-disable-next-line @typescript-eslint/no-floating-promises
printMarkdown();

View File

@ -18,9 +18,9 @@ import { Parser } from '@oclif/core';
import * as ent from 'ent';
import * as _ from 'lodash';
import { getManualSortCompareFunction } from '../../lib/utils/helpers';
import { capitanoizeOclifUsage } from '../../lib/utils/oclif-utils';
import { Category, Document, OclifCommand } from './doc-types';
import { getManualSortCompareFunction } from '../../src/utils/helpers';
import { capitanoizeOclifUsage } from '../../src/utils/oclif-utils';
import type { Category, Document, OclifCommand } from './doc-types';
function renderOclifCommand(command: OclifCommand): string[] {
const result = [`## ${ent.encode(command.usage || '')}`];

View File

@ -15,41 +15,9 @@
* limitations under the License.
*/
import type { OptionDefinition } from 'capitano';
import * as ent from 'ent';
import * as fs from 'fs';
import * as readline from 'readline';
export function getOptionPrefix(signature: string) {
if (signature.length > 1) {
return '--';
} else {
return '-';
}
}
export function getOptionSignature(signature: string) {
return `${getOptionPrefix(signature)}${signature}`;
}
export function parseCapitanoOption(option: OptionDefinition): string {
let result = getOptionSignature(option.signature);
if (Array.isArray(option.alias)) {
for (const alias of option.alias) {
result += `, ${getOptionSignature(alias)}`;
}
} else if (typeof option.alias === 'string') {
result += `, ${getOptionSignature(option.alias)}`;
}
if (option.parameter) {
result += ` <${option.parameter}>`;
}
return ent.encode(result);
}
export class MarkdownFileParser {
constructor(public mdFilePath: string) {}

View File

@ -15,7 +15,7 @@
* limitations under the License.
*/
// tslint:disable-next-line:import-blacklist
// eslint-disable-next-line no-restricted-imports
import { stripIndent } from 'common-tags';
import * as _ from 'lodash';
import { promises as fs } from 'fs';
@ -43,8 +43,8 @@ async function checkBuildTimestamps() {
...gitStatus.staged,
...gitStatus.renamed.map((o) => o.to),
])
// select only staged files that start with lib/ or typings/
.filter((f) => f.match(/^(lib|typings)[/\\]/))
// select only staged files that start with src/ or typings/
.filter((f) => f.match(/^(src|typings)[/\\]/))
.map((f) => path.join(ROOT, f));
const fStats = await Promise.all(stagedFiles.map((f) => fs.stat(f)));
@ -82,5 +82,5 @@ async function run() {
}
}
// tslint:disable-next-line:no-floating-promises
// eslint-disable-next-line @typescript-eslint/no-floating-promises
run();

View File

@ -23,8 +23,8 @@ function parseSemver(version) {
* @param {string} v2
*/
function semverGte(v1, v2) {
let v1Array = parseSemver(v1);
let v2Array = parseSemver(v2);
const v1Array = parseSemver(v1);
const v2Array = parseSemver(v2);
for (let i = 0; i < 3; i++) {
if (v1Array[i] < v2Array[i]) {
return false;

View File

@ -15,59 +15,17 @@
* limitations under the License.
*/
import * as Bluebird from 'bluebird';
import * as _ from 'lodash';
import * as semver from 'semver';
import { finalReleaseAssets, version } from './build-bin';
import { Octokit } from '@octokit/rest';
import { throttling } from '@octokit/plugin-throttling';
const { GITHUB_TOKEN } = process.env;
/**
* Create or update a release in GitHub's releases page, uploading the
* installer files (standalone zip + native oclif installers).
*/
export async function createGitHubRelease() {
console.log(`Publishing release ${version} to GitHub`);
const publishRelease = await import('publish-release');
const ghRelease = await Bluebird.fromCallback(
publishRelease.bind(null, {
token: GITHUB_TOKEN || '',
owner: 'balena-io',
repo: 'balena-cli',
tag: version,
name: `balena-CLI ${version}`,
reuseRelease: true,
assets: finalReleaseAssets[process.platform],
}),
);
console.log(`Release ${version} successful: ${ghRelease.html_url}`);
}
/**
* Top-level function to create a CLI release in GitHub's releases page:
* call zipStandaloneInstaller(), rename the files as we'd like them to
* display on the releases page, and call createGitHubRelease() to upload
* the files.
*/
export async function release() {
try {
await createGitHubRelease();
} catch (err) {
throw new Error(`Error creating GitHub release:\n${err}`);
}
}
/** Return a cached Octokit instance, creating a new one as needed. */
const getOctokit = _.once(function () {
const Octokit = (
require('@octokit/rest') as typeof import('@octokit/rest')
).Octokit.plugin(
(
require('@octokit/plugin-throttling') as typeof import('@octokit/plugin-throttling')
).throttling,
);
return new Octokit({
const OctokitConstructor = Octokit.plugin(throttling);
return new OctokitConstructor({
auth: GITHUB_TOKEN,
throttle: {
onRateLimit: (retryAfter: number, options: any) => {
@ -103,16 +61,16 @@ const getOctokit = _.once(function () {
* 'pages' is the total number of pages, and 'ordinal' is the ordinal number
* (3rd, 4th, 5th...) of the first item in the current page.
*/
function getPageNumbers(
async function getPageNumbers(
response: any,
perPageDefault: number,
): { page: number; pages: number; ordinal: number } {
): Promise<{ page: number; pages: number; ordinal: number }> {
const res = { page: 1, pages: 1, ordinal: 1 };
if (!response.headers.link) {
return res;
}
const parse =
require('parse-link-header') as typeof import('parse-link-header');
const parse = await import('parse-link-header');
const parsed = parse(response.headers.link);
if (parsed == null) {
throw new Error(`Failed to parse link header: '${response.headers.link}'`);
@ -122,13 +80,13 @@ function getPageNumbers(
if (parsed.next.per_page) {
perPage = parseInt(parsed.next.per_page, 10);
}
res.page = parseInt(parsed.next.page, 10) - 1;
res.pages = parseInt(parsed.last.page, 10);
res.page = parseInt(parsed.next.page!, 10) - 1;
res.pages = parseInt(parsed.last!.page!, 10);
} else {
if (parsed.prev.per_page) {
perPage = parseInt(parsed.prev.per_page, 10);
if (parsed.prev!.per_page) {
perPage = parseInt(parsed.prev!.per_page, 10);
}
res.page = res.pages = parseInt(parsed.prev.page, 10) + 1;
res.page = res.pages = parseInt(parsed.prev!.page!, 10) + 1;
}
res.ordinal = (res.page - 1) * perPage + 1;
return res;
@ -154,7 +112,7 @@ async function updateGitHubReleaseDescriptions(
) {
const perPage = 30;
const octokit = getOctokit();
const options = await octokit.repos.listReleases.endpoint.merge({
const options = octokit.repos.listReleases.endpoint.merge({
owner,
repo,
per_page: perPage,
@ -167,7 +125,7 @@ async function updateGitHubReleaseDescriptions(
page: thisPage,
pages: totalPages,
ordinal,
} = getPageNumbers(response, perPage);
} = await getPageNumbers(response, perPage);
let i = 0;
for (const cliRelease of response.data) {
const prefix = `[#${ordinal + i++} pg ${thisPage}/${totalPages}]`;

View File

@ -21,12 +21,10 @@ import {
buildOclifInstaller,
buildStandaloneZip,
catchUncommitted,
signFilesForNotarization,
testShrinkwrap,
} from './build-bin';
import {
release,
updateDescriptionOfReleasesAffectedByIssue1359,
} from './deploy-bin';
import { updateDescriptionOfReleasesAffectedByIssue1359 } from './deploy-bin';
// DEBUG set to falsy for negative values else is truthy
process.env.DEBUG = ['0', 'no', 'false', '', undefined].includes(
@ -40,7 +38,6 @@ process.env.DEBUG = ['0', 'no', 'false', '', undefined].includes(
* of the following strings, then call the appropriate functions:
* 'build:installer' (to build a native oclif installer)
* 'build:standalone' (to build a standalone pkg package)
* 'release' (to create/update a GitHub release)
*
* @param args Arguments to parse (default is process.argv.slice(2))
*/
@ -54,32 +51,17 @@ async function parse(args?: string[]) {
const commands: { [cmd: string]: () => void | Promise<void> } = {
'build:installer': buildOclifInstaller,
'build:standalone': buildStandaloneZip,
'sign:binaries': signFilesForNotarization,
'catch-uncommitted': catchUncommitted,
'test-shrinkwrap': testShrinkwrap,
fix1359: updateDescriptionOfReleasesAffectedByIssue1359,
release,
};
for (const arg of args) {
if (!commands.hasOwnProperty(arg)) {
if (!Object.hasOwn(commands, arg)) {
throw new Error(`command unknown: ${arg}`);
}
}
// The BUILD_TMP env var is used as an alternative location for oclif
// (patched) to copy/extract the CLI files, run npm install and then
// create the NSIS executable installer for Windows. This was necessary
// to avoid issues with a 260-char limit on Windows paths (possibly a
// limitation of some library used by NSIS), as the "current working dir"
// provided by balena CI is a rather long path to start with.
if (process.platform === 'win32' && !process.env.BUILD_TMP) {
const randID = (await import('crypto'))
.randomBytes(6)
.toString('base64')
.replace(/\+/g, '-')
.replace(/\//g, '_'); // base64url (RFC 4648)
process.env.BUILD_TMP = `C:\\tmp\\${randID}`;
}
for (const arg of args) {
try {
const cmdFunc = commands[arg];
@ -103,5 +85,5 @@ export async function run(args?: string[]) {
}
}
// tslint:disable-next-line:no-floating-promises
// eslint-disable-next-line @typescript-eslint/no-floating-promises
run();

View File

@ -107,11 +107,11 @@ async function $main() {
const changeType = process.argv[4]
? // if the caller specified a change type, use that one
validateChangeType(process.argv[4])
validateChangeType(process.argv[4])
: // use the same change type as in the dependency, but avoid major bumps
semverChangeType && semverChangeType !== 'major'
? semverChangeType
: 'minor';
semverChangeType && semverChangeType !== 'major'
? semverChangeType
: 'minor';
console.log(`Using Change-type: ${changeType}`);
let { stdout: currentBranch } = await run('git rev-parse --abbrev-ref HEAD');
@ -136,5 +136,5 @@ async function main() {
}
}
// tslint:disable-next-line:no-floating-promises
// eslint-disable-next-line @typescript-eslint/no-floating-promises
main();

View File

@ -16,8 +16,9 @@
*/
import { spawn } from 'child_process';
import * as _ from 'lodash';
import * as path from 'path';
import * as fs from 'fs';
import { diffTrimmedLines } from 'diff';
export const ROOT = path.join(__dirname, '..');
@ -65,7 +66,6 @@ export class StdOutTap {
* https://www.npmjs.com/package/diff
*/
export function diffLines(str1: string, str2: string): string {
const { diffTrimmedLines } = require('diff');
const diffObjs = diffTrimmedLines(str1, str2);
const prefix = (chunk: string, char: string) =>
chunk
@ -77,15 +77,18 @@ export function diffLines(str1: string, str2: string): string {
return part.added
? prefix(part.value, '+')
: part.removed
? prefix(part.value, '-')
: prefix(part.value, ' ');
? prefix(part.value, '-')
: prefix(part.value, ' ');
})
.join('\n');
return diffStr;
}
export function loadPackageJson() {
return require(path.join(ROOT, 'package.json'));
const packageJsonPath = path.join(ROOT, 'package.json');
const packageJson = fs.readFileSync(packageJsonPath, 'utf8');
return JSON.parse(packageJson);
}
/**

View File

@ -1,23 +0,0 @@
#!/usr/bin/env node
// tslint:disable:no-var-requires
// We boost the threadpool size as ext2fs can deadlock with some
// operations otherwise, if the pool runs out.
process.env.UV_THREADPOOL_SIZE = '64';
// Disable oclif registering ts-node
process.env.OCLIF_TS_NODE = 0;
async function run() {
// Use fast-boot to cache require lookups, speeding up startup
await require('../build/fast-boot').start();
// Set the desired es version for downstream modules that support it
require('@balena/es-version').set('es2018');
// Run the CLI
await require('../build/app').run();
}
run();

1
bin/balena Symbolic link
View File

@ -0,0 +1 @@
run.js

View File

@ -1,89 +0,0 @@
#!/usr/bin/env node
// ****************************************************************************
// THIS IS FOR DEV PURPOSES ONLY AND WILL NOT BE PART OF THE PUBLISHED PACKAGE
// Before opening a PR you should build and test your changes using bin/balena
// ****************************************************************************
// tslint:disable:no-var-requires
// We boost the threadpool size as ext2fs can deadlock with some
// operations otherwise, if the pool runs out.
process.env.UV_THREADPOOL_SIZE = '64';
// Note on `fast-boot2`: We do not use `fast-boot2` with `balena-dev` because:
// * fast-boot2's cacheKiller option is configured to include the timestamps of
// the package.json and npm-shrinkwrap.json files, to avoid unexpected CLI
// behavior when changes are made to dependencies during development. This is
// generally a good thing, however, `balena-dev` (a few lines below) edits
// `package.json` to modify oclif paths, and this results in cache
// invalidation and a performance hit rather than speedup.
// * Even if the timestamps are removed from cacheKiller, so that there is no
// cache invalidation, fast-boot's speedup is barely noticeable when ts-node
// is used, e.g. 1.43s vs 1.4s when running `balena version`.
// * `fast-boot` causes unexpected behavior when used with `npm link` or
// when the `node_modules` folder is manually modified (affecting transitive
// dependencies) during development (e.g. bug investigations). A workaround
// is to use `balena-dev` without `fast-boot`. See also notes in
// `CONTRIBUTING.md`.
const path = require('path');
const rootDir = path.join(__dirname, '..');
// Allow balena-dev to work with oclif by temporarily
// pointing oclif config options to lib/ instead of build/
modifyOclifPaths();
// Undo changes on exit
process.on('exit', function () {
modifyOclifPaths(true);
});
// Undo changes in case of ctrl-c
process.on('SIGINT', function () {
modifyOclifPaths(true);
// Note process exit here will interfere with commands that do their own SIGINT handling,
// but without it commands can not be exited.
// So currently using balena-dev does not guarantee proper exit behaviour when using ctrl-c.
// Ideally a better solution is needed.
process.exit();
});
// Set the desired es version for downstream modules that support it
require('@balena/es-version').set('es2018');
// Note: before ts-node v6.0.0, 'transpile-only' (no type checking) was the
// default option. We upgraded ts-node and found that adding 'transpile-only'
// was necessary to avoid a mysterious 'null' error message. On the plus side,
// it is supposed to run faster. We still benefit from type checking when
// running 'npm run build'.
require('ts-node').register({
project: path.join(rootDir, 'tsconfig.json'),
transpileOnly: true,
});
require('../lib/app').run();
// Modify package.json oclif paths from build/ -> lib/, or vice versa
function modifyOclifPaths(revert) {
const fs = require('fs');
const packageJsonPath = path.join(rootDir, 'package.json');
const packageJson = fs.readFileSync(packageJsonPath, 'utf8');
const packageObj = JSON.parse(packageJson);
if (!packageObj.oclif) {
return;
}
let oclifSectionText = JSON.stringify(packageObj.oclif);
if (!revert) {
oclifSectionText = oclifSectionText.replace(/\/build\//g, '/lib/');
} else {
oclifSectionText = oclifSectionText.replace(/\/lib\//g, '/build/');
}
packageObj.oclif = JSON.parse(oclifSectionText);
fs.writeFileSync(
packageJsonPath,
`${JSON.stringify(packageObj, null, 2)}\n`,
'utf8',
);
}

1
bin/balena-dev Symbolic link
View File

@ -0,0 +1 @@
dev.js

3
bin/dev.cmd Normal file
View File

@ -0,0 +1,3 @@
@echo off
node "%~dp0\run" %*

87
bin/dev.js Executable file
View File

@ -0,0 +1,87 @@
#!/usr/bin/env node
// ****************************************************************************
// THIS IS FOR DEV PURPOSES ONLY AND WILL NOT BE PART OF THE PUBLISHED PACKAGE
// Before opening a PR you should build and test your changes using bin/balena
// ****************************************************************************
// We boost the threadpool size as ext2fs can deadlock with some
// operations otherwise, if the pool runs out.
process.env.UV_THREADPOOL_SIZE = '64';
// Note on `fast-boot2`: We do not use `fast-boot2` with `balena-dev` because:
// * fast-boot2's cacheKiller option is configured to include the timestamps of
// the package.json and npm-shrinkwrap.json files, to avoid unexpected CLI
// behavior when changes are made to dependencies during development. This is
// generally a good thing, however, `balena-dev` (a few lines below) edits
// `package.json` to modify oclif paths, and this results in cache
// invalidation and a performance hit rather than speedup.
// * Even if the timestamps are removed from cacheKiller, so that there is no
// cache invalidation, fast-boot's speedup is barely noticeable when ts-node
// is used, e.g. 1.43s vs 1.4s when running `balena version`.
// * `fast-boot` causes unexpected behavior when used with `npm link` or
// when the `node_modules` folder is manually modified (affecting transitive
// dependencies) during development (e.g. bug investigations). A workaround
// is to use `balena-dev` without `fast-boot`. See also notes in
// `CONTRIBUTING.md`.
const path = require('path');
const rootDir = path.join(__dirname, '..');
// Allow balena-dev to work with oclif by temporarily
// pointing oclif config options to src/ instead of build/
modifyOclifPaths();
// Undo changes on exit
process.on('exit', function () {
modifyOclifPaths(true);
});
// Undo changes in case of ctrl-c
process.on('SIGINT', function () {
modifyOclifPaths(true);
// Note process exit here will interfere with commands that do their own SIGINT handling,
// but without it commands can not be exited.
// So currently using balena-dev does not guarantee proper exit behaviour when using ctrl-c.
// Ideally a better solution is needed.
process.exit();
});
// Set the desired es version for downstream modules that support it
require('@balena/es-version').set('es2018');
// Note: before ts-node v6.0.0, 'transpile-only' (no type checking) was the
// default option. We upgraded ts-node and found that adding 'transpile-only'
// was necessary to avoid a mysterious 'null' error message. On the plus side,
// it is supposed to run faster. We still benefit from type checking when
// running 'npm run build'.
require('ts-node').register({
project: path.join(rootDir, 'tsconfig.json'),
transpileOnly: true,
});
require('../src/app').run(undefined, { dir: __dirname, development: true });
// Modify package.json oclif paths from build/ -> src/, or vice versa
function modifyOclifPaths(revert) {
const fs = require('fs');
const packageJsonPath = path.join(rootDir, 'package.json');
const packageJson = fs.readFileSync(packageJsonPath, 'utf8');
const packageObj = JSON.parse(packageJson);
if (!packageObj.oclif) {
return;
}
let oclifSectionText = JSON.stringify(packageObj.oclif);
if (!revert) {
oclifSectionText = oclifSectionText.replace(/\/build\//g, '/src/');
} else {
oclifSectionText = oclifSectionText.replace(/\/src\//g, '/build/');
}
packageObj.oclif = JSON.parse(oclifSectionText);
fs.writeFileSync(
packageJsonPath,
`${JSON.stringify(packageObj, null, 2)}\n`,
'utf8',
);
}

3
bin/run.cmd Normal file
View File

@ -0,0 +1,3 @@
@echo off
node "%~dp0\run" %*

21
bin/run.js Executable file
View File

@ -0,0 +1,21 @@
#!/usr/bin/env node
// We boost the threadpool size as ext2fs can deadlock with some
// operations otherwise, if the pool runs out.
process.env.UV_THREADPOOL_SIZE = '64';
// Disable oclif registering ts-node
process.env.OCLIF_TS_NODE = 0;
async function run() {
// Use fast-boot to cache require lookups, speeding up startup
await require('../build/fast-boot').start();
// Set the desired es version for downstream modules that support it
require('@balena/es-version').set('es2018');
// Run the CLI
await require('../build/app').run(undefined, { dir: __dirname });
}
run();

View File

@ -8,13 +8,13 @@ _balena() {
local context state line curcontext="$curcontext"
# Valid top-level completions
main_commands=( build deploy envs fleets join keys leave login logout logs note orgs preload push releases scan settings ssh support tags tunnel version whoami api-key api-keys app block config device device devices env fleet fleet internal key key local os release release tag util )
main_commands=( api-key api-keys app block build config deploy device devices env envs fleet fleets internal join key keys leave local login logout logs notes orgs os preload push release releases scan settings ssh support tag tags tunnel util version whoami )
# Sub-completions
api_key_cmds=( generate revoke )
app_cmds=( create )
block_cmds=( create )
config_cmds=( generate inject read reconfigure write )
device_cmds=( deactivate identify init local-mode move os-update pin public-url purge reboot register rename restart rm shutdown track-fleet )
device_cmds=( deactivate identify init local-mode move os-update pin public-url purge reboot register rename restart rm shutdown start-service stop-service track-fleet )
devices_cmds=( supported )
env_cmds=( add rename rm )
fleet_cmds=( create pin purge rename restart rm track-latest )
@ -22,7 +22,7 @@ _balena() {
key_cmds=( add rm )
local_cmds=( configure flash )
os_cmds=( build-config configure download initialize versions )
release_cmds=( finalize invalidate validate )
release_cmds=( export finalize import invalidate validate )
tag_cmds=( rm set )

View File

@ -7,13 +7,13 @@ _balena_complete()
local cur prev
# Valid top-level completions
main_commands="build deploy envs fleets join keys leave login logout logs note orgs preload push releases scan settings ssh support tags tunnel version whoami api-key api-keys app block config device device devices env fleet fleet internal key key local os release release tag util"
main_commands="api-key api-keys app block build config deploy device devices env envs fleet fleets internal join key keys leave local login logout logs notes orgs os preload push release releases scan settings ssh support tag tags tunnel util version whoami"
# Sub-completions
api_key_cmds="generate revoke"
app_cmds="create"
block_cmds="create"
config_cmds="generate inject read reconfigure write"
device_cmds="deactivate identify init local-mode move os-update pin public-url purge reboot register rename restart rm shutdown track-fleet"
device_cmds="deactivate identify init local-mode move os-update pin public-url purge reboot register rename restart rm shutdown start-service stop-service track-fleet"
devices_cmds="supported"
env_cmds="add rename rm"
fleet_cmds="create pin purge rename restart rm track-latest"
@ -21,7 +21,7 @@ _balena_complete()
key_cmds="add rm"
local_cmds="configure flash"
os_cmds="build-config configure download initialize versions"
release_cmds="finalize invalidate validate"
release_cmds="export finalize import invalidate validate"
tag_cmds="rm set"

View File

@ -31,9 +31,9 @@ if (fs.existsSync(commandsFilePath)) {
const commandsJson = JSON.parse(fs.readFileSync(commandsFilePath, 'utf8'));
var mainCommands = [];
var additionalCommands = [];
for (const key of Object.keys(commandsJson.commands)) {
const mainCommands = [];
const additionalCommands = [];
for (const key of Object.keys(commandsJson.commands).sort()) {
const cmd = key.split(':');
if (cmd.length > 1) {
additionalCommands.push(cmd);
@ -72,8 +72,8 @@ fs.readFile(bashFilePathIn, 'utf8', function (err, data) {
/\$main_commands\$/g,
'main_commands="' + mainCommandsStr + '"',
);
var subCommands = [];
var prevElement = additionalCommands[0][0];
let subCommands = [];
let prevElement = additionalCommands[0][0];
additionalCommands.forEach(function (element) {
if (element[0] === prevElement) {
subCommands.push(element[1]);
@ -134,8 +134,8 @@ fs.readFile(zshFilePathIn, 'utf8', function (err, data) {
/\$main_commands\$/g,
'main_commands=( ' + mainCommandsStr + ' )',
);
var subCommands = [];
var prevElement = additionalCommands[0][0];
let subCommands = [];
let prevElement = additionalCommands[0][0];
additionalCommands.forEach(function (element) {
if (element[0] === prevElement) {
subCommands.push(element[1]);

File diff suppressed because it is too large Load Diff

View File

@ -1,19 +0,0 @@
/*
Copyright 2020 Balena
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import type { DataOutputOptions, DataSetOutputOptions } from './output';
export { DataOutputOptions, DataSetOutputOptions };

View File

@ -1,158 +0,0 @@
/*
Copyright 2020 Balena
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import { getCliUx, getChalk } from '../utils/lazy';
export interface DataOutputOptions {
fields?: string;
json?: boolean;
}
export interface DataSetOutputOptions extends DataOutputOptions {
filter?: string;
'no-header'?: boolean;
'no-truncate'?: boolean;
sort?: string;
}
/**
* Output message to STDERR
*/
export function outputMessage(msg: string) {
// Messages go to STDERR
console.error(msg);
}
/**
* Output result data to STDOUT
* Supports:
* - arrays of items (displayed in a tabular way),
* - single items (displayed in a field per row format).
*
* @param data Array of data objects to output
* @param fields Array of fieldnames, specifying the fields and display order
* @param options Output options
*/
export async function outputData(
data: any[] | {},
fields: string[],
options: DataOutputOptions | DataSetOutputOptions,
) {
if (Array.isArray(data)) {
await outputDataSet(data, fields, options as DataSetOutputOptions);
} else {
await outputDataItem(data, fields, options as DataOutputOptions);
}
}
/**
* Wraps the cli.ux table implementation, to output tabular data
*
* @param data Array of data objects to output
* @param fields Array of fieldnames, specifying the fields and display order
* @param options Output options
*/
async function outputDataSet(
data: any[],
fields: string[],
options: DataSetOutputOptions,
) {
// Oclif expects fields to be specified in the format used in table headers (though lowercase)
// By replacing underscores with spaces here, we can support both header format and actual field name
// (e.g. as seen in json output).
options.fields = options.fields?.replace(/_/g, ' ');
options.filter = options.filter?.replace(/_/g, ' ');
options.sort = options.sort?.replace(/_/g, ' ');
getCliUx().table(
data,
// Convert fields array to column object keys
// that cli.ux expects. We can later add support
// for both formats if beneficial
fields.reduce((ac, a) => ({ ...ac, [a]: {} }), {}),
{
...options,
...(options.json
? {
output: 'json',
}
: {}),
columns: options.fields,
printLine,
},
);
}
/**
* Outputs a single data object (like `resin-cli-visuals table.vertical`),
* but supporting a subset of options from `cli-ux table` (--json and --fields)
*
* @param data Array of data objects to output
* @param fields Array of fieldnames, specifying the fields and display order
* @param options Output options
*/
async function outputDataItem(
data: any,
fields: string[],
options: DataOutputOptions,
) {
const outData: typeof data = {};
// Convert comma separated list of fields in `options.fields` to array of correct format.
// Note, user may have specified the true field name (e.g. `some_field`),
// or the format displayed in headers (e.g. `Some field`, case insensitive).
const userSelectedFields = options.fields?.split(',').map((f) => {
return f.toLowerCase().trim().replace(/ /g, '_');
});
// Order and filter the fields based on `fields` parameter and `options.fields`
(userSelectedFields || fields).forEach((fieldName) => {
if (fields.includes(fieldName)) {
outData[fieldName] = data[fieldName];
}
});
if (options.json) {
printLine(JSON.stringify(outData, undefined, 2));
} else {
const chalk = getChalk();
const { capitalize } = await import('lodash');
// Find longest key, so we can align results
const longestKeyLength = getLongestObjectKeyLength(outData);
// Output one field per line
for (const [k, v] of Object.entries(outData)) {
const shim = ' '.repeat(longestKeyLength - k.length);
const kDisplay = capitalize(k.replace(/_/g, ' '));
printLine(`${chalk.bold(kDisplay) + shim} : ${v}`);
}
}
}
function getLongestObjectKeyLength(o: any): number {
return Object.keys(o).length >= 1
? Object.keys(o).reduce((a, b) => {
return a.length > b.length ? a : b;
}).length
: 0;
}
function printLine(s: any) {
// Duplicating oclif cli-ux's default implementation here,
// but using this one explicitly for ease of testing
process.stdout.write(s + '\n');
}

View File

@ -1,40 +0,0 @@
import { enumerateServices, findServices } from 'resin-discoverable-services';
interface LocalBalenaOsDevice {
address: string;
host: string;
osVariant?: string;
port: number;
}
// Although we only check for 'balena-ssh', we know, implicitly, that balenaOS
// devices come with 'rsync' installed that can be used over SSH.
const avahiBalenaSshTag = 'resin-ssh';
export async function discoverLocalBalenaOsDevices(
timeout = 4000,
): Promise<LocalBalenaOsDevice[]> {
const availableServices = await enumerateServices();
const serviceDefinitions = Array.from(availableServices)
.filter((s) => Array.from(s.tags).includes(avahiBalenaSshTag))
.map((s) => s.service);
if (serviceDefinitions.length === 0) {
throw new Error(
`Could not find any available '${avahiBalenaSshTag}' services`,
);
}
const services = await findServices(serviceDefinitions, timeout);
return services.map(function (service) {
// User referer address to get device IP. This will work fine assuming that
// a device only advertises own services.
const {
referer: { address },
host,
port,
} = service;
return { address, host, port };
});
}

35775
npm-shrinkwrap.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{
"name": "balena-cli",
"version": "17.1.5",
"version": "19.0.3",
"description": "The official balena Command Line Interface",
"main": "./build/app.js",
"homepage": "https://github.com/balena-io/balena-cli",
@ -14,14 +14,15 @@
"bin/",
"build/",
"doc/",
"lib/",
"src/",
"patches/",
"!patches/**/**.dev.patch",
"*.md",
"npm-shrinkwrap.json",
"oclif.manifest.json"
],
"bin": {
"balena": "./bin/balena"
"balena": "./bin/run.js"
},
"pkg": {
"scripts": [
@ -32,13 +33,13 @@
],
"assets": [
"build/auth/pages/*.ejs",
"node_modules/resin-discoverable-services/services/**/*",
"node_modules/balena-sdk/node_modules/balena-pine/**/*",
"node_modules/balena-pine/**/*",
"node_modules/pinejs-client-core/**/*",
"node_modules/open/xdg-open",
"node_modules/windosu/*.bat",
"node_modules/windosu/*.cmd",
"node_modules/axios/**/*",
"npm-shrinkwrap.json",
"oclif.manifest.json"
]
@ -46,10 +47,11 @@
"scripts": {
"postinstall": "node patches/apply-patches.js",
"prebuild": "rimraf build/ build-bin/",
"pretarball": "ts-node --transpile-only ../../automation/run.ts sign:binaries",
"build": "npm run build:src && npm run catch-uncommitted",
"build:t": "npm run lint && npm run build:fast && npm run build:test",
"build:src": "npm run lint && npm run build:fast && npm run build:test && npm run build:doc && npm run build:completion",
"build:pages": "mkdirp ./build/auth/pages/&& inline-source --compress ./lib/auth/pages/error.ejs ./build/auth/pages/error.ejs && inline-source --compress ./lib/auth/pages/success.ejs ./build/auth/pages/success.ejs",
"build:pages": "mkdirp ./build/auth/pages/&& inline-source --compress ./src/auth/pages/error.ejs ./build/auth/pages/error.ejs && inline-source --compress ./src/auth/pages/success.ejs ./build/auth/pages/success.ejs",
"build:fast": "npm run build:pages && tsc && npx oclif manifest",
"build:test": "tsc -P ./tsconfig.dev.json --noEmit",
"build:doc": "ts-node --transpile-only automation/capitanodoc/index.ts > docs/balena-cli.md",
@ -57,23 +59,24 @@
"build:standalone": "ts-node --transpile-only automation/run.ts build:standalone",
"build:installer": "ts-node --transpile-only automation/run.ts build:installer",
"package": "npm run build:fast && npm run build:standalone && npm run build:installer",
"release": "ts-node --transpile-only automation/run.ts release",
"pretest": "npm run build",
"test": "npm run test:shrinkwrap && npm run test:source && npm run test:standalone",
"test": "npm run test:shrinkwrap && npm run test:core",
"test:core": "npm run test:source && npm run test:standalone",
"test:shrinkwrap": "ts-node --transpile-only automation/run.ts test-shrinkwrap",
"test:source": "cross-env BALENA_CLI_TEST_TYPE=source mocha",
"test:standalone": "npm run build:standalone && npm run test:standalone:fast",
"test:standalone:fast": "cross-env BALENA_CLI_TEST_TYPE=standalone mocha --config .mocharc-standalone.js",
"test:fast": "npm run build:fast && npm run test:source",
"test:fast-profile": "npm run test:fast -- -- --inspect-brk=0.0.0.0",
"test:debug": "cross-env BALENA_CLI_TEST_TYPE=source mocha --inspect-brk=0.0.0.0",
"test:only": "npm run build:fast && cross-env BALENA_CLI_TEST_TYPE=source mocha \"tests/**/${npm_config_test}.spec.ts\"",
"catch-uncommitted": "ts-node --transpile-only automation/run.ts catch-uncommitted",
"ci": "npm run test && npm run catch-uncommitted",
"lint": "npm run lint-tsconfig && npm run lint-other",
"lint-tsconfig": "balena-lint -e ts -e js -t tsconfig.dev.json --fix automation/ lib/ tests/ typings/",
"lint-other": "balena-lint -e ts -e js --fix bin/balena bin/balena-dev completion/ .mocharc.js .mocharc-standalone.js",
"lint-tsconfig": "balena-lint -e ts -e js -t tsconfig.dev.json --fix automation/ src/ tests/ typings/",
"lint-other": "balena-lint -e ts -e js --fix bin/run.js bin/dev.js completion/ .mocharc.js .mocharc-standalone.js",
"update": "ts-node --transpile-only ./automation/update-module.ts",
"prepare": "echo {} > bin/.fast-boot.json",
"prepare": "echo {} > bin/.fast-boot.json && husky",
"prepublishOnly": "npm run build"
},
"keywords": [
@ -88,17 +91,13 @@
"author": "Balena Inc. (https://balena.io/)",
"license": "Apache-2.0",
"engines": {
"node": ">=18 <20"
},
"husky": {
"hooks": {
"pre-commit": "node automation/check-npm-version.js && ts-node automation/check-doc.ts"
}
"node": "^20.6.0"
},
"oclif": {
"bin": "balena",
"commands": "./build/commands",
"helpClass": "./build/help",
"topicSeparator": " ",
"hooks": {
"prerun": "./build/hooks/prerun/track",
"command_not_found": "./build/hooks/command-not-found/suggest"
@ -108,25 +107,27 @@
],
"macos": {
"identifier": "io.balena.cli",
"sign": "Developer ID Installer: Balena Ltd (66H43P8FRG)"
"sign": "\"Developer ID Installer: Balena Ltd (66H43P8FRG)\""
}
},
"devDependencies": {
"@balena/lint": "^6.2.2",
"@balena/lint": "^8.0.0",
"@electron/notarize": "^2.0.0",
"@octokit/plugin-throttling": "^3.5.1",
"@octokit/rest": "^18.6.7",
"@types/archiver": "^5.1.1",
"@types/archiver": "^6.0.2",
"@types/bluebird": "^3.5.36",
"@types/body-parser": "^1.19.2",
"@types/chai": "^4.3.0",
"@types/chai-as-promised": "^7.1.4",
"@types/cli-truncate": "^2.0.0",
"@types/common-tags": "^1.8.1",
"@types/dockerode": "^3.3.9",
"@types/diff": "^5.0.3",
"@types/dockerode": "3.3.23",
"@types/ejs": "^3.1.0",
"@types/express": "^4.17.13",
"@types/fs-extra": "^9.0.13",
"@types/fast-levenshtein": "^0.0.4",
"@types/fs-extra": "^11.0.4",
"@types/global-agent": "^2.1.1",
"@types/global-tunnel-ng": "^2.1.1",
"@types/http-proxy": "^1.17.8",
@ -134,34 +135,35 @@
"@types/intercept-stdout": "^0.1.0",
"@types/is-root": "^2.1.2",
"@types/js-yaml": "^4.0.5",
"@types/jsonwebtoken": "^8.5.6",
"@types/klaw": "^3.0.3",
"@types/jsonwebtoken": "^9.0.6",
"@types/klaw": "^3.0.6",
"@types/lodash": "^4.14.178",
"@types/mixpanel": "^2.14.3",
"@types/mocha": "^8.2.3",
"@types/mocha": "^10.0.7",
"@types/mock-require": "^2.0.1",
"@types/moment-duration-format": "^2.2.3",
"@types/ndjson": "^2.0.1",
"@types/net-keepalive": "^0.4.1",
"@types/nock": "^11.1.0",
"@types/node": "^18.17.6",
"@types/node": "^20.0.0",
"@types/node-cleanup": "^2.1.2",
"@types/parse-link-header": "^1.0.1",
"@types/prettyjson": "^0.0.30",
"@types/parse-link-header": "^2.0.3",
"@types/prettyjson": "^0.0.33",
"@types/progress-stream": "^2.0.2",
"@types/request": "^2.48.7",
"@types/rewire": "^2.5.28",
"@types/rewire": "^2.5.30",
"@types/rimraf": "^3.0.2",
"@types/semver": "^7.3.9",
"@types/shell-escape": "^0.2.0",
"@types/sinon": "^10.0.6",
"@types/sinon": "^17.0.3",
"@types/split": "^1.0.0",
"@types/stream-to-promise": "^2.2.1",
"@types/tar-stream": "^2.2.2",
"@types/through2": "^2.0.36",
"@types/tmp": "^0.2.3",
"@types/update-notifier": "^4.1.1",
"@types/which": "^2.0.1",
"archiver": "^5.3.0",
"@types/window-size": "^1.1.1",
"@yao-pkg/pkg": "^5.11.1",
"archiver": "^7.0.1",
"catch-uncommitted": "^2.0.0",
"chai": "^4.3.4",
"chai-as-promised": "^7.1.1",
@ -170,60 +172,58 @@
"diff": "^5.0.0",
"ent": "^2.2.0",
"filehound": "^1.17.5",
"fs-extra": "^9.1.0",
"fs-extra": "^11.2.0",
"http-proxy": "^1.18.1",
"husky": "^4.3.8",
"husky": "^9.1.5",
"inline-source-cli": "^2.0.0",
"intercept-stdout": "^0.1.2",
"jsonwebtoken": "^8.5.1",
"mkdirp": "^1.0.4",
"mocha": "^8.4.0",
"jsonwebtoken": "^9.0.0",
"klaw": "^4.1.0",
"mkdirp": "^3.0.1",
"mocha": "^10.6.0",
"mock-require": "^3.0.3",
"nock": "^13.2.1",
"oclif": "^3.17.1",
"oclif": "^4.14.0",
"parse-link-header": "^2.0.0",
"pkg": "^5.8.1",
"publish-release": "^1.6.1",
"rewire": "^5.0.0",
"rewire": "^7.0.0",
"simple-git": "^3.14.1",
"sinon": "^11.1.2",
"sinon": "^18.0.0",
"ts-node": "^10.4.0",
"typescript": "^5.1.3"
"typescript": "^5.5.2"
},
"dependencies": {
"@balena/compose": "^3.0.2",
"@balena/compose": "^4.0.1",
"@balena/dockerignore": "^1.0.2",
"@balena/env-parsing": "^1.1.8",
"@balena/es-version": "^1.0.1",
"@oclif/core": "^2.15.0",
"@balena/release-bundle": "^0.5.2",
"@oclif/core": "^4.0.8",
"@resin.io/valid-email": "^0.1.0",
"@sentry/node": "^6.16.1",
"@types/fast-levenshtein": "0.0.1",
"@types/update-notifier": "^4.1.1",
"balena-config-json": "^4.2.0",
"balena-device-init": "^6.0.0",
"balena-device-init": "^7.0.1",
"balena-errors": "^4.7.3",
"balena-image-fs": "^7.0.6",
"balena-image-manager": "^9.0.2",
"balena-preload": "^14.0.3",
"balena-sdk": "^18.0.0",
"balena-image-manager": "^10.0.1",
"balena-preload": "^15.0.6",
"balena-sdk": "^19.7.3",
"balena-semver": "^2.3.0",
"balena-settings-client": "^5.0.2",
"balena-settings-storage": "^8.1.0",
"bluebird": "^3.7.2",
"body-parser": "^1.19.1",
"bonjour-service": "^1.2.1",
"chalk": "^3.0.0",
"chokidar": "^3.5.2",
"cli-truncate": "^2.1.0",
"color-hash": "^1.1.1",
"columnify": "^1.5.2",
"common-tags": "^1.7.2",
"denymount": "^2.3.0",
"docker-modem": "3.0.0",
"docker-modem": "^5.0.3",
"docker-progress": "^5.1.3",
"dockerode": "3.3.3",
"dockerode": "^4.0.2",
"ejs": "^3.1.6",
"etcher-sdk": "^8.7.0",
"event-stream": "3.3.4",
"etcher-sdk": "9.1.0",
"express": "^4.17.2",
"fast-boot2": "^1.1.0",
"fast-levenshtein": "^3.0.0",
@ -239,25 +239,21 @@
"is-root": "^2.1.0",
"js-yaml": "^4.1.0",
"JSONStream": "^1.0.3",
"klaw": "^3.0.0",
"livepush": "^3.5.1",
"lodash": "^4.17.21",
"minimatch": "^3.0.4",
"moment": "^2.29.1",
"moment-duration-format": "^2.3.2",
"ndjson": "^2.0.0",
"net-keepalive": "^3.0.0",
"node-cleanup": "^2.1.2",
"node-unzip-2": "^0.2.8",
"open": "^7.1.0",
"patch-package": "^6.4.7",
"patch-package": "^8.0.0",
"prettyjson": "^1.2.5",
"progress-stream": "^2.0.0",
"reconfix": "^1.0.0-v0-1-0-fork-46760acff4d165f5238bfac5e464256ef1944476",
"request": "^2.88.2",
"resin-cli-form": "^2.0.2",
"resin-cli-visuals": "^1.8.3",
"resin-discoverable-services": "^2.0.4",
"resin-cli-form": "^3.0.0",
"resin-cli-visuals": "^2.0.0",
"resin-doodles": "^0.2.0",
"resin-stream-logger": "^0.1.2",
"rimraf": "^3.0.2",
@ -279,7 +275,12 @@
"optionalDependencies": {
"windosu": "^0.3.0"
},
"overrides": {
"inline-source-cli": {
"inline-source": "^8.0.3"
}
},
"versionist": {
"publishedAt": "2023-10-05T10:54:32.145Z"
"publishedAt": "2024-09-05T12:34:09.871Z"
}
}

View File

@ -1,106 +0,0 @@
diff --git a/node_modules/@oclif/core/lib/cli-ux/list.js b/node_modules/@oclif/core/lib/cli-ux/list.js
index dc6058c..64b2f85 100644
--- a/node_modules/@oclif/core/lib/cli-ux/list.js
+++ b/node_modules/@oclif/core/lib/cli-ux/list.js
@@ -22,7 +22,7 @@ function renderList(items) {
}
left = left.padEnd(maxLength);
right = linewrap(maxLength + 2, right);
- return `${left} ${right}`;
+ return `${left} : ${right}`;
});
return lines.join('\n');
}
diff --git a/node_modules/@oclif/core/lib/help/command.js b/node_modules/@oclif/core/lib/help/command.js
index 6de139b..3a13197 100644
--- a/node_modules/@oclif/core/lib/help/command.js
+++ b/node_modules/@oclif/core/lib/help/command.js
@@ -206,7 +206,7 @@ class CommandHelp extends formatter_1.HelpFormatter {
if (args.filter(a => a.description).length === 0)
return;
return args.map(a => {
- const name = a.name.toUpperCase();
+ const name = a.required ? `<${a.name}>` : `[${a.name}]`;
let description = a.description || '';
if (a.default)
description = `[default: ${a.default}] ${description}`;
@@ -238,14 +238,12 @@ class CommandHelp extends formatter_1.HelpFormatter {
label = labels.join(', ');
}
if (flag.type === 'option') {
- let value = flag.helpValue || (this.opts.showFlagNameInTitle ? flag.name : '<value>');
+ let value = flag.helpValue || (this.opts.showFlagNameInTitle ? flag.name : `<${flag.name}>`);
if (!flag.helpValue && flag.options) {
value = showOptions || this.opts.showFlagOptionsInTitle ? `${flag.options.join('|')}` : '<option>';
}
if (flag.multiple)
- value += '...';
- if (!value.includes('|'))
- value = underline(value);
+ value += ' ...';
label += `=${value}`;
}
return label;
diff --git a/node_modules/@oclif/core/lib/help/index.js b/node_modules/@oclif/core/lib/help/index.js
index f9ef7cc..a14c67c 100644
--- a/node_modules/@oclif/core/lib/help/index.js
+++ b/node_modules/@oclif/core/lib/help/index.js
@@ -136,11 +136,12 @@ class Help extends HelpBase {
}
this.log(this.formatCommand(command));
this.log('');
- if (subTopics.length > 0) {
+ const SUPPRESS_SUBTOPICS = true;
+ if (subTopics.length > 0 && !SUPPRESS_SUBTOPICS) {
this.log(this.formatTopics(subTopics));
this.log('');
}
- if (subCommands.length > 0) {
+ if (subCommands.length > 0 && !SUPPRESS_SUBTOPICS) {
const aliases = [];
const uniqueSubCommands = subCommands.filter(p => {
aliases.push(...p.aliases);
diff --git a/node_modules/@oclif/core/lib/parser/errors.js b/node_modules/@oclif/core/lib/parser/errors.js
index 07ec8e5..a4560ea 100644
--- a/node_modules/@oclif/core/lib/parser/errors.js
+++ b/node_modules/@oclif/core/lib/parser/errors.js
@@ -10,7 +10,8 @@ var errors_2 = require("../errors");
Object.defineProperty(exports, "CLIError", { enumerable: true, get: function () { return errors_2.CLIError; } });
class CLIParseError extends errors_1.CLIError {
constructor(options) {
- options.message += '\nSee more help with --help';
+ const help = options.command ? `\`${options.command} --help\`` : '--help';
+ options.message += `\nSee more help with ${help}`;
super(options.message);
this.parse = options.parse;
}
@@ -31,7 +32,8 @@ class InvalidArgsSpecError extends CLIParseError {
exports.InvalidArgsSpecError = InvalidArgsSpecError;
class RequiredArgsError extends CLIParseError {
constructor({ args, parse, flagsWithMultiple }) {
- let message = `Missing ${args.length} required arg${args.length === 1 ? '' : 's'}`;
+ const command = 'balena ' + parse.input.context.id.replace(/:/g, ' ');
+ let message = `Missing ${args.length} required argument${args.length === 1 ? '' : 's'}`;
const namedArgs = args.filter(a => a.name);
if (namedArgs.length > 0) {
const list = (0, list_1.renderList)(namedArgs.map(a => [a.name, a.description]));
@@ -42,16 +44,17 @@ class RequiredArgsError extends CLIParseError {
message += `\n\nNote: ${flags} allow${flagsWithMultiple.length === 1 ? 's' : ''} multiple values. Because of this you need to provide all arguments before providing ${flagsWithMultiple.length === 1 ? 'that flag' : 'those flags'}.`;
message += '\nAlternatively, you can use "--" to signify the end of the flags and the beginning of arguments.';
}
- super({ parse, message });
+ super({ parse, message, command });
this.args = args;
}
}
exports.RequiredArgsError = RequiredArgsError;
class RequiredFlagError extends CLIParseError {
constructor({ flag, parse }) {
+ const command = 'balena ' + parse.input.context.id.replace(/:/g, ' ');
const usage = (0, list_1.renderList)((0, help_1.flagUsages)([flag], { displayRequired: false }));
const message = `Missing required flag:\n${usage}`;
- super({ parse, message });
+ super({ parse, message, command });
this.flag = flag;
}
}

View File

@ -0,0 +1,79 @@
diff --git a/node_modules/@oclif/core/lib/help/command.js b/node_modules/@oclif/core/lib/help/command.js
index 90922c8..6b7f417 100644
--- a/node_modules/@oclif/core/lib/help/command.js
+++ b/node_modules/@oclif/core/lib/help/command.js
@@ -58,7 +58,8 @@ class CommandHelp extends formatter_1.HelpFormatter {
return;
return args.map((a) => {
// Add ellipsis to indicate that the argument takes multiple values if strict is false
- const name = this.command.strict === false ? `${a.name.toUpperCase()}...` : a.name.toUpperCase();
+ let name = this.command.strict === false ? `${a.name.toUpperCase()}...` : a.name.toUpperCase();
+ name = a.required ? `<${name}>` : `[${name}]`;
let description = a.description || '';
if (a.default)
description = `${(0, theme_1.colorize)(this.config?.theme?.flagDefaultValue, `[default: ${a.default}]`)} ${description}`;
diff --git a/node_modules/@oclif/core/lib/help/index.js b/node_modules/@oclif/core/lib/help/index.js
index 4a34b89..d7eb6ac 100644
--- a/node_modules/@oclif/core/lib/help/index.js
+++ b/node_modules/@oclif/core/lib/help/index.js
@@ -172,11 +172,12 @@ class Help extends HelpBase {
}
this.log(this.formatCommand(command));
this.log('');
- if (subTopics.length > 0) {
+ const SUPPRESS_SUBTOPICS = true;
+ if (subTopics.length > 0 && !SUPPRESS_SUBTOPICS) {
this.log(this.formatTopics(subTopics));
this.log('');
}
- if (subCommands.length > 0) {
+ if (subCommands.length > 0 && !SUPPRESS_SUBTOPICS) {
const aliases = [];
const uniqueSubCommands = subCommands.filter((p) => {
aliases.push(...p.aliases);
diff --git a/node_modules/@oclif/core/lib/parser/errors.js b/node_modules/@oclif/core/lib/parser/errors.js
index 168da99..538a880 100644
--- a/node_modules/@oclif/core/lib/parser/errors.js
+++ b/node_modules/@oclif/core/lib/parser/errors.js
@@ -15,7 +15,8 @@ class CLIParseError extends errors_1.CLIError {
parse;
showHelp = false;
constructor(options) {
- options.message += '\nSee more help with --help';
+ const help = options.command ? `\`${options.command} --help\`` : '--help';
+ options.message += `\nSee more help with ${help}`;
super(options.message, { exit: options.exit });
this.parse = options.parse;
}
@@ -38,7 +39,8 @@ exports.InvalidArgsSpecError = InvalidArgsSpecError;
class RequiredArgsError extends CLIParseError {
args;
constructor({ args, exit, flagsWithMultiple, parse, }) {
- let message = `Missing ${args.length} required arg${args.length === 1 ? '' : 's'}`;
+ const command = 'balena ' + parse.input.context.id.replace(/:/g, ' ');
+ let message = `Missing ${args.length} required argument${args.length === 1 ? '' : 's'}`;
const namedArgs = args.filter((a) => a.name);
if (namedArgs.length > 0) {
const list = (0, list_1.default)(namedArgs.map((a) => {
@@ -52,7 +54,7 @@ class RequiredArgsError extends CLIParseError {
message += `\n\nNote: ${flags} allow${flagsWithMultiple.length === 1 ? 's' : ''} multiple values. Because of this you need to provide all arguments before providing ${flagsWithMultiple.length === 1 ? 'that flag' : 'those flags'}.`;
message += '\nAlternatively, you can use "--" to signify the end of the flags and the beginning of arguments.';
}
- super({ exit: cache_1.default.getInstance().get('exitCodes')?.requiredArgs ?? exit, message, parse });
+ super({ exit: cache_1.default.getInstance().get('exitCodes')?.requiredArgs ?? exit, message, parse, command });
this.args = args;
this.showHelp = true;
}
diff --git a/node_modules/@oclif/core/lib/ux/list.js b/node_modules/@oclif/core/lib/ux/list.js
index 954954c..0e507c7 100644
--- a/node_modules/@oclif/core/lib/ux/list.js
+++ b/node_modules/@oclif/core/lib/ux/list.js
@@ -22,7 +22,7 @@ function renderList(items) {
}
left = left.padEnd(maxLength);
right = linewrap(maxLength + 2, right);
- return `${left} ${right}`;
+ return `${left} : ${right}`;
});
return lines.join('\n');
}

View File

@ -1,285 +0,0 @@
diff --git a/node_modules/oclif/lib/commands/pack/macos.js b/node_modules/oclif/lib/commands/pack/macos.js
index d06d0b3..c571fe3 100644
--- a/node_modules/oclif/lib/commands/pack/macos.js
+++ b/node_modules/oclif/lib/commands/pack/macos.js
@@ -177,7 +177,8 @@ class PackMacos extends core_1.Command {
if (process.env.OSX_KEYCHAIN)
args.push('--keychain', process.env.OSX_KEYCHAIN);
args.push(dist);
- await exec(`pkgbuild ${args.join(' ')}`);
+ console.error(`[debug] oclif pkgbuild "${args.join('" "')}"`);
+ await exec(`pkgbuild "${args.join('" "')}"`);
};
const arches = _.uniq(buildConfig.targets
.filter(t => t.platform === 'darwin')
diff --git a/node_modules/oclif/lib/commands/pack/win.js b/node_modules/oclif/lib/commands/pack/win.js
index c0926bd..a37cd6e 100644
--- a/node_modules/oclif/lib/commands/pack/win.js
+++ b/node_modules/oclif/lib/commands/pack/win.js
@@ -59,6 +59,12 @@ InstallDir "\$PROGRAMFILES${arch === 'x64' ? '64' : ''}\\${config.dirname}"
${customization}
Section "${config.name} CLI \${VERSION}"
+ ; First remove any old client files.
+ ; (Remnants of old versions were causing CLI errors)
+ ; Initially tried running the Uninstall.exe, but was
+ ; unable to make script wait for completion (despite using _?)
+ DetailPrint "Removing files from previous version."
+ RMDir /r "$INSTDIR\\client"
SetOutPath $INSTDIR
File /r bin
File /r client
@@ -226,7 +232,8 @@ class PackWin extends core_1.Command {
fs.writeFile(path.join(installerBase, 'bin', `${flags['additional-cli']}`), scripts.sh({ bin: flags['additional-cli'] })),
] : []));
await fs.move(buildConfig.workspace({ platform: 'win32', arch }), path.join(installerBase, 'client'));
- await exec(`makensis ${installerBase}/${config.bin}.nsi | grep -v "\\[compress\\]" | grep -v "^File: Descending to"`);
+ const { msysExec, toMsysPath } = require("../../util");
+ await msysExec(`makensis ${toMsysPath(installerBase)}/${config.bin}.nsi | grep -v "\\[compress\\]" | grep -v "^File: Descending to"`);
const templateKey = (0, upload_util_1.templateShortKey)('win32', { bin: config.bin, version: config.version, sha: buildConfig.gitSha, arch });
const o = buildConfig.dist(`win32/${templateKey}`);
await fs.move(path.join(installerBase, 'installer.exe'), o);
diff --git a/node_modules/oclif/lib/tarballs/build.js b/node_modules/oclif/lib/tarballs/build.js
index 384ea4b..602daa4 100644
--- a/node_modules/oclif/lib/tarballs/build.js
+++ b/node_modules/oclif/lib/tarballs/build.js
@@ -21,7 +21,8 @@ const pack = async (from, to) => {
await exec(`tar cfJ ${to} ${(path.basename(from))}`, { cwd }));
};
async function build(c, options = {}) {
- const { xz, config } = c;
+ const { xz, config, tmp } = c;
+ console.error(`[debug] oclif c.root="${c.root}" c.workspace()="${c.workspace()}"`);
const packCLI = async () => {
const { stdout } = await exec('npm pack --unsafe-perm', { cwd: c.root });
return path.join(c.root, stdout.trim().split('\n').pop());
@@ -30,7 +31,8 @@ async function build(c, options = {}) {
await fs.emptyDir(c.workspace());
const tarballNewLocation = path.join(c.workspace(), path.basename(tarball));
await fs.move(tarball, tarballNewLocation);
- await exec(`tar -xzf "${tarballNewLocation}"`, { cwd: c.workspace() });
+ const { msysExec, toMsysPath } = require("../util");
+ await msysExec(`tar -xzf ${toMsysPath(tarballNewLocation)}`, { cwd: c.workspace() });
await Promise.all((await fs.promises.readdir(path.join(c.workspace(), 'package'), { withFileTypes: true }))
.map(i => fs.move(path.join(c.workspace(), 'package', i.name), path.join(c.workspace(), i.name))));
await Promise.all([
@@ -38,6 +40,13 @@ async function build(c, options = {}) {
fs.promises.rm(path.join(c.workspace(), path.basename(tarball)), { recursive: true }),
fs.remove(path.join(c.workspace(), 'bin', 'run.cmd')),
]);
+ // rename the original balena-cli ./bin/balena entry point for oclif compatibility
+ await fs.move(path.join(c.workspace(), 'bin', 'balena'), path.join(c.workspace(), 'bin', 'run'));
+ // The oclif installers are a production installation, while the source
+ // `bin` folder may contain a `.fast-boot.json` file of a dev installation.
+ // This has previously led to issues preventing the CLI from starting, so
+ // delete `.fast-boot.json` (if any) from the destination folder.
+ await fs.promises.rm(path.join(c.workspace(), 'bin', '.fast-boot.json'));
};
const updatePJSON = async () => {
const pjsonPath = path.join(c.workspace(), 'package.json');
@@ -49,35 +58,20 @@ async function build(c, options = {}) {
await fs.writeJSON(pjsonPath, pjson, { spaces: 2 });
};
const addDependencies = async () => {
- const yarnRoot = findYarnWorkspaceRoot(c.root) || c.root;
- if (fs.existsSync(path.join(yarnRoot, 'yarn.lock'))) {
- await fs.copy(path.join(yarnRoot, 'yarn.lock'), path.join(c.workspace(), 'yarn.lock'));
- const yarnVersion = (await exec('yarn -v')).stdout.charAt(0);
- if (yarnVersion === '1') {
- await exec('yarn --no-progress --production --non-interactive', { cwd: c.workspace() });
- }
- else if (yarnVersion === '2') {
- throw new Error('Yarn 2 is not supported yet. Try using Yarn 1, or Yarn 3');
- }
- else {
- try {
- await exec('yarn workspaces focus --production', { cwd: c.workspace() });
- }
- catch (error) {
- if (error instanceof Error && error.message.includes('Command not found')) {
- throw new Error('Missing workspace tools. Run `yarn plugin import workspace-tools`.');
- }
- throw error;
- }
- }
- }
- else {
- const lockpath = fs.existsSync(path.join(c.root, 'package-lock.json')) ?
- path.join(c.root, 'package-lock.json') :
- path.join(c.root, 'npm-shrinkwrap.json');
- await fs.copy(lockpath, path.join(c.workspace(), path.basename(lockpath)));
- await exec('npm install --production', { cwd: c.workspace() });
+ const ws = c.workspace();
+ exec(`cd ${ws}`);
+ console.error(`[debug] oclif copying node_modules to "${ws}"`)
+ const source = path.join(c.root, 'node_modules');
+ if (process.platform === 'win32') {
+ await exec(`xcopy "${source}" "${ws}\\node_modules" /S /E /B /I /K /Q /Y`);
+ } else {
+ // use the shell's `cp` on macOS in order to preserve extended
+ // file attributes containing `codesign` digital signatures
+ await exec(`cp -pR "${source}" "${ws}"`);
}
+ console.error(`[debug] oclif running "npm prune --production" in "${ws}"`);
+ await exec('npm prune --production', { cwd: c.workspace() });
+ console.error(`[debug] oclif done`);
};
const pretarball = async () => {
const pjson = await fs.readJSON(path.join(c.workspace(), 'package.json'));
@@ -115,7 +109,8 @@ async function build(c, options = {}) {
output: path.join(workspace, 'bin', 'node'),
platform: target.platform,
arch: target.arch,
- tmp: path.join(config.root, 'tmp'),
+ tmp,
+ projectRootPath: c.root
});
if (options.pack === false)
return;
@@ -158,6 +153,7 @@ async function build(c, options = {}) {
await fs.writeJSON(manifestFilepath, manifest, { spaces: 2 });
};
(0, log_1.log)(`gathering workspace for ${config.bin} to ${c.workspace()}`);
+ console.error(`[debug] ${options.tarball}`);
await extractCLI(options.tarball ? options.tarball : await packCLI());
await updatePJSON();
await addDependencies();
diff --git a/node_modules/oclif/lib/tarballs/config.js b/node_modules/oclif/lib/tarballs/config.js
index 216759d..cab0e6e 100644
--- a/node_modules/oclif/lib/tarballs/config.js
+++ b/node_modules/oclif/lib/tarballs/config.js
@@ -25,7 +25,10 @@ async function gitSha(cwd, options = {}) {
}
exports.gitSha = gitSha;
async function Tmp(config) {
- const tmp = path.join(config.root, 'tmp');
+ const tmp = process.env.BUILD_TMP
+ ? path.join(process.env.BUILD_TMP, 'oclif')
+ : path.join(config.root, 'tmp');
+ console.error(`[debug] oclif tmp="${tmp}"`);
await fs.promises.mkdir(tmp, { recursive: true });
return tmp;
}
@@ -62,7 +65,7 @@ async function buildConfig(root, options = {}) {
s3Config: updateConfig.s3,
nodeVersion,
workspace(target) {
- const base = path.join(config.root, 'tmp');
+ const base = tmp;
if (target && target.platform)
return path.join(base, [target.platform, target.arch].join('-'), (0, upload_util_1.templateShortKey)('baseDir', { bin: config.bin }));
return path.join(base, (0, upload_util_1.templateShortKey)('baseDir', { bin: config.bin }));
diff --git a/node_modules/oclif/lib/tarballs/node.js b/node_modules/oclif/lib/tarballs/node.js
index 35f1d0c..5349eaa 100644
--- a/node_modules/oclif/lib/tarballs/node.js
+++ b/node_modules/oclif/lib/tarballs/node.js
@@ -12,6 +12,7 @@ const retry = require("async-retry");
const util_2 = require("../util");
const pipeline = (0, util_1.promisify)(stream_1.pipeline);
const exec = (0, util_1.promisify)(child_process_1.exec);
+const { isMSYS2, msysExec, toMsysPath } = require("../util");
const RETRY_TIMEOUT_MS = 1000;
async function fetchNodeBinary({ nodeVersion, output, platform, arch, tmp }) {
if (arch === 'arm')
@@ -42,8 +43,10 @@ async function fetchNodeBinary({ nodeVersion, output, platform, arch, tmp }) {
const basedir = path.dirname(tarball);
await fs.promises.mkdir(basedir, { recursive: true });
await pipeline(got_1.default.stream(url), fs.createWriteStream(tarball));
- if (platform !== 'win32')
- await exec(`grep "${path.basename(tarball)}" "${shasums}" | shasum -a 256 -c -`, { cwd: basedir });
+ if (platform !== 'win32') {
+ const shaCmd = isMSYS2 ? 'sha256sum -c -' : 'shasum -a 256 -c -';
+ await msysExec(`grep ${path.basename(tarball)} ${toMsysPath(shasums)} | ${shaCmd}`, { cwd: basedir });
+ }
};
const extract = async () => {
(0, log_1.log)(`extracting ${nodeBase}`);
@@ -51,7 +54,7 @@ async function fetchNodeBinary({ nodeVersion, output, platform, arch, tmp }) {
await fs.promises.mkdir(nodeTmp, { recursive: true });
await fs.promises.mkdir(path.dirname(cache), { recursive: true });
if (platform === 'win32') {
- await exec(`7z x -bd -y "${tarball}"`, { cwd: nodeTmp });
+ await msysExec(`7z x -bd -y ${toMsysPath(tarball)} > /dev/null`, { cwd: nodeTmp });
await fs.move(path.join(nodeTmp, nodeBase, 'node.exe'), path.join(cache, 'node.exe'));
}
else {
diff --git a/node_modules/oclif/lib/upload-util.js b/node_modules/oclif/lib/upload-util.js
index 6963e4d..430472d 100644
--- a/node_modules/oclif/lib/upload-util.js
+++ b/node_modules/oclif/lib/upload-util.js
@@ -31,10 +31,10 @@ options = { root: '.' }) {
const templates = {
baseDir: '<%- bin %>',
unversioned: '<%- bin %>-<%- platform %>-<%- arch %><%- ext %>',
- versioned: '<%- bin %>-v<%- version %>-<%- sha %>-<%- platform %>-<%- arch %><%- ext %>',
- manifest: '<%- bin %>-v<%- version %>-<%- sha %>-<%- platform %>-<%- arch %>-buildmanifest',
- macos: '<%- bin %>-v<%- version %>-<%- sha %>-<%- arch %>.pkg',
- win32: '<%- bin %>-v<%- version %>-<%- sha %>-<%- arch %>.exe',
+ versioned: '<%- bin %>-v<%- version %>-<%- platform %>-<%- arch %><%- ext %>',
+ manifest: '<%- bin %>-v<%- version %>-<%- platform %>-<%- arch %>-buildmanifest',
+ macos: '<%- bin %>-v<%- version %>.pkg',
+ win32: '<%- bin %>-v<%- version %>-<%- arch %>.exe',
deb: '<%- bin %>_<%- versionShaRevision %>_<%- arch %>.deb',
};
return _.template(templates[type])(Object.assign({}, options));
diff --git a/node_modules/oclif/lib/util.js b/node_modules/oclif/lib/util.js
index 816c71b..1384aa6 100644
--- a/node_modules/oclif/lib/util.js
+++ b/node_modules/oclif/lib/util.js
@@ -95,9 +95,10 @@ const hash = async (algo, fp) => {
});
};
exports.hash = hash;
+
async function checkFor7Zip() {
try {
- await exec('7z');
+ await msysExec('7z', { stdio: [0, null, 2] });
}
catch (error) {
if (error.code === 127)
@@ -107,3 +108,44 @@ async function checkFor7Zip() {
}
}
exports.checkFor7Zip = checkFor7Zip;
+
+// OSTYPE is 'msys' for MSYS 1.0 and for MSYS2, or 'cygwin' for Cygwin
+// but note that OSTYPE is not "exported" by default, so run: export OSTYPE=$OSTYPE
+// MSYSTEM is 'MINGW32' for MSYS 1.0, 'MSYS' for MSYS2, and undefined for Cygwin
+const isCygwin = process.env.OSTYPE === 'cygwin';
+const isMinGW = process.env.MSYSTEM && process.env.MSYSTEM.startsWith('MINGW');
+const isMSYS2 = process.env.MSYSTEM && process.env.MSYSTEM.startsWith('MSYS');
+const MSYSSHELLPATH = process.env.MSYSSHELLPATH ||
+ (isMSYS2 ? 'C:\\msys64\\usr\\bin\\bash.exe' :
+ (isMinGW ? 'C:\\MinGW\\msys\\1.0\\bin\\bash.exe' :
+ (isCygwin ? 'C:\\cygwin64\\bin\\bash.exe' : '/bin/sh')));
+
+exports.isCygwin = isCygwin;
+exports.isMinGW = isMinGW;
+exports.isMSYS2 = isMSYS2;
+console.error(`[debug] oclif MSYSSHELLPATH=${MSYSSHELLPATH} MSYSTEM=${process.env.MSYSTEM} OSTYPE=${process.env.OSTYPE} isMSYS2=${isMSYS2} isMingGW=${isMinGW} isCygwin=${isCygwin}`);
+
+/* Convert a Windows path like 'C:\tmp' to a MSYS path like '/c/tmp' */
+function toMsysPath(windowsPath) {
+ // 'c:\myfolder' -> '/c/myfolder' or '/cygdrive/c/myfolder'
+ let msysPath = windowsPath.replace(/\\/g, '/');
+ if (isMSYS2 || isMinGW) {
+ msysPath = msysPath.replace(/^([a-zA-Z]):/, '/$1');
+ } else if (isCygwin) {
+ msysPath = msysPath.replace(/^([a-zA-Z]):/, '/cygdrive/$1');
+ }
+ console.error(`[debug] oclif toMsysPath before="${windowsPath}" after="${msysPath}"`);
+ return msysPath;
+}
+exports.toMsysPath = toMsysPath;
+
+async function msysExec(cmd, options = {}) {
+ if (process.platform !== 'win32') {
+ return exec(cmd, options);
+ }
+ const sh = MSYSSHELLPATH;
+ const args = ['-c', cmd];
+ console.error(`[debug] oclif msysExec sh="${sh}" args=${JSON.stringify(args)} options=${JSON.stringify(options)}`);
+ return exec(`"${sh}" "${args.join('" "')}"`, options);
+}
+exports.msysExec = msysExec;

View File

@ -0,0 +1,35 @@
diff --git a/node_modules/oclif/lib/commands/pack/win.js b/node_modules/oclif/lib/commands/pack/win.js
index ef7f90e..8264b7c 100644
--- a/node_modules/oclif/lib/commands/pack/win.js
+++ b/node_modules/oclif/lib/commands/pack/win.js
@@ -76,6 +76,12 @@ InstallDir "\$PROGRAMFILES${arch === 'x64' ? '64' : ''}\\${config.dirname}"
${customization}
Section "${config.name} CLI \${VERSION}"
+ ; First remove any old client files.
+ ; (Remnants of old versions were causing CLI errors)
+ ; Initially tried running the Uninstall.exe, but was
+ ; unable to make script wait for completion (despite using _?)
+ DetailPrint "Removing files from previous version."
+ RMDir /r "$INSTDIR\\client"
SetOutPath $INSTDIR
File /r bin
File /r client
diff --git a/node_modules/oclif/lib/tarballs/build.js b/node_modules/oclif/lib/tarballs/build.js
index 14d5a6e..7b42a6f 100644
--- a/node_modules/oclif/lib/tarballs/build.js
+++ b/node_modules/oclif/lib/tarballs/build.js
@@ -200,6 +200,13 @@ const extractCLI = async (tarball, c) => {
(0, promises_1.rm)(path.join(workspace, path.basename(tarball)), { recursive: true }),
(0, fs_extra_1.remove)(path.join(workspace, 'bin', 'run.cmd')),
]);
+
+ // The oclif installers are a production installation, while the source
+ // `bin` folder may contain a `.fast-boot.json` file of a dev installation.
+ // This has previously led to issues preventing the CLI from starting, so
+ // delete `.fast-boot.json` (if any) from the destination folder.
+ await (0, fs_extra_1.remove)(path.join(workspace, 'bin', '.fast-boot.json'));
+
};
const buildTarget = async (target, c, options) => {
const workspace = c.workspace(target);

View File

@ -12,7 +12,7 @@ upstream:
url: 'https://github.com/balena-io-modules/balena-preload'
- repo: 'etcher-sdk'
url: 'https://github.com/balena-io-modules/etcher-sdk/'
- repo: 'balena-compose'
- repo: '@balena/compose'
url: 'https://github.com/balena-io-modules/balena-compose'
- repo: 'docker-progress'
url: 'https://github.com/balena-io-modules/docker-progress'

View File

@ -16,15 +16,15 @@
*/
import * as packageJSON from '../package.json';
import type { AppOptions } from './preparser';
import {
AppOptions,
checkDeletedCommand,
preparseArgs,
unsupportedFlag,
} from './preparser';
import { CliSettings } from './utils/bootstrap';
import { onceAsync } from './utils/lazy';
import { run as mainRun } from '@oclif/core';
import { run as mainRun, settings } from '@oclif/core';
/**
* Sentry.io setup
@ -117,7 +117,14 @@ async function oclifRun(command: string[], options: AppOptions) {
const runPromise = (async function (shouldFlush: boolean) {
let isEEXIT = false;
try {
await mainRun(command, options.configPath);
if (options.development) {
// In dev mode -> use ts-node and dev plugins
process.env.NODE_ENV = 'development';
settings.debug = true;
}
// For posteriority: We can't use default oclif 'execute' as
// We customize error handling and flushing
await mainRun(command, options.loadOptions ?? options.dir);
} catch (error) {
// oclif sometimes exits with ExitError code EEXIT 0 (not an error),
// for example the `balena help` command.
@ -130,7 +137,8 @@ async function oclifRun(command: string[], options: AppOptions) {
}
}
if (shouldFlush) {
await import('@oclif/core/flush');
const { flush } = await import('@oclif/core');
await flush();
}
// TODO: figure out why we need to call fast-boot stop() here, in
// addition to calling it in the main `run()` function in this file.
@ -150,8 +158,8 @@ async function oclifRun(command: string[], options: AppOptions) {
await Promise.all([trackPromise, deprecationPromise, runPromise]);
}
/** CLI entrypoint. Called by the `bin/balena` and `bin/balena-dev` scripts. */
export async function run(cliArgs = process.argv, options: AppOptions = {}) {
/** CLI entrypoint. Called by the `bin/run.js` and `bin/dev.js` scripts. */
export async function run(cliArgs = process.argv, options: AppOptions) {
try {
const { setOfflineModeEnvVars, normalizeEnvVars, pkgExec } = await import(
'./utils/bootstrap'

View File

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@ -21,7 +21,6 @@ import {
NotAvailableInOfflineModeError,
} from './errors';
import { stripIndent } from './utils/lazy';
import * as output from './framework/output';
export default abstract class BalenaCommand extends Command {
/**
@ -168,7 +167,4 @@ export default abstract class BalenaCommand extends Command {
await this.getStdin();
}
}
protected outputMessage = output.outputMessage;
protected outputData = output.outputData;
}

View File

@ -52,20 +52,16 @@ export default class RevokeCmd extends Command {
public async run() {
const { args: params } = await this.parse(RevokeCmd);
try {
const apiKeyIds = params.ids.split(',');
if (apiKeyIds.filter((apiKeyId) => !apiKeyId.match(/^\d+$/)).length > 0) {
console.log('API key ids must be positive integers');
return;
}
await Promise.all(
apiKeyIds.map(
async (id) => await getBalenaSdk().models.apiKey.revoke(Number(id)),
),
);
console.log('Successfully revoked the given API keys');
} catch (e) {
throw e;
const apiKeyIds = params.ids.split(',');
if (apiKeyIds.filter((apiKeyId) => !apiKeyId.match(/^\d+$/)).length > 0) {
console.log('API key ids must be positive integers');
return;
}
await Promise.all(
apiKeyIds.map(
async (id) => await getBalenaSdk().models.apiKey.revoke(Number(id)),
),
);
console.log('Successfully revoked the given API keys');
}
}

View File

@ -46,42 +46,38 @@ export default class ApiKeysCmd extends Command {
public async run() {
const { flags: options } = await this.parse(ApiKeysCmd);
try {
const { getApplication } = await import('../../utils/sdk');
const actorId = options.fleet
? (
await getApplication(getBalenaSdk(), options.fleet, {
$select: 'actor',
})
).actor
: await getBalenaSdk().auth.getActorId();
const keys = await getBalenaSdk().pine.get({
resource: 'api_key',
options: {
$select: ['id', 'created_at', 'name', 'description', 'expiry_date'],
$filter: {
is_of__actor: actorId,
...(options.user
? {
name: {
$ne: null,
},
}
: {}),
},
$orderby: 'name asc',
const { getApplication } = await import('../../utils/sdk');
const actorId = options.fleet
? (
await getApplication(getBalenaSdk(), options.fleet, {
$select: 'actor',
})
).actor
: await getBalenaSdk().auth.getActorId();
const keys = await getBalenaSdk().pine.get({
resource: 'api_key',
options: {
$select: ['id', 'created_at', 'name', 'description', 'expiry_date'],
$filter: {
is_of__actor: actorId,
...(options.user
? {
name: {
$ne: null,
},
}
: {}),
},
});
const fields = ['id', 'name', 'created_at', 'description', 'expiry_date'];
const _ = await import('lodash');
console.log(
getVisuals().table.horizontal(
keys.map((key) => _.mapValues(key, (val) => val ?? 'N/a')),
fields,
),
);
} catch (e) {
throw e;
}
$orderby: 'name asc',
},
});
const fields = ['id', 'name', 'created_at', 'description', 'expiry_date'];
const _ = await import('lodash');
console.log(
getVisuals().table.horizontal(
keys.map((key) => _.mapValues(key, (val) => val ?? 'N/a')),
fields,
),
);
}
}

View File

@ -16,20 +16,26 @@
*/
import { Args, Flags } from '@oclif/core';
import Command from '../command';
import { getBalenaSdk } from '../utils/lazy';
import * as cf from '../utils/common-flags';
import * as compose from '../utils/compose';
import type { ApplicationType, BalenaSDK } from 'balena-sdk';
import Command from '../../command';
import { getBalenaSdk } from '../../utils/lazy';
import * as cf from '../../utils/common-flags';
import * as compose from '../../utils/compose';
import type {
ApplicationType,
BalenaSDK,
DeviceType,
PineOptions,
PineTypedResult,
} from 'balena-sdk';
import {
buildArgDeprecation,
dockerignoreHelp,
registrySecretsHelp,
} from '../utils/messages';
import type { ComposeCliFlags, ComposeOpts } from '../utils/compose-types';
import { buildProject, composeCliFlags } from '../utils/compose_ts';
import type { BuildOpts, DockerCliFlags } from '../utils/docker';
import { dockerCliFlags } from '../utils/docker';
} from '../../utils/messages';
import type { ComposeCliFlags, ComposeOpts } from '../../utils/compose-types';
import { buildProject, composeCliFlags } from '../../utils/compose_ts';
import type { BuildOpts, DockerCliFlags } from '../../utils/docker';
import { dockerCliFlags } from '../../utils/docker';
// TODO: For this special one we can't use Interfaces.InferredFlags/InferredArgs
// because of the 'registry-secrets' type which is defined in the actual code
@ -67,6 +73,7 @@ ${dockerignoreHelp}
public static examples = [
'$ balena build --fleet myFleet',
'$ balena build ./source/ --fleet myorg/myfleet',
'$ balena build --deviceType raspberrypi3 --emulated',
'$ balena build --deviceType raspberrypi3 --arch armv7hf --emulated',
'$ balena build --docker /var/run/docker.sock --fleet myFleet # Linux, Mac',
'$ balena build --docker //./pipe/docker_engine --fleet myFleet # Windows',
@ -114,6 +121,8 @@ ${dockerignoreHelp}
options.source = params.source;
delete params.source;
await this.resolveArchFromDeviceType(sdk, options);
await this.validateOptions(options, sdk);
// Build args are under consideration for removal - warn user
@ -127,7 +136,7 @@ ${dockerignoreHelp}
try {
await this.buildProject(docker, logger, composeOpts, {
app,
appType: app?.application_type?.[0],
arch: options.arch!,
deviceType: options.deviceType!,
buildEmulated: options.emulated,
@ -148,14 +157,14 @@ ${dockerignoreHelp}
(opts.fleet == null && (opts.arch == null || opts.deviceType == null)) ||
(opts.fleet != null && (opts.arch != null || opts.deviceType != null))
) {
const { ExpectedError } = await import('../errors');
const { ExpectedError } = await import('../../errors');
throw new ExpectedError(
'You must specify either a fleet (-f), or the device type (-d) and architecture (-A)',
'You must specify either a fleet (-f), or the device type (-d) and optionally the architecture (-A)',
);
}
// Validate project directory
const { validateProjectDirectory } = await import('../utils/compose_ts');
const { validateProjectDirectory } = await import('../../utils/compose_ts');
const { dockerfilePath, registrySecrets } = await validateProjectDirectory(
sdk,
{
@ -170,9 +179,42 @@ ${dockerignoreHelp}
opts['registry-secrets'] = registrySecrets;
}
protected async resolveArchFromDeviceType(sdk: BalenaSDK, opts: FlagsDef) {
if (opts.deviceType != null && opts.arch == null) {
try {
const deviceTypeOpts = {
$select: 'is_of__cpu_architecture',
$expand: {
is_of__cpu_architecture: {
$select: 'slug',
},
},
} satisfies PineOptions<DeviceType>;
opts.arch = (
(await sdk.models.deviceType.get(
opts.deviceType,
deviceTypeOpts,
)) as PineTypedResult<DeviceType, typeof deviceTypeOpts>
).is_of__cpu_architecture[0].slug;
} catch (err) {
const { ExpectedError } = await import('../../errors');
if (err instanceof sdk.errors.BalenaInvalidDeviceType) {
let message = err.message;
if (!(await sdk.auth.isLoggedIn())) {
message = `${message}. In case you are trying to use a private device type, please try to log in first.`;
}
throw new ExpectedError(message);
}
throw new ExpectedError(
'Failed to resolve the architecture of the provided device type. If you are in an air-gapped environment please also define the architecture (-A) parameter.',
);
}
}
}
protected async getAppAndResolveArch(opts: FlagsDef) {
if (opts.fleet) {
const { getAppWithArch } = await import('../utils/helpers');
const { getAppWithArch } = await import('../../utils/helpers');
const app = await getAppWithArch(opts.fleet);
opts.arch = app.arch;
opts.deviceType = app.is_for__device_type[0].slug;
@ -181,7 +223,7 @@ ${dockerignoreHelp}
}
protected async prepareBuild(options: FlagsDef) {
const { getDocker, generateBuildOpts } = await import('../utils/docker');
const { getDocker, generateBuildOpts } = await import('../../utils/docker');
const [docker, buildOpts, composeOpts] = await Promise.all([
getDocker(options),
generateBuildOpts(options),
@ -209,19 +251,17 @@ ${dockerignoreHelp}
*/
protected async buildProject(
docker: import('dockerode'),
logger: import('../utils/logger'),
logger: import('../../utils/logger'),
composeOpts: ComposeOpts,
opts: {
app?: {
application_type: [Pick<ApplicationType, 'supports_multicontainer'>];
};
appType?: Pick<ApplicationType, 'supports_multicontainer'>;
arch: string;
deviceType: string;
buildEmulated: boolean;
buildOpts: BuildOpts;
},
) {
const { loadProject } = await import('../utils/compose_ts');
const { loadProject } = await import('../../utils/compose_ts');
const project = await loadProject(
logger,
@ -230,11 +270,10 @@ ${dockerignoreHelp}
opts.buildOpts.t,
);
const appType = opts.app?.application_type?.[0];
if (
appType != null &&
opts.appType != null &&
project.descriptors.length > 1 &&
!appType.supports_multicontainer
!opts.appType.supports_multicontainer
) {
logger.logWarn(
'Target fleet does not support multiple containers.\n' +

View File

@ -259,6 +259,8 @@ export default class ConfigGenerateCmd extends Command {
if (!options.fleet && options.deviceType) {
throw new ExpectedError(this.deviceTypeNotAllowedMessage);
}
const { normalizeOsVersion } = await import('../../utils/normalization');
options.version = normalizeOsVersion(options.version);
const { validateDevOptionAndWarn } = await import('../../utils/config');
await validateDevOptionAndWarn(options.dev, options.version);
}

View File

@ -18,31 +18,31 @@
import { Args, Flags } from '@oclif/core';
import type { ImageDescriptor } from '@balena/compose/dist/parse';
import Command from '../command';
import { ExpectedError } from '../errors';
import { getBalenaSdk, getChalk, stripIndent } from '../utils/lazy';
import Command from '../../command';
import { ExpectedError } from '../../errors';
import { getBalenaSdk, getChalk, stripIndent } from '../../utils/lazy';
import {
dockerignoreHelp,
registrySecretsHelp,
buildArgDeprecation,
} from '../utils/messages';
import * as ca from '../utils/common-args';
import * as compose from '../utils/compose';
} from '../../utils/messages';
import * as ca from '../../utils/common-args';
import * as compose from '../../utils/compose';
import type {
BuiltImage,
ComposeCliFlags,
ComposeOpts,
Release as ComposeReleaseInfo,
} from '../utils/compose-types';
import type { BuildOpts, DockerCliFlags } from '../utils/docker';
} from '../../utils/compose-types';
import type { BuildOpts, DockerCliFlags } from '../../utils/docker';
import {
applyReleaseTagKeysAndValues,
buildProject,
composeCliFlags,
isBuildConfig,
parseReleaseTagKeysAndValues,
} from '../utils/compose_ts';
import { dockerCliFlags } from '../utils/docker';
} from '../../utils/compose_ts';
import { dockerCliFlags } from '../../utils/docker';
import type { ApplicationType, DeviceType, Release } from 'balena-sdk';
interface ApplicationWithArch {
@ -175,7 +175,7 @@ ${dockerignoreHelp}
const sdk = getBalenaSdk();
const { getRegistrySecrets, validateProjectDirectory } = await import(
'../utils/compose_ts'
'../../utils/compose_ts'
);
const { releaseTagKeys, releaseTagValues } = parseReleaseTagKeysAndValues(
@ -199,10 +199,10 @@ ${dockerignoreHelp}
(options as FlagsDef)['registry-secrets'] = registrySecrets;
}
const helpers = await import('../utils/helpers');
const helpers = await import('../../utils/helpers');
const app = await helpers.getAppWithArch(fleet);
const dockerUtils = await import('../utils/docker');
const dockerUtils = await import('../../utils/docker');
const [docker, buildOpts, composeOpts] = await Promise.all([
dockerUtils.getDocker(options),
dockerUtils.generateBuildOpts(options as FlagsDef),
@ -232,7 +232,7 @@ ${dockerignoreHelp}
async deployProject(
docker: import('dockerode'),
logger: import('../utils/logger'),
logger: import('../../utils/logger'),
composeOpts: ComposeOpts,
opts: {
app: ApplicationWithArch; // the application instance to deploy to
@ -250,7 +250,7 @@ ${dockerignoreHelp}
const doodles = await import('resin-doodles');
const sdk = getBalenaSdk();
const { deployProject: $deployProject, loadProject } = await import(
'../utils/compose_ts'
'../../utils/compose_ts'
);
const appType = opts.app.application_type[0];
@ -332,7 +332,7 @@ ${dockerignoreHelp}
let release: Release | ComposeReleaseInfo['release'];
if (appType.slug === 'legacy-v1' || appType.slug === 'legacy-v2') {
const { deployLegacy } = require('../utils/deploy-legacy');
const { deployLegacy } = require('../../utils/deploy-legacy');
const msg = getChalk().yellow(
'Target fleet requires legacy deploy method.',
@ -364,20 +364,13 @@ ${dockerignoreHelp}
$select: ['commit'],
});
} else {
const [{ id: userId }, auth, apiEndpoint] = await Promise.all([
sdk.auth.getUserInfo(),
sdk.auth.getToken(),
sdk.settings.get('apiUrl'),
]);
release = await $deployProject(
docker,
sdk,
logger,
project.composition,
images,
opts.app.id,
userId,
`Bearer ${auth}`,
apiEndpoint,
!opts.shouldUploadLogs,
composeOpts.projectPath,
opts.createAsDraft,

View File

@ -51,9 +51,8 @@ export default class DeviceDeactivateCmd extends Command {
public static authenticated = true;
public async run() {
const { args: params, flags: options } = await this.parse(
DeviceDeactivateCmd,
);
const { args: params, flags: options } =
await this.parse(DeviceDeactivateCmd);
const balena = getBalenaSdk();
const patterns = await import('../../utils/patterns');

View File

@ -20,6 +20,7 @@ import Command from '../../command';
import * as cf from '../../utils/common-flags';
import { expandForAppName } from '../../utils/helpers';
import { getBalenaSdk, getVisuals, stripIndent } from '../../utils/lazy';
import { jsonInfo } from '../../utils/messages';
import type { Application, Release } from 'balena-sdk';
@ -45,10 +46,13 @@ export default class DeviceCmd extends Command {
Show info about a single device.
Show information about a single device.
${jsonInfo.split('\n').join('\n\t\t')}
`;
public static examples = [
'$ balena device 7cf02a6',
'$ balena device 7cf02a6 --view',
'$ balena device 7cf02a6 --json',
];
public static args = {
@ -61,6 +65,7 @@ export default class DeviceCmd extends Command {
public static usage = 'device <uuid>';
public static flags = {
json: cf.json,
help: cf.help,
view: Flags.boolean({
default: false,
@ -76,33 +81,45 @@ export default class DeviceCmd extends Command {
const balena = getBalenaSdk();
const device = (await balena.models.device.get(params.uuid, {
$select: [
'device_name',
'id',
'overall_status',
'is_online',
'ip_address',
'mac_address',
'last_connectivity_event',
'uuid',
'supervisor_version',
'is_web_accessible',
'note',
'os_version',
'memory_usage',
'memory_total',
'public_address',
'storage_block_device',
'storage_usage',
'storage_total',
'cpu_usage',
'cpu_temp',
'cpu_id',
'is_undervolted',
],
...expandForAppName,
})) as ExtendedDevice;
const device = (await balena.models.device.get(
params.uuid,
options.json
? {
$expand: {
device_tag: {
$select: ['tag_key', 'value'],
},
...expandForAppName.$expand,
},
}
: {
$select: [
'device_name',
'id',
'overall_status',
'is_online',
'ip_address',
'mac_address',
'last_connectivity_event',
'uuid',
'supervisor_version',
'is_web_accessible',
'note',
'os_version',
'memory_usage',
'memory_total',
'public_address',
'storage_block_device',
'storage_usage',
'storage_total',
'cpu_usage',
'cpu_temp',
'cpu_id',
'is_undervolted',
],
...expandForAppName,
},
)) as ExtendedDevice;
if (options.view) {
const open = await import('open');
@ -166,6 +183,11 @@ export default class DeviceCmd extends Command {
);
}
if (options.json) {
console.log(JSON.stringify(device, null, 4));
return;
}
console.log(
getVisuals().table.vertical(device, [
`$${device.device_name}$`,

View File

@ -132,7 +132,7 @@ export default class DeviceInitCmd extends Command {
$select: 'slug',
},
},
})
})
: await (await import('../../utils/patterns')).selectApplication();
// Register new device

View File

@ -63,9 +63,8 @@ export default class DeviceLocalModeCmd extends Command {
public static authenticated = true;
public async run() {
const { args: params, flags: options } = await this.parse(
DeviceLocalModeCmd,
);
const { args: params, flags: options } =
await this.parse(DeviceLocalModeCmd);
const balena = getBalenaSdk();

View File

@ -37,6 +37,7 @@ export default class DeviceOsUpdateCmd extends Command {
'$ balena device os-update 23c73a1',
'$ balena device os-update 23c73a1 --version 2.101.7',
'$ balena device os-update 23c73a1 --version 2.31.0+rev1.prod',
'$ balena device os-update 23c73a1 --include-draft',
];
public static args = {
@ -51,6 +52,12 @@ export default class DeviceOsUpdateCmd extends Command {
public static flags = {
version: Flags.string({
description: 'a balenaOS version',
exclusive: ['include-draft'],
}),
'include-draft': Flags.boolean({
description: 'include pre-release balenaOS versions',
default: false,
exclusive: ['version'],
}),
yes: cf.yes,
help: cf.help,
@ -59,9 +66,8 @@ export default class DeviceOsUpdateCmd extends Command {
public static authenticated = true;
public async run() {
const { args: params, flags: options } = await this.parse(
DeviceOsUpdateCmd,
);
const { args: params, flags: options } =
await this.parse(DeviceOsUpdateCmd);
const sdk = getBalenaSdk();
@ -87,10 +93,25 @@ export default class DeviceOsUpdateCmd extends Command {
);
}
let includeDraft = options['include-draft'];
if (!includeDraft && options.version != null) {
const bSemver = await import('balena-semver');
const parsedVersion = bSemver.parse(options.version);
// When the user provides a draft version, we need to pass `includeDraft`
// to the os.getSupportedOsUpdateVersions() since w/o it the results
// will for sure not include the user provided version and the command
// would return a "not in the Host OS update targets" error.
includeDraft =
parsedVersion != null && parsedVersion.prerelease.length > 0;
}
// Get supported OS update versions
const hupVersionInfo = await sdk.models.os.getSupportedOsUpdateVersions(
is_of__device_type[0].slug,
currentOsVersion,
{
includeDraft,
},
);
if (hupVersionInfo.versions.length === 0) {
throw new ExpectedError(
@ -101,6 +122,8 @@ export default class DeviceOsUpdateCmd extends Command {
// Get target OS version
let targetOsVersion = options.version;
if (targetOsVersion != null) {
const { normalizeOsVersion } = await import('../../utils/normalization');
targetOsVersion = normalizeOsVersion(targetOsVersion);
if (!hupVersionInfo.versions.includes(targetOsVersion)) {
throw new ExpectedError(
`The provided version ${targetOsVersion} is not in the Host OS update targets for this device`,

View File

@ -65,9 +65,8 @@ export default class DevicePublicUrlCmd extends Command {
public static authenticated = true;
public async run() {
const { args: params, flags: options } = await this.parse(
DevicePublicUrlCmd,
);
const { args: params, flags: options } =
await this.parse(DevicePublicUrlCmd);
const balena = getBalenaSdk();

View File

@ -61,9 +61,8 @@ export default class DeviceRegisterCmd extends Command {
public static authenticated = true;
public async run() {
const { args: params, flags: options } = await this.parse(
DeviceRegisterCmd,
);
const { args: params, flags: options } =
await this.parse(DeviceRegisterCmd);
const { getApplication } = await import('../../utils/sdk');

View File

@ -46,9 +46,8 @@ export default class DeviceShutdownCmd extends Command {
public static authenticated = true;
public async run() {
const { args: params, flags: options } = await this.parse(
DeviceShutdownCmd,
);
const { args: params, flags: options } =
await this.parse(DeviceShutdownCmd);
const balena = getBalenaSdk();

View File

@ -0,0 +1,139 @@
/**
* @license
* Copyright 2016-2020 Balena Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Args } from '@oclif/core';
import Command from '../../command';
import * as cf from '../../utils/common-flags';
import { getBalenaSdk, getCliUx, stripIndent } from '../../utils/lazy';
import type { BalenaSDK } from 'balena-sdk';
export default class DeviceStartServiceCmd extends Command {
public static description = stripIndent`
Start containers on a device.
Start containers on a device.
Multiple devices and services may be specified with a comma-separated list
of values (no spaces).
`;
public static examples = [
'$ balena device start-service 23c73a1 myService',
'$ balena device start-service 23c73a1 myService1,myService2',
];
public static args = {
uuid: Args.string({
description: 'comma-separated list (no blank spaces) of device UUIDs',
required: true,
}),
service: Args.string({
description: 'comma-separated list (no blank spaces) of service names',
required: true,
}),
};
public static usage = 'device start-service <uuid>';
public static flags = {
help: cf.help,
};
public static authenticated = true;
public async run() {
const { args: params } = await this.parse(DeviceStartServiceCmd);
const balena = getBalenaSdk();
const ux = getCliUx();
const deviceUuids = params.uuid.split(',');
const serviceNames = params.service.split(',');
// Iterate sequentially through deviceUuids.
// We may later want to add a batching feature,
// so that n devices are processed in parallel
for (const uuid of deviceUuids) {
ux.action.start(`Starting services on device ${uuid}`);
await this.startServices(balena, uuid, serviceNames);
ux.action.stop();
}
}
async startServices(
balena: BalenaSDK,
deviceUuid: string,
serviceNames: string[],
) {
const { ExpectedError } = await import('../../errors');
const { getExpandedProp } = await import('../../utils/pine');
// Get device
const device = await balena.models.device.getWithServiceDetails(
deviceUuid,
{
$expand: {
is_running__release: { $select: 'commit' },
},
},
);
const activeReleaseCommit = getExpandedProp(
device.is_running__release,
'commit',
);
// Check specified services exist on this device before startinganything
serviceNames.forEach((service) => {
if (!device.current_services[service]) {
throw new ExpectedError(
`Service ${service} not found on device ${deviceUuid}.`,
);
}
});
// Start services
const startPromises: Array<Promise<void>> = [];
for (const serviceName of serviceNames) {
const service = device.current_services[serviceName];
// Each service is an array of `CurrentServiceWithCommit`
// because when service is updating, it will actually hold 2 services
// Target commit matching `device.is_running__release`
const serviceContainer = service.find((s) => {
return s.commit === activeReleaseCommit;
});
if (serviceContainer) {
startPromises.push(
balena.models.device.startService(
deviceUuid,
serviceContainer.image_id,
),
);
}
}
try {
await Promise.all(startPromises);
} catch (e) {
if (e.message.toLowerCase().includes('no online device')) {
throw new ExpectedError(`Device ${deviceUuid} is not online.`);
} else {
throw e;
}
}
}
}

View File

@ -0,0 +1,139 @@
/**
* @license
* Copyright 2016-2020 Balena Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Args } from '@oclif/core';
import Command from '../../command';
import * as cf from '../../utils/common-flags';
import { getBalenaSdk, getCliUx, stripIndent } from '../../utils/lazy';
import type { BalenaSDK } from 'balena-sdk';
export default class DeviceStopServiceCmd extends Command {
public static description = stripIndent`
Stop containers on a device.
Stop containers on a device.
Multiple devices and services may be specified with a comma-separated list
of values (no spaces).
`;
public static examples = [
'$ balena device stop-service 23c73a1 myService',
'$ balena device stop-service 23c73a1 myService1,myService2',
];
public static args = {
uuid: Args.string({
description: 'comma-separated list (no blank spaces) of device UUIDs',
required: true,
}),
service: Args.string({
description: 'comma-separated list (no blank spaces) of service names',
required: true,
}),
};
public static usage = 'device stop-service <uuid>';
public static flags = {
help: cf.help,
};
public static authenticated = true;
public async run() {
const { args: params } = await this.parse(DeviceStopServiceCmd);
const balena = getBalenaSdk();
const ux = getCliUx();
const deviceUuids = params.uuid.split(',');
const serviceNames = params.service.split(',');
// Iterate sequentially through deviceUuids.
// We may later want to add a batching feature,
// so that n devices are processed in parallel
for (const uuid of deviceUuids) {
ux.action.start(`Stopping services on device ${uuid}`);
await this.stopServices(balena, uuid, serviceNames);
ux.action.stop();
}
}
async stopServices(
balena: BalenaSDK,
deviceUuid: string,
serviceNames: string[],
) {
const { ExpectedError } = await import('../../errors');
const { getExpandedProp } = await import('../../utils/pine');
// Get device
const device = await balena.models.device.getWithServiceDetails(
deviceUuid,
{
$expand: {
is_running__release: { $select: 'commit' },
},
},
);
const activeReleaseCommit = getExpandedProp(
device.is_running__release,
'commit',
);
// Check specified services exist on this device before stoppinganything
serviceNames.forEach((service) => {
if (!device.current_services[service]) {
throw new ExpectedError(
`Service ${service} not found on device ${deviceUuid}.`,
);
}
});
// Stop services
const stopPromises: Array<Promise<void>> = [];
for (const serviceName of serviceNames) {
const service = device.current_services[serviceName];
// Each service is an array of `CurrentServiceWithCommit`
// because when service is updating, it will actually hold 2 services
// Target commit matching `device.is_running__release`
const serviceContainer = service.find((s) => {
return s.commit === activeReleaseCommit;
});
if (serviceContainer) {
stopPromises.push(
balena.models.device.stopService(
deviceUuid,
serviceContainer.image_id,
),
);
}
}
try {
await Promise.all(stopPromises);
} catch (e) {
if (e.message.toLowerCase().includes('no online device')) {
throw new ExpectedError(`Device ${deviceUuid} is not online.`);
} else {
throw e;
}
}
}
}

View File

@ -90,6 +90,8 @@ export default class EnvAddCmd extends Command {
}),
};
// Required for supporting empty string ('') `value` args.
public static strict = false;
public static usage = 'env add <name> [value]';
public static flags = {

View File

@ -18,11 +18,11 @@ import { Flags } from '@oclif/core';
import type { Interfaces } from '@oclif/core';
import type * as SDK from 'balena-sdk';
import * as _ from 'lodash';
import Command from '../command';
import { ExpectedError } from '../errors';
import * as cf from '../utils/common-flags';
import { getBalenaSdk, getVisuals, stripIndent } from '../utils/lazy';
import { applicationIdInfo } from '../utils/messages';
import Command from '../../command';
import { ExpectedError } from '../../errors';
import * as cf from '../../utils/common-flags';
import { getBalenaSdk, getVisuals, stripIndent } from '../../utils/lazy';
import { applicationIdInfo } from '../../utils/messages';
type FlagsDef = Interfaces.InferredFlags<typeof EnvsCmd.flags>;
@ -124,12 +124,16 @@ export default class EnvsCmd extends Command {
const balena = getBalenaSdk();
let fleetSlug: string | undefined = options.fleet
? await (await import('../utils/sdk')).getFleetSlug(balena, options.fleet)
? await (
await import('../../utils/sdk')
).getFleetSlug(balena, options.fleet)
: undefined;
let fullUUID: string | undefined; // as oppposed to the short, 7-char UUID
if (options.device) {
const { getDeviceAndMaybeAppFromUUID } = await import('../utils/cloud');
const { getDeviceAndMaybeAppFromUUID } = await import(
'../../utils/cloud'
);
const [device, app] = await getDeviceAndMaybeAppFromUUID(
balena,
options.device,
@ -182,7 +186,7 @@ export default class EnvsCmd extends Command {
}
if (options.json) {
const { pickAndRename } = await import('../utils/helpers');
const { pickAndRename } = await import('../../utils/helpers');
const mapped = varArray.map((o) => pickAndRename(o, fields));
this.log(JSON.stringify(mapped, null, 4));
} else {
@ -228,9 +232,10 @@ async function getAppVars(
if (!fleetSlug) {
return appVars;
}
const vars = await sdk.models.application[
options.config ? 'configVar' : 'envVar'
].getAllByApplication(fleetSlug);
const vars =
await sdk.models.application[
options.config ? 'configVar' : 'envVar'
].getAllByApplication(fleetSlug);
fillInInfoFields(vars, fleetSlug);
appVars.push(...vars);
if (!options.config) {
@ -269,9 +274,8 @@ async function getDeviceVars(
const printedUUID = options.json ? fullUUID : options.device!;
const deviceVars: EnvironmentVariableInfo[] = [];
if (options.config) {
const deviceConfigVars = await sdk.models.device.configVar.getAllByDevice(
fullUUID,
);
const deviceConfigVars =
await sdk.models.device.configVar.getAllByDevice(fullUUID);
fillInInfoFields(deviceConfigVars, fleetSlug, printedUUID);
deviceVars.push(...deviceConfigVars);
} else {
@ -296,9 +300,8 @@ async function getDeviceVars(
fillInInfoFields(deviceServiceVars, fleetSlug, printedUUID);
deviceVars.push(...deviceServiceVars);
const deviceEnvVars = await sdk.models.device.envVar.getAllByDevice(
fullUUID,
);
const deviceEnvVars =
await sdk.models.device.envVar.getAllByDevice(fullUUID);
fillInInfoFields(deviceEnvVars, fleetSlug, printedUUID);
deviceVars.push(...deviceEnvVars);
}

View File

@ -20,7 +20,7 @@ import { Flags } from '@oclif/core';
import Command from '../../command';
import * as cf from '../../utils/common-flags';
import * as ca from '../../utils/common-args';
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
import { getBalenaSdk, getVisuals, stripIndent } from '../../utils/lazy';
import { applicationIdInfo } from '../../utils/messages';
export default class FleetCmd extends Command {
@ -49,7 +49,7 @@ export default class FleetCmd extends Command {
default: false,
description: 'open fleet dashboard page',
}),
...cf.dataOutputFlags,
json: cf.json,
};
public static authenticated = true;
@ -78,16 +78,28 @@ export default class FleetCmd extends Command {
return;
}
const outputApplication = {
...application,
const applicationToDisplay = {
id: application.id,
app_name: application.app_name,
slug: application.slug,
device_type: application.is_for__device_type[0].slug,
commit: application.should_be_running__release[0]?.commit,
};
await this.outputData(
outputApplication,
['app_name', 'id', 'device_type', 'slug', 'commit'],
options,
if (options.json) {
console.log(JSON.stringify(applicationToDisplay, null, 4));
return;
}
// Emulate table.vertical title output, but avoid uppercasing and inserting spaces
console.log(`== ${applicationToDisplay.app_name}`);
console.log(
getVisuals().table.vertical(applicationToDisplay, [
'id',
'device_type',
'slug',
'commit',
]),
);
}
}

Some files were not shown because too many files have changed in this diff Show More