diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..7706445 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,45 @@ +name: ci/cd + +on: + pull_request: + branches: + - 'main' + - 'develop' + push: + branches: + - 'main' + - 'develop' + +jobs: + build: + name: Test on OTP ${{ matrix.otp_version }} and ${{ matrix.os }} + runs-on: ${{ matrix.os }} + + strategy: + matrix: + otp_version: ['24', '23', '22', '21'] + os: [ubuntu-latest] + + steps: + - uses: actions/checkout@v2 + - uses: erlef/setup-beam@v1 + with: + otp-version: ${{ matrix.otp_version }} + rebar3-version: '3.15' + + - name: Compile + run: rebar3 compile + - name: EUnit tests + run: rebar3 eunit + - name: Dialyzer + run: rebar3 dialyzer + - name: XRef + run: rebar3 xref + + - name: Covertool + if: ${{ always() }} + run: rebar3 covertool generate + - uses: codecov/codecov-action@v1 + with: + file: _build/test/covertool/elli_websocket.covertool.xml + env_vars: OTP_VERSION diff --git a/.gitignore b/.gitignore index 121a4de..897d3ee 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,11 @@ erl_crash.dump logs _build .idea +*~ +\#*\# +/.emacs.desktop +/.emacs.desktop.lock +*.elc +auto-save-list +tramp +.\#* \ No newline at end of file diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 7fe4e02..0000000 --- a/.travis.yml +++ /dev/null @@ -1,20 +0,0 @@ -sudo: false -language: erlang -install: true -before_script: -- wget https://s3.amazonaws.com/rebar3/rebar3 -- chmod +x rebar3 -env: PATH=$PATH:. -cache: - directories: - - $HOME/.cache/rebar3/ -otp_release: -- 21.0 -- 20.2 -- 19.3 -- 19.0 -- 18.3 -- 18.0 -script: -- rebar3 as test do xref, dialyzer, eunit -- rebar3 as test coveralls send diff --git a/README.md b/README.md index 8f7c155..f653383 100644 --- a/README.md +++ b/README.md @@ -2,19 +2,22 @@ *A WebSocket handler for [elli][]* +[![Build Status][gh-actions-badge]][gh-actions] +[![Coverage Status][coveralls badge]][coveralls link] [![Hex.pm][hex badge]][hex package] +[![Tags][github tags badge]][github tags] [![Erlang][erlang badge]][erlang downloads] -[![Travis CI][travis badge]][travis builds] -[![Coverage Status][coveralls badge]][coveralls link] [![Apache License][license badge]](LICENSE) [elli]: https://github.com/elli-lib/elli [hex badge]: https://img.shields.io/hexpm/v/elli_websocket.svg [hex package]: https://hex.pm/packages/elli_websocket -[erlang badge]: https://img.shields.io/badge/erlang-%E2%89%A518.0-red.svg +[github tags]: https://github.com/elli-lib/elli_websocket/tags +[github tags badge]: https://img.shields.io/github/tag/elli-lib/elli_websocket.svg +[erlang badge]: https://img.shields.io/badge/erlang-%E2%89%A521.0-red.svg [erlang downloads]: http://www.erlang.org/downloads -[travis builds]: https://travis-ci.org/elli-lib/elli_websocket -[travis badge]: https://travis-ci.org/elli-lib/elli_websocket.svg +[gh-actions-badge]: https://github.com/elli-lib/elli_websocket/workflows/ci%2Fcd/badge.svg +[gh-actions]: https://github.com/elli-lib/elli_websocket/actions [coveralls badge]: https://coveralls.io/repos/github/elli-lib/elli_websocket/badge.svg?branch=develop [coveralls link]: https://coveralls.io/github/elli-lib/elli_websocket?branch=develop [license badge]: https://img.shields.io/hexpm/l/elli_websocket.svg diff --git a/rebar.config b/rebar.config index c42f29e..ef0d71e 100644 --- a/rebar.config +++ b/rebar.config @@ -3,6 +3,10 @@ {platform_define, "^2[1-9]", post20} ]}. +{deps, [ + {elli, "3.3.0"} +]}. + {xref_checks, [undefined_function_calls, locals_not_used]}. {dialyzer, [{base_plt_apps, [elli]}]}. @@ -11,12 +15,10 @@ {test, [ {erl_first_files, [ "src/elli_websocket_handler" - ]}, - {deps, [{elli, "3.1.0"}]} + ]} ]}, {docs, [ {deps, [ - {elli, "3.1.0"}, {edown, "0.8.1"} ]} ]} @@ -37,7 +39,7 @@ ]}. {project_plugins, [ - {coveralls, "1.5.0"}, + {covertool, "2.0.3"}, {rebar3_lint, "0.1.10"} ]}. @@ -45,6 +47,7 @@ {cover_enabled, true}. {cover_export_enabled, true}. -%% {cover_excl_mods, []}. -{coveralls_coverdata, "_build/test/cover/eunit.coverdata"}. -{coveralls_service_name, "travis-ci"}. +{cover_excl_mods, [ + elli_handler +]}. +{covertool, [{coverdata_files, ["eunit.coverdata"]}]}. diff --git a/rebar.config.script b/rebar.config.script deleted file mode 100644 index 1411e37..0000000 --- a/rebar.config.script +++ /dev/null @@ -1,7 +0,0 @@ -case os:getenv("TRAVIS") of - "true" -> - JobId = os:getenv("TRAVIS_JOB_ID"), - lists:keystore(coveralls_service_job_id, 1, CONFIG, - {coveralls_service_job_id, JobId}); - _ -> CONFIG -end. diff --git a/rebar.lock b/rebar.lock index 57afcca..f490fd9 100644 --- a/rebar.lock +++ b/rebar.lock @@ -1 +1,8 @@ -[]. +{"1.2.0", +[{<<"elli">>,{pkg,<<"elli">>,<<"3.3.0">>},0}]}. +[ +{pkg_hash,[ + {<<"elli">>, <<"089218762A7FF3D20AE81C8E911BD0F73EE4EE0ED85454226D1FC6B4FFF3B4F6">>}]}, +{pkg_hash_ext,[ + {<<"elli">>, <<"698B13B33D05661DB9FE7EFCBA41B84825A379CCE86E486CF6AFF9285BE0CCF8">>}]} +]. diff --git a/src/elli_websocket.app.src b/src/elli_websocket.app.src index 0ea9f26..61d67a5 100644 --- a/src/elli_websocket.app.src +++ b/src/elli_websocket.app.src @@ -1,6 +1,6 @@ {application, elli_websocket, [ {description, "Elli WebSocket Handler."}, - {vsn, "0.1.1"}, + {vsn, "0.1.2"}, {modules, []}, {registered, []}, {applications, [kernel, stdlib, elli]}, diff --git a/src/elli_ws_protocol.erl b/src/elli_ws_protocol.erl index bdf4b47..d211fc0 100644 --- a/src/elli_ws_protocol.erl +++ b/src/elli_ws_protocol.erl @@ -38,6 +38,8 @@ -module(elli_ws_protocol). +-include_lib("elli/src/elli_util.hrl"). + %% Ignore the deprecation warning for crypto:sha/1. %% @todo Remove when we support only R16B+. -compile(nowarn_deprecated_function). @@ -92,14 +94,16 @@ upgrade(Req, Env, Handler, HandlerOpts) -> try websocket_upgrade(State, Req) of {ok, State2, Req2} -> handler_init(State2, Req2, HandlerOpts) catch - throw:Exc -> - handle_event(Req, Handler, websocket_throw, [Exc, erlang:get_stacktrace()], HandlerOpts), + throw:{ResponseCode, Headers, Body} when is_integer(ResponseCode) -> + {response, ResponseCode, Headers, Body}; + ?WITH_STACKTRACE(throw, Exc, Stacktrace) + handle_event(Req, Handler, websocket_throw, [Exc, Stacktrace], HandlerOpts), elli_ws_request_adapter:maybe_reply(400, Req); - error:Error -> - handle_event(Req, Handler, websocket_error, [Error, erlang:get_stacktrace()], HandlerOpts), + ?WITH_STACKTRACE(error, Error, Stacktrace) + handle_event(Req, Handler, websocket_error, [Error, Stacktrace], HandlerOpts), elli_ws_request_adapter:maybe_reply(400, Req); - exit:Exit -> - handle_event(Req, Handler, websocket_exit, [Exit, erlang:get_stacktrace()], HandlerOpts), + ?WITH_STACKTRACE(exit, Exit, Stacktrace) + handle_event(Req, Handler, websocket_exit, [Exit, Stacktrace], HandlerOpts), elli_ws_request_adapter:maybe_reply(400, Req) end. @@ -169,14 +173,16 @@ handler_init(State=#state{env=Env, handler=Handler}, Req, HandlerOpts) -> elli_ws_request_adapter:ensure_response(Req2, 400), {ok, Req2, [{result, closed}|Env]} catch - throw:Exc -> - handle_event(Req, Handler, websocket_throw, [Exc, erlang:get_stacktrace()], HandlerOpts), + throw:{ResponseCode, Headers, Body} when is_integer(ResponseCode) -> + {response, ResponseCode, Headers, Body}; + ?WITH_STACKTRACE(throw, Exc, Stacktrace) + handle_event(Req, Handler, websocket_throw, [Exc, Stacktrace], HandlerOpts), elli_ws_request_adapter:maybe_reply(400, Req); - error:Error -> - handle_event(Req, Handler, websocket_error, [Error, erlang:get_stacktrace()], HandlerOpts), + ?WITH_STACKTRACE(error, Error, Stacktrace) + handle_event(Req, Handler, websocket_error, [Error, Stacktrace], HandlerOpts), elli_ws_request_adapter:maybe_reply(400, Req); - exit:Exit -> - handle_event(Req, Handler, websocket_exit, [Exit, erlang:get_stacktrace()], HandlerOpts), + ?WITH_STACKTRACE(exit, Exit, Stacktrace) + handle_event(Req, Handler, websocket_exit, [Exit, Stacktrace], HandlerOpts), elli_ws_request_adapter:maybe_reply(400, Req) end. @@ -665,12 +671,14 @@ handler_call(State=#state{handler=Handler}, Req, HandlerState, {shutdown, Req2, HandlerState2} -> websocket_close(State, Req2, HandlerState2, {normal, shutdown}) catch - throw:Exc -> - handle_event(Req, Handler, websocket_throw, [Exc, erlang:get_stacktrace()], HandlerState); - error:Error -> - handle_event(Req, Handler, websocket_error, [Error, erlang:get_stacktrace()], HandlerState); - exit:Exit -> - handle_event(Req, Handler, websocket_exit, [Exit, erlang:get_stacktrace()], HandlerState) + throw:{ResponseCode, Headers, Body} when is_integer(ResponseCode) -> + {response, ResponseCode, Headers, Body}; + ?WITH_STACKTRACE(throw, Exc, Stacktrace) + handle_event(Req, Handler, websocket_throw, [Exc, Stacktrace], HandlerState); + ?WITH_STACKTRACE(error, Error, Stacktrace) + handle_event(Req, Handler, websocket_error, [Error, Stacktrace], HandlerState); + ?WITH_STACKTRACE(exit, Exit, Stacktrace) + handle_event(Req, Handler, websocket_exit, [Exit, Stacktrace], HandlerState) end. websocket_opcode(text) -> 1;