Awesome
IBM Cloud buildpack for Swift
This is the IBM Cloud buildpack for Swift applications, powered by the Swift Package Manager (SPM). Though this buildpack was developed mainly for IBM Cloud and the sample commands use the IBM Cloud command line, it can be used on any Cloud Foundry environment. This buildpack requires access to the Internet for downloading and installing several system level dependencies.
Check out the Kitura-Starter for a fully working example of a Kitura-based server application that can be deployed to the IBM Cloud (or any Cloud Foundry environment).
Usage
Example usage (see the Specify a Swift version section):
$ ibmcloud app push
Invoking 'ibmcloud app push'...
Using manifest file /Users/gvalenc/git/Kitura-Starter/manifest.yml
Getting app info...
Creating app with these attributes...
+ name: GV-Kitura-Starter
path: /Users/gvalenc/git/Kitura-Starter
buildpacks:
+ https://github.com/IBM-Swift/swift-buildpack
+ command: Kitura-Starter
+ disk quota: 1G
+ instances: 1
+ memory: 256M
routes:
+ gv-kitura-starter-chatty-shark.mybluemix.net
Creating app GV-Kitura-Starter...
Mapping routes...
Comparing local files to remote cache...
Packaging files to upload...
Uploading files...
29.97 KiB / 29.97 KiB [=================================================================] 100.00% 1s
Waiting for API to complete processing files...
timeout connecting to log server, no log will be shown
Staging app and tracing logs...
Cell b52d4499-f402-4b95-8ccc-75f95c8b518d creating container for instance 90754c9f-3c50-43a5-bdaa-80ad61cee7c3
Cell b52d4499-f402-4b95-8ccc-75f95c8b518d successfully created container for instance 90754c9f-3c50-43a5-bdaa-80ad61cee7c3
Downloading app package...
Downloaded app package (30K)
-----> Buildpack version 2.1.1
-----> Default supported Swift version is 5.0.2
-----> Configure for apt-get installs...
-----> Writing profile script...
-----> Copying deb files to installation folder...
-----> No Aptfile found.
-----> Getting swift-5.0.2
Downloaded swift-5.0.2
-----> Unpacking swift-5.0.2.tar.gz
-----> Getting clang-8.0.0
Downloaded clang-8.0.0
-----> Unpacking clang-8.0.0.tar.xz
-----> .ssh directory and config file not found.
-----> Skipping cache restore (new swift signature)
-----> Fetching Swift packages and parsing Package.swift files...
Fetching https://github.com/IBM-Swift/BlueSocket.git
Fetching https://github.com/IBM-Swift/CloudEnvironment.git
Fetching https://github.com/IBM-Swift/Health.git
Fetching https://github.com/IBM-Swift/KituraContracts.git
Fetching https://github.com/IBM-Swift/BlueSignals.git
Fetching https://github.com/IBM-Swift/OpenSSL.git
Fetching https://github.com/IBM-Swift/BlueSSLService.git
Fetching https://github.com/IBM-Swift/Configuration.git
Fetching https://github.com/IBM-Swift/Kitura-net.git
Fetching https://github.com/IBM-Swift/Kitura-TemplateEngine.git
Fetching https://github.com/IBM-Swift/Kitura.git
Fetching https://github.com/IBM-Swift/Swift-cfenv.git
Fetching https://github.com/IBM-Swift/HeliumLogger.git
Fetching https://github.com/IBM-Swift/LoggerAPI.git
Fetching https://github.com/IBM-Swift/TypeDecoder.git
Fetching https://github.com/IBM-Swift/FileKit.git
Completed resolution in 8.55s
Cloning https://github.com/IBM-Swift/KituraContracts.git
Resolving https://github.com/IBM-Swift/KituraContracts.git at 1.1.1
Cloning https://github.com/IBM-Swift/TypeDecoder.git
Resolving https://github.com/IBM-Swift/TypeDecoder.git at 1.3.0
Cloning https://github.com/IBM-Swift/Configuration.git
Resolving https://github.com/IBM-Swift/Configuration.git at 3.0.2
Cloning https://github.com/IBM-Swift/CloudEnvironment.git
Resolving https://github.com/IBM-Swift/CloudEnvironment.git at 9.0.0
Cloning https://github.com/IBM-Swift/Kitura-TemplateEngine.git
Resolving https://github.com/IBM-Swift/Kitura-TemplateEngine.git at 2.0.0
Cloning https://github.com/IBM-Swift/Kitura.git
Resolving https://github.com/IBM-Swift/Kitura.git at 2.6.2
Cloning https://github.com/IBM-Swift/BlueSSLService.git
Resolving https://github.com/IBM-Swift/BlueSSLService.git at 1.0.44
Cloning https://github.com/IBM-Swift/FileKit.git
Resolving https://github.com/IBM-Swift/FileKit.git at 0.0.1
Cloning https://github.com/IBM-Swift/Health.git
Resolving https://github.com/IBM-Swift/Health.git at 1.0.4
Cloning https://github.com/IBM-Swift/BlueSocket.git
Resolving https://github.com/IBM-Swift/BlueSocket.git at 1.0.44
Cloning https://github.com/IBM-Swift/OpenSSL.git
Resolving https://github.com/IBM-Swift/OpenSSL.git at 2.2.2
Cloning https://github.com/IBM-Swift/LoggerAPI.git
Resolving https://github.com/IBM-Swift/LoggerAPI.git at 1.8.0
Cloning https://github.com/IBM-Swift/Swift-cfenv.git
Resolving https://github.com/IBM-Swift/Swift-cfenv.git at 6.0.2
Cloning https://github.com/IBM-Swift/Kitura-net.git
Resolving https://github.com/IBM-Swift/Kitura-net.git at 2.1.6
Cloning https://github.com/IBM-Swift/BlueSignals.git
Resolving https://github.com/IBM-Swift/BlueSignals.git at 1.0.16
Cloning https://github.com/IBM-Swift/HeliumLogger.git
Resolving https://github.com/IBM-Swift/HeliumLogger.git at 1.8.0
-----> No additional packages to download.
-----> Skipping installation of App Management (debug)
-----> Installing system level dependencies...
-----> Building Package...
-----> Build config: release
[1/20] Compiling CHTTPParser utils.c
[2/20] Compiling CHTTPParser http_parser.c
[3/20] Compiling Swift Module 'TypeDecoder' (2 sources)
[4/20] Compiling Swift Module 'Socket' (3 sources)
[5/20] Compiling Swift Module 'Signals' (1 sources)
[6/20] Compiling Swift Module 'LoggerAPI' (1 sources)
[7/20] Compiling Swift Module 'KituraTemplateEngine' (1 sources)
[8/20] Compiling Swift Module 'KituraContracts' (9 sources)
[9/20] Compiling Swift Module 'HeliumLogger' (2 sources)
[10/20] Compiling Swift Module 'Health' (3 sources)
/tmp/app/.build/checkouts/TypeDecoder/Sources/TypeDecoder/TypeDecoder.swift:292:16: warning: 'Hashable.hashValue' is deprecated as a protocol requirement; conform type 'TypeInfo' to 'Hashable' by implementing 'hash(into:)' instead
public var hashValue: Int {
^
[11/20] Compiling Swift Module 'FileKit' (1 sources)
[12/20] Compiling Swift Module 'Configuration' (5 sources)
[13/20] Compiling Swift Module 'SSLService' (2 sources)
[14/20] Compiling Swift Module 'CloudFoundryEnv' (6 sources)
[15/20] Compiling Swift Module 'KituraNet' (36 sources)
[16/20] Compiling Swift Module 'CloudEnvironment' (18 sources)
[17/20] Compiling Swift Module 'Kitura' (52 sources)
/tmp/app/.build/checkouts/Kitura/Sources/Kitura/contentType/MediaType.swift:163:16: warning: 'Hashable.hashValue' is deprecated as a protocol requirement; conform type 'MediaType' to 'Hashable' by implementing 'hash(into:)' instead
public let hashValue: Int
^
[18/20] Compiling Swift Module 'Controller' (1 sources)
[19/20] Compiling Swift Module 'Kitura_Starter' (1 sources)
[20/20] Linking ./.build/x86_64-unknown-linux/release/Kitura-Starter
-----> Bin path: /tmp/app/.build/x86_64-unknown-linux/release
-----> Copying dynamic libraries
-----> Copying binaries to 'bin'
-----> Clearing previous swift cache
-----> Saving cache (default):
-----> - .build
-----> Optimizing contents of cache folder...
No start command specified by buildpack or via Procfile.
App will not start unless a command is provided at runtime.
Exit status 0
Uploading droplet, build artifacts cache...
Uploading droplet...
Uploading build artifacts cache...
Uploaded build artifacts cache (49.1M)
Uploaded droplet (244.7M)
Uploading complete
Cell b52d4499-f402-4b95-8ccc-75f95c8b518d stopping instance 90754c9f-3c50-43a5-bdaa-80ad61cee7c3
Cell b52d4499-f402-4b95-8ccc-75f95c8b518d destroying container for instance 90754c9f-3c50-43a5-bdaa-80ad61cee7c3
Waiting for app to start...
name: GV-Kitura-Starter
requested state: started
routes: gv-kitura-starter-chatty-shark.mybluemix.net
last uploaded: Wed 31 Jul 14:13:09 CDT 2019
stack: cflinuxfs3
buildpacks: https://github.com/IBM-Swift/swift-buildpack
type: web
instances: 1/1
memory usage: 256M
start command: Kitura-Starter
state since cpu memory disk details
#0 running 2019-07-31T19:14:04Z 0.4% 36K of 256M 458.4M of 1G
The buildpack will detect your app as Swift if it has a Package.swift
file in the root.
Version installed on the IBM Cloud
The latest version of the IBM Cloud buildpack for Swift on the IBM Cloud is v2.1.1.
Please note that it is possible that the latest buildpack code contained in this repo hasn't yet been installed on the IBM Cloud. If that happens to be the case and you'd like to leverage the latest buildpack code, you can do so by adding the -b https://github.com/IBM-Swift/swift-buildpack
parameter to the ibmcloud app push
command, as shown below:
ibmcloud app push -b https://github.com/IBM-Swift/swift-buildpack
Procfile
Using the Procfile
, you specify the name of the executable process (e.g. Server
) to run for your web server. Any binaries built from your Swift source using SPM will be placed in your $PATH. You can also specify any runtime parameters for your process in the Procfile
.
web: Server --bind 0.0.0.0:$PORT
Alternative to Procfile
Instead of using the Procfile
, you can use the command
attribute in the manifest.yml
of your application to specify the name of your executable. The snippet of code below shows how to use the command
attribute to specify the same executable and parameter values used in the above Procfile
example:
command: Server -bind 0.0.0.0:$PORT
For further details on the command
attribute, see the command attribute section on the Cloud Foundry documentation.
Swift-cfenv
Instead of specifying IP address and port values in the Procfile
(or in the command
attribute) as runtime parameters to your web server process, you can instead use the Swift-cfenv package to obtain such values at runtime. The Swift-cfenv package provides structures and methods to parse Cloud Foundry-provided environment variables, such as the port number, IP address, and URL of the application. It also provides default values when running the application locally. For details on how to leverage this library in your Swift application, see the README file. When using Swift-cfenv in your app, your Procfile
will be very simple; it will more than likely look like this:
web: <executable_name>
If instead of the Procfile
, you are using the command
attribute in your application's manifest.yml
file, then the entry for the command
attribute is simplified to:
command: <executable_name>
What is the latest version of Swift supported?
The latest version of Swift supported by this buildpack is 5.0.2
.
Specify a Swift version
You specify the version of Swift for your application using a .swift-version
file in the root of your repository:
$ cat .swift-version
5.0
Please note that the swift_buildpack installed on the IBM Cloud caches the following versions of the Swift binaries:
5.0.2
5.0.1
4.2.4
If you'd like to use a different version of Swift [that is not cached] on the IBM Cloud, you can specify it in the .swift-version
file. Please be aware that using a Swift version that is not cached increases the provisioning time of your app on the IBM Cloud.
The manifest.yml file contains the complete list of the Swift versions that are cached on the IBM Cloud.
Since there are frequent Swift language changes, it's advised that you pin your application to a specific Swift version. Once you have tested and migrated your code to a newer version of Swift, you can then update the .swift-version
file with the appropriate Swift version.
Installing additional system level dependencies
Many Swift applications will not require the installation of any additional libraries. It's very common for today’s applications to have dependencies only on services that provide REST interfaces to interact with them (e.g., Cloudant, AlchemyAPI, Personality Insights, etc.).
However, since dependencies vary from application to application, there could be cases when additional system packages may be required to compile and/or execute a Swift application. To address this need, the IBM Cloud buildpack for Swift supports the installation of Ubuntu trusty packages using the apt-get
utility. You can specify the Ubuntu packages that the should be installed by including an Aptfile
in the root directory of your Swift application. Each line in the Aptfile should contain a valid Ubuntu package name. For instance, if your application has a dependency on the jsonbot
package, then your Aptfile should look like this:
$ cat Aptfile
jsonbot
Installing closed source dependencies
For those accessing private or enterprise host respositories, the IBM Cloud buildpack for Swift now works with the Swift Package Manager to build these dependencies. To leverage this capability, add a .ssh
folder in the root of the application. This directory will need to contain the SSH keys needed to access the dependencies, as well as a config
file referencing the keys. The example below shows the config
and Package.swift
files, respectively, which use the same SSH key to access private and public repositories in enterprise and standard GitHub accounts:
$ cat config
# GitHub.IBM.com - Enterprise Host, Account Key
Host github.ibm.com
HostName github.ibm.com
User git
IdentityFile ~/.ssh/ssh_key
# GitHub.com - Private Repo, Account Key
Host github.com
HostName github.com
User git
IdentityFile ~/.ssh/ssh_key
You should use the git
protocol in your Package.swift
for those dependencies that are private or stored in an enterprise solution (e.g. GitHub Enterprise) as shown below. If you use the https
protocol instead, then the buildpack will not be able to clone those dependencies.
$ cat Package.swift
...
dependencies: [
...
.Package(url: "git@github.ibm.com:Org1/repo1.git", majorVersion: 1, minor: 0),
.Package(url: "git@github.ibm.com:Org1/repo2.git", majorVersion: 1, minor: 0),
.Package(url: "git@github.com:Org2/repo3.git", majorVersion: 0, minor: 0),
...
]
...
This approach works for both SSH account keys and deployment keys. For the example below, three keys are used - two deployment keys for the enterprise GitHub, and one account key for the standard one.
$ cat config
# GitHub Enterprise - repo1 deployment key
Host enterprise1
HostName github.ibm.com
User git
IdentityFile ~/.ssh/githubEnterprise_key1
# GitHub Enterprise - repo2 deployment key
Host enterprise2
HostName github.ibm.com
User git
IdentityFile ~/.ssh/githubEnterprise_key2
# GitHub.com - Private Repo, Account Key
Host github.com
HostName github.com
User git
IdentityFile ~/.ssh/github_key
$ cat Package.swift
...
dependencies: [
...
.Package(url: "git@enterprise1:Org1/repo1.git", majorVersion: 1, minor: 0),
.Package(url: "git@enterprise2:Org1/repo2.git", majorVersion: 1, minor: 0),
.Package(url: "git@github.com:Org2/repo3.git", majorVersion: 0, minor: 0),
...
]
...
Additional compiler flags
To specify additional compiler flags for the execution of the swift build
command, you can include a .swift-build-options-linux
file. For example, in order to leverage the system package libmysqlclient-dev
in a Swift application, you'd need an additional compiler flag:
$ cat .swift-build-options-linux
-Xswiftc -DNOJSON
When leveraging the PostgreSQL system library libpq-dev
, the following contents should be added to the .swift-build-options-linux
file:
$ cat .swift-build-options-linux
-Xcc -I/usr/include/postgresql
If you need to specify the path to header files for a system package installed by the buildpack, you can use the following:
-Xcc -I$BUILD_DIR/.apt/usr/include/<path to header files>
If you need to specify environment variables that apply during the build,, such as to enable Kitura-NIO, create a file with the name .swift-build-env-linux
in the root project directory. Edit the file and add one environment variable per line. For example:
KITURA_NIO=1
FOO=BAR
libdispatch
Previous versions of this buildpack provided the libdispatch binaries for Swift development builds prior to 2016-08-23. However, current and future versions of this buildpack will not provide those binaries. Users should upgrade their applications to Swift 3.0, which already includes the libdispatch binaries.
Caching of the .build directory
Following the release of Swift 3.1, the IBM Cloud buildpack for Swift caches the contents of the .build
folder to speed up the provisioning of your application the next time you execute the ibmcloud app push
command. If you'd prefer not to use this caching mechanism, you can disable it by executing the following command:
ibmcloud app env-set <app_name> SWIFT_BUILD_DIR_CACHE false
ibmcloud app restage <app_name>
If at some point, you'd like to re-enable caching of the .build
folder, you can do so by executing:
ibmcloud app env-set <app_name> SWIFT_BUILD_DIR_CACHE true
ibmcloud app restage <app_name>
Note that if at some point you change the contents of your Package.swift
or Package.resolved
(or Package.pins
for older versions of Swift) file, the buildpack will automatically refetch the dependencies and update the cache accordingly. Also, if you do not initially push a Package.resolved
file along with your application and you are using Swift 4.0 (or a later version), a new Package.resolved
file will be generated. It is recommended that you always push a Package.resolved
file along with your application (if using Swift 4.0 or later).
Debugging
If the buildpack preparation or compilation steps are failing, you can enable some debugging using the following command:
ibmcloud app env-set <app_name> BP_DEBUG true
To deactivate:
ibmcoud app env-unset <app_name> BP_DEBUG
Installing Personal Package Archives
The IBM Cloud buildpack for Swift does not support the installation of Personal Package Archives (PPAs). If your application requires the installation of one or more PPAs, we recommend using a different mechanism other than the IBM Cloud buildpack for Swift for provisioning your application to the IBM Cloud. For instance, you could use Docker and Kubernetes to provision your Swift application to the IBM Cloud (in your Dockerfile
, you would add the instructions for installing any necessary PPAs).
Admin tasks
To install this buildpack:
wget https://github.com/IBM-Swift/swift-buildpack/releases/download/2.1.1/buildpack_swift_v2.1.1-20190821-1902.zip
ibmcloud cf create-buildpack swift_buildpack uildpack_swift_v2.1.1-20190821-1902.zip <position>
Position is a positive integer, sets priority, and is sorted from lowest to highest when listed using the ibmcloud cf buildpacks
command.
And to update it:
wget https://github.com/IBM-Swift/swift-buildpack/releases/download/2.1.1/buildpack_swift_v2.1.1-20190821-1902.zip
ibmcloud cf update-buildpack swift_buildpack -p uildpack_swift_v2.1.1-20190821-1902.zip
For more details on installing buildpacks, see Adding buildpacks to Cloud Foundry.
Packaging
The buildpack zip file provided in each release is built using the manifest.yml
file:
BUNDLE_GEMFILE=cf.Gemfile bundle install
BUNDLE_GEMFILE=cf.Gemfile bundle exec buildpack-packager --cached --use-custom-manifest manifest.yml
For details on packaging buildpacks, see buildpack-packager.