Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
fix: fail with error if conda installation is not set to strict chann…
…el priorities (#1672)

* fix: fail with error if conda installation is not set to strict channel priorities

* use conda config and ensure that singularity is considered

* set strict channel priorities

* set channel priority

* set strict priority on the fly when using container images
  • Loading branch information
johanneskoester committed May 19, 2022
1 parent 53972bf commit f1ffbf2
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 23 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/main.yml
Expand Up @@ -54,6 +54,7 @@ jobs:
- name: Setup Snakemake environment
run: |
export PATH="/usr/share/miniconda/bin:$PATH"
conda config --set channel_priority strict
conda install -c conda-forge -q mamba
# ensure that mamba is happy to write into the cache
sudo chown -R runner:docker /usr/share/miniconda/pkgs/cache
Expand Down Expand Up @@ -197,6 +198,7 @@ jobs:

- name: Setup Snakemake environment
run: |
conda config --set channel_priority strict
conda install -q --name base mamba
mamba env update -q --file test-environment.yml
Expand Down
1 change: 1 addition & 0 deletions Dockerfile
Expand Up @@ -8,6 +8,7 @@ ENV SHELL /bin/bash
RUN install_packages wget curl bzip2 ca-certificates gnupg2 squashfs-tools git
RUN /bin/bash -c "curl -L https://github.com/conda-forge/miniforge/releases/latest/download/Mambaforge-Linux-x86_64.sh > mambaforge.sh && \
bash mambaforge.sh -b -p /opt/conda && \
conda config --set channel_priority strict && \
rm mambaforge.sh"
RUN /bin/bash -c "mamba create -q -y -c conda-forge -c bioconda -n snakemake snakemake snakemake-minimal --only-deps && \
source activate snakemake && \
Expand Down
80 changes: 57 additions & 23 deletions snakemake/deployment/conda.py
Expand Up @@ -492,14 +492,21 @@ def create_env(env_file, filetype="yaml"):

logger.info("Downloading and installing remote packages.")

strict_priority = (
["conda config --set channel_priority strict &&"]
if self._container_img
else []
)

subcommand = [self.frontend]
yes_flag = ["--yes"]
if filetype == "yaml":
subcommand.append("env")
yes_flag = []

cmd = " ".join(
subcommand
cmd = (
strict_priority
+ subcommand
+ [
"create",
"--quiet",
Expand All @@ -508,6 +515,7 @@ def create_env(env_file, filetype="yaml"):
]
+ yes_flag
)
cmd = " ".join(cmd)
if self._container_img:
cmd = singularity.shellcmd(
self._container_img.path,
Expand Down Expand Up @@ -624,18 +632,18 @@ def __init__(self, container_img=None, prefix_path=None):
container_img = container_img.path
self.container_img = container_img

info = json.loads(
self.info = json.loads(
shell.check_output(
self._get_cmd("conda info --json"), universal_newlines=True
)
)

if prefix_path is None or container_img is not None:
self.prefix_path = info["conda_prefix"]
self.prefix_path = self.info["conda_prefix"]
else:
self.prefix_path = prefix_path

self.platform = info["platform"]
self.platform = self.info["platform"]

# check conda installation
self._check()
Expand Down Expand Up @@ -689,27 +697,53 @@ def _check(self):
"with `conda activate base`.".format(shell.get_executable())
)
try:
version = shell.check_output(
self._get_cmd("conda --version"),
stderr=subprocess.PIPE,
self._check_version()
self._check_condarc()
except subprocess.CalledProcessError as e:
raise CreateCondaEnvironmentException(
"Unable to check conda installation:\n" + e.stderr.decode()
)

def _check_version(self):
from snakemake.shell import shell

version = shell.check_output(
self._get_cmd("conda --version"),
stderr=subprocess.PIPE,
universal_newlines=True,
)
version_matches = re.findall("\d+.\d+.\d+", version)
if len(version_matches) != 1:
raise WorkflowError(
f"Unable to determine conda version. 'conda --version' returned {version}"
)
else:
version = version_matches[0]
if StrictVersion(version) < StrictVersion("4.2"):
raise CreateCondaEnvironmentException(
"Conda must be version 4.2 or later, found version {}.".format(version)
)

def _check_condarc(self):
if self.container_img:
# Do not check for strict priorities when running conda in an image
# Instead, we set priorities to strict ourselves in the image.
return
from snakemake.shell import shell

res = json.loads(
shell.check_output(
self._get_cmd("conda config --get channel_priority --json"),
universal_newlines=True,
stderr=subprocess.PIPE,
)
version_matches = re.findall("\d+.\d+.\d+", version)
if len(version_matches) != 1:
raise WorkflowError(
f"Unable to determine conda version. 'conda --version' returned {version}"
)
else:
version = version_matches[0]
if StrictVersion(version) < StrictVersion("4.2"):
raise CreateCondaEnvironmentException(
"Conda must be version 4.2 or later, found version {}.".format(
version
)
)
except subprocess.CalledProcessError as e:
)
if res["get"].get("channel_priority") != "strict":
raise CreateCondaEnvironmentException(
"Unable to check conda version:\n" + e.stderr.decode()
"Your conda installation is not configured to use strict channel priorities. "
"This is however crucial for having robust and correct environments (for details, "
"see https://conda-forge.org/docs/user/tipsandtricks.html). "
"Please configure strict priorities by executing 'conda config --set channel_priority strict'."
)

def bin_path(self):
Expand Down

0 comments on commit f1ffbf2

Please sign in to comment.