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
|
cover
|
||||||
.elixir_ls
|
.elixir_ls
|
||||||
*.dump
|
*.dump
|
||||||
|
|
|
@ -18,6 +18,10 @@ variables:
|
||||||
test:
|
test:
|
||||||
stage: test
|
stage: test
|
||||||
image: "elixir:1.10"
|
image: "elixir:1.10"
|
||||||
|
cache:
|
||||||
|
paths:
|
||||||
|
- _build/
|
||||||
|
- deps/
|
||||||
services:
|
services:
|
||||||
- name: postgres:12
|
- name: postgres:12
|
||||||
script: script/cibuild
|
script: script/cibuild
|
||||||
|
@ -27,9 +31,14 @@ build_image_for_commit:
|
||||||
image: "docker:20.10"
|
image: "docker:20.10"
|
||||||
only:
|
only:
|
||||||
- master
|
- master
|
||||||
|
cache:
|
||||||
|
paths:
|
||||||
|
- _build/
|
||||||
|
- deps/
|
||||||
services:
|
services:
|
||||||
- name: docker:20.10-dind
|
- name: docker:20.10-dind
|
||||||
script:
|
script:
|
||||||
|
- script/ci/restore-timestamps
|
||||||
- docker login "https://${CI_REGISTRY}" -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD
|
- docker login "https://${CI_REGISTRY}" -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD
|
||||||
- docker pull $CI_REGISTRY_IMAGE:latest || true
|
- docker pull $CI_REGISTRY_IMAGE:latest || true
|
||||||
# This enables fast parallel builds
|
# 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
|
# Push the commit SHA tagged version to registry. We will later choose to tag that as stable
|
||||||
# if everything passes.
|
# if everything passes.
|
||||||
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
|
- 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
|
# If tests pass, tag the commit and update package versions
|
||||||
deploy_to_tags:
|
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/app/mix.exs /root/app/apps/app/
|
||||||
ADD ./apps/content/mix.exs /root/app/apps/content/
|
ADD ./apps/content/mix.exs /root/app/apps/content/
|
||||||
ADD ./apps/core/mix.exs /root/app/apps/core/
|
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.get
|
||||||
RUN mix deps.compile
|
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
|
# Leave off here so that we can built assets and compile the elixir app in parallel
|
||||||
|
|
||||||
FROM node:15.0
|
FROM node:15.0
|
||||||
|
|
||||||
# Build assets in a node container
|
# Build assets in a node container
|
||||||
|
ADD ./apps/app/assets/ /root/app/apps/app/assets/
|
||||||
|
|
||||||
WORKDIR /root/app/apps/app/assets/
|
WORKDIR /root/app/apps/app/assets/
|
||||||
COPY --from=0 /root/app/ /root/app/
|
COPY --from=0 /root/app/ /root/app/
|
||||||
RUN npm install
|
RUN npm install
|
||||||
|
@ -43,6 +45,8 @@ RUN npm run deploy
|
||||||
|
|
||||||
FROM elixir1
|
FROM elixir1
|
||||||
|
|
||||||
|
ADD ./apps /root/app/apps
|
||||||
|
|
||||||
# Resume compilation of the elixir app
|
# Resume compilation of the elixir app
|
||||||
ADD ./script /root/app/script
|
ADD ./script /root/app/script
|
||||||
RUN MAKE=cmake mix compile
|
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.hex --force
|
||||||
mix local.rebar --force
|
mix local.rebar --force
|
||||||
|
|
||||||
|
script/ci/restore-timestamps
|
||||||
|
|
||||||
mix deps.get
|
mix deps.get
|
||||||
mix ecto.create
|
mix ecto.create
|
||||||
mix ecto.migrate
|
mix ecto.migrate
|
||||||
|
|
||||||
mix test
|
mix test
|
||||||
|
|
||||||
|
script/ci/restore-timestamps
|
||||||
|
|
Loading…
Reference in a new issue