@octoberswimmer/aer-sf-plugin 0.0.1 → 0.0.3
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 +41 -2
- package/lib/aer.d.ts +1 -2
- package/lib/aer.js +9 -6
- package/lib/aer.js.map +1 -1
- package/lib/aerBinary.d.ts +114 -0
- package/lib/aerBinary.js +510 -0
- package/lib/aerBinary.js.map +1 -0
- package/lib/commands/aer/apex/run/test.d.ts +1 -0
- package/lib/commands/aer/apex/run/test.js +48 -1
- package/lib/commands/aer/apex/run/test.js.map +1 -1
- package/messages/aer.apex.run.test.md +22 -1
- package/oclif.manifest.json +2 -2
- package/package.json +7 -2
package/README.md
CHANGED
|
@@ -20,9 +20,10 @@ copy.
|
|
|
20
20
|
## Requirements
|
|
21
21
|
|
|
22
22
|
- [Salesforce CLI](https://developer.salesforce.com/tools/salesforcecli) (`sf`)
|
|
23
|
-
- [aer](https://github.com/octoberswimmer/aer-dist) on `PATH` (or set
|
|
24
|
-
`AER_BIN=/abs/path/to/aer`)
|
|
25
23
|
- Node.js >= 18
|
|
24
|
+
- [aer](https://github.com/octoberswimmer/aer-dist) — the plugin will offer to
|
|
25
|
+
download the right build for your platform on first use if it can't find one
|
|
26
|
+
already (see [Locating the aer binary](#locating-the-aer-binary) below).
|
|
26
27
|
|
|
27
28
|
## Install
|
|
28
29
|
|
|
@@ -64,6 +65,44 @@ With code coverage:
|
|
|
64
65
|
sf aer apex run test --code-coverage --output-dir test-results
|
|
65
66
|
```
|
|
66
67
|
|
|
68
|
+
## Locating the aer binary
|
|
69
|
+
|
|
70
|
+
When the plugin needs to invoke `aer`, it tries these sources in order:
|
|
71
|
+
|
|
72
|
+
1. The `AER_BIN` environment variable, when it points to an executable file.
|
|
73
|
+
2. A copy previously downloaded by this plugin, stored under a platform-specific
|
|
74
|
+
data directory:
|
|
75
|
+
- Linux: `$XDG_DATA_HOME/aer-sf-plugin/aer-bin/` (default
|
|
76
|
+
`~/.local/share/aer-sf-plugin/aer-bin/`)
|
|
77
|
+
- macOS: `~/Library/Application Support/aer-sf-plugin/aer-bin/`
|
|
78
|
+
- Windows: `%LOCALAPPDATA%\aer-sf-plugin\aer-bin\`
|
|
79
|
+
3. `aer` discovered on `PATH`.
|
|
80
|
+
4. If none of the above match and the terminal is interactive, the plugin asks
|
|
81
|
+
for confirmation, then downloads the latest
|
|
82
|
+
[aer-dist](https://github.com/octoberswimmer/aer-dist) release for your
|
|
83
|
+
platform, extracts it into the data directory above, and uses it for that
|
|
84
|
+
run and all later runs.
|
|
85
|
+
|
|
86
|
+
### Update checks
|
|
87
|
+
|
|
88
|
+
Once the plugin has downloaded its own copy of `aer`, each subsequent run starts
|
|
89
|
+
a background GitHub query (rate-limited to one check every 12 hours) to see
|
|
90
|
+
whether a newer release has been published. The query runs in parallel with
|
|
91
|
+
staging and the test execution, so it does not slow tests down. After the test
|
|
92
|
+
run finishes, if a newer release is available you'll be prompted to install it.
|
|
93
|
+
Decline and the same version won't be re-offered until something newer ships.
|
|
94
|
+
|
|
95
|
+
The check is skipped entirely when:
|
|
96
|
+
|
|
97
|
+
- `AER_BIN` is set or `aer` is on `PATH` (i.e. the user manages their own copy).
|
|
98
|
+
- The terminal is non-interactive (`--json`, no TTY).
|
|
99
|
+
|
|
100
|
+
To force an update outside the 12-hour window, delete the contents of the
|
|
101
|
+
`aer-bin/` directory (or the whole `aer-sf-plugin/` directory) and rerun.
|
|
102
|
+
|
|
103
|
+
In non-interactive environments (CI, `--json`) the plugin will not prompt; set
|
|
104
|
+
`AER_BIN` or install `aer` on `PATH` ahead of time.
|
|
105
|
+
|
|
67
106
|
## How source is staged
|
|
68
107
|
|
|
69
108
|
The plugin copies the project's Apex source into a temp directory before
|
package/lib/aer.d.ts
CHANGED
|
@@ -8,5 +8,4 @@ export type AerInvocation = {
|
|
|
8
8
|
verbose: boolean;
|
|
9
9
|
};
|
|
10
10
|
export declare function buildAerArgs(inv: AerInvocation): string[];
|
|
11
|
-
export declare function
|
|
12
|
-
export declare function runAer(args: string[], cwd: string): Promise<number>;
|
|
11
|
+
export declare function runAer(binaryPath: string, args: string[], cwd: string): Promise<number>;
|
package/lib/aer.js
CHANGED
|
@@ -19,18 +19,21 @@ export function buildAerArgs(inv) {
|
|
|
19
19
|
}
|
|
20
20
|
return args;
|
|
21
21
|
}
|
|
22
|
-
export function
|
|
23
|
-
return process.env.AER_BIN ?? 'aer';
|
|
24
|
-
}
|
|
25
|
-
export async function runAer(args, cwd) {
|
|
22
|
+
export async function runAer(binaryPath, args, cwd) {
|
|
26
23
|
return new Promise((resolvePromise, rejectPromise) => {
|
|
27
|
-
const child = spawn(
|
|
24
|
+
const child = spawn(binaryPath, args, {
|
|
28
25
|
cwd,
|
|
29
26
|
stdio: 'inherit',
|
|
27
|
+
env: {
|
|
28
|
+
...process.env,
|
|
29
|
+
// Suppress aer's own version-check notification — the plugin
|
|
30
|
+
// surfaces its own prompt to upgrade.
|
|
31
|
+
AER_AUTOUPDATE_DISABLED: '1',
|
|
32
|
+
},
|
|
30
33
|
});
|
|
31
34
|
child.on('error', (err) => {
|
|
32
35
|
if (err.code === 'ENOENT') {
|
|
33
|
-
rejectPromise(new Error(`Could not
|
|
36
|
+
rejectPromise(new Error(`Could not execute aer at ${binaryPath}. The file may have been moved or deleted.`));
|
|
34
37
|
return;
|
|
35
38
|
}
|
|
36
39
|
rejectPromise(err);
|
package/lib/aer.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"aer.js","sourceRoot":"","sources":["../src/aer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAa3C,MAAM,UAAU,YAAY,CAAC,GAAkB;IAC9C,MAAM,IAAI,GAAa,CAAC,MAAM,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC;IAC/C,KAAK,MAAM,CAAC,IAAI,GAAG,CAAC,OAAO,EAAE,CAAC;QAC7B,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;IAC1B,CAAC;IACD,IAAI,GAAG,CAAC,YAAY,KAAK,OAAO,IAAI,GAAG,CAAC,UAAU,EAAE,CAAC;QACpD,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,CAAC,UAAU,CAAC,CAAC;IACtC,CAAC;SAAM,IAAI,GAAG,CAAC,YAAY,KAAK,MAAM,IAAI,GAAG,CAAC,UAAU,EAAE,CAAC;QAC1D,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,UAAU,CAAC,CAAC;IACrC,CAAC;SAAM,IAAI,GAAG,CAAC,YAAY,KAAK,MAAM,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC;QAC3D,+CAA+C;QAC/C,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACrB,CAAC;IACD,IAAI,GAAG,CAAC,YAAY,EAAE,CAAC;QACtB,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,GAAG,CAAC,YAAY,CAAC,CAAC;IAC3C,CAAC;IACD,OAAO,IAAI,CAAC;AACb,CAAC;AAED,MAAM,
|
|
1
|
+
{"version":3,"file":"aer.js","sourceRoot":"","sources":["../src/aer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAa3C,MAAM,UAAU,YAAY,CAAC,GAAkB;IAC9C,MAAM,IAAI,GAAa,CAAC,MAAM,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC;IAC/C,KAAK,MAAM,CAAC,IAAI,GAAG,CAAC,OAAO,EAAE,CAAC;QAC7B,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;IAC1B,CAAC;IACD,IAAI,GAAG,CAAC,YAAY,KAAK,OAAO,IAAI,GAAG,CAAC,UAAU,EAAE,CAAC;QACpD,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,CAAC,UAAU,CAAC,CAAC;IACtC,CAAC;SAAM,IAAI,GAAG,CAAC,YAAY,KAAK,MAAM,IAAI,GAAG,CAAC,UAAU,EAAE,CAAC;QAC1D,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,UAAU,CAAC,CAAC;IACrC,CAAC;SAAM,IAAI,GAAG,CAAC,YAAY,KAAK,MAAM,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC;QAC3D,+CAA+C;QAC/C,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACrB,CAAC;IACD,IAAI,GAAG,CAAC,YAAY,EAAE,CAAC;QACtB,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,GAAG,CAAC,YAAY,CAAC,CAAC;IAC3C,CAAC;IACD,OAAO,IAAI,CAAC;AACb,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,UAAkB,EAAE,IAAc,EAAE,GAAW;IAC3E,OAAO,IAAI,OAAO,CAAC,CAAC,cAAc,EAAE,aAAa,EAAE,EAAE;QACpD,MAAM,KAAK,GAAG,KAAK,CAAC,UAAU,EAAE,IAAI,EAAE;YACrC,GAAG;YACH,KAAK,EAAE,SAAS;YAChB,GAAG,EAAE;gBACJ,GAAG,OAAO,CAAC,GAAG;gBACd,6DAA6D;gBAC7D,sCAAsC;gBACtC,uBAAuB,EAAE,GAAG;aAC5B;SACD,CAAC,CAAC;QACH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAA0B,EAAE,EAAE;YAChD,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAC3B,aAAa,CACZ,IAAI,KAAK,CACR,4BAA4B,UAAU,4CAA4C,CAClF,CACD,CAAC;gBACF,OAAO;YACR,CAAC;YACD,aAAa,CAAC,GAAG,CAAC,CAAC;QACpB,CAAC,CAAC,CAAC;QACH,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE;YACjC,IAAI,MAAM,EAAE,CAAC;gBACZ,cAAc,CAAC,GAAG,GAAG,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACjF,CAAC;iBAAM,CAAC;gBACP,cAAc,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC;YAC3B,CAAC;QACF,CAAC,CAAC,CAAC;IACJ,CAAC,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
export type ConfirmFn = (message: string) => Promise<boolean>;
|
|
2
|
+
export type LogFn = (message: string) => void;
|
|
3
|
+
export type EnsureAerOptions = {
|
|
4
|
+
/** When false, never prompt — throw if binary cannot be resolved. Defaults to true. */
|
|
5
|
+
allowPrompt?: boolean;
|
|
6
|
+
/** Prompt callback for yes/no confirmation. Required when allowPrompt is true. */
|
|
7
|
+
confirm?: ConfirmFn;
|
|
8
|
+
/** Informational log callback. */
|
|
9
|
+
log?: LogFn;
|
|
10
|
+
/** Warning log callback. */
|
|
11
|
+
warn?: LogFn;
|
|
12
|
+
/** Override the storage directory (for testing). */
|
|
13
|
+
storageDir?: string;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Resolve the aer binary path. Resolution order:
|
|
17
|
+
* 1. AER_BIN env var (must be executable).
|
|
18
|
+
* 2. Previously downloaded copy in the plugin's storage dir.
|
|
19
|
+
* 3. `aer` on PATH.
|
|
20
|
+
* 4. Prompt to download the latest release into the plugin's storage dir.
|
|
21
|
+
*/
|
|
22
|
+
export declare function ensureAerBinary(opts?: EnsureAerOptions): Promise<string>;
|
|
23
|
+
/** For tests: forget any cached binary path so the next call re-resolves. */
|
|
24
|
+
export declare function _resetAerBinaryCache(): void;
|
|
25
|
+
/** Module-private internals exposed for tests only. Not part of the public API. */
|
|
26
|
+
export declare const _internals: {
|
|
27
|
+
readonly replaceBinary: typeof replaceBinary;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Default storage directory for binaries downloaded by this plugin. Mirrors the
|
|
31
|
+
* conventions used by `envPaths` / oclif: respects XDG on Linux, Library/Application
|
|
32
|
+
* Support on macOS, and LOCALAPPDATA on Windows.
|
|
33
|
+
*/
|
|
34
|
+
export declare function defaultStorageDir(): string;
|
|
35
|
+
/**
|
|
36
|
+
* Install a new binary at `target`, using the same atomic-rename strategy as
|
|
37
|
+
* `aer upgrade` so that an in-use executable (notably on Windows) doesn't
|
|
38
|
+
* cause the install to fail.
|
|
39
|
+
*
|
|
40
|
+
* Unix: write to `.{name}.new`, then rename over the target — atomic.
|
|
41
|
+
* Windows: write to `.{name}.new`, rename existing target to `.{name}.old`,
|
|
42
|
+
* rename `.{name}.new` into place, then best-effort delete `.old`
|
|
43
|
+
* (which may stay around briefly if the file is still held open).
|
|
44
|
+
*/
|
|
45
|
+
declare function replaceBinary(binDir: string, binaryName: string, data: Buffer, target: string): Promise<void>;
|
|
46
|
+
export declare function platformDetails(version: string): {
|
|
47
|
+
platformKey: 'linux' | 'darwin' | 'windows';
|
|
48
|
+
cpuKey: 'amd64' | 'arm64';
|
|
49
|
+
binaryName: string;
|
|
50
|
+
archiveName: string;
|
|
51
|
+
};
|
|
52
|
+
export declare function readStoredVersion(storageDir: string): Promise<string | null>;
|
|
53
|
+
export type UpdateState = {
|
|
54
|
+
lastCheck?: number;
|
|
55
|
+
lastPromptVersion?: string;
|
|
56
|
+
};
|
|
57
|
+
export type PendingUpdate = {
|
|
58
|
+
installed: string;
|
|
59
|
+
latest: string;
|
|
60
|
+
};
|
|
61
|
+
export type UpdateCheckOptions = {
|
|
62
|
+
/** Absolute path to the aer binary to query for its --version. */
|
|
63
|
+
aerPath: string;
|
|
64
|
+
storageDir?: string;
|
|
65
|
+
log?: LogFn;
|
|
66
|
+
/** Override the rate-limit interval in ms (default 12h). Useful in tests. */
|
|
67
|
+
intervalMs?: number;
|
|
68
|
+
/** When true, ignore the rate-limit and always perform the GitHub query. */
|
|
69
|
+
force?: boolean;
|
|
70
|
+
/** Inject a clock for testing. */
|
|
71
|
+
now?: () => number;
|
|
72
|
+
/** Override the latest-version resolver (for testing). */
|
|
73
|
+
resolveLatest?: () => Promise<string>;
|
|
74
|
+
/** Override the installed-version resolver (for testing). */
|
|
75
|
+
queryInstalled?: (binaryPath: string) => Promise<string | null>;
|
|
76
|
+
};
|
|
77
|
+
/**
|
|
78
|
+
* Begin a background check for a newer aer release. Resolves with details about
|
|
79
|
+
* an available update, or null when no upgrade is needed for any of the following
|
|
80
|
+
* reasons: the rate-limit window hasn't elapsed since the last check, the binary
|
|
81
|
+
* couldn't be queried for its version, the latest tag matches what's installed,
|
|
82
|
+
* the user was already prompted for this version, or the network call failed
|
|
83
|
+
* (logged but not re-thrown).
|
|
84
|
+
*
|
|
85
|
+
* The installed version is read by running `<aerPath> --version` rather than
|
|
86
|
+
* trusting any cached VERSION file — that way the check survives upgrades
|
|
87
|
+
* performed outside the plugin (e.g. by `aer upgrade`) and also works for users
|
|
88
|
+
* who installed aer themselves on PATH.
|
|
89
|
+
*
|
|
90
|
+
* The lastCheck timestamp is persisted as soon as the GitHub query runs, so
|
|
91
|
+
* we don't query repeatedly even if no update is found. The lastPromptVersion
|
|
92
|
+
* is NOT persisted here — callers must invoke `recordPromptedVersion` once
|
|
93
|
+
* they've actually surfaced the prompt to the user.
|
|
94
|
+
*/
|
|
95
|
+
export declare function checkForUpdate(opts: UpdateCheckOptions): Promise<PendingUpdate | null>;
|
|
96
|
+
/**
|
|
97
|
+
* Run the given aer binary with `--version` and parse the reported version.
|
|
98
|
+
* Returns null if the binary doesn't run, doesn't print recognizable output,
|
|
99
|
+
* or takes too long.
|
|
100
|
+
*/
|
|
101
|
+
export declare function queryBinaryVersion(binaryPath: string): Promise<string | null>;
|
|
102
|
+
/**
|
|
103
|
+
* Persist that the user has been prompted about a version, so subsequent
|
|
104
|
+
* commands don't repeat the prompt for that same version.
|
|
105
|
+
*/
|
|
106
|
+
export declare function recordPromptedVersion(version: string, opts?: {
|
|
107
|
+
storageDir?: string;
|
|
108
|
+
}): Promise<void>;
|
|
109
|
+
/** Download and install a specific aer version into the plugin's storage dir. */
|
|
110
|
+
export declare function installAerVersion(version: string, opts?: {
|
|
111
|
+
storageDir?: string;
|
|
112
|
+
log?: LogFn;
|
|
113
|
+
}): Promise<string>;
|
|
114
|
+
export {};
|
package/lib/aerBinary.js
ADDED
|
@@ -0,0 +1,510 @@
|
|
|
1
|
+
import { chmod, mkdir, mkdtemp, readFile, rename, rm, stat, writeFile, access } from 'node:fs/promises';
|
|
2
|
+
import { constants as fsConstants, createWriteStream } from 'node:fs';
|
|
3
|
+
import { spawn } from 'node:child_process';
|
|
4
|
+
import { delimiter, join, resolve } from 'node:path';
|
|
5
|
+
import { homedir, tmpdir } from 'node:os';
|
|
6
|
+
import { get as httpsGet } from 'node:https';
|
|
7
|
+
import AdmZip from 'adm-zip';
|
|
8
|
+
const REPO = 'octoberswimmer/aer-dist';
|
|
9
|
+
const BINARY_NAME = process.platform === 'win32' ? 'aer.exe' : 'aer';
|
|
10
|
+
const VERSION_FILE = 'VERSION';
|
|
11
|
+
const PLUGIN_DIR_NAME = 'aer-sf-plugin';
|
|
12
|
+
const BIN_SUBDIR = 'aer-bin';
|
|
13
|
+
const UPDATE_STATE_FILE = 'update-check.json';
|
|
14
|
+
const UPDATE_CHECK_INTERVAL_MS = 1000 * 60 * 60 * 12; // 12 hours
|
|
15
|
+
let cachedAerPath = null;
|
|
16
|
+
let resolving = null;
|
|
17
|
+
/**
|
|
18
|
+
* Resolve the aer binary path. Resolution order:
|
|
19
|
+
* 1. AER_BIN env var (must be executable).
|
|
20
|
+
* 2. Previously downloaded copy in the plugin's storage dir.
|
|
21
|
+
* 3. `aer` on PATH.
|
|
22
|
+
* 4. Prompt to download the latest release into the plugin's storage dir.
|
|
23
|
+
*/
|
|
24
|
+
export async function ensureAerBinary(opts = {}) {
|
|
25
|
+
if (resolving) {
|
|
26
|
+
return resolving;
|
|
27
|
+
}
|
|
28
|
+
const log = opts.log ?? (() => { });
|
|
29
|
+
const warn = opts.warn ?? (() => { });
|
|
30
|
+
const allowPrompt = opts.allowPrompt ?? true;
|
|
31
|
+
const storageDir = opts.storageDir ?? defaultStorageDir();
|
|
32
|
+
resolving = (async () => {
|
|
33
|
+
const envBin = process.env.AER_BIN;
|
|
34
|
+
if (envBin) {
|
|
35
|
+
const resolved = await resolveExecutable(envBin);
|
|
36
|
+
if (resolved) {
|
|
37
|
+
cachedAerPath = resolved;
|
|
38
|
+
return resolved;
|
|
39
|
+
}
|
|
40
|
+
warn(`AER_BIN is set to "${envBin}" but the file was not found or is not executable; falling back.`);
|
|
41
|
+
}
|
|
42
|
+
const downloaded = join(storageDir, BIN_SUBDIR, BINARY_NAME);
|
|
43
|
+
if (await isExecutable(downloaded)) {
|
|
44
|
+
cachedAerPath = downloaded;
|
|
45
|
+
return downloaded;
|
|
46
|
+
}
|
|
47
|
+
const fromPath = await resolveExecutable('aer');
|
|
48
|
+
if (fromPath) {
|
|
49
|
+
cachedAerPath = fromPath;
|
|
50
|
+
return fromPath;
|
|
51
|
+
}
|
|
52
|
+
if (cachedAerPath && (await isExecutable(cachedAerPath))) {
|
|
53
|
+
return cachedAerPath;
|
|
54
|
+
}
|
|
55
|
+
if (!allowPrompt || !opts.confirm) {
|
|
56
|
+
throw new Error(`Could not find the 'aer' binary. Install aer from https://github.com/${REPO}, set AER_BIN to its absolute path, or rerun interactively to download it automatically.`);
|
|
57
|
+
}
|
|
58
|
+
const yes = await opts.confirm("aer was not found on PATH. Download the latest release from GitHub?");
|
|
59
|
+
if (!yes) {
|
|
60
|
+
throw new Error(`aer is required but was not installed.`);
|
|
61
|
+
}
|
|
62
|
+
const binPath = await downloadLatest(storageDir, log);
|
|
63
|
+
cachedAerPath = binPath;
|
|
64
|
+
return binPath;
|
|
65
|
+
})().finally(() => {
|
|
66
|
+
resolving = null;
|
|
67
|
+
});
|
|
68
|
+
return resolving;
|
|
69
|
+
}
|
|
70
|
+
/** For tests: forget any cached binary path so the next call re-resolves. */
|
|
71
|
+
export function _resetAerBinaryCache() {
|
|
72
|
+
cachedAerPath = null;
|
|
73
|
+
resolving = null;
|
|
74
|
+
}
|
|
75
|
+
/** Module-private internals exposed for tests only. Not part of the public API. */
|
|
76
|
+
export const _internals = {
|
|
77
|
+
get replaceBinary() {
|
|
78
|
+
return replaceBinary;
|
|
79
|
+
},
|
|
80
|
+
};
|
|
81
|
+
/**
|
|
82
|
+
* Default storage directory for binaries downloaded by this plugin. Mirrors the
|
|
83
|
+
* conventions used by `envPaths` / oclif: respects XDG on Linux, Library/Application
|
|
84
|
+
* Support on macOS, and LOCALAPPDATA on Windows.
|
|
85
|
+
*/
|
|
86
|
+
export function defaultStorageDir() {
|
|
87
|
+
const home = homedir();
|
|
88
|
+
switch (process.platform) {
|
|
89
|
+
case 'win32': {
|
|
90
|
+
const base = process.env.LOCALAPPDATA ?? join(home, 'AppData', 'Local');
|
|
91
|
+
return join(base, PLUGIN_DIR_NAME);
|
|
92
|
+
}
|
|
93
|
+
case 'darwin':
|
|
94
|
+
return join(home, 'Library', 'Application Support', PLUGIN_DIR_NAME);
|
|
95
|
+
default: {
|
|
96
|
+
const base = process.env.XDG_DATA_HOME ?? join(home, '.local', 'share');
|
|
97
|
+
return join(base, PLUGIN_DIR_NAME);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
async function downloadLatest(storageDir, log) {
|
|
102
|
+
const version = await resolveLatestVersion();
|
|
103
|
+
log(`Downloading aer ${version}…`);
|
|
104
|
+
return downloadAndExtract(storageDir, version, log);
|
|
105
|
+
}
|
|
106
|
+
async function downloadAndExtract(storageDir, version, log) {
|
|
107
|
+
const { binaryName, archiveName } = platformDetails(version);
|
|
108
|
+
const url = `https://github.com/${REPO}/releases/download/${version}/${archiveName}`;
|
|
109
|
+
const binDir = join(storageDir, BIN_SUBDIR);
|
|
110
|
+
await mkdir(binDir, { recursive: true, mode: 0o755 });
|
|
111
|
+
const tempDir = await mkdtemp(join(tmpdir(), 'aer-download-'));
|
|
112
|
+
const archivePath = join(tempDir, archiveName);
|
|
113
|
+
try {
|
|
114
|
+
log(`Fetching ${url}`);
|
|
115
|
+
await downloadFile(url, archivePath);
|
|
116
|
+
log(`Extracting ${binaryName}…`);
|
|
117
|
+
const data = readBinaryFromArchive(archivePath, binaryName);
|
|
118
|
+
const target = join(binDir, binaryName);
|
|
119
|
+
await replaceBinary(binDir, binaryName, data, target);
|
|
120
|
+
await writeFile(join(binDir, VERSION_FILE), version, 'utf8');
|
|
121
|
+
return target;
|
|
122
|
+
}
|
|
123
|
+
finally {
|
|
124
|
+
await rm(tempDir, { recursive: true, force: true });
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Install a new binary at `target`, using the same atomic-rename strategy as
|
|
129
|
+
* `aer upgrade` so that an in-use executable (notably on Windows) doesn't
|
|
130
|
+
* cause the install to fail.
|
|
131
|
+
*
|
|
132
|
+
* Unix: write to `.{name}.new`, then rename over the target — atomic.
|
|
133
|
+
* Windows: write to `.{name}.new`, rename existing target to `.{name}.old`,
|
|
134
|
+
* rename `.{name}.new` into place, then best-effort delete `.old`
|
|
135
|
+
* (which may stay around briefly if the file is still held open).
|
|
136
|
+
*/
|
|
137
|
+
async function replaceBinary(binDir, binaryName, data, target) {
|
|
138
|
+
const newPath = join(binDir, `.${binaryName}.new`);
|
|
139
|
+
const oldPath = join(binDir, `.${binaryName}.old`);
|
|
140
|
+
await rm(newPath, { force: true });
|
|
141
|
+
await writeFile(newPath, data, { mode: 0o755 });
|
|
142
|
+
if (process.platform !== 'win32') {
|
|
143
|
+
// writeFile honors `mode` only on file creation; chmod explicitly so
|
|
144
|
+
// a leftover `.new` from a prior failed install still ends up +x.
|
|
145
|
+
await chmod(newPath, 0o755);
|
|
146
|
+
}
|
|
147
|
+
if (process.platform === 'win32') {
|
|
148
|
+
await rm(oldPath, { force: true });
|
|
149
|
+
const targetExists = await pathExists(target);
|
|
150
|
+
if (targetExists) {
|
|
151
|
+
try {
|
|
152
|
+
await rename(target, oldPath);
|
|
153
|
+
}
|
|
154
|
+
catch (err) {
|
|
155
|
+
await rm(newPath, { force: true }).catch(() => { });
|
|
156
|
+
throw new Error(`Failed to move current aer executable aside: ${err.message}`);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
try {
|
|
160
|
+
await rename(newPath, target);
|
|
161
|
+
}
|
|
162
|
+
catch (err) {
|
|
163
|
+
if (targetExists) {
|
|
164
|
+
await rename(oldPath, target).catch(() => { });
|
|
165
|
+
}
|
|
166
|
+
throw new Error(`Failed to move new aer executable into place: ${err.message}`);
|
|
167
|
+
}
|
|
168
|
+
// Best-effort cleanup; on Windows this may fail if the binary is
|
|
169
|
+
// still mapped into a running process. The leftover .old file will
|
|
170
|
+
// be removed by the next install.
|
|
171
|
+
await rm(oldPath, { force: true }).catch(() => { });
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
// rename(2) on Unix atomically replaces the target.
|
|
175
|
+
await rename(newPath, target);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
async function pathExists(filePath) {
|
|
179
|
+
try {
|
|
180
|
+
await stat(filePath);
|
|
181
|
+
return true;
|
|
182
|
+
}
|
|
183
|
+
catch {
|
|
184
|
+
return false;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
export function platformDetails(version) {
|
|
188
|
+
const platformKey = normalizeOS();
|
|
189
|
+
const cpuKey = normalizeArch();
|
|
190
|
+
const binaryName = platformKey === 'windows' ? 'aer.exe' : 'aer';
|
|
191
|
+
const archiveName = `aer_${platformKey}_${cpuKey}_${version}.zip`;
|
|
192
|
+
return { platformKey, cpuKey, binaryName, archiveName };
|
|
193
|
+
}
|
|
194
|
+
function normalizeOS() {
|
|
195
|
+
switch (process.platform) {
|
|
196
|
+
case 'linux':
|
|
197
|
+
return 'linux';
|
|
198
|
+
case 'darwin':
|
|
199
|
+
return 'darwin';
|
|
200
|
+
case 'win32':
|
|
201
|
+
return 'windows';
|
|
202
|
+
default:
|
|
203
|
+
throw new Error(`Unsupported operating system: ${process.platform}`);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
function normalizeArch() {
|
|
207
|
+
switch (process.arch) {
|
|
208
|
+
case 'x64':
|
|
209
|
+
return 'amd64';
|
|
210
|
+
case 'arm64':
|
|
211
|
+
return 'arm64';
|
|
212
|
+
default:
|
|
213
|
+
throw new Error(`Unsupported architecture: ${process.arch}`);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
export async function readStoredVersion(storageDir) {
|
|
217
|
+
try {
|
|
218
|
+
const contents = await readFile(join(storageDir, BIN_SUBDIR, VERSION_FILE), 'utf8');
|
|
219
|
+
return contents.trim() || null;
|
|
220
|
+
}
|
|
221
|
+
catch {
|
|
222
|
+
return null;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Begin a background check for a newer aer release. Resolves with details about
|
|
227
|
+
* an available update, or null when no upgrade is needed for any of the following
|
|
228
|
+
* reasons: the rate-limit window hasn't elapsed since the last check, the binary
|
|
229
|
+
* couldn't be queried for its version, the latest tag matches what's installed,
|
|
230
|
+
* the user was already prompted for this version, or the network call failed
|
|
231
|
+
* (logged but not re-thrown).
|
|
232
|
+
*
|
|
233
|
+
* The installed version is read by running `<aerPath> --version` rather than
|
|
234
|
+
* trusting any cached VERSION file — that way the check survives upgrades
|
|
235
|
+
* performed outside the plugin (e.g. by `aer upgrade`) and also works for users
|
|
236
|
+
* who installed aer themselves on PATH.
|
|
237
|
+
*
|
|
238
|
+
* The lastCheck timestamp is persisted as soon as the GitHub query runs, so
|
|
239
|
+
* we don't query repeatedly even if no update is found. The lastPromptVersion
|
|
240
|
+
* is NOT persisted here — callers must invoke `recordPromptedVersion` once
|
|
241
|
+
* they've actually surfaced the prompt to the user.
|
|
242
|
+
*/
|
|
243
|
+
export async function checkForUpdate(opts) {
|
|
244
|
+
const storageDir = opts.storageDir ?? defaultStorageDir();
|
|
245
|
+
const log = opts.log ?? (() => { });
|
|
246
|
+
const intervalMs = opts.intervalMs ?? UPDATE_CHECK_INTERVAL_MS;
|
|
247
|
+
const now = opts.now?.() ?? Date.now();
|
|
248
|
+
const state = await readUpdateState(storageDir);
|
|
249
|
+
if (!opts.force && state.lastCheck && now - state.lastCheck < intervalMs) {
|
|
250
|
+
return null;
|
|
251
|
+
}
|
|
252
|
+
const queryFn = opts.queryInstalled ?? queryBinaryVersion;
|
|
253
|
+
const installed = await queryFn(opts.aerPath);
|
|
254
|
+
if (!installed) {
|
|
255
|
+
log(`aer update check skipped: could not determine installed version from ${opts.aerPath}`);
|
|
256
|
+
return null;
|
|
257
|
+
}
|
|
258
|
+
const resolver = opts.resolveLatest ?? resolveLatestVersion;
|
|
259
|
+
let latest;
|
|
260
|
+
try {
|
|
261
|
+
latest = await resolver();
|
|
262
|
+
}
|
|
263
|
+
catch (err) {
|
|
264
|
+
log(`aer update check failed: ${err.message}`);
|
|
265
|
+
return null;
|
|
266
|
+
}
|
|
267
|
+
await writeUpdateState(storageDir, { ...state, lastCheck: now });
|
|
268
|
+
if (!latest || normalizeVersion(latest) === normalizeVersion(installed)) {
|
|
269
|
+
return null;
|
|
270
|
+
}
|
|
271
|
+
if (state.lastPromptVersion && normalizeVersion(state.lastPromptVersion) === normalizeVersion(latest)) {
|
|
272
|
+
return null;
|
|
273
|
+
}
|
|
274
|
+
return { installed, latest };
|
|
275
|
+
}
|
|
276
|
+
function normalizeVersion(v) {
|
|
277
|
+
const trimmed = v.trim();
|
|
278
|
+
return trimmed.startsWith('v') ? trimmed.slice(1) : trimmed;
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Run the given aer binary with `--version` and parse the reported version.
|
|
282
|
+
* Returns null if the binary doesn't run, doesn't print recognizable output,
|
|
283
|
+
* or takes too long.
|
|
284
|
+
*/
|
|
285
|
+
export async function queryBinaryVersion(binaryPath) {
|
|
286
|
+
return new Promise((resolvePromise) => {
|
|
287
|
+
let stdout = '';
|
|
288
|
+
let stderr = '';
|
|
289
|
+
let settled = false;
|
|
290
|
+
const finish = (result) => {
|
|
291
|
+
if (settled)
|
|
292
|
+
return;
|
|
293
|
+
settled = true;
|
|
294
|
+
resolvePromise(result);
|
|
295
|
+
};
|
|
296
|
+
let child;
|
|
297
|
+
try {
|
|
298
|
+
child = spawn(binaryPath, ['--version'], {
|
|
299
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
300
|
+
env: { ...process.env, AER_AUTOUPDATE_DISABLED: '1' },
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
catch {
|
|
304
|
+
finish(null);
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
307
|
+
const timer = setTimeout(() => {
|
|
308
|
+
child.kill();
|
|
309
|
+
finish(null);
|
|
310
|
+
}, 5000);
|
|
311
|
+
child.stdout?.on('data', (chunk) => {
|
|
312
|
+
stdout += chunk.toString();
|
|
313
|
+
});
|
|
314
|
+
child.stderr?.on('data', (chunk) => {
|
|
315
|
+
stderr += chunk.toString();
|
|
316
|
+
});
|
|
317
|
+
child.on('error', () => {
|
|
318
|
+
clearTimeout(timer);
|
|
319
|
+
finish(null);
|
|
320
|
+
});
|
|
321
|
+
child.on('exit', (code) => {
|
|
322
|
+
clearTimeout(timer);
|
|
323
|
+
if (code !== 0) {
|
|
324
|
+
finish(null);
|
|
325
|
+
return;
|
|
326
|
+
}
|
|
327
|
+
const output = stdout || stderr;
|
|
328
|
+
// Match strings like "v1.0.0-beta.5" or "1.0.0".
|
|
329
|
+
const match = output.match(/v?\d+\.\d+\.\d+(?:[\w.-]+)?/);
|
|
330
|
+
if (!match) {
|
|
331
|
+
finish(null);
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
334
|
+
const raw = match[0];
|
|
335
|
+
finish(raw.startsWith('v') ? raw : `v${raw}`);
|
|
336
|
+
});
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
/**
|
|
340
|
+
* Persist that the user has been prompted about a version, so subsequent
|
|
341
|
+
* commands don't repeat the prompt for that same version.
|
|
342
|
+
*/
|
|
343
|
+
export async function recordPromptedVersion(version, opts = {}) {
|
|
344
|
+
const storageDir = opts.storageDir ?? defaultStorageDir();
|
|
345
|
+
const state = await readUpdateState(storageDir);
|
|
346
|
+
await writeUpdateState(storageDir, { ...state, lastPromptVersion: version });
|
|
347
|
+
}
|
|
348
|
+
/** Download and install a specific aer version into the plugin's storage dir. */
|
|
349
|
+
export async function installAerVersion(version, opts = {}) {
|
|
350
|
+
const storageDir = opts.storageDir ?? defaultStorageDir();
|
|
351
|
+
const log = opts.log ?? (() => { });
|
|
352
|
+
const newPath = await downloadAndExtract(storageDir, version, log);
|
|
353
|
+
cachedAerPath = newPath;
|
|
354
|
+
return newPath;
|
|
355
|
+
}
|
|
356
|
+
async function readUpdateState(storageDir) {
|
|
357
|
+
try {
|
|
358
|
+
const contents = await readFile(join(storageDir, UPDATE_STATE_FILE), 'utf8');
|
|
359
|
+
const parsed = JSON.parse(contents);
|
|
360
|
+
if (parsed && typeof parsed === 'object') {
|
|
361
|
+
return parsed;
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
catch {
|
|
365
|
+
// Missing or corrupt state — treat as empty.
|
|
366
|
+
}
|
|
367
|
+
return {};
|
|
368
|
+
}
|
|
369
|
+
async function writeUpdateState(storageDir, state) {
|
|
370
|
+
await mkdir(storageDir, { recursive: true });
|
|
371
|
+
await writeFile(join(storageDir, UPDATE_STATE_FILE), JSON.stringify(state), 'utf8');
|
|
372
|
+
}
|
|
373
|
+
async function resolveLatestVersion() {
|
|
374
|
+
const latest = await requestJson(`https://api.github.com/repos/${REPO}/releases/latest`);
|
|
375
|
+
if (latest.statusCode === 404) {
|
|
376
|
+
return latestFromList();
|
|
377
|
+
}
|
|
378
|
+
if (latest.statusCode >= 400) {
|
|
379
|
+
throw new Error(`GitHub API returned ${latest.statusCode} while resolving latest aer release.`);
|
|
380
|
+
}
|
|
381
|
+
const tag = latest.body?.tag_name;
|
|
382
|
+
if (!tag) {
|
|
383
|
+
throw new Error('Latest aer release response is missing tag_name.');
|
|
384
|
+
}
|
|
385
|
+
return String(tag);
|
|
386
|
+
}
|
|
387
|
+
async function latestFromList() {
|
|
388
|
+
const res = await requestJson(`https://api.github.com/repos/${REPO}/releases?per_page=10`);
|
|
389
|
+
if (res.statusCode >= 400) {
|
|
390
|
+
throw new Error(`GitHub API returned ${res.statusCode} while listing aer releases.`);
|
|
391
|
+
}
|
|
392
|
+
if (!Array.isArray(res.body)) {
|
|
393
|
+
throw new Error('Unexpected response while listing aer releases.');
|
|
394
|
+
}
|
|
395
|
+
for (const rel of res.body) {
|
|
396
|
+
if (!rel?.draft && rel?.tag_name) {
|
|
397
|
+
return String(rel.tag_name);
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
throw new Error('No published aer releases were found.');
|
|
401
|
+
}
|
|
402
|
+
async function resolveExecutable(cmd) {
|
|
403
|
+
if (cmd.includes('/') || cmd.includes('\\')) {
|
|
404
|
+
const candidate = resolve(cmd);
|
|
405
|
+
return (await isExecutable(candidate)) ? candidate : null;
|
|
406
|
+
}
|
|
407
|
+
const pathVar = process.env.PATH ?? '';
|
|
408
|
+
const extensions = process.platform === 'win32' ? ['.exe', '.cmd', '.bat', ''] : [''];
|
|
409
|
+
for (const segment of pathVar.split(delimiter)) {
|
|
410
|
+
if (!segment)
|
|
411
|
+
continue;
|
|
412
|
+
for (const ext of extensions) {
|
|
413
|
+
const candidate = join(segment, cmd + ext);
|
|
414
|
+
if (await isExecutable(candidate)) {
|
|
415
|
+
return candidate;
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
return null;
|
|
420
|
+
}
|
|
421
|
+
async function isExecutable(filePath) {
|
|
422
|
+
try {
|
|
423
|
+
const stats = await stat(filePath);
|
|
424
|
+
if (!stats.isFile())
|
|
425
|
+
return false;
|
|
426
|
+
if (process.platform === 'win32')
|
|
427
|
+
return true;
|
|
428
|
+
await access(filePath, fsConstants.X_OK);
|
|
429
|
+
return true;
|
|
430
|
+
}
|
|
431
|
+
catch {
|
|
432
|
+
return false;
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
function readBinaryFromArchive(archivePath, binaryName) {
|
|
436
|
+
const zip = new AdmZip(archivePath);
|
|
437
|
+
const entry = zip
|
|
438
|
+
.getEntries()
|
|
439
|
+
.find((e) => !e.isDirectory && e.entryName.replace(/\/$/, '').endsWith(binaryName));
|
|
440
|
+
if (!entry) {
|
|
441
|
+
throw new Error(`${binaryName} was not found inside the downloaded archive.`);
|
|
442
|
+
}
|
|
443
|
+
return entry.getData();
|
|
444
|
+
}
|
|
445
|
+
async function requestJson(url) {
|
|
446
|
+
const res = await httpRequest(url);
|
|
447
|
+
try {
|
|
448
|
+
return { statusCode: res.statusCode, body: JSON.parse(res.text) };
|
|
449
|
+
}
|
|
450
|
+
catch {
|
|
451
|
+
return { statusCode: res.statusCode, body: null };
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
async function downloadFile(url, dest) {
|
|
455
|
+
return new Promise((resolvePromise, rejectPromise) => {
|
|
456
|
+
const file = createWriteStream(dest);
|
|
457
|
+
const handle = (currentUrl, redirects) => {
|
|
458
|
+
const req = httpsGet(currentUrl, { headers: requestHeaders() }, (res) => {
|
|
459
|
+
if (res.statusCode && res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
|
460
|
+
if (redirects > 5) {
|
|
461
|
+
rejectPromise(new Error('Too many redirects while downloading aer.'));
|
|
462
|
+
return;
|
|
463
|
+
}
|
|
464
|
+
res.resume();
|
|
465
|
+
req.destroy();
|
|
466
|
+
handle(res.headers.location, redirects + 1);
|
|
467
|
+
return;
|
|
468
|
+
}
|
|
469
|
+
if (!res.statusCode || res.statusCode >= 400) {
|
|
470
|
+
file.close();
|
|
471
|
+
rejectPromise(new Error(`Failed to download aer (HTTP ${res.statusCode ?? 'unknown'}).`));
|
|
472
|
+
return;
|
|
473
|
+
}
|
|
474
|
+
res.pipe(file);
|
|
475
|
+
res.on('error', (err) => {
|
|
476
|
+
file.close();
|
|
477
|
+
rejectPromise(err);
|
|
478
|
+
});
|
|
479
|
+
file.on('finish', () => file.close((err) => (err ? rejectPromise(err) : resolvePromise())));
|
|
480
|
+
file.on('error', rejectPromise);
|
|
481
|
+
});
|
|
482
|
+
req.on('error', (err) => {
|
|
483
|
+
file.close();
|
|
484
|
+
rejectPromise(err);
|
|
485
|
+
});
|
|
486
|
+
};
|
|
487
|
+
handle(url, 0);
|
|
488
|
+
});
|
|
489
|
+
}
|
|
490
|
+
async function httpRequest(url) {
|
|
491
|
+
return new Promise((resolvePromise, rejectPromise) => {
|
|
492
|
+
const req = httpsGet(url, { headers: requestHeaders() }, (res) => {
|
|
493
|
+
let data = '';
|
|
494
|
+
res.on('data', (chunk) => {
|
|
495
|
+
data += chunk;
|
|
496
|
+
});
|
|
497
|
+
res.on('end', () => {
|
|
498
|
+
resolvePromise({ statusCode: res.statusCode ?? 0, text: data });
|
|
499
|
+
});
|
|
500
|
+
});
|
|
501
|
+
req.on('error', rejectPromise);
|
|
502
|
+
});
|
|
503
|
+
}
|
|
504
|
+
function requestHeaders() {
|
|
505
|
+
return {
|
|
506
|
+
'User-Agent': '@octoberswimmer/aer-sf-plugin',
|
|
507
|
+
Accept: 'application/vnd.github+json',
|
|
508
|
+
};
|
|
509
|
+
}
|
|
510
|
+
//# sourceMappingURL=aerBinary.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aerBinary.js","sourceRoot":"","sources":["../src/aerBinary.ts"],"names":[],"mappings":"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"}
|
|
@@ -27,5 +27,6 @@ export default class AerApexRunTest extends SfCommand<AerApexRunTestResult> {
|
|
|
27
27
|
'api-version': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
28
28
|
};
|
|
29
29
|
run(): Promise<AerApexRunTestResult>;
|
|
30
|
+
private maybePromptForUpdate;
|
|
30
31
|
}
|
|
31
32
|
export {};
|
|
@@ -4,6 +4,7 @@ import { SfCommand, Flags } from '@salesforce/sf-plugins-core';
|
|
|
4
4
|
import { Messages, SfProject } from '@salesforce/core';
|
|
5
5
|
import { stageSource } from '../../../../staging.js';
|
|
6
6
|
import { buildAerArgs, runAer } from '../../../../aer.js';
|
|
7
|
+
import { checkForUpdate, ensureAerBinary, installAerVersion, recordPromptedVersion, } from '../../../../aerBinary.js';
|
|
7
8
|
Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
|
|
8
9
|
const messages = Messages.loadMessages('@octoberswimmer/aer-sf-plugin', 'aer.apex.run.test');
|
|
9
10
|
export default class AerApexRunTest extends SfCommand {
|
|
@@ -113,6 +114,20 @@ export default class AerApexRunTest extends SfCommand {
|
|
|
113
114
|
if (ignoredFlags.length > 0) {
|
|
114
115
|
this.warn(messages.getMessage('warn.ignoredFlags', [ignoredFlags.join(', ')]));
|
|
115
116
|
}
|
|
117
|
+
const interactive = !this.jsonEnabled() && Boolean(process.stdin.isTTY);
|
|
118
|
+
const aerPath = await ensureAerBinary({
|
|
119
|
+
allowPrompt: interactive,
|
|
120
|
+
// Long timeout so a user with the prompt buried in scrollback still has
|
|
121
|
+
// time to react; default-no keeps CI/headless runs safe.
|
|
122
|
+
confirm: (message) => this.confirm({ message, ms: 5 * 60 * 1000, defaultAnswer: false }),
|
|
123
|
+
log: (m) => this.log(m),
|
|
124
|
+
warn: (m) => this.warn(m),
|
|
125
|
+
});
|
|
126
|
+
// Kick off the update check in parallel with staging and the test run.
|
|
127
|
+
// Errors are swallowed — we never want this to fail the command.
|
|
128
|
+
const updateCheck = interactive
|
|
129
|
+
? checkForUpdate({ aerPath, log: (m) => this.log(m) }).catch(() => null)
|
|
130
|
+
: Promise.resolve(null);
|
|
116
131
|
const staged = await stageSource({
|
|
117
132
|
projectRoot,
|
|
118
133
|
packageDirectories,
|
|
@@ -148,7 +163,7 @@ export default class AerApexRunTest extends SfCommand {
|
|
|
148
163
|
});
|
|
149
164
|
let exitCode = 0;
|
|
150
165
|
try {
|
|
151
|
-
exitCode = await runAer(args, projectRoot);
|
|
166
|
+
exitCode = await runAer(aerPath, args, projectRoot);
|
|
152
167
|
}
|
|
153
168
|
finally {
|
|
154
169
|
await staged.cleanup();
|
|
@@ -156,12 +171,44 @@ export default class AerApexRunTest extends SfCommand {
|
|
|
156
171
|
if (exitCode !== 0 && !this.jsonEnabled()) {
|
|
157
172
|
this.warn(messages.getMessage('warn.aerExit', [String(exitCode)]));
|
|
158
173
|
}
|
|
174
|
+
await this.maybePromptForUpdate(updateCheck);
|
|
159
175
|
return {
|
|
160
176
|
stagedDir: staged.dir,
|
|
161
177
|
filters,
|
|
162
178
|
exitCode,
|
|
163
179
|
};
|
|
164
180
|
}
|
|
181
|
+
async maybePromptForUpdate(check) {
|
|
182
|
+
let update;
|
|
183
|
+
try {
|
|
184
|
+
update = await check;
|
|
185
|
+
}
|
|
186
|
+
catch {
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
if (!update)
|
|
190
|
+
return;
|
|
191
|
+
this.log('');
|
|
192
|
+
const yes = await this.confirm({
|
|
193
|
+
message: messages.getMessage('prompt.updateAvailable', [update.installed, update.latest]),
|
|
194
|
+
ms: 5 * 60 * 1000,
|
|
195
|
+
defaultAnswer: false,
|
|
196
|
+
});
|
|
197
|
+
if (!yes) {
|
|
198
|
+
// Record only after the user has been asked and declined, so a
|
|
199
|
+
// failed prompt doesn't accidentally suppress future ones.
|
|
200
|
+
await recordPromptedVersion(update.latest).catch(() => { });
|
|
201
|
+
this.log(messages.getMessage('info.updateDeferred'));
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
try {
|
|
205
|
+
const newPath = await installAerVersion(update.latest, { log: (m) => this.log(m) });
|
|
206
|
+
this.log(messages.getMessage('info.updateInstalled', [update.latest, newPath]));
|
|
207
|
+
}
|
|
208
|
+
catch (err) {
|
|
209
|
+
this.warn(messages.getMessage('warn.updateFailed', [err.message]));
|
|
210
|
+
}
|
|
211
|
+
}
|
|
165
212
|
}
|
|
166
213
|
function buildFilters(classNames, tests) {
|
|
167
214
|
const out = [];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"test.js","sourceRoot":"","sources":["../../../../../src/commands/aer/apex/run/test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACzC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,WAAW,EAA2C,MAAM,wBAAwB,CAAC;AAC9F,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"test.js","sourceRoot":"","sources":["../../../../../src/commands/aer/apex/run/test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACzC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,WAAW,EAA2C,MAAM,wBAAwB,CAAC;AAC9F,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EACN,cAAc,EACd,eAAe,EACf,iBAAiB,EACjB,qBAAqB,GAErB,MAAM,0BAA0B,CAAC;AAElC,QAAQ,CAAC,kCAAkC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC7D,MAAM,QAAQ,GAAG,QAAQ,CAAC,YAAY,CAAC,+BAA+B,EAAE,mBAAmB,CAAC,CAAC;AAgB7F,MAAM,CAAC,OAAO,OAAO,cAAe,SAAQ,SAA+B;IACnE,MAAM,CAAU,OAAO,GAAG,QAAQ,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;IACzD,MAAM,CAAU,WAAW,GAAG,QAAQ,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;IACjE,MAAM,CAAU,QAAQ,GAAG,QAAQ,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;IAE5D,MAAM,CAAU,KAAK,GAAG;QAC9B,YAAY,EAAE,KAAK,CAAC,MAAM,CAAC;YAC1B,IAAI,EAAE,GAAG;YACT,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,0BAA0B,CAAC;YACxD,WAAW,EAAE,QAAQ,CAAC,UAAU,CAAC,8BAA8B,CAAC;SAChE,CAAC;QACF,YAAY,EAAE,KAAK,CAAC,MAAM,CAAY;YACrC,OAAO,EAAE,CAAC,eAAe,EAAE,kBAAkB,EAAE,mBAAmB,CAAC;SACnE,CAAC,CAAC;YACF,IAAI,EAAE,GAAG;YACT,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,0BAA0B,CAAC;SACxD,CAAC;QACF,aAAa,EAAE,KAAK,CAAC,MAAM,CAAC;YAC3B,IAAI,EAAE,GAAG;YACT,QAAQ,EAAE,IAAI;YACd,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,2BAA2B,CAAC;SACzD,CAAC;QACF,aAAa,EAAE,KAAK,CAAC,MAAM,CAAC;YAC3B,IAAI,EAAE,GAAG;YACT,QAAQ,EAAE,IAAI;YACd,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,2BAA2B,CAAC;SACzD,CAAC;QACF,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC;YACnB,IAAI,EAAE,GAAG;YACT,QAAQ,EAAE,IAAI;YACd,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,qBAAqB,CAAC;SACnD,CAAC;QACF,eAAe,EAAE,KAAK,CAAC,MAAM,CAAe;YAC3C,OAAO,EAAE,CAAC,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC;SAC1C,CAAC,CAAC;YACF,IAAI,EAAE,GAAG;YACT,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,6BAA6B,CAAC;YAC3D,OAAO,EAAE,OAAO;SAChB,CAAC;QACF,YAAY,EAAE,KAAK,CAAC,SAAS,CAAC;YAC7B,IAAI,EAAE,GAAG;YACT,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,0BAA0B,CAAC;SACxD,CAAC;QACF,eAAe,EAAE,KAAK,CAAC,OAAO,CAAC;YAC9B,IAAI,EAAE,GAAG;YACT,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,6BAA6B,CAAC;SAC3D,CAAC;QACF,mBAAmB,EAAE,KAAK,CAAC,OAAO,CAAC;YAClC,IAAI,EAAE,GAAG;YACT,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,iCAAiC,CAAC;YAC/D,SAAS,EAAE,CAAC,eAAe,CAAC;SAC5B,CAAC;QACF,WAAW,EAAE,KAAK,CAAC,OAAO,CAAC;YAC1B,IAAI,EAAE,GAAG;YACT,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,2BAA2B,CAAC;SACzD,CAAC;QACF,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC;YACnB,IAAI,EAAE,GAAG;YACT,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,oBAAoB,CAAC;SAClD,CAAC;QACF,eAAe,EAAE,KAAK,CAAC,OAAO,CAAC;YAC9B,IAAI,EAAE,GAAG;YACT,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,6BAA6B,CAAC;SAC3D,CAAC;QACF,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC;YACtB,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,uBAAuB,CAAC;SACrD,CAAC;QACF,aAAa,EAAE,KAAK,CAAC,MAAM,CAAC;YAC3B,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,2BAA2B,CAAC;SACzD,CAAC;KACF,CAAC;IAEK,KAAK,CAAC,GAAG;QACf,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;QAEnD,MAAM,OAAO,GAAG,MAAM,SAAS,CAAC,OAAO,EAAE,CAAC;QAC1C,MAAM,WAAW,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;QACtC,MAAM,QAAQ,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,WAAW,EAAsC,CAAC;QAC9F,MAAM,kBAAkB,GAAG,QAAQ,CAAC,kBAAkB,IAAI,EAAE,CAAC;QAC7D,IAAI,kBAAkB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACrC,MAAM,QAAQ,CAAC,WAAW,CAAC,4BAA4B,CAAC,CAAC;QAC1D,CAAC;QAED,MAAM,OAAO,GAAG,YAAY,CAAC,KAAK,CAAC,aAAa,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;QAEhE,MAAM,SAAS,GAAG,KAAK,CAAC,YAAY,CAAC,CAAC;QACtC,IAAI,SAAS,KAAK,kBAAkB,EAAE,CAAC;YACtC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,gCAAgC,CAAC,CAAC,CAAC;QAClE,CAAC;QAED,IAAI,KAAK,CAAC,aAAa,CAAC,IAAI,KAAK,CAAC,aAAa,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC7D,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,4BAA4B,CAAC,CAAC,CAAC;QAC9D,CAAC;QAED,MAAM,YAAY,GAAa,EAAE,CAAC;QAClC,IAAI,KAAK,CAAC,YAAY,CAAC;YAAE,YAAY,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAC3D,IAAI,KAAK,CAAC,WAAW;YAAE,YAAY,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QAC1D,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS;YAAE,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC1D,IAAI,KAAK,CAAC,eAAe,CAAC,KAAK,SAAS;YAAE,YAAY,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;QAC/E,IAAI,KAAK,CAAC,aAAa,CAAC;YAAE,YAAY,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QAC7D,IAAI,KAAK,CAAC,mBAAmB,CAAC;YAAE,YAAY,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;QACzE,IAAI,KAAK,CAAC,OAAO;YAAE,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAClD,IAAI,KAAK,CAAC,eAAe,CAAC,KAAK,KAAK;YAAE,YAAY,CAAC,IAAI,CAAC,2CAA2C,CAAC,CAAC;QACrG,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC7B,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,mBAAmB,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QAChF,CAAC;QAED,MAAM,WAAW,GAAG,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAExE,MAAM,OAAO,GAAG,MAAM,eAAe,CAAC;YACrC,WAAW,EAAE,WAAW;YACxB,wEAAwE;YACxE,yDAAyD;YACzD,OAAO,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,CAAC;YACxF,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;YACvB,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;SACzB,CAAC,CAAC;QAEH,uEAAuE;QACvE,iEAAiE;QACjE,MAAM,WAAW,GAAkC,WAAW;YAC7D,CAAC,CAAC,cAAc,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC;YACxE,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAEzB,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC;YAChC,WAAW;YACX,kBAAkB;YAClB,YAAY,EAAE,QAAQ,CAAC,YAAY;SACnC,CAAC,CAAC;QAEH,IAAI,UAA8B,CAAC;QACnC,IAAI,YAAgC,CAAC;QACrC,MAAM,eAAe,GACpB,KAAK,CAAC,eAAe,CAAC,KAAK,OAAO;YACjC,CAAC,CAAC,OAAO;YACT,CAAC,CAAC,KAAK,CAAC,eAAe,CAAC,KAAK,MAAM;gBAClC,CAAC,CAAC,MAAM;gBACR,CAAC,CAAC,OAAO,CAAC;QACb,IAAI,KAAK,CAAC,YAAY,CAAC,EAAE,CAAC;YACzB,MAAM,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC;YACzD,MAAM,KAAK,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YACzC,IAAI,eAAe,KAAK,OAAO,EAAE,CAAC;gBACjC,UAAU,GAAG,IAAI,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;YAC9C,CAAC;iBAAM,IAAI,eAAe,KAAK,MAAM,EAAE,CAAC;gBACvC,UAAU,GAAG,IAAI,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;YAC/C,CAAC;YACD,IAAI,KAAK,CAAC,eAAe,CAAC,EAAE,CAAC;gBAC5B,YAAY,GAAG,IAAI,CAAC,MAAM,EAAE,+BAA+B,CAAC,CAAC;YAC9D,CAAC;QACF,CAAC;QAED,MAAM,IAAI,GAAG,YAAY,CAAC;YACzB,SAAS,EAAE,MAAM,CAAC,GAAG;YACrB,OAAO;YACP,YAAY,EAAE,eAAe;YAC7B,UAAU;YACV,YAAY;YACZ,OAAO,EAAE,KAAK,CAAC,mBAAmB,CAAC,IAAI,KAAK;SAC5C,CAAC,CAAC;QAEH,IAAI,QAAQ,GAAG,CAAC,CAAC;QACjB,IAAI,CAAC;YACJ,QAAQ,GAAG,MAAM,MAAM,CAAC,OAAO,EAAE,IAAI,EAAE,WAAW,CAAC,CAAC;QACrD,CAAC;gBAAS,CAAC;YACV,MAAM,MAAM,CAAC,OAAO,EAAE,CAAC;QACxB,CAAC;QAED,IAAI,QAAQ,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;YAC3C,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,cAAc,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;QACpE,CAAC;QAED,MAAM,IAAI,CAAC,oBAAoB,CAAC,WAAW,CAAC,CAAC;QAE7C,OAAO;YACN,SAAS,EAAE,MAAM,CAAC,GAAG;YACrB,OAAO;YACP,QAAQ;SACR,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,oBAAoB,CAAC,KAAoC;QACtE,IAAI,MAA4B,CAAC;QACjC,IAAI,CAAC;YACJ,MAAM,GAAG,MAAM,KAAK,CAAC;QACtB,CAAC;QAAC,MAAM,CAAC;YACR,OAAO;QACR,CAAC;QACD,IAAI,CAAC,MAAM;YAAE,OAAO;QAEpB,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACb,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC;YAC9B,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,wBAAwB,EAAE,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;YACzF,EAAE,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI;YACjB,aAAa,EAAE,KAAK;SACpB,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,EAAE,CAAC;YACV,+DAA+D;YAC/D,2DAA2D;YAC3D,MAAM,qBAAqB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;YAC3D,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC,qBAAqB,CAAC,CAAC,CAAC;YACrD,OAAO;QACR,CAAC;QAED,IAAI,CAAC;YACJ,MAAM,OAAO,GAAG,MAAM,iBAAiB,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACpF,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC,sBAAsB,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;QACjF,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACd,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,mBAAmB,EAAE,CAAE,GAAa,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QAC/E,CAAC;IACF,CAAC;;AAGF,SAAS,YAAY,CAAC,UAAgC,EAAE,KAA2B;IAClF,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,KAAK,MAAM,EAAE,IAAI,UAAU,IAAI,EAAE,EAAE,CAAC;QACnC,wFAAwF;QACxF,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IACrB,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,KAAK,IAAI,EAAE,EAAE,CAAC;QAC7B,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACb,CAAC;IACD,OAAO,GAAG,CAAC;AACZ,CAAC"}
|
|
@@ -13,7 +13,12 @@ Source is staged into a temporary directory before invoking aer. The staging ste
|
|
|
13
13
|
1. When the same Apex class name appears in more than one packageDirectories entry, the copy whose full path sorts alphabetically last wins.
|
|
14
14
|
2. The `replacements` configuration in sfdx-project.json (stringToReplace / regexToReplace + replaceWithFile / replaceWithEnv) is applied to file contents during staging.
|
|
15
15
|
|
|
16
|
-
The `aer` binary (https://github.com/octoberswimmer/aer-dist)
|
|
16
|
+
The `aer` binary (https://github.com/octoberswimmer/aer-dist) is resolved in the following order:
|
|
17
|
+
|
|
18
|
+
1. The `AER_BIN` environment variable, when set to an executable file.
|
|
19
|
+
2. A copy previously downloaded by this plugin (stored under a platform-specific data directory, e.g. `~/.local/share/aer-sf-plugin/aer-bin/`).
|
|
20
|
+
3. `aer` discovered on `PATH`.
|
|
21
|
+
4. If none of the above match and the terminal is interactive, you'll be prompted to download the latest release for your platform from GitHub; the binary is then stored in the plugin's data directory and used for subsequent runs.
|
|
17
22
|
|
|
18
23
|
# examples
|
|
19
24
|
|
|
@@ -116,3 +121,19 @@ aer exited with non-zero status %s.
|
|
|
116
121
|
# error.noPackageDirectories
|
|
117
122
|
|
|
118
123
|
sfdx-project.json must contain at least one packageDirectories entry.
|
|
124
|
+
|
|
125
|
+
# prompt.updateAvailable
|
|
126
|
+
|
|
127
|
+
A newer aer release is available (installed: %s, latest: %s). Update now?
|
|
128
|
+
|
|
129
|
+
# info.updateDeferred
|
|
130
|
+
|
|
131
|
+
Skipping aer update. You'll be prompted again the next time a new release is published.
|
|
132
|
+
|
|
133
|
+
# info.updateInstalled
|
|
134
|
+
|
|
135
|
+
Installed aer %s to %s. The new version will be used on the next run.
|
|
136
|
+
|
|
137
|
+
# warn.updateFailed
|
|
138
|
+
|
|
139
|
+
Failed to update aer: %s
|
package/oclif.manifest.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"aer:apex:run:test": {
|
|
4
4
|
"aliases": [],
|
|
5
5
|
"args": {},
|
|
6
|
-
"description": "Run Apex tests against a local sandbox using aer instead of submitting them to a Salesforce org.\n\nThis command accepts the same flags as `sf apex run test` so it can be used as a drop-in replacement, but flags that only make sense when running against a real org (--target-org, --wait, --poll-interval, --synchronous, --api-version) are accepted for compatibility and otherwise ignored.\n\nSource is staged into a temporary directory before invoking aer. The staging step reproduces two behaviors of `sf project deploy start` that aer does not implement natively:\n\n1. When the same Apex class name appears in more than one packageDirectories entry, the copy whose full path sorts alphabetically last wins.\n2. The `replacements` configuration in sfdx-project.json (stringToReplace / regexToReplace + replaceWithFile / replaceWithEnv) is applied to file contents during staging.\n\nThe `aer` binary (https://github.com/octoberswimmer/aer-dist)
|
|
6
|
+
"description": "Run Apex tests against a local sandbox using aer instead of submitting them to a Salesforce org.\n\nThis command accepts the same flags as `sf apex run test` so it can be used as a drop-in replacement, but flags that only make sense when running against a real org (--target-org, --wait, --poll-interval, --synchronous, --api-version) are accepted for compatibility and otherwise ignored.\n\nSource is staged into a temporary directory before invoking aer. The staging step reproduces two behaviors of `sf project deploy start` that aer does not implement natively:\n\n1. When the same Apex class name appears in more than one packageDirectories entry, the copy whose full path sorts alphabetically last wins.\n2. The `replacements` configuration in sfdx-project.json (stringToReplace / regexToReplace + replaceWithFile / replaceWithEnv) is applied to file contents during staging.\n\nThe `aer` binary (https://github.com/octoberswimmer/aer-dist) is resolved in the following order:\n\n1. The `AER_BIN` environment variable, when set to an executable file.\n2. A copy previously downloaded by this plugin (stored under a platform-specific data directory, e.g. `~/.local/share/aer-sf-plugin/aer-bin/`).\n3. `aer` discovered on `PATH`.\n4. If none of the above match and the terminal is interactive, you'll be prompted to download the latest release for your platform from GitHub; the binary is then stored in the plugin's data directory and used for subsequent runs.",
|
|
7
7
|
"examples": [
|
|
8
8
|
"Run every Apex test in the project:\n<%= config.bin %> <%= command.id %>",
|
|
9
9
|
"Run a specific Apex test class:\n<%= config.bin %> <%= command.id %> --class-names MyClassTest",
|
|
@@ -197,5 +197,5 @@
|
|
|
197
197
|
]
|
|
198
198
|
}
|
|
199
199
|
},
|
|
200
|
-
"version": "0.0.
|
|
200
|
+
"version": "0.0.3"
|
|
201
201
|
}
|
package/package.json
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@octoberswimmer/aer-sf-plugin",
|
|
3
3
|
"description": "Salesforce CLI plugin that runs Apex tests locally using aer.",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.3",
|
|
5
5
|
"author": "Christian G. Warden",
|
|
6
6
|
"bugs": "https://github.com/octoberswimmer/aer-sf-plugin/issues",
|
|
7
7
|
"homepage": "https://github.com/octoberswimmer/aer-sf-plugin",
|
|
8
|
-
"repository":
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/octoberswimmer/aer-sf-plugin.git"
|
|
11
|
+
},
|
|
9
12
|
"type": "module",
|
|
10
13
|
"exports": "./lib/index.js",
|
|
11
14
|
"engines": {
|
|
@@ -58,9 +61,11 @@
|
|
|
58
61
|
"@oclif/core": "^4",
|
|
59
62
|
"@salesforce/core": "^8",
|
|
60
63
|
"@salesforce/sf-plugins-core": "^12",
|
|
64
|
+
"adm-zip": "0.5.17",
|
|
61
65
|
"minimatch": "^9"
|
|
62
66
|
},
|
|
63
67
|
"devDependencies": {
|
|
68
|
+
"@types/adm-zip": "0.5.8",
|
|
64
69
|
"@types/chai": "^4.3.16",
|
|
65
70
|
"@types/mocha": "^10.0.6",
|
|
66
71
|
"@types/node": "^20.12.12",
|