diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e549ad1..d4ce7ce 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -27,6 +27,7 @@ jobs: persist-credentials: false - name: Set up Elixir + id: setup-beam uses: erlef/setup-beam@61e01a43a562a89bfc54c7f9a378ff67b03e4a21 # v1.16.0 with: version-type: strict @@ -35,20 +36,20 @@ jobs: - name: Restore dependencies cache uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2 env: - cache-name: mix-deps + cache-key: deps with: - path: deps - key: ${{ runner.os }}-${{ env.cache-name }}-${{ hashFiles('**/mix.lock') }} - restore-keys: ${{ runner.os }}-${{ env.cache-name }}- + key: ${{ env.cache-key }}-${{ runner.os }}-${{ steps.setup-beam.outputs.otp-version }}-${{ steps.setup-beam.outputs.elixir-version }}-${{ hashFiles('**/mix.lock') }}-git-${{ github.sha }} + restore-keys: | + ${{ env.cache-key }}-${{ runner.os }}-${{ steps.setup-beam.outputs.otp-version }}-${{ steps.setup-beam.outputs.elixir-version }}-${{ hashFiles('**/mix.lock') }} + ${{ env.cache-key }}-${{ runner.os }}-${{ steps.setup-beam.outputs.otp-version }}-${{ steps.setup-beam.outputs.elixir-version }} + path: | + deps + _build - - name: Restore build cache - uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2 - env: - cache-name: mix-build - with: - path: _build - key: ${{ runner.os }}-${{ env.cache-name }}-${{ hashFiles('**/mix.lock') }} - restore-keys: ${{ runner.os }}-${{ env.cache-name }}- + - name: Install dependencies + run: | + mix local.hex --force + mix do deps.get, deps.compile - name: Use Node.js LTS uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 7d4769b..5ca6959 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -12,64 +12,130 @@ on: permissions: contents: read -env: - MIX_ENV: test - jobs: # ignore the push event trigger if a PR is open for the current branch - prevent-duplicate-checks: + prevent_duplicate_checks: runs-on: ubuntu-latest steps: - - uses: insurgent-lab/is-in-pr-action@78ecb5daf15aca198aeb2b6f208aabd06b2cb716 # v0.1.4 + - uses: insurgent-lab/is-in-pr-action@3e01b38aa0d2a0e51bbc84540300303ec850e80d # v0.1.5 id: isInPR outputs: should-run: ${{ !(steps.isInPR.outputs.result == 'true' && github.event_name == 'push') }} - test: - name: Build and test + test_matrix: + name: Test (Elixir ${{matrix.elixir}} | OTP ${{matrix.otp}}) - runs-on: ubuntu-latest - timeout-minutes: 5 + runs-on: ${{ matrix.os }} + timeout-minutes: 10 + + needs: prevent_duplicate_checks + if: ${{ needs.prevent_duplicate_checks.outputs.should-run == 'true' }} - needs: prevent-duplicate-checks - if: ${{ needs.prevent-duplicate-checks.outputs.should-run == 'true' }} + strategy: + fail-fast: false + matrix: + include: + - elixir: 1.12.x + otp: 22 + os: ubuntu-20.04 + - elixir: 1.13.x + otp: 23 + os: ubuntu-20.04 + - elixir: 1.14.x + otp: 24 + os: ubuntu-22.04 + - elixir: 1.15.x + otp: 25 + os: ubuntu-22.04 + - elixir: 1.16.x + otp: 26 + os: ubuntu-latest + + env: + MIX_ENV: test steps: - name: Checkout code uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - - name: Set up Elixir + - name: Set up BEAM + id: setup-beam uses: erlef/setup-beam@61e01a43a562a89bfc54c7f9a378ff67b03e4a21 # v1.16.0 with: - version-type: strict - version-file: .tool-versions + otp-version: ${{matrix.otp}} + elixir-version: ${{matrix.elixir}} - name: Restore dependencies cache uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2 env: - cache-name: mix-deps + cache-key: deps with: - path: deps - key: ${{ runner.os }}-${{ env.cache-name }}-${{ hashFiles('**/mix.lock') }} - restore-keys: ${{ runner.os }}-${{ env.cache-name }}- - - - name: Restore build cache - uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2 - env: - cache-name: mix-build - with: - path: _build - key: ${{ runner.os }}-${{ env.cache-name }}-${{ hashFiles('**/mix.lock') }} - restore-keys: ${{ runner.os }}-${{ env.cache-name }}- + key: ${{ env.cache-key }}-${{ runner.os }}-${{ steps.setup-beam.outputs.otp-version }}-${{ steps.setup-beam.outputs.elixir-version }}-${{ hashFiles('**/mix.lock') }}-git-${{ github.sha }} + restore-keys: | + ${{ env.cache-key }}-${{ runner.os }}-${{ steps.setup-beam.outputs.otp-version }}-${{ steps.setup-beam.outputs.elixir-version }}-${{ hashFiles('**/mix.lock') }} + ${{ env.cache-key }}-${{ runner.os }}-${{ steps.setup-beam.outputs.otp-version }}-${{ steps.setup-beam.outputs.elixir-version }} + path: | + deps + _build - name: Install dependencies - run: mix deps.get + run: | + mix local.hex --force + mix do deps.get, deps.compile - name: Check formatting run: mix format --check-formatted - - name: Compile code (without warning) and deps + - name: Compile code (without warning) run: mix compile --warnings-as-errors - name: Run tests run: mix test + + # Dialyzer + + - name: Restore PLTs cache + id: restore_plts_cache + uses: actions/cache/restore@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2 + env: + cache-key: plts + with: + key: ${{ env.cache-key }}-${{ runner.os }}-${{ steps.setup-beam.outputs.otp-version }}-${{ steps.setup-beam.outputs.elixir-version }}-${{ hashFiles('**/mix.lock') }}-git-${{ github.sha }} + restore-keys: | + ${{ env.cache-key }}-${{ runner.os }}-${{ steps.setup-beam.outputs.otp-version }}-${{ steps.setup-beam.outputs.elixir-version }}-${{ hashFiles('**/mix.lock') }} + ${{ env.cache-key }}-${{ runner.os }}-${{ steps.setup-beam.outputs.otp-version }}-${{ steps.setup-beam.outputs.elixir-version }} + path: priv/plts + + - name: Create PLTs + if: steps.restore_plts_cache.outputs.cache-hit != 'true' + run: | + mkdir -p priv/plts/core.plt + mix dialyzer --plt + + - name: Save PLTs cache + uses: actions/cache/save@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2 + env: + cache-key: plts + if: steps.restore_plts_cache.outputs.cache-hit != 'true' + with: + key: ${{ env.cache-key }}-${{ runner.os }}-${{ steps.setup-beam.outputs.otp-version }}-${{ steps.setup-beam.outputs.elixir-version }}-${{ hashFiles('**/mix.lock') }}-git-${{ github.sha }} + path: priv/plts + + - name: Run dialyzer + run: mix dialyzer --format github + + # separate job to set as required status check in branch protection + required_check: + runs-on: ubuntu-latest + needs: + - prevent_duplicate_checks + - test_matrix + + if: ${{ !cancelled() && needs.prevent_duplicate_checks.outputs.should-run == 'true' }} + steps: + - name: All required jobs and matrix versions passed + if: ${{ !(contains(needs.*.result, 'failure')) }} + run: exit 0 + - name: Some required jobs or matrix versions failed + if: ${{ contains(needs.*.result, 'failure') }} + run: exit 1 diff --git a/.gitignore b/.gitignore index e993be5..d9610f4 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,7 @@ nodelix-*.tar # Node.js dependencies directory node_modules + +# Dialyzer +/priv/plts/*.plt +/priv/plts/*.plt.hash diff --git a/mix.exs b/mix.exs index 5aa3101..ba7a72c 100644 --- a/mix.exs +++ b/mix.exs @@ -8,9 +8,10 @@ defmodule Nodelix.MixProject do [ app: :nodelix, version: @version, - elixir: "~> 1.12.3 or ~> 1.13", + elixir: "~> 1.12", start_permanent: Mix.env() == :prod, deps: deps(), + dialyzer: dialyzer(), description: description(), package: package(), docs: docs(), @@ -18,6 +19,30 @@ defmodule Nodelix.MixProject do ] end + def application do + [ + extra_applications: [:crypto, :logger, inets: :optional, ssl: :optional], + mod: {Nodelix, []}, + env: [default: []] + ] + end + + defp deps do + [ + {:gpg_ex, "1.0.0-alpha.3"}, + {:castore, "~> 1.0"}, + {:dialyxir, "~> 1.4", only: [:dev, :test], runtime: false}, + {:ex_doc, ">= 0.0.0", only: :dev, runtime: false} + ] + end + + defp dialyzer() do + [ + plt_local_path: "priv/plts/project.plt", + plt_core_path: "priv/plts/core.plt" + ] + end + defp description() do """ Seamless Node.js in Elixir. @@ -42,20 +67,4 @@ defmodule Nodelix.MixProject do extras: ["README.md", "CHANGELOG.md", "LICENSE.md"] ] end - - def application do - [ - extra_applications: [:crypto, :logger, inets: :optional, ssl: :optional], - mod: {Nodelix, []}, - env: [default: []] - ] - end - - defp deps do - [ - {:gpg_ex, "1.0.0-alpha.3"}, - {:castore, "~> 1.0"}, - {:ex_doc, ">= 0.0.0", only: :dev, runtime: false} - ] - end end diff --git a/mix.lock b/mix.lock index 2829057..43a8dc5 100644 --- a/mix.lock +++ b/mix.lock @@ -1,7 +1,9 @@ %{ "castore": {:hex, :castore, "1.0.4", "ff4d0fb2e6411c0479b1d965a814ea6d00e51eb2f58697446e9c41a97d940b28", [:mix], [], "hexpm", "9418c1b8144e11656f0be99943db4caf04612e3eaecefb5dae9a2a87565584f8"}, + "dialyxir": {:hex, :dialyxir, "1.4.2", "764a6e8e7a354f0ba95d58418178d486065ead1f69ad89782817c296d0d746a5", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "516603d8067b2fd585319e4b13d3674ad4f314a5902ba8130cd97dc902ce6bbd"}, "earmark_parser": {:hex, :earmark_parser, "1.4.38", "b42252eddf63bda05554ba8be93a1262dc0920c721f1aaf989f5de0f73a2e367", [:mix], [], "hexpm", "2cd0907795aaef0c7e8442e376633c5b3bd6edc8dbbdc539b22f095501c1cdb6"}, "elixir_uuid": {:hex, :elixir_uuid, "1.2.1", "dce506597acb7e6b0daeaff52ff6a9043f5919a4c3315abb4143f0b00378c097", [:mix], [], "hexpm", "f7eba2ea6c3555cea09706492716b0d87397b88946e6380898c2889d68585752"}, + "erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"}, "ex_doc": {:hex, :ex_doc, "0.30.9", "d691453495c47434c0f2052b08dd91cc32bc4e1a218f86884563448ee2502dd2", [:mix], [{:earmark_parser, "~> 1.4.31", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "d7aaaf21e95dc5cddabf89063327e96867d00013963eadf2c6ad135506a8bc10"}, "gpg_ex": {:hex, :gpg_ex, "1.0.0-alpha.3", "d5860bb91b8c833441770f38707ad0556074ab5772f8e1dfc71ddedf7cae9e78", [:mix], [{:elixir_uuid, "~> 1.2", [hex: :elixir_uuid, repo: "hexpm", optional: false]}], "hexpm", "748d4283f0a62836afa07d27944f54c29cd6f02bd238ab1f72534f5273745630"}, "makeup": {:hex, :makeup, "1.1.1", "fa0bc768698053b2b3869fa8a62616501ff9d11a562f3ce39580d60860c3a55e", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "5dc62fbdd0de44de194898b6710692490be74baa02d9d108bc29f007783b0b48"},