Skip to content

Commit 3f08ab4

Browse files
committed
Chapter 16 updated
1 parent 49d429a commit 3f08ab4

File tree

10 files changed

+265
-7
lines changed

10 files changed

+265
-7
lines changed
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
name: deploy
2+
on:
3+
push:
4+
branches:
5+
- master
6+
jobs:
7+
deploy_aws_ecs:
8+
steps:
9+
- uses: actions/checkout@v2
10+
11+
- name: AWS - Config
12+
run: |
13+
aws configure set aws_access_key_id ${{ secrets.AWS_KEY }} --profile default
14+
aws configure set aws_secret_access_key ${{ secrets.AWS_SECRET }} --profile default
15+
aws configure set region ${{ secrets.AWS_REGION }} --profile default
16+
17+
- name: AWS ECR - Login
18+
run: |
19+
LOGIN_COMMAND=$(aws ecr get-login --no-include-email --region ${{ secrets.AWS_REGION }})
20+
$LOGIN_COMMAND
21+
22+
- name: Docker - Build image
23+
run: |
24+
docker build \
25+
--build-arg AWS_RDS_HOST=${{secrets.AWS_RDS_HOST}} \
26+
--build-arg AWS_RDS_USER=${{secrets.AWS_RDS_USER}} \
27+
--build-arg AWS_RDS_PASS=${{secrets.AWS_RDS_PASS}} \
28+
--build-arg AWS_RDS_DB=${{secrets.AWS_RDS_DB}} \
29+
--build-arg AWS_S3_REGION=${{secrets.AWS_S3_REGION}} \
30+
--build-arg AWS_S3_BUCKET=${{secrets.AWS_S3_BUCKET}} \
31+
-t "${{ secrets.AWS_ECR_IMAGE_NAME }}:latest" -f Dockerfile .
32+
33+
- name: Docker - Push image
34+
run: docker push "${{ secrets.AWS_ECR_IMAGE_NAME }}:latest"
35+
36+
- name: AWS ECS - deploy image
37+
run: |
38+
aws ecs update-service --cluster "${{ secrets.AWS_ECS_CLUSTER }}" \
39+
--service "${{ secrets.AWS_ECS_SERVICE }}" \
40+
--force-new-deployment
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
name: test
2+
on:
3+
- pull_request
4+
5+
jobs:
6+
7+
test_on_macos:
8+
runs-on: macos-latest
9+
env:
10+
DEVELOPER_DIR: /Applications/Xcode_12.app/Contents/Developer
11+
steps:
12+
- uses: actions/checkout@v2
13+
- run: xcrun swift test --enable-test-discovery --sanitize=thread
14+
15+
test_on_ubuntu_xenial:
16+
container:
17+
image: vapor/swift:5.2.2-xenial-ci
18+
runs-on: ubuntu-latest
19+
steps:
20+
- run: apt update -y; apt install -y libsqlite3-dev
21+
- uses: actions/checkout@v2
22+
- run: swift test --enable-test-discovery --sanitize=thread
23+
24+
test_on_ubuntu_bionic:
25+
container:
26+
image: vapor/swift:5.2.2-bionic-ci
27+
runs-on: ubuntu-latest
28+
steps:
29+
- run: apt update -y; apt install -y libsqlite3-dev
30+
- uses: actions/checkout@v2
31+
- run: swift test --enable-test-discovery --sanitize=thread

