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

Add support for generic git remotes #1641

Merged
merged 58 commits into from
Jun 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
fb6d3c2
Rewriting intialisation of ModulesRepo
ErikDanielsson Jun 16, 2022
63beb2c
Setup should be done
ErikDanielsson Jun 16, 2022
b0b640f
Rationalize variables
ErikDanielsson Jun 16, 2022
babf143
Update module file download
ErikDanielsson Jun 16, 2022
e55ab0a
Downloading at different refs
ErikDanielsson Jun 16, 2022
2a47e79
Merge branch 'dev' of github.com:nf-core/tools into get-generic-git
ErikDanielsson Jun 16, 2022
112b103
Fix get_module_git_log
ErikDanielsson Jun 16, 2022
6953cf9
Update file comparision functionality
ErikDanielsson Jun 17, 2022
bc1c067
add comment to prompt func
ErikDanielsson Jun 17, 2022
3186292
Update prompt function
ErikDanielsson Jun 17, 2022
9c61c72
Update sha_exists
ErikDanielsson Jun 17, 2022
a31870e
Bugfixing - starting to work now
ErikDanielsson Jun 17, 2022
ee2f8d6
Update git commit info
ErikDanielsson Jun 17, 2022
b7a7ce4
Add no-pull option
ErikDanielsson Jun 17, 2022
23aefc9
Start updating modules.json functionality
ErikDanielsson Jun 17, 2022
948a4db
Update remaining modules.json functionality. Add new entry for git URL
ErikDanielsson Jun 17, 2022
ff4a6ee
Remove gh api functions
ErikDanielsson Jun 17, 2022
b85c212
Remove more api stuff
ErikDanielsson Jun 17, 2022
c251e74
Remove verify_pipeline. We cannot provide this functionality with the…
ErikDanielsson Jun 17, 2022
458e6bc
Remove gh api
ErikDanielsson Jun 17, 2022
0c99465
Misc bugfix
ErikDanielsson Jun 17, 2022
6379992
Fix bugs in create mod json and init of ModulesRepo
ErikDanielsson Jun 18, 2022
b093fc9
Remove old functions
ErikDanielsson Jun 18, 2022
4b405fd
Update module names functionality
ErikDanielsson Jun 18, 2022
d7e8e8b
ask -> unsafe_ask
ErikDanielsson Jun 18, 2022
928c905
Remove print statements
ErikDanielsson Jun 18, 2022
cc6ccef
Fix get_avail_modules
ErikDanielsson Jun 18, 2022
829f09f
Fix module name selection
ErikDanielsson Jun 18, 2022
1a69c4e
Make update work
ErikDanielsson Jun 18, 2022
a9eaf14
Add progress bars when cloning and pulling remote
ErikDanielsson Jun 18, 2022
99f581d
Add static variables for keeping track of pull status
ErikDanielsson Jun 18, 2022
6824918
Use @staticmethod method instead of @classmethod...
ErikDanielsson Jun 18, 2022
770e4e1
Fix modules list
ErikDanielsson Jun 18, 2022
ab09a58
Fix info
ErikDanielsson Jun 19, 2022
b698585
Update main function
ErikDanielsson Jun 19, 2022
632fc67
Bug fix, user info and new option --no-pull
ErikDanielsson Jun 19, 2022
fdfde82
Remove unused function and update comments
ErikDanielsson Jun 19, 2022
d7c46bb
Update CHANGELOG.md
ErikDanielsson Jun 19, 2022
a6b6521
Update docs
ErikDanielsson Jun 19, 2022
91d7bf8
Fix docs
ErikDanielsson Jun 19, 2022
ae05e73
Fix dry run bug
ErikDanielsson Jun 20, 2022
c973783
Remove double creation of ModulesRepo
ErikDanielsson Jun 20, 2022
1bf1db7
Fix list local
ErikDanielsson Jun 20, 2022
76374e3
Fix no-pull
ErikDanielsson Jun 20, 2022
c166aa1
Update tests
ErikDanielsson Jun 20, 2022
e97d30c
Fix the last bugs
ErikDanielsson Jun 20, 2022
7c70169
Remove sneaky api calls
ErikDanielsson Jun 20, 2022
08b92d8
make work with https
ErikDanielsson Jun 20, 2022
305ead8
isort
ErikDanielsson Jun 20, 2022
5e7c1a3
Don't fail horribly due to LookupError
ErikDanielsson Jun 20, 2022
228973a
black
ErikDanielsson Jun 20, 2022
b30007e
Fix lookup bug
ErikDanielsson Jun 21, 2022
80c6c20
General cleanup. Change where files are cloned
ErikDanielsson Jun 21, 2022
0bee100
Apply suggestions from code review
ErikDanielsson Jun 21, 2022
f994bd3
Use .config
ErikDanielsson Jun 21, 2022
b4d4b89
Update docs
ErikDanielsson Jun 21, 2022
1b1b7e3
Merge branch 'dev' of github.com:nf-core/tools into get-generic-git
ErikDanielsson Jun 21, 2022
c558fd3
Merge branch 'get-generic-git' of github.com:ErikDanielsson/tools int…
ErikDanielsson Jun 21, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

