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

Add Sentry for error reporting #443

Closed
wants to merge 16 commits into from
Closed
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
13 changes: 9 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ Please, check out guidelines: https://keepachangelog.com/en/1.0.0/
## Next

### Added

- `tuist graph` command https://github.com/tuist/tuist/pull/427 by @pepibumur.
- Allow customisation of `productName` in the project Manifest https://github.com/tuist/tuist/pull/435 by @ollieatkinson
- Adding support for static products depending on dynamic frameworks https://github.com/tuist/tuist/pull/439 by @kwridan
- Error tracking https://github.com/tuist/tuist/pull/443 by @pepibumur.

### Fixed

Expand All @@ -16,11 +18,13 @@ Please, check out guidelines: https://keepachangelog.com/en/1.0.0/
- Update manifest target name such that its product has a valid name https://github.com/tuist/tuist/pull/426 by @kwridan

### Changed

- Update XcodeProj to 7.0.0 https://github.com/tuist/tuist/pull/421 by @pepibumur.

## 0.16.0

### Added

- `DefaultSettings.none` to disable the generation of default build settings https://github.com/tuist/tuist/pull/395 by @pepibumur.
- Version information for tuistenv https://github.com/tuist/tuist/pull/399 by @ollieatkinson
- Add input & output paths for target action https://github.com/tuist/tuist/pull/353 by Rag0n
Expand All @@ -43,6 +47,7 @@ Please, check out guidelines: https://keepachangelog.com/en/1.0.0/
## 0.15.0

### Changed

- Introduce the `InfoPlist` file https://github.com/tuist/tuist/pull/373 by @pepibumur.
- Add `defaultSettings` option to `Settings` definition to control default settings generation https://github.com/tuist/tuist/pull/378 by @marciniwanicki

Expand All @@ -58,13 +63,13 @@ Please, check out guidelines: https://keepachangelog.com/en/1.0.0/
- Fixing unstable diff (products and embedded frameworks) https://github.com/tuist/tuist/pull/357 by @marciniwanicki
- Set Code Sign On Copy to true for Embed Frameworks https://github.com/tuist/tuist/pull/333 by @dangthaison91
- Fixing files getting mistaken for folders https://github.com/tuist/tuist/pull/338 by @kwridan
- Updating init template to avoid warnings https://github.com/tuist/tuist/pull/339 by @kwridan
- Fixing generation failures due to asset catalog & `**/*.png` glob patterns handling https://github.com/tuist/tuist/pull/346 by @kwridan
- Supporting bundle target dependencies that reside in different projects (in `TuistGenerator`) https://github.com/tuist/tuist/pull/348 by @kwridan
- Updating init template to avoid warnings https://github.com/tuist/tuist/pull/339 by @kwridan
- Fixing generation failures due to asset catalog & `**/*.png` glob patterns handling https://github.com/tuist/tuist/pull/346 by @kwridan
- Supporting bundle target dependencies that reside in different projects (in `TuistGenerator`) https://github.com/tuist/tuist/pull/348 by @kwridan
- Fixing header paths including folders and non-header files https://github.com/tuist/tuist/pull/356 by @kwridan
- Fix duplicate localized resource files https://github.com/tuist/tuist/pull/363 by @kwridan
- Update static dependency lint rule https://github.com/tuist/tuist/pull/360 by @kwridan
- Ensure resource bundles in other projects get built https://github.com/tuist/tuist/pull/374 by @kwridan
- Ensure resource bundles in other projects get built https://github.com/tuist/tuist/pull/374 by @kwridan

## 0.14.0

