Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion org.coloradomesh.MeshClient.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ modules:
pnpm_config_cache: /run/build/mesh-client/.npm
build-commands:
# Install pnpm standalone binary from archived release (no network needed).
# Archive extracts to pnpm-vendor/ so the bundled dist/ does not collide with app dist/.
# Archive extracts to pnpm-vendor/ (strip-components: 0) so the root `pnpm` binary is
# kept and the bundled dist/ does not collide with app dist/.
- install -Dm755 pnpm-vendor/pnpm /run/build/mesh-client/.pnpm-bin/pnpm
# Offline install using generated-sources.json (retries @jsr temp-dir races).
# --store-dir must use the sandbox-absolute path because the type:shell
Expand Down Expand Up @@ -81,11 +82,14 @@ modules:
url: https://github.com/pnpm/pnpm/releases/download/v11.15.1/pnpm-linux-x64.tar.gz
sha256: 0c1373b6390f6b89ff8b896d3647c9826577ddc49173a2f732da69b36569f9e0
dest: pnpm-vendor
# pnpm tarball has root-level `pnpm` + `dist/`; default strip-components:1 drops the binary.
strip-components: 0
only-arches: [x86_64]
- type: archive
url: https://github.com/pnpm/pnpm/releases/download/v11.15.1/pnpm-linux-arm64.tar.gz
sha256: 361e385867146972d0635a41a1871cb44c9c23f65acce78a5f1ca1d44ac0afcd
dest: pnpm-vendor
strip-components: 0
only-arches: [aarch64]
- type: archive
url: https://github.com/electron/electron/releases/download/v41.10.2/electron-v41.10.2-linux-x64.zip
Expand Down
9 changes: 6 additions & 3 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 8 additions & 3 deletions pnpm-workspace.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,15 @@ overrides:
'@meshtastic/core': npm:@jsr/meshtastic__core@^2.6.6
cacheable-request: ^10.0.0
form-data: ^4.0.6
js-yaml: ^4.2.0
# Security floors (Dependabot GHSA-52cp-r559-cp3m / GHSA-395f-4hp3-45gv /
# GHSA-w8wr-v893-vjvp / GHSA-3jxr-9vmj-r5cp). Keep majors separate for brace-expansion.
'brace-expansion@<1.1.16': 1.1.16
'brace-expansion@>=2.0.0 <2.1.2': 2.1.2
'brace-expansion@>=3.0.0 <5.0.7': 5.0.7
js-yaml: ^4.3.0
markdown-it@<=14.1.1: '>=14.2.0 <15'
shell-quote: ^1.8.4
tar: ^7.5.16
shell-quote: ^1.9.0
tar: ^7.5.18
tmp: ^0.2.6
undici: ^7.28.0
undici-types: ^7.28.0
Expand Down
18 changes: 18 additions & 0 deletions scripts/check-flatpak.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,24 @@ function checkManifestPnpmVersion(pkg) {
});
}