- Add `--fix-version` flag to `nf-core modules lint` command to update modules to the latest version ([#1588](https://github.com/nf-core/tools/pull/1588))
- Fix a bug in the regex extracting the version from biocontainers URLs ([#1598](https://github.com/nf-core/tools/pull/1598))
- Update how we interface with git remotes. ([#1626](https://github.com/nf-core/tools/issues/1626))

## [v2.4.1 - Cobolt Koala Patch](https://github.com/nf-core/tools/releases/tag/2.4) - [2022-05-16]

Expand Down
37 changes: 9 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -911,38 +911,19 @@ The nf-core DSL2 modules repository is at <https://github.com/nf-core/modules>

The modules supercommand comes with two flags for specifying a custom remote:

- `--github-repository <github repo>`: Specify the repository from which the modules should be fetched. Defaults to `nf-core/modules`.
- `--branch <branch name>`: Specify the branch from which the modules shoudl be fetched. Defaults to `master`.
- `--git-remote <git remote url>`: Specify the repository from which the modules should be fetched as a git URL. Defaults to the github repository of `nf-core/modules`.
ErikDanielsson marked this conversation as resolved.
Show resolved Hide resolved
- `--branch <branch name>`: Specify the branch from which the modules should be fetched. Defaults to the default branch of your repository.

Note that a custom remote must follow a similar directory structure to that of `nf-core/moduleś` for the `nf-core modules` commands to work properly.

### Private remote modules
ErikDanielsson marked this conversation as resolved.
Show resolved Hide resolved
The modules commands will during initalisation try to pull changes from the remote repositories. If you want to disable this, for example
due to performance reason or if you want to run the commands offline, you can use the flag `--no-pull`. Note however that the commands will
still need to clone repositories that have previously not been used.

In order to get access to your private modules repo, you need to create
the `~/.config/gh/hosts.yml` file, which is the same file required by
[GitHub CLI](https://cli.github.com/) to deal with private repositories.
Such file is structured as follow:
### Private remote repositories

```conf
github.com:
oauth_token: <your github access token>
user: <your github user>
git_protocol: <ssh or https are valid choices>
```

The easiest way to create this configuration file is through _GitHub CLI_: follow
its [installation instructions](https://cli.github.com/manual/installation)
and then call:

```bash
gh auth login
```

After that, you will be able to list and install your private modules without
providing your github credentials through command line, by using `--github-repository`
and `--branch` options properly.
See the documentation on [gh auth login](https://cli.github.com/manual/gh_auth_login>)
to get more information.
You can use the modules command with private remote repositories. Make sure that your local `git` is correctly configured with your private remote
and then specify the remote the same way you would do with a public remote repository.

### List modules

Expand Down Expand Up @@ -1079,7 +1060,7 @@ There are three additional flags that you can use when installing a module:

- `--force`: Overwrite a previously installed version of the module.
- `--prompt`: Select the module version using a cli prompt.
- `--sha <commit_sha>`: Install the module at a specific commit from the `nf-core/modules` repository.
- `--sha <commit_sha>`: Install the module at a specific commit.

### Update modules in a pipeline

Expand Down
104 changes: 68 additions & 36 deletions nf_core/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@
# Submodules should all traverse back to this
log = logging.getLogger()

# Set up .nfcore directory for storing files between sessions
nf_core.utils.setup_nfcore_dir()

# Set up nicer formatting of click cli help messages
click.rich_click.MAX_WIDTH = 100
click.rich_click.USE_RICH_MARKUP = True
Expand Down Expand Up @@ -342,27 +345,31 @@ def lint(dir, release, fix, key, show_passed, fail_ignored, fail_warned, markdow
@nf_core_cli.group()
@click.option(
"-g",
"--github-repository",
"--git-remote",
type=str,
default="nf-core/modules",
help="GitHub repository hosting modules.",
default=nf_core.modules.modules_repo.NF_CORE_MODULES_REMOTE,
help="Remote git repo to fetch files from",
)
@click.option("-b", "--branch", type=str, default=None, help="Branch of git repository hosting modules.")
@click.option(
"--no-pull",
is_flag=True,
default=False,
help="Do not pull in latest changes to local clone of modules repository.",
)
@click.option("-b", "--branch", type=str, default="master", help="Branch of GitHub repository hosting modules.")
@click.pass_context
def modules(ctx, github_repository, branch):
def modules(ctx, git_remote, branch, no_pull):
"""
Commands to manage Nextflow DSL2 modules (tool wrappers).
"""
# ensure that ctx.obj exists and is a dict (in case `cli()` is called
# by means other than the `if` block below)
ctx.ensure_object(dict)

# Make repository object to pass to subcommands
try:
ctx.obj["modules_repo_obj"] = nf_core.modules.ModulesRepo(github_repository, branch)
except LookupError as e:
log.critical(e)
sys.exit(1)
# Place the arguments in a context object
ctx.obj["modules_repo_url"] = git_remote
ctx.obj["modules_repo_branch"] = branch
ctx.obj["modules_repo_no_pull"] = no_pull


# nf-core modules list subcommands
Expand All @@ -385,10 +392,11 @@ def remote(ctx, keywords, json):
List modules in a remote GitHub repo [dim i](e.g [link=https://github.com/nf-core/modules]nf-core/modules[/])[/].
"""
try:
module_list = nf_core.modules.ModuleList(None, remote=True)
module_list.modules_repo = ctx.obj["modules_repo_obj"]
module_list = nf_core.modules.ModuleList(
None, True, ctx.obj["modules_repo_url"], ctx.obj["modules_repo_branch"], ctx.obj["modules_repo_no_pull"]
)
print(module_list.list_modules(keywords, json))
except UserWarning as e:
except (UserWarning, LookupError) as e:
log.critical(e)
sys.exit(1)

Expand All @@ -410,10 +418,11 @@ def local(ctx, keywords, json, dir):
List modules installed locally in a pipeline
"""
try:
module_list = nf_core.modules.ModuleList(dir, remote=False)
module_list.modules_repo = ctx.obj["modules_repo_obj"]
module_list = nf_core.modules.ModuleList(
dir, False, ctx.obj["modules_repo_url"], ctx.obj["modules_repo_branch"], ctx.obj["modules_repo_no_pull"]
)
print(module_list.list_modules(keywords, json))
except UserWarning as e:
except (UserWarning, LookupError) as e:
log.critical(e)
sys.exit(1)

Expand All @@ -439,12 +448,19 @@ def install(ctx, tool, dir, prompt, force, sha):
Fetches and installs module files from a remote repo e.g. nf-core/modules.
"""
try:
module_install = nf_core.modules.ModuleInstall(dir, force=force, prompt=prompt, sha=sha)
module_install.modules_repo = ctx.obj["modules_repo_obj"]
module_install = nf_core.modules.ModuleInstall(
dir,
force,
prompt,
sha,
ctx.obj["modules_repo_url"],
ctx.obj["modules_repo_branch"],
ctx.obj["modules_repo_no_pull"],
)
exit_status = module_install.install(tool)
if not exit_status and all:
sys.exit(1)
except UserWarning as e:
except (UserWarning, LookupError) as e:
log.error(e)
sys.exit(1)

Expand Down Expand Up @@ -487,13 +503,21 @@ def update(ctx, tool, dir, force, prompt, sha, all, preview, save_diff):
"""
try:
module_install = nf_core.modules.ModuleUpdate(
dir, force=force, prompt=prompt, sha=sha, update_all=all, show_diff=preview, save_diff_fn=save_diff
dir,
force,
prompt,
sha,
all,
preview,
save_diff,
ctx.obj["modules_repo_url"],
ctx.obj["modules_repo_branch"],
ctx.obj["modules_repo_no_pull"],
)
module_install.modules_repo = ctx.obj["modules_repo_obj"]
exit_status = module_install.update(tool)
if not exit_status and all:
sys.exit(1)
except UserWarning as e:
except (UserWarning, LookupError) as e:
log.error(e)
sys.exit(1)

Expand All @@ -514,10 +538,11 @@ def remove(ctx, dir, tool):
Remove a module from a pipeline.
"""
try:
module_remove = nf_core.modules.ModuleRemove(dir)
module_remove.modules_repo = ctx.obj["modules_repo_obj"]
module_remove = nf_core.modules.ModuleRemove(
dir, ctx.obj["modules_repo_url"], ctx.obj["modules_repo_branch"], ctx.obj["modules_repo_no_pull"]
)
module_remove.remove(tool)
except UserWarning as e:
except (UserWarning, LookupError) as e:
log.critical(e)
sys.exit(1)

Expand Down Expand Up @@ -562,6 +587,9 @@ def create_module(ctx, tool, dir, author, label, meta, no_meta, force, conda_nam
except UserWarning as e:
log.critical(e)
sys.exit(1)
except LookupError as e:
log.error(e)
sys.exit(1)


# nf-core modules create-test-yml
Expand All @@ -582,7 +610,7 @@ def create_test_yml(ctx, tool, run_tests, output, force, no_prompts):
try:
meta_builder = nf_core.modules.ModulesTestYmlBuilder(tool, run_tests, output, force, no_prompts)
meta_builder.run()
except UserWarning as e:
except (UserWarning, LookupError) as e:
log.critical(e)
sys.exit(1)

Expand All @@ -608,8 +636,9 @@ def lint(ctx, tool, dir, key, all, local, passed, fix_version):
nf-core/modules repository.
"""
try:
module_lint = nf_core.modules.ModuleLint(dir=dir)
module_lint.modules_repo = ctx.obj["modules_repo_obj"]
module_lint = nf_core.modules.ModuleLint(
dir, ctx.obj["modules_repo_url"], ctx.obj["modules_repo_branch"], ctx.obj["modules_repo_no_pull"]
)
module_lint.lint(
module=tool,
key=key,
Expand All @@ -624,7 +653,7 @@ def lint(ctx, tool, dir, key, all, local, passed, fix_version):
except nf_core.modules.lint.ModuleLintException as e:
log.error(e)
sys.exit(1)
except UserWarning as e:
except (UserWarning, LookupError) as e:
log.critical(e)
sys.exit(1)

Expand Down Expand Up @@ -653,10 +682,11 @@ def info(ctx, tool, dir):
If not, usage from the remote modules repo will be shown.
"""
try:
module_info = nf_core.modules.ModuleInfo(dir, tool)
module_info.modules_repo = ctx.obj["modules_repo_obj"]
module_info = nf_core.modules.ModuleInfo(
dir, tool, ctx.obj["modules_repo_url"], ctx.obj["modules_repo_branch"], ctx.obj["modules_repo_no_pull"]
)
print(module_info.get_module_info())
except UserWarning as e:
except (UserWarning, LookupError) as e:
log.error(e)
sys.exit(1)

Expand All @@ -674,12 +704,14 @@ def bump_versions(ctx, tool, dir, all, show_all):
the nf-core/modules repo.
"""
try:
version_bumper = nf_core.modules.bump_versions.ModuleVersionBumper(pipeline_dir=dir)
version_bumper = nf_core.modules.bump_versions.ModuleVersionBumper(
dir, ctx.obj["modules_repo_url"], ctx.obj["modules_repo_branch"], ctx.obj["modules_repo_no_pull"]
)
version_bumper.bump_versions(module=tool, all_modules=all, show_uptodate=show_all)
except nf_core.modules.module_utils.ModuleException as e:
log.error(e)
sys.exit(1)
except UserWarning as e:
except (UserWarning, LookupError) as e:
log.critical(e)
sys.exit(1)

Expand Down Expand Up @@ -742,7 +774,7 @@ def test_module(ctx, tool, no_prompts, pytest_args):
try:
meta_builder = nf_core.modules.ModulesTest(tool, no_prompts, pytest_args)
meta_builder.run()
except UserWarning as e:
except (UserWarning, LookupError) as e:
log.critical(e)
sys.exit(1)

Expand Down
9 changes: 8 additions & 1 deletion nf_core/lint/modules_json.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,14 @@ def modules_json(self):
all_modules_passed = True

for repo in modules_json["repos"].keys():
for key in modules_json["repos"][repo].keys():
# Check if the modules.json has been updated to keep the
if "modules" not in modules_json["repos"][repo] or "git_url" not in modules_json["repos"][repo]:
failed.append(
f"Your `modules.json` file is outdated. Please remove it and reinstall it by running any module command"
)
continue

for key in modules_json["repos"][repo]["modules"]:
if not key in modules_command.module_names[repo]:
failed.append(f"Entry for `{key}` found in `modules.json` but module is not installed in pipeline.")
all_modules_passed = False
Expand Down
4 changes: 2 additions & 2 deletions nf_core/modules/bump_versions.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@


class ModuleVersionBumper(ModuleCommand):
def __init__(self, pipeline_dir):
super().__init__(pipeline_dir)
def __init__(self, pipeline_dir, remote_url=None, branch=None, no_pull=False):
super().__init__(pipeline_dir, remote_url, branch, no_pull)

self.up_to_date = None
self.updated = None
Expand Down
33 changes: 7 additions & 26 deletions nf_core/modules/info.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,15 @@
from rich.table import Table
from rich.text import Text

from .module_utils import (
get_installed_modules,
get_module_git_log,
get_repo_type,
module_exist_in_repo,
)
from .module_utils import get_repo_type
from .modules_command import ModuleCommand
from .modules_repo import ModulesRepo

log = logging.getLogger(__name__)


class ModuleInfo(ModuleCommand):
def __init__(self, pipeline_dir, tool):
def __init__(self, pipeline_dir, tool, remote_url, branch, no_pull):

self.module = tool
self.meta = None
Expand All @@ -40,7 +35,7 @@ def __init__(self, pipeline_dir, tool):
log.debug(f"Only showing remote info: {e}")
pipeline_dir = None

super().__init__(pipeline_dir)
super().__init__(pipeline_dir, remote_url, branch, no_pull)

def get_module_info(self):
"""Given the name of a module, parse meta.yml and print usage help."""
Expand Down Expand Up @@ -93,28 +88,14 @@ def get_remote_yaml(self):
Returns:
dict or bool: Parsed meta.yml found, False otherwise
"""
# Fetch the remote repo information
self.modules_repo.get_modules_file_tree()

# Check if our requested module is there
if self.module not in self.modules_repo.modules_avail_module_names:
if self.module not in self.modules_repo.get_avail_modules():
return False

# Get the remote path
meta_url = None
for file_dict in self.modules_repo.modules_file_tree:
if file_dict.get("path") == f"modules/{self.module}/meta.yml":
meta_url = file_dict.get("url")

if not meta_url:
file_contents = self.modules_repo.get_meta_yml(self.module)
if file_contents is None:
return False

# Download and parse
log.debug(f"Attempting to fetch {meta_url}")
response = requests.get(meta_url)
result = response.json()
file_contents = base64.b64decode(result["content"])
self.remote_location = self.modules_repo.name
self.remote_location = self.modules_repo.fullname
return yaml.safe_load(file_contents)

def generate_module_info_help(self):
Expand Down
Loading