@hasna/recordings 0.3.1 → 0.3.2

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.
@@ -0,0 +1,99 @@
1
+ import Foundation
2
+ import Testing
3
+ @testable import RecordingsLib
4
+
5
+ /// Regression coverage for the bar-only successor lane (task 4ee4ebbf-9a10-4181-8e43-9307d56e684b).
6
+ ///
7
+ /// These lock the launch-plan control flow behind the terminated hasna/apps#269 lineage's P1
8
+ /// classes:
9
+ ///
10
+ /// - Cycle-1 P1: real launches of the installed bar never passed `--bar-only`, so the bar
11
+ /// binary was behaviorally identical to the full app. Fixed by making bar builds bar-only by
12
+ /// construction (`#if RECORDINGS_BAR_ONLY` compile-time default); the argument is now only a
13
+ /// self-describing launch record.
14
+ /// - Cycle-2 P1: the windowless branch keyed on `declaresMainWindow`, which excludes EVERY
15
+ /// runtime smoke, so the FULL build's smoke failed deterministically. Fixed by splitting the
16
+ /// conditions: `declaresWindow` (window creation may happen) excludes only the helper and bar
17
+ /// launches, while `declaresMainWindow` (auto-open / reopen) additionally excludes runtime
18
+ /// smoke so the smoke controls window creation deterministically.
19
+ struct BarOnlyLaunchPlanTests {
20
+ @Test("a bare launch follows the build variant")
21
+ func bareLaunchFollowsBuildVariant() {
22
+ let plan = PermissionRequestLaunchPlan(arguments: [])
23
+ #if RECORDINGS_BAR_ONLY
24
+ #expect(plan.isBarOnly, "a bar build must be bar-only by construction on a bare launch")
25
+ #expect(!plan.declaresWindow)
26
+ #expect(!plan.declaresMainWindow)
27
+ #else
28
+ #expect(!plan.isBarOnly, "a full build must launch with the workspace window")
29
+ #expect(plan.declaresWindow)
30
+ #expect(plan.declaresMainWindow)
31
+ #endif
32
+ #expect(plan.declaresMenuBar)
33
+ #expect(plan.installsGlobalHandlers)
34
+ }
35
+
36
+ @Test("the explicit bar argument makes any launch bar-only on a full build")
37
+ func explicitBarArgument() {
38
+ #if !RECORDINGS_BAR_ONLY
39
+ let plan = PermissionRequestLaunchPlan(arguments: ["--bar-only"])
40
+ #expect(plan.isBarOnly)
41
+ #expect(!plan.declaresWindow)
42
+ #expect(!plan.declaresMainWindow)
43
+ // The menu bar is still declared: the bar keeps the record controls, live
44
+ // transcription, paste delivery, and settings surfaces.
45
+ #expect(plan.declaresMenuBar)
46
+ #endif
47
+ }
48
+
49
+ @Test("a full build's normal-mode runtime smoke keeps exercising the workspace window")
50
+ func fullBuildRuntimeSmokePlan() {
51
+ let plan = PermissionRequestLaunchPlan(arguments: [
52
+ "--runtime-smoke", "normal",
53
+ "--runtime-smoke-output", "/tmp/smoke.json",
54
+ ])
55
+ #if RECORDINGS_BAR_ONLY
56
+ // On a bar build even the smoke is bar-only: the windowless branch keys on the
57
+ // build variant, not on the smoke mode.
58
+ #expect(plan.isBarOnly)
59
+ #expect(!plan.declaresWindow)
60
+ #else
61
+ // The cycle-2 P1 regression: a full build's smoke must still be able to create
62
+ // the workspace window, or every full build's smoke fails deterministically.
63
+ #expect(!plan.isBarOnly)
64
+ #expect(plan.declaresWindow, "the full-build smoke must exercise the workspace window")
65
+ #endif
66
+ // declaresMainWindow excludes runtime smoke in BOTH variants so the smoke controls
67
+ // window creation deterministically (no init auto-open, no reopen handler).
68
+ #expect(!plan.declaresMainWindow)
69
+ #expect(plan.isRuntimeSmoke)
70
+ #expect(plan.declaresMenuBar, "the smoke must observe the live menu bar surface")
71
+ }
72
+
73
+ @Test("a bar plan keeps the menu bar and global handlers but never declares a window")
74
+ func barPlanKeepsMenuBarAndGlobalHandlers() {
75
+ let plan = PermissionRequestLaunchPlan(arguments: ["--bar-only"])
76
+ #expect(plan.installsGlobalHandlers)
77
+ #expect(plan.declaresMenuBar)
78
+ #expect(plan.isBarOnly)
79
+ #expect(!plan.declaresWindow)
80
+ #expect(!plan.declaresMainWindow)
81
+ }
82
+
83
+ @Test("declaresMainWindow excludes runtime smoke, helper, and bar launches")
84
+ func declaresMainWindowExcludesRuntimeSmoke() {
85
+ for arguments in [
86
+ ["--runtime-smoke", "normal"],
87
+ ["--runtime-smoke", "permission-helper"],
88
+ ["--request-permissions"],
89
+ ["--bar-only"],
90
+ ] {
91
+ let plan = PermissionRequestLaunchPlan(arguments: arguments)
92
+ #expect(!plan.declaresMainWindow)
93
+ }
94
+ let plain = PermissionRequestLaunchPlan(arguments: [])
95
+ #if !RECORDINGS_BAR_ONLY
96
+ #expect(plain.declaresMainWindow)
97
+ #endif
98
+ }
99
+ }
@@ -83,7 +83,7 @@ fi
83
83
  readonly RELEASE_SUBTYPE
