Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Xcode integration for Swift Package Plugins #2554

Merged
merged 10 commits into from
Oct 11, 2022
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
17 changes: 14 additions & 3 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -95,15 +95,25 @@ commands:
- run:
working_directory: Tests/CodegenCLITests/pod-install-test/
command: pod install --verbose
name: Install Pod (verbose)
name: CocoaPods - Install
- run:
working_directory: Tests/CodegenCLITests/pod-install-test/Pods/Apollo/
command: ./apollo-ios-cli init --schema-name NewTestSchema
name: Test init
name: CocoaPods - CLI Test (init)
- run:
working_directory: Tests/CodegenCLITests/pod-install-test/Pods/Apollo/
command: ./apollo-ios-cli generate
name: Test generate
name: CocoaPods - CLI Test (generate)
swiftpm_plugin_test:
steps:
- run:
working_directory: Tests/CodegenCLITests/swiftpm-test/
command: swift build
name: SwiftPM - Build package
- run:
working_directory: Tests/CodegenCLITests/swiftpm-test/
command: swift package plugin --allow-writing-to-package-directory apollo-generate --verbose
Copy link
Member Author

Choose a reason for hiding this comment

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

We only test the generate command here because we needed have an existing JSON config file to prevent codegen finding all the test graphQL definition files in the .build folder. We're going to fix that behaviour in #2552.

name: SwiftPM - Plugin Test (generate)
save-xcodebuild-artifacts:
description: Save artifacts logs, crash reports and test results generated by xcodebuild
steps:
Expand Down Expand Up @@ -223,6 +233,7 @@ jobs:
steps:
- common_test_setup
- cocoapods_install_test
- swiftpm_plugin_test

