@aptos-labs/aptos-cli 1.1.1 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +109 -0
- package/dist/aptos.js +7 -2
- package/dist/aptos.js.map +1 -1
- package/dist/examples/examples.test.js +69 -0
- package/dist/examples/examples.test.js.map +1 -0
- package/dist/tasks/install.js +82 -31
- package/dist/tasks/install.js.map +1 -1
- package/dist/tasks/install.test.js +227 -0
- package/dist/tasks/install.test.js.map +1 -0
- package/dist/tasks/run.js +13 -8
- package/dist/tasks/run.js.map +1 -1
- package/dist/tasks/run.test.js +92 -0
- package/dist/tasks/run.test.js.map +1 -0
- package/dist/tasks/update.js +55 -20
- package/dist/tasks/update.js.map +1 -1
- package/dist/utils/brewOperations.js +30 -4
- package/dist/utils/brewOperations.js.map +1 -1
- package/dist/utils/brewOperations.test.js +83 -0
- package/dist/utils/brewOperations.test.js.map +1 -0
- package/dist/utils/consts.js.map +1 -1
- package/dist/utils/execSyncShell.js +6 -2
- package/dist/utils/execSyncShell.js.map +1 -1
- package/dist/utils/executableIsAvailable.js +12 -0
- package/dist/utils/executableIsAvailable.js.map +1 -0
- package/dist/utils/getLocalBinPath.js +76 -20
- package/dist/utils/getLocalBinPath.js.map +1 -1
- package/dist/utils/getUserOs.js +92 -6
- package/dist/utils/getUserOs.js.map +1 -1
- package/dist/utils/getUserOs.test.js +143 -0
- package/dist/utils/getUserOs.test.js.map +1 -0
- package/dist/utils/ghOperations.js +81 -6
- package/dist/utils/ghOperations.js.map +1 -1
- package/dist/utils/ghOperations.test.js +217 -0
- package/dist/utils/ghOperations.test.js.map +1 -0
- package/dist/utils/parseCommandOptions.js +4 -4
- package/dist/utils/parseCommandOptions.js.map +1 -1
- package/dist/utils/windowsPackageManagers.js +100 -0
- package/dist/utils/windowsPackageManagers.js.map +1 -0
- package/dist/utils/windowsPackageManagers.test.js +169 -0
- package/dist/utils/windowsPackageManagers.test.js.map +1 -0
- package/package.json +22 -11
- package/bin/.gitkeep +0 -0
- package/bin/aptos.ts +0 -44
- package/bin/tasks/install.ts +0 -55
- package/bin/tasks/run.ts +0 -27
- package/bin/tasks/update.ts +0 -41
- package/bin/utils/aptosExecutableIsAvailable.ts +0 -14
- package/bin/utils/brewOperations.ts +0 -12
- package/bin/utils/consts.ts +0 -3
- package/bin/utils/execSyncShell.ts +0 -8
- package/bin/utils/getLocalBinPath.ts +0 -28
- package/bin/utils/getUserOs.ts +0 -18
- package/bin/utils/ghOperations.ts +0 -20
- package/bin/utils/handleHelpOptions.ts +0 -38
- package/bin/utils/parseCommandOptions.ts +0 -28
- package/bin/utils/versions.ts +0 -9
- package/dist/aptos.d.ts +0 -2
- package/dist/tasks/install.d.ts +0 -1
- package/dist/tasks/run.d.ts +0 -1
- package/dist/tasks/update.d.ts +0 -1
- package/dist/utils/aptosExecutableIsAvailable.d.ts +0 -1
- package/dist/utils/aptosExecutableIsAvailable.js +0 -11
- package/dist/utils/aptosExecutableIsAvailable.js.map +0 -1
- package/dist/utils/brewOperations.d.ts +0 -1
- package/dist/utils/consts.d.ts +0 -2
- package/dist/utils/execSyncShell.d.ts +0 -1
- package/dist/utils/getLocalBinPath.d.ts +0 -1
- package/dist/utils/getUserOs.d.ts +0 -1
- package/dist/utils/ghOperations.d.ts +0 -1
- package/dist/utils/handleHelpOptions.d.ts +0 -2
- package/dist/utils/handleHelpOptions.js +0 -16
- package/dist/utils/handleHelpOptions.js.map +0 -1
- package/dist/utils/parseCommandOptions.d.ts +0 -5
- package/dist/utils/versions.d.ts +0 -1
- package/dist/utils/versions.js +0 -6
- package/dist/utils/versions.js.map +0 -1
package/README.md
CHANGED
|
@@ -42,6 +42,28 @@ If you already have the Aptos CLI binary installed on your system, you can speci
|
|
|
42
42
|
npx aptos --binary-path /path/to/aptos <command>
|
|
43
43
|
```
|
|
44
44
|
|
|
45
|
+
### Installing a Specific Version
|
|
46
|
+
|
|
47
|
+
You can install a specific version of the Aptos CLI by setting the `APTOS_CLI_VERSION` environment variable:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
# Install version 4.5.0
|
|
51
|
+
APTOS_CLI_VERSION=4.5.0 npx aptos --install
|
|
52
|
+
|
|
53
|
+
# Or with the v prefix
|
|
54
|
+
APTOS_CLI_VERSION=v4.5.0 npx aptos --install
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
When `APTOS_CLI_VERSION` is set:
|
|
58
|
+
- The specified version is downloaded directly from GitHub releases (package managers are bypassed)
|
|
59
|
+
- The version is validated to ensure it exists before downloading
|
|
60
|
+
- This works for both `--install` and `--update` commands
|
|
61
|
+
|
|
62
|
+
This is useful for:
|
|
63
|
+
- Pinning to a known working version
|
|
64
|
+
- Testing against specific CLI versions
|
|
65
|
+
- Reproducible builds in CI/CD pipelines
|
|
66
|
+
|
|
45
67
|
## Updating the Aptos CLI
|
|
46
68
|
|
|
47
69
|
To update the Aptos CLI, you can run the following command within your project environment:
|
|
@@ -73,3 +95,90 @@ To build the project:
|
|
|
73
95
|
```bash
|
|
74
96
|
npm run build
|
|
75
97
|
```
|
|
98
|
+
|
|
99
|
+
## Building Move Artifacts in CI/CD
|
|
100
|
+
|
|
101
|
+
The Aptos CLI can be used in CI/CD pipelines to build Move packages and generate deployment payloads. This is useful for automated deployments and multi-step workflows.
|
|
102
|
+
|
|
103
|
+
### Example: Building Publish Payload
|
|
104
|
+
|
|
105
|
+
```yaml
|
|
106
|
+
# In your GitHub Actions workflow
|
|
107
|
+
|
|
108
|
+
# Prerequisites: Set up Node.js first
|
|
109
|
+
- name: Setup Node.js
|
|
110
|
+
uses: actions/setup-node@v4
|
|
111
|
+
with:
|
|
112
|
+
node-version: "20"
|
|
113
|
+
|
|
114
|
+
- name: Install Aptos CLI npm package
|
|
115
|
+
run: npm install @aptos-labs/aptos-cli
|
|
116
|
+
|
|
117
|
+
- name: Install Aptos CLI
|
|
118
|
+
run: npx aptos --install
|
|
119
|
+
|
|
120
|
+
- name: Build Move package
|
|
121
|
+
working-directory: your-move-project
|
|
122
|
+
run: |
|
|
123
|
+
~/.local/bin/aptos move compile \
|
|
124
|
+
--named-addresses your_module=0x1 \
|
|
125
|
+
--save-metadata
|
|
126
|
+
|
|
127
|
+
- name: Generate publish payload
|
|
128
|
+
working-directory: your-move-project
|
|
129
|
+
run: |
|
|
130
|
+
~/.local/bin/aptos move build-publish-payload \
|
|
131
|
+
--named-addresses your_module=0x1 \
|
|
132
|
+
--json-output-file publish-payload.json \
|
|
133
|
+
--assume-yes
|
|
134
|
+
|
|
135
|
+
- name: Upload artifact for later steps
|
|
136
|
+
uses: actions/upload-artifact@v4
|
|
137
|
+
with:
|
|
138
|
+
name: move-artifacts
|
|
139
|
+
path: your-move-project/publish-payload.json
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Example: Building Upgrade Payload (Object Code Deployment)
|
|
143
|
+
|
|
144
|
+
For upgrading existing object-deployed contracts:
|
|
145
|
+
|
|
146
|
+
```yaml
|
|
147
|
+
- name: Generate upgrade payload
|
|
148
|
+
working-directory: your-move-project
|
|
149
|
+
run: |
|
|
150
|
+
~/.local/bin/aptos move build-upgrade-payload \
|
|
151
|
+
--named-addresses your_module=0x1 \
|
|
152
|
+
--object-address 0xYOUR_OBJECT_ADDRESS \
|
|
153
|
+
--json-output-file upgrade-payload.json \
|
|
154
|
+
--assume-yes
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### Using Artifacts in Subsequent Jobs
|
|
158
|
+
|
|
159
|
+
```yaml
|
|
160
|
+
jobs:
|
|
161
|
+
build:
|
|
162
|
+
runs-on: ubuntu-latest
|
|
163
|
+
steps:
|
|
164
|
+
# ... build steps above ...
|
|
165
|
+
- uses: actions/upload-artifact@v4
|
|
166
|
+
with:
|
|
167
|
+
name: move-artifacts
|
|
168
|
+
path: your-move-project/publish-payload.json
|
|
169
|
+
|
|
170
|
+
deploy:
|
|
171
|
+
needs: build
|
|
172
|
+
runs-on: ubuntu-latest
|
|
173
|
+
steps:
|
|
174
|
+
- uses: actions/download-artifact@v4
|
|
175
|
+
with:
|
|
176
|
+
name: move-artifacts
|
|
177
|
+
|
|
178
|
+
- name: Use the payload
|
|
179
|
+
run: |
|
|
180
|
+
# The payload JSON can be used for deployment
|
|
181
|
+
cat publish-payload.json
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
See the [build-move-artifacts.yaml](.github/workflows/build-move-artifacts.yaml) workflow for a complete working example.
|
package/dist/aptos.js
CHANGED
|
@@ -1,20 +1,25 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { program } from "commander";
|
|
3
|
-
import { parseCommandOptions } from "./utils/parseCommandOptions.js";
|
|
4
3
|
import { runCLI } from "./tasks/run.js";
|
|
4
|
+
import { parseCommandOptions } from "./utils/parseCommandOptions.js";
|
|
5
5
|
program
|
|
6
6
|
.name("aptos")
|
|
7
7
|
.helpOption(false)
|
|
8
8
|
.option("-i, --install", "install the latest version of the CLI")
|
|
9
9
|
.option("-u, --update", "update the CLI to the latest version")
|
|
10
10
|
.option("-b, --binary-path <path>", "path to an existing Aptos CLI binary")
|
|
11
|
-
.
|
|
11
|
+
.option("-d, --direct-download", "skip package managers and download directly from GitHub")
|
|
12
|
+
.allowUnknownOption()
|
|
13
|
+
.allowExcessArguments(true);
|
|
12
14
|
program.parse(process.argv);
|
|
13
15
|
const main = async () => {
|
|
14
16
|
const options = {
|
|
15
17
|
install: program.opts().install,
|
|
16
18
|
update: program.opts().update,
|
|
17
19
|
binaryPath: program.opts().binaryPath,
|
|
20
|
+
directDownload: program.opts().directDownload ||
|
|
21
|
+
process.env.APTOS_DIRECT_DOWNLOAD === "1" ||
|
|
22
|
+
process.env.APTOS_DIRECT_DOWNLOAD === "true",
|
|
18
23
|
};
|
|
19
24
|
const unknownOptions = program.args;
|
|
20
25
|
if (process.argv.includes("--help")) {
|
package/dist/aptos.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"aptos.js","sourceRoot":"","sources":["../bin/aptos.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"aptos.js","sourceRoot":"","sources":["../bin/aptos.ts"],"names":[],"mappings":";AAkBA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AACxC,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AAErE,OAAO;KACJ,IAAI,CAAC,OAAO,CAAC;KACb,UAAU,CAAC,KAAK,CAAC;KACjB,MAAM,CAAC,eAAe,EAAE,uCAAuC,CAAC;KAChE,MAAM,CAAC,cAAc,EAAE,sCAAsC,CAAC;KAC9D,MAAM,CAAC,0BAA0B,EAAE,sCAAsC,CAAC;KAC1E,MAAM,CACL,uBAAuB,EACvB,yDAAyD,CAC1D;KACA,kBAAkB,EAAE;KACpB,oBAAoB,CAAC,IAAI,CAAC,CAAC;AAE9B,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;AAE5B,MAAM,IAAI,GAAG,KAAK,IAAI,EAAE;IACtB,MAAM,OAAO,GAAG;QACd,OAAO,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,OAAO;QAC/B,MAAM,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,MAAM;QAC7B,UAAU,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,UAAU;QACrC,cAAc,EACZ,OAAO,CAAC,IAAI,EAAE,CAAC,cAAc;YAC7B,OAAO,CAAC,GAAG,CAAC,qBAAqB,KAAK,GAAG;YACzC,OAAO,CAAC,GAAG,CAAC,qBAAqB,KAAK,MAAM;KAC/C,CAAC;IACF,MAAM,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAGpC,IAAI,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QAEpC,OAAO,MAAM,CAAC,cAAc,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;IACpD,CAAC;IAED,MAAM,mBAAmB,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;AACrD,CAAC,CAAC;AAEF,IAAI,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC","sourcesContent":["#!/usr/bin/env node\n\n// Installation priorities by platform:\n//\n// macOS:\n// 1. Homebrew (if available) - builds for native CPU architecture\n// 2. Direct download from GitHub releases\n//\n// Windows:\n// 1. winget (if available)\n// 2. Chocolatey (if available)\n// 3. Direct download from GitHub releases\n//\n// Linux:\n// - Direct download from GitHub releases (with Ubuntu version detection)\n//\n// Use --direct-download or set APTOS_DIRECT_DOWNLOAD=1 to skip package managers.\n\nimport { program } from \"commander\";\nimport { runCLI } from \"./tasks/run.js\";\nimport { parseCommandOptions } from \"./utils/parseCommandOptions.js\";\n\nprogram\n .name(\"aptos\")\n .helpOption(false)\n .option(\"-i, --install\", \"install the latest version of the CLI\")\n .option(\"-u, --update\", \"update the CLI to the latest version\")\n .option(\"-b, --binary-path <path>\", \"path to an existing Aptos CLI binary\")\n .option(\n \"-d, --direct-download\",\n \"skip package managers and download directly from GitHub\",\n )\n .allowUnknownOption()\n .allowExcessArguments(true);\n\nprogram.parse(process.argv);\n\nconst main = async () => {\n const options = {\n install: program.opts().install,\n update: program.opts().update,\n binaryPath: program.opts().binaryPath,\n directDownload:\n program.opts().directDownload ||\n process.env.APTOS_DIRECT_DOWNLOAD === \"1\" ||\n process.env.APTOS_DIRECT_DOWNLOAD === \"true\",\n };\n const unknownOptions = program.args;\n\n // Manually check for `--help` and handle the CLI `--help`\n if (process.argv.includes(\"--help\")) {\n // Forward to the CLI\n return runCLI(unknownOptions, options.binaryPath);\n }\n\n await parseCommandOptions(options, unknownOptions);\n};\n\nmain().catch(console.error);\n"]}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { describe, expect, it } from "vitest";
|
|
4
|
+
const WORKSPACE_ROOT = join(__dirname, "../..");
|
|
5
|
+
const EXAMPLES_DIR = join(WORKSPACE_ROOT, "examples");
|
|
6
|
+
const HELLO_BLOCKCHAIN_DIR = join(EXAMPLES_DIR, "hello_blockchain");
|
|
7
|
+
describe("Example Move Projects", () => {
|
|
8
|
+
describe("hello_blockchain example", () => {
|
|
9
|
+
it("should have Move.toml configuration file", () => {
|
|
10
|
+
const moveTomlPath = join(HELLO_BLOCKCHAIN_DIR, "Move.toml");
|
|
11
|
+
expect(existsSync(moveTomlPath)).toBe(true);
|
|
12
|
+
const content = readFileSync(moveTomlPath, "utf-8");
|
|
13
|
+
expect(content).toContain("[package]");
|
|
14
|
+
expect(content).toContain('name = "HelloBlockchain"');
|
|
15
|
+
expect(content).toContain("[addresses]");
|
|
16
|
+
expect(content).toContain("hello_blockchain");
|
|
17
|
+
expect(content).toContain("[dependencies.AptosFramework]");
|
|
18
|
+
});
|
|
19
|
+
it("should have source files", () => {
|
|
20
|
+
const sourcesDir = join(HELLO_BLOCKCHAIN_DIR, "sources");
|
|
21
|
+
expect(existsSync(sourcesDir)).toBe(true);
|
|
22
|
+
const messageMovePath = join(sourcesDir, "message.move");
|
|
23
|
+
expect(existsSync(messageMovePath)).toBe(true);
|
|
24
|
+
});
|
|
25
|
+
it("should have valid Move module structure", () => {
|
|
26
|
+
const messageMovePath = join(HELLO_BLOCKCHAIN_DIR, "sources/message.move");
|
|
27
|
+
const content = readFileSync(messageMovePath, "utf-8");
|
|
28
|
+
expect(content).toContain("module hello_blockchain::message");
|
|
29
|
+
expect(content).toContain("public entry fun");
|
|
30
|
+
expect(content).toContain("has key");
|
|
31
|
+
expect(content).toContain("#[test");
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
describe("Build Move Artifacts Workflow", () => {
|
|
36
|
+
const workflowPath = join(WORKSPACE_ROOT, ".github/workflows/build-move-artifacts.yaml");
|
|
37
|
+
it("should have the workflow file", () => {
|
|
38
|
+
expect(existsSync(workflowPath)).toBe(true);
|
|
39
|
+
});
|
|
40
|
+
it("should contain required workflow configuration", () => {
|
|
41
|
+
const content = readFileSync(workflowPath, "utf-8");
|
|
42
|
+
expect(content).toContain("name: Build Move Artifacts");
|
|
43
|
+
expect(content).toContain("on:");
|
|
44
|
+
expect(content).toContain("jobs:");
|
|
45
|
+
expect(content).toContain("Install Aptos CLI");
|
|
46
|
+
expect(content).toContain("--install");
|
|
47
|
+
expect(content).toContain("Build Move package");
|
|
48
|
+
expect(content).toContain("move compile");
|
|
49
|
+
expect(content).toContain("--named-addresses");
|
|
50
|
+
expect(content).toContain("--save-metadata");
|
|
51
|
+
expect(content).toContain("Generate publish payload");
|
|
52
|
+
expect(content).toContain("build-publish-payload");
|
|
53
|
+
expect(content).toContain("--json-output-file");
|
|
54
|
+
expect(content).toContain("Upload build artifacts");
|
|
55
|
+
expect(content).toContain("actions/upload-artifact");
|
|
56
|
+
});
|
|
57
|
+
it("should have artifact download job for downstream usage", () => {
|
|
58
|
+
const content = readFileSync(workflowPath, "utf-8");
|
|
59
|
+
expect(content).toContain("use-artifacts");
|
|
60
|
+
expect(content).toContain("needs: build-artifacts");
|
|
61
|
+
expect(content).toContain("actions/download-artifact");
|
|
62
|
+
});
|
|
63
|
+
it("should demonstrate upgrade payload generation", () => {
|
|
64
|
+
const content = readFileSync(workflowPath, "utf-8");
|
|
65
|
+
expect(content).toContain("build-upgrade-payload");
|
|
66
|
+
expect(content).toContain("--object-address");
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
//# sourceMappingURL=examples.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"examples.test.js","sourceRoot":"","sources":["../../bin/examples/examples.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAE9C,MAAM,cAAc,GAAG,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;AAChD,MAAM,YAAY,GAAG,IAAI,CAAC,cAAc,EAAE,UAAU,CAAC,CAAC;AACtD,MAAM,oBAAoB,GAAG,IAAI,CAAC,YAAY,EAAE,kBAAkB,CAAC,CAAC;AAEpE,QAAQ,CAAC,uBAAuB,EAAE,GAAG,EAAE;IACrC,QAAQ,CAAC,0BAA0B,EAAE,GAAG,EAAE;QACxC,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE;YAClD,MAAM,YAAY,GAAG,IAAI,CAAC,oBAAoB,EAAE,WAAW,CAAC,CAAC;YAC7D,MAAM,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAE5C,MAAM,OAAO,GAAG,YAAY,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;YACpD,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;YACvC,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,0BAA0B,CAAC,CAAC;YACtD,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC;YACzC,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,kBAAkB,CAAC,CAAC;YAC9C,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,+BAA+B,CAAC,CAAC;QAC7D,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,0BAA0B,EAAE,GAAG,EAAE;YAClC,MAAM,UAAU,GAAG,IAAI,CAAC,oBAAoB,EAAE,SAAS,CAAC,CAAC;YACzD,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAE1C,MAAM,eAAe,GAAG,IAAI,CAAC,UAAU,EAAE,cAAc,CAAC,CAAC;YACzD,MAAM,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;YACjD,MAAM,eAAe,GAAG,IAAI,CAC1B,oBAAoB,EACpB,sBAAsB,CACvB,CAAC;YACF,MAAM,OAAO,GAAG,YAAY,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC;YAGvD,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,kCAAkC,CAAC,CAAC;YAG9D,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,kBAAkB,CAAC,CAAC;YAC9C,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;YAGrC,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QACtC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,+BAA+B,EAAE,GAAG,EAAE;IAC7C,MAAM,YAAY,GAAG,IAAI,CACvB,cAAc,EACd,6CAA6C,CAC9C,CAAC;IAEF,EAAE,CAAC,+BAA+B,EAAE,GAAG,EAAE;QACvC,MAAM,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gDAAgD,EAAE,GAAG,EAAE;QACxD,MAAM,OAAO,GAAG,YAAY,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;QAGpD,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,4BAA4B,CAAC,CAAC;QACxD,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QACjC,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QAGnC,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,mBAAmB,CAAC,CAAC;QAC/C,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;QAGvC,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,oBAAoB,CAAC,CAAC;QAChD,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC;QAC1C,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,mBAAmB,CAAC,CAAC;QAC/C,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,iBAAiB,CAAC,CAAC;QAG7C,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,0BAA0B,CAAC,CAAC;QACtD,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,uBAAuB,CAAC,CAAC;QACnD,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,oBAAoB,CAAC,CAAC;QAGhD,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,wBAAwB,CAAC,CAAC;QACpD,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,yBAAyB,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wDAAwD,EAAE,GAAG,EAAE;QAChE,MAAM,OAAO,GAAG,YAAY,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;QAGpD,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC;QAC3C,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,wBAAwB,CAAC,CAAC;QACpD,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,2BAA2B,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+CAA+C,EAAE,GAAG,EAAE;QACvD,MAAM,OAAO,GAAG,YAAY,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;QAGpD,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,uBAAuB,CAAC,CAAC;QACnD,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,kBAAkB,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { existsSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { describe, expect, it } from \"vitest\";\n\nconst WORKSPACE_ROOT = join(__dirname, \"../..\");\nconst EXAMPLES_DIR = join(WORKSPACE_ROOT, \"examples\");\nconst HELLO_BLOCKCHAIN_DIR = join(EXAMPLES_DIR, \"hello_blockchain\");\n\ndescribe(\"Example Move Projects\", () => {\n describe(\"hello_blockchain example\", () => {\n it(\"should have Move.toml configuration file\", () => {\n const moveTomlPath = join(HELLO_BLOCKCHAIN_DIR, \"Move.toml\");\n expect(existsSync(moveTomlPath)).toBe(true);\n\n const content = readFileSync(moveTomlPath, \"utf-8\");\n expect(content).toContain(\"[package]\");\n expect(content).toContain('name = \"HelloBlockchain\"');\n expect(content).toContain(\"[addresses]\");\n expect(content).toContain(\"hello_blockchain\");\n expect(content).toContain(\"[dependencies.AptosFramework]\");\n });\n\n it(\"should have source files\", () => {\n const sourcesDir = join(HELLO_BLOCKCHAIN_DIR, \"sources\");\n expect(existsSync(sourcesDir)).toBe(true);\n\n const messageMovePath = join(sourcesDir, \"message.move\");\n expect(existsSync(messageMovePath)).toBe(true);\n });\n\n it(\"should have valid Move module structure\", () => {\n const messageMovePath = join(\n HELLO_BLOCKCHAIN_DIR,\n \"sources/message.move\",\n );\n const content = readFileSync(messageMovePath, \"utf-8\");\n\n // Verify module declaration\n expect(content).toContain(\"module hello_blockchain::message\");\n\n // Verify it has required components for a deployable module\n expect(content).toContain(\"public entry fun\");\n expect(content).toContain(\"has key\");\n\n // Verify it has a test\n expect(content).toContain(\"#[test\");\n });\n });\n});\n\ndescribe(\"Build Move Artifacts Workflow\", () => {\n const workflowPath = join(\n WORKSPACE_ROOT,\n \".github/workflows/build-move-artifacts.yaml\",\n );\n\n it(\"should have the workflow file\", () => {\n expect(existsSync(workflowPath)).toBe(true);\n });\n\n it(\"should contain required workflow configuration\", () => {\n const content = readFileSync(workflowPath, \"utf-8\");\n\n // Verify workflow structure\n expect(content).toContain(\"name: Build Move Artifacts\");\n expect(content).toContain(\"on:\");\n expect(content).toContain(\"jobs:\");\n\n // Verify it installs the CLI\n expect(content).toContain(\"Install Aptos CLI\");\n expect(content).toContain(\"--install\");\n\n // Verify it builds Move package\n expect(content).toContain(\"Build Move package\");\n expect(content).toContain(\"move compile\");\n expect(content).toContain(\"--named-addresses\");\n expect(content).toContain(\"--save-metadata\");\n\n // Verify it generates publish payload\n expect(content).toContain(\"Generate publish payload\");\n expect(content).toContain(\"build-publish-payload\");\n expect(content).toContain(\"--json-output-file\");\n\n // Verify artifact upload step\n expect(content).toContain(\"Upload build artifacts\");\n expect(content).toContain(\"actions/upload-artifact\");\n });\n\n it(\"should have artifact download job for downstream usage\", () => {\n const content = readFileSync(workflowPath, \"utf-8\");\n\n // Verify there's a job that uses artifacts\n expect(content).toContain(\"use-artifacts\");\n expect(content).toContain(\"needs: build-artifacts\");\n expect(content).toContain(\"actions/download-artifact\");\n });\n\n it(\"should demonstrate upgrade payload generation\", () => {\n const content = readFileSync(workflowPath, \"utf-8\");\n\n // Verify upgrade payload example is present\n expect(content).toContain(\"build-upgrade-payload\");\n expect(content).toContain(\"--object-address\");\n });\n});\n"]}
|
package/dist/tasks/install.js
CHANGED
|
@@ -1,42 +1,93 @@
|
|
|
1
|
-
import { execSync } from "child_process";
|
|
2
|
-
import { existsSync } from "fs";
|
|
1
|
+
import { execSync } from "node:child_process";
|
|
2
|
+
import { chmodSync, existsSync, mkdirSync } from "node:fs";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { installViaBrew, isBrewAvailable, isInstalledViaBrew, } from "../utils/brewOperations.js";
|
|
3
6
|
import { GH_CLI_DOWNLOAD_URL, PNAME } from "../utils/consts.js";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
const
|
|
11
|
-
|
|
7
|
+
import { getBinDir, getLocalBinPath, invalidateBinPathCache, } from "../utils/getLocalBinPath.js";
|
|
8
|
+
import { getOS, getTargetPlatform } from "../utils/getUserOs.js";
|
|
9
|
+
import { getCliVersion, hasUserSpecifiedVersion, } from "../utils/ghOperations.js";
|
|
10
|
+
import { installViaChoco, installViaWinget, isChocoAvailable, isInstalledViaChoco, isInstalledViaWinget, isWingetAvailable, } from "../utils/windowsPackageManagers.js";
|
|
11
|
+
export const installCli = async (directDownload = false) => {
|
|
12
|
+
invalidateBinPathCache();
|
|
13
|
+
const os = getOS();
|
|
14
|
+
const useDirectDownload = directDownload || hasUserSpecifiedVersion();
|
|
15
|
+
if (useDirectDownload && hasUserSpecifiedVersion()) {
|
|
16
|
+
console.log(`Using specified version from APTOS_CLI_VERSION: ${process.env.APTOS_CLI_VERSION}`);
|
|
17
|
+
}
|
|
18
|
+
if (!useDirectDownload) {
|
|
19
|
+
if (os === "MacOS" && isBrewAvailable()) {
|
|
20
|
+
if (isInstalledViaBrew()) {
|
|
21
|
+
console.log("Aptos CLI is already installed via Homebrew");
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
installViaBrew();
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
if (os === "Windows") {
|
|
28
|
+
if (isWingetAvailable()) {
|
|
29
|
+
if (isInstalledViaWinget()) {
|
|
30
|
+
console.log("Aptos CLI is already installed via winget");
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
installViaWinget();
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
if (isChocoAvailable()) {
|
|
37
|
+
if (isInstalledViaChoco()) {
|
|
38
|
+
console.log("Aptos CLI is already installed via Chocolatey");
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
installViaChoco();
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
const binaryPath = getLocalBinPath();
|
|
47
|
+
if (existsSync(binaryPath)) {
|
|
12
48
|
console.log("Aptos CLI is already installed");
|
|
13
49
|
return;
|
|
14
50
|
}
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
if (os === "Windows") {
|
|
19
|
-
const url = `${GH_CLI_DOWNLOAD_URL}/${PNAME}-v${latestCLIVersion}/${PNAME}-${latestCLIVersion}-${os}-x86_64.zip`;
|
|
20
|
-
execSync(`powershell -Command "if (!(Test-Path -Path 'C:\\tmp')) { New-Item -ItemType Directory -Path 'C:\\tmp' } ; Invoke-RestMethod -Uri ${url} -OutFile C:\\tmp\\aptos.zip; Expand-Archive -Path C:\\tmp\\aptos.zip -DestinationPath C:\\tmp -Force; Move-Item -Path C:\\tmp\\aptos.exe -Destination \"${path}\""`);
|
|
21
|
-
}
|
|
22
|
-
else if (os === "MacOS") {
|
|
23
|
-
execSyncShell("brew install aptos", { encoding: "utf8" });
|
|
51
|
+
const binDir = getBinDir();
|
|
52
|
+
if (!existsSync(binDir)) {
|
|
53
|
+
mkdirSync(binDir, { recursive: true });
|
|
24
54
|
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
55
|
+
const targetPlatform = getTargetPlatform();
|
|
56
|
+
const version = await getCliVersion(targetPlatform);
|
|
57
|
+
console.log(`Downloading Aptos CLI version ${version} for ${targetPlatform}...`);
|
|
58
|
+
const url = `${GH_CLI_DOWNLOAD_URL}/${PNAME}-v${version}/${PNAME}-${version}-${targetPlatform}.zip`;
|
|
59
|
+
const tempDir = tmpdir();
|
|
60
|
+
try {
|
|
61
|
+
if (os === "Windows") {
|
|
62
|
+
const zipPath = join(tempDir, "aptos-cli.zip");
|
|
63
|
+
execSync(`powershell -Command "` +
|
|
64
|
+
`Invoke-WebRequest -Uri '${url}' -OutFile '${zipPath}'; ` +
|
|
65
|
+
`Expand-Archive -Path '${zipPath}' -DestinationPath '${binDir}' -Force; ` +
|
|
66
|
+
`Remove-Item -Path '${zipPath}' -Force"`, { stdio: "inherit" });
|
|
30
67
|
}
|
|
31
|
-
|
|
32
|
-
|
|
68
|
+
else {
|
|
69
|
+
const zipPath = join(tempDir, "aptos-cli.zip");
|
|
70
|
+
execSync(`curl -L -o "${zipPath}" "${url}"`, { stdio: "inherit" });
|
|
71
|
+
execSync(`unzip -o -q "${zipPath}" -d "${tempDir}"`, {
|
|
72
|
+
stdio: "inherit",
|
|
73
|
+
});
|
|
74
|
+
const extractedBinary = join(tempDir, "aptos");
|
|
75
|
+
execSync(`mv "${extractedBinary}" "${binaryPath}"`, { stdio: "inherit" });
|
|
76
|
+
chmodSync(binaryPath, 0o755);
|
|
77
|
+
try {
|
|
78
|
+
execSync(`rm -f "${zipPath}"`, { stdio: "ignore" });
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
}
|
|
33
82
|
}
|
|
34
|
-
|
|
35
|
-
|
|
83
|
+
console.log(`Aptos CLI installed successfully to ${binaryPath}`);
|
|
84
|
+
if (os !== "Windows") {
|
|
85
|
+
console.log(`\nMake sure ${binDir} is in your PATH. You can add it by running:`);
|
|
86
|
+
console.log(` export PATH="${binDir}:$PATH"`);
|
|
36
87
|
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
88
|
+
}
|
|
89
|
+
catch (error) {
|
|
90
|
+
throw new Error(`Failed to install Aptos CLI: ${error instanceof Error ? error.message : String(error)}`);
|
|
40
91
|
}
|
|
41
92
|
};
|
|
42
93
|
//# sourceMappingURL=install.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"install.js","sourceRoot":"","sources":["../../bin/tasks/install.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"install.js","sourceRoot":"","sources":["../../bin/tasks/install.ts"],"names":[],"mappings":"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","sourcesContent":["import { execSync } from \"node:child_process\";\nimport { chmodSync, existsSync, mkdirSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport {\n installViaBrew,\n isBrewAvailable,\n isInstalledViaBrew,\n} from \"../utils/brewOperations.js\";\nimport { GH_CLI_DOWNLOAD_URL, PNAME } from \"../utils/consts.js\";\nimport {\n getBinDir,\n getLocalBinPath,\n invalidateBinPathCache,\n} from \"../utils/getLocalBinPath.js\";\nimport { getOS, getTargetPlatform } from \"../utils/getUserOs.js\";\nimport {\n getCliVersion,\n hasUserSpecifiedVersion,\n} from \"../utils/ghOperations.js\";\nimport {\n installViaChoco,\n installViaWinget,\n isChocoAvailable,\n isInstalledViaChoco,\n isInstalledViaWinget,\n isWingetAvailable,\n} from \"../utils/windowsPackageManagers.js\";\n\n/**\n * Install the Aptos CLI.\n *\n * Installation priority:\n *\n * macOS:\n * 1. Homebrew (if available)\n * 2. Direct download from GitHub releases\n *\n * Windows:\n * 1. winget (if available)\n * 2. Chocolatey (if available)\n * 3. Direct download from GitHub releases\n *\n * Linux:\n * - Direct download from GitHub releases\n *\n * Note: When APTOS_CLI_VERSION is set, package managers are skipped and the\n * specified version is downloaded directly from GitHub releases.\n *\n * @param directDownload - If true, skip package managers and download directly\n */\nexport const installCli = async (\n directDownload: boolean = false,\n): Promise<void> => {\n invalidateBinPathCache();\n const os = getOS();\n\n // If a specific version is requested, force direct download\n // Package managers don't support installing specific versions\n const useDirectDownload = directDownload || hasUserSpecifiedVersion();\n\n if (useDirectDownload && hasUserSpecifiedVersion()) {\n console.log(\n `Using specified version from APTOS_CLI_VERSION: ${process.env.APTOS_CLI_VERSION}`,\n );\n }\n\n // Skip package managers if directDownload is set or specific version requested\n if (!useDirectDownload) {\n // On macOS, prefer Homebrew if available\n if (os === \"MacOS\" && isBrewAvailable()) {\n if (isInstalledViaBrew()) {\n console.log(\"Aptos CLI is already installed via Homebrew\");\n return;\n }\n installViaBrew();\n return;\n }\n\n // On Windows, prefer winget, then Chocolatey\n if (os === \"Windows\") {\n if (isWingetAvailable()) {\n if (isInstalledViaWinget()) {\n console.log(\"Aptos CLI is already installed via winget\");\n return;\n }\n installViaWinget();\n return;\n }\n\n if (isChocoAvailable()) {\n if (isInstalledViaChoco()) {\n console.log(\"Aptos CLI is already installed via Chocolatey\");\n return;\n }\n installViaChoco();\n return;\n }\n }\n }\n\n // Direct download installation\n const binaryPath = getLocalBinPath();\n if (existsSync(binaryPath)) {\n console.log(\"Aptos CLI is already installed\");\n return;\n }\n\n // Ensure the bin directory exists\n const binDir = getBinDir();\n if (!existsSync(binDir)) {\n mkdirSync(binDir, { recursive: true });\n }\n\n // Get target platform first for version validation\n const targetPlatform = getTargetPlatform();\n\n // Get the version to install (user-specified or latest)\n const version = await getCliVersion(targetPlatform);\n\n console.log(\n `Downloading Aptos CLI version ${version} for ${targetPlatform}...`,\n );\n\n // Build download URL matching official release artifact naming\n const url = `${GH_CLI_DOWNLOAD_URL}/${PNAME}-v${version}/${PNAME}-${version}-${targetPlatform}.zip`;\n\n const tempDir = tmpdir();\n\n try {\n if (os === \"Windows\") {\n // Windows installation using PowerShell\n const zipPath = join(tempDir, \"aptos-cli.zip\");\n execSync(\n `powershell -Command \"` +\n `Invoke-WebRequest -Uri '${url}' -OutFile '${zipPath}'; ` +\n `Expand-Archive -Path '${zipPath}' -DestinationPath '${binDir}' -Force; ` +\n `Remove-Item -Path '${zipPath}' -Force\"`,\n { stdio: \"inherit\" },\n );\n } else {\n // macOS (without Homebrew) and Linux installation using curl/unzip\n const zipPath = join(tempDir, \"aptos-cli.zip\");\n\n // Download\n execSync(`curl -L -o \"${zipPath}\" \"${url}\"`, { stdio: \"inherit\" });\n\n // Extract\n execSync(`unzip -o -q \"${zipPath}\" -d \"${tempDir}\"`, {\n stdio: \"inherit\",\n });\n\n // Move binary to bin directory\n const extractedBinary = join(tempDir, \"aptos\");\n execSync(`mv \"${extractedBinary}\" \"${binaryPath}\"`, { stdio: \"inherit\" });\n\n // Set executable permissions\n chmodSync(binaryPath, 0o755);\n\n // Clean up\n try {\n execSync(`rm -f \"${zipPath}\"`, { stdio: \"ignore\" });\n } catch {\n // Ignore cleanup errors\n }\n }\n\n console.log(`Aptos CLI installed successfully to ${binaryPath}`);\n\n // Remind user about PATH if needed\n if (os !== \"Windows\") {\n console.log(\n `\\nMake sure ${binDir} is in your PATH. You can add it by running:`,\n );\n console.log(` export PATH=\"${binDir}:$PATH\"`);\n }\n } catch (error) {\n throw new Error(\n `Failed to install Aptos CLI: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n};\n"]}
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
|
+
vi.mock("child_process", () => ({
|
|
3
|
+
execSync: vi.fn(),
|
|
4
|
+
}));
|
|
5
|
+
vi.mock("fs", () => ({
|
|
6
|
+
existsSync: vi.fn(),
|
|
7
|
+
chmodSync: vi.fn(),
|
|
8
|
+
mkdirSync: vi.fn(),
|
|
9
|
+
}));
|
|
10
|
+
vi.mock("os", () => ({
|
|
11
|
+
tmpdir: () => "/tmp",
|
|
12
|
+
homedir: () => "/home/user",
|
|
13
|
+
platform: vi.fn(() => "linux"),
|
|
14
|
+
arch: vi.fn(() => "x64"),
|
|
15
|
+
}));
|
|
16
|
+
vi.mock("../utils/getUserOs.js", () => ({
|
|
17
|
+
getOS: vi.fn(),
|
|
18
|
+
getTargetPlatform: vi.fn(),
|
|
19
|
+
}));
|
|
20
|
+
vi.mock("../utils/getLocalBinPath.js", () => ({
|
|
21
|
+
getLocalBinPath: vi.fn(),
|
|
22
|
+
getBinDir: vi.fn(),
|
|
23
|
+
invalidateBinPathCache: vi.fn(),
|
|
24
|
+
}));
|
|
25
|
+
vi.mock("../utils/ghOperations.js", () => ({
|
|
26
|
+
getCliVersion: vi.fn(),
|
|
27
|
+
hasUserSpecifiedVersion: vi.fn(),
|
|
28
|
+
}));
|
|
29
|
+
vi.mock("../utils/brewOperations.js", () => ({
|
|
30
|
+
isBrewAvailable: vi.fn(),
|
|
31
|
+
isInstalledViaBrew: vi.fn(),
|
|
32
|
+
installViaBrew: vi.fn(),
|
|
33
|
+
}));
|
|
34
|
+
vi.mock("../utils/windowsPackageManagers.js", () => ({
|
|
35
|
+
isWingetAvailable: vi.fn(),
|
|
36
|
+
isChocoAvailable: vi.fn(),
|
|
37
|
+
isInstalledViaWinget: vi.fn(),
|
|
38
|
+
isInstalledViaChoco: vi.fn(),
|
|
39
|
+
installViaWinget: vi.fn(),
|
|
40
|
+
installViaChoco: vi.fn(),
|
|
41
|
+
}));
|
|
42
|
+
import { execSync } from "node:child_process";
|
|
43
|
+
import { existsSync, mkdirSync } from "node:fs";
|
|
44
|
+
import { installViaBrew, isBrewAvailable, isInstalledViaBrew, } from "../utils/brewOperations.js";
|
|
45
|
+
import { getBinDir, getLocalBinPath } from "../utils/getLocalBinPath.js";
|
|
46
|
+
import { getOS, getTargetPlatform } from "../utils/getUserOs.js";
|
|
47
|
+
import { getCliVersion, hasUserSpecifiedVersion, } from "../utils/ghOperations.js";
|
|
48
|
+
import { installViaChoco, installViaWinget, isChocoAvailable, isInstalledViaChoco, isInstalledViaWinget, isWingetAvailable, } from "../utils/windowsPackageManagers.js";
|
|
49
|
+
import { installCli } from "./install.js";
|
|
50
|
+
describe("install", () => {
|
|
51
|
+
beforeEach(() => {
|
|
52
|
+
vi.clearAllMocks();
|
|
53
|
+
vi.mocked(getLocalBinPath).mockReturnValue("/home/user/.local/bin/aptos");
|
|
54
|
+
vi.mocked(getBinDir).mockReturnValue("/home/user/.local/bin");
|
|
55
|
+
vi.mocked(getCliVersion).mockResolvedValue("1.0.0");
|
|
56
|
+
vi.mocked(hasUserSpecifiedVersion).mockReturnValue(false);
|
|
57
|
+
vi.mocked(getTargetPlatform).mockReturnValue("Linux-x86_64");
|
|
58
|
+
});
|
|
59
|
+
afterEach(() => {
|
|
60
|
+
vi.restoreAllMocks();
|
|
61
|
+
});
|
|
62
|
+
describe("macOS with Homebrew", () => {
|
|
63
|
+
beforeEach(() => {
|
|
64
|
+
vi.mocked(getOS).mockReturnValue("MacOS");
|
|
65
|
+
vi.mocked(isBrewAvailable).mockReturnValue(true);
|
|
66
|
+
});
|
|
67
|
+
it("should use Homebrew when available", async () => {
|
|
68
|
+
vi.mocked(isInstalledViaBrew).mockReturnValue(false);
|
|
69
|
+
await installCli();
|
|
70
|
+
expect(installViaBrew).toHaveBeenCalled();
|
|
71
|
+
expect(execSync).not.toHaveBeenCalled();
|
|
72
|
+
});
|
|
73
|
+
it("should skip if already installed via Homebrew", async () => {
|
|
74
|
+
vi.mocked(isInstalledViaBrew).mockReturnValue(true);
|
|
75
|
+
await installCli();
|
|
76
|
+
expect(installViaBrew).not.toHaveBeenCalled();
|
|
77
|
+
});
|
|
78
|
+
it("should skip Homebrew when directDownload is true", async () => {
|
|
79
|
+
vi.mocked(isInstalledViaBrew).mockReturnValue(false);
|
|
80
|
+
vi.mocked(existsSync).mockReturnValue(false);
|
|
81
|
+
vi.mocked(execSync).mockReturnValue(Buffer.from(""));
|
|
82
|
+
vi.mocked(getTargetPlatform).mockReturnValue("macos-x86_64");
|
|
83
|
+
await installCli(true);
|
|
84
|
+
expect(installViaBrew).not.toHaveBeenCalled();
|
|
85
|
+
expect(execSync).toHaveBeenCalled();
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
describe("Windows with winget", () => {
|
|
89
|
+
beforeEach(() => {
|
|
90
|
+
vi.mocked(getOS).mockReturnValue("Windows");
|
|
91
|
+
vi.mocked(isBrewAvailable).mockReturnValue(false);
|
|
92
|
+
vi.mocked(isWingetAvailable).mockReturnValue(true);
|
|
93
|
+
vi.mocked(isChocoAvailable).mockReturnValue(false);
|
|
94
|
+
});
|
|
95
|
+
it("should use winget when available", async () => {
|
|
96
|
+
vi.mocked(isInstalledViaWinget).mockReturnValue(false);
|
|
97
|
+
await installCli();
|
|
98
|
+
expect(installViaWinget).toHaveBeenCalled();
|
|
99
|
+
expect(installViaChoco).not.toHaveBeenCalled();
|
|
100
|
+
});
|
|
101
|
+
it("should skip if already installed via winget", async () => {
|
|
102
|
+
vi.mocked(isInstalledViaWinget).mockReturnValue(true);
|
|
103
|
+
await installCli();
|
|
104
|
+
expect(installViaWinget).not.toHaveBeenCalled();
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
describe("Windows with Chocolatey", () => {
|
|
108
|
+
beforeEach(() => {
|
|
109
|
+
vi.mocked(getOS).mockReturnValue("Windows");
|
|
110
|
+
vi.mocked(isBrewAvailable).mockReturnValue(false);
|
|
111
|
+
vi.mocked(isWingetAvailable).mockReturnValue(false);
|
|
112
|
+
vi.mocked(isChocoAvailable).mockReturnValue(true);
|
|
113
|
+
});
|
|
114
|
+
it("should use Chocolatey when winget is not available", async () => {
|
|
115
|
+
vi.mocked(isInstalledViaChoco).mockReturnValue(false);
|
|
116
|
+
await installCli();
|
|
117
|
+
expect(installViaChoco).toHaveBeenCalled();
|
|
118
|
+
expect(installViaWinget).not.toHaveBeenCalled();
|
|
119
|
+
});
|
|
120
|
+
it("should skip if already installed via Chocolatey", async () => {
|
|
121
|
+
vi.mocked(isInstalledViaChoco).mockReturnValue(true);
|
|
122
|
+
await installCli();
|
|
123
|
+
expect(installViaChoco).not.toHaveBeenCalled();
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
describe("Windows direct download", () => {
|
|
127
|
+
beforeEach(() => {
|
|
128
|
+
vi.mocked(getOS).mockReturnValue("Windows");
|
|
129
|
+
vi.mocked(isBrewAvailable).mockReturnValue(false);
|
|
130
|
+
vi.mocked(isWingetAvailable).mockReturnValue(false);
|
|
131
|
+
vi.mocked(isChocoAvailable).mockReturnValue(false);
|
|
132
|
+
vi.mocked(existsSync).mockReturnValue(false);
|
|
133
|
+
vi.mocked(getTargetPlatform).mockReturnValue("Windows-x86_64");
|
|
134
|
+
});
|
|
135
|
+
it("should download directly when no package manager available", async () => {
|
|
136
|
+
vi.mocked(execSync).mockReturnValue(Buffer.from(""));
|
|
137
|
+
await installCli();
|
|
138
|
+
expect(installViaWinget).not.toHaveBeenCalled();
|
|
139
|
+
expect(installViaChoco).not.toHaveBeenCalled();
|
|
140
|
+
expect(execSync).toHaveBeenCalledWith(expect.stringContaining("powershell"), expect.any(Object));
|
|
141
|
+
});
|
|
142
|
+
it("should skip package managers when directDownload is true", async () => {
|
|
143
|
+
vi.mocked(isWingetAvailable).mockReturnValue(true);
|
|
144
|
+
vi.mocked(isChocoAvailable).mockReturnValue(true);
|
|
145
|
+
vi.mocked(execSync).mockReturnValue(Buffer.from(""));
|
|
146
|
+
await installCli(true);
|
|
147
|
+
expect(installViaWinget).not.toHaveBeenCalled();
|
|
148
|
+
expect(installViaChoco).not.toHaveBeenCalled();
|
|
149
|
+
expect(execSync).toHaveBeenCalled();
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
describe("Linux direct download", () => {
|
|
153
|
+
beforeEach(() => {
|
|
154
|
+
vi.mocked(getOS).mockReturnValue("Linux");
|
|
155
|
+
vi.mocked(isBrewAvailable).mockReturnValue(false);
|
|
156
|
+
vi.mocked(existsSync).mockReturnValue(false);
|
|
157
|
+
vi.mocked(getTargetPlatform).mockReturnValue("Ubuntu-22.04-x86_64");
|
|
158
|
+
});
|
|
159
|
+
it("should download directly on Linux", async () => {
|
|
160
|
+
vi.mocked(execSync).mockReturnValue(Buffer.from(""));
|
|
161
|
+
await installCli();
|
|
162
|
+
expect(execSync).toHaveBeenCalledWith(expect.stringContaining("curl"), expect.any(Object));
|
|
163
|
+
});
|
|
164
|
+
it("should create bin directory if it doesn't exist", async () => {
|
|
165
|
+
vi.mocked(existsSync).mockImplementation((path) => {
|
|
166
|
+
if (path === "/home/user/.local/bin")
|
|
167
|
+
return false;
|
|
168
|
+
return false;
|
|
169
|
+
});
|
|
170
|
+
vi.mocked(execSync).mockReturnValue(Buffer.from(""));
|
|
171
|
+
await installCli();
|
|
172
|
+
expect(mkdirSync).toHaveBeenCalledWith("/home/user/.local/bin", {
|
|
173
|
+
recursive: true,
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
});
|
|
177
|
+
describe("already installed", () => {
|
|
178
|
+
it("should skip if binary already exists", async () => {
|
|
179
|
+
vi.mocked(getOS).mockReturnValue("Linux");
|
|
180
|
+
vi.mocked(isBrewAvailable).mockReturnValue(false);
|
|
181
|
+
vi.mocked(existsSync).mockReturnValue(true);
|
|
182
|
+
await installCli();
|
|
183
|
+
expect(execSync).not.toHaveBeenCalled();
|
|
184
|
+
expect(getCliVersion).not.toHaveBeenCalled();
|
|
185
|
+
});
|
|
186
|
+
});
|
|
187
|
+
describe("specific version via APTOS_CLI_VERSION", () => {
|
|
188
|
+
beforeEach(() => {
|
|
189
|
+
vi.mocked(hasUserSpecifiedVersion).mockReturnValue(true);
|
|
190
|
+
vi.mocked(getCliVersion).mockResolvedValue("4.5.0");
|
|
191
|
+
});
|
|
192
|
+
it("should skip package managers when specific version is set", async () => {
|
|
193
|
+
vi.mocked(getOS).mockReturnValue("MacOS");
|
|
194
|
+
vi.mocked(isBrewAvailable).mockReturnValue(true);
|
|
195
|
+
vi.mocked(isInstalledViaBrew).mockReturnValue(false);
|
|
196
|
+
vi.mocked(existsSync).mockReturnValue(false);
|
|
197
|
+
vi.mocked(execSync).mockReturnValue(Buffer.from(""));
|
|
198
|
+
vi.mocked(getTargetPlatform).mockReturnValue("macos-x86_64");
|
|
199
|
+
await installCli();
|
|
200
|
+
expect(installViaBrew).not.toHaveBeenCalled();
|
|
201
|
+
expect(execSync).toHaveBeenCalled();
|
|
202
|
+
});
|
|
203
|
+
it("should skip winget when specific version is set on Windows", async () => {
|
|
204
|
+
vi.mocked(getOS).mockReturnValue("Windows");
|
|
205
|
+
vi.mocked(isBrewAvailable).mockReturnValue(false);
|
|
206
|
+
vi.mocked(isWingetAvailable).mockReturnValue(true);
|
|
207
|
+
vi.mocked(isChocoAvailable).mockReturnValue(true);
|
|
208
|
+
vi.mocked(existsSync).mockReturnValue(false);
|
|
209
|
+
vi.mocked(execSync).mockReturnValue(Buffer.from(""));
|
|
210
|
+
vi.mocked(getTargetPlatform).mockReturnValue("Windows-x86_64");
|
|
211
|
+
await installCli();
|
|
212
|
+
expect(installViaWinget).not.toHaveBeenCalled();
|
|
213
|
+
expect(installViaChoco).not.toHaveBeenCalled();
|
|
214
|
+
expect(execSync).toHaveBeenCalled();
|
|
215
|
+
});
|
|
216
|
+
it("should use specific version in download URL", async () => {
|
|
217
|
+
vi.mocked(getOS).mockReturnValue("Linux");
|
|
218
|
+
vi.mocked(isBrewAvailable).mockReturnValue(false);
|
|
219
|
+
vi.mocked(existsSync).mockReturnValue(false);
|
|
220
|
+
vi.mocked(execSync).mockReturnValue(Buffer.from(""));
|
|
221
|
+
vi.mocked(getTargetPlatform).mockReturnValue("Ubuntu-22.04-x86_64");
|
|
222
|
+
await installCli();
|
|
223
|
+
expect(execSync).toHaveBeenCalledWith(expect.stringContaining("4.5.0"), expect.any(Object));
|
|
224
|
+
});
|
|
225
|
+
});
|
|
226
|
+
});
|
|
227
|
+
//# sourceMappingURL=install.test.js.map
|