// pnpm 11+ ships tar.gz with root-level `pnpm` + `dist/`. flatpak-builder defaults to
// strip-components:1, which discards the binary (only dist/ contents remain under dest).
if (yaml.includes('pnpm-linux-') && yaml.includes('.tar.gz')) {
const pnpmArchiveBlocks = yaml
.split(/^\s*- type: archive\s*$/m)
.filter((block) => /pnpm-linux-.*\.tar\.gz/.test(block));
for (const block of pnpmArchiveBlocks) {
if (!/strip-components:\s*0\b/.test(block)) {
Comment on lines +147 to +152

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Match the actual YAML field exactly.

The current regex searches arbitrary block text, so a comment such as # strip-components: 0 or a value like strip-components: 0.5 can satisfy the check even though Flatpak will not receive the required setting. Anchor the pattern to a real strip-components property line (or parse the YAML) and require the exact numeric value 0.

Suggested fix
-      if (!/strip-components:\s*0\b/.test(block)) {
+      if (!/^[ \t]*strip-components:[ \t]*0[ \t]*(?:#.*)?$/m.test(block)) {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (yaml.includes('pnpm-linux-') && yaml.includes('.tar.gz')) {
const pnpmArchiveBlocks = yaml
.split(/^\s*- type: archive\s*$/m)
.filter((block) => /pnpm-linux-.*\.tar\.gz/.test(block));
for (const block of pnpmArchiveBlocks) {
if (!/strip-components:\s*0\b/.test(block)) {
if (yaml.includes('pnpm-linux-') && yaml.includes('.tar.gz')) {
const pnpmArchiveBlocks = yaml
.split(/^\s*- type: archive\s*$/m)
.filter((block) => /pnpm-linux-.*\.tar\.gz/.test(block));
for (const block of pnpmArchiveBlocks) {
if (!/^[ \t]*strip-components:[ \t]*0[ \t]*(?:#.*)?$/m.test(block)) {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/check-flatpak.mjs` around lines 147 - 152, The strip-components
validation in the pnpm archive block check must match an actual YAML property
with the exact numeric value 0. Update the regex used in the loop over
pnpmArchiveBlocks to anchor at the field line, allow YAML indentation, and
reject comments or values such as 0.5 while preserving the existing archive
filtering behavior.

violations.push({
file: rel,
message:
'pnpm linux tar.gz archive sources must set strip-components: 0 (default 1 drops root-level pnpm binary)',
});
break;
}
}
}

return violations;
}

Expand Down
30 changes: 28 additions & 2 deletions scripts/check-package-manager.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,26 @@ export function parsePackageManagerField(packageManager) {
return { name: 'pnpm', version: raw, ...parsed };
}

/**
* Prefer lifecycle user-agent (set while pnpm runs preinstall/dev) over PATH lookup.
* Windows `spawnSync('pnpm')` without `shell: true` cannot resolve `.cmd` shims.
* @param {string | undefined} userAgent
* @returns {string | null}
*/
export function pnpmVersionFromUserAgent(userAgent) {
if (typeof userAgent !== 'string' || !userAgent) return null;
const match = userAgent.match(/(?:^|\s)pnpm\/(\d+\.\d+\.\d+)/);
return match?.[1] ?? null;
}

/** @returns {boolean} */
export function hasCorepack() {
const res = spawnSync('corepack', ['--version'], { encoding: 'utf8', stdio: 'pipe' });
const res = spawnSync('corepack', ['--version'], {
encoding: 'utf8',
stdio: 'pipe',
// Windows: corepack is a .cmd shim; spawn without shell cannot resolve it.
shell: process.platform === 'win32',
});
return res.status === 0 && !res.error;
}

Expand Down Expand Up @@ -192,7 +209,16 @@ function readPackageJson(root = repoRoot) {
}

function currentPnpmVersion() {
const res = spawnSync('pnpm', ['--version'], { encoding: 'utf8', stdio: 'pipe' });
const fromUa = pnpmVersionFromUserAgent(process.env.npm_config_user_agent);
if (fromUa) return fromUa;

const res = spawnSync('pnpm', ['--version'], {
encoding: 'utf8',
stdio: 'pipe',
// Windows: pnpm/action-setup and Corepack install .cmd shims; without shell,
// spawnSync cannot find them and preinstall reports "You have: not found".
shell: process.platform === 'win32',
});
if (res.error || res.status !== 0) return null;
return String(res.stdout || '').trim() || null;
}
Expand Down
9 changes: 9 additions & 0 deletions scripts/check-package-manager.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
parseEngineFloor,
parsePackageManagerField,
parseSemver,
pnpmVersionFromUserAgent,
} from './check-package-manager.mjs';

describe('check-package-manager parseSemver', () => {
Expand Down Expand Up @@ -38,6 +39,14 @@ describe('check-package-manager parseEngineFloor', () => {
});
});

describe('check-package-manager pnpmVersionFromUserAgent', () => {
it('reads pnpm version from lifecycle user-agent', () => {
expect(pnpmVersionFromUserAgent('pnpm/11.15.1 npm/? node/v22.23.1 win32 x64')).toBe('11.15.1');
expect(pnpmVersionFromUserAgent('npm/10.9.0 node/v22.23.1')).toBeNull();
expect(pnpmVersionFromUserAgent(undefined)).toBeNull();
});
});

describe('check-package-manager upgrade hints', () => {
it('uses corepack when available', () => {
expect(buildPnpmUpgradeHintLines('11.15.1', { corepackAvailable: true })[0]).toBe(
Expand Down
1 change: 1 addition & 0 deletions scripts/sync-flatpak-electron.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const SAMPLE_MANIFEST = ` - type: archive
url: https://github.com/pnpm/pnpm/releases/download/v11.15.1/pnpm-linux-arm64.tar.gz
sha256: 361e385867146972d0635a41a1871cb44c9c23f65acce78a5f1ca1d44ac0afcd
dest: pnpm-vendor
strip-components: 0
only-arches: [aarch64]
- type: archive
url: https://github.com/electron/electron/releases/download/v41.10.0/electron-v41.10.0-linux-x64.zip
Expand Down