Feat: Library template (#22)

* docs: Update README link to rebar3 templates

* refactor: switch to default elvis rulesets

* feat: more comprehensive gitignore in templates

* feat: Add erlang_ls config

* feat: Add editorconfig

* refactor: split templates in common and service parts

* feat: Add rebar3_lint to service/rebar.config

* refactor: move rebar script to service templates

* feat: Add shell to service Makefile

* refactor: move service-specific elvis config

* refactor: Use plugin-based linter in service Makefile

* feat: Add rebar.config for file formatting

* feat: Add library templates

* refactor: Structure service template

* docs: Rewrite docs for library

* deps: Update plugin versions

* ci: Fix caching on local `act` for lib templates

* fix: remove unnecesary distclean dirs for cleaning

* test: Add test jobs for library template

* deps: update build_utils

* fix: I've fixed my tab settings

* feat: Wercker -> build_utils+Jenkins for service

* ci: Fix wc_gen commands

* fix: format service erl templates

* fix: another try at jenkinsfile

* ci: move pipeline defs

* ci: move build_utils init

* ci: submodule -> clone build_utils

* fix: Use build_utils to test library template as well

* ci: Fix make arg order

* ci: cp Makefile.ci and optimize repo Makefile

* ci: Fix Makefile.ci path

* ci: Pass service docker-files to lib for testing

* feat: Remove custom macro name rules

* ci: fix typo

* ci: fix path typo

* ci: change chmod pos

* fix: Remove erlang_ls and ext. gitignore
This commit is contained in:
Yaroslav Rogov 2021-05-19 20:10:43 +03:00 committed by GitHub
parent 422fb39fad
commit 067f1e3921
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
34 changed files with 565 additions and 109 deletions

3
.gitignore vendored
View File

@ -5,4 +5,7 @@
.DS_Store
snakeoil
Dockerfile
_build
# Rebar is only used for erlfmt: lock file has no meaning
rebar.lock

105
Jenkinsfile vendored
View File

@ -9,13 +9,28 @@ def finalHook = {
}
build('erlang-service-template', 'docker-host', finalHook) {
runStage('clone build_utils') {
withGithubSshCredentials {
sh "git clone git@github.com:rbkmoney/build_utils.git build_utils"
}
}
def pipeDefault
def withWsCache
runStage('load library pipeline') {
env.JENKINS_LIB = "build_utils/jenkins_lib"
pipeDefault = load("${env.JENKINS_LIB}/pipeDefault.groovy")
withWsCache = load("${env.JENKINS_LIB}/withWsCache.groovy")
}
// erlang-service-template
ws {
try {
checkoutRepo()
loadBuildUtils()
runStage('generate erlang service: snakeoil') {
sh 'make wc_gen'
sh 'make wc_gen_service'
}
runStage('archive snakeoil') {
@ -48,14 +63,6 @@ build('erlang-service-template', 'docker-host', finalHook) {
}
}
def pipeDefault
def withWsCache
runStage('load service pipeline') {
env.JENKINS_LIB = "build_utils/jenkins_lib"
pipeDefault = load("${env.JENKINS_LIB}/pipeDefault.groovy")
withWsCache = load("${env.JENKINS_LIB}/withWsCache.groovy")
}
pipeDefault() {
def imageTags = "BASE_IMAGE_TAG=51bd5f25d00cbf75616e2d672601dfe7351dcaa4 BUILD_IMAGE_TAG=61a001bbb48128895735a3ac35b0858484fdb2eb"
@ -67,6 +74,9 @@ build('erlang-service-template', 'docker-host', finalHook) {
runStage('lint service') {
sh "make wc_lint ${imageTags}"
}
runStage('check formatting for service') {
sh "make wc_check_format ${imageTags}"
}
runStage('xref service') {
sh "make wc_xref ${imageTags}"
}
@ -85,5 +95,80 @@ build('erlang-service-template', 'docker-host', finalHook) {
}
}
}
}
// erlang-library-template
ws {
try {
checkoutRepo()
loadBuildUtils()
runStage('generate erlang library: trickster') {
sh 'make wc_gen_library'
sh """
cp \\
library-templates/Makefile.ci \\
service-templates/Dockerfile.sh \\
service-templates/docker-compose.sh \\
trickster/
"""
}
runStage('archive trickster') {
archive 'trickster/'
}
} finally {
runStage('cleanup sub ws') {
sh 'rm -rf * .* || echo ignore'
}
}
} //close other ws
runStage('unarchive trickster') {
unarchive mapping: ['trickster/': '.']
sh 'chmod 755 trickster/Dockerfile.sh trickster/docker-compose.sh'
}
dir('trickster') {
runStage('init git repo') {
sh 'git init'
sh 'git config user.email "$CHANGE_AUTHOR_EMAIL"'
sh 'git config user.name "$COMMIT_AUTHOR"'
sh 'git add README.md'
sh 'git commit -m "Initial commit"'
}
runStage('add git submodule') {
withGithubSshCredentials {
sh "git submodule add -b master git@github.com:rbkmoney/build_utils.git build_utils"
}
}
pipeDefault() {
def imageTags = "BASE_IMAGE_TAG=51bd5f25d00cbf75616e2d672601dfe7351dcaa4 BUILD_IMAGE_TAG=61a001bbb48128895735a3ac35b0858484fdb2eb"
runStage('compile library') {
withGithubPrivkey {
sh "make --file=Makefile.ci wc_compile ${imageTags}"
}
}
runStage('lint library') {
sh "make --file=Makefile.ci wc_lint ${imageTags}"
}
runStage('check formatting for library') {
sh "make --file=Makefile.ci wc_check_format ${imageTags}"
}
runStage('xref library') {
sh "make --file=Makefile.ci wc_xref ${imageTags}"
}
runStage('dialyze library') {
withWsCache("_build/default/rebar3_23.2.3_plt") {
sh "make --file=Makefile.ci wc_dialyze ${imageTags}"
}
}
runStage('test library') {
sh "make --file=Makefile.ci wdeps_test ${imageTags}"
}
}
}
}

View File

@ -7,7 +7,7 @@ SERVICE_NAME := service_erlang
BUILD_IMAGE_NAME := build-erlang
BUILD_IMAGE_TAG := 61a001bbb48128895735a3ac35b0858484fdb2eb
CALL_W_CONTAINER := all gen submodules clean
CALL_W_CONTAINER := all gen_service gen_library submodules clean
all: gen
@ -21,13 +21,17 @@ $(SUBTARGETS): %/.git: %
submodules: $(SUBTARGETS)
add_template:
~/.config/rebar3/templates:
mkdir -p ~/.config/rebar3/templates
cp -rv ./* ~/.config/rebar3/templates
gen: add_template
add_template: ~/.config/rebar3/templates
gen_service: add_template
rebar3 new erlang-service name=snakeoil
gen_library: add_template
rebar3 new erlang-service name=trickster
clean:
rm Dockerfile

View File

@ -33,7 +33,6 @@ $ git submodule init
> * GNU Make
> * [rebar3](http://www.rebar3.org/)
> * [elvis](https://github.com/inaka/elvis/releases)
> * [wercker cli](http://devcenter.wercker.com/cli/index.html)
>
> К счастью, теперь все это доступно в build образе, работать с которым легко и удобно через `make`:
> * wc_<target> - запустить в build контейнере
@ -60,4 +59,4 @@ erlang-service:
apps_dir="apps" (Directory where applications will be created if needed)
```
В случае необходимости доработки в первую очередь обращайтесь к [официальной документации](http://www.rebar3.org/docs/using-templates).
В случае необходимости доработки в первую очередь обращайтесь к [официальной документации](http://rebar3.org/docs/tutorials/templates/).

@ -1 +1 @@
Subproject commit e1318727d4d0c3e48f5122bf3197158b6695f50e
Subproject commit 24aa772730be966667adb285a09fcb494d4f218e

View File

@ -0,0 +1,8 @@
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
indent_size = 4
indent_style = space
trim_trailing_whitespace = true
max_line_length = 120

View File

@ -0,0 +1,13 @@
# Build artifacts
/_build/
*.o
*.beam
*.plt
# Run artifacts
erl_crash.dump
log
# Files generated from scripts
Dockerfile
docker-compose.yml

35
erlang-library.template Normal file
View File

@ -0,0 +1,35 @@
{description, "Erlang OTP Library"}.
{variables, [
{name, "myapp", "Name of the library, an application with this name will also be created"},
{description, "A library that does something", "Short description of purpose of the library"},
{version, "1", "Initial version string"}
]}.
%% Project and plugins
{template, "library-templates/rebar.config", "{{name}}/rebar.config"}.
{template, "library-templates/elvis.config", "{{name}}/elvis.config"}.
{dir, "{{name}}/include"}.
{dir, "{{name}}/test"}.
%% Code
{template, "library-templates/src/app.app.src", "{{name}}/src/{{name}}.app.src"}.
{template, "library-templates/src/app.erl", "{{name}}/src/{{name}}.erl"}.
%% Build
{template, "library-templates/Makefile", "{{name}}/Makefile"}.
%% VCS setup
{template, "common-templates/gitignore", "{{name}}/.gitignore"}.
%% Docs
{template, "library-templates/README.md", "{{name}}/README.md"}.
%% Tools
{file, "common-templates/editorconfig", "{{name}}/.editorconfig"}.
%% CI/CD
{file, "library-templates/github/workflows/code-checks.yml", "{{name}}/.github/workflows/code-checks.yml"}.
%% Licenses
{file, "common-templates/LICENSE", "{{name}}/LICENSE"}.

View File

@ -1,12 +0,0 @@
# general
log
/_build/
*~
erl_crash.dump
.tags*
*.sublime-workspace
.DS_Store
.edts
Dockerfile
docker-compose.yml

View File

@ -1,5 +0,0 @@
case os:getenv("WERCKER_CACHE_DIR") of
false -> CONFIG;
[] -> CONFIG;
Dir -> lists:keystore(global_rebar_dir, 1, CONFIG, {global_rebar_dir, Dir})
end.

View File

@ -6,22 +6,37 @@
{version, "1", "Initial version string"}
]}.
{template, "erlang-service-files/apps/app/src/app.app.src", "{{name}}/{{apps_dir}}/{{name}}/src/{{name}}.app.src"}.
{template, "erlang-service-files/apps/app/src/app.erl", "{{name}}/{{apps_dir}}/{{name}}/src/{{name}}.erl"}.
{template, "erlang-service-files/apps/app/test/app_tests_SUITE.erl", "{{name}}/{{apps_dir}}/{{name}}/test/{{name}}_tests_SUITE.erl"}.
{template, "erlang-service-files/config/sys.config", "{{name}}/config/sys.config"}.
{template, "erlang-service-files/config/vm.args", "{{name}}/config/vm.args"}.
{template, "erlang-service-files/doc/index.md", "{{name}}/doc/index.md"}.
{template, "erlang-service-files/rebar.config", "{{name}}/rebar.config"}.
{template, "erlang-service-files/elvis.config", "{{name}}/elvis.config"}.
{template, "erlang-service-files/rebar.config.script", "{{name}}/rebar.config.script"}.
{template, "erlang-service-files/gitignore", "{{name}}/.gitignore"}.
{template, "erlang-service-files/README.md", "{{name}}/README.md"}.
{template, "erlang-service-files/Makefile", "{{name}}/Makefile"}.
{template, "erlang-service-files/Jenkinsfile", "{{name}}/Jenkinsfile"}.
{template, "erlang-service-files/Dockerfile.sh", "{{name}}/Dockerfile.sh"}.
{chmod, "{{name}}/Dockerfile.sh", 8#755}.
{template, "erlang-service-files/docker-compose.sh", "{{name}}/docker-compose.sh"}.
{chmod, "{{name}}/docker-compose.sh", 8#755}.
{file, "erlang-service-files/LICENSE", "{{name}}/LICENSE"}.
%% Project and plugins
{template, "service-templates/rebar.config", "{{name}}/rebar.config"}.
{template, "service-templates/elvis.config", "{{name}}/elvis.config"}.
%% Code
{template, "service-templates/apps/app/src/app.app.src", "{{name}}/{{apps_dir}}/{{name}}/src/{{name}}.app.src"}.
{template, "service-templates/apps/app/src/app.erl", "{{name}}/{{apps_dir}}/{{name}}/src/{{name}}.erl"}.
{template, "service-templates/apps/app/test/app_tests_SUITE.erl",
"{{name}}/{{apps_dir}}/{{name}}/test/{{name}}_tests_SUITE.erl"}.
{template, "service-templates/config/sys.config", "{{name}}/config/sys.config"}.
{template, "service-templates/config/vm.args", "{{name}}/config/vm.args"}.
%% Build
{template, "service-templates/Makefile", "{{name}}/Makefile"}.
{template, "service-templates/Dockerfile.sh", "{{name}}/Dockerfile.sh"}.
{chmod, "{{name}}/Dockerfile.sh", 8#755}.
{template, "service-templates/docker-compose.sh", "{{name}}/docker-compose.sh"}.
{chmod, "{{name}}/docker-compose.sh", 8#755}.
%% VCS
{template, "common-templates/gitignore", "{{name}}/.gitignore"}.
%% Docs
{template, "service-templates/README.md", "{{name}}/README.md"}.
{template, "service-templates/doc/index.md", "{{name}}/doc/index.md"}.
%% Tools
{file, "common-templates/editorconfig", "{{name}}/.editorconfig"}.
%% CI/CD
{template, "service-templates/Jenkinsfile", "{{name}}/Jenkinsfile"}.
%% Licenses
{file, "common-templates/LICENSE", "{{name}}/LICENSE"}.

View File

@ -0,0 +1,43 @@
REBAR := $(shell which rebar3 2>/dev/null || which ./rebar3)
.PHONY: all get_deps ensure_elvis compile lint check_format \
format test xref clean distclean dialyze plt_update shell
all: compile
get_deps:
$(REBAR) get-deps
compile:
$(REBAR) compile
shell: submodules
$(REBAR) shell
lint:
$(REBAR) lint
check_format:
$(REBAR) fmt -c
format:
$(REBAR) fmt -w
test:
$(REBAR) do eunit, proper
xref:
$(REBAR) xref
clean:
$(REBAR) clean
distclean:
$(REBAR) clean -a
rm -rfv _build
dialyze:
$(REBAR) dialyzer
plt_update:
$(REBAR) dialyzer -u true -s false

View File

@ -0,0 +1,77 @@
REBAR := $(shell which rebar3 2>/dev/null || which ./rebar3)
SUBMODULES = build_utils
SUBTARGETS = $(patsubst %,%/.git,$(SUBMODULES))
UTILS_PATH := build_utils
TEMPLATES_PATH := .
# Name of the service
SERVICE_NAME := {{name}}
# Service image default tag
SERVICE_IMAGE_TAG ?= $(shell git rev-parse HEAD)
# The tag for service image to be pushed with
SERVICE_IMAGE_PUSH_TAG ?= $(SERVICE_IMAGE_TAG)
# Base image for the service
BASE_IMAGE_NAME := service_erlang
BASE_IMAGE_TAG := $(BASE_IMAGE_TAG) # Replace with the current version (tag) for service_erlang image!
# Build image tag to be used
BUILD_IMAGE_NAME := build-erlang
BUILD_IMAGE_TAG := $(BUILD_IMAGE_TAG) # Replace with the current version (tag) for build image!
CALL_ANYWHERE := all submodules compile xref lint dialyze plt_update test \
shell release clean distclean format check_format
# Hint: 'test' might be a candidate for CALL_W_CONTAINER-only target
CALL_W_CONTAINER := $(CALL_ANYWHERE)
.PHONY: $(CALL_W_CONTAINER)
all: compile
-include $(UTILS_PATH)/make_lib/utils_container.mk
-include $(UTILS_PATH)/make_lib/utils_image.mk
$(SUBTARGETS): %/.git: %
git submodule update --init $<
touch $@
submodules: $(SUBTARGETS)
compile: submodules
$(REBAR) compile
shell: submodules
$(REBAR) shell
lint:
$(REBAR) lint
check_format:
$(REBAR) fmt -c
format:
$(REBAR) fmt -w
test: submodules
$(REBAR) do eunit, ct
xref: submodules
$(REBAR) xref
clean:
$(REBAR) clean
distclean:
$(REBAR) clean -a
rm -rfv _build
dialyze:
$(REBAR) dialyzer
plt_update:
$(REBAR) dialyzer -u true -s false
release: submodules
$(REBAR) as prod release

View File

@ -0,0 +1,21 @@
# {{name}}
{{description}}
## Сборка
Для запуска процесса сборки достаточно выполнить просто:
make
Чтобы запустить проект в режиме разработки и получить стандартный [Erlang shell][2], нужно всего лишь:
make shell
## CI/CD
Данная библиотека проходит автоматическую проверку с помощью Github Actions, которую можно также запустить локально с помощью [act](https://github.com/nektos/act):
```
act
```
> _Хозяйке на заметку._ В зависимости от вашего окружения и операционной системы вам может понадобиться [Docker Machine][4].

View File

@ -0,0 +1,49 @@
[
{elvis, [
{config, [
#{
dirs => ["src", "include", "test"],
filter => "*.erl",
ruleset => erl_files,
rules => [
{elvis_text_style, line_length, #{limit => 120}},
{elvis_text_style, no_trailing_whitespace, #{ignore_empty_lines => true}},
{elvis_style, nesting_level, #{level => 3, ignore => [genlib_trunc_io]}},
{elvis_style, atom_naming_convention, disable},
{elvis_style, function_naming_convention, #{regex => "^([a-z][a-z0-9]*_?)*$"}},
{elvis_style, no_if_expression, disable}
]
},
#{
dirs => ["."],
filter => "Makefile",
ruleset => makefiles
},
#{
dirs => ["."],
filter => "elvis.config",
ruleset => elvis_config
},
#{
dirs => ["."],
filter => "rebar.config",
ruleset => rebar_config,
rules => [
{elvis_text_style, line_length, #{limit => 120, skip_comments => false}},
{elvis_text_style, no_tabs},
{elvis_text_style, no_trailing_whitespace}
]
},
#{
dirs => ["src"],
filter => "*.app.src",
rules => [
{elvis_text_style, line_length, #{limit => 120, skip_comments => false}},
{elvis_text_style, no_tabs},
{elvis_text_style, no_trailing_whitespace}
]
}
]}
]}
].

View File

@ -0,0 +1,37 @@
name: Erlang Code Checks
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
build:
runs-on: ubuntu-latest
container:
image: erlang:22.0.7
steps:
- uses: actions/checkout@v2
- name: Cache build
if: ${{ !env.ACT }}
id: cache-build
uses: actions/cache@v2
with:
path: "_build/default/"
key: ${{ runner.os }}-${{ hashFiles('rebar.lock') }}-build-default
- name: Fetch Deps
run: make get_deps
- name: Compile
run: make compile
- name: Run Xref
run: make xref
- name: Run Dialyzer
run: make dialyze
- name: Run erlfmt
run: make check_format
- name: Run linter
run: make lint
- name: Run tests (eunit, proper)
run: make test

View File

@ -0,0 +1,70 @@
%% Common project erlang options.
{erl_opts, [
% mandatory
debug_info,
warnings_as_errors,
warn_export_all,
warn_missing_spec,
warn_untyped_record,
warn_export_vars,
% by default
warn_unused_record,
warn_bif_clash,
warn_obsolete_guard,
warn_unused_vars,
warn_shadow_vars,
warn_unused_import,
warn_unused_function,
warn_deprecated_function
% at will
% bin_opt_info
% no_auto_import
% warn_missing_spec_all
]}.
%% Common project dependencies.
{deps, []}.
%% XRef checks
{xref_checks, [
undefined_function_calls,
undefined_functions,
deprecated_functions_calls,
deprecated_functions
]}.
% at will
% {xref_warnings, true}.
%% Tests
{cover_enabled, true}.
%% Dialyzer static analyzing
{dialyzer, [
{warnings, [
% mandatory
unmatched_returns,
error_handling,
race_conditions,
unknown
]},
{plt_apps, all_deps}
]}.
{profiles, [
{test, [
{deps, [proper]}
]}
]}.
{plugins, [
{erlfmt, "0.14.1"},
{rebar3_proper, "0.12.1"},
{rebar3_lint, "0.4.0"}
]}.
{erlfmt, [
{print_width, 120},
{files, ["{src,include,test}/*.{hrl,erl}", "rebar.config", "elvis.config"]}
]}.

View File

@ -0,0 +1,14 @@
{application, {{name}} , [
{description, "{{description}}"},
{vsn, "{{version}}"},
{applications, [
kernel,
stdlib
]},
{env, []},
{maintainers, [
"{{author_name}} <{{author_email}}>"
]},
{licenses, ["Apache 2.0"]},
{links, []}
]}.

View File

@ -0,0 +1 @@
-module({{name}}).

13
rebar.config Normal file
View File

@ -0,0 +1,13 @@
{plugins, [
{erlfmt, "0.10.0"}
]}.
{erlfmt, [
{print_width, 120},
{files, [
"rebar.config",
"*.template",
"service-templates/{rebar.config,elvis.config}",
"library-templates/{rebar.config,elvis.config}"
]}
]}.

View File

@ -21,7 +21,7 @@ BUILD_IMAGE_NAME := build-erlang
BUILD_IMAGE_TAG := $(BUILD_IMAGE_TAG) # Replace with the current version (tag) for build image!
CALL_ANYWHERE := all submodules compile xref lint dialyze plt_update test \
release clean distclean format check_format
shell release clean distclean format check_format
# Hint: 'test' might be a candidate for CALL_W_CONTAINER-only target
CALL_W_CONTAINER := $(CALL_ANYWHERE)
@ -42,8 +42,11 @@ submodules: $(SUBTARGETS)
compile: submodules
$(REBAR) compile
shell: submodules
$(REBAR) shell
lint:
elvis rock
$(REBAR) lint
check_format:
$(REBAR) fmt -c
@ -62,7 +65,7 @@ clean:
distclean:
$(REBAR) clean -a
rm -rfv _build _builds _cache _steps _temp
rm -rfv _build
dialyze:
$(REBAR) dialyzer
@ -72,4 +75,3 @@ plt_update:
release: submodules
$(REBAR) as prod release

View File

@ -14,17 +14,17 @@
> _Хозяйке на заметку._ При этом используется стандартный Erlang релиз, собранный при помощи [relx][3] в режиме разработчика.
Рекомендуется вести разработку и сборку проекта в рамках локальной виртуальной среды, предоставляемой [wercker][1]. Настоятельно рекомендуется прогоны тестовых сценариев проводить только в этой среде.
Рекомендуется вести разработку и сборку проекта в рамках локальной виртуальной среды, предоставляемой локальным Makefile и Make задачами `wc_`, предоставляемыми [`build_utils`][1], которые дублируют задачи местного Makefile, но выполняются в контейнере с необходимой средой ([при условии установки `build_utils`](https://github.com/rbkmoney/erlang-service-template/blob/master/README.md)). Настоятельно рекомендуется прогоны тестовых сценариев проводить только в этой среде.
$ wercker dev
$ make wc_all
> _Хозяйке на заметку._ В зависимости от вашего окружения и операционной системы вам может понадобиться [Docker Machine][4].
## Документация
Дальнейшую документацию можно почерпнуть, пройдясь по ссылкам в [соответствующем документе](doc/index.md).
Дальнейшую документацию можно почерпнуть, пройдясь по ссылкам в [соответствующем документе](doc/index.md).
[1]: http://devcenter.wercker.com/learn/basics/the-wercker-cli.html
[1]: https://github.com/rbkmoney/build_utils
[2]: http://erlang.org/doc/man/shell.html
[3]: https://github.com/erlware/relx
[4]: https://docs.docker.com/machine/install-machine/

View File

@ -7,47 +7,44 @@
%% API
-export([start/0]).
-export([stop /0]).
-export([stop/0]).
%% Supervisor callbacks
-export([init/1]).
%% Application callbacks
-export([start/2]).
-export([stop /1]).
-export([stop/1]).
%%
%% API
%%
-spec start() ->
{ok, _}.
-spec start() -> {ok, _}.
start() ->
application:ensure_all_started({{name}}).
-spec stop() ->
ok.
-spec stop() -> ok.
stop() ->
application:stop({{name}}).
%%
%% Supervisor callbacks
%%
-spec init([]) ->
{ok, {supervisor:sup_flags(), [supervisor:child_spec()]}}.
-spec init([]) -> {ok, {supervisor:sup_flags(), [supervisor:child_spec()]}}.
init([]) ->
{ok, {
{one_for_all, 0, 1}, []
}}.
{ok,
{
{one_for_all, 0, 1},
[]
}}.
%%
%% Application callbacks
%%
-spec start(normal, any()) ->
{ok, pid()} | {error, any()}.
-spec start(normal, any()) -> {ok, pid()} | {error, any()}.
start(_StartType, _StartArgs) ->
supervisor:start_link({local, ?MODULE}, ?MODULE, []).
-spec stop(any()) ->
ok.
-spec stop(any()) -> ok.
stop(_State) ->
ok.

View File

@ -1,10 +1,10 @@
-module({{name}}_tests_SUITE).
-include_lib("common_test/include/ct.hrl").
-export([all /0]).
-export([all/0]).
-export([init_per_suite/1]).
-export([end_per_suite /1]).
-export([dummy_test /1]).
-export([end_per_suite/1]).
-export([dummy_test/1]).
-type test_name() :: atom().
-type config() :: [{atom(), _}].
@ -12,8 +12,7 @@
%%
%% tests descriptions
%%
-spec all() ->
[test_name()].
-spec all() -> [test_name()].
all() ->
[
dummy_test
@ -22,18 +21,16 @@ all() ->
%%
%% starting/stopping
%%
-spec init_per_suite(config()) ->
config().
-spec init_per_suite(config()) -> config().
init_per_suite(C) ->
{ok, Apps} = application:ensure_all_started({{name}}),
[{apps, Apps}|C].
[{apps, Apps} | C].
-spec end_per_suite(config()) ->
any().
-spec end_per_suite(config()) -> any().
end_per_suite(C) ->
[application_stop(App) || App <- proplists:get_value(apps, C)].
application_stop(App=sasl) ->
application_stop(App = sasl) ->
%% hack for preventing sasl deadlock
%% http://erlang.org/pipermail/erlang-questions/2014-May/079012.html
error_logger:delete_report_handler(cth_log_redirect),
@ -46,7 +43,6 @@ application_stop(App) ->
%%
%% tests
%%
-spec dummy_test(config()) ->
any().
-spec dummy_test(config()) -> any().
dummy_test(_C) ->
ok.

View File

@ -2,27 +2,18 @@
{elvis, [
{config, [
#{
dirs => ["apps/*/src"],
dirs => ["apps/*/src", "apps/*/include", "apps/*/test"],
filter => "*.erl",
ignore => ["_thrift.erl$"],
ruleset => erl_files,
rules => [
{elvis_text_style, line_length, #{limit => 120, skip_comments => false}},
{elvis_text_style, no_tabs},
{elvis_text_style, no_trailing_whitespace},
{elvis_style, macro_module_names},
{elvis_style, operator_spaces, #{rules => [{right, ","}, {right, "++"}, {left, "++"}]}},
{elvis_style, nesting_level, #{level => 3}},
{elvis_style, god_modules, #{limit => 25}},
{elvis_style, no_if_expression},
{elvis_style, invalid_dynamic_call, #{ignore => [elvis]}},
{elvis_style, used_ignored_variable},
{elvis_style, no_behavior_info},
{elvis_style, module_naming_convention, #{regex => "^([a-z][a-z0-9]*_?)*(_SUITE)?$"}},
{elvis_text_style, line_length, #{limit => 120}},
{elvis_text_style, no_trailing_whitespace, #{ignore_empty_lines => true}},
{elvis_style, nesting_level, #{level => 3, ignore => [genlib_trunc_io]}},
{elvis_style, atom_naming_convention, disable},
{elvis_style, function_naming_convention, #{regex => "^([a-z][a-z0-9]*_?)*$"}},
{elvis_style, state_record_and_type},
{elvis_style, no_spec_with_records},
{elvis_style, dont_repeat_yourself, #{min_complexity => 10}},
{elvis_style, no_debug_call, #{ignore => [elvis, elvis_utils]}}
{elvis_style, no_if_expression, disable}
]
},
#{
@ -47,6 +38,7 @@
#{
dirs => ["."],
filter => "rebar.config",
ruleset => rebar_config,
rules => [
{elvis_text_style, line_length, #{limit => 120, skip_comments => false}},
{elvis_text_style, no_tabs},

View File

@ -1,6 +1,5 @@
%% Common project erlang options.
{erl_opts, [
% mandatory
debug_info,
warnings_as_errors,
@ -26,8 +25,7 @@
]}.
%% Common project dependencies.
{deps, [
]}.
{deps, []}.
%% XRef checks
{xref_checks, [
@ -81,7 +79,8 @@
]}.
{plugins, [
{erlfmt, "0.10.0"}
{erlfmt, "0.14.1"},
{rebar3_lint, "0.4.0"}
]}.
{erlfmt, [