chore: Speed up compilation in CI
This commit is contained in:
parent
5ff02b80c3
commit
79d68fb144
5 changed files with 96 additions and 4 deletions
|
@ -1,5 +1,3 @@
|
|||
_build
|
||||
deps
|
||||
cover
|
||||
.elixir_ls
|
||||
*.dump
|
||||
|
|
|
@ -18,6 +18,10 @@ variables:
|
|||
test:
|
||||
stage: test
|
||||
image: "elixir:1.10"
|
||||
cache:
|
||||
paths:
|
||||
- _build/
|
||||
- deps/
|
||||
services:
|
||||
- name: postgres:12
|
||||
script: script/cibuild
|
||||
|
@ -27,9 +31,14 @@ build_image_for_commit:
|
|||
image: "docker:20.10"
|
||||
only:
|
||||
- master
|
||||
cache:
|
||||
paths:
|
||||
- _build/
|
||||
- deps/
|
||||
services:
|
||||
- name: docker:20.10-dind
|
||||
script:
|
||||
- script/ci/restore-timestamps
|
||||
- docker login "https://${CI_REGISTRY}" -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD
|
||||
- docker pull $CI_REGISTRY_IMAGE:latest || true
|
||||
# This enables fast parallel builds
|
||||
|
@ -38,6 +47,9 @@ build_image_for_commit:
|
|||
# Push the commit SHA tagged version to registry. We will later choose to tag that as stable
|
||||
# if everything passes.
|
||||
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
|
||||
# Pull out the built _build/prod directory so we can cache it!
|
||||
- docker cp `docker create $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA`:/root/app/_build/prod _build
|
||||
- script/ci/restore-timestamps
|
||||
|
||||
# If tests pass, tag the commit and update package versions
|
||||
deploy_to_tags:
|
||||
|
|
|
@ -26,16 +26,18 @@ ADD ./apps/admin/mix.exs /root/app/apps/admin/
|
|||
ADD ./apps/app/mix.exs /root/app/apps/app/
|
||||
ADD ./apps/content/mix.exs /root/app/apps/content/
|
||||
ADD ./apps/core/mix.exs /root/app/apps/core/
|
||||
ADD ./_build/ /root/app/_build/
|
||||
ADD ./deps/ /root/app/deps/
|
||||
RUN mix deps.get
|
||||
RUN mix deps.compile
|
||||
|
||||
ADD ./apps /root/app/apps
|
||||
|
||||
# Leave off here so that we can built assets and compile the elixir app in parallel
|
||||
|
||||
FROM node:15.0
|
||||
|
||||
# Build assets in a node container
|
||||
ADD ./apps/app/assets/ /root/app/apps/app/assets/
|
||||
|
||||
WORKDIR /root/app/apps/app/assets/
|
||||
COPY --from=0 /root/app/ /root/app/
|
||||
RUN npm install
|
||||
|
@ -43,6 +45,8 @@ RUN npm run deploy
|
|||
|
||||
FROM elixir1
|
||||
|
||||
ADD ./apps /root/app/apps
|
||||
|
||||
# Resume compilation of the elixir app
|
||||
ADD ./script /root/app/script
|
||||
RUN MAKE=cmake mix compile
|
||||
|
|
74
script/ci/restore-timestamps
Executable file
74
script/ci/restore-timestamps
Executable file
|
@ -0,0 +1,74 @@
|
|||
#!/usr/bin/env elixir
|
||||
|
||||
defmodule TimestampRestorer do
|
||||
@environment System.get_env("MIX_ENV", "dev")
|
||||
@db_path "_build/#{@environment}/timestamp-database"
|
||||
|
||||
def sha_all do
|
||||
timestamp_database = load_timestamp_database()
|
||||
|
||||
"**/*.{ex,exs,beam}"
|
||||
|> Path.wildcard()
|
||||
|> Enum.reduce(%{}, fn filename, acc ->
|
||||
{sha, timestamp} = process(filename, timestamp_database)
|
||||
Map.put(acc, sha, timestamp)
|
||||
end)
|
||||
|> write_timestamp_database()
|
||||
end
|
||||
|
||||
defp load_timestamp_database() do
|
||||
if File.exists?(@db_path) do
|
||||
@db_path
|
||||
|> File.read!()
|
||||
|> String.split("\n")
|
||||
|> Enum.reduce(%{}, fn line, acc ->
|
||||
[sha, timestamp_string] = String.split(line, ":")
|
||||
{timestamp, ""} = Integer.parse(timestamp_string)
|
||||
Map.put(acc, sha, timestamp)
|
||||
end)
|
||||
else
|
||||
%{}
|
||||
end
|
||||
end
|
||||
|
||||
defp write_timestamp_database(database) do
|
||||
database
|
||||
|> Enum.map(fn {key, value} -> "#{key}:#{value}" end)
|
||||
|> Enum.join("\n")
|
||||
|> (& File.write!(@db_path, &1)).()
|
||||
end
|
||||
|
||||
defp process(filename, timestamp_database) do
|
||||
sha = sha(filename)
|
||||
{:ok, %{mtime: new_timestamp}} = File.lstat(filename, time: :posix)
|
||||
|
||||
case Map.get(timestamp_database, sha) do
|
||||
nil ->
|
||||
:logger.debug("[NEW SHA ] #{filename}: #{new_timestamp}")
|
||||
timestamp when timestamp < new_timestamp ->
|
||||
:logger.debug("[RESTORED ] #{filename}: #{timestamp}")
|
||||
File.touch(filename, timestamp)
|
||||
timestamp when timestamp >= new_timestamp ->
|
||||
:logger.debug("[UNCHANGED] #{filename}: #{timestamp}")
|
||||
end
|
||||
|
||||
{sha, new_timestamp}
|
||||
end
|
||||
|
||||
defp sha(filename) do
|
||||
hash_ref = :crypto.hash_init(:sha)
|
||||
|
||||
File.stream!(filename)
|
||||
|> Enum.reduce(hash_ref, fn chunk, prev_ref->
|
||||
new_ref = :crypto.hash_update(prev_ref, chunk)
|
||||
new_ref
|
||||
end)
|
||||
|> :crypto.hash_final()
|
||||
|> Base.encode16()
|
||||
|> String.downcase()
|
||||
end
|
||||
end
|
||||
|
||||
{time, _result} = :timer.tc(TimestampRestorer, :sha_all, [])
|
||||
|
||||
:logger.info("Restored timestamps in #{time / 1_000_000}s")
|
|
@ -6,8 +6,12 @@ set -e
|
|||
mix local.hex --force
|
||||
mix local.rebar --force
|
||||
|
||||
script/ci/restore-timestamps
|
||||
|
||||
mix deps.get
|
||||
mix ecto.create
|
||||
mix ecto.migrate
|
||||
|
||||
mix test
|
||||
|
||||
script/ci/restore-timestamps
|
||||
|
|
Loading…
Reference in a new issue