84
84
  RELEASE_ARCHITECTURES=(arm64 x86_64)
85
85
 
86
- CODESIGN_IDENTITY="${RECORDINGS_CODESIGN_IDENTITY:-}"
86
+ CODESIGN_IDENTITY="${RECORDINGS_CODESIGN_IDENTITY:-${HASNA_CODESIGN_IDENTITY:-}}"
87
87
  EXPECTED_TEAM_ID="${RECORDINGS_EXPECTED_TEAM_IDENTIFIER:-}"
88
88
  NOTARY_PROFILE="${RECORDINGS_NOTARY_KEYCHAIN_PROFILE:-}"
89
89
  INSTALLER_IDENTITY="${RECORDINGS_INSTALLER_CODESIGN_IDENTITY:-}"
@@ -96,6 +96,41 @@ COMPATIBLE_COHORT_MANIFEST="${RECORDINGS_RELEASE_COMPATIBLE_COHORT_MANIFEST:-}"
96
96
  LOCAL_APPROVED_TARGET="${RECORDINGS_LOCAL_APPROVED_TARGET:-}"
97
97
  LOCAL_APPROVED_TARGET_IDENTITY_KIND="${RECORDINGS_LOCAL_APPROVED_TARGET_IDENTITY_KIND:-}"
98
98
  LOCAL_APPROVED_TARGET_IDENTITY_SHA256="${RECORDINGS_LOCAL_APPROVED_TARGET_IDENTITY_SHA256:-}"
99
+ VARIANT="${RECORDINGS_VARIANT:-full}"
100
+ case "$VARIANT" in
101
+ full|bar) ;;
102
+ *)
103
+ echo "RECORDINGS_VARIANT must be full or bar; got: $VARIANT" >&2
104
+ exit 2
105
+ ;;
106
+ esac
107
+ if [ "$MODE" = "release" ] && [ "$VARIANT" = "bar" ]; then
108
+ # The bar variant is a deliberate product change (no workspace window, accessory
109
+ # launch); a release that carries it must be explicitly marked so a default release
110
+ # can never silently emit a bar artifact.
111
+ if [ "${RECORDINGS_RELEASE_BAR_VARIANT_MARKED:-0}" != "1" ]; then
112
+ echo "release-mode bar-variant builds require RECORDINGS_RELEASE_BAR_VARIANT_MARKED=1 to proceed explicitly." >&2
113
+ exit 2
114
+ fi
115
+ fi
116
+ readonly VARIANT
117
+ VARIANT_SWIFT_FLAGS=()
118
+ if [ "$VARIANT" = "bar" ]; then
119
+ VARIANT_SWIFT_FLAGS=(-Xswiftc -DRECORDINGS_BAR_ONLY)
120
+ fi
121
+ # Fleet naming rule (knowledge k_msxd5rz3_jfvl3i): every Hasna macOS app is
122
+ # Hasna<Name>.app with 'Hasna' at the beginning. The full app keeps its historical
123
+ # Recordings.app name (its rename is the rule's recorded follow-up decision); the
124
+ # bar-only artifact is named per the rule NOW — HasnaRecordings.app. The 'bar' is the
125
+ # variant, never a separate app name: bundle identifier stays com.hasna.recordings so
126
+ # TCC keeps keying on bundle id + signing identity, and the executable inside the
127
+ # bundle stays "Recordings".
128
+ APP_BUNDLE_NAME="Recordings.app"
129
+ if [ "$VARIANT" = "bar" ]; then
130
+ APP_BUNDLE_NAME="HasnaRecordings.app"
131
+ fi
132
+ readonly APP_BUNDLE_NAME
133
+ APP_BASENAME="${APP_BUNDLE_NAME%.app}"
99
134
  PLIST_BUDDY="$(select_executable "/usr/libexec/PlistBuddy" "${RECORDINGS_TEST_PLIST_BUDDY_EXECUTABLE:-${PLIST_BUDDY:-}}")"
