Skip to content

Commit

Permalink
Remove dependency on tox in the CI/CD pipeline (#118)
Browse files Browse the repository at this point in the history
* remove ruff from venv
* no tox in ci
* improve tests
* update makefile
  • Loading branch information
fpgmaas authored Jul 15, 2024
1 parent 0db00df commit a7682be
Show file tree
Hide file tree
Showing 15 changed files with 194 additions and 142 deletions.
15 changes: 12 additions & 3 deletions .github/actions/setup-poetry-env/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,18 @@ runs:
python-version: ${{ inputs.python-version }}

- name: Install Poetry
uses: snok/install-poetry@v1
with:
virtualenvs-in-project: true
env:
POETRY_VERSION: "1.7.1"
run: curl -sSL https://install.python-poetry.org | python - -y
shell: bash

- name: Add Poetry to Path
run: echo "$HOME/.local/bin" >> $GITHUB_PATH
shell: bash

- name: Configure Poetry virtual environment in project
run: poetry config virtualenvs.in-project true
shell: bash

- name: Load cached venv
id: cached-poetry-dependencies
Expand Down
39 changes: 15 additions & 24 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
name: Main

on:
push:
branches:
- main
pull_request:
types: [opened, synchronize, reopened]
push:
branches: [main]

jobs:
quality:
Expand All @@ -31,40 +30,32 @@ jobs:
- name: Check Poetry lock file consistency
run: poetry lock --check

tox:
tests-and-type-check:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.8", "3.9", "3.10", "3.11"]
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
fail-fast: false
defaults:
run:
shell: bash
steps:
- name: Check out
uses: actions/checkout@v4

- name: Set up python
uses: actions/setup-python@v5
- name: Set up the environment
uses: ./.github/actions/setup-poetry-env
with:
python-version: ${{ matrix.python-version }}

- name: Install Poetry
uses: snok/install-poetry@v1

- name: Load cached venv
uses: actions/cache@v4
with:
path: .tox
key: venv-${{ runner.os }}-${{ matrix.python-version }}-${{ hashFiles('poetry.lock') }}

- name: Install tox
run: |
python -m pip install --upgrade pip
python -m pip install tox tox-gh-actions
- name: Run tests
run: poetry run pytest tests --cov --cov-config=pyproject.toml --cov-report=xml

- name: Test with tox
run: tox
- name: Check typing
run: poetry run mypy

- name: Upload coverage reports to Codecov with GitHub Action on Python 3.11
uses: codecov/codecov-action@v4
- name: Upload coverage reports to Codecov with GitHub Action on Python 3.11 for Ubuntu
uses: codecov/codecov-action@v3
if: ${{ matrix.python-version == '3.11' }}

check-docs:
Expand Down
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ repos:
- id: trailing-whitespace

- repo: https://github.com/astral-sh/ruff-pre-commit
rev: "v0.5.0"
rev: "v0.5.2"
hooks:
- id: ruff
args: [--exit-non-zero-on-fix, --config=pyproject.toml]
Expand Down
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,11 @@ build-and-publish: build publish ## Build and publish.

.PHONY: docs-test
docs-test: ## Test if documentation can be built without warnings or errors
@mkdocs build -s
@poetry run mkdocs build -s

.PHONY: docs
docs: ## Build and serve the documentation
@mkdocs serve
@poetry run mkdocs serve

.PHONY: help
help:
Expand Down
2 changes: 2 additions & 0 deletions cookiecutter_poetry/cli.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import annotations

import os


Expand Down
2 changes: 2 additions & 0 deletions hooks/post_gen_project.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#!/usr/bin/env python
from __future__ import annotations

import os
import shutil

Expand Down
2 changes: 2 additions & 0 deletions hooks/pre_gen_project.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import annotations

import re
import sys

Expand Down
137 changes: 72 additions & 65 deletions poetry.lock

Large diffs are not rendered by default.

12 changes: 5 additions & 7 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ pytest = "^7.2.0"
pre-commit = "^2.20.0"
pytest-cookies = "^0.6.1"
tox = "^3.25.1"
deptry = "^0.12.0"
deptry = "^0.16.2"
mypy = "^0.991"
pytest-cov = "^4.0.0"

Expand All @@ -37,11 +37,6 @@ mkdocs-material = "^8.5.10"
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"

[tool.black]
line-length = 120
target-version = ['py37']
preview = true

[tool.poetry.scripts]
ccp = 'cookiecutter_poetry.cli:main'

Expand All @@ -67,7 +62,7 @@ show_error_codes = "True"

[tool.deptry]
extend_exclude = [
"{{cookiecutter.project_name}}"
".+/test_foo.py"
]

[tool.deptry.per_rule_ignores]
Expand Down Expand Up @@ -120,3 +115,6 @@ ignore = [

[tool.ruff.lint.per-file-ignores]
"tests/*" = ["S101", "S603"]

[tool.ruff.lint.isort]
required-imports = ["from __future__ import annotations"]
29 changes: 13 additions & 16 deletions tests/test_cookiecutter.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,10 @@
from __future__ import annotations

import os
import shlex
import subprocess
from contextlib import contextmanager


@contextmanager
def run_within_dir(path: str):
oldpwd = os.getcwd()
os.chdir(path)
try:
yield
finally:
os.chdir(oldpwd)


def file_contains_text(file: str, text: str) -> bool:
with open(file) as f:
return f.read().find(text) != -1
from tests.utils import file_contains_text, is_valid_yaml, run_within_dir


def test_bake_project(cookies):
Expand All @@ -37,6 +25,7 @@ def test_using_pytest(cookies, tmp_path):
assert result.exception is None
assert result.project_path.name == "example-project"
assert result.project_path.is_dir()
assert is_valid_yaml(result.project_path / ".github" / "workflows" / "main.yml")

# Install the poetry environment and run the tests.
with run_within_dir(str(result.project_path)):
Expand Down Expand Up @@ -66,6 +55,7 @@ def test_cicd_contains_artifactory_secrets(cookies, tmp_path):
with run_within_dir(tmp_path):
result = cookies.bake(extra_context={"publish_to": "artifactory"})
assert result.exit_code == 0
assert is_valid_yaml(result.project_path / ".github" / "workflows" / "on-release-main.yml")
for text in ["ARTIFACTORY_URL", "ARTIFACTORY_USERNAME", "ARTIFACTORY_PASSWORD"]:
assert file_contains_text(f"{result.project_path}/.github/workflows/on-release-main.yml", text)
assert file_contains_text(f"{result.project_path}/Makefile", "build-and-publish")
Expand All @@ -75,6 +65,7 @@ def test_cicd_contains_pypi_secrets(cookies, tmp_path):
with run_within_dir(tmp_path):
result = cookies.bake(extra_context={"publish_to": "pypi"})
assert result.exit_code == 0
assert is_valid_yaml(result.project_path / ".github" / "workflows" / "on-release-main.yml")
assert file_contains_text(f"{result.project_path}/.github/workflows/on-release-main.yml", "PYPI_TOKEN")
assert file_contains_text(f"{result.project_path}/Makefile", "build-and-publish")

Expand All @@ -83,6 +74,7 @@ def test_dont_publish(cookies, tmp_path):
with run_within_dir(tmp_path):
result = cookies.bake(extra_context={"publish_to": "none"})
assert result.exit_code == 0
assert is_valid_yaml(result.project_path / ".github" / "workflows" / "on-release-main.yml")
assert not file_contains_text(
f"{result.project_path}/.github/workflows/on-release-main.yml", "make build-and-publish"
)
Expand All @@ -92,6 +84,8 @@ def test_mkdocs(cookies, tmp_path):
with run_within_dir(tmp_path):
result = cookies.bake(extra_context={"mkdocs": "y"})
assert result.exit_code == 0
assert is_valid_yaml(result.project_path / ".github" / "workflows" / "main.yml")
assert is_valid_yaml(result.project_path / ".github" / "workflows" / "on-release-main.yml")
assert file_contains_text(f"{result.project_path}/.github/workflows/on-release-main.yml", "mkdocs gh-deploy")
assert file_contains_text(f"{result.project_path}/Makefile", "docs:")
assert os.path.isdir(f"{result.project_path}/docs")
Expand All @@ -101,6 +95,8 @@ def test_not_mkdocs(cookies, tmp_path):
with run_within_dir(tmp_path):
result = cookies.bake(extra_context={"mkdocs": "n"})
assert result.exit_code == 0
assert is_valid_yaml(result.project_path / ".github" / "workflows" / "main.yml")
assert is_valid_yaml(result.project_path / ".github" / "workflows" / "on-release-main.yml")
assert not file_contains_text(
f"{result.project_path}/.github/workflows/on-release-main.yml", "mkdocs gh-deploy"
)
Expand All @@ -112,7 +108,6 @@ def test_tox(cookies, tmp_path):
with run_within_dir(tmp_path):
result = cookies.bake()
assert result.exit_code == 0
assert file_contains_text(f"{result.project_path}/.github/workflows/main.yml", "pip install tox tox-gh-actions")
assert os.path.isfile(f"{result.project_path}/tox.ini")
assert file_contains_text(f"{result.project_path}/tox.ini", "[tox]")

Expand All @@ -135,6 +130,7 @@ def test_codecov(cookies, tmp_path):
with run_within_dir(tmp_path):
result = cookies.bake()
assert result.exit_code == 0
assert is_valid_yaml(result.project_path / ".github" / "workflows" / "main.yml")
assert os.path.isfile(f"{result.project_path}/codecov.yaml")
assert os.path.isfile(f"{result.project_path}/.github/workflows/validate-codecov-config.yml")

Expand All @@ -143,6 +139,7 @@ def test_not_codecov(cookies, tmp_path):
with run_within_dir(tmp_path):
result = cookies.bake(extra_context={"codecov": "n"})
assert result.exit_code == 0
assert is_valid_yaml(result.project_path / ".github" / "workflows" / "main.yml")
assert not os.path.isfile(f"{result.project_path}/codecov.yaml")
assert not os.path.isfile(f"{result.project_path}/.github/workflows/validate-codecov-config.yml")

Expand Down
42 changes: 42 additions & 0 deletions tests/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
from __future__ import annotations

import os
from contextlib import contextmanager
from pathlib import Path

import yaml


def is_valid_yaml(path: str | Path):
path = Path(path)

if not path.is_file():
print(f"File does not exist: {path}")
return False

try:
with path.open("r") as file:
yaml.safe_load(file)
except yaml.YAMLError as e:
print(f"Invalid YAML file: {path} - Error: {e}")
return False
except OSError as e:
print(f"Error reading file: {path} - Error: {e}")
return False

return True


@contextmanager
def run_within_dir(path: str):
oldpwd = os.getcwd()
os.chdir(path)
try:
yield
finally:
os.chdir(oldpwd)


def file_contains_text(file: str, text: str) -> bool:
with open(file) as f:
return f.read().find(text) != -1
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,18 @@ runs:
python-version: {% raw %}${{ inputs.python-version }}{% endraw %}

- name: Install Poetry
uses: snok/install-poetry@v1
with:
virtualenvs-in-project: true
env:
POETRY_VERSION: "1.7.1"
run: curl -sSL https://install.python-poetry.org | python - -y
shell: bash

- name: Add Poetry to Path
run: echo "$HOME/.local/bin" >> $GITHUB_PATH
shell: bash

- name: Configure Poetry virtual environment in project
run: poetry config virtualenvs.in-project true
shell: bash

- name: Load cached venv
id: cached-poetry-dependencies
Expand Down
29 changes: 11 additions & 18 deletions {{cookiecutter.project_name}}/.github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,37 +25,30 @@ jobs:
- name: Run checks
run: make check

tox:
tests-and-type-check:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ['3.8', '3.9', '3.10', '3.11']
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
fail-fast: false
defaults:
run:
shell: bash
steps:
- name: Check out
uses: actions/checkout@v4

- name: Set up python
uses: actions/setup-python@v5
- name: Set up the environment
uses: ./.github/actions/setup-poetry-env
with:
python-version: {% raw %}${{ matrix.python-version }}{% endraw %}

- name: Install Poetry
uses: snok/install-poetry@v1

- name: Load cached venv
uses: actions/cache@v4
with:
path: .tox
key: {% raw %}venv-${{ runner.os }}-${{ matrix.python-version }}-${{ hashFiles('poetry.lock') }}{% endraw %}
- name: Run tests
run: poetry run pytest tests --cov --cov-config=pyproject.toml --cov-report=xml

- name: Install tox
run: |
python -m pip install --upgrade pip
python -m pip install tox tox-gh-actions
- name: Check typing
run: poetry run mypy

- name: Test with tox
run: tox
{% if cookiecutter.codecov == "y" %}
- name: Upload coverage reports to Codecov with GitHub Action on Python 3.11
uses: codecov/codecov-action@v4
Expand Down
2 changes: 1 addition & 1 deletion {{cookiecutter.project_name}}/.pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ repos:
- id: trailing-whitespace

- repo: https://github.com/astral-sh/ruff-pre-commit
rev: "v0.1.6"
rev: "v0.5.2"
hooks:
- id: ruff
args: [--exit-non-zero-on-fix]
Expand Down
Loading

0 comments on commit a7682be

Please sign in to comment.