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
26 changes: 26 additions & 0 deletions cli/src/ios/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,3 +113,29 @@ export function getMajoriOSVersion(config: Config): string {
);
return iosVersion;
}

export function getMajorMinoriOSVersion(config: Config): string {
const pbx = readFileSync(join(config.ios.nativeXcodeProjDirAbs, 'project.pbxproj'), 'utf-8');
const searchString = 'IPHONEOS_DEPLOYMENT_TARGET = ';
const startIndex = pbx.indexOf(searchString);
if (startIndex === -1) {
return '';
}
const valueStart = startIndex + searchString.length;
// Extract until semicolon or newline (typical end of value in pbxproj)
const endIndex = pbx.indexOf(';', valueStart);
const newlineIndex = pbx.indexOf('\n', valueStart);
const actualEnd = endIndex !== -1 && newlineIndex !== -1
? Math.min(endIndex, newlineIndex)
: endIndex !== -1
? endIndex
: newlineIndex !== -1
? newlineIndex
: pbx.length;
let iosVersion = pbx.substring(valueStart, actualEnd).trim();
// Remove trailing .0 if present
if (iosVersion.endsWith('.0')) {
iosVersion = iosVersion.slice(0, -2);
}
Comment on lines +137 to +139
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

find . -name "common.ts" -path "*ios*" | head -5

Repository: Cap-go/capacitor-plus

Length of output: 88


🏁 Script executed:

head -150 ./cli/src/ios/common.ts | tail -20

Repository: Cap-go/capacitor-plus

Length of output: 733


🏁 Script executed:

sed -n '100,160p' ./cli/src/ios/common.ts

Repository: Cap-go/capacitor-plus

Length of output: 1730


🏁 Script executed:

find . -name "*.test.ts" -o -name "*.spec.ts" | xargs grep -l "getMajorMinoriOSVersion\|IPHONEOS_DEPLOYMENT_TARGET" 2>/dev/null

Repository: Cap-go/capacitor-plus

Length of output: 49


🏁 Script executed:

find . -type f \( -name "*.test.ts" -o -name "*.spec.ts" -o -name "*.test.js" -o -name "*.spec.js" \) | head -20

Repository: Cap-go/capacitor-plus

Length of output: 456


🏁 Script executed:

grep -n "getMajorMinoriOSVersion\|getMajoriOSVersion" ./cli/test/*.spec.ts 2>/dev/null

Repository: Cap-go/capacitor-plus

Length of output: 47


🏁 Script executed:

rg "getMajorMinoriOSVersion|getMajoriOSVersion" --type ts

Repository: Cap-go/capacitor-plus

Length of output: 705


🏁 Script executed:

sed -n '1,50p' ./cli/src/util/spm.ts

Repository: Cap-go/capacitor-plus

Length of output: 1939


🏁 Script executed:

grep -n -A 5 "getMajorMinoriOSVersion" ./cli/src/util/spm.ts

Repository: Cap-go/capacitor-plus

Length of output: 552


🏁 Script executed:

sed -n '90,130p' ./cli/src/util/spm.ts

Repository: Cap-go/capacitor-plus

Length of output: 1627


🏁 Script executed:

grep -r "getMajorMinoriOSVersion\|IPHONEOS_DEPLOYMENT_TARGET" ./cli/test/ --include="*.ts" --include="*.js"

Repository: Cap-go/capacitor-plus

Length of output: 47


🏁 Script executed:

sed -n '100,110p' ./cli/src/util/spm.ts

Repository: Cap-go/capacitor-plus

Length of output: 508


Trailing .0 removal logic is correct; add test coverage for version formats.

The logic properly handles iOS version formatting for SPM platform syntax:

  • 15.015 (uses .v15 enum syntax)
  • 15.515.5 (uses "15.5" string syntax)
  • 15.5.015.5 (uses "15.5" string syntax)

This function lacks test coverage. Add tests to the test suite verifying these version formats are correctly extracted and normalized:

describe('getMajorMinoriOSVersion', () => {
  it('should remove trailing .0 from versions', () => {
    // Test with mocked pbxproj containing "IPHONEOS_DEPLOYMENT_TARGET = 15.0;"
    // Expect: "15"
  });
  
  it('should preserve decimal versions', () => {
    // Test with "IPHONEOS_DEPLOYMENT_TARGET = 15.5;"
    // Expect: "15.5"
  });
  
  it('should handle three-part versions', () => {
    // Test with "IPHONEOS_DEPLOYMENT_TARGET = 15.5.0;"
    // Expect: "15.5"
  });
});
🤖 Prompt for AI Agents
In cli/src/ios/common.ts around lines 137 to 139, add unit tests covering
getMajorMinoriOSVersion behavior: create three tests that mock pbxproj content
with IPHONEOS_DEPLOYMENT_TARGET set to "15.0", "15.5", and "15.5.0"
respectively, assert the function returns "15", "15.5", and "15.5" (ensuring
trailing ".0" is removed and decimals preserved); place tests in the existing
iOS/common test file or create a new spec, mock or stub the file reading/parse
function used by getMajorMinoriOSVersion, and include assertions for each
expected normalized output.

return iosVersion;
}
Comment on lines +117 to +141
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Review the empty string return behavior and address the pipeline failure.

The function logic for extracting the iOS deployment target is sound, but there are a few concerns:

  1. Empty string return (Line 122): Returning an empty string when IPHONEOS_DEPLOYMENT_TARGET is not found will cause invalid Swift code generation in spm.ts (see my comment on that file). Consider either throwing an error or coordinating with the caller to handle this case.

  2. Pipeline failure: Prettier reports code style issues. Please run prettier --write cli/src/ios/common.ts to fix formatting.

Optional refactor to reduce duplication:

The logic overlaps significantly with getMajoriOSVersion (Lines 107-115). Consider refactoring to share the file reading and search logic:

export function getMajoriOSVersion(config: Config): string {
  const fullVersion = getMajorMinoriOSVersion(config);
  return fullVersion.split('.')[0] || fullVersion;
}

This would maintain backward compatibility while eliminating duplication.

🤖 Prompt for AI Agents
In cli/src/ios/common.ts around lines 117 to 141, the function currently returns
an empty string when IPHONEOS_DEPLOYMENT_TARGET is not found which leads to
invalid Swift code generation downstream; change this to throw a descriptive
Error (e.g., `throw new Error("IPHONEOS_DEPLOYMENT_TARGET not found in
project.pbxproj")`) so callers must handle it; after making that change, run
`prettier --write cli/src/ios/common.ts` to fix formatting; optionally refactor
getMajoriOSVersion to call getMajorMinoriOSVersion and derive the major part to
remove duplication.

6 changes: 3 additions & 3 deletions cli/src/util/spm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { extract } from 'tar';
import { getCapacitorPackageVersion } from '../common';
import type { Config } from '../definitions';
import { fatal } from '../errors';
import { getMajoriOSVersion } from '../ios/common';
import { getMajorMinoriOSVersion } from '../ios/common';
import { logger } from '../log';
import type { Plugin } from '../plugin';
import { getPluginType, PluginType } from '../plugin';
Expand Down Expand Up @@ -92,15 +92,15 @@ export async function removeCocoapodsFiles(config: Config): Promise<void> {

export async function generatePackageText(config: Config, plugins: Plugin[]): Promise<string> {
const iosPlatformVersion = await getCapacitorPackageVersion(config, config.ios.name);
const iosVersion = getMajoriOSVersion(config);
const iosVersion = getMajorMinoriOSVersion(config);

let packageSwiftText = `// swift-tools-version: 5.9
import PackageDescription

// DO NOT MODIFY THIS FILE - managed by Capacitor CLI commands
let package = Package(
name: "CapApp-SPM",
platforms: [.iOS(.v${iosVersion})],
platforms: [.iOS(${iosVersion.includes('.') ? `"${iosVersion}"` : `.v${iosVersion}`})],
Comment on lines +95 to +103
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Handle empty version string to prevent invalid Swift code generation.

If getMajorMinoriOSVersion returns an empty string (when IPHONEOS_DEPLOYMENT_TARGET is not found in the pbxproj), Line 103 will generate invalid Swift code: .iOS(.v). This would cause build failures.

Consider adding a fallback or validation:

  const iosVersion = getMajorMinoriOSVersion(config);
+ if (!iosVersion) {
+   fatal('Unable to determine iOS deployment target from project.pbxproj');
+ }

  let packageSwiftText = `// swift-tools-version: 5.9

Alternatively, provide a sensible default:

- const iosVersion = getMajorMinoriOSVersion(config);
+ const iosVersion = getMajorMinoriOSVersion(config) || '13';
📝 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
const iosVersion = getMajorMinoriOSVersion(config);
let packageSwiftText = `// swift-tools-version: 5.9
import PackageDescription
// DO NOT MODIFY THIS FILE - managed by Capacitor CLI commands
let package = Package(
name: "CapApp-SPM",
platforms: [.iOS(.v${iosVersion})],
platforms: [.iOS(${iosVersion.includes('.') ? `"${iosVersion}"` : `.v${iosVersion}`})],
const iosVersion = getMajorMinoriOSVersion(config) || '13';
let packageSwiftText = `// swift-tools-version: 5.9
import PackageDescription
// DO NOT MODIFY THIS FILE - managed by Capacitor CLI commands
let package = Package(
name: "CapApp-SPM",
platforms: [.iOS(${iosVersion.includes('.') ? `"${iosVersion}"` : `.v${iosVersion}`})],
🤖 Prompt for AI Agents
In cli/src/util/spm.ts around lines 95 to 103, the computed iosVersion may be an
empty string which causes invalid Swift `.iOS(.v)` output; add a
validation/fallback so that if iosVersion is falsy use a sensible default (e.g.
"15.0" or major 15) before building packageSwiftText, and then keep the existing
conditional formatting: if the version contains a dot emit the quoted string
`"15.0"`, otherwise emit `.v15`; ensure the fallback is applied so the generated
Swift is always valid.

products: [
.library(
name: "CapApp-SPM",
Expand Down
Loading