Merge pull request #718 from betatim/early-r

[MRG] Install R packages before copying repo contents
pull/745/head
Min RK 2019-07-16 07:30:16 +02:00 zatwierdzone przez GitHub
commit 5ef42fc2af
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
2 zmienionych plików z 69 dodań i 11 usunięć

Wyświetl plik

@ -90,7 +90,7 @@ ENV PATH {{ ':'.join(path) }}:${PATH}
{% if build_script_files -%}
# If scripts required during build are present, copy them
{% for src, dst in build_script_files.items() %}
{% for src, dst in build_script_files|dictsort %}
COPY {{ src }} {{ dst }}
{% endfor -%}
{% endif -%}
@ -125,7 +125,14 @@ ENV {{item[0]}} {{item[1]}}
# of the repository but don't access any files in the repository. By executing
# them before copying the repository itself we can cache these steps. For
# example installing APT packages.
{% for sd in pre_assemble_script_directives -%}
{% if preassemble_script_files -%}
# If scripts required during build are present, copy them
{% for src, dst in preassemble_script_files|dictsort %}
COPY src/{{ src }} ${REPO_DIR}/{{ dst }}
{% endfor -%}
{% endif -%}
{% for sd in preassemble_script_directives -%}
{{ sd }}
{% endfor %}
@ -144,7 +151,7 @@ RUN chown -R ${NB_USER}:${NB_USER} ${REPO_DIR}
# Container image Labels!
# Put these at the end, since we don't want to rebuild everything
# when these change! Did I mention I hate Dockerfile cache semantics?
{% for k, v in labels.items() %}
{% for k, v in labels|dictsort %}
LABEL {{k}}="{{v}}"
{%- endfor %}
@ -379,6 +386,19 @@ class BuildPack:
return []
def get_preassemble_script_files(self):
"""
Dict of files to be copied to the container image for use in preassembly.
This is copied before the `build_scripts`, `preassemble_scripts` and
`assemble_scripts` are run, so can be executed from either of them.
It's a dictionary where the key is the source file path in the
repository and the value is the destination file path inside the
repository in the container.
"""
return {}
def get_preassemble_scripts(self):
"""
Ordered list of shell snippets to build an image for this repository.
@ -499,13 +519,13 @@ class BuildPack:
"RUN {}".format(textwrap.dedent(script.strip("\n")))
)
pre_assemble_script_directives = []
preassemble_script_directives = []
last_user = "root"
for user, script in self.get_preassemble_scripts():
if last_user != user:
pre_assemble_script_directives.append("USER {}".format(user))
preassemble_script_directives.append("USER {}".format(user))
last_user = user
pre_assemble_script_directives.append(
preassemble_script_directives.append(
"RUN {}".format(textwrap.dedent(script.strip("\n")))
)
@ -516,7 +536,8 @@ class BuildPack:
env=self.get_env(),
labels=self.get_labels(),
build_script_directives=build_script_directives,
pre_assemble_script_directives=pre_assemble_script_directives,
preassemble_script_files=self.get_preassemble_script_files(),
preassemble_script_directives=preassemble_script_directives,
assemble_script_directives=assemble_script_directives,
build_script_files=self.get_build_script_files(),
base_packages=sorted(self.get_base_packages()),

Wyświetl plik

@ -291,15 +291,52 @@ class RBuildPack(PythonBuildPack):
return super().get_build_scripts() + scripts
def get_preassemble_script_files(self):
files = {}
installR_path = self.binder_path("install.R")
if os.path.exists(installR_path):
files[installR_path] = installR_path
return files
def get_preassemble_scripts(self):
"""Install contents of install.R
Attempt to execute `install.R` before copying the contents of the
repository. We speculate that most of the time we do not need access.
In case this fails we re-run it after copying the repository contents.
The advantage of executing it before copying is that minor edits to the
repository content will not trigger a re-install making things faster.
"""
scripts = []
installR_path = self.binder_path("install.R")
if os.path.exists(installR_path):
scripts += [
(
"${NB_USER}",
"Rscript %s && touch /tmp/.preassembled || true" % installR_path,
)
]
return super().get_preassemble_scripts() + scripts
def get_assemble_scripts(self):
"""
Return series of build-steps specific to this repository.
"""
"""Install the dependencies of or the repository itself"""
assemble_scripts = super().get_assemble_scripts()
installR_path = self.binder_path("install.R")
if os.path.exists(installR_path):
assemble_scripts += [("${NB_USER}", "Rscript %s" % installR_path)]
assemble_scripts += [
(
"${NB_USER}",
# only run install.R if the pre-assembly failed
"if [ ! -f /tmp/.preassembled ]; then Rscript {}; fi".format(
installR_path
),
)
]
description_R = "DESCRIPTION"
if not self.binder_dir and os.path.exists(description_R):