100
135
  PLUTIL="$(select_executable "/usr/bin/plutil" "${RECORDINGS_TEST_PLUTIL_EXECUTABLE:-${PLUTIL:-}}")"
101
136
  BUN_EXECUTABLE="${BUN_EXECUTABLE:-}"
@@ -134,6 +169,48 @@ LIPO_EXECUTABLE="$(select_executable "/usr/bin/lipo" "${RECORDINGS_TEST_LIPO_EXE
134
169
  STAT_EXECUTABLE="$(select_executable "/usr/bin/stat" "${RECORDINGS_TEST_STAT_EXECUTABLE:-}")"
135
170
  TEST_GIT_EXECUTABLE="$(select_executable "" "${RECORDINGS_TEST_GIT_EXECUTABLE:-}")"
136
171
  TEST_SWIFT_EXECUTABLE="$(select_executable "" "${RECORDINGS_TEST_SWIFT_EXECUTABLE:-}")"
172
+ SECURITY_EXECUTABLE="$(select_executable "/usr/bin/security" "${RECORDINGS_TEST_SECURITY_EXECUTABLE:-}")"
173
+
174
+ # Developer ID signing identity support. The identity comes from RECORDINGS_CODESIGN_IDENTITY
175
+ # (legacy) or HASNA_CODESIGN_IDENTITY (canonical name), and when neither is supplied the
176
+ # keychain is consulted with `security find-identity -v -p codesigning` and the first
177
+ # "Developer ID Application:" identity is used. Signing NEVER silently falls back to ad-hoc
178
+ # when a Developer ID was requested: release builds always require one, and a local build
179
+ # with RECORDINGS_SIGNING_REQUIRED=1 fails loudly when none exists.
180
+ discover_developer_id_identity() {
181
+ local listing
182
+ listing="$("$SECURITY_EXECUTABLE" find-identity -v -p codesigning 2>/dev/null)" || return 0
183
+ printf '%s\n' "$listing" | "$AWK_EXECUTABLE" -F'"' '/Developer ID Application:/ { print $2; exit }'
184
+ }
185
+
186
+ derive_team_id() {
187
+ local identity="$1"
188
+ local team_id
189
+ team_id="$(printf '%s\n' "$identity" | "$SED_EXECUTABLE" -n 's/.*(\([A-Z0-9]\{10\}\))$/\1/p')"
190
+ if ! [[ "$team_id" =~ ^[A-Z0-9]{10}$ ]]; then
191
+ echo "Could not derive a 10-character Developer ID team from the signing identity: $identity" >&2
192
+ return 1
193
+ fi
194
+ printf '%s\n' "$team_id"
195
+ }
196
+
197
+ resolve_signing_identity() {
198
+ # Called when no explicit identity was supplied. Fails loudly when a Developer ID
199
+ # was requested but none can be found; the caller decides whether one was requested.
200
+ if [ "$HOST_PLATFORM" != "Darwin" ]; then
201
+ return 0
202
+ fi
203
+ local discovered
204
+ discovered="$(discover_developer_id_identity)"
205
+ if [ -z "$discovered" ]; then
206
+ echo "Developer ID signing was requested but no Developer ID Application identity found in the keychain; never silently ad-hoc when a Developer ID is requested." >&2
207
+ return 1
208
+ fi
209
+ CODESIGN_IDENTITY="$discovered"
210
+ if [ -z "$EXPECTED_TEAM_ID" ]; then
211
+ EXPECTED_TEAM_ID="$(derive_team_id "$CODESIGN_IDENTITY")" || return 1
212
+ fi
213
+ }
137
214
 
138
215
  require_executable() {
139
216
  local label="$1"
@@ -253,6 +330,7 @@ require_executable "ID_EXECUTABLE" "$ID_EXECUTABLE"
253
330
  require_executable "STAT_EXECUTABLE" "$STAT_EXECUTABLE"
254
331
  if [ "$HOST_PLATFORM" = "Darwin" ]; then
255
332
  require_executable "LIPO_EXECUTABLE" "$LIPO_EXECUTABLE"
333
+ require_executable "SECURITY_EXECUTABLE" "$SECURITY_EXECUTABLE"
256
334
  fi
257
335
  require_bun_executable "$BUN_EXECUTABLE"
258
336
  if [ "$MODE" = "release" ]; then
@@ -545,11 +623,23 @@ run_codesign() {
545
623
  }
546
624
 
547
625
  run_swift() {
626
+ # VARIANT_SWIFT_FLAGS is empty for every full build (the default). A bare
627
+ # "${arr[@]}" on an EMPTY array under `set -u` aborts bash < 4.4 — macOS
628
+ # /bin/bash is 3.2.57 — with `unbound variable`, which killed every build the
629
+ # moment the flags existed. The ${arr[0]+"${arr[@]}"} guard is the script-wide
630
+ # idiom (see run_bun, run_xcrun, run_release_sensitive_tool); do not reintroduce
631
+ # a bare expansion here.
632
+ #
633
+ # The flags are arguments TO swift (after the executable), never before it:
634
+ # placed before the executable they would be consumed by /usr/bin/env as its
635
+ # own options and the build would die with `env: '-Xswiftc': No such file`.
548
636
  "$ENV_EXECUTABLE" -i \
549
637
  HOME="$BUILD_HOME" \
550
638
  PATH="$SANITIZED_PATH" \
551
639
  TMPDIR="$BUILD_WORK_DIR" \
552
- "$SWIFT_EXECUTABLE" "$@"
640
+ "$SWIFT_EXECUTABLE" \
641
+ ${VARIANT_SWIFT_FLAGS[0]+"${VARIANT_SWIFT_FLAGS[@]}"} \
642
+ "$@"
553
643
  }
554
644
 
555
645
  run_lipo() {
@@ -939,8 +1029,19 @@ BUILDER_IDENTITY_KIND="none"
939
1029
  BUILDER_IDENTITY_SHA256="none"
940
1030
  if [ "$MODE" = "release" ]; then
941
1031
  if [ -z "$CODESIGN_IDENTITY" ] || [ "$CODESIGN_IDENTITY" = "-" ]; then
942
- echo "Release builds require RECORDINGS_CODESIGN_IDENTITY for a Developer ID Application identity." >&2
943
- exit 1
1032
+ # No explicit identity: discover the Developer ID Application identity from the
1033
+ # keychain. Release signing is never optional, so "requested but not found" fails
1034
+ # loudly instead of degrading to an ad-hoc signature.
1035
+ if [ "$HOST_PLATFORM" = "Darwin" ]; then
1036
+ resolve_signing_identity || {
1037
+ echo "Release builds require a Developer ID Application identity in RECORDINGS_CODESIGN_IDENTITY or HASNA_CODESIGN_IDENTITY." >&2
1038
+ exit 1
1039
+ }
1040
+ fi
1041
+ if [ -z "$CODESIGN_IDENTITY" ] || [ "$CODESIGN_IDENTITY" = "-" ]; then
1042
+ echo "Release builds require RECORDINGS_CODESIGN_IDENTITY or HASNA_CODESIGN_IDENTITY for a Developer ID Application identity." >&2
1043
+ exit 1
1044
+ fi
944
1045
  fi
945
1046
  if [ -z "$EXPECTED_TEAM_ID" ]; then
946
1047
  echo "Release builds require RECORDINGS_EXPECTED_TEAM_IDENTIFIER to pin the Developer ID team." >&2
@@ -1075,6 +1176,31 @@ elif [ "$MODE" = "local" ]; then
1075
1176
  # a release is notarization, the single-target binding, and the builder attestation
1076
1177
  # above, none of which are relaxed. With no identity supplied the old ad-hoc behaviour
1077
1178
  # is kept verbatim, because a Mac without the signing key must still be able to build.
1179
+ if [ -z "$CODESIGN_IDENTITY" ] || [ "$CODESIGN_IDENTITY" = "-" ]; then
1180
+ if [ "${RECORDINGS_SIGNING_REQUIRED:-0}" = "1" ]; then
1181
+ # A Developer ID was explicitly requested for this local build: discover it
1182
+ # from the keychain and fail loudly when none exists.
1183
+ resolve_signing_identity || exit 1
1184
+ elif [ "$HOST_PLATFORM" = "Darwin" ]; then
1185
+ # The DEFAULT route is the keychain: `security find-identity` and use the
1186
+ # Developer ID Application identity when one exists. That is the stable
1187
+ # signing identity TCC grants key on — an ad-hoc signature has no identity
1188
+ # to key on beyond a CDHash that changes on every rebuild, which orphans
1189
+ # the Accessibility grant and breaks the Fn hold-to-talk path. A Mac
1190
+ # without the signing key still builds ad-hoc (the old behaviour), but the
1191
+ # fallback is LOUD, never silent, and RECORDINGS_SIGNING_REQUIRED=1 above
1192
+ # turns it into a hard failure.
1193
+ discovered_identity="$(discover_developer_id_identity)"
1194
+ if [ -n "$discovered_identity" ]; then
1195
+ CODESIGN_IDENTITY="$discovered_identity"
1196
+ if [ -z "$EXPECTED_TEAM_ID" ]; then
1197
+ EXPECTED_TEAM_ID="$(derive_team_id "$CODESIGN_IDENTITY")" || exit 1
1198
+ fi
1199
+ else
1200
+ echo "WARNING: no Developer ID Application identity found in the keychain; local build falls back to ad-hoc signing (set RECORDINGS_SIGNING_REQUIRED=1 to fail instead)." >&2
1201
+ fi
1202
+ fi
1203
+ fi
1078
1204
  if [ -n "$CODESIGN_IDENTITY" ] && [ "$CODESIGN_IDENTITY" != "-" ]; then
1079
1205
  if [[ "$CODESIGN_IDENTITY" != "Developer ID Application:"* ]]; then
1080
1206
  echo "Local-station signing requires a Developer ID Application identity in RECORDINGS_CODESIGN_IDENTITY." >&2
@@ -1140,9 +1266,9 @@ if [ "$MODE" = "release" ]; then
1140
1266
  else
1141
1267
  OUTPUT_BUILD_DIR="$SCRIPT_DIR/.build/$BUILD_CONFIGURATION"
1142
1268
  fi
1143
- OUTPUT_APP_DIR="$OUTPUT_BUILD_DIR/Recordings.app"
1269
+ OUTPUT_APP_DIR="$OUTPUT_BUILD_DIR/$APP_BUNDLE_NAME"
1144
1270
  SWIFT_PRODUCT_DIR="$SWIFT_SCRATCH_PATH/$BUILD_CONFIGURATION"
1145
- APP_DIR="$BUILD_WORK_DIR/Recordings.app"
1271
+ APP_DIR="$BUILD_WORK_DIR/$APP_BUNDLE_NAME"
1146
1272
  CONTENTS="$APP_DIR/Contents"
1147
1273
  MACOS="$CONTENTS/MacOS"
1148
1274
  RESOURCES="$CONTENTS/Resources"
@@ -1300,6 +1426,16 @@ if [ "$MODE" = "release" ] && [ "$HOST_PLATFORM" = "Darwin" ]; then
1300
1426
  fi
1301
1427
  fi
1302
1428
  "$CP_EXECUTABLE" "$SOURCE_NATIVE_DIR/RecordingsLib/Info.plist" "$CONTENTS/Info.plist"
1429
+ if [ "$VARIANT" = "bar" ]; then
1430
+ # The bar is an accessory app: LSUIElement keeps it out of the Dock and the app
1431
+ # switcher, and the app's window-declaring control flow (RECORDINGS_BAR_ONLY)
1432
+ # keeps the workspace window absent. The bundle identifier stays com.hasna.recordings
1433
+ # so TCC grants continue to key on bundle id + signing identity, and the bundle is
1434
+ # named per the fleet rule (knowledge k_msxd5rz3_jfvl3i) — HasnaRecordings.app with
1435
+ # the display name "Hasna Recordings"; 'Hasna' at the beginning of the name.
1436
+ "$PLIST_BUDDY" -c 'Add :LSUIElement bool true' "$CONTENTS/Info.plist"
1437
+ "$PLIST_BUDDY" -c 'Set :CFBundleDisplayName Hasna Recordings' "$CONTENTS/Info.plist"
1438
+ fi
1303
1439
  VERSION="$("$PLIST_BUDDY" -c 'Print :CFBundleShortVersionString' "$CONTENTS/Info.plist")"
1304
1440
 
1305
1441
  compute_release_publication_identity() {
@@ -1313,6 +1449,7 @@ compute_release_publication_identity() {
1313
1449
  --component "release_sequence=$RELEASE_SEQUENCE"
1314
1450
  --component "key_epoch=$KEY_EPOCH"
1315
1451
  --component "expires_at_utc=$ENVELOPE_EXPIRES_AT_UTC"
1452
+ --component "variant=$VARIANT"
1316
1453
  )
1317
1454
  identity_arguments+=(--component "envelope_public_key_sha256=$ENVELOPE_PUBLIC_KEY_SHA256")
1318
1455
  if [ "$RELEASE_SUBTYPE" = "initial-bootstrap" ]; then
@@ -1331,7 +1468,7 @@ compute_release_publication_identity() {
1331
1468
 
1332
1469
  reserve_release_output() {
1333
1470
  local release_set_basename reserved_output
1334
- release_set_basename="Recordings-${VERSION}-macos-${RELEASE_SUBTYPE}"
1471
+ release_set_basename="${APP_BASENAME}-${VERSION}-macos-${RELEASE_SUBTYPE}"
1335
1472
  compute_release_publication_identity
1336
1473
  RELEASE_OUTPUT_ROOT="$OUTPUT_BUILD_DIR"
1337
1474
  RELEASE_FINAL_DIR="$RELEASE_OUTPUT_ROOT/${release_set_basename}.release"
@@ -1398,7 +1535,7 @@ reserve_release_output() {
1398
1535
  RELEASE_STAGING_DIR="$($MKTEMP_EXECUTABLE -d "$RELEASE_OUTPUT_ROOT/.${release_set_basename}.staging.XXXXXX")"
1399
1536
  "$CHMOD_EXECUTABLE" 0700 "$RELEASE_STAGING_DIR"
1400
1537
  OUTPUT_BUILD_DIR="$RELEASE_STAGING_DIR"
1401
- OUTPUT_APP_DIR="$OUTPUT_BUILD_DIR/Recordings.app"
1538
+ OUTPUT_APP_DIR="$OUTPUT_BUILD_DIR/$APP_BUNDLE_NAME"
1402
1539
  }
1403
1540
 
1404
1541
  if [ "$MODE" = "release" ]; then
@@ -1586,6 +1723,7 @@ if [ "$MODE" != "debug" ]; then
1586
1723
  --team-id "$EXPECTED_TEAM_ID" \
1587
1724
  --package-root "$PACKAGE_ROOT" \
1588
1725
  --artifact-policy "$ARTIFACT_POLICY" \
1726
+ --variant "$VARIANT" \
1589
1727
  --approved-target "$APPROVED_TARGET" \
1590
1728
  --approved-target-identity-kind "$APPROVED_TARGET_IDENTITY_KIND" \
1591
1729
  --approved-target-identity-sha256 "$APPROVED_TARGET_IDENTITY_SHA256" \
@@ -1643,7 +1781,7 @@ run_codesign --verify --deep --strict --verbose=2 "$APP_DIR"
1643
1781
  TMPDIR="$BUILD_WORK_DIR" \
1644
1782
  SSH_CONNECTION="${SSH_CONNECTION:-}" \
1645
1783
  ${SMOKE_TEST_ENVIRONMENT[0]+"${SMOKE_TEST_ENVIRONMENT[@]}"} \
1646
- "$BASH_EXECUTABLE" "$SMOKE_SCRIPT" "$APP_DIR" "$BUN_EXECUTABLE"
1784
+ "$BASH_EXECUTABLE" "$SMOKE_SCRIPT" "$APP_DIR" "$BUN_EXECUTABLE" --variant "$VARIANT"
1647
1785
 
1648
1786
  publish_app_output() {
1649
1787
  local source_tree_digest
@@ -1807,7 +1945,7 @@ publish_complete_release_set() {
1807
1945
  RELEASE_DIRECTORY_PUBLISHED=1
1808
1946
  RELEASE_STAGING_DIR=""
1809
1947
  OUTPUT_BUILD_DIR="$RELEASE_FINAL_DIR"
1810
- OUTPUT_APP_DIR="$OUTPUT_BUILD_DIR/Recordings.app"
1948
+ OUTPUT_APP_DIR="$OUTPUT_BUILD_DIR/$APP_BUNDLE_NAME"
1811
1949
  run_bun "$SOURCE_PACKAGE_ROOT/scripts/macos_artifact.ts" complete-release-publication \
1812
1950
  --destination "$RELEASE_FINAL_DIR" \
1813
1951
  --reservation "$RELEASE_RESERVATION" \
@@ -1833,7 +1971,7 @@ if [ "$MODE" = "debug" ]; then
1833
1971
  fi
1834
1972
 
1835
1973
  if [ "$MODE" = "local" ]; then
1836
- ARTIFACT_BASENAME="Recordings-${VERSION}-macos-${APPROVED_TARGET}-local-only"
1974
+ ARTIFACT_BASENAME="${APP_BASENAME}-${VERSION}-macos-${APPROVED_TARGET}-local-only"
1837
1975
  FINAL_ARCHIVE="$OUTPUT_BUILD_DIR/${ARTIFACT_BASENAME}.zip"
1838
1976
  FINAL_MANIFEST="$OUTPUT_BUILD_DIR/${ARTIFACT_BASENAME}.manifest.json"
1839
1977
  "$RM_EXECUTABLE" -f "$FINAL_ARCHIVE" "$FINAL_MANIFEST"
@@ -1846,6 +1984,7 @@ if [ "$MODE" = "local" ]; then
1846
1984
  --archive "$FINAL_ARCHIVE" \
1847
1985
  --manifest "$FINAL_MANIFEST" \
1848
1986
  --package-root "$PACKAGE_ROOT" \
1987
+ --variant "$VARIANT" \
1849
1988
  --approved-target "$APPROVED_TARGET" \
1850
1989
  --approved-target-identity-kind "$APPROVED_TARGET_IDENTITY_KIND" \
1851
1990
  --approved-target-identity-sha256 "$APPROVED_TARGET_IDENTITY_SHA256" \
@@ -1860,7 +1999,7 @@ fi
1860
1999
 
1861
2000
  verify_signed_code "$HELPERS/recordings" "Companion CLI"
1862
2001
  verify_signed_code "$APP_DIR" "Recordings.app"
1863
- ARTIFACT_BASENAME="Recordings-${VERSION}-macos-${RELEASE_SUBTYPE}"
2002
+ ARTIFACT_BASENAME="${APP_BASENAME}-${VERSION}-macos-${RELEASE_SUBTYPE}"
1864
2003
  NOTARY_ARCHIVE="$OUTPUT_BUILD_DIR/${ARTIFACT_BASENAME}-notarization.zip"
1865
2004
  FINAL_ARCHIVE="$OUTPUT_BUILD_DIR/${ARTIFACT_BASENAME}.zip"
1866
2005
  FINAL_MANIFEST="$OUTPUT_BUILD_DIR/${ARTIFACT_BASENAME}.manifest.json"
@@ -1923,6 +2062,7 @@ run_bun "$SOURCE_PACKAGE_ROOT/scripts/macos_artifact.ts" finalize \
1923
2062
  --manifest "$FINAL_MANIFEST" \
1924
2063
  --package-root "$PACKAGE_ROOT" \
1925
2064
  --team-id "$EXPECTED_TEAM_ID" \
2065
+ --variant "$VARIANT" \
1926
2066
  --notary-log "$NOTARY_LOG" \
1927
2067
  --notary-submission-id "$NOTARY_ID" \
1928
2068
  --submitted-archive-sha256 "$NOTARY_ARCHIVE_SHA256"