Expand Down
4 changes: 2 additions & 2 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ let package = Package(
),
.target(
name: "tuist",
dependencies: ["TuistKit"]
dependencies: ["TuistKit", "TuistCore"]
),
.target(
name: "TuistEnvKit",
Expand All @@ -52,7 +52,7 @@ let package = Package(
),
.target(
name: "tuistenv",
dependencies: ["TuistEnvKit"]
dependencies: ["TuistEnvKit", "TuistCore"]
),
.target(
name: "ProjectDescription",
Expand Down
21 changes: 19 additions & 2 deletions Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,26 @@ end
def package
print_section("Building tuist")
FileUtils.mkdir_p("build")
system("swift", "build", "--product", "tuist", "--configuration", "release")

link_args = []
build_cli_args = ["swift", "build", "--configuration", "release"]

build_tuist_args = build_cli_args.dup
build_tuist_args.concat(["--product", "tuist"])
build_tuist_args.concat(link_args)

build_tuistenv_args = build_cli_args.dup
build_tuistenv_args.concat(["--product", "tuistenv"])
build_tuistenv_args.concat(link_args)

# ProjectDescription
system("swift", "build", "--product", "ProjectDescription", "--configuration", "release")
system("swift", "build", "--product", "tuistenv", "--configuration", "release")

# Tuist
system(*build_tuist_args)

# Tuistenv
system(*build_tuistenv_args)

Dir.chdir(".build/release") do
system("zip", "-q", "-r", "--symlinks", "tuist.zip", "tuist", "ProjectDescription.swiftmodule", "ProjectDescription.swiftdoc", " libProjectDescription.dylib")
Expand Down
19 changes: 15 additions & 4 deletions Sources/TuistCore/Errors/ErrorHandler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,14 @@ public protocol ErrorHandling: AnyObject {
/// to the entity that conforms this protocol.
///
/// - Parameter error: Fatal error that should be handler.
func fatal(error: FatalError)
func fatal(error: FatalError, file: StaticString, line: UInt)
}

/// The default implementation of the ErrorHandling protocol
public final class ErrorHandler: ErrorHandling {
/// Shared instance of the error handler.
public static let shared: ErrorHandler = ErrorHandler()

// MARK: - Attributes

/// Printer to output information to the user.
Expand All @@ -32,8 +35,8 @@ public final class ErrorHandler: ErrorHandling {
/// Default error handler initializer.
///
/// - Parameters:
/// - printer: <#printer description#>
/// - exiter: <#exiter description#>
/// - printer: Printer to output information to the user.
/// - exiter: Instance to exit the process.
init(printer: Printing,
exiter: @escaping (Int32) -> Void) {
self.printer = printer
Expand All @@ -46,7 +49,7 @@ public final class ErrorHandler: ErrorHandling {
/// to the entity that conforms this protocol.
///
/// - Parameter error: Fatal error that should be handler.
public func fatal(error: FatalError) {
public func fatal(error: FatalError, file _: StaticString = #file, line _: UInt = #line) {
let isSilent = error.type == .abortSilent || error.type == .bugSilent
if !error.description.isEmpty, !isSilent {
printer.print(errorMessage: error.description)
Expand All @@ -57,6 +60,14 @@ public final class ErrorHandler: ErrorHandling {
"""
printer.print(errorMessage: message)
}

exiter(1)
}

/// Returns true if the user decided to disable the analytics by setting the TUIST_ANALYTICS_DISABLED environment variable.
///
/// - Returns: True if the analytics are disabled.
func isDisabled() -> Bool {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

cc @kwridan do you think this should be enough?

return ProcessInfo.processInfo.environment["TUIST_ANALYTICS_DISABLED"] != nil
}
}
10 changes: 10 additions & 0 deletions Sources/TuistCore/Errors/FatalError.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,16 @@ public enum ErrorType {
case bug
case abortSilent
case bugSilent

/// Returns true if the error is a bug.
var isBug: Bool {
switch self {
case .bug, .bugSilent:
return true
default:
return false
}
}
}

/// An error type that decorates an error that hasn't been handled.
Expand Down
7 changes: 7 additions & 0 deletions Sources/TuistCore/Utils/Printer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ public protocol Printing: AnyObject {
func print(error: Error)
func print(success: String)
func print(errorMessage: String)
func print(importantText: String)

/// Prints a deprecation message (yellow color)
///
Expand All @@ -30,6 +31,12 @@ public class Printer: Printing {
writer.write("\n")
}

public func print(importantText: String) {
let writer = InteractiveWriter.stdout
writer.write(importantText, inColor: .cyan, bold: true)
writer.write("\n")
}

public func print(_ text: String, color: TerminalController.Color) {
let writer = InteractiveWriter.stdout
writer.write(text, inColor: color, bold: false)
Expand Down
12 changes: 11 additions & 1 deletion Sources/TuistCoreTesting/Errors/MockErrorHandler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,21 @@ import TuistCore
import XCTest

public final class MockErrorHandler: ErrorHandling {
public var setupCallCount: UInt = 0
public var sendEnqueuedErrorsCallCount: UInt = 0
public var fatalErrorArgs: [FatalError] = []

public init() {}

public func fatal(error: FatalError) {
public func setup() throws {
setupCallCount += 1
}

public func fatal(error: FatalError, file _: StaticString = #file, line _: UInt = #line) {
fatalErrorArgs.append(error)
}

public func sendEnqueuedErrors() {
sendEnqueuedErrorsCallCount += 1
}
}
6 changes: 6 additions & 0 deletions Sources/TuistCoreTesting/Utils/MockPrinter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public final class MockPrinter: Printing {
public var printSuccessArgs: [String] = []
public var printWarningArgs: [String] = []
public var printDeprecationArgs: [String] = []
public var printImportantArgs: [String] = []

public func print(_ text: String) {
printArgs.append(text)
Expand Down Expand Up @@ -51,6 +52,11 @@ public final class MockPrinter: Printing {
standardError.append("\(error.localizedDescription)\n")
}

public func print(importantText: String) {
printImportantArgs.append(importantText)
standardOutput.append("\(importantText)\n")
}

public func print(success: String) {
printSuccessArgs.append(success)
standardOutput.append("\(success)\n")
Expand Down
6 changes: 3 additions & 3 deletions Sources/TuistEnvKit/Commands/CommandRegistry.swift
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public final class CommandRegistry {

// MARK: - Public

public func run() {
public func run(file: StaticString = #file, line: UInt = #line) {
do {
if processArguments().dropFirst().first == "--help-env" {
parser.printUsage(on: stdoutStream)
Expand All @@ -51,9 +51,9 @@ public final class CommandRegistry {
try commandRunner.run()
}
} catch let error as FatalError {
errorHandler.fatal(error: error)
errorHandler.fatal(error: error, file: file, line: line)
} catch {
errorHandler.fatal(error: UnhandledError(error: error))
errorHandler.fatal(error: UnhandledError(error: error), file: file, line: line)
}
}

Expand Down
20 changes: 20 additions & 0 deletions Sources/TuistEnvKit/Installer/BuildCopier.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@ import Foundation
import TuistCore

protocol BuildCopying: AnyObject {
/// Copies the frameworks under the project's Framework directory to the installation directory.
///
/// - Parameters:
/// - from: Absolute path to the project's Framework folder.
/// - to: Installation directory where the binaries are.
/// - Throws: An error if the copy of the frameworks fails.
func copy(from: AbsolutePath, to: AbsolutePath) throws
}

Expand All @@ -20,17 +26,31 @@ class BuildCopier: BuildCopying {

// MARK: - Attributes

/// Instance to interact with the file system.
private let fileHandler: FileHandling

/// Instance to run system tasks.
private let system: Systeming

// MARK: - Init

/// Initializes the build copier with its attributes.
///
/// - Parameters:
/// - fileHandler: <#fileHandler description#>
/// - system: <#system description#>
init(fileHandler: FileHandling = FileHandler(),
system: Systeming = System()) {
self.fileHandler = fileHandler
self.system = system
}

/// Copies the built arfifacts that are required to run Tuist.
///
/// - Parameters:
/// - from: Directory where all the artifacts have been built into (.build/release)
/// - to: Installation directory.
/// - Throws: An error if a required artifact hasn't been found or the copy task fails.
func copy(from: AbsolutePath, to: AbsolutePath) throws {
try BuildCopier.files.forEach { file in
let filePath = from.appending(component: file)
Expand Down
51 changes: 15 additions & 36 deletions Sources/TuistEnvKit/Installer/Installer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -92,14 +92,8 @@ final class Installer: Installing {
return
}

try verifySwiftVersion(version: version)

var bundleURL: URL?
do {
bundleURL = try self.bundleURL(version: version)
} catch {}

if let bundleURL = bundleURL {
if let release = githubRelease(version: version),
let bundleURL = bundleURL(release: release) {
try installFromBundle(bundleURL: bundleURL,
version: version,
temporaryDirectory: temporaryDirectory)
Expand All @@ -109,36 +103,17 @@ final class Installer: Installing {
}
}

func verifySwiftVersion(version: String) throws {
guard let localVersionString = try system.swiftVersion() else { return }
printer.print("Verifying the Swift version is compatible with your version \(localVersionString)")
var remoteVersionString: String!
do {
remoteVersionString = try githubClient.getContent(ref: version, path: ".swift-version").spm_chomp()
} catch is GitHubClientError {
printer.print(warning: "Couldn't get the Swift version needed for \(version). Continuing...")
}

let localVersion = SwiftVersion(localVersionString)
let remoteVersion = SwiftVersion(remoteVersionString)
let versionFive = SwiftVersion("5")

if localVersion >= versionFive, remoteVersion >= versionFive {
return
} else if localVersion == remoteVersion {
return
} else {
throw InstallerError.incompatibleSwiftVersion(local: localVersionString, expected: remoteVersionString)
}
}

func bundleURL(version: String) throws -> URL? {
func githubRelease(version: String) -> Release? {
guard let release = try? githubClient.release(tag: version) else {
printer.print(warning: "The release \(version) couldn't be obtained from GitHub")
return nil
}
return release
}

func bundleURL(release: Release) -> URL? {
guard let bundleAsset = release.assets.first(where: { $0.name == Constants.bundleName }) else {
printer.print(warning: "The release \(version) is not bundled")
printer.print(warning: "The release \(release.version) is not bundled")
return nil
}
return bundleAsset.downloadURL
Expand All @@ -151,12 +126,12 @@ final class Installer: Installing {

// Download bundle
printer.print("Downloading version from \(bundleURL.absoluteString)")
let downloadPath = temporaryDirectory.path.appending(component: Constants.bundleName)
try system.run("/usr/bin/curl", "-LSs", "--output", downloadPath.pathString, bundleURL.absoluteString)
let tuistDownloadPath = temporaryDirectory.path.appending(component: Constants.bundleName)
try system.run("/usr/bin/curl", "-LSs", "--output", tuistDownloadPath.pathString, bundleURL.absoluteString)

// Unzip
printer.print("Installing...")
try system.run("/usr/bin/unzip", "-q", downloadPath.pathString, "-d", installationDirectory.pathString)
try system.run("/usr/bin/unzip", "-q", tuistDownloadPath.pathString, "-d", installationDirectory.pathString)

try createTuistVersionFile(version: version, path: installationDirectory)
printer.print("Version \(version) installed")
Expand Down Expand Up @@ -189,6 +164,10 @@ final class Installer: Installing {
"--product", "tuist",
"--package-path", temporaryDirectory.path.pathString,
"--configuration", "release")
try system.run("install_name_tool",
"-add_rpath", "@executable_path",
buildDirectory.appending(component: "tuist").pathString)

try system.run(swiftPath, "build",
"--product", "ProjectDescription",
"--package-path", temporaryDirectory.path.pathString,
Expand Down
Loading