Skip to content

Commit

Permalink
🚀 Version 5.1
Browse files Browse the repository at this point in the history
Merge branch 'dev/5.x'
  • Loading branch information
nicoverbruggen committed Mar 2, 2022
2 parents d046946 + 6a8d667 commit 768bf06
Show file tree
Hide file tree
Showing 77 changed files with 1,528 additions and 745 deletions.
14 changes: 14 additions & 0 deletions DEVELOPER.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,20 @@ Once you have downloaded this repository, open `PHP Monitor.xcodeproj`, and you

If you'd like to create a production build, choose "Any Mac" as the target and select Product > Archive.

## 🚀 Release procedure

1. Merge into `main`
2. Create tag
3. Add changes to changelog + update security document
4. Archive
5. Notarize and prepare for own distribution
6. After notarization, export .app
7. Create zipped version
8. Calculate SHA256: `openssl dgst -sha256 phpmon.zip`
9. Upload to GitHub and add to tagged release
10. Update Cask with new version + hash
11. Check new version can be installed via Cask

## 🐛 Symbolication of crashes

If you have an archived build of the app and exported the DSYM, it is possible to symbolicate .ips crash logs.
Expand Down
141 changes: 104 additions & 37 deletions PHP Monitor.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

23 changes: 19 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,13 @@ To upgrade your existing installation, run:

brew upgrade phpmon

(You may need to run `brew update` first in order to update the cask file if you ran a Homebrew operation recently.)
(You may need to run `brew update` or `brew update-reset` first in order to update the cask file if you ran a Homebrew operation recently.)

## ⚡️ Launchers (Alfred, Raycast)

