Swiftformat on githooks + New swift run tools setup command (#563)

This commit is contained in:
Mauro 2023-02-10 14:04:00 +01:00 committed by GitHub
parent f0a4cfd946
commit c8fb93e00d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 123 additions and 32 deletions

8
.githooks/post-checkout Executable file
View File

@ -0,0 +1,8 @@
#!/bin/sh
command -v git-lfs >/dev/null 2>&1 || { echo >&2 "\nThis repository is configured for Git LFS but 'git-lfs' was not found on your path. If you no longer wish to use Git LFS, remove this hook by deleting '.git/hooks/post-checkout'.\n"; exit 2; }
git lfs post-checkout "$@"
#!/bin/bash
export PATH="$PATH:/opt/homebrew/bin"
xcodegen

3
.githooks/post-commit Executable file
View File

@ -0,0 +1,3 @@
#!/bin/sh
command -v git-lfs >/dev/null 2>&1 || { echo >&2 "\nThis repository is configured for Git LFS but 'git-lfs' was not found on your path. If you no longer wish to use Git LFS, remove this hook by deleting '.git/hooks/post-commit'.\n"; exit 2; }
git lfs post-commit "$@"

3
.githooks/post-merge Executable file
View File

@ -0,0 +1,3 @@
#!/bin/sh
command -v git-lfs >/dev/null 2>&1 || { echo >&2 "\nThis repository is configured for Git LFS but 'git-lfs' was not found on your path. If you no longer wish to use Git LFS, remove this hook by deleting '.git/hooks/post-merge'.\n"; exit 2; }
git lfs post-merge "$@"

10
.githooks/pre-commit Executable file
View File

@ -0,0 +1,10 @@
#!/bin/bash
export PATH="$PATH:/opt/homebrew/bin"
if ! swiftformat --lint . > /dev/null 2>&1
then
echo "pre-commit: Commit aborted due to SwiftFormat warnings. Please check the automatically generated fixes and try again"
swiftformat . > /dev/null 2>&1
exit 1
fi

3
.githooks/pre-push Executable file
View File

@ -0,0 +1,3 @@
#!/bin/sh
command -v git-lfs >/dev/null 2>&1 || { echo >&2 "\nThis repository is configured for Git LFS but 'git-lfs' was not found on your path. If you no longer wish to use Git LFS, remove this hook by deleting '.git/hooks/pre-push'.\n"; exit 2; }
git lfs pre-push "$@"

3
.gitignore vendored
View File

@ -35,6 +35,9 @@ build
Tools/Scripts/element-android
/vendor/
## brew
Brewfile.lock.json
## macOS Files
.DS_Store
._*

View File

@ -6,11 +6,24 @@ Element iOS support can be found in this room: [![Element iOS Matrix room #eleme
## Setting up a development environment
### Setup Project
It's mandatory to have [homebrew](https://brew.sh/) installed on your mac, and run after the checkout:
```
swift run tools setup-project
```
This will:
- Install various brew dependencies required for the project (like xcodegen).
- Set up git to use the shared githooks from the repo, instead of the default ones.
- Automatically run xcodegen for the first time.
### Xcode
We suggest using an Xcode version later than 13.2.1.
The Xcode project can be directly compiled after checkout through the shared ElementX scheme which includes the main application as well as the unit and UI tests.
The Xcode project can be directly compiled through the shared ElementX scheme which includes the main application as well as the unit and UI tests.
The Xcode project itself is generated through [xcodegen](https://github.com/yonaskolb/XcodeGen) so any changes shouldn't be made directly to it but to the configuration files.
@ -38,12 +51,20 @@ The project depends on some tools for the build process. These are all included
brew bundle
```
Git LFS is used to store UI test snapshots. After cloning the repo this can be configured by running
Git LFS is used to store UI test snapshots. `swift run tools setup-project` will already install it, however it can also be installed after a checkout by running:
```
git lfs install
```
### Githooks
The project uses its own shared githooks stored in the .githooks folder, you will need to configure git to use such folder, this is already done if you have run the setup tool with `swift run tools setup-project` otherwise you would need to run:
```
git config core.hooksPath .githooks
```
### Continuous Integration
ElementX uses Fastlane for running actions on the CI and tries to keep the configuration confined to either [fastlane](fastlane/Fastfile) or [xcodegen](project.yml).

View File

@ -11,12 +11,10 @@ struct BuildSDK: ParsableCommand {
@Option(help: "The target to build for such as aarch64-apple-ios. Omit this option to build for all targets.")
var target: String?
private var projectDirectoryURL: URL { URL(filePath: FileManager.default.currentDirectoryPath) }
private var parentDirectoryURL: URL { projectDirectoryURL.deletingLastPathComponent() }
private var parentDirectoryURL: URL { Utilities.projectDirectoryURL.deletingLastPathComponent() }
private var sdkDirectoryURL: URL { parentDirectoryURL.appending(path: "matrix-rust-sdk") }
enum Error: LocalizedError {
case scriptFailed
case rustupOutputFailure
case missingRustTargets([String])
case failureParsingProjectYAML
@ -49,7 +47,7 @@ struct BuildSDK: ParsableCommand {
/// but only when the ``target`` option hasn't been supplied.
func checkRustupTargets() throws {
guard target == nil else { return }
guard let output = try zsh("rustup show", workingDirectoryURL: projectDirectoryURL) else { throw Error.rustupOutputFailure }
guard let output = try Utilities.zsh("rustup show") else { throw Error.rustupOutputFailure }
var requiredTargets = [
"aarch64-apple-darwin": false,
@ -71,13 +69,13 @@ struct BuildSDK: ParsableCommand {
/// Clones the Rust SDK if a copy isn't found in the parent directory.
func cloneSDKIfNeeded() throws {
guard !FileManager.default.fileExists(atPath: sdkDirectoryURL.path) else { return }
try zsh("git clone https://github.com/matrix-org/matrix-rust-sdk", workingDirectoryURL: parentDirectoryURL)
try Utilities.zsh("git clone https://github.com/matrix-org/matrix-rust-sdk", workingDirectoryURL: parentDirectoryURL)
}
/// Checkout the specified branch of the SDK if supplied.
func checkoutBranchIfSupplied() throws {
guard let branch else { return }
try zsh("git checkout \(branch)", workingDirectoryURL: sdkDirectoryURL)
try Utilities.zsh("git checkout \(branch)", workingDirectoryURL: sdkDirectoryURL)
}
/// Build the Rust SDK as an XCFramework with the debug profile.
@ -86,18 +84,18 @@ struct BuildSDK: ParsableCommand {
if let target {
buildCommand.append(" --only-target \(target)")
}
try zsh(buildCommand, workingDirectoryURL: sdkDirectoryURL)
try Utilities.zsh(buildCommand, workingDirectoryURL: sdkDirectoryURL)
}
/// Update the Xcode project to use the build of the SDK.
func updateXcodeProject() throws {
try updateProjectYAML()
try zsh("xcodegen", workingDirectoryURL: projectDirectoryURL)
try Utilities.zsh("xcodegen")
}
/// Update project.yml with the local path of the SDK.
func updateProjectYAML() throws {
let yamlURL = projectDirectoryURL.appending(path: "project.yml")
let yamlURL = Utilities.projectDirectoryURL.appending(path: "project.yml")
let yamlString = try String(contentsOf: yamlURL)
guard var projectConfig = try Yams.compose(yaml: yamlString) else { throw Error.failureParsingProjectYAML }
@ -106,24 +104,4 @@ struct BuildSDK: ParsableCommand {
let updatedYAMLString = try Yams.serialize(node: projectConfig)
try updatedYAMLString.write(to: yamlURL, atomically: true, encoding: .utf8)
}
/// Runs a command in zsh.
@discardableResult
func zsh(_ command: String, workingDirectoryURL: URL) throws -> String? {
let process = Process()
process.executableURL = URL(filePath: "/bin/zsh")
process.arguments = ["-c", command]
process.currentDirectoryURL = workingDirectoryURL
let outputPipe = Pipe()
process.standardOutput = outputPipe
try process.run()
process.waitUntilExit()
guard process.terminationReason == .exit, process.terminationStatus == 0 else { throw Error.scriptFailed }
guard let outputData = try outputPipe.fileHandleForReading.readToEnd() else { return nil }
return String(data: outputData, encoding: .utf8)
}
}

View File

@ -0,0 +1,24 @@
import ArgumentParser
import Foundation
struct SetupProject: ParsableCommand {
static var configuration = CommandConfiguration(abstract: "A tool to setup the required components to efficiently run and contribute to Element X iOS")
func run() throws {
try setupGitHooks()
try brewBundleInstall()
try xcodegen()
}
func setupGitHooks() throws {
try Utilities.zsh("git config core.hooksPath .githooks")
}
func brewBundleInstall() throws {
try Utilities.zsh("brew bundle install")
}
func xcodegen() throws {
try Utilities.zsh("xcodegen")
}
}

View File

@ -4,5 +4,6 @@ import Foundation
@main
struct Tools: ParsableCommand {
static var configuration = CommandConfiguration(abstract: "A collection of command line tools for ElementX",
subcommands: [BuildSDK.self])
subcommands: [BuildSDK.self,
SetupProject.self])
}

View File

@ -0,0 +1,37 @@
import ArgumentParser
import Foundation
enum Utilities {
enum Error: LocalizedError {
case scriptFailed(command: String, path: String)
var errorDescription: String? {
switch self {
case let .scriptFailed(command, path):
return "command \(command) failed in path: \(path)"
}
}
}
static var projectDirectoryURL: URL { URL(filePath: FileManager.default.currentDirectoryPath) }
/// Runs a command in zsh.
@discardableResult
static func zsh(_ command: String, workingDirectoryURL: URL = projectDirectoryURL) throws -> String? {
let process = Process()
process.executableURL = URL(filePath: "/bin/zsh")
process.arguments = ["-c", command]
process.currentDirectoryURL = workingDirectoryURL
let outputPipe = Pipe()
process.standardOutput = outputPipe
try process.run()
process.waitUntilExit()
guard process.terminationReason == .exit, process.terminationStatus == 0 else { throw Error.scriptFailed(command: command, path: workingDirectoryURL.absoluteString) }
guard let outputData = try outputPipe.fileHandleForReading.readToEnd() else { return nil }
return String(data: outputData, encoding: .utf8)
}
}