Chapter 16/myProject/Dockerfile

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# Build image
2+
FROM swift:5.3-focal as build
3+
4+
RUN apt-get update -y \
5+
&& apt-get install -y libsqlite3-dev
6+
7+
WORKDIR /build
8+
9+
COPY . .
10+
11+
RUN for f in Sources/App/Modules/*; do \
12+
m=$(basename $f); \
13+
cp -r "${f}/Views/" "Resources/Views/${m}" 2>/dev/null; \
14+
done; \
15+
exit 0;
16+
17+
RUN swift build \
18+
--enable-test-discovery \
19+
-c release \
20+
-Xswiftc -g
21+
22+
23+
# Run image
24+
FROM swift:5.3-focal-slim
25+
26+
RUN useradd --user-group --create-home --home-dir /app vapor
27+
28+
WORKDIR /app
29+
30+
COPY --from=build --chown=vapor:vapor /build/.build/release /app
31+
COPY --from=build --chown=vapor:vapor /build/Public /app/Public
32+
COPY --from=build --chown=vapor:vapor /build/Resources /app/Resources
33+
34+
USER vapor
35+
ENTRYPOINT ["./Run"]
36+
CMD ["serve", "--env", "production", "--hostname", "0.0.0.0", "--port", "8080"]

Chapter 16/myProject/Package.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,12 @@ let package = Package(
1313
.package(url: "https://github.com/vapor/leaf-kit", from: "1.0.0-tau"),
1414
.package(url: "https://github.com/vapor/fluent", from: "4.0.0"),
1515
.package(url: "https://github.com/vapor/fluent-sqlite-driver", from: "4.0.0"),
16+
.package(url: "https://github.com/vapor/fluent-postgres-driver", from: "2.0.0"),
1617
.package(url: "https://github.com/vapor/jwt", from: "4.0.0"),
1718
.package(name: "apns", url: "https://github.com/vapor/apns", from: "1.0.0"),
1819
.package(url: "https://github.com/binarybirds/liquid", from: "1.1.0"),
1920
.package(url: "https://github.com/binarybirds/liquid-local-driver", from: "1.1.0"),
21+
.package(url: "https://github.com/binarybirds/liquid-aws-s3-driver", from: "1.0.5"),
2022
.package(url: "https://github.com/lukaskubanek/LoremSwiftum", from: "2.2.1"),
2123
.package(name: "MyProjectApi", path: "../MyProjectApi"),
2224
.package(url: "https://github.com/binarybirds/spec", from: "1.1.0"),
@@ -30,8 +32,10 @@ let package = Package(
3032
.product(name: "Leaf", package: "leaf"),
3133
.product(name: "Fluent", package: "fluent"),
3234
.product(name: "FluentSQLiteDriver", package: "fluent-sqlite-driver"),
35+
.product(name: "FluentPostgresDriver", package: "fluent-postgres-driver"),
3336
.product(name: "Liquid", package: "liquid"),
3437
.product(name: "LiquidLocalDriver", package: "liquid-local-driver"),
38+
.product(name: "LiquidAwsS3Driver", package: "liquid-aws-s3-driver"),
3539
.product(name: "JWT", package: "jwt"),
3640
.product(name: "APNS", package: "apns"),
3741
.product(name: "LoremSwiftum", package: "LoremSwiftum"),

Chapter 16/myProject/Sources/App/Extensions/Environment+App.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,20 @@ extension Environment {
2727
/// com.example.ios.app
2828
static let topic = Environment.get("APNS_TOPIC")!
2929
}
30+
31+
struct Postgres {
32+
/// postgres://myuser:mypass@localhost:5432/mydb
33+
//static let connectionUrl = Environment.get("PSQL_CONNECTION_URL")!
34+
35+
static let host = Environment.get("DB_HOST")!
36+
static let port = Int(Environment.get("DB_PORT")!)!
37+
static let user = Environment.get("DB_USER")!
38+
static let pass = Environment.get("DB_PASS")!
39+
static let database = Environment.get("DB_NAME")!
40+
}
41+
42+
struct Aws {
43+
static let region = Environment.get("AWS_REGION")!
44+
static let bucket = Environment.get("AWS_BUCKET")!
45+
}
3046
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import Vapor
2+
import Fluent
3+
import FluentSQLiteDriver
4+
5+
final class UtilityDatabaseTransferCommand: Command {
6+
7+
static let name = "database-transfer"
8+
9+
struct Signature: CommandSignature { }
10+
11+
let help = "Transfer database models from one db to another"
12+
13+
func run(using context: CommandContext, signature: Signature) throws {
14+
let app = context.application
15+
16+
app.databases.use(.sqlite(.file("db.sqlite")), as: .sqlite, isDefault: false)
17+
18+
let frames = ["","","","","","","","","",""]
19+
.map { $0 + " Transfer in progress..."}
20+
21+
let loadingBar = context.console.customActivity(frames: frames)
22+
23+
24+
25+
let sourceDb = app.databases.database(.sqlite,
26+
logger: app.logger,
27+
on: app.eventLoopGroup.next())!
28+
29+
let targetDb = app.databases.database(.psql,
30+
logger: app.logger,
31+
on: app.eventLoopGroup.next())!
32+
33+
loadingBar.start()
34+
35+
do {
36+
// wipe target db first
37+
try UserModel.query(on: targetDb).delete().wait()
38+
try BlogPostModel.query(on: targetDb).delete().wait()
39+
try BlogCategoryModel.query(on: targetDb).delete().wait()
40+
41+
// create existing items on the target db
42+
try UserModel.query(on: sourceDb).all()
43+
.flatMap {
44+
$0.map { UserModel(id: $0.id, email: $0.email, password: $0.password) }
45+
.create(on: targetDb)
46+
}
47+
.wait()
48+
49+
try BlogCategoryModel.query(on: sourceDb).all().flatMap {
50+
$0.map { BlogCategoryModel(id: $0.id, title: $0.title) }
51+
.create(on: targetDb)
52+
}.wait()
53+
54+
try BlogPostModel.query(on: sourceDb)
55+
.with(\.$category)
56+
.all()
57+
.flatMap {
58+
$0.map { BlogPostModel(id: $0.id,
59+
title: $0.title,
60+
slug: $0.slug,
61+
image: $0.image,
62+
excerpt: $0.excerpt,
63+
date: $0.date,
64+
content: $0.content,
65+
categoryId: $0.category.id!) }
66+
.create(on: targetDb)
67+
}.wait()
68+
69+
loadingBar.succeed()
70+
}
71+
catch {
72+
loadingBar.fail()
73+
context.console.error("Error: \(error.localizedDescription)")
74+
}
75+
}
76+
}

Chapter 16/myProject/Sources/App/Modules/Utility/UtilityCommandGroup.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ struct UtilityCommandGroup: CommandGroup {
1414

1515
commands = [
1616
UtilityFileTransferCommand.name: UtilityFileTransferCommand(),
17+
UtilityDatabaseTransferCommand.name: UtilityDatabaseTransferCommand(),
1718
]
1819
}
1920
}

Chapter 16/myProject/Sources/App/configure.swift

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ import Vapor
22
import Leaf
33
import LeafFoundation
44
import Fluent
5-
import FluentSQLiteDriver
5+
import FluentPostgresDriver
66
import Liquid
7-
import LiquidLocalDriver
7+
import LiquidAwsS3Driver
88
import JWT
99
import APNS
1010
@_exported import ContentApi
@@ -37,12 +37,17 @@ public func configure(_ app: Application) throws {
3737
environment: .sandbox
3838
)
3939

40-
app.databases.use(.sqlite(.file("db.sqlite")), as: .sqlite)
41-
40+
let configuration = PostgresConfiguration(hostname: Environment.Postgres.host,
41+
port: Environment.Postgres.port,
42+
username: Environment.Postgres.user,
43+
password: Environment.Postgres.pass,
44+
database: Environment.Postgres.database)
45+
app.databases.use(.postgres(configuration: configuration), as: .psql)
46+
4247
app.routes.defaultMaxBodySize = "10mb"
43-
app.fileStorages.use(.local(publicUrl: "http://localhost:8080",
44-
publicPath: app.directory.publicDirectory,
45-
workDirectory: "assets"), as: .local)
48+
49+
app.fileStorages.use(.awsS3(region: .init(rawValue: Environment.Aws.region),
50+
bucket: .init(stringLiteral: Environment.Aws.bucket)), as: .awsS3)
4651

4752
app.sessions.use(.fluent)
4853
app.migrations.add(SessionRecord.migration)

Chapter 16/myProject/Tests/AppTests/AppTestCase.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@ import XCTVapor
33
import XCTLeafKit
44
import Leaf
55
import Fluent
6+
import FluentSQLiteDriver
7+
import Liquid
8+
import LiquidLocalDriver
9+
//...
610

711
extension XCTApplicationTester {
812
@discardableResult public func test<T>(
@@ -25,8 +29,16 @@ open class AppTestCase: LeafKitTestCase {
2529

2630
try configure(app)
2731
app.databases.reinitialize()
32+
2833
app.databases.use(.sqlite(.memory), as: .sqlite)
2934
app.databases.default(to: .sqlite)
35+
36+
app.fileStorages.reinitialize()
37+
app.fileStorages.use(.local(publicUrl: "http://localhost:8080",
38+
publicPath: app.directory.publicDirectory,
39+
workDirectory: "assets"), as: .local)
40+
app.fileStorages.default(to: .local)
41+
3042
try app.autoMigrate().wait()
3143
return app
3244
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
version: '3.7'
2+
3+
volumes:
4+
db_data:
5+
6+
x-shared_environment: &shared_environment
7+
LOG_LEVEL: ${LOG_LEVEL:-debug}
8+
DB_HOST: db
9+
DB_NAME: mydb
10+
DB_USER: myuser
11+
DB_PASS: mypass
12+
13+
services:
14+
15+
app:
16+
image: my-project:latest
17+
build:
18+
context: .
19+
environment:
20+
<<: *shared_environment
21+
depends_on:
22+
- db
23+
ports:
24+
- '8080:8080'
25+
26+
db:
27+
image: postgres:13.0-alpine
28+
volumes:
29+
- db_data:/var/lib/postgresql/data/pgdata
30+
environment:
31+
PGDATA: /var/lib/postgresql/data/pgdata
32+
POSTGRES_USER: myuser
33+
POSTGRES_PASSWORD: mypass
34+
POSTGRES_DB: mydb
35+
ports:
36+
- '5432:5432'
37+

0 commit comments

Comments
 (0)