electron-cli 0.3.0-alpha.18 → 0.3.0-alpha.19
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 +4 -3
- package/package.json +1 -1
- package/src/commands/package.rs +215 -1
package/Cargo.lock
CHANGED
package/Cargo.toml
CHANGED
package/README.md
CHANGED
|
@@ -41,9 +41,9 @@ The Rust-native flow currently owns:
|
|
|
41
41
|
|
|
42
42
|
The GitHub publisher creates or reuses a release, uploads selected make artifacts, and can replace an existing asset with `--force`. It reads `GITHUB_TOKEN` or `GH_TOKEN` and can infer `OWNER/REPO` from package metadata, Forge GitHub publisher config, or `package.json` `repository`. You can also pass `--github-repo`.
|
|
43
43
|
|
|
44
|
-
The package command recognizes macOS `packagerConfig.osxSign` and `packagerConfig.osxNotarize` options and reports the signing/notarization plan without serializing credential values. When `osxSign` is enabled on macOS and no certificate identity is configured, or the identity is `"-"`, `package` writes an experimental Rust-native ad-hoc signature for the generated `.app` bundle. When `osxSign.p12File` points at a `.p12`/PFX certificate export, `package` can sign the bundle with that certificate. macOS keychain identity lookup and notarization
|
|
44
|
+
The package command recognizes macOS `packagerConfig.osxSign` and `packagerConfig.osxNotarize` options and reports the signing/notarization plan without serializing credential values. When `osxSign` is enabled on macOS and no certificate identity is configured, or the identity is `"-"`, `package` writes an experimental Rust-native ad-hoc signature for the generated `.app` bundle. When `osxSign.p12File` points at a `.p12`/PFX certificate export, `package` can sign the bundle with that certificate and can request a CMS timestamp token for notarization-compatible signatures. macOS keychain identity lookup and notarization submission/stapling are not implemented yet.
|
|
45
45
|
|
|
46
|
-
The DMG maker is currently a pure-Rust FAT32 image with the app bundle and an Applications entry. The MSI maker writes a compressed embedded CAB, Windows Installer database tables, and a Start Menu shortcut when the packaged executable is present. HFS+/APFS DMG layout customization, installer UI customization, Windows/Linux icon embedding, macOS keychain signing,
|
|
46
|
+
The DMG maker is currently a pure-Rust FAT32 image with the app bundle and an Applications entry. The MSI maker writes a compressed embedded CAB, Windows Installer database tables, and a Start Menu shortcut when the packaged executable is present. HFS+/APFS DMG layout customization, installer UI customization, Windows/Linux icon embedding, macOS keychain signing, and notarization execution are still TODO.
|
|
47
47
|
|
|
48
48
|
Package metadata can be configured in `package.json`:
|
|
49
49
|
|
|
@@ -59,6 +59,7 @@ Package metadata can be configured in `package.json`:
|
|
|
59
59
|
"osxSign": {
|
|
60
60
|
"p12File": "certs/developer-id.p12",
|
|
61
61
|
"p12PasswordEnv": "ELECTRON_CLI_P12_PASSWORD",
|
|
62
|
+
"timestamp": true,
|
|
62
63
|
"entitlements": "assets/entitlements.plist",
|
|
63
64
|
"hardenedRuntime": true
|
|
64
65
|
},
|
|
@@ -98,7 +99,7 @@ Package metadata can be configured in `package.json`:
|
|
|
98
99
|
}
|
|
99
100
|
```
|
|
100
101
|
|
|
101
|
-
Use `p12PasswordEnv`, `p12PasswordFile`, or `p12Password` for the `.p12` password; password values are not serialized in package reports. Set `identity` to a Developer ID certificate name when you want the plan to reflect Forge-style keychain release signing, but this project will report it as not executable until Rust-native keychain lookup exists. Use `identity: "-"` or omit `identity` for the current ad-hoc signing path.
|
|
102
|
+
Use `p12PasswordEnv`, `p12PasswordFile`, or `p12Password` for the `.p12` password; password values are not serialized in package reports. Set `osxSign.timestamp` to a timestamp server URL, `true` for Apple's default `http://timestamp.apple.com/ts01`, or `"none"` / `false` to disable timestamping. When `osxNotarize` is enabled with p12 signing, `electron-cli` automatically enables notarization-compatible signing and uses Apple's timestamp server unless timestamping is disabled explicitly. Set `identity` to a Developer ID certificate name when you want the plan to reflect Forge-style keychain release signing, but this project will report it as not executable until Rust-native keychain lookup exists. Use `identity: "-"` or omit `identity` for the current ad-hoc signing path.
|
|
102
103
|
|
|
103
104
|
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. The publish command maps JSON-shaped publisher names to local and GitHub.
|
|
104
105
|
|
package/package.json
CHANGED
package/src/commands/package.rs
CHANGED
|
@@ -16,6 +16,8 @@ use serde_json::Value as JsonValue;
|
|
|
16
16
|
|
|
17
17
|
use crate::{cli::PackageArgs, output, project::ProjectSnapshot};
|
|
18
18
|
|
|
19
|
+
const APPLE_TIMESTAMP_URL: &str = "http://timestamp.apple.com/ts01";
|
|
20
|
+
|
|
19
21
|
#[derive(Clone, Debug, Serialize)]
|
|
20
22
|
pub(crate) struct PackageReport {
|
|
21
23
|
project: ProjectSnapshot,
|
|
@@ -84,6 +86,8 @@ struct MacosSignPlan {
|
|
|
84
86
|
p12_password_file: Option<Utf8PathBuf>,
|
|
85
87
|
#[serde(skip)]
|
|
86
88
|
p12_password: RedactedSecret,
|
|
89
|
+
timestamp_url: Option<String>,
|
|
90
|
+
for_notarization: bool,
|
|
87
91
|
entitlements: Vec<Utf8PathBuf>,
|
|
88
92
|
entitlements_inherit: Option<Utf8PathBuf>,
|
|
89
93
|
hardened_runtime: Option<bool>,
|
|
@@ -163,12 +167,20 @@ struct MacosSignConfig {
|
|
|
163
167
|
p12_password: Option<String>,
|
|
164
168
|
p12_password_env: Option<String>,
|
|
165
169
|
p12_password_file: Option<String>,
|
|
170
|
+
timestamp: Option<MacosTimestampConfig>,
|
|
166
171
|
entitlements: Vec<String>,
|
|
167
172
|
entitlements_inherit: Option<String>,
|
|
168
173
|
hardened_runtime: Option<bool>,
|
|
169
174
|
gatekeeper_assess: Option<bool>,
|
|
170
175
|
}
|
|
171
176
|
|
|
177
|
+
#[derive(Clone, Debug)]
|
|
178
|
+
enum MacosTimestampConfig {
|
|
179
|
+
Default,
|
|
180
|
+
Disabled,
|
|
181
|
+
Url(String),
|
|
182
|
+
}
|
|
183
|
+
|
|
172
184
|
#[derive(Clone, Debug, Default)]
|
|
173
185
|
struct MacosNotarizeConfig {
|
|
174
186
|
configured: bool,
|
|
@@ -457,6 +469,9 @@ fn execute_macos_signing(report: &PackageReport) -> Result<()> {
|
|
|
457
469
|
settings.set_signing_key(signing_key.as_key_info_signer(), certificate);
|
|
458
470
|
settings.chain_apple_certificates();
|
|
459
471
|
settings.set_team_id_from_signing_certificate();
|
|
472
|
+
settings
|
|
473
|
+
.ensure_for_notarization_settings()
|
|
474
|
+
.context("macOS signing settings are not compatible with notarization")?;
|
|
460
475
|
signer
|
|
461
476
|
.write_signed_bundle(&signed_bundle_dir, &settings)
|
|
462
477
|
.with_context(|| {
|
|
@@ -502,6 +517,13 @@ fn macos_signing_settings<'key>(report: &PackageReport) -> Result<SigningSetting
|
|
|
502
517
|
let sign = &report.signing.macos.sign;
|
|
503
518
|
let mut settings = SigningSettings::default();
|
|
504
519
|
settings.set_binary_identifier(SettingsScope::Main, &report.metadata.bundle_identifier);
|
|
520
|
+
settings.set_for_notarization(sign.for_notarization);
|
|
521
|
+
|
|
522
|
+
if let Some(timestamp_url) = &sign.timestamp_url {
|
|
523
|
+
settings
|
|
524
|
+
.set_time_stamp_url(timestamp_url)
|
|
525
|
+
.with_context(|| format!("Invalid macOS signing timestamp URL: {timestamp_url}"))?;
|
|
526
|
+
}
|
|
505
527
|
|
|
506
528
|
if sign.hardened_runtime.unwrap_or(false) {
|
|
507
529
|
settings.add_code_signature_flags(SettingsScope::Main, CodeSignatureFlags::RUNTIME);
|
|
@@ -601,6 +623,12 @@ fn print_report(report: &PackageReport, json: bool) -> Result<()> {
|
|
|
601
623
|
if let Some(source) = &report.signing.macos.sign.p12_password_source {
|
|
602
624
|
println!(" p12 password: {source}");
|
|
603
625
|
}
|
|
626
|
+
if let Some(timestamp_url) = &report.signing.macos.sign.timestamp_url {
|
|
627
|
+
println!(" timestamp server: {timestamp_url}");
|
|
628
|
+
}
|
|
629
|
+
if report.signing.macos.sign.for_notarization {
|
|
630
|
+
println!(" signing mode: notarization-compatible");
|
|
631
|
+
}
|
|
604
632
|
if let Some(method) = &report.signing.macos.sign.method {
|
|
605
633
|
println!(" signing method: {method}");
|
|
606
634
|
}
|
|
@@ -762,6 +790,12 @@ fn parse_macos_sign_config(value: Option<&JsonValue>) -> MacosSignConfig {
|
|
|
762
790
|
.or_else(|| object.get("pfxPasswordFile"))
|
|
763
791
|
.and_then(JsonValue::as_str)
|
|
764
792
|
.map(ToOwned::to_owned),
|
|
793
|
+
timestamp: parse_macos_timestamp_config(
|
|
794
|
+
object
|
|
795
|
+
.get("timestamp")
|
|
796
|
+
.or_else(|| object.get("timestampUrl"))
|
|
797
|
+
.or_else(|| object.get("timestampURL")),
|
|
798
|
+
),
|
|
765
799
|
entitlements,
|
|
766
800
|
entitlements_inherit: object
|
|
767
801
|
.get("entitlementsInherit")
|
|
@@ -779,6 +813,22 @@ fn parse_macos_sign_config(value: Option<&JsonValue>) -> MacosSignConfig {
|
|
|
779
813
|
}
|
|
780
814
|
}
|
|
781
815
|
|
|
816
|
+
fn parse_macos_timestamp_config(value: Option<&JsonValue>) -> Option<MacosTimestampConfig> {
|
|
817
|
+
match value {
|
|
818
|
+
Some(JsonValue::String(value)) => {
|
|
819
|
+
let value = value.trim();
|
|
820
|
+
if value.is_empty() || value.eq_ignore_ascii_case("none") {
|
|
821
|
+
Some(MacosTimestampConfig::Disabled)
|
|
822
|
+
} else {
|
|
823
|
+
Some(MacosTimestampConfig::Url(value.to_string()))
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
Some(JsonValue::Bool(true)) => Some(MacosTimestampConfig::Default),
|
|
827
|
+
Some(JsonValue::Bool(false)) => Some(MacosTimestampConfig::Disabled),
|
|
828
|
+
_ => None,
|
|
829
|
+
}
|
|
830
|
+
}
|
|
831
|
+
|
|
782
832
|
fn parse_macos_notarize_config(value: Option<&JsonValue>) -> MacosNotarizeConfig {
|
|
783
833
|
match value {
|
|
784
834
|
None => MacosNotarizeConfig::default(),
|
|
@@ -907,7 +957,13 @@ fn package_signing(
|
|
|
907
957
|
platform: &str,
|
|
908
958
|
) -> Result<(PackageSigningPlan, Vec<String>)> {
|
|
909
959
|
let mut warnings = Vec::new();
|
|
910
|
-
let sign = macos_sign_plan(
|
|
960
|
+
let sign = macos_sign_plan(
|
|
961
|
+
root,
|
|
962
|
+
&config.packager.osx_sign,
|
|
963
|
+
&config.packager.osx_notarize,
|
|
964
|
+
platform,
|
|
965
|
+
&mut warnings,
|
|
966
|
+
)?;
|
|
911
967
|
let notarize = macos_notarize_plan(root, config, platform, &mut warnings);
|
|
912
968
|
|
|
913
969
|
Ok((
|
|
@@ -921,6 +977,7 @@ fn package_signing(
|
|
|
921
977
|
fn macos_sign_plan(
|
|
922
978
|
root: &Path,
|
|
923
979
|
config: &MacosSignConfig,
|
|
980
|
+
notarize_config: &MacosNotarizeConfig,
|
|
924
981
|
platform: &str,
|
|
925
982
|
warnings: &mut Vec<String>,
|
|
926
983
|
) -> Result<MacosSignPlan> {
|
|
@@ -1008,6 +1065,9 @@ fn macos_sign_plan(
|
|
|
1008
1065
|
let ad_hoc_identity = matches!(identity, None | Some("-"));
|
|
1009
1066
|
let p12_identity = p12_file.is_some();
|
|
1010
1067
|
let will_execute = config.enabled && platform == "darwin" && (ad_hoc_identity || p12_identity);
|
|
1068
|
+
let timestamp_url = macos_timestamp_url(config, p12_identity, notarize_config.enabled);
|
|
1069
|
+
let for_notarization =
|
|
1070
|
+
will_execute && p12_identity && notarize_config.enabled && timestamp_url.is_some();
|
|
1011
1071
|
let method = if config.enabled && platform == "darwin" {
|
|
1012
1072
|
if p12_identity {
|
|
1013
1073
|
Some("certificate-p12".to_string())
|
|
@@ -1049,6 +1109,16 @@ fn macos_sign_plan(
|
|
|
1049
1109
|
"packagerConfig.osxSign.gatekeeperAssess is recognized but Gatekeeper assessment is not implemented yet.".to_string(),
|
|
1050
1110
|
);
|
|
1051
1111
|
}
|
|
1112
|
+
if config.timestamp.is_some() && !p12_identity {
|
|
1113
|
+
warnings.push(
|
|
1114
|
+
"packagerConfig.osxSign.timestamp is recognized but ignored without p12File certificate signing.".to_string(),
|
|
1115
|
+
);
|
|
1116
|
+
}
|
|
1117
|
+
if notarize_config.enabled && p12_identity && timestamp_url.is_none() {
|
|
1118
|
+
warnings.push(
|
|
1119
|
+
"macOS notarization requires a secure timestamp; packagerConfig.osxSign.timestamp disabled timestamping.".to_string(),
|
|
1120
|
+
);
|
|
1121
|
+
}
|
|
1052
1122
|
}
|
|
1053
1123
|
|
|
1054
1124
|
Ok(MacosSignPlan {
|
|
@@ -1062,6 +1132,8 @@ fn macos_sign_plan(
|
|
|
1062
1132
|
p12_password_env: config.p12_password_env.clone(),
|
|
1063
1133
|
p12_password_file,
|
|
1064
1134
|
p12_password: RedactedSecret::new(config.p12_password.clone()),
|
|
1135
|
+
timestamp_url,
|
|
1136
|
+
for_notarization,
|
|
1065
1137
|
entitlements,
|
|
1066
1138
|
entitlements_inherit,
|
|
1067
1139
|
hardened_runtime: config.hardened_runtime,
|
|
@@ -1069,6 +1141,24 @@ fn macos_sign_plan(
|
|
|
1069
1141
|
})
|
|
1070
1142
|
}
|
|
1071
1143
|
|
|
1144
|
+
fn macos_timestamp_url(
|
|
1145
|
+
config: &MacosSignConfig,
|
|
1146
|
+
p12_identity: bool,
|
|
1147
|
+
notarize_enabled: bool,
|
|
1148
|
+
) -> Option<String> {
|
|
1149
|
+
if !p12_identity {
|
|
1150
|
+
return None;
|
|
1151
|
+
}
|
|
1152
|
+
|
|
1153
|
+
match &config.timestamp {
|
|
1154
|
+
Some(MacosTimestampConfig::Default) => Some(APPLE_TIMESTAMP_URL.to_string()),
|
|
1155
|
+
Some(MacosTimestampConfig::Disabled) => None,
|
|
1156
|
+
Some(MacosTimestampConfig::Url(url)) => Some(url.clone()),
|
|
1157
|
+
None if notarize_enabled => Some(APPLE_TIMESTAMP_URL.to_string()),
|
|
1158
|
+
None => None,
|
|
1159
|
+
}
|
|
1160
|
+
}
|
|
1161
|
+
|
|
1072
1162
|
fn macos_notarize_plan(
|
|
1073
1163
|
root: &Path,
|
|
1074
1164
|
package_config: &PackageJsonConfig,
|
|
@@ -2259,6 +2349,7 @@ mod tests {
|
|
|
2259
2349
|
identity: 'Developer ID Application: Example, Inc. (TEAMID1234)',
|
|
2260
2350
|
p12File: 'developer-id.p12',
|
|
2261
2351
|
p12Password: 'p12-secret',
|
|
2352
|
+
timestamp: 'http://timestamp.example.test/tsa',
|
|
2262
2353
|
hardenedRuntime: true,
|
|
2263
2354
|
},
|
|
2264
2355
|
},
|
|
@@ -2293,6 +2384,11 @@ mod tests {
|
|
|
2293
2384
|
report.signing.macos.sign.p12_password_source.as_deref(),
|
|
2294
2385
|
Some("config")
|
|
2295
2386
|
);
|
|
2387
|
+
assert_eq!(
|
|
2388
|
+
report.signing.macos.sign.timestamp_url.as_deref(),
|
|
2389
|
+
Some("http://timestamp.example.test/tsa")
|
|
2390
|
+
);
|
|
2391
|
+
assert!(!report.signing.macos.sign.for_notarization);
|
|
2296
2392
|
assert!(report.signing.macos.sign.p12_file.is_some());
|
|
2297
2393
|
assert!(report
|
|
2298
2394
|
.warnings
|
|
@@ -2305,6 +2401,124 @@ mod tests {
|
|
|
2305
2401
|
let _ = fs::remove_dir_all(root);
|
|
2306
2402
|
}
|
|
2307
2403
|
|
|
2404
|
+
#[test]
|
|
2405
|
+
fn plans_macos_p12_signing_for_notarization_with_default_timestamp() {
|
|
2406
|
+
let root = unique_temp_dir("macos-p12-notarization-signing-plan");
|
|
2407
|
+
write_package_json(&root);
|
|
2408
|
+
fs::write(root.join("developer-id.p12"), "not a real p12")
|
|
2409
|
+
.expect("p12 placeholder should be written");
|
|
2410
|
+
fs::write(
|
|
2411
|
+
root.join("forge.config.js"),
|
|
2412
|
+
r#"
|
|
2413
|
+
module.exports = {
|
|
2414
|
+
packagerConfig: {
|
|
2415
|
+
appBundleId: 'com.example.notarized',
|
|
2416
|
+
osxSign: {
|
|
2417
|
+
p12File: 'developer-id.p12',
|
|
2418
|
+
p12PasswordEnv: 'P12_PASSWORD',
|
|
2419
|
+
},
|
|
2420
|
+
osxNotarize: {
|
|
2421
|
+
keychainProfile: 'notary-profile',
|
|
2422
|
+
},
|
|
2423
|
+
},
|
|
2424
|
+
};
|
|
2425
|
+
"#,
|
|
2426
|
+
)
|
|
2427
|
+
.expect("forge config should be written");
|
|
2428
|
+
write_app_file(&root);
|
|
2429
|
+
write_fake_electron_dist(&root);
|
|
2430
|
+
|
|
2431
|
+
let args = PackageArgs {
|
|
2432
|
+
cwd: root.clone(),
|
|
2433
|
+
out_dir: PathBuf::from("out"),
|
|
2434
|
+
name: None,
|
|
2435
|
+
platform: Some("darwin".to_string()),
|
|
2436
|
+
arch: Some("arm64".to_string()),
|
|
2437
|
+
force: false,
|
|
2438
|
+
dry_run: true,
|
|
2439
|
+
json: true,
|
|
2440
|
+
};
|
|
2441
|
+
let snapshot = crate::project::inspect(&root).expect("project should inspect");
|
|
2442
|
+
let report = build_report(snapshot, &args).expect("report should build");
|
|
2443
|
+
|
|
2444
|
+
assert!(report.signing.macos.sign.will_execute);
|
|
2445
|
+
assert_eq!(
|
|
2446
|
+
report.signing.macos.sign.timestamp_url.as_deref(),
|
|
2447
|
+
Some(APPLE_TIMESTAMP_URL)
|
|
2448
|
+
);
|
|
2449
|
+
assert!(report.signing.macos.sign.for_notarization);
|
|
2450
|
+
assert_eq!(
|
|
2451
|
+
report.signing.macos.notarize.auth_method.as_deref(),
|
|
2452
|
+
Some("keychain-profile")
|
|
2453
|
+
);
|
|
2454
|
+
assert!(!report
|
|
2455
|
+
.warnings
|
|
2456
|
+
.iter()
|
|
2457
|
+
.any(|warning| warning.contains("ad-hoc signing is not notarizable")));
|
|
2458
|
+
|
|
2459
|
+
let settings = macos_signing_settings(&report).expect("signing settings should build");
|
|
2460
|
+
assert!(settings.for_notarization());
|
|
2461
|
+
assert_eq!(
|
|
2462
|
+
settings.time_stamp_url().map(|url| url.as_str()),
|
|
2463
|
+
Some(APPLE_TIMESTAMP_URL)
|
|
2464
|
+
);
|
|
2465
|
+
|
|
2466
|
+
let json = serde_json::to_string(&report).expect("report should serialize");
|
|
2467
|
+
assert!(!json.contains("P12_PASSWORD="));
|
|
2468
|
+
|
|
2469
|
+
let _ = fs::remove_dir_all(root);
|
|
2470
|
+
}
|
|
2471
|
+
|
|
2472
|
+
#[test]
|
|
2473
|
+
fn warns_when_macos_notarization_timestamp_is_disabled() {
|
|
2474
|
+
let root = unique_temp_dir("macos-p12-notarization-no-timestamp");
|
|
2475
|
+
write_package_json(&root);
|
|
2476
|
+
fs::write(root.join("developer-id.p12"), "not a real p12")
|
|
2477
|
+
.expect("p12 placeholder should be written");
|
|
2478
|
+
fs::write(
|
|
2479
|
+
root.join("forge.config.js"),
|
|
2480
|
+
r#"
|
|
2481
|
+
module.exports = {
|
|
2482
|
+
packagerConfig: {
|
|
2483
|
+
osxSign: {
|
|
2484
|
+
p12File: 'developer-id.p12',
|
|
2485
|
+
timestamp: 'none',
|
|
2486
|
+
},
|
|
2487
|
+
osxNotarize: {
|
|
2488
|
+
keychainProfile: 'notary-profile',
|
|
2489
|
+
},
|
|
2490
|
+
},
|
|
2491
|
+
};
|
|
2492
|
+
"#,
|
|
2493
|
+
)
|
|
2494
|
+
.expect("forge config should be written");
|
|
2495
|
+
write_app_file(&root);
|
|
2496
|
+
write_fake_electron_dist(&root);
|
|
2497
|
+
|
|
2498
|
+
let args = PackageArgs {
|
|
2499
|
+
cwd: root.clone(),
|
|
2500
|
+
out_dir: PathBuf::from("out"),
|
|
2501
|
+
name: None,
|
|
2502
|
+
platform: Some("darwin".to_string()),
|
|
2503
|
+
arch: Some("arm64".to_string()),
|
|
2504
|
+
force: false,
|
|
2505
|
+
dry_run: true,
|
|
2506
|
+
json: true,
|
|
2507
|
+
};
|
|
2508
|
+
let snapshot = crate::project::inspect(&root).expect("project should inspect");
|
|
2509
|
+
let report = build_report(snapshot, &args).expect("report should build");
|
|
2510
|
+
|
|
2511
|
+
assert!(report.signing.macos.sign.will_execute);
|
|
2512
|
+
assert!(report.signing.macos.sign.timestamp_url.is_none());
|
|
2513
|
+
assert!(!report.signing.macos.sign.for_notarization);
|
|
2514
|
+
assert!(report
|
|
2515
|
+
.warnings
|
|
2516
|
+
.iter()
|
|
2517
|
+
.any(|warning| warning.contains("requires a secure timestamp")));
|
|
2518
|
+
|
|
2519
|
+
let _ = fs::remove_dir_all(root);
|
|
2520
|
+
}
|
|
2521
|
+
|
|
2308
2522
|
#[test]
|
|
2309
2523
|
fn warns_when_macos_notarization_is_configured_without_signing() {
|
|
2310
2524
|
let root = unique_temp_dir("notarize-without-sign");
|