If you would like to integrate with your launcher of choice, you can also download an [Alfred workflow](https://github.com/nicoverbruggen/phpmon/raw/main/integrations/phpmon.alfredworkflow) or [Raycast extension](https://www.raycast.com/nicoverbruggen/php-monitor) that works with PHP Monitor.

The app must be running in the background for these to work, and the _Allow third-party integrations_ checkbox must be enabled in Preferences (it is by default).

## 🔑 Is the app signed & notarized?

Expand Down Expand Up @@ -231,8 +237,15 @@ Since v3.4 all of the loaded .ini files are sourced to determine which extension
<details>
<summary><strong>I've got two Homebrew installations on my Apple Silicon Mac, can I choose which installation to use with PHP Monitor?</strong></summary>

Not at this time, no. PHP Monitor will prefer the `/opt/homebrew` installation over the classic installation directory.
If you are using PHP Monitor on an Intel machine or on an Apple Silicon machine with Rosetta enabled, PHP Monitor expects the main Homebrew binary in `/usr/local/bin/brew`.

If you are using PHP Monitor on Apple Silicon without Rosetta, PHP Monitor expects the main Homebrew binary in `/opt/homebrew/bin/brew`.

If there's an issue here, you'll get an alert at launch.

Make sure that the version of Homebrew that you are running normally is the same as the one that PHP Monitor expects. If you are on M1 hardware for example, but still using Rosetta for Homebrew, you'll need to run PHP Monitor under Rosetta as well.

PHP Monitor is a universal app and supports both architectures, so [find out here](https://support.apple.com/en-us/HT211861) how to enable Rosetta with PHP Monitor.
</details>

<details>
Expand Down Expand Up @@ -267,9 +280,11 @@ You can put as many apps as you'd like in the `scan_apps` array, and PHP Monitor
</details>

<details>
<summary><strong>How can the app integrate with third party tools, like Alfred?</strong></summary>
<summary><strong>How can the app integrate with third party tools, like Alfred or Raycast?</strong></summary>

PHP Monitor supports third party app integrations by default, and this feature is enabled in Preferences unless you disable it.

There's an Alfred workflow usually included in the release list, you can grab it by going to releases and downloading the asset `phpmon.alfredworkflow`.
You can grab the official [Alfred workflow](https://github.com/nicoverbruggen/phpmon/raw/main/integrations/phpmon.alfredworkflow) or [Raycast extension](https://www.raycast.com/nicoverbruggen/php-monitor).

If you'd like to integrate something yourself, all you need to to is use the `phpmon://` protocol and ensure that third party app integrations are enabled in Preferences (in PHP Monitor).

Expand Down
13 changes: 0 additions & 13 deletions RELEASE.md

This file was deleted.

2 changes: 1 addition & 1 deletion SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Generally speaking, only the latest version of **PHP Monitor** is supported, exc

| Version | Apple Silicon | Supported | Supported macOS | Deployment Target | Detected PHP Versions | Minimum Required Valet Version |
| ------- | ------------- | ------------------ | ----- | ----- | ----- | ----
| 5.0 | ✅ Universal binary | ✅ Yes | Big Sur (11.0) and Monterey (12.0) | macOS 11+ | PHP 5.6—PHP 8.2 | 2.16.2 |
| 5 | ✅ Universal binary | ✅ Yes | Big Sur (11.0) and Monterey (12.0) | macOS 11+ | PHP 5.6—PHP 8.2 | 2.16.2 |

## Legacy versions

Expand Down
Binary file added assets/affinity/icon.afdesign
Binary file not shown.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@

import XCTest

class ValetTest: XCTestCase {
class ValetVersionExtractorTest: XCTestCase {

func testDetermineValetVersion() {
let version = valet("--version")
let version = valet("--version", sudo: false)
XCTAssert(version.contains("Laravel Valet 2."))
}

Expand Down
File renamed without changes.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions phpmon/Common/Core/Actions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,8 @@ class Actions {
Detects all currently available PHP versions,
and unlinks each and every one of them.

This all happens in sequence, nothing runs in parallel.

After this, the brew services are also stopped,
the latest PHP version is linked, and php + nginx are restarted.

Expand Down
21 changes: 15 additions & 6 deletions phpmon/Common/Core/Constants.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import Cocoa

class Constants {
struct Constants {

/**
* The latest PHP version that is considered to be stable at the time of release.
Expand Down Expand Up @@ -50,10 +50,19 @@ class Constants {
// dev release. In this case, that means that the version below is detected.
"8.2"
]

/**
The URL that people can visit if they wish to help support the project.
*/
static let DonationUrl = URL(string: "https://nicoverbruggen.be/sponsor#pay-now")!

struct Urls {

static let DonationPayment = URL(
string: "https://nicoverbruggen.be/sponsor#pay-now"
)!
static let DonationPage = URL(
string: "https://nicoverbruggen.be/sponsor"
)!
static let FrequentlyAskedQuestions = URL(
string: "https://github.com/nicoverbruggen/phpmon#%EF%B8%8F-faq--troubleshooting"
)!

}

}
8 changes: 4 additions & 4 deletions phpmon/Common/Core/Helpers.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@
// MARK: Common Shell Commands

/**
Runs a `valet` command.
Runs a `valet` command. Defaults to running as superuser.
*/
func valet(_ command: String) -> String
func valet(_ command: String, sudo: Bool = true) -> String
{
return Shell.pipe("sudo \(Paths.valet) \(command)", requiresPath: true)
return Shell.pipe("\(sudo ? "sudo " : "")" + "\(Paths.valet) \(command)", requiresPath: true)
}

/**
Expand All @@ -35,7 +35,7 @@ func sed(file: String, original: String, replacement: String)

// Check if gsed exists; it is able to follow symlinks,
// which we want to do to toggle the extension
if Shell.fileExists("\(Paths.binPath)/gsed") {
if Filesystem.fileExists("\(Paths.binPath)/gsed") {
Shell.run("\(Paths.binPath)/gsed -i --follow-symlinks 's/\(e_original)/\(e_replacement)/g' \(file)")
} else {
Shell.run("sed -i '' 's/\(e_original)/\(e_replacement)/g' \(file)")
Expand Down
14 changes: 10 additions & 4 deletions phpmon/Common/Core/Logger.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,25 +27,31 @@ class Log {

static func err(_ item: Any) {
if Verbosity.error.isApplicable() {
print("[ERR] \(item)")
print("[E] \(item)")
}
}

static func warn(_ item: Any) {
if Verbosity.warning.isApplicable() {
print("[WRN] \(item)")
print("[W] \(item)")
}
}

static func info(_ item: Any) {
if Verbosity.info.isApplicable() {
print(item)
print("\(item)")
}
}

static func perf(_ item: Any) {
if Verbosity.performance.isApplicable() {
print(item)
print("[P] \(item)")
}
}

static func separator(as verbosity: Verbosity = .info) {
if verbosity.isApplicable() {
print("==================================")
}
}

Expand Down
30 changes: 27 additions & 3 deletions phpmon/Common/Core/Paths.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,19 @@ public class Paths {

public static let shared = Paths()

private var baseDir : Paths.HomebrewDir
internal var baseDir: Paths.HomebrewDir

private var userName : String
private var userName: String

init() {
baseDir = FileManager.default.fileExists(atPath: "\(HomebrewDir.opt.rawValue)/bin/brew") ? .opt : .usr
baseDir = App.architecture != "x86_64" ? .opt : .usr
userName = String(Shell.pipe("whoami").split(separator: "\n")[0])
}

public func detectBinaryPaths() {
detectComposerBinary()
}

// - MARK: Binaries

public static var valet: String {
Expand All @@ -42,6 +46,11 @@ public class Paths {
return "\(binPath)/php-config"
}

// - MARK: Detected Binaries

/** The path to the Composer binary. Can be in multiple locations, so is detected instead. */
public static var composer: String? = nil

// - MARK: Paths

public static var whoami: String {
Expand All @@ -64,6 +73,21 @@ public class Paths {
return "\(shared.baseDir.rawValue)/etc"
}

// MARK: - Flexible Binaries
// (these can be in multiple locations, so we scan common places because)
// (PHP Monitor will not use the user's own PATH)

private func detectComposerBinary() {
if Filesystem.fileExists("/usr/local/bin/composer") {
Paths.composer = "/usr/local/bin/composer"
} else if Filesystem.fileExists("/opt/homebrew/bin/composer") {
Paths.composer = "/opt/homebrew/bin/composer"
} else {
Paths.composer = nil
Log.warn("Composer was not found.")
}
}

// MARK: - Enum

public enum HomebrewDir: String {
Expand Down
59 changes: 59 additions & 0 deletions phpmon/Common/Core/Process.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
//
// Process.swift
// PHP Monitor
//
// Created by Nico Verbruggen on 23/02/2022.
// Copyright © 2022 Nico Verbruggen. All rights reserved.
//

import Foundation

extension Process {

/**
When a process is running in the background, it can send content to standard
output or standard error, just like it would in a terminal. Using `listen`
allows us to react whenever data is received by running a particular closure,
depending on which type of data is received.
*/
public func listen(
didReceiveStandardOutputData: @escaping (String) -> Void,
didReceiveStandardErrorData: @escaping (String) -> Void
) {
let outputPipe = Pipe()
let errorPipe = Pipe()

self.standardOutput = outputPipe
self.standardError = errorPipe

[
(outputPipe, didReceiveStandardOutputData),
(errorPipe, didReceiveStandardErrorData)
].forEach { (pipe: Pipe, callback: @escaping (String) -> Void) in
pipe.fileHandleForReading.waitForDataInBackgroundAndNotify()
NotificationCenter.default.addObserver(
forName: NSNotification.Name.NSFileHandleDataAvailable,
object: pipe.fileHandleForReading,
queue: nil
) { notification in
if let outputString = String(data: pipe.fileHandleForReading.availableData, encoding: String.Encoding.utf8) {
callback(outputString)
}
pipe.fileHandleForReading.waitForDataInBackgroundAndNotify()
}
}
}

/**
After the process is done running, you'll want to stop listening.
*/
public func haltListening() {
if let pipe = self.standardOutput as? Pipe {
NotificationCenter.default.removeObserver(pipe.fileHandleForReading)
}
if let pipe = self.standardError as? Pipe {
NotificationCenter.default.removeObserver(pipe.fileHandleForReading)
}
}

}
45 changes: 0 additions & 45 deletions phpmon/Common/Core/Shell.swift
Original file line number Diff line number Diff line change
Expand Up @@ -104,15 +104,6 @@ public class Shell {
)
}

/**
Checks if a file exists at a certain path.
Used to be done with a shell command, now uses the native FileManager class instead.
*/
public static func fileExists(_ path: String) -> Bool {
let fullPath = path.replacingOccurrences(of: "~", with: "/Users/\(Paths.whoami)")
return FileManager.default.fileExists(atPath: fullPath)
}

/**
Creates a new process with the correct PATH and shell.
*/
Expand All @@ -128,42 +119,6 @@ public class Shell {
return task
}

public static func captureOutput(
_ task: Process,
didReceiveStdOutData: @escaping (String) -> Void,
didReceiveStdErrData: @escaping (String) -> Void
) {
let outputPipe = Pipe()
let errorPipe = Pipe()

task.standardOutput = outputPipe
task.standardError = errorPipe

[(outputPipe, didReceiveStdOutData), (errorPipe, didReceiveStdErrData)].forEach {
(pipe: Pipe, callback: @escaping (String) -> Void) in
pipe.fileHandleForReading.waitForDataInBackgroundAndNotify()
NotificationCenter.default.addObserver(
forName: NSNotification.Name.NSFileHandleDataAvailable,
object: pipe.fileHandleForReading,
queue: nil
) { notification in
if let outputString = String(data: pipe.fileHandleForReading.availableData, encoding: String.Encoding.utf8) {
callback(outputString)
}
pipe.fileHandleForReading.waitForDataInBackgroundAndNotify()
}
}
}

public static func haltCapturingOutput(_ task: Process) {
if let pipe = task.standardOutput as? Pipe {
NotificationCenter.default.removeObserver(pipe.fileHandleForReading)
}
if let pipe = task.standardError as? Pipe {
NotificationCenter.default.removeObserver(pipe.fileHandleForReading)
}
}

public class Output {
public let standardOutput: String
public let errorOutput: String
Expand Down
Loading

0 comments on commit 768bf06

Please sign in to comment.