Skip to content

Commit 79d720a

Browse files
author
Bunyod Bobojonov
committed
init
0 parents  commit 79d720a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+1799
-0
lines changed

.gitignore

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
.history
2+
.idea
3+
*.iml
4+
out
5+
*.ipr
6+
*.iws
7+
target
8+
.sonarwork
9+
*.log

.pre-commit-config.yaml

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
repos:
2+
- repo: https://github.com/pre-commit/pre-commit-hooks
3+
rev: v2.0.0
4+
hooks:
5+
- id: check-json
6+
- id: check-merge-conflict
7+
- id: check-xml
8+
- id: check-yaml
9+
- id: detect-private-key
10+
- repo: [email protected]:coyainsurance/pre-commit-scalafmt.git
11+
sha: master
12+
hooks:
13+
- id: scalafmt
14+
args: [-t ]
15+
16+
- repo: local
17+
hooks:
18+
- id: scalastyle
19+
name: scalastyle
20+
entry: scalastyle --config scalastyle-config.xml
21+
language: system
22+
files: \.(scala|sbt)$
23+
types: [file, text]

.scalafmt.conf

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
version=2.0.0-RC8
2+
style = defaultWithAlign
3+
maxColumn = 120
4+
lineEndings = unix
5+
importSelectors = singleLine
6+
docstrings = ScalaDoc
7+
8+
project {
9+
git = true
10+
}
11+
12+
align = none
13+
14+
align {
15+
tokens = [ {code = "=>", owner = "Case|Type.Arg.ByName"}, "<-", "->", "%", "%%" ]
16+
arrowEnumeratorGenerator = true
17+
openParenCallSite = false
18+
openParenDefnSite = false
19+
}
20+
21+
binPack {
22+
parentConstructors = true
23+
}
24+
25+
continuationIndent {
26+
callSite = 2
27+
defnSite = 2
28+
}
29+
30+
newlines {
31+
penalizeSingleSelectMultiArgList = false
32+
sometimesBeforeColonInMethodReturnType = true
33+
}
34+
35+
rewrite {
36+
rules = [RedundantBraces, RedundantParens, AsciiSortImports]
37+
redundantBraces {
38+
maxLines = 100
39+
includeUnitMethods = true
40+
stringInterpolation = true
41+
}
42+
}
43+
44+
spaces {
45+
inImportCurlyBraces = false
46+
beforeContextBoundColon = false
47+
}
48+
49+
assumeStandardLibraryStripMargin = true

Dockerfile

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
FROM 'hseeberger/scala-sbt:11.0.1_2.12.8_1.2.8' as build-env
2+
LABEL image=build-env
3+
ENV SONAR_SCANNER_VERSION 3.3.0.1492
4+
5+
ENV SONAR_RUNNER_HOME=/root/sonar_home
6+
COPY . /root
7+
# Add sonarScan to build step
8+
#RUN sbt scalastyle scapegoat coverage test coverageReport coverageOff scala213/assembly
9+
RUN sbt compile test:compile scala213/assembly
10+
FROM openjdk:8u181-slim as scala213-prod
11+
RUN mkdir -p /opt/scala-service
12+
COPY --from=build-env A B
13+
CMD ["java","-jar", "-Dconfig.resource=prod/application.conf", "/opt/scala-service/scala213-0.1.jar"]

Jenkinsfile

+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
pipeline {
2+
agent {
3+
label 'connectivity'
4+
}
5+
stages {
6+
stage('Build image') {
7+
steps {
8+
sh "docker image build --target build-env -t scala213-dev:${BUILD_NUMBER} ."
9+
}
10+
}
11+
stage('Code analysis') {
12+
steps {
13+
sh 'docker run --rm -v sbt-dev:/root scala213-dev:${BUILD_NUMBER} sbt scalastyle scapegoat'
14+
}
15+
}
16+
stage('Test Unit') {
17+
steps {
18+
sh 'docker run --rm -v sbt-dev:/root scala213-dev:${BUILD_NUMBER} sbt coverage test coverageReport'
19+
}
20+
}
21+
stage('Create production image') {
22+
when {
23+
anyOf {
24+
branch 'master'; branch 'refactoring'
25+
}
26+
}
27+
steps {
28+
sh "docker image build -t docker.bunic.de:5001/scala213:${BUILD_NUMBER} ."
29+
sh "docker push docker.bunic.de:5001/scala213:${BUILD_NUMBER}"
30+
}
31+
}
32+
stage('Deploy Stage') {
33+
when {
34+
anyOf {
35+
branch 'master';
36+
}
37+
}
38+
steps {
39+
sh 'echo \'{ \
40+
"container": { \
41+
"type": "DOCKER", \
42+
"docker": { \
43+
"image": "docker.bunic.de:5001/sscala213:\'$BUILD_NUMBER\'", \
44+
"network": "BRIDGE", \
45+
"portMappings": [ \
46+
{ \
47+
"containerPort": 8080, \
48+
"hostPort": 0, \
49+
"protocol": "tcp" \
50+
} \
51+
] \
52+
} \
53+
} \
54+
}\' | docker run -i k0pernikus/httpie-docker-alpine:1.0.0 PUT http://bunic.de/marathon/v2/apps/seed'
55+
}
56+
}
57+
stage('Deploy Production') {
58+
input {
59+
message "Deploy to production?"
60+
id "simple-input"
61+
}
62+
steps {
63+
echo 'deploy production'
64+
}
65+
}
66+
}
67+
}

