-
Notifications
You must be signed in to change notification settings - Fork 190
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
Provide helper script for template changes and broadcasting #88
Conversation
This script should be executed, once a new release is done for nf-core tools. It will traverse all pipelines and make changes according to the cookiecutter template and commit them into each pipelines branch 'TEMPLATE'.
addresses #74 |
Codecov Report
@@ Coverage Diff @@
## dev #88 +/- ##
==========================================
+ Coverage 91.47% 91.53% +0.06%
==========================================
Files 7 7
Lines 704 709 +5
==========================================
+ Hits 644 649 +5
Misses 60 60
Continue to review full report at Codecov.
|
bin/broadcast_prs.py
Outdated
# Get context from pipeline and load it into a dictionary | ||
# context = load_context(pipeline) | ||
print(pipeline['name']) # Just for testing, can be safely deleted | ||
ut.UpdateTemplate(pipeline['name'], context) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is "ut" defined somewhere?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it is a typo. Maybe @sven1103 meant it to be ut =
(not ut.
) 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
copy waste error, had separated test scripts before :D Well spotted!
Required config variables for running the cookiecutter template:
|
Also, the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Really nice work! A few minor comments and suggestions added here, plus recommendations for updates with the new nf-core create
subcommand.
bin/broadcast_prs.py
Outdated
def _clone_repo(self): | ||
"""Clone the repo and switch to the configured branch. | ||
""" | ||
subprocess.run(["git", "clone", self.repo_url, "-b", self.branch, self.pipeline]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could be nicer with GitPython. Also perhaps working in a temporary directory instead of the cwd? eg:
self.tmpdir = tempfile.mkdtemp()
self.repo = git.Repo.clone_from(self.repo_url, self.tmpdir)
self.repo.git.checkout(self.branch)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh yes, looks much cleaner. And it stays in the same thread :D
bin/broadcast_prs.py
Outdated
"""Apply the changes of the cookiecutter template | ||
to the pipelines template branch. | ||
""" | ||
cookiecutter(NF_CORE_TEMPLATE, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of using cookiecutter, you can now use nf-core create
:
from nf_core.create import run_cookiecutter
run_cookiecutter(self.pipeline_name, self.pipeline_description, self.pipeline_version)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NB: I should probably add an option to specify an output directory. At the moment it just spits it out into the current working directory I think. I guess you'll want to use self.tmpdir
.
Also note that currently it creates the files in a subdirectory called self.pipeline_name. I haven't figured an easy way to avoid this, though I guess the create
command could also use a temp directory and then copy.
bin/broadcast_prs.py
Outdated
def _commit_changes(self): | ||
"""Commits the changes of the new template to the current branch. | ||
""" | ||
subprocess.run(["git", "add", "-A", "."], cwd=self.pipeline) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
self.repo.git.add(A=True)
self.repo.index.commit("Update nf-core template")
Could also be nice to reference os.environ('TRAVIS_TAG')
in the commit message.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yup, agree, this is a nice idea!
bin/broadcast_prs.py
Outdated
Returns: An instance of class requests.Response | ||
""" | ||
content = {} | ||
content['title'] = "Important pipeline nf-core update!" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As above, could be nice to reference the release tag with os.environ('TRAVIS_TAG')
bin/broadcast_prs.py
Outdated
""" | ||
content = {} | ||
content['title'] = "Important pipeline nf-core update!" | ||
content['body'] = "Some important changes have been made in the nf-core pipelines templates.\n" + |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could perhaps link to 'https://github.com/nf-core/tools/releases/tag/{}'.format(os.environ('TRAVIS_TAG'))
here too, to easily show the changelog...
bin/broadcast_prs.py
Outdated
"Please make sure to merge this in ASAP and make a new minor release of your pipeline." | ||
content['head'] = "{}:{}".format(pipeline, template) | ||
content['base'] = master | ||
return requests.post(url=GITHUB_PR_URL_TEMPL.format(pipeline=pipeline), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is ridiculously simple and awesome 😎
bin/broadcast_prs.py
Outdated
|
||
Returns: A context dictionary | ||
""" | ||
pass |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
?
bin/broadcast_prs.py
Outdated
pass | ||
|
||
def main(): | ||
res = requests.get(NF_CORE_PIPELINE_INFO) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe do a check for TRAVIS_TAG
environment variable here first to make sure that we're running on Travis?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yup, planned this too :D
I think we need to add the creation of the 'TEMPLATE' branch to the |
@alneberg you are right. But I guess that would be a new issue, as this PR only addresses the distribution, right? |
I did the switch now. So don't worry about it. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks really good!
My only concerns are regarding better error catching, especially for pipelines where everything is not yet properly set up.
bin/broadcast_prs.py
Outdated
""" | ||
self.repo = git.Repo.clone_from(self.repo_url, self.tmpdir) | ||
config = utils.fetch_wf_config(wf_path=self.tmpdir) | ||
self.repo.git.checkout("origin/{branch}".format(branch=self.branch), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess this will fail when pipelines doesn't have a TEMPLATE branch. Might be useful to fail gracefully in that case, since it will be very common at least in the beginning?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think failing here is totally ok, as the error will be listed in the Travis log anyway with stacktrace. So in my opinion no need to try catch here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes sure, but it would also cause the script to crash on the first pipeline without a TEMPLATE branch and no pull requests at all would be created. But that is perhaps what you intended?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean, i can catch the errors in a list, and print them afterwards? So we see all failing pipelines at once?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i think this indeed would make sense here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I didn't understand if you changed your mind or not. From my understanding the script will be run once in the tools travis and it would be strange if it would fail/crash until all pipelines are set up properly, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think he changed his mind to agree with you 😉
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yup, I agree with @alneberg 's suggestion
bin/broadcast_prs.py
Outdated
|
||
|
||
def create_pullrequest(pipeline, origin="dev", template="TEMPLATE", token="", user="nf-core"): | ||
"""Create a pull request to a base branch (default: dev), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like that it defaults to dev, but I think it is still a lot of pipelines that do not use a dev branch yet.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same as above. Let it fail. The dev branch will be a requirement we need to document :)
bin/syncutils/template.py
Outdated
"""Apply the changes of the cookiecutter template | ||
to the pipelines template branch. | ||
""" | ||
cookiecutter(template_url, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any reason to do this directly using cookiecutter? It may be safer / more futureproof to use the nf-core.create.run_cookiecutter
function instead, in case that is updated in the future... Especially if we add an output directory argument to that feature (which we should - I'll do that now).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, but how can I access this function from within my script? Traversing through the repo just to access the code is quite ugly
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean, I can extend the system path so python will find the nf-core module, but it is not very consice
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking nice! Still some stuff you can simplify if you're using the nf_core command to generate the template.
# The GitHub base url or the nf-core project | ||
GH_BASE_URL = "https://{token}@github.com/nf-core/{pipeline}" | ||
# The current cookiecutter template url for nf-core pipelines | ||
NF_CORE_TEMPLATE = os.path.join( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You don't need to define this any more if you're using the function from the nf_core
package.
from cookiecutter.main import cookiecutter | ||
|
||
# Enable access to the nf_core package | ||
rootPath = os.path.abspath("../..") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't really understand why you need to do this?
except: | ||
os.remove(os.path.join(target_dir, f)) | ||
# Move the new template content into the template branch | ||
template_path = os.path.join(self.templatedir, self.pipeline) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You don't need to do any of this now that I added the new outdir
option for the nf_core function.
This script should be executed every time a new release is created for nf-core tools. It will traverse all pipelines and make changes according to the cookiecutter template and commit them into a branch called
TEMPLATE
on each repository.In addition, a new pull request will be created for every pipeline, which will introduce the changes in the template to the pipeline source code.