From 83af511732007a5af0b6601e8376f24553a466e1 Mon Sep 17 00:00:00 2001 From: Alex Couture-Beil Date: Sun, 25 Apr 2021 01:22:53 -0700 Subject: [PATCH] Earthfile for running ci tests locally (#320) --- .github/workflows/ci.yml | 188 ++++++++++++--------------------------- Earthfile | 158 ++++++++++++++++++++++++++++++++ README.md | 18 ++++ 3 files changed, 231 insertions(+), 133 deletions(-) create mode 100644 Earthfile diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c2d69f91..f85ac886 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,151 +1,73 @@ name: CI on: [push, pull_request] jobs: - test-elixir: - runs-on: ubuntu-16.04 - env: - MIX_ENV: test + test: + name: unittest + runs-on: ubuntu-latest strategy: fail-fast: false matrix: - include: - - pair: - elixir: 1.8.2 - otp: 20.3.8.26 - - pair: - elixir: 1.11.3 - otp: 23.2.5 - lint: lint + elixirbase: + - "1.11.0-erlang-23.1.1-alpine-3.13.1" + - "1.11.0-erlang-21.3.8.21-alpine-3.13.1" steps: - - uses: actions/checkout@v2 - - - uses: erlef/setup-elixir@v1 + - uses: earthly/actions/setup-earthly@v1 with: - otp-version: ${{matrix.pair.otp}} - elixir-version: ${{matrix.pair.elixir}} - - - name: Install Dependencies - run: mix deps.get --only test - - - run: mix format --check-formatted - if: ${{ matrix.lint }} - - - run: mix deps.get && mix deps.unlock --check-unused - if: ${{ matrix.lint }} - - - run: mix deps.compile - - - run: mix compile --warnings-as-errors - if: ${{ matrix.lint }} - - - run: mix test - - - run: mix test.as_a_dep - - test-mysql: - runs-on: ubuntu-18.04 - - services: - mysql: - image: mysql:${{ matrix.mysql_version }} - env: - MYSQL_ROOT_PASSWORD: root - options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3 - - container: elixir:1.9-slim - + version: v0.5.10 + - uses: actions/checkout@v2 + - name: test ectl_sql + run: earthly -P --ci --build-arg ELIXIR_BASE=${{matrix.elixirbase}} +test + test-postgres: + name: postgres integration test + runs-on: ubuntu-latest strategy: + fail-fast: false matrix: - mysql_version: ["5.7"] - + elixirbase: + - "1.9.4-erlang-22.3.4.16-alpine-3.13.1" + postgres: + - "11.11" + - "9.6" + - "9.5" steps: - - name: Install MySQL Client - run: | - apt-get update - apt-get install -y default-mysql-client - mysql --version - - uses: actions/checkout@v1 - - name: Install Dependencies - run: | - apt-get install -y git - mix local.rebar --force - mix local.hex --force - mix deps.get - - run: MYSQL_URL=root:root@mysql ECTO_ADAPTER=myxql mix test - - test-mssql: - runs-on: ubuntu-16.04 - - services: - mssql: - image: mcr.microsoft.com/mssql/server:${{ matrix.mssql_version }} - env: - ACCEPT_EULA: Y - SA_PASSWORD: some!Password - ports: - - 1433:1433 - + - uses: earthly/actions/setup-earthly@v1 + with: + version: v0.5.10 + - uses: actions/checkout@v2 + - name: test ecto_sql + run: earthly -P --ci --build-arg ELIXIR_BASE=${{matrix.elixirbase}} --build-arg POSTGRES=${{matrix.postgres}} +integration-test-postgres + test-mysql: + name: mysql integration test + runs-on: ubuntu-latest strategy: + fail-fast: false matrix: - mssql_version: ["2017-latest", "2019-latest"] - otp: [22.1.7] - elixir: [1.9.4] - - env: - ACCEPT_EULA: Y - MIX_ENV: test - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - + elixirbase: + - "1.9.4-erlang-22.3.4.16-alpine-3.13.1" + mysql: + - "5.7" steps: - - name: Install MsSql Client Tools - run: | - sudo apt-get update - sudo apt-get install -y mssql-tools unixodbc-dev - - uses: actions/checkout@v2 - - name: Setup elixir - uses: actions/setup-elixir@v1 + - uses: earthly/actions/setup-earthly@v1 with: - otp-version: ${{matrix.otp}} - elixir-version: ${{matrix.elixir}} - - name: Install Dependencies - run: mix deps.get - - run: | - export PATH="/opt/mssql-tools/bin:$PATH" - ECTO_ADAPTER=tds mix test - - test-pg: - runs-on: ubuntu-18.04 - - services: - pg: - image: postgres:${{ matrix.pg_version }} - env: - POSTGRES_USER: postgres - POSTGRES_PASSWORD: postgres - POSTGRES_DB: postgres - options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 - - container: elixir:1.9-slim - + version: v0.5.10 + - uses: actions/checkout@v2 + - name: test ecto_sql + run: earthly -P --ci --build-arg ELIXIR_BASE=${{matrix.elixirbase}} --build-arg POSTGRES=${{matrix.postgres}} +integration-test-mysql + test-mssql: + name: mssql integration test + runs-on: ubuntu-latest strategy: + fail-fast: false matrix: - pg_version: ["9.5", "9.6", "11"] - + elixirbase: + - "1.9.4-erlang-22.1.7-alpine-3.11.3" + mssql: + - "2017" + - "2019" steps: - - name: Install PG Client - run: | - apt-get update - apt-get install -y wget ca-certificates gnupg - wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - - echo "deb http://apt.postgresql.org/pub/repos/apt/ buster-pgdg main ${{ matrix.pg_version }}" >> /etc/apt/sources.list.d/pgdg.list - apt-get update - apt-get install -y postgresql-${{ matrix.pg_version }} postgresql-contrib-${{ matrix.pg_version }} - psql --version - - uses: actions/checkout@v1 - - name: Install Dependencies - run: | - apt-get install -y git - mix local.rebar --force - mix local.hex --force - mix deps.get - - run: PG_URL=postgres:postgres@pg ECTO_ADAPTER=pg mix test + - uses: earthly/actions/setup-earthly@v1 + with: + version: v0.5.10 + - uses: actions/checkout@v2 + - name: test ecto_sql + run: earthly -P --ci --build-arg ELIXIR_BASE=${{matrix.elixirbase}} --build-arg MSSQL=${{matrix.mssql}} +integration-test-mssql diff --git a/Earthfile b/Earthfile new file mode 100644 index 00000000..09ed7682 --- /dev/null +++ b/Earthfile @@ -0,0 +1,158 @@ +all: + BUILD +test-all + BUILD +integration-test-all + + +test-all: + BUILD \ + --build-arg ELIXIR_BASE=1.11.0-erlang-23.1.1-alpine-3.13.1 \ + --build-arg ELIXIR_BASE=1.11.0-erlang-21.3.8.21-alpine-3.13.1 \ + +test + + +test: + FROM +test-setup + RUN MIX_ENV=test mix deps.compile + COPY --dir bench integration_test lib test ./ + + RUN mix deps.get && mix deps.unlock --check-unused + RUN mix deps.compile + RUN mix compile #--warnings-as-errors + RUN mix test + + +integration-test-all: + ARG ELIXIR_BASE=1.11.0-erlang-23.1.1-alpine-3.13.1 + BUILD \ + --build-arg POSTGRES=11.11 \ + --build-arg POSTGRES=9.6 \ + --build-arg POSTGRES=9.5 \ + +integration-test-postgres + + BUILD \ + --build-arg MYSQL=5.7 \ + +integration-test-mysql + + BUILD \ + --build-arg MSSQL=2017 \ + --build-arg MSSQL=2019 \ + +integration-test-mssql + + +integration-test-base: + FROM +setup-base + RUN apk add --no-progress --update docker docker-compose + + RUN mix local.rebar --force + RUN mix local.hex --force + + +COMMON_INTEGRATION_SETUP_AND_MIX: + COMMAND + COPY mix.exs mix.lock .formatter.exs . + COPY --dir bench integration_test lib test ./ + RUN mix deps.get + RUN mix deps.compile + RUN mix compile #--warnings-as-errors + + +integration-test-postgres: + FROM +integration-test-base + ARG POSTGRES="11.11" + + IF [ "$POSTGRES" = "9.5" ] + # for 9.5 we require a downgraded version of pg_dump; + # and in the 3.4 version, it is not included in postgresql-client but rather in postgresql + RUN echo 'http://dl-cdn.alpinelinux.org/alpine/v3.4/main' >> /etc/apk/repositories + RUN apk add postgresql=9.5.13-r0 + ELSE + RUN apk add postgresql-client + END + + DO +COMMON_INTEGRATION_SETUP_AND_MIX + + # then run the tests + WITH DOCKER \ + --pull "postgres:$POSTGRES" + RUN set -e; \ + timeout=$(expr $(date +%s) + 30); \ + docker run --name pg --network=host -d -e POSTGRES_USER=postgres -e POSTGRES_PASSWORD=postgres -e POSTGRES_DB=postgres "postgres:$POSTGRES"; \ + # wait for postgres to start + while ! pg_isready --host=127.0.0.1 --port=5432 --quiet; do \ + test "$(date +%s)" -le "$timeout" || (echo "timed out waiting for postgres"; exit 1); \ + echo "waiting for postgres"; \ + sleep 1; \ + done; \ + # run tests + PG_URL=postgres:postgres@127.0.0.1 ECTO_ADAPTER=pg mix test; + END + + +integration-test-mysql: + FROM +integration-test-base + RUN apk add mysql-client + + DO +COMMON_INTEGRATION_SETUP_AND_MIX + + ARG MYSQL="5.7" + WITH DOCKER \ + --pull "mysql:$MYSQL" + RUN set -e; \ + timeout=$(expr $(date +%s) + 30); \ + docker run --name mysql --network=host -d -e MYSQL_ROOT_PASSWORD=root "mysql:$MYSQL"; \ + # wait for mysql to start + while ! mysqladmin ping --host=127.0.0.1 --port=3306 --protocol=TCP --silent; do \ + test "$(date +%s)" -le "$timeout" || (echo "timed out waiting for mysql"; exit 1); \ + echo "waiting for mysql"; \ + sleep 1; \ + done; \ + # run tests + MYSQL_URL=root:root@127.0.0.1 ECTO_ADAPTER=myxql mix test; + END + + +integration-test-mssql: + FROM +integration-test-base + + RUN apk add --no-cache curl gnupg --virtual .build-dependencies -- && \ + curl -O https://download.microsoft.com/download/e/4/e/e4e67866-dffd-428c-aac7-8d28ddafb39b/msodbcsql17_17.5.2.1-1_amd64.apk && \ + curl -O https://download.microsoft.com/download/e/4/e/e4e67866-dffd-428c-aac7-8d28ddafb39b/mssql-tools_17.5.2.1-1_amd64.apk && \ + echo y | apk add --allow-untrusted msodbcsql17_17.5.2.1-1_amd64.apk mssql-tools_17.5.2.1-1_amd64.apk && \ + apk del .build-dependencies && rm -f msodbcsql*.sig mssql-tools*.apk + ENV PATH="/opt/mssql-tools/bin:${PATH}" + + DO +COMMON_INTEGRATION_SETUP_AND_MIX + + ARG MSSQL="2017" + WITH DOCKER \ + --pull "mcr.microsoft.com/mssql/server:$MSSQL-latest" + RUN set -e; \ + timeout=$(expr $(date +%s) + 30); \ + docker run -d -p 1433:1433 --name mssql -e 'ACCEPT_EULA=Y' -e 'MSSQL_SA_PASSWORD=some!Password' "mcr.microsoft.com/mssql/server:$MSSQL-latest"; \ + # wait for mssql to start + while ! sqlcmd -S tcp:127.0.0.1,1433 -U sa -P 'some!Password' -Q "SELECT 1" >/dev/null 2>&1; do \ + test "$(date +%s)" -le "$timeout" || (echo "timed out waiting for mssql"; exit 1); \ + echo "waiting for mssql"; \ + sleep 1; \ + done; \ + # run tests + ECTO_ADAPTER=tds mix test; + END + + +setup-base: + ARG ELIXIR_BASE=1.11.0-erlang-23.1.1-alpine-3.13.1 + FROM hexpm/elixir:$ELIXIR_BASE + RUN apk add --no-progress --update git build-base + ENV ELIXIR_ASSERT_TIMEOUT=10000 + WORKDIR /src/ecto_sql + + +test-setup: + FROM +setup-base + COPY mix.exs . + COPY mix.lock . + COPY .formatter.exs . + RUN mix local.rebar --force + RUN mix local.hex --force + RUN mix deps.get diff --git a/README.md b/README.md index e2f2efc6..f3ba5ffe 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,24 @@ MySQL and PostgreSQL can be installed directly on most systems. For MSSQL, you m docker run -d -p 1433:1433 --name mssql -e 'ACCEPT_EULA=Y' -e 'MSSQL_SA_PASSWORD=some!Password' mcr.microsoft.com/mssql/server:2017-latest +### Running containerized tests + +It is also possible to run the integration tests under a containerized environment using [earthly](https://earthly.dev/get-earthly): + + $ earthly -P +all + +You can also use this to interactively debug any failing integration tests using the corresponding commands: + + $ earthly -P -i --build-arg ELIXIR_BASE=1.8.2-erlang-20.3.8.26-alpine-3.11.6 --build-arg MYSQL=5.7 +integration-test-mysql + $ earthly -P -i --build-arg ELIXIR_BASE=1.8.2-erlang-20.3.8.26-alpine-3.11.6 --build-arg MSSQL=2019 +integration-test-mssql + $ earthly -P -i --build-arg ELIXIR_BASE=1.8.2-erlang-20.3.8.26-alpine-3.11.6 --build-arg POSTGRES=11.11 +integration-test-postgres + +Then once you enter the containerized shell, you can inspect the underlying databases with the respective commands: + + PGPASSWORD=postgres psql -h 127.0.0.1 -U postgres -d postgres ecto_test + MYSQL_PASSWORD=root mysql -h 127.0.0.1 -uroot -proot ecto_test + sqlcmd -U sa -P 'some!Password' + ## License Copyright (c) 2012 Plataformatec \