LICENSE

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
This software is licensed under the Apache 2 license, quoted below.
2+
3+
Licensed under the Apache License, Version 2.0 (the "License"); you may not
4+
use this file except in compliance with the License. You may obtain a copy of
5+
the License at
6+
7+
[http://www.apache.org/licenses/LICENSE-2.0]
8+
9+
Unless required by applicable law or agreed to in writing, software
10+
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11+
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12+
License for the specific language governing permissions and limitations under
13+
the License.

README.md

+189
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
Scala 2.13 Project
2+
=============================
3+
4+
## Goal
5+
The goal for this project is to demonstrate how to start easily a new scala 2.13 project (using FP techniques? :) ).
6+
7+
## Stack technologies
8+
9+
- [JDK 8](http://www.oracle.com/technetwork/java/javase/downloads/index.html)
10+
- [SBT](http://www.scala-sbt.org/release/docs/Getting-Started/Setup.html)
11+
- [akka-http](https://doc.akka.io/docs/akka-http/current/) as the web server. I could have gone with finch, twitter server, or http4s here as well.
12+
- [Circe](https://circe.github.io/circe/) for json serialization
13+
- [Cats](https://typelevel.org/cats/) for FP awesomeness
14+
- [Scapegoat](https://github.com/sksamuel/scapegoat) for linting
15+
- [ScalaTest](http://www.scalatest.org/) for test
16+
17+
## Architecture
18+
### Domain Driven Design (DDD)
19+
Domain driven design is all about developing a _ubiquitous language_, which is a language that you can use to discuss your software with business folks (who presumably do not know programming).
20+
21+
DDD is all about making your code expressive, making sure that how you _talk_ about your software materializes in your code. One of the best ways to do this is to keep you _domain_ pure. That is, allow the business concepts and entities to be real things, and keep all the other cruft out. However, HTTP, JDBC, SQL are not essential to domain, so we want to _decouple_ those as much as possible.
22+
23+
### Onion (or Hexagonal) Architecture
24+
In concert with DDD, the [Onion Architecture](https://jeffreypalermo.com/2008/08/the-onion-architecture-part-3/) and [Hexagonal Architecture from Cockburn](https://java-design-patterns.com/patterns/hexagonal/) give us patterns on how to separate our domain from the ugliness of implementation.
25+
26+
We fit DDD an Onion together via the following mechanisms:
27+
28+
**The domain package**
29+
The domain package constitutes the things inside our domain. It is deliberately free of the ugliness of JDBC, JSON, HTTP, and the rest.
30+
We use `Services` as coarse-grained interfaces to our domain. These typically represent real-world use cases. Often times, you see a 1-to-1 mapping of `Services` to `R` or HTTP API calls your application surfaces.
31+
32+
Inside of the **domain**, we see a few concepts:
33+
34+
1. `Service` - the coarse grained use cases that work with other domain concepts to realize your use-cases
35+
1. `Repository` - ways to get data into and out of persistent storage. **Important: Repositories do not have any business logic in them, they should not know about the context in which they are used, and should not leak details of their implementations into the world**.
36+
1. `payloads` or `models` - things like `Tweet`, etc are all domain objects. We keep these lean (i.e. free of behavior).
37+
38+
**The repository package**
39+
The repository package is where the ugliness lives. It has JDBC things, and the like.
40+
it contains implementations of our `Repositories`. We may have 2 different implementations, an in-memory version as well as a **doobie** version.
41+
42+
**The http package**
43+
It contains the HTTP endpoints that we surface via **akka-http**. You will also typically see JSON things in here via **circe**
44+
45+
**The util package**
46+
The util package could be considered infrastructure, as it has nothing to do with the domain.
47+
48+
**NOTE**
49+
All business logic is located in `domain` package, every package inside is
50+
related to some domain.
51+
52+
Service classes contains high level logic that relate to data manipulation,
53+
that means that services MUST NOT implement storage.
54+
55+
For storage there are dedicated classes.
56+
57+
## Conventions
58+
59+
## Versioning
60+
61+
## Database
62+
63+
## Configuration
64+
1.`application.conf`
65+
1.`stage.application.conf`
66+
1.`prod.application.conf`
67+
We use **Pure Config** to load configuration objects when the application starts up. **pure config** Provides a neat mapping of config file to case classes for us, so we really do not have to do any code.
68+
69+
## Run
70+
71+
To run project locally and load the corresponding secretes, it is recommended to
72+
choose one of the following alternatives.
73+
74+
## Command line
75+
76+
In order to run locally on a developer machine via the command line, go to
77+
source folder and execute
78+
79+
```
80+
~/scala213/> sbt runServer
81+
```
82+
83+
For `<command>` use one of `~compile | test | run`
84+
85+
## IntelliJ
86+
FIXME
87+
1. Open settings (`File -> Settings or CTRL+ALT+S`)
88+
1. Choose Plugins
89+
1. Open "browse repositories" window and type `BashSupport`
90+
1. Click "Install" button and wait until the installation completes
91+
1. Restart Intellij IDEA
92+
1. Open Run/Debug Configuration (`Run -> Edit Configurations`)
93+
1. Click "+" button and select "Bash" item from drop down
94+
1. Give a name and select `sbt` file from source code
95+
1. Enter `run` into "Program arguments" field
96+
1. Click "Apply" and "OK"
97+
1. Click green button on the right side at the top of the window (or `Shift+F10`)
98+
99+
## Testing
100+
101+
```
102+
```
103+
104+
## Pre-Commit Hook
105+
106+
[Pre Commit](https://github.com/pre-commit/pre-commit) is a project on github to setup and maintain
107+
git commit hooks. The default hooks are defined in `.pre-commit-config.yaml`
108+
109+
For installation on osx run
110+
111+
```
112+
brew install pre-commit
113+
```
114+
115+
To setup the hooks with pre-commit run:
116+
117+
```
118+
pre-commit install -f --install-hooks
119+
```
120+
121+
After that scalafmt checks your changed files for codestyle:
122+
123+
_Note:_ Conflicts should be resolved
124+
125+
## Deployment
126+
127+
This section describes how to deploy `scala213` to either `STAGE` or `PROD`.
128+
129+
## Dependency Udpates
130+
131+
```
132+
sbt dependencyUpdates
133+
```
134+
135+
Lists newer versions of integrated dependencies from Maven/Ivy
136+
137+
sbt dependencyUpdates
138+
139+
## Linting
140+
141+
Linting is done via scapegoat. It is a static code analyzer inspecting the code with a set of 117 rules.
142+
Certain files can be excluded, rules can be changed. Configuration is described [here](https://github.com/sksamuel/scapegoat).
143+
144+
The report can be picked up by Jenkins and should be part of the deployment pipeline.
145+
146+
## Publish
147+
148+
Not to be confused with Sbt's "publishing"!.
149+
150+
```
151+
haha FIXME
152+
```
153+
154+
## Release
155+
156+
```
157+
haha FIXME
158+
```
159+
160+
## Resources
161+
162+
- For setting up the initial `seed` structure, we utilized
163+
[Scala Pet Store](https://github.com/pauljamescleary/scala-pet-store).
164+
165+
- For STAGE/ PROD configuration, we utilized [Production
166+
Configuration](https://www.playframework.com/documentation/2.6.x/ProductionConfiguration#overriding-configuration-with-system-properties)
167+
168+
## Known issues
169+
170+
### Configuration via Pureconfig
171+
172+
Pureconfig's config file does not support uppercase and underscores. [Read here](https://github.com/pureconfig/pureconfig/issues/394)
173+
174+
### sbt-partial-unification
175+
In order to use cats...
176+
177+
## How to use sbt-coverage
178+
179+
Run the tests with enabled coverage:
180+
```
181+
$ sbt clean test
182+
```
183+
184+
To generate the coverage reports run
185+
```
186+
$ sbt coverageReport
187+
```
188+
189+
Coverage reports will be in target/scala-2.12/scoverage-report/index.html.

api/src/it/resources/application.conf

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
http {
2+
host = "0.0.0.0"
3+
port = 8082
4+
}
5+
6+
auth {
7+
realm = "test"
8+
secret = "test"
9+
}
10+
11+
swagger {
12+
host = "localhost:9000"
13+
}

0 commit comments

Comments
 (0)