feat: Extend Swift FileFetcher for Xcode-managed SwiftPM (.xcodeproj) support#14332
Open
markhallen wants to merge 8 commits intomainfrom
Open
feat: Extend Swift FileFetcher for Xcode-managed SwiftPM (.xcodeproj) support#14332markhallen wants to merge 8 commits intomainfrom
markhallen wants to merge 8 commits intomainfrom
Conversation
Add five fixture projects covering different Xcode SPM configurations: - xcode_project: single .xcodeproj with Package.resolved - xcode_project_multiple: two .xcodeproj directories - xcode_project_nested: .xcodeproj in a subdirectory - xcode_project_no_resolved: .xcodeproj without Package.resolved - xcode_project_with_manifest: both Package.swift and .xcodeproj
…dencies Behind the :enable_swift_xcode_spm feature flag, the FileFetcher now: - Recursively scans for .xcodeproj directories - Fetches project.pbxproj as a support file - Fetches Package.resolved from the Xcode shared workspace data - Falls back to standard Package.swift flow when present - Skips irrelevant directories (.git, .build, Pods, node_modules, etc.) When the flag is disabled, behavior is unchanged.
Cover all Xcode SPM scenarios with the feature flag enabled: - Single .xcodeproj with Package.resolved - Multiple .xcodeproj directories - Nested .xcodeproj in subdirectories - Coexistence with Package.swift (classic flow takes priority) - .xcodeproj without Package.resolved (raises error) - Flag disabled with .xcodeproj only (raises error)
Contributor
There was a problem hiding this comment.
Pull request overview
Adds experimental Swift FileFetcher support to discover Xcode-managed SwiftPM dependency files (inside .xcodeproj bundles) when :enable_swift_xcode_spm is enabled, while keeping the classic Package.swift flow intact.
Changes:
- Extend Swift
FileFetcherto (optionally) scan for.xcodeprojdirectories and fetchproject.pbxproj(support file) plus the Xcode SwiftPMPackage.resolved. - Update Swift FileFetcher behavior to not immediately error when
Package.swiftis absent (so Xcode-only repos can be inspected under the flag). - Add RSpec coverage and fixtures for single/multiple/nested
.xcodeprojscenarios and mixed repos.
Reviewed changes
Copilot reviewed 15 out of 15 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| swift/lib/dependabot/swift/file_fetcher.rb | Adds feature-flagged .xcodeproj discovery + fetch logic, plus required-files logic updates and a memoization fix. |
| swift/spec/dependabot/swift/file_fetcher_spec.rb | Adds test coverage for flag-enabled/disabled behavior and various .xcodeproj layouts. |
| swift/spec/fixtures/projects/xcode_project_with_manifest/* | Fixture repo containing both classic Package.swift + Package.resolved and an .xcodeproj SwiftPM resolved file. |
| swift/spec/fixtures/projects/xcode_project/* | Fixture repo containing an .xcodeproj with project.pbxproj and Xcode SwiftPM Package.resolved. |
| swift/spec/fixtures/projects/xcode_project_multiple/* | Fixture repo with multiple .xcodeproj directories each containing SwiftPM resolved/pbxproj files. |
| swift/spec/fixtures/projects/xcode_project_nested/* | Fixture repo with a nested .xcodeproj SwiftPM resolved/pbxproj under a subdirectory. |
| swift/spec/fixtures/projects/xcode_project_no_resolved/* | Fixture repo with .xcodeproj but no SwiftPM Package.resolved (invalid case). |
Comments suppressed due to low confidence (1)
swift/lib/dependabot/swift/file_fetcher.rb:54
- The comment about the base class validating against
required_files_in?is a bit misleading:Dependabot::FileFetchers::Base#filesraisesDependencyFileNotFoundearly whenfetch_filesreturns an empty array, before callingrequired_files_in?. Consider updating/removing this comment or raising a more specific error from here when neitherPackage.swiftnor any Xcode SwiftPM files are found.
# Base class validates returned files against required_files_in? and raises if needed
return fetched_files unless Dependabot::Experiments.enabled?(:enable_swift_xcode_spm)
- Revert required_files_in? to always require Package.swift, preventing xcodeproj-only repos from passing validation when the parser still requires Package.swift (avoids downstream DependencyFileNotFound) - Simplify required_files_message (no experiment check needed) - Reduce MAX_SCAN_DEPTH from 10 to 3 (xcodeproj is rarely >3 levels deep) - Add MAX_XCODEPROJ_RESULTS = 5 with early exit to bound API calls - Update tests: xcodeproj-only scenarios now expect DependencyFileNotFound
… fixture - Replace recursive scan_for_xcodeproj_dirs with a single repo_contents call on the configured directory, matching existing fetcher behavior - Remove MAX_SCAN_DEPTH, MAX_XCODEPROJ_RESULTS, SKIP_DIRECTORIES constants - Remove Pathname require (no longer needed) - Remove xcode_project_nested fixture (no longer applicable) - Restore flag-gated required_files_in? and required_files_message (the parser mismatch is expected; parser support comes in a follow-up)
5 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What are you trying to accomplish?
This adds support for discovering Swift Package Manager dependencies managed through Xcode projects (
.xcodeproj), behind the:enable_swift_xcode_spmfeature flag.Currently, the Swift FileFetcher only supports repos with a top-level
Package.swiftmanifest. Many iOS/macOS projects use Xcode's built-in SwiftPM integration instead, where dependency pins live at.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolvedand package references are declared inproject.pbxproj. This change allows Dependabot to discover and fetch those files.Relates to #7694
Anything you want to highlight for special attention from reviewers?
Dependabot::Experiments.enabled?(:enable_swift_xcode_spm). When disabled, the FileFetcher behaves identically to before.package_manifestchanged fromfetch_file_from_hosttofetch_file_if_present: This is necessary so that repos withoutPackage.swiftdon't raise immediately. The base class validation (required_files_in?) still catches repos that have neitherPackage.swiftnor a valid.xcodeproj.package_resolvedwas using=instead of||=— fixed as part of this PR (pre-existing bug).scan_for_xcodeproj_dirswalks the repo tree up to 10 levels deep, skipping directories like.git,.build,Pods,node_modules, andvendorthat are unlikely to contain Xcode projects.project.pbxprojfetched as support file: It's needed for future parsing ofXCRemoteSwiftPackageReferenceentries but isn't a primary dependency file.Package.resolved: A.xcodeprojwithout aPackage.resolvedis not considered valid — there are no dependency pins to work with.How will you know you've accomplished your goal?
.xcodeproj, coexistence withPackage.swift, missingPackage.resolved, and flag-disabled behavior."a dependency file fetcher"examples continue to pass, confirming no new public instance methods were added.Checklist