electron-cli 0.3.0-alpha.12 → 0.3.0-alpha.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Cargo.lock +1 -1
- package/Cargo.toml +1 -1
- package/README.md +16 -2
- package/package.json +1 -1
- package/src/cli.rs +3 -3
- package/src/commands/make.rs +470 -32
- package/src/commands/publish.rs +2 -2
- package/src/project.rs +1 -1
package/Cargo.lock
CHANGED
package/Cargo.toml
CHANGED
package/README.md
CHANGED
|
@@ -36,7 +36,7 @@ The Rust-native flow currently owns:
|
|
|
36
36
|
- `init --template minimal`: writes a local Electron starter without Electron Forge.
|
|
37
37
|
- `start`: launches the installed Electron runtime directly.
|
|
38
38
|
- `package`: copies the installed Electron runtime, app files, installed production dependency closure, app metadata, macOS icon, and extra resources into a local app bundle for the current platform and architecture.
|
|
39
|
-
- `make`: runs `package` and writes
|
|
39
|
+
- `make`: runs `package` and writes distributables under `out/make/<target>/<platform>/<arch>/`; it reads JSON-shaped `config.forge.makers` / `electronCli.makers` arrays when `--target` is omitted, and `--target` still forces one maker. ZIP works on all platforms, `--target dmg` writes a basic macOS disk image, `--target deb` / `--target rpm` write Linux packages, and `--target msi` writes a basic Windows Installer package.
|
|
40
40
|
- `publish`: runs `make` and publishes the distributable to a local directory with a manifest or to GitHub Releases.
|
|
41
41
|
|
|
42
42
|
The GitHub publisher creates or reuses a release, uploads the selected make artifact, and can replace an existing asset with `--force`. It reads `GITHUB_TOKEN` or `GH_TOKEN` and can infer `OWNER/REPO` from `package.json` `repository`, or you can pass `--github-repo`.
|
|
@@ -54,12 +54,26 @@ Package metadata can be configured in `package.json`:
|
|
|
54
54
|
"appCategoryType": "public.app-category.developer-tools",
|
|
55
55
|
"icon": "assets/icon",
|
|
56
56
|
"extraResource": "assets/config.json"
|
|
57
|
+
},
|
|
58
|
+
"makers": [
|
|
59
|
+
{ "name": "@electron-forge/maker-zip" },
|
|
60
|
+
{ "name": "@electron-forge/maker-dmg", "platforms": ["darwin"] },
|
|
61
|
+
{ "name": "@electron-forge/maker-deb", "platforms": ["linux"] },
|
|
62
|
+
{ "name": "@electron-forge/maker-rpm", "platforms": ["linux"] },
|
|
63
|
+
{ "name": "@electron-forge/maker-wix", "platforms": ["win32"] }
|
|
64
|
+
]
|
|
65
|
+
},
|
|
66
|
+
"config": {
|
|
67
|
+
"forge": {
|
|
68
|
+
"makers": [
|
|
69
|
+
{ "name": "@electron-forge/maker-zip" }
|
|
70
|
+
]
|
|
57
71
|
}
|
|
58
72
|
}
|
|
59
73
|
}
|
|
60
74
|
```
|
|
61
75
|
|
|
62
|
-
The package command also reads JSON-shaped `config.forge.packagerConfig` and `electronPackagerConfig` entries for the same fields. JavaScript Forge config files are not evaluated.
|
|
76
|
+
The package command also reads JSON-shaped `config.forge.packagerConfig` and `electronPackagerConfig` entries for the same fields. The make command maps JSON-shaped Forge maker names to the Rust-native targets it supports: zip, dmg, deb, rpm, and wix/msi. JavaScript Forge config files are not evaluated.
|
|
63
77
|
|
|
64
78
|
## Install
|
|
65
79
|
|
package/package.json
CHANGED
package/src/cli.rs
CHANGED
|
@@ -164,9 +164,9 @@ pub struct MakeArgs {
|
|
|
164
164
|
#[arg(long)]
|
|
165
165
|
pub arch: Option<String>,
|
|
166
166
|
|
|
167
|
-
/// Maker target to run.
|
|
168
|
-
#[arg(long, value_enum
|
|
169
|
-
pub target: MakeTarget
|
|
167
|
+
/// Maker target to run. Overrides configured makers when provided.
|
|
168
|
+
#[arg(long, value_enum)]
|
|
169
|
+
pub target: Option<MakeTarget>,
|
|
170
170
|
|
|
171
171
|
/// Reuse an existing package output instead of running package first.
|
|
172
172
|
#[arg(long)]
|
package/src/commands/make.rs
CHANGED
|
@@ -15,6 +15,7 @@ use fscommon::BufStream;
|
|
|
15
15
|
use msi::{Column, Insert, Language, Package, PackageType, Value};
|
|
16
16
|
use rpm::{BuildConfig, CompressionType, FileOptions, PackageBuilder};
|
|
17
17
|
use serde::Serialize;
|
|
18
|
+
use serde_json::Value as JsonValue;
|
|
18
19
|
use tar::{Builder as TarBuilder, Header as TarHeader};
|
|
19
20
|
use uuid::Uuid;
|
|
20
21
|
use zip::{write::SimpleFileOptions, CompressionMethod, ZipWriter};
|
|
@@ -23,12 +24,15 @@ use crate::{
|
|
|
23
24
|
cli::{MakeArgs, MakeTarget, PackageArgs},
|
|
24
25
|
commands::package::{self, PackageReport},
|
|
25
26
|
output,
|
|
27
|
+
project::ProjectSnapshot,
|
|
26
28
|
};
|
|
27
29
|
|
|
28
30
|
#[derive(Debug, Serialize)]
|
|
29
31
|
pub(crate) struct MakeReport {
|
|
30
32
|
package: PackageReport,
|
|
31
33
|
target: String,
|
|
34
|
+
#[serde(skip)]
|
|
35
|
+
target_kind: MakeTarget,
|
|
32
36
|
skip_package: bool,
|
|
33
37
|
dry_run: bool,
|
|
34
38
|
make_dir: Utf8PathBuf,
|
|
@@ -38,27 +42,53 @@ pub(crate) struct MakeReport {
|
|
|
38
42
|
warnings: Vec<String>,
|
|
39
43
|
}
|
|
40
44
|
|
|
41
|
-
#[derive(Debug, Serialize)]
|
|
45
|
+
#[derive(Clone, Copy, Debug, Serialize)]
|
|
42
46
|
#[serde(rename_all = "kebab-case")]
|
|
43
47
|
enum MakeStatus {
|
|
44
48
|
Planned,
|
|
45
49
|
Made,
|
|
46
50
|
}
|
|
47
51
|
|
|
52
|
+
struct ResolvedMakeTargets {
|
|
53
|
+
targets: Vec<MakeTarget>,
|
|
54
|
+
warnings: Vec<String>,
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
#[derive(Debug, Serialize)]
|
|
58
|
+
struct MakeRunReport<'a> {
|
|
59
|
+
targets: &'a [MakeReport],
|
|
60
|
+
dry_run: bool,
|
|
61
|
+
status: MakeStatus,
|
|
62
|
+
warnings: Vec<String>,
|
|
63
|
+
}
|
|
64
|
+
|
|
48
65
|
pub fn run(args: MakeArgs) -> Result<()> {
|
|
49
|
-
let mut
|
|
66
|
+
let mut reports = build_reports(&args)?;
|
|
50
67
|
|
|
51
68
|
if args.dry_run {
|
|
52
|
-
return
|
|
69
|
+
return print_reports(&reports, args.json, MakeStatus::Planned);
|
|
53
70
|
}
|
|
54
71
|
|
|
55
|
-
|
|
56
|
-
report.mark_made()?;
|
|
72
|
+
execute_make_reports(&mut reports, &args)?;
|
|
57
73
|
|
|
58
|
-
|
|
74
|
+
print_reports(&reports, args.json, MakeStatus::Made)
|
|
59
75
|
}
|
|
60
76
|
|
|
61
77
|
pub(crate) fn build_report(args: &MakeArgs) -> Result<MakeReport> {
|
|
78
|
+
let reports = build_reports(args)?;
|
|
79
|
+
if reports.len() != 1 {
|
|
80
|
+
bail!(
|
|
81
|
+
"Expected one make target, but resolved {}. Pass --target to select one target.",
|
|
82
|
+
reports.len()
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
Ok(reports
|
|
86
|
+
.into_iter()
|
|
87
|
+
.next()
|
|
88
|
+
.expect("length was checked above"))
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
pub(crate) fn build_reports(args: &MakeArgs) -> Result<Vec<MakeReport>> {
|
|
62
92
|
let package_args = PackageArgs {
|
|
63
93
|
cwd: args.cwd.clone(),
|
|
64
94
|
out_dir: args.out_dir.clone(),
|
|
@@ -70,29 +100,47 @@ pub(crate) fn build_report(args: &MakeArgs) -> Result<MakeReport> {
|
|
|
70
100
|
json: false,
|
|
71
101
|
};
|
|
72
102
|
let snapshot = crate::project::inspect(&package_args.cwd)?;
|
|
73
|
-
let
|
|
103
|
+
let resolved = resolve_make_targets(&snapshot, args)?;
|
|
104
|
+
let config_warnings = resolved.warnings;
|
|
105
|
+
resolved
|
|
106
|
+
.targets
|
|
107
|
+
.into_iter()
|
|
108
|
+
.map(|target| {
|
|
109
|
+
let package = package::build_report(snapshot.clone(), &package_args)?;
|
|
110
|
+
build_report_for_target(package, target, args, &config_warnings)
|
|
111
|
+
})
|
|
112
|
+
.collect()
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
fn build_report_for_target(
|
|
116
|
+
package: PackageReport,
|
|
117
|
+
target: MakeTarget,
|
|
118
|
+
args: &MakeArgs,
|
|
119
|
+
config_warnings: &[String],
|
|
120
|
+
) -> Result<MakeReport> {
|
|
74
121
|
let make_dir = Path::new(package.output_dir().as_str())
|
|
75
122
|
.join("make")
|
|
76
|
-
.join(
|
|
123
|
+
.join(target.as_str())
|
|
77
124
|
.join(package.platform())
|
|
78
125
|
.join(package.arch());
|
|
79
|
-
let artifact = make_artifact_path(&make_dir, &package,
|
|
126
|
+
let artifact = make_artifact_path(&make_dir, &package, target);
|
|
80
127
|
|
|
81
128
|
let mut warnings = package.warnings().to_vec();
|
|
82
|
-
|
|
129
|
+
warnings.extend(config_warnings.iter().cloned());
|
|
130
|
+
if matches!(target, MakeTarget::Deb | MakeTarget::Rpm) && package.platform() != "linux" {
|
|
83
131
|
warnings.push(format!(
|
|
84
132
|
"{} maker only supports linux packages; target platform is {}.",
|
|
85
|
-
|
|
133
|
+
target.as_str(),
|
|
86
134
|
package.platform()
|
|
87
135
|
));
|
|
88
136
|
}
|
|
89
|
-
if
|
|
137
|
+
if target == MakeTarget::Dmg && package.platform() != "darwin" {
|
|
90
138
|
warnings.push(format!(
|
|
91
139
|
"dmg maker only supports macOS packages; target platform is {}.",
|
|
92
140
|
package.platform()
|
|
93
141
|
));
|
|
94
142
|
}
|
|
95
|
-
if
|
|
143
|
+
if target == MakeTarget::Msi && package.platform() != "win32" {
|
|
96
144
|
warnings.push(format!(
|
|
97
145
|
"msi maker only supports Windows packages; target platform is {}.",
|
|
98
146
|
package.platform()
|
|
@@ -114,7 +162,8 @@ pub(crate) fn build_report(args: &MakeArgs) -> Result<MakeReport> {
|
|
|
114
162
|
|
|
115
163
|
Ok(MakeReport {
|
|
116
164
|
package,
|
|
117
|
-
target:
|
|
165
|
+
target: target.as_str().to_string(),
|
|
166
|
+
target_kind: target,
|
|
118
167
|
skip_package: args.skip_package,
|
|
119
168
|
dry_run: args.dry_run,
|
|
120
169
|
make_dir: utf8_path(make_dir)?,
|
|
@@ -125,17 +174,215 @@ pub(crate) fn build_report(args: &MakeArgs) -> Result<MakeReport> {
|
|
|
125
174
|
})
|
|
126
175
|
}
|
|
127
176
|
|
|
177
|
+
struct ConfiguredMaker {
|
|
178
|
+
label: String,
|
|
179
|
+
target: Option<MakeTarget>,
|
|
180
|
+
platforms: Vec<String>,
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
fn resolve_make_targets(
|
|
184
|
+
snapshot: &ProjectSnapshot,
|
|
185
|
+
args: &MakeArgs,
|
|
186
|
+
) -> Result<ResolvedMakeTargets> {
|
|
187
|
+
if let Some(target) = args.target {
|
|
188
|
+
return Ok(ResolvedMakeTargets {
|
|
189
|
+
targets: vec![target],
|
|
190
|
+
warnings: Vec::new(),
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
let platform = args.platform.clone().unwrap_or_else(current_platform_label);
|
|
195
|
+
let makers = configured_makers(snapshot)?;
|
|
196
|
+
let mut warnings = Vec::new();
|
|
197
|
+
let mut targets = Vec::new();
|
|
198
|
+
|
|
199
|
+
for maker in &makers {
|
|
200
|
+
let Some(target) = maker.target else {
|
|
201
|
+
warnings.push(format!(
|
|
202
|
+
"Configured maker is not implemented yet and will be skipped: {}.",
|
|
203
|
+
maker.label
|
|
204
|
+
));
|
|
205
|
+
continue;
|
|
206
|
+
};
|
|
207
|
+
if !maker_applies_to_platform(maker, &platform) {
|
|
208
|
+
continue;
|
|
209
|
+
}
|
|
210
|
+
if !targets.contains(&target) {
|
|
211
|
+
targets.push(target);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
if targets.is_empty() {
|
|
216
|
+
if makers.is_empty() {
|
|
217
|
+
targets.push(MakeTarget::Zip);
|
|
218
|
+
} else {
|
|
219
|
+
warnings.push(format!(
|
|
220
|
+
"No supported configured makers apply to {platform}; defaulting to zip. Pass --target to override."
|
|
221
|
+
));
|
|
222
|
+
targets.push(MakeTarget::Zip);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
Ok(ResolvedMakeTargets { targets, warnings })
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
fn configured_makers(snapshot: &ProjectSnapshot) -> Result<Vec<ConfiguredMaker>> {
|
|
230
|
+
let Some(package_json_path) = &snapshot.package_json else {
|
|
231
|
+
return Ok(Vec::new());
|
|
232
|
+
};
|
|
233
|
+
let package_json_path = Path::new(package_json_path.as_str());
|
|
234
|
+
let raw = fs::read_to_string(package_json_path)
|
|
235
|
+
.with_context(|| format!("Could not read {}", package_json_path.display()))?;
|
|
236
|
+
let package = serde_json::from_str::<JsonValue>(&raw)
|
|
237
|
+
.with_context(|| format!("Could not parse {}", package_json_path.display()))?;
|
|
238
|
+
|
|
239
|
+
let mut makers = Vec::new();
|
|
240
|
+
for value in [
|
|
241
|
+
package
|
|
242
|
+
.get("config")
|
|
243
|
+
.and_then(|config| config.get("forge"))
|
|
244
|
+
.and_then(|forge| forge.get("makers")),
|
|
245
|
+
package
|
|
246
|
+
.get("electronCli")
|
|
247
|
+
.or_else(|| package.get("electron-cli"))
|
|
248
|
+
.and_then(|config| config.get("makers")),
|
|
249
|
+
]
|
|
250
|
+
.into_iter()
|
|
251
|
+
.flatten()
|
|
252
|
+
{
|
|
253
|
+
makers.extend(parse_maker_list(value));
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
Ok(makers)
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
fn parse_maker_list(value: &JsonValue) -> Vec<ConfiguredMaker> {
|
|
260
|
+
match value {
|
|
261
|
+
JsonValue::Array(values) => values.iter().filter_map(parse_maker).collect(),
|
|
262
|
+
_ => Vec::new(),
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
fn parse_maker(value: &JsonValue) -> Option<ConfiguredMaker> {
|
|
267
|
+
match value {
|
|
268
|
+
JsonValue::String(label) => Some(ConfiguredMaker {
|
|
269
|
+
label: label.clone(),
|
|
270
|
+
target: maker_target(label),
|
|
271
|
+
platforms: Vec::new(),
|
|
272
|
+
}),
|
|
273
|
+
JsonValue::Object(object) => {
|
|
274
|
+
let label = object
|
|
275
|
+
.get("name")
|
|
276
|
+
.or_else(|| object.get("target"))
|
|
277
|
+
.or_else(|| object.get("maker"))
|
|
278
|
+
.and_then(JsonValue::as_str)?
|
|
279
|
+
.to_string();
|
|
280
|
+
Some(ConfiguredMaker {
|
|
281
|
+
target: maker_target(&label),
|
|
282
|
+
platforms: string_values(object.get("platforms")),
|
|
283
|
+
label,
|
|
284
|
+
})
|
|
285
|
+
}
|
|
286
|
+
_ => None,
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
fn maker_target(label: &str) -> Option<MakeTarget> {
|
|
291
|
+
let label = label.trim().to_ascii_lowercase();
|
|
292
|
+
let compact = label
|
|
293
|
+
.trim_start_matches("@electron-forge/")
|
|
294
|
+
.trim_start_matches("electron-forge-")
|
|
295
|
+
.trim_start_matches("maker-");
|
|
296
|
+
|
|
297
|
+
if matches!(compact, "zip" | "@electron-forge/maker-zip")
|
|
298
|
+
|| label.ends_with("/maker-zip")
|
|
299
|
+
|| label.ends_with("maker-zip")
|
|
300
|
+
{
|
|
301
|
+
Some(MakeTarget::Zip)
|
|
302
|
+
} else if compact == "dmg" || label.ends_with("/maker-dmg") || label.ends_with("maker-dmg") {
|
|
303
|
+
Some(MakeTarget::Dmg)
|
|
304
|
+
} else if compact == "deb" || label.ends_with("/maker-deb") || label.ends_with("maker-deb") {
|
|
305
|
+
Some(MakeTarget::Deb)
|
|
306
|
+
} else if compact == "rpm" || label.ends_with("/maker-rpm") || label.ends_with("maker-rpm") {
|
|
307
|
+
Some(MakeTarget::Rpm)
|
|
308
|
+
} else if matches!(compact, "msi" | "wix")
|
|
309
|
+
|| label.ends_with("/maker-wix")
|
|
310
|
+
|| label.ends_with("maker-wix")
|
|
311
|
+
{
|
|
312
|
+
Some(MakeTarget::Msi)
|
|
313
|
+
} else {
|
|
314
|
+
None
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
fn maker_applies_to_platform(maker: &ConfiguredMaker, platform: &str) -> bool {
|
|
319
|
+
maker.platforms.is_empty()
|
|
320
|
+
|| maker
|
|
321
|
+
.platforms
|
|
322
|
+
.iter()
|
|
323
|
+
.any(|configured| configured == platform || configured == "*")
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
fn string_values(value: Option<&JsonValue>) -> Vec<String> {
|
|
327
|
+
match value {
|
|
328
|
+
Some(JsonValue::String(value)) => vec![value.clone()],
|
|
329
|
+
Some(JsonValue::Array(values)) => values
|
|
330
|
+
.iter()
|
|
331
|
+
.filter_map(JsonValue::as_str)
|
|
332
|
+
.map(ToOwned::to_owned)
|
|
333
|
+
.collect(),
|
|
334
|
+
_ => Vec::new(),
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
fn current_platform_label() -> String {
|
|
339
|
+
if cfg!(target_os = "macos") {
|
|
340
|
+
"darwin".to_string()
|
|
341
|
+
} else if cfg!(target_os = "windows") {
|
|
342
|
+
"win32".to_string()
|
|
343
|
+
} else {
|
|
344
|
+
"linux".to_string()
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
|
|
128
348
|
pub(crate) fn execute_make(report: &mut MakeReport, args: &MakeArgs) -> Result<()> {
|
|
349
|
+
ensure_package_ready(std::slice::from_mut(report), args)?;
|
|
350
|
+
execute_make_artifact(report, args)?;
|
|
351
|
+
Ok(())
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
pub(crate) fn execute_make_reports(reports: &mut [MakeReport], args: &MakeArgs) -> Result<()> {
|
|
355
|
+
if reports.is_empty() {
|
|
356
|
+
bail!("No make targets were resolved.");
|
|
357
|
+
}
|
|
358
|
+
ensure_package_ready(reports, args)?;
|
|
359
|
+
for report in reports {
|
|
360
|
+
execute_make_artifact(report, args)?;
|
|
361
|
+
report.mark_made()?;
|
|
362
|
+
}
|
|
363
|
+
Ok(())
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
fn ensure_package_ready(reports: &mut [MakeReport], args: &MakeArgs) -> Result<()> {
|
|
367
|
+
let first = reports
|
|
368
|
+
.first_mut()
|
|
369
|
+
.context("No make targets were resolved.")?;
|
|
129
370
|
if !args.skip_package {
|
|
130
|
-
package::execute_package(&
|
|
131
|
-
report
|
|
132
|
-
|
|
371
|
+
package::execute_package(&first.package, args.force)?;
|
|
372
|
+
for report in reports {
|
|
373
|
+
report.package.mark_packaged();
|
|
374
|
+
}
|
|
375
|
+
} else if !Path::new(first.package.bundle_dir().as_str()).exists() {
|
|
133
376
|
bail!(
|
|
134
377
|
"Package output does not exist: {}. Run without --skip-package or run electron-cli package first.",
|
|
135
|
-
|
|
378
|
+
first.package.bundle_dir()
|
|
136
379
|
);
|
|
137
380
|
}
|
|
138
381
|
|
|
382
|
+
Ok(())
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
fn execute_make_artifact(report: &mut MakeReport, args: &MakeArgs) -> Result<()> {
|
|
139
386
|
let artifact = Path::new(report.artifact.as_str());
|
|
140
387
|
if artifact.exists() {
|
|
141
388
|
if args.force {
|
|
@@ -151,7 +398,7 @@ pub(crate) fn execute_make(report: &mut MakeReport, args: &MakeArgs) -> Result<(
|
|
|
151
398
|
|
|
152
399
|
fs::create_dir_all(report.make_dir.as_str())
|
|
153
400
|
.with_context(|| format!("Could not create {}", report.make_dir))?;
|
|
154
|
-
match
|
|
401
|
+
match report.target_kind {
|
|
155
402
|
MakeTarget::Zip => {
|
|
156
403
|
write_zip_archive(Path::new(report.package.bundle_dir().as_str()), artifact)?
|
|
157
404
|
}
|
|
@@ -204,6 +451,69 @@ fn print_report(report: &MakeReport, json: bool) -> Result<()> {
|
|
|
204
451
|
Ok(())
|
|
205
452
|
}
|
|
206
453
|
|
|
454
|
+
fn print_reports(reports: &[MakeReport], json: bool, status: MakeStatus) -> Result<()> {
|
|
455
|
+
if reports.len() == 1 {
|
|
456
|
+
return print_report(&reports[0], json);
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
let warnings = combined_warnings(reports);
|
|
460
|
+
if json {
|
|
461
|
+
return output::json(&MakeRunReport {
|
|
462
|
+
targets: reports,
|
|
463
|
+
dry_run: reports.iter().any(|report| report.dry_run),
|
|
464
|
+
status,
|
|
465
|
+
warnings,
|
|
466
|
+
});
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
println!("electron-cli make");
|
|
470
|
+
println!();
|
|
471
|
+
if let Some(first) = reports.first() {
|
|
472
|
+
println!("Project");
|
|
473
|
+
println!(" root: {}", first.package.project().root);
|
|
474
|
+
match first.package.project().package_label() {
|
|
475
|
+
Some(label) => println!(" package: {label}"),
|
|
476
|
+
None => println!(" package: not found"),
|
|
477
|
+
}
|
|
478
|
+
println!(" app name: {}", first.package.app_name());
|
|
479
|
+
println!(
|
|
480
|
+
" target platform: {} {}",
|
|
481
|
+
first.package.platform(),
|
|
482
|
+
first.package.arch()
|
|
483
|
+
);
|
|
484
|
+
println!(" status: {}", status.as_str());
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
println!();
|
|
488
|
+
println!("Artifacts");
|
|
489
|
+
for report in reports {
|
|
490
|
+
println!(" {}: {}", report.target, report.artifact);
|
|
491
|
+
if let Some(size) = report.artifact_size {
|
|
492
|
+
println!(" size: {size} bytes");
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
if !warnings.is_empty() {
|
|
497
|
+
println!();
|
|
498
|
+
println!("Warnings");
|
|
499
|
+
for warning in warnings {
|
|
500
|
+
println!(" {warning}");
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
Ok(())
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
fn combined_warnings(reports: &[MakeReport]) -> Vec<String> {
|
|
508
|
+
let mut warnings = Vec::new();
|
|
509
|
+
for warning in reports.iter().flat_map(|report| report.warnings()) {
|
|
510
|
+
if !warnings.contains(warning) {
|
|
511
|
+
warnings.push(warning.clone());
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
warnings
|
|
515
|
+
}
|
|
516
|
+
|
|
207
517
|
fn make_artifact_path(make_dir: &Path, package: &PackageReport, target: MakeTarget) -> PathBuf {
|
|
208
518
|
match target {
|
|
209
519
|
MakeTarget::Zip => make_dir.join(format!(
|
|
@@ -1909,7 +2219,7 @@ mod tests {
|
|
|
1909
2219
|
name: None,
|
|
1910
2220
|
platform: None,
|
|
1911
2221
|
arch: None,
|
|
1912
|
-
target: crate::cli::MakeTarget::Zip,
|
|
2222
|
+
target: Some(crate::cli::MakeTarget::Zip),
|
|
1913
2223
|
skip_package: false,
|
|
1914
2224
|
force: false,
|
|
1915
2225
|
dry_run: true,
|
|
@@ -1946,7 +2256,7 @@ mod tests {
|
|
|
1946
2256
|
name: None,
|
|
1947
2257
|
platform: Some("linux".to_string()),
|
|
1948
2258
|
arch: Some("x64".to_string()),
|
|
1949
|
-
target: crate::cli::MakeTarget::Deb,
|
|
2259
|
+
target: Some(crate::cli::MakeTarget::Deb),
|
|
1950
2260
|
skip_package: false,
|
|
1951
2261
|
force: false,
|
|
1952
2262
|
dry_run: true,
|
|
@@ -1980,7 +2290,7 @@ mod tests {
|
|
|
1980
2290
|
name: None,
|
|
1981
2291
|
platform: Some("darwin".to_string()),
|
|
1982
2292
|
arch: Some("arm64".to_string()),
|
|
1983
|
-
target: crate::cli::MakeTarget::Dmg,
|
|
2293
|
+
target: Some(crate::cli::MakeTarget::Dmg),
|
|
1984
2294
|
skip_package: false,
|
|
1985
2295
|
force: false,
|
|
1986
2296
|
dry_run: true,
|
|
@@ -2014,7 +2324,7 @@ mod tests {
|
|
|
2014
2324
|
name: None,
|
|
2015
2325
|
platform: Some("linux".to_string()),
|
|
2016
2326
|
arch: Some("x64".to_string()),
|
|
2017
|
-
target: crate::cli::MakeTarget::Rpm,
|
|
2327
|
+
target: Some(crate::cli::MakeTarget::Rpm),
|
|
2018
2328
|
skip_package: false,
|
|
2019
2329
|
force: false,
|
|
2020
2330
|
dry_run: true,
|
|
@@ -2048,7 +2358,7 @@ mod tests {
|
|
|
2048
2358
|
name: None,
|
|
2049
2359
|
platform: Some("win32".to_string()),
|
|
2050
2360
|
arch: Some("x64".to_string()),
|
|
2051
|
-
target: crate::cli::MakeTarget::Msi,
|
|
2361
|
+
target: Some(crate::cli::MakeTarget::Msi),
|
|
2052
2362
|
skip_package: false,
|
|
2053
2363
|
force: false,
|
|
2054
2364
|
dry_run: true,
|
|
@@ -2069,6 +2379,79 @@ mod tests {
|
|
|
2069
2379
|
let _ = fs::remove_dir_all(root);
|
|
2070
2380
|
}
|
|
2071
2381
|
|
|
2382
|
+
#[test]
|
|
2383
|
+
fn builds_make_reports_from_configured_forge_makers() {
|
|
2384
|
+
let root = unique_temp_dir("configured-makers");
|
|
2385
|
+
write_package_json_with_makers(
|
|
2386
|
+
&root,
|
|
2387
|
+
r#"[
|
|
2388
|
+
{"name":"@electron-forge/maker-zip"},
|
|
2389
|
+
{"name":"@electron-forge/maker-deb","platforms":["linux"]},
|
|
2390
|
+
{"name":"@electron-forge/maker-rpm","platforms":["darwin"]},
|
|
2391
|
+
{"name":"@electron-forge/maker-squirrel","platforms":["linux"]}
|
|
2392
|
+
]"#,
|
|
2393
|
+
);
|
|
2394
|
+
write_app_file(&root);
|
|
2395
|
+
write_fake_electron_dist(&root);
|
|
2396
|
+
|
|
2397
|
+
let args = MakeArgs {
|
|
2398
|
+
cwd: root.clone(),
|
|
2399
|
+
out_dir: PathBuf::from("out"),
|
|
2400
|
+
name: None,
|
|
2401
|
+
platform: Some("linux".to_string()),
|
|
2402
|
+
arch: Some("x64".to_string()),
|
|
2403
|
+
target: None,
|
|
2404
|
+
skip_package: false,
|
|
2405
|
+
force: false,
|
|
2406
|
+
dry_run: true,
|
|
2407
|
+
json: true,
|
|
2408
|
+
};
|
|
2409
|
+
let reports = build_reports(&args).expect("reports should build");
|
|
2410
|
+
|
|
2411
|
+
assert_eq!(reports.len(), 2);
|
|
2412
|
+
assert_eq!(reports[0].target(), "zip");
|
|
2413
|
+
assert_eq!(reports[1].target(), "deb");
|
|
2414
|
+
assert!(reports[0]
|
|
2415
|
+
.warnings()
|
|
2416
|
+
.iter()
|
|
2417
|
+
.any(|warning| warning.contains("@electron-forge/maker-squirrel")));
|
|
2418
|
+
|
|
2419
|
+
let _ = fs::remove_dir_all(root);
|
|
2420
|
+
}
|
|
2421
|
+
|
|
2422
|
+
#[test]
|
|
2423
|
+
fn explicit_make_target_overrides_configured_makers() {
|
|
2424
|
+
let root = unique_temp_dir("target-override");
|
|
2425
|
+
write_package_json_with_makers(
|
|
2426
|
+
&root,
|
|
2427
|
+
r#"[{"name":"@electron-forge/maker-zip"},{"name":"@electron-forge/maker-deb"}]"#,
|
|
2428
|
+
);
|
|
2429
|
+
write_app_file(&root);
|
|
2430
|
+
write_fake_electron_dist(&root);
|
|
2431
|
+
|
|
2432
|
+
let args = MakeArgs {
|
|
2433
|
+
cwd: root.clone(),
|
|
2434
|
+
out_dir: PathBuf::from("out"),
|
|
2435
|
+
name: None,
|
|
2436
|
+
platform: Some("win32".to_string()),
|
|
2437
|
+
arch: Some("x64".to_string()),
|
|
2438
|
+
target: Some(crate::cli::MakeTarget::Msi),
|
|
2439
|
+
skip_package: false,
|
|
2440
|
+
force: false,
|
|
2441
|
+
dry_run: true,
|
|
2442
|
+
json: true,
|
|
2443
|
+
};
|
|
2444
|
+
let report = build_report(&args).expect("report should build");
|
|
2445
|
+
|
|
2446
|
+
assert_eq!(report.target(), "msi");
|
|
2447
|
+
assert!(report
|
|
2448
|
+
.warnings()
|
|
2449
|
+
.iter()
|
|
2450
|
+
.all(|warning| !warning.contains("maker-deb")));
|
|
2451
|
+
|
|
2452
|
+
let _ = fs::remove_dir_all(root);
|
|
2453
|
+
}
|
|
2454
|
+
|
|
2072
2455
|
#[test]
|
|
2073
2456
|
fn makes_zip_artifact_after_packaging() {
|
|
2074
2457
|
let root = unique_temp_dir("execute");
|
|
@@ -2082,7 +2465,7 @@ mod tests {
|
|
|
2082
2465
|
name: None,
|
|
2083
2466
|
platform: None,
|
|
2084
2467
|
arch: None,
|
|
2085
|
-
target: crate::cli::MakeTarget::Zip,
|
|
2468
|
+
target: Some(crate::cli::MakeTarget::Zip),
|
|
2086
2469
|
skip_package: false,
|
|
2087
2470
|
force: false,
|
|
2088
2471
|
dry_run: false,
|
|
@@ -2111,6 +2494,44 @@ mod tests {
|
|
|
2111
2494
|
let _ = fs::remove_dir_all(root);
|
|
2112
2495
|
}
|
|
2113
2496
|
|
|
2497
|
+
#[test]
|
|
2498
|
+
fn makes_multiple_configured_artifacts_from_existing_package() {
|
|
2499
|
+
let root = unique_temp_dir("configured-execute");
|
|
2500
|
+
write_package_json_with_makers(
|
|
2501
|
+
&root,
|
|
2502
|
+
r#"[
|
|
2503
|
+
{"name":"@electron-forge/maker-zip","platforms":["win32"]},
|
|
2504
|
+
{"name":"@electron-forge/maker-wix","platforms":["win32"]}
|
|
2505
|
+
]"#,
|
|
2506
|
+
);
|
|
2507
|
+
write_app_file(&root);
|
|
2508
|
+
write_fake_windows_bundle(&root.join("out/starter-app-win32-x64"), "starter-app.exe");
|
|
2509
|
+
|
|
2510
|
+
let args = MakeArgs {
|
|
2511
|
+
cwd: root.clone(),
|
|
2512
|
+
out_dir: PathBuf::from("out"),
|
|
2513
|
+
name: None,
|
|
2514
|
+
platform: Some("win32".to_string()),
|
|
2515
|
+
arch: Some("x64".to_string()),
|
|
2516
|
+
target: None,
|
|
2517
|
+
skip_package: true,
|
|
2518
|
+
force: false,
|
|
2519
|
+
dry_run: false,
|
|
2520
|
+
json: true,
|
|
2521
|
+
};
|
|
2522
|
+
let mut reports = build_reports(&args).expect("reports should build");
|
|
2523
|
+
|
|
2524
|
+
execute_make_reports(&mut reports, &args).expect("configured makers should execute");
|
|
2525
|
+
|
|
2526
|
+
assert_eq!(reports.len(), 2);
|
|
2527
|
+
assert_eq!(reports[0].target(), "zip");
|
|
2528
|
+
assert_eq!(reports[1].target(), "msi");
|
|
2529
|
+
assert!(Path::new(reports[0].artifact.as_str()).exists());
|
|
2530
|
+
assert!(Path::new(reports[1].artifact.as_str()).exists());
|
|
2531
|
+
|
|
2532
|
+
let _ = fs::remove_dir_all(root);
|
|
2533
|
+
}
|
|
2534
|
+
|
|
2114
2535
|
#[test]
|
|
2115
2536
|
fn writes_deb_archive_with_control_and_data_members() {
|
|
2116
2537
|
let root = unique_temp_dir("deb-archive");
|
|
@@ -2124,7 +2545,7 @@ mod tests {
|
|
|
2124
2545
|
name: None,
|
|
2125
2546
|
platform: Some("linux".to_string()),
|
|
2126
2547
|
arch: Some("x64".to_string()),
|
|
2127
|
-
target: crate::cli::MakeTarget::Deb,
|
|
2548
|
+
target: Some(crate::cli::MakeTarget::Deb),
|
|
2128
2549
|
skip_package: false,
|
|
2129
2550
|
force: false,
|
|
2130
2551
|
dry_run: true,
|
|
@@ -2183,7 +2604,7 @@ mod tests {
|
|
|
2183
2604
|
name: None,
|
|
2184
2605
|
platform: Some("darwin".to_string()),
|
|
2185
2606
|
arch: Some("arm64".to_string()),
|
|
2186
|
-
target: crate::cli::MakeTarget::Dmg,
|
|
2607
|
+
target: Some(crate::cli::MakeTarget::Dmg),
|
|
2187
2608
|
skip_package: false,
|
|
2188
2609
|
force: false,
|
|
2189
2610
|
dry_run: true,
|
|
@@ -2251,7 +2672,7 @@ mod tests {
|
|
|
2251
2672
|
name: None,
|
|
2252
2673
|
platform: Some("linux".to_string()),
|
|
2253
2674
|
arch: Some("x64".to_string()),
|
|
2254
|
-
target: crate::cli::MakeTarget::Rpm,
|
|
2675
|
+
target: Some(crate::cli::MakeTarget::Rpm),
|
|
2255
2676
|
skip_package: false,
|
|
2256
2677
|
force: false,
|
|
2257
2678
|
dry_run: true,
|
|
@@ -2310,7 +2731,7 @@ mod tests {
|
|
|
2310
2731
|
name: None,
|
|
2311
2732
|
platform: Some("win32".to_string()),
|
|
2312
2733
|
arch: Some("x64".to_string()),
|
|
2313
|
-
target: crate::cli::MakeTarget::Msi,
|
|
2734
|
+
target: Some(crate::cli::MakeTarget::Msi),
|
|
2314
2735
|
skip_package: false,
|
|
2315
2736
|
force: false,
|
|
2316
2737
|
dry_run: true,
|
|
@@ -2384,7 +2805,7 @@ mod tests {
|
|
|
2384
2805
|
name: None,
|
|
2385
2806
|
platform: None,
|
|
2386
2807
|
arch: None,
|
|
2387
|
-
target: crate::cli::MakeTarget::Deb,
|
|
2808
|
+
target: Some(crate::cli::MakeTarget::Deb),
|
|
2388
2809
|
skip_package: false,
|
|
2389
2810
|
force: false,
|
|
2390
2811
|
dry_run: false,
|
|
@@ -2416,7 +2837,7 @@ mod tests {
|
|
|
2416
2837
|
name: None,
|
|
2417
2838
|
platform: None,
|
|
2418
2839
|
arch: None,
|
|
2419
|
-
target: crate::cli::MakeTarget::Dmg,
|
|
2840
|
+
target: Some(crate::cli::MakeTarget::Dmg),
|
|
2420
2841
|
skip_package: false,
|
|
2421
2842
|
force: false,
|
|
2422
2843
|
dry_run: false,
|
|
@@ -2448,7 +2869,7 @@ mod tests {
|
|
|
2448
2869
|
name: None,
|
|
2449
2870
|
platform: None,
|
|
2450
2871
|
arch: None,
|
|
2451
|
-
target: crate::cli::MakeTarget::Rpm,
|
|
2872
|
+
target: Some(crate::cli::MakeTarget::Rpm),
|
|
2452
2873
|
skip_package: false,
|
|
2453
2874
|
force: false,
|
|
2454
2875
|
dry_run: false,
|
|
@@ -2471,6 +2892,23 @@ mod tests {
|
|
|
2471
2892
|
.expect("package.json should be written");
|
|
2472
2893
|
}
|
|
2473
2894
|
|
|
2895
|
+
fn write_package_json_with_makers(root: &Path, makers: &str) {
|
|
2896
|
+
fs::write(
|
|
2897
|
+
root.join("package.json"),
|
|
2898
|
+
format!(
|
|
2899
|
+
r#"{{
|
|
2900
|
+
"name":"starter-app",
|
|
2901
|
+
"version":"0.1.0",
|
|
2902
|
+
"license":"MIT",
|
|
2903
|
+
"main":"src/main.js",
|
|
2904
|
+
"devDependencies":{{"electron":"30.0.0"}},
|
|
2905
|
+
"config":{{"forge":{{"makers":{makers}}}}}
|
|
2906
|
+
}}"#
|
|
2907
|
+
),
|
|
2908
|
+
)
|
|
2909
|
+
.expect("package.json with makers should be written");
|
|
2910
|
+
}
|
|
2911
|
+
|
|
2474
2912
|
fn write_app_file(root: &Path) {
|
|
2475
2913
|
fs::create_dir_all(root.join("src")).expect("src should be created");
|
|
2476
2914
|
fs::write(root.join("src/main.js"), "console.log('hello');")
|
package/src/commands/publish.rs
CHANGED
|
@@ -98,7 +98,7 @@ fn build_report(args: &PublishArgs) -> Result<PublishReport> {
|
|
|
98
98
|
name: args.name.clone(),
|
|
99
99
|
platform: args.platform.clone(),
|
|
100
100
|
arch: args.arch.clone(),
|
|
101
|
-
target: args.target,
|
|
101
|
+
target: Some(args.target),
|
|
102
102
|
skip_package: false,
|
|
103
103
|
force: args.force,
|
|
104
104
|
dry_run: false,
|
|
@@ -235,7 +235,7 @@ fn execute_publish(report: &mut PublishReport, args: &PublishArgs) -> Result<()>
|
|
|
235
235
|
name: args.name.clone(),
|
|
236
236
|
platform: args.platform.clone(),
|
|
237
237
|
arch: args.arch.clone(),
|
|
238
|
-
target: args.target,
|
|
238
|
+
target: Some(args.target),
|
|
239
239
|
skip_package: false,
|
|
240
240
|
force: args.force,
|
|
241
241
|
dry_run: false,
|
package/src/project.rs
CHANGED