diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index bc5a2385..8470effa 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -153,6 +153,7 @@ jobs: - automation.sh - auto-format-tools.sh - build-systems.sh + - ci.sh - containers.sh - docs-jupyter-book.sh - docs-mkdocs.sh diff --git a/.makim.yaml b/.makim.yaml index ee6edf56..c993abc9 100644 --- a/.makim.yaml +++ b/.makim.yaml @@ -68,6 +68,7 @@ groups: run: | ./tests/smoke/auto-format-tools.sh ./tests/smoke/build-systems.sh + ./tests/smoke/ci.sh ./tests/smoke/cli.sh ./tests/smoke/containers.sh ./tests/smoke/docs-jupyter-book.sh diff --git a/conda/dev-win.yaml b/conda/dev-win.yaml index 6c244888..97e9dcdb 100644 --- a/conda/dev-win.yaml +++ b/conda/dev-win.yaml @@ -5,6 +5,7 @@ channels: dependencies: - m2-bash - git + - opensciencelabs::circleci-cli - python >=3.8.1,<3.12 - poetry >=1.5 - nodejs diff --git a/conda/dev.yaml b/conda/dev.yaml index 93541188..c3dfb44c 100644 --- a/conda/dev.yaml +++ b/conda/dev.yaml @@ -5,6 +5,7 @@ channels: dependencies: - bash - git + - opensciencelabs::circleci-cli - python >=3.8.1,<3.12 - poetry >=1.5 - nodejs diff --git a/docs/guide.md b/docs/guide.md index bc2d9ec1..4d0083af 100644 --- a/docs/guide.md +++ b/docs/guide.md @@ -971,3 +971,23 @@ By providing this information, you can easily integrate your codebase with GitHub and take advantage of its powerful version control features. These functionalities in SciCookie make it easy to manage your project and collaborate with others, while ensuring that your code is properly versioned and tracked. + +## Continuos integration + +Continuous Integration (CI) is a development practice where code changes are +frequently merged into a shared repository. Each change is automatically built +and tested to ensure it does not introduce defects or break existing +functionality. This process helps prevent integration issues and improves code +quality. + +CI tools provide automated feedback on code changes, allowing developers to +quickly identify and fix problems. By automating repetitive tasks, CI also saves +time and effort. With SciCookie you can integrate tools like GitHub and/or +CircleCI into your project. + +- GitHub Actions (**github_actions**): This option allows you to incorporate + GitHub Actions into your project. As a native CI/CD platform integrated with + GitHub, it offers flexible workflows and an easy setup process. +- CircleCI (**circleci**): This option enables you to integrate CircleCI into + your project. Known for its speed and reliability, CircleCI is a cloud-based + CI/CD platform that streamlines the development process. diff --git a/src/scicookie/cookiecutter.json b/src/scicookie/cookiecutter.json index 9e1e6b42..d8aa1736 100644 --- a/src/scicookie/cookiecutter.json +++ b/src/scicookie/cookiecutter.json @@ -78,5 +78,7 @@ "git_username": "zoro_roronoa", "git_https_origin": "", "git_https_upstream": "", - "git_main_branch": "main" + "git_main_branch": "main", + "use_github_actions": "no", + "use_circleci": "no" } diff --git a/src/scicookie/hooks/post_gen_project.py b/src/scicookie/hooks/post_gen_project.py index 4c1d4827..d810ea4a 100644 --- a/src/scicookie/hooks/post_gen_project.py +++ b/src/scicookie/hooks/post_gen_project.py @@ -50,6 +50,8 @@ USE_PRE_COMMIT = {{ cookiecutter.use_pre_commit == "yes" }} USE_PYTEST = {{ cookiecutter.use_pytest == "yes" }} USE_HYPOTHESIS = {{ cookiecutter.use_hypothesis == "yes" }} +USE_GITHUB_ACTIONS = {{ cookiecutter.use_github_actions == "yes" }} +USE_CIRCLECI = {{ cookiecutter.use_circleci == "yes" }} {% if cookiecutter.code_of_conduct == "contributor-covenant" -%} COC_PATH = PROJECT_DIRECTORY / 'coc' / 'CONTRIBUTOR_COVENANT.md' {%- elif cookiecutter.code_of_conduct == "citizen-code-of-conduct" -%} @@ -98,6 +100,7 @@ {%- endif %} + def remove_dirs(dirs: list): for dirs in dirs: shutil.rmtree(dirs) @@ -319,6 +322,12 @@ def clean_up_build_system(): remove_dir("build-system") +def clean_up_ci(): + if not USE_CIRCLECI: + remove_dir(".circleci") + if not USE_GITHUB_ACTIONS: + remove_dir(".github") + def http2ssh(url): url = url.replace("https://", "git@") return url.replace("/", ":", 1) @@ -420,6 +429,7 @@ def prepare_git() -> None: def post_gen(): # keep this one first, because it changes the package folder clean_up_project_layout() + clean_up_ci() clean_up_automation() clean_up_cli() clean_up_code_of_conduct() diff --git a/src/scicookie/profiles/base.yaml b/src/scicookie/profiles/base.yaml index 0a316317..d76ecdb4 100644 --- a/src/scicookie/profiles/base.yaml +++ b/src/scicookie/profiles/base.yaml @@ -290,3 +290,12 @@ git_main_branch: type: "text" default: main visible: true + +continuos_integration: + message: Select one option for Continuous Integration + help: "For more information, check:\n https://osl-incubator.github.io/scicookie/guide/#continuous-integration" + type: multiple-choices + choices: + - github_actions + - circleci + visible: true diff --git a/src/scicookie/profiles/osl.yaml b/src/scicookie/profiles/osl.yaml index 04656eda..de9f5883 100644 --- a/src/scicookie/profiles/osl.yaml +++ b/src/scicookie/profiles/osl.yaml @@ -104,3 +104,8 @@ git_https_upstream: git_main_branch: visible: true + +continuos_integration: + choices: + - github_actions + visible: false diff --git a/src/scicookie/{{cookiecutter.project_slug}}/.circleci/config.yml b/src/scicookie/{{cookiecutter.project_slug}}/.circleci/config.yml new file mode 100644 index 00000000..f5891a84 --- /dev/null +++ b/src/scicookie/{{cookiecutter.project_slug}}/.circleci/config.yml @@ -0,0 +1,81 @@ +version: 2.1 # Adjust if needed based on CircleCI requirements +executors: + default_image: + docker: +{%- if cookiecutter.use_conda == "yes" %} + - image: continuumio/miniconda3 +jobs: + check-branch: + executor: default_image + steps: + - checkout + test: + docker: + - image: continuumio/miniconda3 + steps: + - checkout + - run: + name: Create environment + command: | + conda env create -f conda/dev.yaml + conda init bash + source ~/.bashrc + conda activate {{ cookiecutter.project_slug }} +{%- else %} + - image: cimg/python:3.10 # Adjust Python version if needed +jobs: + check-branch: + executor: default_image + steps: + - checkout + test: + executor: default_image + steps: + - checkout + - run: + name: Create environment and install dependencies + command: | + python -m pip install -r requirements.txt +{%- endif %} + {%- if cookiecutter.build_system == "poetry" %} + poetry install + {%- elif cookiecutter.build_system == "flit" %} + flit install + {%- elif cookiecutter.build_system == "pdm" %} + pdm install + {%- else %} + pip install . + {%- endif %} + export PATH=$PATH:/home/circleci/.pyenv/versions/3.10.15/bin; + {%- if cookiecutter.use_pre_commit == "yes" %} + pre-commit install + {%- endif %} + {%- if cookiecutter.use_makim == "yes" %} + makim tests.unit + makim tests.linter + {%- endif %} + {%- if cookiecutter.use_make == "yes" %} + make test + make lint + {%- endif %} +{%- if cookiecutter.use_conda == "yes" %} + - save_cache: + paths: + - ~/.conda/envs/{{ cookiecutter.project_slug }} + key: conda-{% raw %}{{ checksum "conda/dev.yaml" }}{% endraw %} +{%- endif %} +workflows: + main: + jobs: + - check-branch: + filters: + branches: + only: + - main + tags: {} + - test: + filters: + branches: + only: + - main + tags: {} diff --git a/src/scicookie/{{cookiecutter.project_slug}}/docs-mkdocs/mkdocs.yaml b/src/scicookie/{{cookiecutter.project_slug}}/docs-mkdocs/mkdocs.yaml index da49fa07..97decd64 100644 --- a/src/scicookie/{{cookiecutter.project_slug}}/docs-mkdocs/mkdocs.yaml +++ b/src/scicookie/{{cookiecutter.project_slug}}/docs-mkdocs/mkdocs.yaml @@ -23,7 +23,7 @@ theme: name: mkdocs {% else %} name: {{ cookiecutter.mkdocs_theme }} -{% endif%} +{% endif %} features: - content.code.annotate - content.tabs.link diff --git a/src/scicookie/{{cookiecutter.project_slug}}/tests/test_main.py b/src/scicookie/{{cookiecutter.project_slug}}/tests/test_main.py index d4d23919..12b36664 100644 --- a/src/scicookie/{{cookiecutter.project_slug}}/tests/test_main.py +++ b/src/scicookie/{{cookiecutter.project_slug}}/tests/test_main.py @@ -38,7 +38,7 @@ def test_content_pytest(): {%- if cookiecutter.use_hypothesis == "yes" %} -@given(st.text()) +@given(st.text().filter(lambda s: s != "")) def test_content_hypothesis(response_hypothesis): """Test with pytest + hypothesis.""" assert response_hypothesis diff --git a/tests/profiles/test-depends-on.yaml b/tests/profiles/test-depends-on.yaml index dff8261f..448da12f 100644 --- a/tests/profiles/test-depends-on.yaml +++ b/tests/profiles/test-depends-on.yaml @@ -299,3 +299,12 @@ git_main_branch: type: "text" default: main visible: true + +continuos_integration: + message: Select one option for Continuous Integration + help: "For more information, check:\n https://osl-incubator.github.io/scicookie/guide/#continuous-integration" + type: multiple-choices + choices: + - github_actions + - circleci + visible: true diff --git a/tests/profiles/test-main.yaml b/tests/profiles/test-main.yaml index cbb06b6f..9f3cb1e2 100644 --- a/tests/profiles/test-main.yaml +++ b/tests/profiles/test-main.yaml @@ -295,3 +295,12 @@ git_main_branch: type: "text" default: main visible: true + +continuos_integration: + message: Select one option for Continuous Integration + help: "For more information, check:\n https://osl-incubator.github.io/scicookie/guide/#continuous-integration" + type: multiple-choices + choices: + - github_actions + - circleci + visible: true diff --git a/tests/smoke/ci.sh b/tests/smoke/ci.sh new file mode 100755 index 00000000..028f538b --- /dev/null +++ b/tests/smoke/ci.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash +set -e + +SMOKE_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" + +# run the complete smoke tests +. ${SMOKE_DIR}/base.sh "use_circleci=yes use_conda=yes" +. ${SMOKE_DIR}/base.sh "use_circleci=yes use_pyenv=yes" + +# check the CI files from template +. ${SMOKE_DIR}/base-template.sh "use_circleci=yes use_conda=yes" +pushd /tmp/osl/osl-python-package + circleci config validate +popd + +. ${SMOKE_DIR}/base-template.sh "use_circleci=yes use_pyenv=yes" +pushd /tmp/osl/osl-python-package + circleci config validate +popd