mirror of
https://github.com/balena-io/balena-cli.git
synced 2025-06-24 18:45:07 +00:00
Compare commits
199 Commits
upgrade_to
...
esm2
Author | SHA1 | Date | |
---|---|---|---|
b86e26f9aa | |||
0591f5edbd | |||
c30dd323f1 | |||
1640bd6457 | |||
da2ffde483 | |||
5c9e3ad8f6 | |||
7515d4b710 | |||
fae5af6b75 | |||
45aa1adacb | |||
b34ea14413 | |||
90eae06017 | |||
41da8f6f6f | |||
8d706a7d81 | |||
d67952024c | |||
8895fc485c | |||
c2dbcaaaf4 | |||
52cb951e49 | |||
2a357a438f | |||
a9a202281d | |||
b74979fb9e | |||
4760866c77 | |||
2b044348e0 | |||
c9fa10b9c6 | |||
63674c8201 | |||
a08ac447a3 | |||
12a338fb21 | |||
1d70e6b4b4 | |||
d3458379e6 | |||
544f615ca0 | |||
245c51d974 | |||
03f0f11f8b | |||
2c0c1f8fd1 | |||
d4d7fce2c1 | |||
0f23318367 | |||
003d537433 | |||
46d3497663 | |||
a39a772c9e | |||
efa0d67f0a | |||
232b9678bc | |||
a8ce14b0e8 | |||
838a36758a | |||
4e101e2fd9 | |||
9f9fd97795 | |||
1b36dc84fc | |||
5d6ee707ff | |||
3c64e13fb3 | |||
7e41fda8d4 | |||
5df316e9cb | |||
79fcd95491 | |||
33199acbe8 | |||
4633c2456d | |||
f8bc081228 | |||
1702f8ba59 | |||
60b0c7e346 | |||
e95ef8b3b4 | |||
1bc0f7447f | |||
f65215e144 | |||
97abc5cf1c | |||
e64a09d2f4 | |||
b1073ca549 | |||
e659e3577a | |||
f7233c5d42 | |||
4ae2ff1740 | |||
19a60bb0ab | |||
d1a6f7560c | |||
4619ce7daa | |||
7624240d5e | |||
7273656d07 | |||
00bd4d5415 | |||
c2d3c9fc71 | |||
1749937373 | |||
bcb7fb8902 | |||
81e9601d6b | |||
6c89ba4b22 | |||
57d3d6d537 | |||
6330574c01 | |||
b6d1afac2d | |||
f2d0da0837 | |||
068cd887c8 | |||
93e597a596 | |||
5b1d6a3190 | |||
dba102f347 | |||
c30a1dc1ed | |||
78368c8a51 | |||
d7250ccc4e | |||
2d47eb53cd | |||
b5fc97bdf9 | |||
3472df2c04 | |||
6b5657625a | |||
dad6b23202 | |||
6b59c06978 | |||
b518067058 | |||
bd4bdb805f | |||
32e59eccc5 | |||
f05e49915d | |||
92146429c4 | |||
40f5214317 | |||
14e1255b5f | |||
15e91e95b4 | |||
1814fe7581 | |||
7325e8d9d5 | |||
5358f92590 | |||
fe6a7cfdba | |||
a29bd8d0ef | |||
049e1da53e | |||
2c0b4072ae | |||
15c0c32a01 | |||
8f2c7f9dbf | |||
90982256c7 | |||
73220206a2 | |||
8b453aae89 | |||
d85d5933fb | |||
2cd455ff81 | |||
066cbaf35f | |||
17fa888fea | |||
f50287873a | |||
edff14fa72 | |||
9de753d9d3 | |||
75d2d7d375 | |||
d9b193acc1 | |||
2e42999642 | |||
5a3f0ea453 | |||
e1cd30060c | |||
7959e23cd3 | |||
9c4d788d6d | |||
181f5a6a2f | |||
163dcf596e | |||
1724187466 | |||
b27dcdd582 | |||
c28039a3f2 | |||
233bc705de | |||
71518678e1 | |||
88a705c935 | |||
55d06aced2 | |||
aa9a148c46 | |||
10ca5b4f59 | |||
47e11d5f9b | |||
6fb65bcf22 | |||
954de13b10 | |||
f81a27e931 | |||
e8815d0275 | |||
766e6d4e5e | |||
7b46f65a01 | |||
db8df0ac35 | |||
7c7f46fe2b | |||
b29aae1821 | |||
0b10701015 | |||
1dbe08d7e0 | |||
d01461ff3e | |||
2a970478bd | |||
ffd44d3fec | |||
df51f87fbc | |||
6178f34f88 | |||
c5ecf692bb | |||
87f5f18721 | |||
e33810b448 | |||
3caf54aa16 | |||
9d3ee9eb49 | |||
3dac94db70 | |||
04b4444fc2 | |||
98514cef09 | |||
4811031172 | |||
be682c7426 | |||
c6827ee51d | |||
2cba3bbc22 | |||
933eacf275 | |||
e7869f4c6d | |||
1a246a9ba5 | |||
e26895085d | |||
71345a8cc1 | |||
619f605eb2 | |||
bb4713ab9a | |||
168bddf7db | |||
24076e4f8d | |||
634ad156ce | |||
6ebeb97917 | |||
cb444998cd | |||
742c015f21 | |||
556e50c87c | |||
3294f78b00 | |||
7f11805a7f | |||
42dd732f68 | |||
aed50480c3 | |||
6515d6ae10 | |||
7903c82821 | |||
eee8a0ecca | |||
38a2817587 | |||
2bd0641d5f | |||
122a763f82 | |||
756f6b328b | |||
eb9db6f7b4 | |||
6f9e5a697c | |||
f9f41eef4b | |||
5371fea588 | |||
bacb55a1ea | |||
ecfd4a260e | |||
1525822239 | |||
1614d9b2c8 | |||
2e061845ae |
50
.github/actions/publish/action.yml
vendored
50
.github/actions/publish/action.yml
vendored
@ -28,7 +28,7 @@ runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- name: Download custom source artifact
|
||||
uses: actions/download-artifact@f44cd7b40bfd40b6aa1cc1b9b5b7bf03d3c67110 # v4.1.0
|
||||
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,15 +127,15 @@ 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@c7d193f32edcb7bfad88892161225aeda64e9392 # v4
|
||||
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4
|
||||
with:
|
||||
name: gh-release-${{ github.event.pull_request.head.sha || github.event.head_commit.id }}-${{ strategy.job-index }}
|
||||
path: dist
|
||||
|
6
.github/actions/test/action.yml
vendored
6
.github/actions/test/action.yml
vendored
@ -26,14 +26,14 @@ 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@d27e3f3d7c64b4bbf8e4abfb9b63b83e846e0435 # v4
|
||||
uses: actions/setup-python@65d7f2d534ac1bc67fcd62888c5f4f3d2cb2b236 # v4
|
||||
with:
|
||||
python-version: "3.11"
|
||||
|
||||
@ -58,7 +58,7 @@ runs:
|
||||
run: tar --exclude-vcs -acf ${{ runner.temp }}/custom.tgz .
|
||||
|
||||
- name: Upload custom artifact
|
||||
uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4
|
||||
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
4
.github/renovate.json
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"extends": ["github>balena-io/renovate-config"],
|
||||
"postUpdateOptions": ["npmDedupe"]
|
||||
}
|
21
.github/workflows/flowzone.yml
vendored
21
.github/workflows/flowzone.yml
vendored
@ -21,6 +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"]]'
|
||||
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
1
.husky/pre-commit
Normal file
@ -0,0 +1 @@
|
||||
node automation/check-npm-version.cjs && npx tsc automation/check-doc.ts
|
File diff suppressed because it is too large
Load Diff
435
CHANGELOG.md
435
CHANGELOG.md
@ -4,6 +4,441 @@ 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.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]
|
||||
|
@ -115,9 +115,9 @@ 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
|
||||
@ -224,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:
|
||||
|
@ -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,7 +78,7 @@ 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 20.**
|
||||
> **The balena CLI currently requires Node.js version ^20.6.0**
|
||||
> **Versions 21 and later are not yet fully supported.**
|
||||
|
||||
### Install development tools
|
||||
|
@ -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
|
||||
|
@ -15,32 +15,32 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import type { JsonVersions } from '../lib/commands/version/index';
|
||||
import type { JsonVersions } from '../src/commands/version/index.js';
|
||||
|
||||
import { run as oclifRun } from '@oclif/core';
|
||||
import * as archiver from 'archiver';
|
||||
import * as Bluebird from 'bluebird';
|
||||
import { execFile } from 'child_process';
|
||||
import * as filehound from 'filehound';
|
||||
import { Stats } from 'fs';
|
||||
import * as fs from 'fs-extra';
|
||||
import * as klaw from 'klaw';
|
||||
import * as path from 'path';
|
||||
import * as rimraf from 'rimraf';
|
||||
import * as semver from 'semver';
|
||||
import archiver from 'archiver';
|
||||
import { exec, execFile } from 'child_process';
|
||||
import filehound from 'filehound';
|
||||
import type { Stats } from 'fs';
|
||||
import fs from 'fs-extra';
|
||||
import klaw from 'klaw';
|
||||
import path from 'path';
|
||||
import { rimraf } from 'rimraf';
|
||||
import semver from 'semver';
|
||||
import { promisify } from 'util';
|
||||
import { notarize } from '@electron/notarize';
|
||||
|
||||
import { stripIndent } from '../build/utils/lazy';
|
||||
import { stripIndent } from '../build/utils/lazy.js';
|
||||
import {
|
||||
diffLines,
|
||||
loadPackageJson,
|
||||
ROOT,
|
||||
StdOutTap,
|
||||
whichSpawn,
|
||||
} from './utils';
|
||||
} from './utils.js';
|
||||
|
||||
const execFileAsync = promisify(execFile);
|
||||
const execAsync = promisify(exec);
|
||||
|
||||
export const packageJSON = loadPackageJson();
|
||||
export const version = 'v' + packageJSON.version;
|
||||
@ -60,9 +60,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 = {
|
||||
@ -82,7 +86,7 @@ export const finalReleaseAssets: { [platform: string]: string[] } = {
|
||||
* Throw an error if the diff is not empty.
|
||||
*/
|
||||
async function diffPkgOutput(pkgOut: string) {
|
||||
const { monochrome } = await import('../tests/helpers');
|
||||
const { monochrome } = await import('../tests/helpers.js');
|
||||
const relSavedPath = path.join(
|
||||
'tests',
|
||||
'test-data',
|
||||
@ -146,7 +150,8 @@ sections in the CLI's 'package.json' file, or a matter of updating the
|
||||
patching dependencies: See for example 'patches/all/open+7.0.2.patch'.
|
||||
${sep}
|
||||
`;
|
||||
throw new Error(msg);
|
||||
// throw new Error(msg);
|
||||
console.error(msg);
|
||||
}
|
||||
}
|
||||
|
||||
@ -182,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`;
|
||||
}
|
||||
@ -258,7 +263,7 @@ async function testPkg() {
|
||||
'version',
|
||||
'-j',
|
||||
]);
|
||||
const { filterCliOutputForTests } = await import('../tests/helpers');
|
||||
const { filterCliOutputForTests } = await import('../tests/helpers.js');
|
||||
const filtered = filterCliOutputForTests({
|
||||
err: stderr.split(/\r?\n/),
|
||||
out: stdout.split(/\r?\n/),
|
||||
@ -321,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/')
|
||||
@ -421,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],
|
||||
@ -435,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,
|
||||
@ -491,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');
|
||||
@ -505,11 +517,7 @@ export async function buildOclifInstaller() {
|
||||
}
|
||||
for (const dir of dirs) {
|
||||
console.log(`rimraf(${dir})`);
|
||||
await Bluebird.fromCallback((cb) => rimraf(dir, cb));
|
||||
}
|
||||
if (process.platform === 'darwin') {
|
||||
console.log('Signing files for notarization...');
|
||||
await signFilesForNotarization();
|
||||
await rimraf(dir);
|
||||
}
|
||||
console.log('=======================================================');
|
||||
console.log(`oclif ${packCmd} ${packOpts.join(' ')}`);
|
||||
@ -562,6 +570,8 @@ export async function testShrinkwrap(): Promise<void> {
|
||||
console.error(`[debug] platform=${process.platform}`);
|
||||
}
|
||||
if (process.platform !== 'win32') {
|
||||
await whichSpawn(path.resolve(__dirname, 'test-lock-deduplicated.sh'));
|
||||
await whichSpawn(
|
||||
path.resolve(import.meta.dirname, 'test-lock-deduplicated.sh'),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -16,8 +16,8 @@
|
||||
*/
|
||||
|
||||
import * as path from 'path';
|
||||
import { MarkdownFileParser } from './utils';
|
||||
import { GlobSync } from 'glob';
|
||||
import { MarkdownFileParser } from './utils.js';
|
||||
import { globSync } from 'glob';
|
||||
|
||||
/**
|
||||
* This is the skeleton of CLI documentation/reference web page at:
|
||||
@ -28,7 +28,7 @@ import { GlobSync } from 'glob';
|
||||
*
|
||||
* IMPORTANT
|
||||
*
|
||||
* All commands need to be stored under a folder in lib/commands to maintain uniformity
|
||||
* 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.
|
||||
@ -54,15 +54,15 @@ interface Documentation {
|
||||
|
||||
// Mapping folders names to custom headings in the docs
|
||||
const commandHeadings: { [key: string]: string } = {
|
||||
'api-key': 'API Key',
|
||||
'api-key': 'API Keys',
|
||||
'api-keys': 'API Keys',
|
||||
login: 'Authentication',
|
||||
whoami: 'Authentication',
|
||||
logout: 'Authentication',
|
||||
env: 'Environment Variable',
|
||||
env: 'Environment Variables',
|
||||
envs: 'Environment Variables',
|
||||
help: 'Help and Version',
|
||||
key: 'SSH Key',
|
||||
key: 'SSH Keys',
|
||||
keys: 'SSH Keys',
|
||||
orgs: 'Organizations',
|
||||
os: 'OS',
|
||||
@ -73,12 +73,18 @@ const commandHeadings: { [key: string]: string } = {
|
||||
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', {
|
||||
const allCommandsPaths = 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) =>
|
||||
@ -138,7 +144,7 @@ capitanoDoc.categories.forEach((category) => {
|
||||
* for the documentation web page.
|
||||
*/
|
||||
export async function getCapitanoDoc(): Promise<typeof capitanoDoc> {
|
||||
const readmePath = path.join(__dirname, '..', '..', 'README.md');
|
||||
const readmePath = path.join(import.meta.dirname, '..', '..', 'README.md');
|
||||
const mdParser = new MarkdownFileParser(readmePath);
|
||||
const sections: string[] = await Promise.all([
|
||||
mdParser.getSectionOfTitle('About').then((sectionLines: string) => {
|
||||
|
2
automation/capitanodoc/doc-types.d.ts
vendored
2
automation/capitanodoc/doc-types.d.ts
vendored
@ -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;
|
||||
|
||||
|
@ -15,11 +15,13 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
import * as path from 'path';
|
||||
import { getCapitanoDoc } from './capitanodoc';
|
||||
import { Category, Document, OclifCommand } from './doc-types';
|
||||
import * as markdown from './markdown';
|
||||
import { stripIndent } from '../../lib/utils/lazy';
|
||||
import { getCapitanoDoc } from './capitanodoc.js';
|
||||
import type { Category, Document, OclifCommand } from './doc-types.js';
|
||||
import * as markdown from './markdown.js';
|
||||
import { stripIndent } from '../../src/utils/lazy.js';
|
||||
import { Module } from 'node:module';
|
||||
|
||||
const require = Module.createRequire(import.meta.url);
|
||||
/**
|
||||
* Generates the markdown document (as a string) for the CLI documentation
|
||||
* page on the web: https://www.balena.io/docs/reference/cli/
|
||||
|
@ -16,11 +16,11 @@
|
||||
*/
|
||||
import { Parser } from '@oclif/core';
|
||||
import * as ent from 'ent';
|
||||
import * as _ from 'lodash';
|
||||
import _ 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.js';
|
||||
import { capitanoizeOclifUsage } from '../../src/utils/oclif-utils.js';
|
||||
import type { Category, Document, OclifCommand } from './doc-types.js';
|
||||
|
||||
function renderOclifCommand(command: OclifCommand): string[] {
|
||||
const result = [`## ${ent.encode(command.usage || '')}`];
|
||||
|
@ -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) {}
|
||||
|
||||
|
@ -17,12 +17,12 @@
|
||||
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
import { stripIndent } from 'common-tags';
|
||||
import * as _ from 'lodash';
|
||||
import _ from 'lodash';
|
||||
import { promises as fs } from 'fs';
|
||||
import * as path from 'path';
|
||||
import path from 'path';
|
||||
import { simpleGit } from 'simple-git';
|
||||
|
||||
const ROOT = path.normalize(path.join(__dirname, '..'));
|
||||
const ROOT = path.normalize(path.join(import.meta.dirname, '..'));
|
||||
|
||||
/**
|
||||
* Compare the timestamp of balena-cli.md with the timestamp of staged files,
|
||||
@ -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)));
|
||||
|
@ -15,49 +15,11 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import * as Bluebird from 'bluebird';
|
||||
import * as _ from 'lodash';
|
||||
import _ from 'lodash';
|
||||
import * as semver from 'semver';
|
||||
|
||||
import { finalReleaseAssets, version } from './build-bin';
|
||||
|
||||
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],
|
||||
}),
|
||||
)) as { html_url: any };
|
||||
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 = (
|
||||
@ -122,13 +84,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;
|
||||
|
@ -15,18 +15,16 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import * as _ from 'lodash';
|
||||
import _ from 'lodash';
|
||||
|
||||
import {
|
||||
buildOclifInstaller,
|
||||
buildStandaloneZip,
|
||||
catchUncommitted,
|
||||
signFilesForNotarization,
|
||||
testShrinkwrap,
|
||||
} from './build-bin';
|
||||
import {
|
||||
release,
|
||||
updateDescriptionOfReleasesAffectedByIssue1359,
|
||||
} from './deploy-bin';
|
||||
} from './build-bin.js';
|
||||
import { updateDescriptionOfReleasesAffectedByIssue1359 } from './deploy-bin.js';
|
||||
|
||||
// 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,10 +51,10 @@ 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 (!Object.hasOwn(commands, arg)) {
|
||||
@ -65,21 +62,6 @@ async function parse(args?: string[]) {
|
||||
}
|
||||
}
|
||||
|
||||
// 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];
|
||||
|
@ -54,7 +54,10 @@ interface Upstream {
|
||||
|
||||
const getUpstreams = async () => {
|
||||
const fs = await import('fs');
|
||||
const repoYaml = fs.readFileSync(__dirname + '/../repo.yml', 'utf8');
|
||||
const repoYaml = fs.readFileSync(
|
||||
import.meta.dirname + '/../repo.yml',
|
||||
'utf8',
|
||||
);
|
||||
|
||||
const yaml = await import('js-yaml');
|
||||
const { upstream } = yaml.load(repoYaml) as {
|
||||
@ -107,11 +110,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');
|
||||
|
@ -17,8 +17,11 @@
|
||||
|
||||
import { spawn } from 'child_process';
|
||||
import * as path from 'path';
|
||||
import { diffTrimmedLines } from 'diff';
|
||||
import { Module } from 'node:module';
|
||||
|
||||
export const ROOT = path.join(__dirname, '..');
|
||||
const require = Module.createRequire(import.meta.url);
|
||||
export const ROOT = path.join(import.meta.dirname, '..');
|
||||
|
||||
/** Tap and buffer this process' stdout and stderr */
|
||||
export class StdOutTap {
|
||||
@ -64,7 +67,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
|
||||
@ -76,8 +78,8 @@ 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;
|
||||
@ -97,7 +99,7 @@ export function loadPackageJson() {
|
||||
* @returns The program's full path, e.g. 'C:\WINDOWS\System32\OpenSSH\ssh.EXE'
|
||||
*/
|
||||
export async function which(program: string): Promise<string> {
|
||||
const whichMod = await import('which');
|
||||
const { default: whichMod } = await import('which');
|
||||
let programPath: string;
|
||||
try {
|
||||
programPath = await whichMod(program);
|
||||
|
21
bin/balena
21
bin/balena
@ -1,21 +0,0 @@
|
||||
#!/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();
|
1
bin/balena
Symbolic link
1
bin/balena
Symbolic link
@ -0,0 +1 @@
|
||||
run.js
|
@ -1,87 +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
|
||||
// ****************************************************************************
|
||||
|
||||
// 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(undefined, { dir: __dirname, development: true });
|
||||
|
||||
// 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
1
bin/balena-dev
Symbolic link
@ -0,0 +1 @@
|
||||
dev.js
|
3
bin/dev.cmd
Normal file
3
bin/dev.cmd
Normal file
@ -0,0 +1,3 @@
|
||||
@echo off
|
||||
|
||||
node "%~dp0\run" %*
|
90
bin/dev.js
Executable file
90
bin/dev.js
Executable file
@ -0,0 +1,90 @@
|
||||
#!/usr/bin/env -S node --loader ts-node/esm --no-warnings=ExperimentalWarning
|
||||
|
||||
// ****************************************************************************
|
||||
// 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`.
|
||||
|
||||
import * as path from 'path';
|
||||
import * as fs from 'fs';
|
||||
const rootDir = path.join(import.meta.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
|
||||
(await import('@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'.
|
||||
// (await import('ts-node')).register({
|
||||
// project: path.join(rootDir, 'tsconfig.json'),
|
||||
// transpileOnly: true,
|
||||
// });
|
||||
(await import('../src/app.js')).run(undefined, {
|
||||
dir: import.meta.url,
|
||||
development: true,
|
||||
});
|
||||
|
||||
// Modify package.json oclif paths from build/ -> src/, or vice versa
|
||||
function modifyOclifPaths(revert) {
|
||||
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
3
bin/run.cmd
Normal file
@ -0,0 +1,3 @@
|
||||
@echo off
|
||||
|
||||
node "%~dp0\run" %*
|
20
bin/run.js
Executable file
20
bin/run.js
Executable file
@ -0,0 +1,20 @@
|
||||
#!/usr/bin/env -S node --loader ts-node/esm --no-warnings=ExperimentalWarning
|
||||
|
||||
// We boost the threadpool size as ext2fs can deadlock with some
|
||||
// operations otherwise, if the pool runs out.
|
||||
process.env.UV_THREADPOOL_SIZE = '64';
|
||||
|
||||
async function run() {
|
||||
// Use fast-boot to cache require lookups, speeding up startup
|
||||
await (await import('../build/fast-boot.js')).start();
|
||||
|
||||
// Set the desired es version for downstream modules that support it
|
||||
(await import('@balena/es-version')).set('es2018');
|
||||
|
||||
// Run the CLI
|
||||
await (
|
||||
await import('../build/app.js')
|
||||
).run(undefined, { dir: import.meta.url });
|
||||
}
|
||||
|
||||
run();
|
@ -8,7 +8,7 @@ _balena() {
|
||||
local context state line curcontext="$curcontext"
|
||||
|
||||
# Valid top-level completions
|
||||
main_commands=( api-key api-keys app block build config deploy device device devices env envs fleet fleet fleets internal join key key keys leave local login logout logs notes orgs os preload push release release releases scan settings ssh support tag tags tunnel util version whoami )
|
||||
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 )
|
||||
|
@ -7,7 +7,7 @@ _balena_complete()
|
||||
local cur prev
|
||||
|
||||
# Valid top-level completions
|
||||
main_commands="api-key api-keys app block build config deploy device device devices env envs fleet fleet fleets internal join key key keys leave local login logout logs notes orgs os preload push release release releases scan settings ssh support tag tags tunnel util version whoami"
|
||||
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"
|
||||
|
@ -33,7 +33,7 @@ const commandsJson = JSON.parse(fs.readFileSync(commandsFilePath, 'utf8'));
|
||||
|
||||
const mainCommands = [];
|
||||
const additionalCommands = [];
|
||||
for (const key of Object.keys(commandsJson.commands)) {
|
||||
for (const key of Object.keys(commandsJson.commands).sort()) {
|
||||
const cmd = key.split(':');
|
||||
if (cmd.length > 1) {
|
||||
additionalCommands.push(cmd);
|
@ -160,16 +160,13 @@ are encouraged to regularly update the balena CLI to the latest version.
|
||||
|
||||
# CLI Command Reference
|
||||
|
||||
- API Key
|
||||
- API Keys
|
||||
|
||||
- [api-key generate <name>](#api-key-generate-name)
|
||||
- [api-key revoke <ids>](#api-key-revoke-ids)
|
||||
|
||||
- API Keys
|
||||
|
||||
- [api-keys](#api-keys)
|
||||
|
||||
- App
|
||||
- Apps
|
||||
|
||||
- [app create <name>](#app-create-name)
|
||||
|
||||
@ -179,7 +176,7 @@ are encouraged to regularly update the balena CLI to the latest version.
|
||||
- [logout](#logout)
|
||||
- [whoami](#whoami)
|
||||
|
||||
- Block
|
||||
- Blocks
|
||||
|
||||
- [block create <name>](#block-create-name)
|
||||
|
||||
@ -196,7 +193,7 @@ are encouraged to regularly update the balena CLI to the latest version.
|
||||
- [build [source]](#build-source)
|
||||
- [deploy <fleet> [image]](#deploy-fleet-image)
|
||||
|
||||
- Device
|
||||
- Devices
|
||||
|
||||
- [device deactivate <uuid>](#device-deactivate-uuid)
|
||||
- [device identify <uuid>](#device-identify-uuid)
|
||||
@ -217,23 +214,17 @@ are encouraged to regularly update the balena CLI to the latest version.
|
||||
- [device start-service <uuid>](#device-start-service-uuid)
|
||||
- [device stop-service <uuid>](#device-stop-service-uuid)
|
||||
- [device track-fleet <uuid>](#device-track-fleet-uuid)
|
||||
|
||||
- Devices
|
||||
|
||||
- [devices](#devices)
|
||||
- [devices supported](#devices-supported)
|
||||
|
||||
- Environment Variable
|
||||
|
||||
- [env add <name> [value]](#env-add-name-value)
|
||||
- [env rename <id> <value>](#env-rename-id-value)
|
||||
- [env rm <id>](#env-rm-id)
|
||||
|
||||
- Environment Variables
|
||||
|
||||
- [envs](#envs)
|
||||
- [env rm <id>](#env-rm-id)
|
||||
- [env add <name> [value]](#env-add-name-value)
|
||||
- [env rename <id> <value>](#env-rename-id-value)
|
||||
|
||||
- Fleet
|
||||
- Fleets
|
||||
|
||||
- [fleet create <name>](#fleet-create-name)
|
||||
- [fleet <fleet>](#fleet-fleet)
|
||||
@ -243,9 +234,6 @@ are encouraged to regularly update the balena CLI to the latest version.
|
||||
- [fleet restart <fleet>](#fleet-restart-fleet)
|
||||
- [fleet rm <fleet>](#fleet-rm-fleet)
|
||||
- [fleet track-latest <slug>](#fleet-track-latest-slug)
|
||||
|
||||
- Fleets
|
||||
|
||||
- [fleets](#fleets)
|
||||
|
||||
- Local
|
||||
@ -292,42 +280,33 @@ are encouraged to regularly update the balena CLI to the latest version.
|
||||
|
||||
- [push <fleetordevice>](#push-fleetordevice)
|
||||
|
||||
- Release
|
||||
- Releases
|
||||
|
||||
- [release finalize <commitorid>](#release-finalize-commitorid)
|
||||
- [release <commitorid>](#release-commitorid)
|
||||
- [release invalidate <commitorid>](#release-invalidate-commitorid)
|
||||
- [release validate <commitorid>](#release-validate-commitorid)
|
||||
|
||||
- Releases
|
||||
|
||||
- [releases <fleet>](#releases-fleet)
|
||||
|
||||
- Settings
|
||||
|
||||
- [settings](#settings)
|
||||
|
||||
- SSH Key
|
||||
- SSH Keys
|
||||
|
||||
- [key add <name> [path]](#key-add-name-path)
|
||||
- [key <id>](#key-id)
|
||||
- [key rm <id>](#key-rm-id)
|
||||
|
||||
- SSH Keys
|
||||
|
||||
- [keys](#keys)
|
||||
|
||||
- Support
|
||||
|
||||
- [support <action>](#support-action)
|
||||
|
||||
- Tag
|
||||
- Tags
|
||||
|
||||
- [tag rm <tagkey>](#tag-rm-tagkey)
|
||||
- [tag set <tagkey> [value]](#tag-set-tagkey-value)
|
||||
|
||||
- Tags
|
||||
|
||||
- [tags](#tags)
|
||||
|
||||
- Utilities
|
||||
@ -338,7 +317,7 @@ are encouraged to regularly update the balena CLI to the latest version.
|
||||
|
||||
- [version](#version)
|
||||
|
||||
# API Key
|
||||
# API Keys
|
||||
|
||||
## api-key generate <name>
|
||||
|
||||
@ -380,8 +359,6 @@ the API key ids
|
||||
|
||||
### Options
|
||||
|
||||
# API Keys
|
||||
|
||||
## api-keys
|
||||
|
||||
Print a list of balenaCloud API keys.
|
||||
@ -402,7 +379,7 @@ show API keys for your user
|
||||
|
||||
fleet name or slug (preferred)
|
||||
|
||||
# App
|
||||
# Apps
|
||||
|
||||
## app create <name>
|
||||
|
||||
@ -524,7 +501,7 @@ Examples:
|
||||
|
||||
$ balena whoami
|
||||
|
||||
# Block
|
||||
# Blocks
|
||||
|
||||
## block create <name>
|
||||
|
||||
@ -882,6 +859,7 @@ 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
|
||||
@ -1214,7 +1192,7 @@ Docker host TLS certificate file
|
||||
|
||||
Docker host TLS key file
|
||||
|
||||
# Device
|
||||
# Devices
|
||||
|
||||
## device deactivate <uuid>
|
||||
|
||||
@ -1774,8 +1752,6 @@ the uuid of the device to make track the fleet's release
|
||||
|
||||
### Options
|
||||
|
||||
# Devices
|
||||
|
||||
## devices
|
||||
|
||||
List all of your devices.
|
||||
@ -1835,7 +1811,149 @@ Examples:
|
||||
|
||||
produce JSON output instead of tabular output
|
||||
|
||||
# Environment Variable
|
||||
# Environment Variables
|
||||
|
||||
## envs
|
||||
|
||||
List the environment or configuration variables of a fleet, device or
|
||||
service, as selected by the respective command-line options. (A service
|
||||
corresponds to a Docker image/container in a microservices fleet.)
|
||||
|
||||
The results include fleet-wide (multiple devices), device-specific (multiple
|
||||
services on a specific device) and service-specific variables that apply to the
|
||||
selected fleet, device or service. It can be thought of as including inherited
|
||||
variables; for example, a service inherits device-wide variables, and a device
|
||||
inherits fleet-wide variables.
|
||||
|
||||
The printed output may include DEVICE and/or SERVICE columns to distinguish
|
||||
between fleet-wide, device-specific and service-specific variables.
|
||||
An asterisk in these columns indicates that the variable applies to
|
||||
"all devices" or "all services".
|
||||
|
||||
The --config option is used to list "configuration variables" that control
|
||||
balena platform features, as opposed to custom environment variables defined
|
||||
by the user. The --config and the --service options are mutually exclusive
|
||||
because configuration variables cannot be set for specific services.
|
||||
|
||||
The --json option is recommended when scripting the output of this command,
|
||||
because the JSON format is less likely to change and it better represents data
|
||||
types like lists and empty strings. The 'jq' utility may be helpful in shell
|
||||
scripts (https://stedolan.github.io/jq/manual/). When --json is used, an empty
|
||||
JSON array ([]) is printed instead of an error message when no variables exist
|
||||
for the given query. When querying variables for a device, note that the fleet
|
||||
name may be null in JSON output (or 'N/A' in tabular output) if the fleet that
|
||||
the device belonged to is no longer accessible by the current user (for example,
|
||||
in case the current user was removed from the fleet by the fleet's owner).
|
||||
|
||||
Fleets may be specified by fleet name or slug. Fleet slugs are
|
||||
the recommended option, as they are unique and unambiguous. Slugs can be
|
||||
listed with the `balena fleets` command. Note that slugs may change if the
|
||||
fleet is renamed. Fleet names are not unique and may result in "Fleet is
|
||||
ambiguous" errors at any time (even if it "used to work in the past"), for
|
||||
example if the name clashes with a newly created public fleet, or with fleets
|
||||
from other balena accounts that you may be invited to join under any role.
|
||||
For this reason, fleet names are especially discouraged in scripts (e.g. CI
|
||||
environments).
|
||||
|
||||
Examples:
|
||||
|
||||
$ balena envs --fleet myorg/myfleet
|
||||
$ balena envs --fleet MyFleet --json
|
||||
$ balena envs --fleet MyFleet --service MyService
|
||||
$ balena envs --fleet MyFleet --config
|
||||
$ balena envs --device 7cf02a6
|
||||
$ balena envs --device 7cf02a6 --json
|
||||
$ balena envs --device 7cf02a6 --config --json
|
||||
$ balena envs --device 7cf02a6 --service MyService
|
||||
|
||||
### Options
|
||||
|
||||
#### -f, --fleet FLEET
|
||||
|
||||
fleet name or slug (preferred)
|
||||
|
||||
#### -c, --config
|
||||
|
||||
show configuration variables only
|
||||
|
||||
#### -d, --device DEVICE
|
||||
|
||||
device UUID
|
||||
|
||||
#### -j, --json
|
||||
|
||||
produce JSON output instead of tabular output
|
||||
|
||||
#### -s, --service SERVICE
|
||||
|
||||
service name
|
||||
|
||||
## env rm <id>
|
||||
|
||||
Remove a configuration or environment variable from a fleet, device
|
||||
or service, as selected by command-line options.
|
||||
|
||||
Variables are selected by their database ID (as reported by the 'balena envs'
|
||||
command) and one of six database "resource types":
|
||||
|
||||
- fleet environment variable
|
||||
- fleet configuration variable (--config)
|
||||
- fleet service variable (--service)
|
||||
- device environment variable (--device)
|
||||
- device configuration variable (--device --config)
|
||||
- device service variable (--device --service)
|
||||
|
||||
The --device option selects a device-specific variable instead of a fleet
|
||||
variable.
|
||||
|
||||
The --config option selects a configuration variable. Configuration variable
|
||||
names typically start with the 'BALENA_' or 'RESIN_' prefixes and are used to
|
||||
configure balena platform features.
|
||||
|
||||
The --service option selects a service variable, which is an environment variable
|
||||
that applies to a specifc service (container) in a microservices (multicontainer)
|
||||
fleet.
|
||||
|
||||
The --service and --config options cannot be used together, but they can be
|
||||
used alongside the --device option to select a device-specific service or
|
||||
configuration variable.
|
||||
|
||||
Interactive confirmation is normally asked before the variable is deleted.
|
||||
The --yes option disables this behavior.
|
||||
|
||||
Examples:
|
||||
|
||||
$ balena env rm 123123
|
||||
$ balena env rm 234234 --yes
|
||||
$ balena env rm 345345 --config
|
||||
$ balena env rm 456456 --service
|
||||
$ balena env rm 567567 --device
|
||||
$ balena env rm 678678 --device --config
|
||||
$ balena env rm 789789 --device --service --yes
|
||||
|
||||
### Arguments
|
||||
|
||||
#### ID
|
||||
|
||||
variable's numeric database ID
|
||||
|
||||
### Options
|
||||
|
||||
#### -c, --config
|
||||
|
||||
select a configuration variable (may be used together with the --device option)
|
||||
|
||||
#### -d, --device
|
||||
|
||||
select a device-specific variable instead of a fleet variable
|
||||
|
||||
#### -s, --service
|
||||
|
||||
select a service variable (may be used together with the --device option)
|
||||
|
||||
#### -y, --yes
|
||||
|
||||
do not prompt for confirmation before deleting the variable
|
||||
|
||||
## env add <name> [value]
|
||||
|
||||
@ -1975,151 +2093,7 @@ select a device-specific variable instead of a fleet variable
|
||||
|
||||
select a service variable (may be used together with the --device option)
|
||||
|
||||
## env rm <id>
|
||||
|
||||
Remove a configuration or environment variable from a fleet, device
|
||||
or service, as selected by command-line options.
|
||||
|
||||
Variables are selected by their database ID (as reported by the 'balena envs'
|
||||
command) and one of six database "resource types":
|
||||
|
||||
- fleet environment variable
|
||||
- fleet configuration variable (--config)
|
||||
- fleet service variable (--service)
|
||||
- device environment variable (--device)
|
||||
- device configuration variable (--device --config)
|
||||
- device service variable (--device --service)
|
||||
|
||||
The --device option selects a device-specific variable instead of a fleet
|
||||
variable.
|
||||
|
||||
The --config option selects a configuration variable. Configuration variable
|
||||
names typically start with the 'BALENA_' or 'RESIN_' prefixes and are used to
|
||||
configure balena platform features.
|
||||
|
||||
The --service option selects a service variable, which is an environment variable
|
||||
that applies to a specifc service (container) in a microservices (multicontainer)
|
||||
fleet.
|
||||
|
||||
The --service and --config options cannot be used together, but they can be
|
||||
used alongside the --device option to select a device-specific service or
|
||||
configuration variable.
|
||||
|
||||
Interactive confirmation is normally asked before the variable is deleted.
|
||||
The --yes option disables this behavior.
|
||||
|
||||
Examples:
|
||||
|
||||
$ balena env rm 123123
|
||||
$ balena env rm 234234 --yes
|
||||
$ balena env rm 345345 --config
|
||||
$ balena env rm 456456 --service
|
||||
$ balena env rm 567567 --device
|
||||
$ balena env rm 678678 --device --config
|
||||
$ balena env rm 789789 --device --service --yes
|
||||
|
||||
### Arguments
|
||||
|
||||
#### ID
|
||||
|
||||
variable's numeric database ID
|
||||
|
||||
### Options
|
||||
|
||||
#### -c, --config
|
||||
|
||||
select a configuration variable (may be used together with the --device option)
|
||||
|
||||
#### -d, --device
|
||||
|
||||
select a device-specific variable instead of a fleet variable
|
||||
|
||||
#### -s, --service
|
||||
|
||||
select a service variable (may be used together with the --device option)
|
||||
|
||||
#### -y, --yes
|
||||
|
||||
do not prompt for confirmation before deleting the variable
|
||||
|
||||
# Environment Variables
|
||||
|
||||
## envs
|
||||
|
||||
List the environment or configuration variables of a fleet, device or
|
||||
service, as selected by the respective command-line options. (A service
|
||||
corresponds to a Docker image/container in a microservices fleet.)
|
||||
|
||||
The results include fleet-wide (multiple devices), device-specific (multiple
|
||||
services on a specific device) and service-specific variables that apply to the
|
||||
selected fleet, device or service. It can be thought of as including inherited
|
||||
variables; for example, a service inherits device-wide variables, and a device
|
||||
inherits fleet-wide variables.
|
||||
|
||||
The printed output may include DEVICE and/or SERVICE columns to distinguish
|
||||
between fleet-wide, device-specific and service-specific variables.
|
||||
An asterisk in these columns indicates that the variable applies to
|
||||
"all devices" or "all services".
|
||||
|
||||
The --config option is used to list "configuration variables" that control
|
||||
balena platform features, as opposed to custom environment variables defined
|
||||
by the user. The --config and the --service options are mutually exclusive
|
||||
because configuration variables cannot be set for specific services.
|
||||
|
||||
The --json option is recommended when scripting the output of this command,
|
||||
because the JSON format is less likely to change and it better represents data
|
||||
types like lists and empty strings. The 'jq' utility may be helpful in shell
|
||||
scripts (https://stedolan.github.io/jq/manual/). When --json is used, an empty
|
||||
JSON array ([]) is printed instead of an error message when no variables exist
|
||||
for the given query. When querying variables for a device, note that the fleet
|
||||
name may be null in JSON output (or 'N/A' in tabular output) if the fleet that
|
||||
the device belonged to is no longer accessible by the current user (for example,
|
||||
in case the current user was removed from the fleet by the fleet's owner).
|
||||
|
||||
Fleets may be specified by fleet name or slug. Fleet slugs are
|
||||
the recommended option, as they are unique and unambiguous. Slugs can be
|
||||
listed with the `balena fleets` command. Note that slugs may change if the
|
||||
fleet is renamed. Fleet names are not unique and may result in "Fleet is
|
||||
ambiguous" errors at any time (even if it "used to work in the past"), for
|
||||
example if the name clashes with a newly created public fleet, or with fleets
|
||||
from other balena accounts that you may be invited to join under any role.
|
||||
For this reason, fleet names are especially discouraged in scripts (e.g. CI
|
||||
environments).
|
||||
|
||||
Examples:
|
||||
|
||||
$ balena envs --fleet myorg/myfleet
|
||||
$ balena envs --fleet MyFleet --json
|
||||
$ balena envs --fleet MyFleet --service MyService
|
||||
$ balena envs --fleet MyFleet --config
|
||||
$ balena envs --device 7cf02a6
|
||||
$ balena envs --device 7cf02a6 --json
|
||||
$ balena envs --device 7cf02a6 --config --json
|
||||
$ balena envs --device 7cf02a6 --service MyService
|
||||
|
||||
### Options
|
||||
|
||||
#### -f, --fleet FLEET
|
||||
|
||||
fleet name or slug (preferred)
|
||||
|
||||
#### -c, --config
|
||||
|
||||
show configuration variables only
|
||||
|
||||
#### -d, --device DEVICE
|
||||
|
||||
device UUID
|
||||
|
||||
#### -j, --json
|
||||
|
||||
produce JSON output instead of tabular output
|
||||
|
||||
#### -s, --service SERVICE
|
||||
|
||||
service name
|
||||
|
||||
# Fleet
|
||||
# Fleets
|
||||
|
||||
## fleet create <name>
|
||||
|
||||
@ -2194,13 +2168,9 @@ fleet name or slug (preferred)
|
||||
|
||||
open fleet dashboard page
|
||||
|
||||
#### --fields FIELDS
|
||||
|
||||
only show provided fields (comma-separated)
|
||||
|
||||
#### -j, --json
|
||||
|
||||
output in json format
|
||||
produce JSON output instead of tabular output
|
||||
|
||||
## fleet pin <slug> [releaseToPinTo]
|
||||
|
||||
@ -2366,8 +2336,6 @@ the slug of the fleet to make track the latest release
|
||||
|
||||
### Options
|
||||
|
||||
# Fleets
|
||||
|
||||
## fleets
|
||||
|
||||
List all your balena fleets.
|
||||
@ -2381,29 +2349,9 @@ Examples:
|
||||
|
||||
### Options
|
||||
|
||||
#### --fields FIELDS
|
||||
|
||||
only show provided fields (comma-separated)
|
||||
|
||||
#### -j, --json
|
||||
|
||||
output in json format
|
||||
|
||||
#### --filter FILTER
|
||||
|
||||
filter results by substring matching of a given field, eg: --filter field=foo
|
||||
|
||||
#### --no-header
|
||||
|
||||
hide table header from output
|
||||
|
||||
#### --no-truncate
|
||||
|
||||
do not truncate output to fit screen
|
||||
|
||||
#### --sort SORT
|
||||
|
||||
field to sort by (prepend '-' for descending order)
|
||||
produce JSON output instead of tabular output
|
||||
|
||||
# Local
|
||||
|
||||
@ -2862,11 +2810,6 @@ from other balena accounts that you may be invited to join under any role.
|
||||
For this reason, fleet names are especially discouraged in scripts (e.g. CI
|
||||
environments).
|
||||
|
||||
Note: This command is currently not supported on Windows natively. Windows users
|
||||
are advised to install the Windows Subsystem for Linux (WSL) with Ubuntu, and use
|
||||
the Linux release of the balena CLI:
|
||||
https://docs.microsoft.com/en-us/windows/wsl/about
|
||||
|
||||
Examples:
|
||||
|
||||
$ balena os configure ../path/rpi3.img --device 7cf02a6
|
||||
@ -3400,7 +3343,7 @@ as final by default unless this option is given.
|
||||
|
||||
The notes for this release
|
||||
|
||||
# Release
|
||||
# Releases
|
||||
|
||||
## release finalize <commitOrId>
|
||||
|
||||
@ -3499,8 +3442,6 @@ the commit or ID of the release to validate
|
||||
|
||||
### Options
|
||||
|
||||
# Releases
|
||||
|
||||
## releases <fleet>
|
||||
|
||||
List all releases of the given fleet.
|
||||
@ -3549,7 +3490,7 @@ Examples:
|
||||
|
||||
### Options
|
||||
|
||||
# SSH Key
|
||||
# SSH Keys
|
||||
|
||||
## key add <name> [path]
|
||||
|
||||
@ -3629,8 +3570,6 @@ balenaCloud ID for the SSH key
|
||||
|
||||
answer "yes" to all questions (non interactive use)
|
||||
|
||||
# SSH Keys
|
||||
|
||||
## keys
|
||||
|
||||
List all SSH keys registered in balenaCloud for the logged in user.
|
||||
@ -3691,7 +3630,7 @@ comma-separated list (no spaces) of fleet names or slugs (preferred)
|
||||
|
||||
length of time to enable support for, in (h)ours or (d)ays, e.g. 12h, 2d
|
||||
|
||||
# Tag
|
||||
# Tags
|
||||
|
||||
## tag rm <tagKey>
|
||||
|
||||
@ -3788,8 +3727,6 @@ device UUID
|
||||
|
||||
release id
|
||||
|
||||
# Tags
|
||||
|
||||
## tags
|
||||
|
||||
List all tags and their values for the specified fleet, device or release.
|
||||
|
@ -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 };
|
@ -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[] | object,
|
||||
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');
|
||||
}
|
@ -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 };
|
||||
});
|
||||
}
|
36896
npm-shrinkwrap.json
generated
36896
npm-shrinkwrap.json
generated
File diff suppressed because it is too large
Load Diff
156
package.json
156
package.json
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "balena-cli",
|
||||
"version": "18.0.0",
|
||||
"version": "19.0.2",
|
||||
"description": "The official balena Command Line Interface",
|
||||
"main": "./build/app.js",
|
||||
"homepage": "https://github.com/balena-io/balena-cli",
|
||||
@ -9,12 +9,13 @@
|
||||
"url": "git@github.com:balena-io/balena-cli.git"
|
||||
},
|
||||
"preferGlobal": true,
|
||||
"type": "module",
|
||||
"files": [
|
||||
"bin/.fast-boot.json",
|
||||
"bin/",
|
||||
"build/",
|
||||
"doc/",
|
||||
"lib/",
|
||||
"src/",
|
||||
"patches/",
|
||||
"!patches/**/**.dev.patch",
|
||||
"*.md",
|
||||
@ -22,7 +23,7 @@
|
||||
"oclif.manifest.json"
|
||||
],
|
||||
"bin": {
|
||||
"balena": "./bin/balena"
|
||||
"balena": "./bin/run.js"
|
||||
},
|
||||
"pkg": {
|
||||
"scripts": [
|
||||
@ -33,7 +34,6 @@
|
||||
],
|
||||
"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/**/*",
|
||||
@ -48,35 +48,36 @@
|
||||
"scripts": {
|
||||
"postinstall": "node patches/apply-patches.js",
|
||||
"prebuild": "rimraf build/ build-bin/",
|
||||
"pretarball": "npx tsx ../../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",
|
||||
"build:completion": "node completion/generate-completion.js",
|
||||
"build:standalone": "ts-node --transpile-only automation/run.ts build:standalone",
|
||||
"build:installer": "ts-node --transpile-only automation/run.ts build:installer",
|
||||
"build:doc": "npx tsx automation/capitanodoc/index.ts > docs/balena-cli.md",
|
||||
"build:completion": "node completion/generate-completion.cjs",
|
||||
"build:standalone": "npx tsx automation/run.ts build:standalone",
|
||||
"build:installer": "npx tsx 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:core",
|
||||
"test:core": "npm run test:source && npm run test:standalone",
|
||||
"test:shrinkwrap": "ts-node --transpile-only automation/run.ts test-shrinkwrap",
|
||||
"test:shrinkwrap": "npx tsx 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",
|
||||
"catch-uncommitted": "npx tsx 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",
|
||||
"update": "ts-node --transpile-only ./automation/update-module.ts",
|
||||
"prepare": "echo {} > bin/.fast-boot.json",
|
||||
"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": "npx tsx ./automation/update-module.ts",
|
||||
"prepare": "echo {} > bin/.fast-boot.json && husky",
|
||||
"prepublishOnly": "npm run build"
|
||||
},
|
||||
"keywords": [
|
||||
@ -91,17 +92,13 @@
|
||||
"author": "Balena Inc. (https://balena.io/)",
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": ">=20 <21"
|
||||
},
|
||||
"husky": {
|
||||
"hooks": {
|
||||
"pre-commit": "node automation/check-npm-version.js && ts-node automation/check-doc.ts"
|
||||
}
|
||||
"node": "^20.11.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"
|
||||
@ -111,26 +108,27 @@
|
||||
],
|
||||
"macos": {
|
||||
"identifier": "io.balena.cli",
|
||||
"sign": "Developer ID Installer: Balena Ltd (66H43P8FRG)"
|
||||
"sign": "\"Developer ID Installer: Balena Ltd (66H43P8FRG)\""
|
||||
}
|
||||
},
|
||||
"devDependencies": {
|
||||
"@balena/lint": "^7.2.1",
|
||||
"@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/chai-as-promised": "^8.0.0",
|
||||
"@types/cli-truncate": "^2.0.0",
|
||||
"@types/common-tags": "^1.8.1",
|
||||
"@types/diff": "^5.0.3",
|
||||
"@types/dockerode": "^3.3.9",
|
||||
"@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",
|
||||
@ -138,135 +136,126 @@
|
||||
"@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": "^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/rimraf": "^3.0.2",
|
||||
"@types/rewire": "^2.5.30",
|
||||
"@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/which": "^2.0.1",
|
||||
"@types/update-notifier": "^6.0.8",
|
||||
"@types/which": "^3.0.4",
|
||||
"@types/window-size": "^1.1.1",
|
||||
"archiver": "^5.3.0",
|
||||
"@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",
|
||||
"chai": "^5.1.1",
|
||||
"chai-as-promised": "^8.0.0",
|
||||
"cross-env": "^7.0.3",
|
||||
"deep-object-diff": "^1.1.0",
|
||||
"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",
|
||||
"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.3.2"
|
||||
"typescript": "^5.5.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@balena/compose": "^3.2.0",
|
||||
"@balena/compose": "^4.0.1",
|
||||
"@balena/dockerignore": "^1.0.2",
|
||||
"@balena/env-parsing": "^1.1.8",
|
||||
"@balena/es-version": "^1.0.1",
|
||||
"@oclif/core": "^3.14.1",
|
||||
"@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",
|
||||
"@yao-pkg/pkg": "^5.11.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": "^10.0.1",
|
||||
"balena-preload": "^15.0.1",
|
||||
"balena-sdk": "^19.4.0",
|
||||
"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": "9.0.6",
|
||||
"event-stream": "3.3.4",
|
||||
"etcher-sdk": "9.1.0",
|
||||
"express": "^4.17.2",
|
||||
"fast-boot2": "^1.1.0",
|
||||
"fast-levenshtein": "^3.0.0",
|
||||
"filenamify": "^4.3.0",
|
||||
"get-stdin": "^8.0.0",
|
||||
"glob": "^7.2.0",
|
||||
"get-stdin": "^9.0.0",
|
||||
"glob": "^11.0.0",
|
||||
"global-agent": "^2.2.0",
|
||||
"global-tunnel-ng": "^2.1.1",
|
||||
"got": "^11.8.3",
|
||||
"humanize": "0.0.9",
|
||||
"inquirer": "^7.3.3",
|
||||
"is-elevated": "^3.0.0",
|
||||
"is-root": "^2.1.0",
|
||||
"is-elevated": "^4.0.0",
|
||||
"is-root": "^3.0.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",
|
||||
"open": "^10.1.0",
|
||||
"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",
|
||||
"rimraf": "^6.0.1",
|
||||
"semver": "^7.3.5",
|
||||
"shell-escape": "^0.2.0",
|
||||
"split": "^1.0.1",
|
||||
@ -278,14 +267,19 @@
|
||||
"through2": "^2.0.3",
|
||||
"tmp": "^0.2.1",
|
||||
"typed-error": "^3.2.1",
|
||||
"update-notifier": "^5.1.0",
|
||||
"which": "^2.0.2",
|
||||
"update-notifier": "^7.3.0",
|
||||
"which": "^4.0.0",
|
||||
"window-size": "^1.1.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"windosu": "^0.3.0"
|
||||
},
|
||||
"overrides": {
|
||||
"inline-source-cli": {
|
||||
"inline-source": "^8.0.3"
|
||||
}
|
||||
},
|
||||
"versionist": {
|
||||
"publishedAt": "2024-02-06T12:19:36.007Z"
|
||||
"publishedAt": "2024-09-03T14:56:14.237Z"
|
||||
}
|
||||
}
|
||||
|
@ -1,51 +1,22 @@
|
||||
diff --git a/node_modules/@oclif/core/lib/cli-ux/list.js b/node_modules/@oclif/core/lib/cli-ux/list.js
|
||||
index 607d8dc..07ba1f2 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 63c0545..7caad4a 100644
|
||||
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,7 @@ class CommandHelp extends formatter_1.HelpFormatter {
|
||||
if (args.filter((a) => a.description).length === 0)
|
||||
@@ -58,7 +58,8 @@ class CommandHelp extends formatter_1.HelpFormatter {
|
||||
return;
|
||||
return args.map((a) => {
|
||||
- const name = a.name.toUpperCase();
|
||||
+ const name = a.required ? `<${a.name}>` : `[${a.name}]`;
|
||||
// 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}`;
|
||||
@@ -153,14 +153,12 @@ class CommandHelp extends formatter_1.HelpFormatter {
|
||||
label = labels.join(flag.char ? (0, theme_1.colorize)(this.config?.theme?.flagSeparator, ', ') : ' ');
|
||||
}
|
||||
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 = chalk_1.default.underline(value);
|
||||
+ value += ' ...';
|
||||
label += `=${value}`;
|
||||
}
|
||||
return (0, theme_1.colorize)(this.config.theme?.flag, label);
|
||||
diff --git a/node_modules/@oclif/core/lib/help/index.js b/node_modules/@oclif/core/lib/help/index.js
|
||||
index 242538a..efde8ac 100644
|
||||
index 4a34b89..d7eb6ac 100644
|
||||
--- a/node_modules/@oclif/core/lib/help/index.js
|
||||
+++ b/node_modules/@oclif/core/lib/help/index.js
|
||||
@@ -168,11 +168,12 @@ class Help extends HelpBase {
|
||||
@@ -172,11 +172,12 @@ class Help extends HelpBase {
|
||||
}
|
||||
this.log(this.formatCommand(command));
|
||||
this.log('');
|
||||
@ -56,17 +27,17 @@ index 242538a..efde8ac 100644
|
||||
this.log('');
|
||||
}
|
||||
- if (subCommands.length > 0) {
|
||||
+ if (subTopics.length > 0 && !SUPPRESS_SUBTOPICS) {
|
||||
+ 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 656ec6b..2bbf36b 100644
|
||||
index 168da99..538a880 100644
|
||||
--- a/node_modules/@oclif/core/lib/parser/errors.js
|
||||
+++ b/node_modules/@oclif/core/lib/parser/errors.js
|
||||
@@ -14,7 +14,8 @@ Object.defineProperty(exports, "CLIError", { enumerable: true, get: function ()
|
||||
class CLIParseError extends errors_1.CLIError {
|
||||
@@ -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';
|
||||
@ -74,7 +45,7 @@ index 656ec6b..2bbf36b 100644
|
||||
super(options.message, { exit: options.exit });
|
||||
this.parse = options.parse;
|
||||
}
|
||||
@@ -37,7 +38,8 @@ exports.InvalidArgsSpecError = InvalidArgsSpecError;
|
||||
@@ -38,7 +39,8 @@ exports.InvalidArgsSpecError = InvalidArgsSpecError;
|
||||
class RequiredArgsError extends CLIParseError {
|
||||
args;
|
||||
constructor({ args, exit, flagsWithMultiple, parse, }) {
|
||||
@ -83,13 +54,26 @@ index 656ec6b..2bbf36b 100644
|
||||
+ 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]));
|
||||
@@ -48,7 +50,7 @@ class RequiredArgsError extends CLIParseError {
|
||||
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');
|
||||
}
|
@ -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;
|
35
patches/all/oclif+4.14.0.dev.patch
Normal file
35
patches/all/oclif+4.14.0.dev.patch
Normal 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);
|
@ -15,23 +15,26 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import * as packageJSON from '../package.json';
|
||||
import type { AppOptions } from './preparser.js';
|
||||
import {
|
||||
AppOptions,
|
||||
checkDeletedCommand,
|
||||
preparseArgs,
|
||||
unsupportedFlag,
|
||||
} from './preparser';
|
||||
import { CliSettings } from './utils/bootstrap';
|
||||
import { onceAsync } from './utils/lazy';
|
||||
} from './preparser.js';
|
||||
import { CliSettings } from './utils/bootstrap.js';
|
||||
import { onceAsync, getPackageJson } from './utils/lazy.js';
|
||||
import { run as mainRun, settings } from '@oclif/core';
|
||||
import { Module } from 'node:module';
|
||||
|
||||
const require = Module.createRequire(import.meta.url);
|
||||
const packageJSON = getPackageJson();
|
||||
|
||||
/**
|
||||
* Sentry.io setup
|
||||
* @see https://docs.sentry.io/error-reporting/quickstart/?platform=node
|
||||
*/
|
||||
export const setupSentry = onceAsync(async () => {
|
||||
const config = await import('./config');
|
||||
const config = await import('./config.js');
|
||||
const Sentry = await import('@sentry/node');
|
||||
Sentry.init({
|
||||
autoSessionTracking: false,
|
||||
@ -51,7 +54,7 @@ export const setupSentry = onceAsync(async () => {
|
||||
async function checkNodeVersion() {
|
||||
const validNodeVersions = packageJSON.engines.node;
|
||||
if (!(await import('semver')).satisfies(process.version, validNodeVersions)) {
|
||||
const { getNodeEngineVersionWarn } = await import('./utils/messages');
|
||||
const { getNodeEngineVersionWarn } = await import('./utils/messages.js');
|
||||
console.warn(getNodeEngineVersionWarn(process.version, validNodeVersions));
|
||||
}
|
||||
}
|
||||
@ -89,13 +92,13 @@ async function init() {
|
||||
const settings = new CliSettings();
|
||||
|
||||
// Proxy setup should be done early on, before loading balena-sdk
|
||||
await (await import('./utils/proxy')).setupGlobalHttpProxy(settings);
|
||||
await (await import('./utils/proxy.js')).setupGlobalHttpProxy(settings);
|
||||
|
||||
setupBalenaSdkSharedOptions(settings);
|
||||
|
||||
// check for CLI updates once a day
|
||||
if (!process.env.BALENARC_OFFLINE_MODE) {
|
||||
(await import('./utils/update')).notify();
|
||||
(await import('./utils/update.js')).notify();
|
||||
}
|
||||
}
|
||||
|
||||
@ -106,7 +109,7 @@ async function oclifRun(command: string[], options: AppOptions) {
|
||||
if (unsupportedFlag || process.env.BALENARC_UNSUPPORTED) {
|
||||
deprecationPromise = Promise.resolve();
|
||||
} else {
|
||||
const { DeprecationChecker } = await import('./deprecation');
|
||||
const { DeprecationChecker } = await import('./deprecation.js');
|
||||
const deprecationChecker = new DeprecationChecker(packageJSON.version);
|
||||
// warnAndAbortIfDeprecated uses previously cached data only
|
||||
await deprecationChecker.warnAndAbortIfDeprecated();
|
||||
@ -137,7 +140,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.
|
||||
@ -148,20 +152,20 @@ async function oclifRun(command: string[], options: AppOptions) {
|
||||
// the try/catch block above, execution does not get past the
|
||||
// Promise.all() call below, but I don't understand why.
|
||||
if (isEEXIT) {
|
||||
(await import('./fast-boot')).stop();
|
||||
(await import('./fast-boot.js')).stop();
|
||||
}
|
||||
})(!options.noFlush);
|
||||
|
||||
const { trackPromise } = await import('./hooks/prerun/track');
|
||||
const { trackPromise } = await import('./hooks/prerun/track.js');
|
||||
|
||||
await Promise.all([trackPromise, deprecationPromise, runPromise]);
|
||||
}
|
||||
|
||||
/** CLI entrypoint. Called by the `bin/balena` and `bin/balena-dev` scripts. */
|
||||
/** 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'
|
||||
'./utils/bootstrap.js'
|
||||
);
|
||||
setOfflineModeEnvVars();
|
||||
normalizeEnvVars();
|
||||
@ -175,15 +179,15 @@ export async function run(cliArgs = process.argv, options: AppOptions) {
|
||||
await init();
|
||||
|
||||
// Look for commands that have been removed and if so, exit with a notice
|
||||
checkDeletedCommand(cliArgs.slice(2));
|
||||
await checkDeletedCommand(cliArgs.slice(2));
|
||||
|
||||
const args = await preparseArgs(cliArgs);
|
||||
await oclifRun(args, options);
|
||||
} catch (err) {
|
||||
await (await import('./errors')).handleError(err);
|
||||
await (await import('./errors.js')).handleError(err);
|
||||
} finally {
|
||||
try {
|
||||
(await import('./fast-boot')).stop();
|
||||
(await import('./fast-boot.js')).stop();
|
||||
} catch (e) {
|
||||
if (process.env.DEBUG) {
|
||||
console.error(`[debug] Stopping fast-boot: ${e}`);
|
@ -14,8 +14,8 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import { getBalenaSdk } from '../utils/lazy';
|
||||
import { LoginServer } from './server';
|
||||
import { getBalenaSdk } from '../utils/lazy.js';
|
||||
import { LoginServer } from './server.js';
|
||||
|
||||
/**
|
||||
* @module auth
|
||||
@ -42,7 +42,7 @@ import { LoginServer } from './server';
|
||||
* console.log("My session token is: #{sessionToken}")
|
||||
*/
|
||||
export async function login({ host = '127.0.0.1', port = 0 }) {
|
||||
const utils = await import('./utils');
|
||||
const utils = await import('./utils.js');
|
||||
|
||||
const loginServer = new LoginServer();
|
||||
const {
|
||||
@ -55,7 +55,7 @@ export async function login({ host = '127.0.0.1', port = 0 }) {
|
||||
const loginUrl = await utils.getDashboardLoginURL(callbackUrl);
|
||||
|
||||
console.info(`Opening web browser for URL:\n${loginUrl}`);
|
||||
const open = await import('open');
|
||||
const { default: open } = await import('open');
|
||||
await open(loginUrl, { wait: false });
|
||||
|
||||
const balena = getBalenaSdk();
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.6 KiB |
@ -14,14 +14,14 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import * as bodyParser from 'body-parser';
|
||||
import bodyParser from 'body-parser';
|
||||
import { EventEmitter } from 'events';
|
||||
import * as express from 'express';
|
||||
import express from 'express';
|
||||
import type { Socket } from 'net';
|
||||
import * as path from 'path';
|
||||
import path from 'path';
|
||||
|
||||
import * as utils from './utils';
|
||||
import { ExpectedError } from '../errors';
|
||||
import * as utils from './utils.js';
|
||||
import { ExpectedError } from '../errors.js';
|
||||
|
||||
export class LoginServer extends EventEmitter {
|
||||
protected expressApp: express.Express;
|
||||
@ -56,7 +56,7 @@ export class LoginServer extends EventEmitter {
|
||||
);
|
||||
|
||||
app.set('view engine', 'ejs');
|
||||
app.set('views', path.join(__dirname, 'pages'));
|
||||
app.set('views', path.join(import.meta.dirname, 'pages'));
|
||||
|
||||
this.server = await new Promise<import('net').Server>((resolve, reject) => {
|
||||
const callback = (err: Error) => {
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import { getBalenaSdk } from '../utils/lazy';
|
||||
import { getBalenaSdk } from '../utils/lazy.js';
|
||||
|
||||
/**
|
||||
* Get dashboard CLI login URL
|
@ -19,9 +19,8 @@ import { Command } from '@oclif/core';
|
||||
import {
|
||||
InsufficientPrivilegesError,
|
||||
NotAvailableInOfflineModeError,
|
||||
} from './errors';
|
||||
import { stripIndent } from './utils/lazy';
|
||||
import * as output from './framework/output';
|
||||
} from './errors.js';
|
||||
import { stripIndent } from './utils/lazy.js';
|
||||
|
||||
export default abstract class BalenaCommand extends Command {
|
||||
/**
|
||||
@ -71,7 +70,7 @@ export default abstract class BalenaCommand extends Command {
|
||||
* - other code needs to execute before check
|
||||
*/
|
||||
protected static async checkElevatedPrivileges() {
|
||||
const isElevated = await (await import('is-elevated'))();
|
||||
const isElevated = await (await import('is-elevated')).default();
|
||||
if (!isElevated) {
|
||||
throw new InsufficientPrivilegesError(
|
||||
'You need root/admin privileges to run this command',
|
||||
@ -94,7 +93,7 @@ export default abstract class BalenaCommand extends Command {
|
||||
* @throws {NotLoggedInError}
|
||||
*/
|
||||
public static async checkLoggedIn() {
|
||||
await (await import('./utils/patterns')).checkLoggedIn();
|
||||
await (await import('./utils/patterns.js')).checkLoggedIn();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -139,14 +138,14 @@ export default abstract class BalenaCommand extends Command {
|
||||
* values from stdin based in configuration, minimising command implementation.
|
||||
*/
|
||||
protected async getStdin() {
|
||||
this.stdin = await (await import('get-stdin'))();
|
||||
this.stdin = await (await import('get-stdin')).default();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a logger instance.
|
||||
*/
|
||||
protected static async getLogger() {
|
||||
return (await import('./utils/logger')).getLogger();
|
||||
return (await import('./utils/logger.js')).default.getLogger();
|
||||
}
|
||||
|
||||
protected async init() {
|
||||
@ -168,7 +167,4 @@ export default abstract class BalenaCommand extends Command {
|
||||
await this.getStdin();
|
||||
}
|
||||
}
|
||||
|
||||
protected outputMessage = output.outputMessage;
|
||||
protected outputData = output.outputData;
|
||||
}
|
@ -16,10 +16,10 @@
|
||||
*/
|
||||
|
||||
import { Args } from '@oclif/core';
|
||||
import Command from '../../command';
|
||||
import { ExpectedError } from '../../errors';
|
||||
import * as cf from '../../utils/common-flags';
|
||||
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
|
||||
import Command from '../../command.js';
|
||||
import { ExpectedError } from '../../errors.js';
|
||||
import * as cf from '../../utils/common-flags.js';
|
||||
import { getBalenaSdk, stripIndent } from '../../utils/lazy.js';
|
||||
|
||||
export default class GenerateCmd extends Command {
|
||||
public static description = stripIndent`
|
@ -16,9 +16,9 @@
|
||||
*/
|
||||
|
||||
import { Args } from '@oclif/core';
|
||||
import Command from '../../command';
|
||||
import * as cf from '../../utils/common-flags';
|
||||
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
|
||||
import Command from '../../command.js';
|
||||
import * as cf from '../../utils/common-flags.js';
|
||||
import { getBalenaSdk, stripIndent } from '../../utils/lazy.js';
|
||||
|
||||
export default class RevokeCmd extends Command {
|
||||
public static description = stripIndent`
|
@ -16,9 +16,9 @@
|
||||
*/
|
||||
|
||||
import { Flags } from '@oclif/core';
|
||||
import Command from '../../command';
|
||||
import * as cf from '../../utils/common-flags';
|
||||
import { getBalenaSdk, getVisuals, stripIndent } from '../../utils/lazy';
|
||||
import Command from '../../command.js';
|
||||
import * as cf from '../../utils/common-flags.js';
|
||||
import { getBalenaSdk, getVisuals, stripIndent } from '../../utils/lazy.js';
|
||||
|
||||
export default class ApiKeysCmd extends Command {
|
||||
public static description = stripIndent`
|
||||
@ -46,13 +46,13 @@ export default class ApiKeysCmd extends Command {
|
||||
public async run() {
|
||||
const { flags: options } = await this.parse(ApiKeysCmd);
|
||||
|
||||
const { getApplication } = await import('../../utils/sdk');
|
||||
const { getApplication } = await import('../../utils/sdk.js');
|
||||
const actorId = options.fleet
|
||||
? (
|
||||
await getApplication(getBalenaSdk(), options.fleet, {
|
||||
$select: 'actor',
|
||||
})
|
||||
).actor
|
||||
).actor
|
||||
: await getBalenaSdk().auth.getActorId();
|
||||
const keys = await getBalenaSdk().pine.get({
|
||||
resource: 'api_key',
|
||||
@ -65,7 +65,7 @@ export default class ApiKeysCmd extends Command {
|
||||
name: {
|
||||
$ne: null,
|
||||
},
|
||||
}
|
||||
}
|
||||
: {}),
|
||||
},
|
||||
$orderby: 'name asc',
|
@ -17,9 +17,9 @@
|
||||
|
||||
import { Flags, Args } from '@oclif/core';
|
||||
|
||||
import Command from '../../command';
|
||||
import * as cf from '../../utils/common-flags';
|
||||
import { stripIndent } from '../../utils/lazy';
|
||||
import Command from '../../command.js';
|
||||
import * as cf from '../../utils/common-flags.js';
|
||||
import { stripIndent } from '../../utils/lazy.js';
|
||||
|
||||
export default class AppCreateCmd extends Command {
|
||||
public static description = stripIndent`
|
||||
@ -77,7 +77,7 @@ export default class AppCreateCmd extends Command {
|
||||
const { args: params, flags: options } = await this.parse(AppCreateCmd);
|
||||
|
||||
await (
|
||||
await import('../../utils/application-create')
|
||||
await import('../../utils/application-create.js')
|
||||
).applicationCreateBase('app', options, params);
|
||||
}
|
||||
}
|
@ -17,9 +17,9 @@
|
||||
|
||||
import { Flags, Args } from '@oclif/core';
|
||||
|
||||
import Command from '../../command';
|
||||
import * as cf from '../../utils/common-flags';
|
||||
import { stripIndent } from '../../utils/lazy';
|
||||
import Command from '../../command.js';
|
||||
import * as cf from '../../utils/common-flags.js';
|
||||
import { stripIndent } from '../../utils/lazy.js';
|
||||
|
||||
export default class BlockCreateCmd extends Command {
|
||||
public static description = stripIndent`
|
||||
@ -77,7 +77,7 @@ export default class BlockCreateCmd extends Command {
|
||||
const { args: params, flags: options } = await this.parse(BlockCreateCmd);
|
||||
|
||||
await (
|
||||
await import('../../utils/application-create')
|
||||
await import('../../utils/application-create.js')
|
||||
).applicationCreateBase('block', options, params);
|
||||
}
|
||||
}
|
@ -16,20 +16,30 @@
|
||||
*/
|
||||
|
||||
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.js';
|
||||
import { getBalenaSdk } from '../../utils/lazy.js';
|
||||
import * as cf from '../../utils/common-flags.js';
|
||||
import * as compose from '../../utils/compose.js';
|
||||
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.js';
|
||||
import type {
|
||||
ComposeCliFlags,
|
||||
ComposeOpts,
|
||||
} from '../../utils/compose-types.js';
|
||||
import { buildProject, composeCliFlags } from '../../utils/compose_ts.js';
|
||||
import type { BuildOpts, DockerCliFlags } from '../../utils/docker.js';
|
||||
import { dockerCliFlags } from '../../utils/docker.js';
|
||||
import type Dockerode from 'dockerode';
|
||||
|
||||
// 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 +77,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 +125,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 +140,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 +161,16 @@ ${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.js');
|
||||
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.js'
|
||||
);
|
||||
const { dockerfilePath, registrySecrets } = await validateProjectDirectory(
|
||||
sdk,
|
||||
{
|
||||
@ -170,9 +185,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.js');
|
||||
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.js');
|
||||
const app = await getAppWithArch(opts.fleet);
|
||||
opts.arch = app.arch;
|
||||
opts.deviceType = app.is_for__device_type[0].slug;
|
||||
@ -180,8 +228,14 @@ ${dockerignoreHelp}
|
||||
}
|
||||
}
|
||||
|
||||
protected async prepareBuild(options: FlagsDef) {
|
||||
const { getDocker, generateBuildOpts } = await import('../../utils/docker');
|
||||
protected async prepareBuild(options: FlagsDef): Promise<{
|
||||
docker: Dockerode;
|
||||
buildOpts: BuildOpts;
|
||||
composeOpts: ComposeOpts;
|
||||
}> {
|
||||
const { getDocker, generateBuildOpts } = await import(
|
||||
'../../utils/docker.js'
|
||||
);
|
||||
const [docker, buildOpts, composeOpts] = await Promise.all([
|
||||
getDocker(options),
|
||||
generateBuildOpts(options),
|
||||
@ -209,19 +263,17 @@ ${dockerignoreHelp}
|
||||
*/
|
||||
protected async buildProject(
|
||||
docker: import('dockerode'),
|
||||
logger: import('../../utils/logger'),
|
||||
logger: import('../../utils/logger.js').default,
|
||||
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.js');
|
||||
|
||||
const project = await loadProject(
|
||||
logger,
|
||||
@ -230,11 +282,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' +
|
@ -17,14 +17,14 @@
|
||||
|
||||
import { Flags } from '@oclif/core';
|
||||
import type { Interfaces } from '@oclif/core';
|
||||
import Command from '../../command';
|
||||
import * as cf from '../../utils/common-flags';
|
||||
import { getBalenaSdk, getCliForm, stripIndent } from '../../utils/lazy';
|
||||
import Command from '../../command.js';
|
||||
import * as cf from '../../utils/common-flags.js';
|
||||
import { getBalenaSdk, getCliForm, stripIndent } from '../../utils/lazy.js';
|
||||
import {
|
||||
applicationIdInfo,
|
||||
devModeInfo,
|
||||
secureBootInfo,
|
||||
} from '../../utils/messages';
|
||||
} from '../../utils/messages.js';
|
||||
import type { BalenaSDK, PineDeferred } from 'balena-sdk';
|
||||
|
||||
export default class ConfigGenerateCmd extends Command {
|
||||
@ -67,17 +67,14 @@ export default class ConfigGenerateCmd extends Command {
|
||||
description: 'a balenaOS version',
|
||||
required: true,
|
||||
}),
|
||||
fleet: { ...cf.fleet, exclusive: ['device'] },
|
||||
fleet: cf.fleetExclusive(['device']),
|
||||
dev: cf.dev,
|
||||
secureBoot: cf.secureBoot,
|
||||
device: {
|
||||
...cf.device,
|
||||
exclusive: [
|
||||
'fleet',
|
||||
'provisioning-key-name',
|
||||
'provisioning-key-expiry-date',
|
||||
],
|
||||
},
|
||||
device: cf.deviceExclusive([
|
||||
'fleet',
|
||||
'provisioning-key-name',
|
||||
'provisioning-key-expiry-date',
|
||||
]),
|
||||
deviceApiKey: Flags.string({
|
||||
description:
|
||||
'custom device key - note that this is only supported on balenaOS 2.0.3+',
|
||||
@ -126,7 +123,7 @@ export default class ConfigGenerateCmd extends Command {
|
||||
public static authenticated = true;
|
||||
|
||||
public async getApplication(balena: BalenaSDK, fleet: string) {
|
||||
const { getApplication } = await import('../../utils/sdk');
|
||||
const { getApplication } = await import('../../utils/sdk.js');
|
||||
return await getApplication(balena, fleet, {
|
||||
$select: 'slug',
|
||||
$expand: {
|
||||
@ -152,7 +149,7 @@ export default class ConfigGenerateCmd extends Command {
|
||||
$expand: { is_of__device_type: { $select: 'slug' } },
|
||||
});
|
||||
if (!rawDevice.belongs_to__application) {
|
||||
const { ExpectedError } = await import('../../errors');
|
||||
const { ExpectedError } = await import('../../errors.js');
|
||||
throw new ExpectedError(stripIndent`
|
||||
Device ${options.device} does not appear to belong to an accessible fleet.
|
||||
Try with a different device, or use '--fleet' instead of '--device'.`);
|
||||
@ -171,14 +168,14 @@ export default class ConfigGenerateCmd extends Command {
|
||||
|
||||
// Check compatibility if application and deviceType provided
|
||||
if (options.fleet && options.deviceType) {
|
||||
const helpers = await import('../../utils/helpers');
|
||||
const helpers = await import('../../utils/helpers.js');
|
||||
if (
|
||||
!(await helpers.areDeviceTypesCompatible(
|
||||
resourceDeviceType,
|
||||
deviceType,
|
||||
))
|
||||
) {
|
||||
const { ExpectedError } = await import('../../errors');
|
||||
const { ExpectedError } = await import('../../errors.js');
|
||||
throw new ExpectedError(
|
||||
`Device type ${options.deviceType} is incompatible with fleet ${options.fleet}`,
|
||||
);
|
||||
@ -189,7 +186,7 @@ export default class ConfigGenerateCmd extends Command {
|
||||
await balena.models.config.getDeviceTypeManifestBySlug(deviceType);
|
||||
|
||||
const { validateSecureBootOptionAndWarn } = await import(
|
||||
'../../utils/config'
|
||||
'../../utils/config.js'
|
||||
);
|
||||
await validateSecureBootOptionAndWarn(
|
||||
options.secureBoot,
|
||||
@ -211,7 +208,7 @@ export default class ConfigGenerateCmd extends Command {
|
||||
|
||||
// Generate config
|
||||
const { generateDeviceConfig, generateApplicationConfig } = await import(
|
||||
'../../utils/config'
|
||||
'../../utils/config.js'
|
||||
);
|
||||
|
||||
let config;
|
||||
@ -250,7 +247,7 @@ export default class ConfigGenerateCmd extends Command {
|
||||
protected async validateOptions(
|
||||
options: Interfaces.InferredFlags<typeof ConfigGenerateCmd.flags>,
|
||||
) {
|
||||
const { ExpectedError } = await import('../../errors');
|
||||
const { ExpectedError } = await import('../../errors.js');
|
||||
|
||||
if (options.device == null && options.fleet == null) {
|
||||
throw new ExpectedError(this.missingDeviceOrAppMessage);
|
||||
@ -259,9 +256,9 @@ export default class ConfigGenerateCmd extends Command {
|
||||
if (!options.fleet && options.deviceType) {
|
||||
throw new ExpectedError(this.deviceTypeNotAllowedMessage);
|
||||
}
|
||||
const { normalizeOsVersion } = await import('../../utils/normalization');
|
||||
const { normalizeOsVersion } = await import('../../utils/normalization.js');
|
||||
options.version = normalizeOsVersion(options.version);
|
||||
const { validateDevOptionAndWarn } = await import('../../utils/config');
|
||||
const { validateDevOptionAndWarn } = await import('../../utils/config.js');
|
||||
await validateDevOptionAndWarn(options.dev, options.version);
|
||||
}
|
||||
}
|
@ -16,9 +16,9 @@
|
||||
*/
|
||||
|
||||
import { Args } from '@oclif/core';
|
||||
import Command from '../../command';
|
||||
import * as cf from '../../utils/common-flags';
|
||||
import { getVisuals, stripIndent } from '../../utils/lazy';
|
||||
import Command from '../../command.js';
|
||||
import * as cf from '../../utils/common-flags.js';
|
||||
import { getVisuals, stripIndent } from '../../utils/lazy.js';
|
||||
|
||||
export default class ConfigInjectCmd extends Command {
|
||||
public static description = stripIndent`
|
||||
@ -56,7 +56,7 @@ export default class ConfigInjectCmd extends Command {
|
||||
public async run() {
|
||||
const { args: params, flags: options } = await this.parse(ConfigInjectCmd);
|
||||
|
||||
const { safeUmount } = await import('../../utils/umount');
|
||||
const { safeUmount } = await import('../../utils/umount.js');
|
||||
|
||||
const drive =
|
||||
options.drive || (await getVisuals().drive('Select the device/OS drive'));
|
@ -15,9 +15,9 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import Command from '../../command';
|
||||
import * as cf from '../../utils/common-flags';
|
||||
import { getVisuals, stripIndent } from '../../utils/lazy';
|
||||
import Command from '../../command.js';
|
||||
import * as cf from '../../utils/common-flags.js';
|
||||
import { getVisuals, stripIndent } from '../../utils/lazy.js';
|
||||
|
||||
export default class ConfigReadCmd extends Command {
|
||||
public static description = stripIndent`
|
||||
@ -50,7 +50,7 @@ export default class ConfigReadCmd extends Command {
|
||||
public async run() {
|
||||
const { flags: options } = await this.parse(ConfigReadCmd);
|
||||
|
||||
const { safeUmount } = await import('../../utils/umount');
|
||||
const { safeUmount } = await import('../../utils/umount.js');
|
||||
|
||||
const drive =
|
||||
options.drive || (await getVisuals().drive('Select the device drive'));
|
@ -16,9 +16,9 @@
|
||||
*/
|
||||
|
||||
import { Flags } from '@oclif/core';
|
||||
import Command from '../../command';
|
||||
import * as cf from '../../utils/common-flags';
|
||||
import { getVisuals, stripIndent } from '../../utils/lazy';
|
||||
import Command from '../../command.js';
|
||||
import * as cf from '../../utils/common-flags.js';
|
||||
import { getVisuals, stripIndent } from '../../utils/lazy.js';
|
||||
|
||||
export default class ConfigReconfigureCmd extends Command {
|
||||
public static description = stripIndent`
|
||||
@ -59,7 +59,7 @@ export default class ConfigReconfigureCmd extends Command {
|
||||
public async run() {
|
||||
const { flags: options } = await this.parse(ConfigReconfigureCmd);
|
||||
|
||||
const { safeUmount } = await import('../../utils/umount');
|
||||
const { safeUmount } = await import('../../utils/umount.js');
|
||||
|
||||
const drive =
|
||||
options.drive || (await getVisuals().drive('Select the device drive'));
|
||||
@ -70,7 +70,7 @@ export default class ConfigReconfigureCmd extends Command {
|
||||
await safeUmount(drive);
|
||||
|
||||
if (!uuid) {
|
||||
const { ExpectedError } = await import('../../errors');
|
||||
const { ExpectedError } = await import('../../errors.js');
|
||||
throw new ExpectedError(
|
||||
`Error: UUID not found in 'config.json' file for '${drive}'`,
|
||||
);
|
||||
@ -84,7 +84,7 @@ export default class ConfigReconfigureCmd extends Command {
|
||||
configureCommand.push('--advanced');
|
||||
}
|
||||
|
||||
const { runCommand } = await import('../../utils/helpers');
|
||||
const { runCommand } = await import('../../utils/helpers.js');
|
||||
await runCommand(configureCommand);
|
||||
|
||||
console.info('Done');
|
@ -16,9 +16,9 @@
|
||||
*/
|
||||
|
||||
import { Args } from '@oclif/core';
|
||||
import Command from '../../command';
|
||||
import * as cf from '../../utils/common-flags';
|
||||
import { getVisuals, stripIndent } from '../../utils/lazy';
|
||||
import Command from '../../command.js';
|
||||
import * as cf from '../../utils/common-flags.js';
|
||||
import { getVisuals, stripIndent } from '../../utils/lazy.js';
|
||||
|
||||
export default class ConfigWriteCmd extends Command {
|
||||
public static description = stripIndent`
|
||||
@ -61,7 +61,7 @@ export default class ConfigWriteCmd extends Command {
|
||||
public async run() {
|
||||
const { args: params, flags: options } = await this.parse(ConfigWriteCmd);
|
||||
|
||||
const { denyMount, safeUmount } = await import('../../utils/umount');
|
||||
const { denyMount, safeUmount } = await import('../../utils/umount.js');
|
||||
|
||||
const drive =
|
||||
options.drive || (await getVisuals().drive('Select the device drive'));
|
@ -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.js';
|
||||
import { ExpectedError } from '../../errors.js';
|
||||
import { getBalenaSdk, getChalk, stripIndent } from '../../utils/lazy.js';
|
||||
import {
|
||||
dockerignoreHelp,
|
||||
registrySecretsHelp,
|
||||
buildArgDeprecation,
|
||||
} from '../../utils/messages';
|
||||
import * as ca from '../../utils/common-args';
|
||||
import * as compose from '../../utils/compose';
|
||||
} from '../../utils/messages.js';
|
||||
import * as ca from '../../utils/common-args.js';
|
||||
import * as compose from '../../utils/compose.js';
|
||||
import type {
|
||||
BuiltImage,
|
||||
ComposeCliFlags,
|
||||
ComposeOpts,
|
||||
Release as ComposeReleaseInfo,
|
||||
} from '../../utils/compose-types';
|
||||
import type { BuildOpts, DockerCliFlags } from '../../utils/docker';
|
||||
} from '../../utils/compose-types.js';
|
||||
import type { BuildOpts, DockerCliFlags } from '../../utils/docker.js';
|
||||
import {
|
||||
applyReleaseTagKeysAndValues,
|
||||
buildProject,
|
||||
composeCliFlags,
|
||||
isBuildConfig,
|
||||
parseReleaseTagKeysAndValues,
|
||||
} from '../../utils/compose_ts';
|
||||
import { dockerCliFlags } from '../../utils/docker';
|
||||
} from '../../utils/compose_ts.js';
|
||||
import { dockerCliFlags } from '../../utils/docker.js';
|
||||
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.js'
|
||||
);
|
||||
|
||||
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.js');
|
||||
const app = await helpers.getAppWithArch(fleet);
|
||||
|
||||
const dockerUtils = await import('../../utils/docker');
|
||||
const dockerUtils = await import('../../utils/docker.js');
|
||||
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.js').default,
|
||||
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.js'
|
||||
);
|
||||
|
||||
const appType = opts.app.application_type[0];
|
||||
@ -321,7 +321,7 @@ ${dockerignoreHelp}
|
||||
builtImagesByService = _.keyBy(builtImages, 'serviceName');
|
||||
}
|
||||
const images: BuiltImage[] = project.descriptors.map(
|
||||
(d) =>
|
||||
(d: ImageDescriptor) =>
|
||||
builtImagesByService[d.serviceName] ?? {
|
||||
serviceName: d.serviceName,
|
||||
name: (isBuildConfig(d.image) ? d.image.tag : d.image) || '',
|
||||
@ -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,
|
@ -16,9 +16,9 @@
|
||||
*/
|
||||
|
||||
import { Args } from '@oclif/core';
|
||||
import Command from '../../command';
|
||||
import * as cf from '../../utils/common-flags';
|
||||
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
|
||||
import Command from '../../command.js';
|
||||
import * as cf from '../../utils/common-flags.js';
|
||||
import { getBalenaSdk, stripIndent } from '../../utils/lazy.js';
|
||||
|
||||
export default class DeviceDeactivateCmd extends Command {
|
||||
public static description = stripIndent`
|
||||
@ -55,7 +55,7 @@ export default class DeviceDeactivateCmd extends Command {
|
||||
await this.parse(DeviceDeactivateCmd);
|
||||
|
||||
const balena = getBalenaSdk();
|
||||
const patterns = await import('../../utils/patterns');
|
||||
const patterns = await import('../../utils/patterns.js');
|
||||
|
||||
const uuid = params.uuid;
|
||||
const deactivationWarning = `
|
@ -16,10 +16,10 @@
|
||||
*/
|
||||
|
||||
import { Args } from '@oclif/core';
|
||||
import Command from '../../command';
|
||||
import * as cf from '../../utils/common-flags';
|
||||
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
|
||||
import { ExpectedError } from '../../errors';
|
||||
import Command from '../../command.js';
|
||||
import * as cf from '../../utils/common-flags.js';
|
||||
import { getBalenaSdk, stripIndent } from '../../utils/lazy.js';
|
||||
import { ExpectedError } from '../../errors.js';
|
||||
|
||||
export default class DeviceIdentifyCmd extends Command {
|
||||
public static description = stripIndent`
|
@ -16,11 +16,11 @@
|
||||
*/
|
||||
|
||||
import { Flags, Args } from '@oclif/core';
|
||||
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 Command from '../../command.js';
|
||||
import * as cf from '../../utils/common-flags.js';
|
||||
import { expandForAppName } from '../../utils/helpers.js';
|
||||
import { getBalenaSdk, getVisuals, stripIndent } from '../../utils/lazy.js';
|
||||
import { jsonInfo } from '../../utils/messages.js';
|
||||
|
||||
import type { Application, Release } from 'balena-sdk';
|
||||
|
||||
@ -91,7 +91,7 @@ export default class DeviceCmd extends Command {
|
||||
},
|
||||
...expandForAppName.$expand,
|
||||
},
|
||||
}
|
||||
}
|
||||
: {
|
||||
$select: [
|
||||
'device_name',
|
||||
@ -118,11 +118,11 @@ export default class DeviceCmd extends Command {
|
||||
'is_undervolted',
|
||||
],
|
||||
...expandForAppName,
|
||||
},
|
||||
},
|
||||
)) as ExtendedDevice;
|
||||
|
||||
if (options.view) {
|
||||
const open = await import('open');
|
||||
const { default: open } = await import('open');
|
||||
const dashboardUrl = balena.models.device.getDashboardUrl(device.uuid);
|
||||
await open(dashboardUrl, { wait: false });
|
||||
return;
|
@ -16,11 +16,11 @@
|
||||
*/
|
||||
|
||||
import { Flags } from '@oclif/core';
|
||||
import Command from '../../command';
|
||||
import * as cf from '../../utils/common-flags';
|
||||
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
|
||||
import { applicationIdInfo } from '../../utils/messages';
|
||||
import { runCommand } from '../../utils/helpers';
|
||||
import Command from '../../command.js';
|
||||
import * as cf from '../../utils/common-flags.js';
|
||||
import { getBalenaSdk, stripIndent } from '../../utils/lazy.js';
|
||||
import { applicationIdInfo } from '../../utils/messages.js';
|
||||
import { runCommand } from '../../utils/helpers.js';
|
||||
|
||||
interface FlagsDef {
|
||||
fleet?: string;
|
||||
@ -113,12 +113,12 @@ export default class DeviceInitCmd extends Command {
|
||||
|
||||
// Imports
|
||||
const { promisify } = await import('util');
|
||||
const rimraf = promisify(await import('rimraf'));
|
||||
const { rimraf } = await import('rimraf');
|
||||
const tmp = await import('tmp');
|
||||
const tmpNameAsync = promisify(tmp.tmpName);
|
||||
tmp.setGracefulCleanup();
|
||||
const { downloadOSImage } = await import('../../utils/cloud');
|
||||
const { getApplication } = await import('../../utils/sdk');
|
||||
const { downloadOSImage } = await import('../../utils/cloud.js');
|
||||
const { getApplication } = await import('../../utils/sdk.js');
|
||||
|
||||
const logger = await Command.getLogger();
|
||||
const balena = getBalenaSdk();
|
||||
@ -132,8 +132,8 @@ export default class DeviceInitCmd extends Command {
|
||||
$select: 'slug',
|
||||
},
|
||||
},
|
||||
})
|
||||
: await (await import('../../utils/patterns')).selectApplication();
|
||||
})
|
||||
: await (await import('../../utils/patterns.js')).selectApplication();
|
||||
|
||||
// Register new device
|
||||
const deviceUuid = balena.models.device.generateUniqueKey();
|
@ -16,9 +16,9 @@
|
||||
*/
|
||||
|
||||
import { Flags, Args } from '@oclif/core';
|
||||
import Command from '../../command';
|
||||
import * as cf from '../../utils/common-flags';
|
||||
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
|
||||
import Command from '../../command.js';
|
||||
import * as cf from '../../utils/common-flags.js';
|
||||
import { getBalenaSdk, stripIndent } from '../../utils/lazy.js';
|
||||
|
||||
export default class DeviceLocalModeCmd extends Command {
|
||||
public static description = stripIndent`
|
@ -22,11 +22,11 @@ import type {
|
||||
PineOptions,
|
||||
PineTypedResult,
|
||||
} from 'balena-sdk';
|
||||
import Command from '../../command';
|
||||
import * as cf from '../../utils/common-flags';
|
||||
import { ExpectedError } from '../../errors';
|
||||
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
|
||||
import { applicationIdInfo } from '../../utils/messages';
|
||||
import Command from '../../command.js';
|
||||
import * as cf from '../../utils/common-flags.js';
|
||||
import { ExpectedError } from '../../errors.js';
|
||||
import { getBalenaSdk, stripIndent } from '../../utils/lazy.js';
|
||||
import { applicationIdInfo } from '../../utils/messages.js';
|
||||
|
||||
export default class DeviceMoveCmd extends Command {
|
||||
public static description = stripIndent`
|
||||
@ -101,7 +101,7 @@ export default class DeviceMoveCmd extends Command {
|
||||
const devices = await this.getDevices(balena, deviceUuids);
|
||||
|
||||
// Disambiguate application
|
||||
const { getApplication } = await import('../../utils/sdk');
|
||||
const { getApplication } = await import('../../utils/sdk.js');
|
||||
|
||||
// Get destination application
|
||||
const application = options.fleet
|
||||
@ -151,7 +151,7 @@ export default class DeviceMoveCmd extends Command {
|
||||
})
|
||||
.map((deviceType) => deviceType.id);
|
||||
|
||||
const patterns = await import('../../utils/patterns');
|
||||
const patterns = await import('../../utils/patterns.js');
|
||||
try {
|
||||
const application = await patterns.selectApplication(
|
||||
{
|
@ -16,11 +16,11 @@
|
||||
*/
|
||||
|
||||
import { Flags, Args } from '@oclif/core';
|
||||
import Command from '../../command';
|
||||
import * as cf from '../../utils/common-flags';
|
||||
import { getBalenaSdk, stripIndent, getCliForm } from '../../utils/lazy';
|
||||
import Command from '../../command.js';
|
||||
import * as cf from '../../utils/common-flags.js';
|
||||
import { getBalenaSdk, stripIndent, getCliForm } from '../../utils/lazy.js';
|
||||
import type { Device } from 'balena-sdk';
|
||||
import { ExpectedError } from '../../errors';
|
||||
import { ExpectedError } from '../../errors.js';
|
||||
|
||||
export default class DeviceOsUpdateCmd extends Command {
|
||||
public static description = stripIndent`
|
||||
@ -122,7 +122,9 @@ export default class DeviceOsUpdateCmd extends Command {
|
||||
// Get target OS version
|
||||
let targetOsVersion = options.version;
|
||||
if (targetOsVersion != null) {
|
||||
const { normalizeOsVersion } = await import('../../utils/normalization');
|
||||
const { normalizeOsVersion } = await import(
|
||||
'../../utils/normalization.js'
|
||||
);
|
||||
targetOsVersion = normalizeOsVersion(targetOsVersion);
|
||||
if (!hupVersionInfo.versions.includes(targetOsVersion)) {
|
||||
throw new ExpectedError(
|
||||
@ -143,7 +145,7 @@ export default class DeviceOsUpdateCmd extends Command {
|
||||
});
|
||||
}
|
||||
|
||||
const patterns = await import('../../utils/patterns');
|
||||
const patterns = await import('../../utils/patterns.js');
|
||||
// Confirm and start update
|
||||
await patterns.confirm(
|
||||
options.yes || false,
|
@ -16,10 +16,10 @@
|
||||
*/
|
||||
|
||||
import { Args } from '@oclif/core';
|
||||
import Command from '../../command';
|
||||
import * as cf from '../../utils/common-flags';
|
||||
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
|
||||
import { getExpandedProp } from '../../utils/pine';
|
||||
import Command from '../../command.js';
|
||||
import * as cf from '../../utils/common-flags.js';
|
||||
import { getBalenaSdk, stripIndent } from '../../utils/lazy.js';
|
||||
import { getExpandedProp } from '../../utils/pine.js';
|
||||
|
||||
export default class DevicePinCmd extends Command {
|
||||
public static description = stripIndent`
|
@ -16,10 +16,10 @@
|
||||
*/
|
||||
|
||||
import { Flags, Args } from '@oclif/core';
|
||||
import Command from '../../command';
|
||||
import { ExpectedError } from '../../errors';
|
||||
import * as cf from '../../utils/common-flags';
|
||||
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
|
||||
import Command from '../../command.js';
|
||||
import { ExpectedError } from '../../errors.js';
|
||||
import * as cf from '../../utils/common-flags.js';
|
||||
import { getBalenaSdk, stripIndent } from '../../utils/lazy.js';
|
||||
|
||||
export default class DevicePublicUrlCmd extends Command {
|
||||
public static description = stripIndent`
|
@ -16,9 +16,9 @@
|
||||
*/
|
||||
|
||||
import { Args } from '@oclif/core';
|
||||
import Command from '../../command';
|
||||
import * as cf from '../../utils/common-flags';
|
||||
import { getBalenaSdk, getCliUx, stripIndent } from '../../utils/lazy';
|
||||
import Command from '../../command.js';
|
||||
import * as cf from '../../utils/common-flags.js';
|
||||
import { getBalenaSdk, getCliUx, stripIndent } from '../../utils/lazy.js';
|
||||
|
||||
export default class DevicePurgeCmd extends Command {
|
||||
public static description = stripIndent`
|
@ -16,9 +16,9 @@
|
||||
*/
|
||||
|
||||
import { Args } from '@oclif/core';
|
||||
import Command from '../../command';
|
||||
import * as cf from '../../utils/common-flags';
|
||||
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
|
||||
import Command from '../../command.js';
|
||||
import * as cf from '../../utils/common-flags.js';
|
||||
import { getBalenaSdk, stripIndent } from '../../utils/lazy.js';
|
||||
|
||||
export default class DeviceRebootCmd extends Command {
|
||||
public static description = stripIndent`
|
@ -16,11 +16,11 @@
|
||||
*/
|
||||
|
||||
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 { applicationIdInfo } from '../../utils/messages';
|
||||
import Command from '../../command.js';
|
||||
import * as cf from '../../utils/common-flags.js';
|
||||
import * as ca from '../../utils/common-args.js';
|
||||
import { getBalenaSdk, stripIndent } from '../../utils/lazy.js';
|
||||
import { applicationIdInfo } from '../../utils/messages.js';
|
||||
|
||||
export default class DeviceRegisterCmd extends Command {
|
||||
public static description = stripIndent`
|
||||
@ -64,7 +64,7 @@ export default class DeviceRegisterCmd extends Command {
|
||||
const { args: params, flags: options } =
|
||||
await this.parse(DeviceRegisterCmd);
|
||||
|
||||
const { getApplication } = await import('../../utils/sdk');
|
||||
const { getApplication } = await import('../../utils/sdk.js');
|
||||
|
||||
const balena = getBalenaSdk();
|
||||
|
@ -16,9 +16,9 @@
|
||||
*/
|
||||
|
||||
import { Args } from '@oclif/core';
|
||||
import Command from '../../command';
|
||||
import * as cf from '../../utils/common-flags';
|
||||
import { getBalenaSdk, stripIndent, getCliForm } from '../../utils/lazy';
|
||||
import Command from '../../command.js';
|
||||
import * as cf from '../../utils/common-flags.js';
|
||||
import { getBalenaSdk, stripIndent, getCliForm } from '../../utils/lazy.js';
|
||||
|
||||
export default class DeviceRenameCmd extends Command {
|
||||
public static description = stripIndent`
|
@ -16,9 +16,9 @@
|
||||
*/
|
||||
|
||||
import { Flags, Args } from '@oclif/core';
|
||||
import Command from '../../command';
|
||||
import * as cf from '../../utils/common-flags';
|
||||
import { getBalenaSdk, getCliUx, stripIndent } from '../../utils/lazy';
|
||||
import Command from '../../command.js';
|
||||
import * as cf from '../../utils/common-flags.js';
|
||||
import { getBalenaSdk, getCliUx, stripIndent } from '../../utils/lazy.js';
|
||||
import type {
|
||||
BalenaSDK,
|
||||
DeviceWithServiceDetails,
|
||||
@ -94,8 +94,8 @@ export default class DeviceRestartCmd extends Command {
|
||||
deviceUuid: string,
|
||||
serviceNames: string[],
|
||||
) {
|
||||
const { ExpectedError, instanceOf } = await import('../../errors');
|
||||
const { getExpandedProp } = await import('../../utils/pine');
|
||||
const { ExpectedError, instanceOf } = await import('../../errors.js');
|
||||
const { getExpandedProp } = await import('../../utils/pine.js');
|
||||
|
||||
// Get device
|
||||
let device: DeviceWithServiceDetails<CurrentServiceWithCommit>;
|
||||
@ -161,7 +161,7 @@ export default class DeviceRestartCmd extends Command {
|
||||
// Note: device.restartApplication throws `BalenaDeviceNotFound: Device not found` if device not online.
|
||||
// Need to use device.get first to distinguish between non-existant and offline devices.
|
||||
// Remove this workaround when SDK issue resolved: https://github.com/balena-io/balena-sdk/issues/649
|
||||
const { instanceOf, ExpectedError } = await import('../../errors');
|
||||
const { instanceOf, ExpectedError } = await import('../../errors.js');
|
||||
try {
|
||||
const device = await balena.models.device.get(deviceUuid);
|
||||
if (!device.is_online) {
|
@ -16,9 +16,9 @@
|
||||
*/
|
||||
|
||||
import { Args } from '@oclif/core';
|
||||
import Command from '../../command';
|
||||
import * as cf from '../../utils/common-flags';
|
||||
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
|
||||
import Command from '../../command.js';
|
||||
import * as cf from '../../utils/common-flags.js';
|
||||
import { getBalenaSdk, stripIndent } from '../../utils/lazy.js';
|
||||
|
||||
export default class DeviceRmCmd extends Command {
|
||||
public static description = stripIndent`
|
||||
@ -56,7 +56,7 @@ export default class DeviceRmCmd extends Command {
|
||||
const { args: params, flags: options } = await this.parse(DeviceRmCmd);
|
||||
|
||||
const balena = getBalenaSdk();
|
||||
const patterns = await import('../../utils/patterns');
|
||||
const patterns = await import('../../utils/patterns.js');
|
||||
|
||||
// Confirm
|
||||
const uuids = params.uuid.split(',');
|
@ -16,10 +16,10 @@
|
||||
*/
|
||||
|
||||
import { Args } from '@oclif/core';
|
||||
import Command from '../../command';
|
||||
import * as cf from '../../utils/common-flags';
|
||||
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
|
||||
import { ExpectedError } from '../../errors';
|
||||
import Command from '../../command.js';
|
||||
import * as cf from '../../utils/common-flags.js';
|
||||
import { getBalenaSdk, stripIndent } from '../../utils/lazy.js';
|
||||
import { ExpectedError } from '../../errors.js';
|
||||
|
||||
export default class DeviceShutdownCmd extends Command {
|
||||
public static description = stripIndent`
|
@ -16,9 +16,9 @@
|
||||
*/
|
||||
|
||||
import { Args } from '@oclif/core';
|
||||
import Command from '../../command';
|
||||
import * as cf from '../../utils/common-flags';
|
||||
import { getBalenaSdk, getCliUx, stripIndent } from '../../utils/lazy';
|
||||
import Command from '../../command.js';
|
||||
import * as cf from '../../utils/common-flags.js';
|
||||
import { getBalenaSdk, getCliUx, stripIndent } from '../../utils/lazy.js';
|
||||
import type { BalenaSDK } from 'balena-sdk';
|
||||
|
||||
export default class DeviceStartServiceCmd extends Command {
|
||||
@ -78,8 +78,8 @@ export default class DeviceStartServiceCmd extends Command {
|
||||
deviceUuid: string,
|
||||
serviceNames: string[],
|
||||
) {
|
||||
const { ExpectedError } = await import('../../errors');
|
||||
const { getExpandedProp } = await import('../../utils/pine');
|
||||
const { ExpectedError } = await import('../../errors.js');
|
||||
const { getExpandedProp } = await import('../../utils/pine.js');
|
||||
|
||||
// Get device
|
||||
const device = await balena.models.device.getWithServiceDetails(
|
@ -16,9 +16,9 @@
|
||||
*/
|
||||
|
||||
import { Args } from '@oclif/core';
|
||||
import Command from '../../command';
|
||||
import * as cf from '../../utils/common-flags';
|
||||
import { getBalenaSdk, getCliUx, stripIndent } from '../../utils/lazy';
|
||||
import Command from '../../command.js';
|
||||
import * as cf from '../../utils/common-flags.js';
|
||||
import { getBalenaSdk, getCliUx, stripIndent } from '../../utils/lazy.js';
|
||||
import type { BalenaSDK } from 'balena-sdk';
|
||||
|
||||
export default class DeviceStopServiceCmd extends Command {
|
||||
@ -78,8 +78,8 @@ export default class DeviceStopServiceCmd extends Command {
|
||||
deviceUuid: string,
|
||||
serviceNames: string[],
|
||||
) {
|
||||
const { ExpectedError } = await import('../../errors');
|
||||
const { getExpandedProp } = await import('../../utils/pine');
|
||||
const { ExpectedError } = await import('../../errors.js');
|
||||
const { getExpandedProp } = await import('../../utils/pine.js');
|
||||
|
||||
// Get device
|
||||
const device = await balena.models.device.getWithServiceDetails(
|
@ -16,9 +16,9 @@
|
||||
*/
|
||||
|
||||
import { Args } from '@oclif/core';
|
||||
import Command from '../../command';
|
||||
import * as cf from '../../utils/common-flags';
|
||||
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
|
||||
import Command from '../../command.js';
|
||||
import * as cf from '../../utils/common-flags.js';
|
||||
import { getBalenaSdk, stripIndent } from '../../utils/lazy.js';
|
||||
|
||||
export default class DeviceTrackFleetCmd extends Command {
|
||||
public static description = stripIndent`
|
@ -15,11 +15,11 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import Command from '../../command';
|
||||
import * as cf from '../../utils/common-flags';
|
||||
import { expandForAppName } from '../../utils/helpers';
|
||||
import { getBalenaSdk, getVisuals, stripIndent } from '../../utils/lazy';
|
||||
import { applicationIdInfo, jsonInfo } from '../../utils/messages';
|
||||
import Command from '../../command.js';
|
||||
import * as cf from '../../utils/common-flags.js';
|
||||
import { expandForAppName } from '../../utils/helpers.js';
|
||||
import { getBalenaSdk, getVisuals, stripIndent } from '../../utils/lazy.js';
|
||||
import { applicationIdInfo, jsonInfo } from '../../utils/messages.js';
|
||||
|
||||
import type { Device, PineOptions } from 'balena-sdk';
|
||||
|
||||
@ -78,7 +78,7 @@ export default class DevicesCmd extends Command {
|
||||
const devices = (
|
||||
await (async () => {
|
||||
if (options.fleet != null) {
|
||||
const { getApplication } = await import('../../utils/sdk');
|
||||
const { getApplication } = await import('../../utils/sdk.js');
|
||||
const application = await getApplication(balena, options.fleet, {
|
||||
$select: 'slug',
|
||||
$expand: {
|
||||
@ -115,7 +115,7 @@ export default class DevicesCmd extends Command {
|
||||
];
|
||||
|
||||
if (options.json) {
|
||||
const { pickAndRename } = await import('../../utils/helpers');
|
||||
const { pickAndRename } = await import('../../utils/helpers.js');
|
||||
const mapped = devices.map((device) => pickAndRename(device, fields));
|
||||
console.log(JSON.stringify(mapped, null, 4));
|
||||
} else {
|
@ -16,12 +16,12 @@
|
||||
*/
|
||||
import { Flags } from '@oclif/core';
|
||||
import type * as BalenaSdk from 'balena-sdk';
|
||||
import * as _ from 'lodash';
|
||||
import Command from '../../command';
|
||||
import _ from 'lodash';
|
||||
import Command from '../../command.js';
|
||||
|
||||
import * as cf from '../../utils/common-flags';
|
||||
import { getBalenaSdk, getVisuals, stripIndent } from '../../utils/lazy';
|
||||
import { CommandHelp } from '../../utils/oclif-utils';
|
||||
import * as cf from '../../utils/common-flags.js';
|
||||
import { getBalenaSdk, getVisuals, stripIndent } from '../../utils/lazy.js';
|
||||
import { CommandHelp } from '../../utils/oclif-utils.js';
|
||||
|
||||
export default class DevicesSupportedCmd extends Command {
|
||||
public static description = stripIndent`
|
@ -17,11 +17,11 @@
|
||||
|
||||
import { Args } from '@oclif/core';
|
||||
import type * as BalenaSdk from 'balena-sdk';
|
||||
import Command from '../../command';
|
||||
import { ExpectedError } from '../../errors';
|
||||
import * as cf from '../../utils/common-flags';
|
||||
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
|
||||
import { applicationIdInfo } from '../../utils/messages';
|
||||
import Command from '../../command.js';
|
||||
import { ExpectedError } from '../../errors.js';
|
||||
import * as cf from '../../utils/common-flags.js';
|
||||
import { getBalenaSdk, stripIndent } from '../../utils/lazy.js';
|
||||
import { applicationIdInfo } from '../../utils/messages.js';
|
||||
|
||||
interface FlagsDef {
|
||||
fleet?: string;
|
||||
@ -95,8 +95,8 @@ export default class EnvAddCmd extends Command {
|
||||
public static usage = 'env add <name> [value]';
|
||||
|
||||
public static flags = {
|
||||
fleet: { ...cf.fleet, exclusive: ['device'] },
|
||||
device: { ...cf.device, exclusive: ['fleet'] },
|
||||
fleet: cf.fleetExclusive(['device']),
|
||||
device: cf.deviceExclusive(['fleet']),
|
||||
help: cf.help,
|
||||
quiet: cf.quiet,
|
||||
service: cf.service,
|
||||
@ -185,7 +185,7 @@ async function resolveFleetSlugs(
|
||||
fleetOption: string,
|
||||
) {
|
||||
const fleetSlugs: string[] = [];
|
||||
const { getFleetSlug } = await import('../../utils/sdk');
|
||||
const { getFleetSlug } = await import('../../utils/sdk.js');
|
||||
for (const appNameOrSlug of fleetOption.split(',')) {
|
||||
try {
|
||||
fleetSlugs.push(await getFleetSlug(balena, appNameOrSlug));
|
||||
@ -222,7 +222,7 @@ async function setServiceVars(
|
||||
}
|
||||
}
|
||||
} else if (options.device) {
|
||||
const { getDeviceAndAppFromUUID } = await import('../../utils/cloud');
|
||||
const { getDeviceAndAppFromUUID } = await import('../../utils/cloud.js');
|
||||
for (const uuid of options.device.split(',')) {
|
||||
let device;
|
||||
let app;
|
@ -15,12 +15,12 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { Args } from '@oclif/core';
|
||||
import Command from '../../command';
|
||||
import Command from '../../command.js';
|
||||
|
||||
import * as cf from '../../utils/common-flags';
|
||||
import * as ec from '../../utils/env-common';
|
||||
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
|
||||
import { parseAsInteger } from '../../utils/validation';
|
||||
import * as cf from '../../utils/common-flags.js';
|
||||
import * as ec from '../../utils/env-common.js';
|
||||
import { getBalenaSdk, stripIndent } from '../../utils/lazy.js';
|
||||
import { parseAsInteger } from '../../utils/validation.js';
|
||||
|
||||
export default class EnvRenameCmd extends Command {
|
||||
public static description = stripIndent`
|
10
lib/commands/env/rm.ts → src/commands/env/rm.ts
vendored
10
lib/commands/env/rm.ts → src/commands/env/rm.ts
vendored
@ -16,11 +16,11 @@
|
||||
*/
|
||||
|
||||
import { Flags, Args } from '@oclif/core';
|
||||
import Command from '../../command';
|
||||
import Command from '../../command.js';
|
||||
|
||||
import * as ec from '../../utils/env-common';
|
||||
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
|
||||
import { parseAsInteger } from '../../utils/validation';
|
||||
import * as ec from '../../utils/env-common.js';
|
||||
import { getBalenaSdk, stripIndent } from '../../utils/lazy.js';
|
||||
import { parseAsInteger } from '../../utils/validation.js';
|
||||
|
||||
export default class EnvRmCmd extends Command {
|
||||
public static description = stripIndent`
|
||||
@ -71,7 +71,7 @@ export default class EnvRmCmd extends Command {
|
||||
|
||||
await Command.checkLoggedIn();
|
||||
|
||||
const { confirm } = await import('../../utils/patterns');
|
||||
const { confirm } = await import('../../utils/patterns.js');
|
||||
await confirm(
|
||||
opt.yes || false,
|
||||
'Are you sure you want to delete the environment variable?',
|
@ -17,12 +17,12 @@
|
||||
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 _ from 'lodash';
|
||||
import Command from '../../command.js';
|
||||
import { ExpectedError } from '../../errors.js';
|
||||
import * as cf from '../../utils/common-flags.js';
|
||||
import { getBalenaSdk, getVisuals, stripIndent } from '../../utils/lazy.js';
|
||||
import { applicationIdInfo } from '../../utils/messages.js';
|
||||
|
||||
type FlagsDef = Interfaces.InferredFlags<typeof EnvsCmd.flags>;
|
||||
|
||||
@ -97,17 +97,17 @@ export default class EnvsCmd extends Command {
|
||||
public static usage = 'envs';
|
||||
|
||||
public static flags = {
|
||||
fleet: { ...cf.fleet, exclusive: ['device'] },
|
||||
fleet: cf.fleetExclusive(['device']),
|
||||
config: Flags.boolean({
|
||||
default: false,
|
||||
char: 'c',
|
||||
description: 'show configuration variables only',
|
||||
exclusive: ['service'],
|
||||
}),
|
||||
device: { ...cf.device, exclusive: ['fleet'] },
|
||||
device: cf.deviceExclusive(['fleet']),
|
||||
help: cf.help,
|
||||
json: cf.json,
|
||||
service: { ...cf.service, exclusive: ['config'] },
|
||||
service: cf.serviceExclusive(['config']),
|
||||
};
|
||||
|
||||
public async run() {
|
||||
@ -125,14 +125,14 @@ export default class EnvsCmd extends Command {
|
||||
|
||||
let fleetSlug: string | undefined = options.fleet
|
||||
? await (
|
||||
await import('../../utils/sdk')
|
||||
).getFleetSlug(balena, options.fleet)
|
||||
await import('../../utils/sdk.js')
|
||||
).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'
|
||||
'../../utils/cloud.js'
|
||||
);
|
||||
const [device, app] = await getDeviceAndMaybeAppFromUUID(
|
||||
balena,
|
||||
@ -186,7 +186,7 @@ export default class EnvsCmd extends Command {
|
||||
}
|
||||
|
||||
if (options.json) {
|
||||
const { pickAndRename } = await import('../../utils/helpers');
|
||||
const { pickAndRename } = await import('../../utils/helpers.js');
|
||||
const mapped = varArray.map((o) => pickAndRename(o, fields));
|
||||
this.log(JSON.stringify(mapped, null, 4));
|
||||
} else {
|
@ -17,9 +17,9 @@
|
||||
|
||||
import { Flags, Args } from '@oclif/core';
|
||||
|
||||
import Command from '../../command';
|
||||
import * as cf from '../../utils/common-flags';
|
||||
import { stripIndent } from '../../utils/lazy';
|
||||
import Command from '../../command.js';
|
||||
import * as cf from '../../utils/common-flags.js';
|
||||
import { stripIndent } from '../../utils/lazy.js';
|
||||
|
||||
export default class FleetCreateCmd extends Command {
|
||||
public static description = stripIndent`
|
||||
@ -77,7 +77,7 @@ export default class FleetCreateCmd extends Command {
|
||||
const { args: params, flags: options } = await this.parse(FleetCreateCmd);
|
||||
|
||||
await (
|
||||
await import('../../utils/application-create')
|
||||
await import('../../utils/application-create.js')
|
||||
).applicationCreateBase('fleet', options, params);
|
||||
}
|
||||
}
|
@ -17,11 +17,11 @@
|
||||
|
||||
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 { applicationIdInfo } from '../../utils/messages';
|
||||
import Command from '../../command.js';
|
||||
import * as cf from '../../utils/common-flags.js';
|
||||
import * as ca from '../../utils/common-args.js';
|
||||
import { getBalenaSdk, getVisuals, stripIndent } from '../../utils/lazy.js';
|
||||
import { applicationIdInfo } from '../../utils/messages.js';
|
||||
|
||||
export default class FleetCmd extends Command {
|
||||
public static description = stripIndent`
|
||||
@ -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;
|
||||
@ -58,7 +58,7 @@ export default class FleetCmd extends Command {
|
||||
public async run() {
|
||||
const { args: params, flags: options } = await this.parse(FleetCmd);
|
||||
|
||||
const { getApplication } = await import('../../utils/sdk');
|
||||
const { getApplication } = await import('../../utils/sdk.js');
|
||||
|
||||
const balena = getBalenaSdk();
|
||||
|
||||
@ -70,7 +70,7 @@ export default class FleetCmd extends Command {
|
||||
});
|
||||
|
||||
if (options.view) {
|
||||
const open = await import('open');
|
||||
const { default: open } = await import('open');
|
||||
const dashboardUrl = balena.models.application.getDashboardUrl(
|
||||
application.id,
|
||||
);
|
||||
@ -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',
|
||||
]),
|
||||
);
|
||||
}
|
||||
}
|
@ -16,10 +16,10 @@
|
||||
*/
|
||||
|
||||
import { Args } from '@oclif/core';
|
||||
import Command from '../../command';
|
||||
import * as cf from '../../utils/common-flags';
|
||||
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
|
||||
import { getExpandedProp } from '../../utils/pine';
|
||||
import Command from '../../command.js';
|
||||
import * as cf from '../../utils/common-flags.js';
|
||||
import { getBalenaSdk, stripIndent } from '../../utils/lazy.js';
|
||||
import { getExpandedProp } from '../../utils/pine.js';
|
||||
|
||||
export default class FleetPinCmd extends Command {
|
||||
public static description = stripIndent`
|
@ -15,11 +15,11 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
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 { applicationIdInfo } from '../../utils/messages';
|
||||
import Command from '../../command.js';
|
||||
import * as cf from '../../utils/common-flags.js';
|
||||
import * as ca from '../../utils/common-args.js';
|
||||
import { getBalenaSdk, stripIndent } from '../../utils/lazy.js';
|
||||
import { applicationIdInfo } from '../../utils/messages.js';
|
||||
|
||||
export default class FleetPurgeCmd extends Command {
|
||||
public static description = stripIndent`
|
||||
@ -51,7 +51,7 @@ export default class FleetPurgeCmd extends Command {
|
||||
public async run() {
|
||||
const { args: params } = await this.parse(FleetPurgeCmd);
|
||||
|
||||
const { getApplication } = await import('../../utils/sdk');
|
||||
const { getApplication } = await import('../../utils/sdk.js');
|
||||
|
||||
const balena = getBalenaSdk();
|
||||
|
@ -17,11 +17,11 @@
|
||||
|
||||
import { Args } from '@oclif/core';
|
||||
|
||||
import Command from '../../command';
|
||||
import * as cf from '../../utils/common-flags';
|
||||
import * as ca from '../../utils/common-args';
|
||||
import { getBalenaSdk, stripIndent, getCliForm } from '../../utils/lazy';
|
||||
import { applicationIdInfo } from '../../utils/messages';
|
||||
import Command from '../../command.js';
|
||||
import * as cf from '../../utils/common-flags.js';
|
||||
import * as ca from '../../utils/common-args.js';
|
||||
import { getBalenaSdk, stripIndent, getCliForm } from '../../utils/lazy.js';
|
||||
import { applicationIdInfo } from '../../utils/messages.js';
|
||||
|
||||
export default class FleetRenameCmd extends Command {
|
||||
public static description = stripIndent`
|
||||
@ -59,13 +59,15 @@ export default class FleetRenameCmd extends Command {
|
||||
public async run() {
|
||||
const { args: params } = await this.parse(FleetRenameCmd);
|
||||
|
||||
const { validateApplicationName } = await import('../../utils/validation');
|
||||
const { ExpectedError } = await import('../../errors');
|
||||
const { validateApplicationName } = await import(
|
||||
'../../utils/validation.js'
|
||||
);
|
||||
const { ExpectedError } = await import('../../errors.js');
|
||||
|
||||
const balena = getBalenaSdk();
|
||||
|
||||
// Disambiguate target application (if params.params is a number, it could either be an ID or a numerical name)
|
||||
const { getApplication } = await import('../../utils/sdk');
|
||||
const { getApplication } = await import('../../utils/sdk.js');
|
||||
const application = await getApplication(balena, params.fleet, {
|
||||
$select: ['id', 'app_name', 'slug'],
|
||||
$expand: {
|
@ -15,11 +15,11 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
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 { applicationIdInfo } from '../../utils/messages';
|
||||
import Command from '../../command.js';
|
||||
import * as cf from '../../utils/common-flags.js';
|
||||
import * as ca from '../../utils/common-args.js';
|
||||
import { getBalenaSdk, stripIndent } from '../../utils/lazy.js';
|
||||
import { applicationIdInfo } from '../../utils/messages.js';
|
||||
|
||||
export default class FleetRestartCmd extends Command {
|
||||
public static description = stripIndent`
|
||||
@ -50,7 +50,7 @@ export default class FleetRestartCmd extends Command {
|
||||
public async run() {
|
||||
const { args: params } = await this.parse(FleetRestartCmd);
|
||||
|
||||
const { getApplication } = await import('../../utils/sdk');
|
||||
const { getApplication } = await import('../../utils/sdk.js');
|
||||
|
||||
const balena = getBalenaSdk();
|
||||
|
@ -15,11 +15,11 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
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 { applicationIdInfo } from '../../utils/messages';
|
||||
import Command from '../../command.js';
|
||||
import * as cf from '../../utils/common-flags.js';
|
||||
import * as ca from '../../utils/common-args.js';
|
||||
import { getBalenaSdk, stripIndent } from '../../utils/lazy.js';
|
||||
import { applicationIdInfo } from '../../utils/messages.js';
|
||||
|
||||
export default class FleetRmCmd extends Command {
|
||||
public static description = stripIndent`
|
||||
@ -54,8 +54,8 @@ export default class FleetRmCmd extends Command {
|
||||
public async run() {
|
||||
const { args: params, flags: options } = await this.parse(FleetRmCmd);
|
||||
|
||||
const { confirm } = await import('../../utils/patterns');
|
||||
const { getApplication } = await import('../../utils/sdk');
|
||||
const { confirm } = await import('../../utils/patterns.js');
|
||||
const { getApplication } = await import('../../utils/sdk.js');
|
||||
const balena = getBalenaSdk();
|
||||
|
||||
// Confirm
|
@ -16,9 +16,9 @@
|
||||
*/
|
||||
|
||||
import { Args } from '@oclif/core';
|
||||
import Command from '../../command';
|
||||
import * as cf from '../../utils/common-flags';
|
||||
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
|
||||
import Command from '../../command.js';
|
||||
import * as cf from '../../utils/common-flags.js';
|
||||
import { getBalenaSdk, stripIndent } from '../../utils/lazy.js';
|
||||
|
||||
export default class FleetTrackLatestCmd extends Command {
|
||||
public static description = stripIndent`
|
@ -17,9 +17,9 @@
|
||||
|
||||
import type * as BalenaSdk from 'balena-sdk';
|
||||
|
||||
import Command from '../../command';
|
||||
import * as cf from '../../utils/common-flags';
|
||||
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
|
||||
import Command from '../../command.js';
|
||||
import * as cf from '../../utils/common-flags.js';
|
||||
import { getBalenaSdk, getVisuals, stripIndent } from '../../utils/lazy.js';
|
||||
|
||||
interface ExtendedApplication extends ApplicationWithDeviceTypeSlug {
|
||||
device_count: number;
|
||||
@ -42,8 +42,8 @@ export default class FleetsCmd extends Command {
|
||||
public static usage = 'fleets';
|
||||
|
||||
public static flags = {
|
||||
...cf.dataSetOutputFlags,
|
||||
help: cf.help,
|
||||
json: cf.json,
|
||||
};
|
||||
|
||||
public static authenticated = true;
|
||||
@ -77,17 +77,29 @@ export default class FleetsCmd extends Command {
|
||||
application.device_type = application.is_for__device_type[0].slug;
|
||||
});
|
||||
|
||||
await this.outputData(
|
||||
applications,
|
||||
[
|
||||
const applicationsToDisplay = applications.map((application) => ({
|
||||
id: application.id,
|
||||
app_name: application.app_name,
|
||||
slug: application.slug,
|
||||
device_type: application.device_type,
|
||||
online_devices: application.online_devices,
|
||||
device_count: application.device_count,
|
||||
}));
|
||||
|
||||
if (options.json) {
|
||||
console.log(JSON.stringify(applicationsToDisplay, null, 4));
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(
|
||||
getVisuals().table.horizontal(applicationsToDisplay, [
|
||||
'id',
|
||||
'app_name',
|
||||
'app_name => NAME',
|
||||
'slug',
|
||||
'device_type',
|
||||
'device_count',
|
||||
'online_devices',
|
||||
],
|
||||
options,
|
||||
]),
|
||||
);
|
||||
}
|
||||
}
|
@ -16,9 +16,9 @@
|
||||
*/
|
||||
|
||||
import { Args } from '@oclif/core';
|
||||
import Command from '../../command';
|
||||
import { stripIndent } from '../../utils/lazy';
|
||||
import { CommandHelp } from '../../utils/oclif-utils';
|
||||
import Command from '../../command.js';
|
||||
import { stripIndent } from '../../utils/lazy.js';
|
||||
import { CommandHelp } from '../../utils/oclif-utils.js';
|
||||
|
||||
// 'Internal' commands are called during the execution of other commands.
|
||||
// `osinit` is called during `os initialize`
|
||||
@ -63,7 +63,7 @@ export default class OsinitCmd extends Command {
|
||||
const config = JSON.parse(params.config);
|
||||
|
||||
const { getManifest, osProgressHandler } = await import(
|
||||
'../../utils/helpers'
|
||||
'../../utils/helpers.js'
|
||||
);
|
||||
const manifest = await getManifest(params.image, params.type);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user