Help to deploy Elixir faster when the CI/CD pipeline is slow?

I have an umbrella application but the CI/CD Pipeline I have is terrible slow. I make unit tests and integration tests in this pipeline. But to run the unit tests it compiles once and to run the server in dev mode and run request tests it compiles again. Also both are in different pipelines so the dependencies are downloaded again and takes a lot time to do it. I wan to use distillery but it takes another step for compilation because I have to run mix test once and this compiles again only for the test environment. Each PR takes about 20 minutes to pass for the CI/CD pipeline.

I would like to know experiences from the community and how have solved this issue.

These are the pipeline steps I have:

pipeline:
  unit-tests:
    image: bitwalker/alpine-elixir-phoenix:1.6.5
    environment:
      DATABASE_URL: ecto://random_username:random_password@postgres/integration
      RABBITCONN: amqp://integration_user:integration_password@rabbitmq:5672/integration
      MIX_ENV: test
    commands:
      - mix local.hex --force
      - mix local.rebar --force
      - HEX_HTTP_CONCURRENCY=1 HEX_HTTP_TIMEOUT=180 mix deps.get --force
      - cp wkhtmltopdf /bin
      - chmod +x /bin/wkhtmltopdf
      - MIX_ENV=test mix ecto.drop; MIX_ENV=test mix ecto.create; MIX_ENV=test mix ecto.migrate
      - mix test

  integration-tests:
    image: bitwalker/alpine-elixir-phoenix:1.6.5
    environment:
      GATEWAY_SALT_REQUEST: dGUMdrETWFVyGwQtsfgQ7qTprCzmxFE
      REPLACE_OS_VARS: "true"
      RABBITCONN: amqp://integration_user:integration_password@rabbitmq:5672/integration
      RDS_DB_NAME: integration
      RDS_HOSTNAME: postgres
      RDS_PASSWORD: random_password
      RDS_USERNAME: random_username
      MIX_ENV: ci
      DATABASE_URL: postgresql://random_username:random_password@postgres:5432/integration
    commands:
      # Setup and runs the api server
      - cp wkhtmltopdf /bin
      - chmod +x /bin/wkhtmltopdf

      - MIX_ENV=ci mix ecto.setup
      - MIX_ENV=ci mix release --name=liftit --verbose
      - _build/ci/rel/liftit/bin/liftit start
      - sleep 10

      # Setups python3 and runs pytest
      - ./scripts/ci/install_python3_alpine.sh
      - pip3 install -r pytest/requirements.txt
      - ./run_pytest.sh
    when:
      status: [ success ]

We use two containers presently. As our E2E test suite grows we’ll probably add a third. The problem with this is you will still do the compilation step in every container, so it can only help so much. Right now just building the Elixir code, database and the asset pipeline takes almost half the total job duration container and this is with effective caching (~6 minutes now for the slowest container, where we run the E2E tests). One thing that helped a lot was choosing a base container image that is widely deployed on the hosts. We use Circle and while we could use any image, if we use one of Circle’s images as the base a lot more layers are likely to be in cache, making the pull time much faster. I saved something like two minutes here.

2 Likes