workflows:
version: 2
Expand Down
4 changes: 4 additions & 0 deletions Apollo.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -718,6 +718,7 @@
E6203346284F252A00A291D1 /* MockUnionsFileGeneratorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6203345284F252A00A291D1 /* MockUnionsFileGeneratorTests.swift */; };
E6203348284F25DF00A291D1 /* MockUnionsTemplateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6203347284F25DF00A291D1 /* MockUnionsTemplateTests.swift */; };
E623FD2A2797A6F4008B4CED /* InterfaceTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E623FD292797A6F4008B4CED /* InterfaceTemplate.swift */; };
E639F20528F0A8FA00441FF4 /* IgnoredOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = E639F20428F0A8FA00441FF4 /* IgnoredOptions.swift */; };
E63F0C0328EE0F2A009069EA /* ApolloCodegenFrontendBundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = E63F0C0028EE099A009069EA /* ApolloCodegenFrontendBundle.swift */; };
E64F226D28B8B3FE0011292F /* LogLevelSetter.swift in Sources */ = {isa = PBXBuildFile; fileRef = E64F226C28B8B3FE0011292F /* LogLevelSetter.swift */; };
E64F227128B8BEE10011292F /* MockLogLevelSetter.swift in Sources */ = {isa = PBXBuildFile; fileRef = E64F227028B8BEE10011292F /* MockLogLevelSetter.swift */; };
Expand Down Expand Up @@ -1852,6 +1853,7 @@
E6203347284F25DF00A291D1 /* MockUnionsTemplateTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockUnionsTemplateTests.swift; sourceTree = "<group>"; };
E623FD292797A6F4008B4CED /* InterfaceTemplate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InterfaceTemplate.swift; sourceTree = "<group>"; };
E623FD2B2797A700008B4CED /* InterfaceTemplateTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InterfaceTemplateTests.swift; sourceTree = "<group>"; };
E639F20428F0A8FA00441FF4 /* IgnoredOptions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IgnoredOptions.swift; sourceTree = "<group>"; };
E63F0C0028EE099A009069EA /* ApolloCodegenFrontendBundle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApolloCodegenFrontendBundle.swift; sourceTree = "<group>"; };
E64F226C28B8B3FE0011292F /* LogLevelSetter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogLevelSetter.swift; sourceTree = "<group>"; };
E64F227028B8BEE10011292F /* MockLogLevelSetter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockLogLevelSetter.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -3927,6 +3929,7 @@
isa = PBXGroup;
children = (
E687B3CC28B398E600A9551C /* InputOptions.swift */,
E639F20428F0A8FA00441FF4 /* IgnoredOptions.swift */,
);
path = OptionGroups;
sourceTree = "<group>";
Expand Down Expand Up @@ -5690,6 +5693,7 @@
E687B3E828B398E600A9551C /* SchemaDownloadProvider.swift in Sources */,
E64F226D28B8B3FE0011292F /* LogLevelSetter.swift in Sources */,
E687B3E428B398E600A9551C /* Initialize.swift in Sources */,
E639F20528F0A8FA00441FF4 /* IgnoredOptions.swift in Sources */,
E687B3E128B398E600A9551C /* String+Data.swift in Sources */,
E687B3DD28B398E600A9551C /* InputOptions.swift in Sources */,
E687B3E728B398E600A9551C /* CodegenProvider.swift in Sources */,
Expand Down
3 changes: 0 additions & 3 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,6 @@ let package = Package(
exclude: [
"Info.plist",
"Frontend/JavaScript",
],
Copy link
Member Author

Choose a reason for hiding this comment

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

This was forgotten about in #2548 resulting in a warning in Xcode.

resources: [
.copy("Frontend/dist/ApolloCodegenFrontend.bundle.js"),
]),
.target(
name: "ApolloSQLite",
Expand Down
21 changes: 15 additions & 6 deletions Plugins/ApolloCodegenPlugin-Fetch/ApolloCodegenPluginFetch.swift
Original file line number Diff line number Diff line change
@@ -1,13 +1,22 @@
import Foundation
import PackagePlugin

@main struct ApolloCodegenPluginFetch: CommandPlugin {
@main struct ApolloCodegenPluginFetch: CodegenCommand {
static var commandName: String = "fetch-schema"
}

extension ApolloCodegenPluginFetch: CommandPlugin {
func performCommand(context: PluginContext, arguments: [String]) async throws {
let process = Process()
process.executableURL = try context.codegenExecutable
process.arguments = ["fetch-schema"] + arguments
try performCommand(contextProvider: context, arguments: arguments)
}
}

#if canImport(XcodeProjectPlugin)
import XcodeProjectPlugin

try process.run()
process.waitUntilExit()
extension ApolloCodegenPluginFetch: XcodeCommandPlugin {
func performCommand(context: XcodePluginContext, arguments: [String]) throws {
try performCommand(contextProvider: context, arguments: arguments)
}
}
#endif

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,13 +1,22 @@
import Foundation
import PackagePlugin

@main struct ApolloCodegenPluginGenerate: CommandPlugin {
@main struct ApolloCodegenPluginGenerate: CodegenCommand {
static var commandName: String = "generate"
}

extension ApolloCodegenPluginGenerate: CommandPlugin {
func performCommand(context: PluginContext, arguments: [String]) async throws {
let process = Process()
process.executableURL = try context.codegenExecutable
process.arguments = ["generate"] + arguments
try performCommand(contextProvider: context, arguments: arguments)
}
}

#if canImport(XcodeProjectPlugin)
import XcodeProjectPlugin

try process.run()
process.waitUntilExit()
extension ApolloCodegenPluginGenerate: XcodeCommandPlugin {
func performCommand(context: XcodePluginContext, arguments: [String]) throws {
try performCommand(contextProvider: context, arguments: arguments)
}
}
#endif

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,13 +1,22 @@
import Foundation
import PackagePlugin

@main struct ApolloCodegenPluginInitialize: CommandPlugin {
@main struct ApolloCodegenPluginInitialize: CodegenCommand {
static var commandName: String = "init"
}

extension ApolloCodegenPluginInitialize: CommandPlugin {
func performCommand(context: PluginContext, arguments: [String]) async throws {
let process = Process()
process.executableURL = try context.codegenExecutable
process.arguments = ["init"] + arguments
try performCommand(contextProvider: context, arguments: arguments)
}
}

#if canImport(XcodeProjectPlugin)
import XcodeProjectPlugin

try process.run()
process.waitUntilExit()
extension ApolloCodegenPluginInitialize: XcodeCommandPlugin {
func performCommand(context: XcodePluginContext, arguments: [String]) throws {
try performCommand(contextProvider: context, arguments: arguments)
}
}
#endif

This file was deleted.

18 changes: 18 additions & 0 deletions Plugins/SharedPackageFiles/CodegenCommand.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import Foundation

protocol CodegenCommand {
static var commandName: String { get }

func performCommand(contextProvider: PluginContextProvider, arguments: [String]) throws
}

extension CodegenCommand {
func performCommand(contextProvider: PluginContextProvider, arguments: [String]) throws {
let process = Process()
process.executableURL = try contextProvider.codegenExecutable
process.arguments = [Self.commandName] + arguments

try process.run()
process.waitUntilExit()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import Foundation
import PackagePlugin

protocol PluginContextProvider {
func tool(named name: String) throws -> PackagePlugin.PluginContext.Tool
}

extension PluginContextProvider {
var codegenExecutable: URL {
get throws {
let executable = try tool(named: "apollo-ios-cli")
return URL(fileURLWithPath: executable.path.string)
}
}
}

extension PluginContext: PluginContextProvider {}

#if canImport(XcodeProjectPlugin)
import XcodeProjectPlugin

extension XcodePluginContext: PluginContextProvider {}
#endif

This file was deleted.

1 change: 1 addition & 0 deletions Sources/CodegenCLI/Commands/FetchSchema.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ public struct FetchSchema: ParsableCommand {
)

@OptionGroup var inputs: InputOptions
@OptionGroup var ignored: IgnoredOptions

// MARK: - Implementation

Expand Down
1 change: 1 addition & 0 deletions Sources/CodegenCLI/Commands/Generate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ public struct Generate: ParsableCommand {
)

@OptionGroup var inputs: InputOptions
@OptionGroup var ignored: IgnoredOptions

@Flag(
name: .shortAndLong,
Expand Down
2 changes: 2 additions & 0 deletions Sources/CodegenCLI/Commands/Initialize.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ public struct Initialize: ParsableCommand {
abstract: "Initialize a new configuration with defaults."
)

@OptionGroup var ignored: IgnoredOptions

@Option(
name: [.long, .customShort("n")],
help: "Name used to scope the generated schema type files."
Expand Down
19 changes: 19 additions & 0 deletions Sources/CodegenCLI/OptionGroups/IgnoredOptions.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import ArgumentParser

/// Shared group of arguments that are sent by various automation tools, such as Xcode, but are
/// ignored from input.
struct IgnoredOptions: ParsableArguments {
@Option(
name: .long,
help: ArgumentHelp(
"Ignored - used by Xcode only.",
discussion: """
Xcode will automatically include this option when calling any plugin command to pass the
target name of the Swift package. This option is ignored and is not intended to be sent
by anything other than Xcode.
""",
visibility: .hidden
)
)
var target: String?
}
24 changes: 24 additions & 0 deletions Tests/CodegenCLITests/swiftpm-test/Package.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// swift-tools-version: 5.7
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let package = Package(
name: "swiftpm-test",
platforms: [.macOS(.v10_15)],
products: [
.library(
name: "swiftpm-test",
targets: ["swiftpm-test"]),
],
dependencies: [
.package(name: "apollo-ios", path: "../../.."),
],
targets: [
.target(
name: "swiftpm-test",
dependencies: [
.product(name: "Apollo", package: "apollo-ios"),
]),
]
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
public struct swiftpm_test {
public private(set) var text = "Hello, World!"

public init() {
}
}
29 changes: 29 additions & 0 deletions Tests/CodegenCLITests/swiftpm-test/apollo-codegen-config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"schemaName" : "NewTestSchema",
"input" : {
"operationSearchPaths" : [
"./graphql/**/*.graphql"
],
"schemaSearchPaths" : [
"./graphql/**/*.graphqls"
]
},
"output" : {
"testMocks" : {
"none" : {
}
},
"schemaTypes" : {
"path" : "./NewTestSchema",
"moduleType" : {
"embeddedInTarget" : {
"name": "swiftpm_test"
}
}
},
"operations" : {
"relative" : {
}
}
}
}
8 changes: 8 additions & 0 deletions Tests/CodegenCLITests/swiftpm-test/graphql/operation.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
query AllBooks {
books {
title
author {
name
}
}
}
14 changes: 14 additions & 0 deletions Tests/CodegenCLITests/swiftpm-test/graphql/schema.graphqls
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
type Book {
title: String
author: Author
}

type Author {
name: String
books: [Book]
}

type Query {
books: [Book]
authors: [Author]
}
14 changes: 13 additions & 1 deletion docs/source/code-generation/codegen-cli.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,19 @@ When Apollo iOS is included as a dependency through Swift Package Manager (SPM)

Each package manager deploys the Codegen CLI using different methods. To learn how to run the Codegen CLI with your chosen package manager, open the appropriate section:

<ExpansionPanel title="Swift Package Manager">
<ExpansionPanel title="Swift Package Manager - Xcode">

When using Swift packages through Xcode, Apollo iOS exposes the Codegen CLI as SPM plugins which are available from the Xcode menu.

After adding the Apollo iOS package as a dependency for your Xcode project, right-click on your project and at the bottom of the menu you will find an 'Apollo' labeled group of menu items that are the plugin commands. Clicking on any of these will present another screen where you are able to add any custom arguments.

<img class="screenshot" src="../screenshot/xcode_menu_plugins.png" alt="Where to find the SPM plugin commands in Xcode" />

See [Usage](#usage) for a list of all commands and their options.

</ExpansionPanel>

<ExpansionPanel title="Swift Package Manager - Package.swift file">

When using Swift Package Manager, Apollo iOS exposes the Codegen CLI as an SPM plugin. This means you can run the Codegen CLI using the `swift package` command.

Expand Down
Binary file added docs/source/screenshot/xcode_menu_plugins.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.