name: Elixir on: workflow_call: jobs: unit-test: runs-on: ubuntu-22.04 defaults: run: working-directory: ./elixir permissions: checks: write env: MIX_ENV: test POSTGRES_HOST: localhost GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} services: postgres: image: postgres:15.5 ports: - 5432:5432 env: POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres options: >- --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 steps: - uses: actions/checkout@v4 - uses: ./.github/actions/setup-elixir with: mix_env: ${{ env.MIX_ENV }} - name: Compile Application run: mix compile --warnings-as-errors - name: Setup Database run: | mix ecto.create mix ecto.migrate - name: Run Tests env: E2E_DEFAULT_WAIT_SECONDS: 20 CI_ASSERT_RECEIVE_TIMEOUT_MS: 250 run: | mix_test="mix test --warnings-as-errors --exclude flaky:true --exclude acceptance:true" $mix_test || $mix_test --failed - name: Test Report uses: dorny/test-reporter@v1 if: ${{ github.event.pull_request.head.repo.full_name == github.repository && (success() || failure()) }} with: name: Elixir Unit Test Report path: elixir/_build/test/lib/*/test-junit-report.xml reporter: java-junit type-check: runs-on: ubuntu-22.04 defaults: run: working-directory: ./elixir env: # We need to set MIX_ENV to dev to make sure that we won't type-check our test helpers MIX_ENV: dev GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} steps: - uses: actions/checkout@v4 - uses: ./.github/actions/setup-elixir id: setup-beam with: mix_env: ${{ env.MIX_ENV }} - name: Compile Application run: mix compile --warnings-as-errors - uses: actions/cache/restore@v4 name: Restore PLT cache id: plt_cache with: path: elixir/priv/plts key: dialyzer-ubuntu-22.04-${{ runner.arch }}-${{ steps.setup-beam.outputs.elixir-version }}-${{ hashFiles('elixir/mix.lock') }} # This will make sure that we can incrementally build the PLT from older cache and save it under a new key restore-keys: | dialyzer-ubuntu-22.04-${{ runner.arch }}-${{ steps.setup-beam.outputs.elixir-version }}- - name: Create PLTs if: ${{ steps.plt_cache.outputs.cache-hit != 'true' }} run: mix dialyzer --plt - uses: actions/cache/save@v4 if: ${{ github.ref_name == 'main' }} name: Save PLT cache with: key: ${{ steps.plt_cache.outputs.cache-primary-key }} path: elixir/priv/plts - name: Run Dialyzer run: mix dialyzer --format dialyxir static-analysis: runs-on: ubuntu-22.04 defaults: run: working-directory: ./elixir env: MIX_ENV: test GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} steps: - uses: actions/checkout@v4 - uses: ./.github/actions/setup-elixir with: mix_env: ${{ env.MIX_ENV }} - name: Compile Application run: mix compile --force --warnings-as-errors - name: Check Formatting run: mix format --check-formatted - name: Check For Retired Packages run: mix hex.audit - name: Check For Vulnerable Packages run: mix deps.audit - name: Run Sobelow vulnerability scanner for web app working-directory: ./elixir/apps/web run: mix sobelow --skip - name: Run Credo run: mix credo --strict - name: Check for unused deps run: mix deps.unlock --check-unused migrations-and-seed-test: runs-on: ubuntu-22.04 defaults: run: working-directory: ./elixir env: MIX_ENV: dev POSTGRES_HOST: localhost GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} services: postgres: image: postgres:15.5 ports: - 5432:5432 env: POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres options: >- --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 steps: - uses: actions/checkout@v4 - uses: ./.github/actions/setup-elixir with: mix_env: ${{ env.MIX_ENV }} - name: Compile run: mix compile --warnings-as-errors - name: Create Database run: mix ecto.create - name: Migrate DB to base ref and seed run: | git fetch --depth=1 origin ${{ github.base_ref }} git checkout ${{ github.base_ref }} mix deps.get mix ecto.migrate mix ecto.seed # Then checkout current ref and rerun migrations - name: Run new migrations run: | git checkout ${{ github.sha }} mix deps.get mix ecto.migrate mix ecto.reset mix ecto.migrate mix ecto.seed acceptance-test: name: acceptance-test-${{ matrix.MIX_TEST_PARTITION }} permissions: checks: write runs-on: ubuntu-22.04 defaults: run: working-directory: ./elixir env: MIX_ENV: test POSTGRES_HOST: localhost GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} MIX_TEST_PARTITIONS: 1 strategy: fail-fast: false matrix: MIX_TEST_PARTITION: [1] services: postgres: image: postgres:15.5 ports: - 5432:5432 env: POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres options: >- --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 vault: image: vault:1.12.2 env: VAULT_ADDR: "http://127.0.0.1:8200" VAULT_DEV_ROOT_TOKEN_ID: "firezone" ports: - 8200:8200/tcp options: --cap-add=IPC_LOCK steps: - uses: actions/checkout@v4 - uses: nanasess/setup-chromedriver@v2 - run: | export DISPLAY=:99 chromedriver --url-base=/wd/hub & sudo Xvfb -ac :99 -screen 0 1280x1024x24 > /dev/null 2>&1 & - uses: ./.github/actions/setup-elixir with: mix_env: ${{ env.MIX_ENV }} - uses: ./.github/actions/setup-node - name: Compile Application run: mix compile --warnings-as-errors # Front-End deps cache - uses: actions/cache/restore@v4 name: pnpm Web Deps Cache id: pnpm-web-deps-cache env: cache-name: pnpm-deps-web with: path: | elixir/apps/web/assets/node_modules elixir/esbuild-* elixir/tailwind-* key: ubuntu-22.04-${{ runner.arch }}-${{ env.cache-name }}-${{ hashFiles('elixir/apps/web/assets/pnpm-lock.yaml') }} - name: Install Front-End Dependencies if: ${{ steps.pnpm-web-deps-cache.outputs.cache-hit != 'true' }} run: | cd apps/web mix assets.setup - uses: actions/cache/save@v4 name: Save pnpm Deps Cache if: ${{ github.ref_name == 'main' }} env: cache-name: pnpm-deps-web with: path: | elixir/apps/web/assets/node_modules elixir/esbuild-* elixir/tailwind-* key: ubuntu-22.04-${{ runner.arch }}-${{ env.cache-name }}-${{ hashFiles('elixir/apps/web/assets/pnpm-lock.yaml') }} # Front-End build cache, it rarely changes so we cache it aggressively too - uses: actions/cache/restore@v4 name: Web Assets Cache id: pnpm-web-build-cache env: cache-name: pnpm-build-web with: path: | elixir/apps/web/assets/tmp elixir/apps/web/priv/static key: ubuntu-22.04-${{ runner.arch }}-${{ env.cache-name }}-${{ hashFiles('elixir/apps/web/assets/**') }} - name: Build Web Assets if: ${{ steps.pnpm-web-build-cache.outputs.cache-hit != 'true' }} run: | cd apps/web mix assets.build - uses: actions/cache/save@v4 name: Save Web Assets Cache if: ${{ github.ref_name == 'main' }} env: cache-name: pnpm-build-web with: path: | elixir/apps/web/assets/tmp elixir/apps/web/priv/static key: ubuntu-22.04-${{ runner.arch }}-${{ env.cache-name }}-${{ hashFiles('elixir/apps/web/assets/**') }} # Run tests - name: Setup Database run: | mix ecto.create mix ecto.migrate - name: Run Acceptance Tests env: MIX_TEST_PARTITION: ${{ matrix.MIX_TEST_PARTITION }} E2E_DEFAULT_WAIT_SECONDS: 20 run: | mix test --only acceptance:true \ --partitions=${{ env.MIX_TEST_PARTITIONS }} \ --no-compile \ --no-archives-check \ --no-deps-check \ || pkill -f chromedriver \ || mix test --only acceptance:true --failed \ || pkill -f chromedriver \ || mix test --only acceptance:true --failed - name: Save Screenshots if: ${{ github.event.pull_request.head.repo.full_name == github.repository && always() }} uses: actions/upload-artifact@v4 with: name: screenshots-${{ matrix.MIX_TEST_PARTITION }} path: elixir/apps/web/screenshots - name: Test Report uses: dorny/test-reporter@v1 if: ${{ github.event.pull_request.head.repo.full_name == github.repository && (success() || failure()) }} with: name: Elixir Acceptance Test Report path: elixir/_build/test/lib/*/test-junit-report.xml reporter: java-junit