Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 5 commits into from May 19, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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