From e4d402d3368501ee2cce054db795f875a3e9fa38 Mon Sep 17 00:00:00 2001 From: "Paulo F. Oliveira" Date: Thu, 27 Jul 2023 17:39:15 +0100 Subject: [PATCH 1/4] Update code for the new OTP 22-27 maintenance range In CI we also update some of the action tools' versions --- .github/workflows/main.yml | 36 +++++++++++++----- rebar.config | 6 +-- src/elli_http.erl | 78 ++++++++------------------------------ src/elli_tcp.erl | 13 ------- src/elli_util.hrl | 13 ------- test/elli_tests.erl | 6 --- 6 files changed, 44 insertions(+), 108 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 6f7fbee..2d16b5e 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -10,21 +10,38 @@ on: jobs: build: - name: Test on OTP ${{ matrix.otp_version }} and ${{ matrix.os }} - runs-on: ${{ matrix.os }} + name: Test on OTP ${{ matrix.tuple.otp_version }} and ${{ matrix.tuple.os }} + runs-on: ${{ matrix.tuple.os }} strategy: matrix: - otp_version: ['24', '23', '22', '21'] - os: [ubuntu-latest] + tuple: + - otp_version: 27 + os: ubuntu-22.04 + rebar3_version: 3.23 + - otp_version: 26 + os: ubuntu-22.04 + rebar3_version: 3.22 + - otp_version: 25 + os: ubuntu-22.04 + rebar3_version: 3.22 + - otp_version: 24 + os: ubuntu-22.04 + rebar3_version: 3.22 + - otp_version: 23 + os: ubuntu-20.04 + rebar3_version: 3.15 + - otp_version: 22 + os: ubuntu-20.04 + rebar3_version: 3.15 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - uses: erlef/setup-beam@v1 with: - otp-version: ${{ matrix.otp_version }} - rebar3-version: '3.14' + otp-version: ${{ matrix.tuple.otp_version }} + rebar3-version: ${{ matrix.tuple.rebar3_version }} - name: Compile run: rebar3 compile @@ -36,9 +53,8 @@ jobs: run: rebar3 xref - name: Covertool - if: ${{ always() }} run: rebar3 covertool generate - - uses: codecov/codecov-action@v1 + - uses: codecov/codecov-action@v4 with: - file: _build/test/covertool/elli.covertool.xml + files: _build/test/covertool/elli.covertool.xml env_vars: OTP_VERSION diff --git a/rebar.config b/rebar.config index 07ba484..682c417 100644 --- a/rebar.config +++ b/rebar.config @@ -1,9 +1,7 @@ {erl_first_files, ["src/elli_handler.erl"]}. {erl_opts, [debug_info, - {i, "include"}, - {platform_define, "^2", binary_http_uri}, - {platform_define, "^2[1-9]", post20}]}. -{minimum_otp_vsn, "20.0"}. + {i, "include"}]}. +{minimum_otp_vsn, "22.0"}. {deps, []}. {xref_checks, [undefined_function_calls,locals_not_used]}. {profiles, [ diff --git a/src/elli_http.erl b/src/elli_http.erl index 4404a76..cd549e4 100644 --- a/src/elli_http.erl +++ b/src/elli_http.erl @@ -323,17 +323,17 @@ execute_callback(#req{callback = {Mod, Args}} = Req) -> catch throw:{ResponseCode, Headers, Body} when is_integer(ResponseCode) -> {response, ResponseCode, Headers, Body}; - ?WITH_STACKTRACE(throw, Exc, Stacktrace) + throw:Exc:Stacktrace -> handle_event(Mod, request_throw, [Req, Exc, Stacktrace], Args), {response, 500, [], <<"Internal server error">>}; - ?WITH_STACKTRACE(error, Error, Stacktrace) + error:Error:Stacktrace -> handle_event(Mod, request_error, [Req, Error, Stacktrace], Args), {response, 500, [], <<"Internal server error">>}; - ?WITH_STACKTRACE(exit, Exit, Stacktrace) + exit:Exit:Stacktrace -> handle_event(Mod, request_exit, [Req, Exit, Stacktrace], Args), @@ -708,7 +708,6 @@ is_header_defined(Key, Headers) -> get_header(Key, Headers) -> get_header(Key, Headers, undefined). --ifdef(OTP_RELEASE). get_header(Key, Headers, Default) -> CaseFoldedKey = string:casefold(Key), case lists:search(fun({N, _}) -> string:equal(CaseFoldedKey, N, true) end, Headers) of @@ -717,68 +716,23 @@ get_header(Key, Headers, Default) -> false -> Default end. --else. -get_header(Key, Headers, Default) -> - CaseFoldedKey = string:casefold(Key), - case search(fun({N, _}) -> string:equal(CaseFoldedKey, N, true) end, Headers) of - {value, {_, Value}} -> - Value; - false -> - Default - end. - -search(Pred, [Hd|Tail]) -> - case Pred(Hd) of - true -> {value, Hd}; - false -> search(Pred, Tail) - end; -search(Pred, []) when is_function(Pred, 1) -> - false. --endif. %% %% PATH HELPERS %% --ifdef(OTP_RELEASE). - -if(?OTP_RELEASE >= 22). - parse_path({abs_path, FullPath}) -> - URIMap = uri_string:parse(FullPath), - Host = maps:get(host, URIMap, undefined), - Scheme = maps:get(scheme, URIMap, undefined), - Path = maps:get(path, URIMap, <<>>), - Query = maps:get(query, URIMap, <<>>), - Port = maps:get(port, URIMap, case Scheme of http -> 80; https -> 443; _ -> undefined end), - {ok, {Scheme, Host, Port}, {Path, split_path(Path), uri_string:dissect_query(Query)}}; - parse_path({absoluteURI, Scheme, Host, Port, Path}) -> - setelement(2, parse_path({abs_path, Path}), {Scheme, Host, Port}); - parse_path(_) -> - {error, unsupported_uri}. - -else. - parse_path({abs_path, FullPath}) -> - Parsed = case binary:split(FullPath, [<<"?">>]) of - [URL] -> {FullPath, split_path(URL), []}; - [URL, Args] -> {FullPath, split_path(URL), split_args(Args)} - end, - {ok, {undefined, undefined, undefined}, Parsed}; - parse_path({absoluteURI, Scheme, Host, Port, Path}) -> - setelement(2, parse_path({abs_path, Path}), {Scheme, Host, Port}); - parse_path(_) -> - {error, unsupported_uri}. - -endif. --else. - %% same as else branch above. can drop this when only OTP 21+ is supported - parse_path({abs_path, FullPath}) -> - Parsed = case binary:split(FullPath, [<<"?">>]) of - [URL] -> {FullPath, split_path(URL), []}; - [URL, Args] -> {FullPath, split_path(URL), split_args(Args)} - end, - {ok, {undefined, undefined, undefined}, Parsed}; - parse_path({absoluteURI, Scheme, Host, Port, Path}) -> - setelement(2, parse_path({abs_path, Path}), {Scheme, Host, Port}); - parse_path(_) -> - {error, unsupported_uri}. --endif. +parse_path({abs_path, FullPath}) -> + URIMap = uri_string:parse(FullPath), + Host = maps:get(host, URIMap, undefined), + Scheme = maps:get(scheme, URIMap, undefined), + Path = maps:get(path, URIMap, <<>>), + Query = maps:get(query, URIMap, <<>>), + Port = maps:get(port, URIMap, case Scheme of http -> 80; https -> 443; _ -> undefined end), + {ok, {Scheme, Host, Port}, {Path, split_path(Path), uri_string:dissect_query(Query)}}; +parse_path({absoluteURI, Scheme, Host, Port, Path}) -> + setelement(2, parse_path({abs_path, Path}), {Scheme, Host, Port}); +parse_path(_) -> + {error, unsupported_uri}. split_path(Path) -> [P || P <- binary:split(Path, [<<"/">>], [global]), @@ -813,7 +767,7 @@ handle_event(Mod, Name, EventArgs, ElliArgs) -> try Mod:handle_event(Name, EventArgs, ElliArgs) catch - ?WITH_STACKTRACE(EvClass, EvError, Stacktrace) + EvClass:EvError:Stacktrace -> ?LOG_ERROR("~p:handle_event/3 crashed ~p:~p~n~p", [Mod, EvClass, EvError, Stacktrace]) end. diff --git a/src/elli_tcp.erl b/src/elli_tcp.erl index ee9ad39..b0f3fdc 100644 --- a/src/elli_tcp.erl +++ b/src/elli_tcp.erl @@ -42,7 +42,6 @@ accept({ssl, Socket}, Server, Timeout) -> {error, Reason} end. --ifdef(post20). handshake(S, Server, Timeout) -> case ssl:handshake(S, Timeout) of {ok, S1} -> @@ -53,18 +52,6 @@ handshake(S, Server, Timeout) -> {error, Reason} -> {error, Reason} end. --else. -handshake(S, Server, Timeout) -> - case ssl:ssl_accept(S, Timeout) of - ok -> - gen_server:cast(Server, accepted), - {ok, {ssl, S}}; - {error, closed} -> - {error, econnaborted}; - {error, Reason} -> - {error, Reason} - end. --endif. recv({plain, Socket}, Size, Timeout) -> gen_tcp:recv(Socket, Size, Timeout); diff --git a/src/elli_util.hrl b/src/elli_util.hrl index 557ec28..e844c95 100644 --- a/src/elli_util.hrl +++ b/src/elli_util.hrl @@ -1,17 +1,4 @@ - --ifdef(OTP_RELEASE). -include_lib("kernel/include/logger.hrl"). --else. --define(LOG_ERROR(Str), error_logger:error_msg(Str)). --define(LOG_ERROR(Format,Data), error_logger:error_msg(Format, Data)). --define(LOG_INFO(Format,Data), error_logger:info_msg(Format, Data)). --endif. - --ifdef(OTP_RELEASE). --define(WITH_STACKTRACE(T, R, S), T:R:S ->). --else. --define(WITH_STACKTRACE(T, R, S), T:R -> S = erlang:get_stacktrace(),). --endif. %% Bloody useful -define(IF(Test,True,False), case Test of true -> True; false -> False end). diff --git a/test/elli_tests.erl b/test/elli_tests.erl index c89ba17..fb62ed1 100644 --- a/test/elli_tests.erl +++ b/test/elli_tests.erl @@ -7,13 +7,7 @@ -define(VTB(T1, T2, LB, UB), time_diff_to_micro_seconds(T1, T2) >= LB andalso time_diff_to_micro_seconds(T1, T2) =< UB). --ifdef(OTP_RELEASE). -include_lib("kernel/include/logger.hrl"). --else. --define(LOG_ERROR(Str), error_logger:error_msg(Str)). --define(LOG_ERROR(Format,Data), error_logger:error_msg(Format, Data)). --define(LOG_INFO(Format,Data), error_logger:info_msg(Format, Data)). --endif. time_diff_to_micro_seconds(T1, T2) -> erlang:convert_time_unit( From 17072631b333ff645691fd0b7e63eabe4ed2052f Mon Sep 17 00:00:00 2001 From: "Paulo F. Oliveira" Date: Sat, 8 Jun 2024 17:37:05 +0100 Subject: [PATCH 2/4] Make it easier to debug in the current pull request We: - (temporarily) remove rebar3_lint to re-enable it later - stop failing fast (this can be considered as an enhancement) --- .github/workflows/main.yml | 1 + rebar.config | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 2d16b5e..885af14 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -14,6 +14,7 @@ jobs: runs-on: ${{ matrix.tuple.os }} strategy: + fail-fast: false matrix: tuple: - otp_version: 27 diff --git a/rebar.config b/rebar.config index 682c417..706b4e0 100644 --- a/rebar.config +++ b/rebar.config @@ -23,11 +23,11 @@ {shell, [{script_file, "bin/shell.escript"}]}. {project_plugins, [ - {covertool, "2.0.3"}, - {rebar3_lint, "v0.1.10"} + {covertool, "2.0.3"}%, + %{rebar3_lint, "v0.1.10"} ]}. -{provider_hooks, [{pre, [{eunit, lint}]}]}. +%{provider_hooks, [{pre, [{eunit, lint}]}]}. {dialyzer, [{plt_extra_apps, [ssl]}]}. {cover_enabled, true}. From 3c81e4c45ed1b7b7abc3e103a2ef3dacf8966e8f Mon Sep 17 00:00:00 2001 From: "Paulo F. Oliveira" Date: Sat, 8 Jun 2024 17:39:17 +0100 Subject: [PATCH 3/4] Temporarily remove support for 26 and 27 --- .github/workflows/main.yml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 885af14..a3127a1 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -17,12 +17,6 @@ jobs: fail-fast: false matrix: tuple: - - otp_version: 27 - os: ubuntu-22.04 - rebar3_version: 3.23 - - otp_version: 26 - os: ubuntu-22.04 - rebar3_version: 3.22 - otp_version: 25 os: ubuntu-22.04 rebar3_version: 3.22 From 9db9cc170b0d94bec0230111fa8358aabae0220e Mon Sep 17 00:00:00 2001 From: "Paulo F. Oliveira" Date: Sat, 8 Jun 2024 18:06:25 +0100 Subject: [PATCH 4/4] Implement cache in CI --- .github/workflows/main.yml | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index a3127a1..bbed24e 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -10,13 +10,13 @@ on: jobs: build: - name: Test on OTP ${{ matrix.tuple.otp_version }} and ${{ matrix.tuple.os }} - runs-on: ${{ matrix.tuple.os }} + name: Test on OTP ${{ matrix.otp_version }} and ${{ matrix.os }} + runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: - tuple: + include: - otp_version: 25 os: ubuntu-22.04 rebar3_version: 3.22 @@ -25,18 +25,39 @@ jobs: rebar3_version: 3.22 - otp_version: 23 os: ubuntu-20.04 - rebar3_version: 3.15 + rebar3_version: 3.18 - otp_version: 22 os: ubuntu-20.04 - rebar3_version: 3.15 + rebar3_version: 3.18 steps: - uses: actions/checkout@v4 - uses: erlef/setup-beam@v1 + id: setup-beam with: - otp-version: ${{ matrix.tuple.otp_version }} - rebar3-version: ${{ matrix.tuple.rebar3_version }} + otp-version: ${{ matrix.otp_version }} + rebar3-version: ${{ matrix.rebar3_version }} + + - name: Restore _build + uses: actions/cache@v3 + with: + path: _build + key: "_build-cache-for\ + -os-${{ matrix.os }}\ + -otp-${{ steps.setup-beam.outputs.otp-version }}\ + -rebar3-${{ steps.setup-beam.outputs.rebar3-version }}\ + -hash-${{ hashFiles('rebar.lock') }}" + + - name: Restore rebar3's cache + uses: actions/cache@v3 + with: + path: ~/.cache/rebar3 + key: "rebar3-cache-for\ + -os-${{ matrix.os }}\ + -otp-${{ steps.setup-beam.outputs.otp-version }}\ + -rebar3-${{ steps.setup-beam.outputs.rebar3-version }}\ + -hash-${{ hashFiles('rebar.lock') }}" - name: Compile run: rebar3 compile