From a6ede23c299a3798526cdc5c5dce674396f3cc02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Claus=20Ho=CC=88fele?= Date: Wed, 12 Oct 2016 22:30:31 +0200 Subject: [PATCH] Initial check in --- .gitignore | 68 +++++++++++++++++++++ Package.swift | 7 +++ README.md | 59 ++++++++++++++++++ Sources/AlexaSkillsKit/Request.swift | 49 +++++++++++++++ Sources/AlexaSkillsKit/RequestHandler.swift | 15 +++++ Sources/AlexaSkillsKit/Response.swift | 31 ++++++++++ Tests/AlexaSkillsKitTests/ItemTests.swift | 16 +++++ Tests/LinuxMain.swift | 9 +++ 8 files changed, 254 insertions(+) create mode 100644 .gitignore create mode 100755 Package.swift create mode 100644 README.md create mode 100644 Sources/AlexaSkillsKit/Request.swift create mode 100644 Sources/AlexaSkillsKit/RequestHandler.swift create mode 100644 Sources/AlexaSkillsKit/Response.swift create mode 100644 Tests/AlexaSkillsKitTests/ItemTests.swift create mode 100644 Tests/LinuxMain.swift diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..611bf48 --- /dev/null +++ b/.gitignore @@ -0,0 +1,68 @@ +.DS_Store + +# Xcode +# +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore + +## Build generated +build/ +DerivedData/ + +## Various settings +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata/ + +## Other +*.moved-aside +*.xcuserstate + +## Obj-C/Swift specific +*.hmap +*.ipa +*.dSYM.zip +*.dSYM + +## Playgrounds +timeline.xctimeline +playground.xcworkspace + +# Swift Package Manager +# +# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. +Packages/ +.build/ +*.xcodeproj + +# CocoaPods +# +# We recommend against adding the Pods directory to your .gitignore. However +# you should judge for yourself, the pros and cons are mentioned at: +# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control +# +# Pods/ + +# Carthage +# +# Add this line if you want to avoid checking in source code from Carthage dependencies. +# Carthage/Checkouts + +Carthage/Build + +# fastlane +# +# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the +# screenshots whenever they are needed. +# For more information about the recommended setup visit: +# https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md + +fastlane/report.xml +fastlane/Preview.html +fastlane/screenshots +fastlane/test_output diff --git a/Package.swift b/Package.swift new file mode 100755 index 0000000..421836b --- /dev/null +++ b/Package.swift @@ -0,0 +1,7 @@ +import PackageDescription + +let package = Package( + name: "AlexaSkillsKit", + targets: [ + Target(name: "AlexaSkillsKit"), + ]) diff --git a/README.md b/README.md new file mode 100644 index 0000000..4155b8b --- /dev/null +++ b/README.md @@ -0,0 +1,59 @@ +# SwiftServer +Server app with Swift and Docker + +[![Build Status](https://travis-ci.org/choefele/swift-server-app.svg?branch=master)](https://travis-ci.org/choefele/swift-server-app) + +## Tools +- Xcode + - Download from [Xcode 8](https://developer.apple.com/download/) + - Select Xcode 8 as default `sudo xcode-select -s /Applications/Xcode-beta.app/Contents/Developer/` +- `swiftenv` (optional since Swift built into Xcode 8 is the currently the latest version) + - Install `swiftenv` via [Homebrew](https://swiftenv.fuller.li/en/latest/installation.html#via-homebrew) + - `swiftenv rehash`, `swiftenv install ` (see `.swift-version`) +- Docker + - Install from [Docker website](https://www.docker.com/products/overview) + - Consider installing [Kitematic](https://www.docker.com/products/docker-kitematic) to simplify Docker management + +## Build & Run with Swift Package Manager +- Run `swift build` in root folder, wait until dependencies have been downloaded and server has been built +- Run dependent services `docker-compose -f docker-compose-dev.yml up` +- Run server `./.build/debug/SwiftServer` +- Test server by executing `curl http://localhost:8090/ping` +- Test DB with `curl -X POST localhost:8090/items`, `curl http://localhost:8090/items` +- Run unit tests with `swift test` + +## Build & Run with Xcode +- Run `swift package fetch` in root folder to update dependencies +- Generate Xcode project with `swift package generate-xcodeproj` +- Run dependent services `docker-compose -f docker-compose-dev.yml up` +- Open `SwiftServer.xcodeproj` in Xcode and Run `SwiftServer` scheme +- Test server by executing `curl http://localhost:8090/ping` +- Test DB with `curl -X POST localhost:8090/items`, `curl http://localhost:8090/items` +- Run unit tests with CMD-U + +## Build & Run in Docker +- Build image with `docker-compose -f docker-compose-ci.yml build`; tests a run as part of the build process +- Run with `docker-compose -f docker-compose-ci.yml up [-d]` (stop: `docker-compose down [-v]`, logs: `docker-compose logs -f`) +- Test server by executing `curl http://localhost:8090/ping` +- Test DB with `curl -X POST localhost:8090/items`, `curl http://localhost:8090/items` + +### Connect `mongo` to database server +- `docker-compose run --rm db mongo mongodb://db` to connect to database +-- `use test`, `db.items.insert({})`, `db.items.find()` to create sample data +- Restart db instance to see that data persists in volume container + +### Handle managed volumes +- `docker inspect -f "{{json .Mounts}}" swiftserver_db_1` to find out mount point +- `docker volume ls -f dangling=true` to find orphaned managed volumes +- `docker volume rm $(docker volume ls -qf dangling=true)` to remove orphaned volumes + +### Provision on Digital Ocean +- `docker-machine create --driver digitalocean --digitalocean-access-token SwiftServer` +- `eval "$(docker-machine env SwiftServer)"`, `eval "$(docker-machine env -u)"` +- `docker-machine ssh SwiftServer` to ssh into new machine +- Export/import ssh setup: `https://github.com/bhurlow/machine-share` +- `docker compose -f docker-compose-prod.yml up` to start services + +## Integration tests +- Install `newman` with `npm install newman --global` +- Run `./run-integration-tests.sh` diff --git a/Sources/AlexaSkillsKit/Request.swift b/Sources/AlexaSkillsKit/Request.swift new file mode 100644 index 0000000..c797a3a --- /dev/null +++ b/Sources/AlexaSkillsKit/Request.swift @@ -0,0 +1,49 @@ +import Foundation + +public struct LaunchRequest { + public var request: Request +} + +public struct Request { + public var requestId: String + public var timestamp: Date + public var locale: String +} + +public struct IntentRequest { + public var request: Request + public var intent: Intent +} + +public struct Intent { + public var name: String + public var slots: [String: Slot] +} + +public struct Slot { + public var name: String + public var value: String? +} + +public struct SessionEndedRequest { + public var request: Request + public var reason: Reason + public var error: Error +} + +public enum Reason { + case userInitiated + case error + case exceededMaxReprompts +} + +public struct Error { + public var type: ErrorType + public var reason: String +} + +public enum ErrorType { + case invalidResponse + case deviceCommunicationError + case internalError +} diff --git a/Sources/AlexaSkillsKit/RequestHandler.swift b/Sources/AlexaSkillsKit/RequestHandler.swift new file mode 100644 index 0000000..9303abf --- /dev/null +++ b/Sources/AlexaSkillsKit/RequestHandler.swift @@ -0,0 +1,15 @@ +// +// RequestHandler.swift +// AlexaSkillsKit +// +// Created by Claus Höfele on 12.10.16. +// +// + +import Foundation + +public protocol RequestHandler { + func handleLaunch(request: LaunchRequest) -> StandardResponse + func handleIntent(request: IntentRequest) -> StandardResponse + func handleSessionEnded(request: SessionEndedRequest) +} diff --git a/Sources/AlexaSkillsKit/Response.swift b/Sources/AlexaSkillsKit/Response.swift new file mode 100644 index 0000000..f0034ad --- /dev/null +++ b/Sources/AlexaSkillsKit/Response.swift @@ -0,0 +1,31 @@ +// +// Response.swift +// AlexaSkillsKit +// +// Created by Claus Höfele on 12.10.16. +// +// + +import Foundation + +public struct StandardResponse { + public var outputSpeech: OutputSpeech? + public var card: Card? + public var reprompt: OutputSpeech? +} + +public enum OutputSpeech { + case plainText(String) + case ssml(String) +} + +public enum Card { + case simple(title: String?, content: String?) + case standard(title: String?, text: String?, image: Image?) + case linkAccount +} + +public struct Image { + public var smallImageUrl: URL + public var largeImageUrl: URL +} diff --git a/Tests/AlexaSkillsKitTests/ItemTests.swift b/Tests/AlexaSkillsKitTests/ItemTests.swift new file mode 100644 index 0000000..aa90c64 --- /dev/null +++ b/Tests/AlexaSkillsKitTests/ItemTests.swift @@ -0,0 +1,16 @@ +import AlexaSkillsKit +import XCTest + +class ItemTests: XCTestCase { + static let allTests = [ + ("testGetRequestStatusCode", testGetRequestStatusCode) + ] + + func testGetRequestStatusCode() { + let e = expectation(description: "test") + e.fulfill() + waitForExpectations(timeout: 1) + + XCTAssertEqual(40, 40) + } +} diff --git a/Tests/LinuxMain.swift b/Tests/LinuxMain.swift new file mode 100644 index 0000000..2ae85ed --- /dev/null +++ b/Tests/LinuxMain.swift @@ -0,0 +1,9 @@ +#if os(Linux) +import XCTest + +@testable import SwiftServerLibraryTests + +XCTMain([ + testCase(ItemTests.allTests) +]) +#endif \ No newline at end of file