forked from ReproNim/neurodocker
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from Alafia-Ai/20220414-fs-source
Brings 20220414-fs-source branch up to date with ReproNim/master
- Loading branch information
Showing
69 changed files
with
1,511 additions
and
848 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
{ | ||
"onlyPublishWithReleaseLabel": true, | ||
"baseBranch": "master", | ||
"author": "Repronim Bot <[email protected]>", | ||
"noVersionPrefix": true, | ||
"plugins": ["git-tag"] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
[codespell] | ||
skip = .git,*.pdf,*.svg,versioneer.py,_version.py | ||
# didi -- some name Dear to someone | ||
ignore-words-list = didi |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
{ "bad_versions" : ["0.9.2", "0.9.3"] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
--- | ||
# Documentation | ||
# https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file | ||
version: 2 | ||
updates: | ||
- package-ecosystem: github-actions | ||
directory: / | ||
schedule: | ||
interval: weekly |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
# this workflow bootstraps the testing of the build the docker images | ||
# | ||
# - this will run the python script used to generate the workflows | ||
# based on a the jinja template | ||
# - commit and push the generated workflows to the branch test_docker_build | ||
# where they will be executed | ||
|
||
name: bootstrap | ||
|
||
concurrency: | ||
group: ${{ github.workflow }}-${{ github.ref }} | ||
cancel-in-progress: true | ||
|
||
on: | ||
push: | ||
branches: [ "master" ] | ||
paths: | ||
- .github/workflows/bootstrap.yml | ||
- .github/workflows/create_workflows.py | ||
- neurodocker/** | ||
|
||
# Uses the cron schedule for github actions | ||
# | ||
# https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#scheduled-events | ||
# | ||
# ┌───────────── minute (0 - 59) | ||
# │ ┌───────────── hour (0 - 23) | ||
# │ │ ┌───────────── day of the month (1 - 31) | ||
# │ │ │ ┌───────────── month (1 - 12 or JAN-DEC) | ||
# │ │ │ │ ┌───────────── day of the week (0 - 6 or SUN-SAT) | ||
# │ │ │ │ │ | ||
# │ │ │ │ │ | ||
# │ │ │ │ │ | ||
# * * * * * | ||
|
||
schedule: | ||
- cron: 0 0 1,15 * * | ||
|
||
# Allows you to run this workflow manually from the Actions tab | ||
workflow_dispatch: | ||
inputs: | ||
software_name: | ||
description: 'software to test' | ||
required: true | ||
default: 'all' | ||
|
||
permissions: | ||
contents: write | ||
actions: write | ||
jobs: | ||
bootstrap: | ||
runs-on: ubuntu-22.04 | ||
|
||
steps: | ||
- uses: actions/checkout@v4 | ||
with: | ||
token: ${{ secrets.CI_FLOW }} | ||
|
||
- name: Set up Python | ||
uses: actions/setup-python@v4 | ||
with: | ||
python-version: '3.11' | ||
|
||
- name: Install dependencies | ||
run: python -m pip install jinja2 pyyaml | ||
|
||
- name: Create workflows | ||
run: | | ||
software_name=${{ inputs.software_name }} | ||
if [ -z "$software_name" ]; then | ||
software_name="all" | ||
fi | ||
if [ "$software_name" = "all" ]; then | ||
echo "testing all software" | ||
else | ||
echo "testing ${software_name}" | ||
fi | ||
git checkout -b test_docker_build | ||
python .github/workflows/create_workflows.py --software_name ${software_name} | ||
ls -l .github/workflows | ||
git add . | ||
git config --global user.email "[email protected]" | ||
git config --global user.name "Repronim neurodocker bot" | ||
git commit -am "added new workflows" | ||
git push origin --force test_docker_build |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
--- | ||
name: Codespell | ||
|
||
on: | ||
push: | ||
branches: [master] | ||
pull_request: | ||
branches: [master] | ||
|
||
concurrency: | ||
group: ${{ github.workflow }}-${{ github.ref }} | ||
cancel-in-progress: true | ||
|
||
permissions: | ||
contents: read | ||
|
||
jobs: | ||
codespell: | ||
name: Check for spelling errors | ||
runs-on: ubuntu-latest | ||
|
||
steps: | ||
- name: Checkout | ||
uses: actions/checkout@v4 | ||
- name: Codespell | ||
uses: codespell-project/actions-codespell@v2 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,218 @@ | ||
""" | ||
This scripts uses a jinja template to create CI workflows to test. | ||
- different linux distributions (split by the package manager they use) | ||
- different software that neurodocker supports | ||
- different install method for a given software | ||
All of those are defined in a python dictionary. | ||
Versions to install are read from the neurodocker template for a given software. | ||
It is possible to skip a version by adding a "skip_versions" key to the software. | ||
Each workflow: | ||
- installs the latest version of neurodocker | ||
- builds a dockerfile for a combination of OS / software / version / install method | ||
- cat the dockerfile | ||
- attempts to build the corresponding image | ||
This script will also create a "dashboard" saved in docs/README.md | ||
to be picked up to be rendered by the github pages. | ||
This requires for you to build the pages from the docs folder | ||
and on the branch where the workflows are pushed to (currently "test_docker_build"). | ||
""" | ||
import argparse | ||
from pathlib import Path | ||
|
||
import yaml # type: ignore | ||
from jinja2 import Environment, FileSystemLoader, select_autoescape | ||
|
||
apt_based = [ | ||
"ubuntu:22.04", | ||
"ubuntu:18.04", | ||
"debian:bullseye-slim", | ||
"debian:buster-slim", | ||
] | ||
yum_based = ["fedora:36", "centos:7"] | ||
|
||
""" | ||
Add a "skip_versions" key to the software dictionary if you want to skip | ||
testing a specific version. For example, if you want to skip testing | ||
version 1.0.0 of afni, add the following to the software dictionary: | ||
"afni": { | ||
"skip_versions": ["1.0.0"], | ||
"methods": ["binaries", "source"], | ||
"afni_python": ["true", "false"], | ||
}, | ||
""" | ||
output_dir = Path(__file__).parent | ||
|
||
template_folder = Path(__file__).parents[2].joinpath("neurodocker", "templates") | ||
|
||
build_dashboard_file = Path(__file__).parents[2].joinpath("docs", "README.md") | ||
|
||
# this has to match the name of the branch where the workflows are pushed to | ||
# see .github/workflows/bootstrap.yml | ||
branch = "test_docker_build" | ||
|
||
# Update to match your username and repo name if you are testing things on your fork | ||
# "ReproNim/neurodocker" | ||
repo = "ReproNim/neurodocker" | ||
|
||
|
||
def software() -> dict[str, dict[str, list[str]]]: | ||
return { | ||
"afni": { | ||
"methods": ["binaries", "source"], | ||
"afni_python": ["true", "false"], | ||
}, | ||
"ants": { | ||
"methods": ["binaries", "source"], | ||
}, | ||
"cat12": {"methods": ["binaries"]}, | ||
"convert3d": {"methods": ["binaries"]}, | ||
"dcm2niix": { | ||
"methods": ["binaries", "source"], | ||
}, | ||
"freesurfer": {"methods": []}, | ||
"fsl": { | ||
"methods": ["binaries"], | ||
}, | ||
"matlabmcr": { | ||
"methods": ["binaries"], | ||
}, | ||
"mricron": {"methods": ["binaries"]}, | ||
"mrtrix3": { | ||
"methods": ["binaries", "source"], | ||
}, | ||
"spm12": {"methods": ["binaries"]}, | ||
"miniconda": {}, | ||
} | ||
|
||
|
||
def create_dashboard_file(): | ||
"""Create a build dashboard file.""" | ||
|
||
print("creating build dashboard file...") | ||
print(build_dashboard_file) | ||
|
||
gh_actions_url = "http://github-actions.40ants.com/" | ||
|
||
with open(build_dashboard_file, "w") as f: | ||
image_base_url = f"{gh_actions_url}{repo}/matrix.svg?branch={branch}" | ||
print( | ||
"""<!-- This page is generated automatically. Do not edit manually. --> | ||
# Build dashboard | ||
""", | ||
file=f, | ||
) | ||
|
||
# table of content | ||
for software_, _ in software().items(): | ||
print(f"""- [{software_}](#{software_})""", file=f) | ||
|
||
print("", file=f) | ||
|
||
# link to the github actions workflow and image of the build status | ||
for software_, _ in software().items(): | ||
image_url = f"{image_base_url}&only={software_}" | ||
print( | ||
f"""## {software_} | ||
[{software_} workflow](https://github.com/{repo}/actions/workflows/{software_}.yml) | ||
![{software_} build status]({image_url}) | ||
""", | ||
file=f, | ||
) | ||
|
||
|
||
def get_versions_from_neurodocker_template(software: str) -> list[str]: | ||
"""Load the list of versions to test from the software template.""" | ||
template = template_folder.joinpath(software).with_suffix(".yaml") | ||
with open(template, "r") as f: | ||
data = yaml.load(f, Loader=yaml.FullLoader) | ||
return list(data["binaries"]["urls"].keys()) | ||
|
||
|
||
def stringify(some_list: list[str]) -> str: | ||
if len(some_list) == 1: | ||
return f"'{some_list[0]}'" | ||
return "'" + "', '".join(some_list) + "'" | ||
|
||
|
||
def main(software_name="all"): | ||
env = Environment( | ||
loader=FileSystemLoader(Path(__file__).parent), | ||
autoescape=select_autoescape(), | ||
lstrip_blocks=True, | ||
trim_blocks=True, | ||
) | ||
|
||
template = env.get_template("docker_build.jinja") | ||
|
||
os = { | ||
"apt_based": stringify(apt_based), | ||
"yum_based": stringify(yum_based), | ||
"all": stringify(apt_based + yum_based), | ||
} | ||
|
||
# only keep relevant software | ||
software_to_test = software() | ||
if software_name in software_to_test: | ||
software_to_test = {software_name: software_to_test[software_name]} | ||
|
||
for software_, spec in software_to_test.items(): | ||
wf = { | ||
"header": "# This is file is automatically generated. Do not edit.", | ||
"os": os, | ||
"software": software_, | ||
} | ||
|
||
versions = get_versions_from_neurodocker_template(software_) | ||
for i in spec.get("skip_versions", []): | ||
versions.remove(i) | ||
if software_ == "miniconda": | ||
versions = ["latest"] | ||
|
||
if versions is not None and len(versions) > 0: | ||
wf["add_version"] = True | ||
wf["versions"] = stringify(versions) | ||
|
||
if spec.get("methods") is not None and len(spec["methods"]) > 0: | ||
wf["add_method"] = True | ||
wf["methods"] = stringify(spec["methods"]) | ||
|
||
if spec.get("afni_python") is not None and len(spec["afni_python"]) > 0: | ||
wf["add_afni_python"] = True | ||
wf["afni_python"] = stringify(spec["afni_python"]) | ||
|
||
output_file = output_dir.joinpath(software_).with_suffix(".yml") | ||
print("creating workflow") | ||
print(f"{output_file}") | ||
with open(output_file, "w") as f: | ||
print(template.render(wf=wf), file=f) | ||
|
||
create_dashboard_file() | ||
|
||
|
||
if __name__ == "__main__": | ||
parser = argparse.ArgumentParser() | ||
|
||
choices = list(software().keys()) | ||
choices.append("all") | ||
|
||
parser.add_argument( | ||
"--software_name", | ||
required=False, | ||
default="all", | ||
choices=choices, | ||
nargs=1, | ||
) | ||
args = parser.parse_args() | ||
|
||
main(software_name=args.software_name[0]) |
Oops, something went wrong.