@hominis/fireforge 0.41.0 → 0.42.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.42.0
4
+
5
+ ### macOS bundle identity
6
+
7
+ - `MOZ_MACBUNDLE_ID` in the generated branding `configure.sh` now carries only the LEAF segment of `appId`, and the generated mozconfig emits `ac_add_options --with-distribution-id=<appId prefix>` — upstream `toolkit/moz.configure` composes `CFBundleIdentifier` as `<distribution-id>.<MOZ_MACBUNDLE_ID>`, so writing the full reverse-domain `appId` double-prefixed the shipped bundle id (observed: `org.mozilla.org.hominis.browser`). A `configure.sh` carrying the full `appId` now reads as stale and is rewritten.
8
+
3
9
  ## 0.41.0
4
10
 
5
11
  ### Release and build integrity
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "version": "0.41.0",
4
- "commit": "8d94512ea3928aa68b5525ddb73091fec73ce56c",
5
- "shortCommit": "8d94512ea392",
3
+ "version": "0.42.0",
4
+ "commit": "8200882a267f82974cd34356112990be0650c2ee",
5
+ "shortCommit": "8200882a267f",
6
6
  "dirty": false,
7
7
  "dirtyHash": null,
8
- "buildTime": "2026-08-15T22:42:44.650Z"
8
+ "buildTime": "2026-08-16T18:03:30.697Z"
9
9
  }
@@ -52,6 +52,22 @@ export interface BrandingConfig {
52
52
  */
53
53
  license?: ProjectLicense;
54
54
  }
55
+ /**
56
+ * Splits the reverse-domain `appId` for macOS bundle identity. Upstream
57
+ * `toolkit/moz.configure` composes `CFBundleIdentifier` as
58
+ * `<--with-distribution-id>.<MOZ_MACBUNDLE_ID>` (the distribution id
59
+ * defaults to `org.mozilla`), so branding `configure.sh` must carry only
60
+ * the LEAF segment while the generated mozconfig carries the remainder as
61
+ * `--with-distribution-id`. Writing the full appId into `MOZ_MACBUNDLE_ID`
62
+ * double-prefixes the shipped bundle id (observed:
63
+ * `org.mozilla.org.hominis.browser`, and with a distribution-id flag,
64
+ * `org.hominis.org.hominis.browser`). Config validation guarantees a
65
+ * reverse-domain id, so the split always has both halves.
66
+ */
67
+ export declare function splitAppId(appId: string): {
68
+ distributionId: string;
69
+ leaf: string;
70
+ };
55
71
  /**
56
72
  * Sets up the custom branding directory for the browser.
57
73
  *
@@ -53,6 +53,22 @@ export class BrandingMozconfigMismatchError extends FireForgeError {
53
53
  'The mismatch is caught before mach builds because resolving the build against the wrong branding tree fails deep in moz.build with a confusing "path does not exist" message.');
54
54
  }
55
55
  }
56
+ /**
57
+ * Splits the reverse-domain `appId` for macOS bundle identity. Upstream
58
+ * `toolkit/moz.configure` composes `CFBundleIdentifier` as
59
+ * `<--with-distribution-id>.<MOZ_MACBUNDLE_ID>` (the distribution id
60
+ * defaults to `org.mozilla`), so branding `configure.sh` must carry only
61
+ * the LEAF segment while the generated mozconfig carries the remainder as
62
+ * `--with-distribution-id`. Writing the full appId into `MOZ_MACBUNDLE_ID`
63
+ * double-prefixes the shipped bundle id (observed:
64
+ * `org.mozilla.org.hominis.browser`, and with a distribution-id flag,
65
+ * `org.hominis.org.hominis.browser`). Config validation guarantees a
66
+ * reverse-domain id, so the split always has both halves.
67
+ */
68
+ export function splitAppId(appId) {
69
+ const lastDot = appId.lastIndexOf('.');
70
+ return { distributionId: appId.slice(0, lastDot), leaf: appId.slice(lastDot + 1) };
71
+ }
56
72
  const MOZ_APP_VENDOR_IMPLY_REGEX = /imply_option\("MOZ_APP_VENDOR",\s*"[^"]*"\)/;
57
73
  const BRANDING_CONFIGURE_MANAGED_KEYS = new Set([
58
74
  'MOZ_APP_DISPLAYNAME',
@@ -107,7 +123,7 @@ function buildConfigureScriptContent(config, vendorPlacement, existingContent) {
107
123
  if (vendorPlacement === 'branding-configure') {
108
124
  managedLines.push(`MOZ_APP_VENDOR="${escapeShellValue(config.vendor)}"`);
109
125
  }
110
- managedLines.push(`MOZ_MACBUNDLE_ID="${escapeShellValue(config.appId)}"`);
126
+ managedLines.push(`MOZ_MACBUNDLE_ID="${escapeShellValue(splitAppId(config.appId).leaf)}"`);
111
127
  const preservedLines = existingContent ? extractPreservedConfigureLines(existingContent) : [];
112
128
  const body = [...managedLines, ...preservedLines].join('\n');
113
129
  return `${header}\n\n${body}\n`;
@@ -140,7 +156,7 @@ function isConfigureScriptCurrent(content, config, vendorPlacement) {
140
156
  if (assignments.get('MOZ_APP_DISPLAYNAME') !== `"${escapeShellValue(config.name)}"`) {
141
157
  return false;
142
158
  }
143
- if (assignments.get('MOZ_MACBUNDLE_ID') !== `"${escapeShellValue(config.appId)}"`) {
159
+ if (assignments.get('MOZ_MACBUNDLE_ID') !== `"${escapeShellValue(splitAppId(config.appId).leaf)}"`) {
144
160
  return false;
145
161
  }
146
162
  const vendorValue = assignments.get('MOZ_APP_VENDOR');
@@ -3,7 +3,7 @@ import { join } from 'node:path';
3
3
  import { MozconfigError } from '../errors/build.js';
4
4
  import { pathExists, readText, writeText } from '../utils/fs.js';
5
5
  import { getPlatform } from '../utils/platform.js';
6
- import { BrandingMozconfigMismatchError } from './branding.js';
6
+ import { BrandingMozconfigMismatchError, splitAppId } from './branding.js';
7
7
  /**
8
8
  * Replaces template variables in a string.
9
9
  * @param content - Content with ${variable} placeholders
@@ -95,6 +95,14 @@ export async function generateMozconfig(configsDir, engineDir, config) {
95
95
  binaryName: config.binaryName,
96
96
  };
97
97
  let content = '';
98
+ // Bundle identity: branding configure.sh carries only the LEAF of appId
99
+ // (see splitAppId in branding.ts — upstream composes the mac bundle id as
100
+ // <distribution-id>.<MOZ_MACBUNDLE_ID>); the prefix travels here so the
101
+ // two halves can never drift apart.
102
+ const { distributionId } = splitAppId(config.appId);
103
+ content +=
104
+ `# FireForge identity (generated from fireforge.json appId)\n` +
105
+ `ac_add_options --with-distribution-id=${distributionId}\n\n`;
98
106
  // Read common config if it exists
99
107
  if (await pathExists(commonPath)) {
100
108
  const commonContent = await readText(commonPath);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hominis/fireforge",
3
- "version": "0.41.0",
3
+ "version": "0.42.0",
4
4
  "description": "FireForge — a build tool for customizing Firefox",
5
5
  "type": "module",
6
6
  "main": "./dist/src/index.js",