Skip to content

Commit

Permalink
Merge pull request #30 from buildkite/template/swift
Browse files Browse the repository at this point in the history
Add Swift CI template
  • Loading branch information
dannymidnight authored Feb 29, 2024
2 parents 6952f81 + be6e398 commit ed3bf2c
Show file tree
Hide file tree
Showing 9 changed files with 191 additions and 0 deletions.
2 changes: 2 additions & 0 deletions python-ci/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ This template:
3. Runs pytest unit tests.
4. Automatically annotates the build based on junit test output

The runtime environment uses the official [Python Docker image](https://hub.docker.com/_/python) with the latest version.

## Next steps

After you select **Use template**, you’ll:
Expand Down
43 changes: 43 additions & 0 deletions swift/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
---
title: CI for Swift
description: Build, lint, and test a Swift project using SwiftLint and XCTest.
author: Buildkite
languages: ["Swift"]
use_cases: ["CI", "Mobile", "Web"]
platforms: ["Docker", "macOS", "iOS"]
tools: ["SwiftLint"]
primary_emojis: [":swift:"]
---

# CI for Swift

This template gives you a continuous integration (CI) pipeline that lints, tests, and builds a Swift project.

At a glance:

- For [Swift](https://www.swift.org/) projects
- Requires [Docker](https://docs.docker.com/get-docker/)
- Uses the [Swift Package Manager](https://swift.org/package-manager/)
- Lints code with [SwiftLint](https://github.com/realm/SwiftLint)
- Tests code using [XCTest](https://developer.apple.com/documentation/xctest)

## How it works

This template:

1. Builds your Swift project, caching dependencies for subsequent steps.
2. Lints the code with SwiftLint.
3. Runs tests with XCTest.

The runtime environment uses the official [Swift Docker image](https://hub.docker.com/_/swift) with the latest version.

## Next steps

After you select Use template, you’ll:

1. Connect the Git repository with your Swift project.
2. Modify the commands if necessary.
3. Configure the compute—run locally, on-premises, or in the cloud.
4. Run the pipeline.

You can then play around with the pipeline settings. For example, run the pipeline locally while you iterate on the definition or set a schedule to trigger a nightly build.
12 changes: 12 additions & 0 deletions swift/example-project/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
.DS_Store
/.build
/Packages
xcuserdata/
DerivedData/
.swiftpm/configuration/registries.json
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
.netrc

# Buildkite artifacts
.cache
cache.tgz
14 changes: 14 additions & 0 deletions swift/example-project/Package.resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"pins" : [
{
"identity" : "example-package-figlet",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/example-package-figlet",
"state" : {
"branch" : "main",
"revision" : "166eef46de0b094d6d1966e749f727d6c4beba0e"
}
}
],
"version" : 2
}
29 changes: 29 additions & 0 deletions swift/example-project/Package.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// swift-tools-version: 5.9
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let package = Package(
name: "MyLibrary",
products: [
// Products define the executables and libraries a package produces, making them visible to other packages.
.library(
name: "MyLibrary",
targets: ["MyLibrary"]),
],
dependencies: [
.package(url: "https://github.com/apple/example-package-figlet", branch: "main"),
],
targets: [
// Targets are the basic building blocks of a package, defining a module or a test suite.
// Targets can depend on other targets in this package and products from dependencies.
.target(
name: "MyLibrary",
dependencies: [
.product(name: "Figlet", package: "example-package-figlet")
]),
.testTarget(
name: "MyLibraryTests",
dependencies: ["MyLibrary"]),
]
)
8 changes: 8 additions & 0 deletions swift/example-project/Sources/MyCLI.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import Figlet

@main
struct FigletTool {
static func main() {
Figlet.say("Hello, Swift!")
}
}
30 changes: 30 additions & 0 deletions swift/example-project/Sources/MyLibrary/MyLibrary.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift open source project
//
// Copyright (c) 2023 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===--------------------------------------------------------------------

import Foundation
import Figlet

struct Email: CustomStringConvertible {
var description: String

public init(_ emailString: String) throws {
let regex = #"[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,64}"#
guard let _ = emailString.range(of: regex, options: .regularExpression) else {
throw InvalidEmailError(email: emailString)
}
self.description = emailString
}
}

private struct InvalidEmailError: Error {
let email: String
}
23 changes: 23 additions & 0 deletions swift/example-project/Tests/MyLibraryTests/MyLibraryTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift open source project
//
// Copyright (c) 2023 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===--------------------------------------------------------------------

@testable import MyLibrary
import XCTest

final class MyLibraryTests: XCTestCase {
func testEmail() throws {
let email = try Email("[email protected]")
XCTAssertEqual(email.description, "[email protected]")

XCTAssertThrowsError(try Email("invalid"))
}
}
30 changes: 30 additions & 0 deletions swift/pipeline.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
env:
SWIFT_CACHE_PATH: .cache

steps:
- label: ":swift: Build"
key: "build"
command: "swift build --cache-path $SWIFT_CACHE_PATH"
plugins:
- docker#v5.9.0:
image: "swift:latest"
- artifacts#v1.9.3:
upload: "$SWIFT_CACHE_PATH"
compressed: cache.tgz

- label: ":swift: Lint"
command: "swiftlint"
plugins:
- docker#v5.9.0:
image: "ghcr.io/realm/swiftlint:latest"
platform: "linux/amd64"

- label: ":swift: Test"
command: "swift test --cache-path $SWIFT_CACHE_PATH"
depends_on: ["build"]
plugins:
- docker#v5.9.0:
image: "swift:latest"
- artifacts#v1.9.3:
download: "$SWIFT_CACHE_PATH"
compressed: cache.tgz

0 comments on commit ed3bf2c

Please sign in to comment.