Skip to content

Commit

Permalink
fix: cwd template variable not working as expected
Browse files Browse the repository at this point in the history
  • Loading branch information
fyhertz committed Dec 22, 2022
1 parent 6a2fdef commit 6bdacf7
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 90 deletions.
70 changes: 9 additions & 61 deletions .github/workflows/cicd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,42 +44,16 @@ jobs:
debhelper
fakeroot
- name: Run black
run: poetry run black src tests --check

- name: Run isort
run: poetry run isort src tests --check

- name: Run flake8
run: poetry run flake8 src tests

- name: Run mypy
run: poetry run mypy --show-error-codes src

- name: Run pytest
run: poetry run pytest --cov=src --cov-report=term-missing tests

- name: Generate coverage report
shell: bash
run: poetry run coverage xml

- uses: codecov/codecov-action@v2
with:
files: ./coverage.xml

- name: Build single binary application
- name: Build distributions
run: |
poetry install --extras pyinstaller
poetry run poetry-dynamic-versioning
poetry run pyinstaller --onefile src/ops2deb/__main__.py --name ops2deb -s
dist/ops2deb version
mv dist/ops2deb ops2deb_linux_amd64
rm -rf dist/
poetry run poetry build
- name: Upload build artifact
- name: Upload build artifacts
uses: actions/upload-artifact@v2
with:
name: ops2deb_linux_amd64
path: ops2deb_linux_amd64
name: distributions
path: dist/*
retention-days: 2

publish_release:
Expand Down Expand Up @@ -118,37 +92,11 @@ jobs:
publish_pypi:
runs-on: ubuntu-18.04
needs: [test_and_build]
if: startsWith(github.ref, 'refs/tags')
steps:
- name: Checkout
uses: actions/checkout@v2

- name: Install Python
uses: actions/setup-python@v2
with:
python-version: "3.10"

- name: Load Cached Poetry
uses: actions/cache@v2
with:
path: ~/.local
key: poetry-dependencies-v2

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

- name: Get Release Version
run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV

- name: Build Distribution
run: |
poetry version "$RELEASE_VERSION"
poetry build
- name: Publish distribution 📦 to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
- name: Download build artifacts
uses: actions/download-artifact@v2
with:
password: ${{ secrets.PYPI_API_TOKEN }}
name: distributions

publish_images:
runs-on: ubuntu-latest
Expand Down
14 changes: 7 additions & 7 deletions src/ops2deb/generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,12 @@ def __init__(
self.debian_version = f"{epoch}{blueprint.version}-{blueprint.revision}~ops2deb"
self.directory_name = f"{blueprint.name}_{blueprint.version}_{blueprint.arch}"
self.package_directory = (output_directory / self.directory_name).absolute()
self.configuration_directory = configuration_directory.absolute()
self.debian_directory = self.package_directory / "debian"
self.source_directory = self.package_directory / "src"
self.fetch_directory = self.package_directory / "fetched"
self.blueprint = blueprint
self.remote_file = self.blueprint.render_fetch()
self.configuration_directory = configuration_directory

def _render_template(self, template_name: str) -> None:
template = environment.get_template(f"{template_name}")
Expand All @@ -47,7 +47,7 @@ def _init(self) -> None:
shutil.rmtree(self.fetch_directory, ignore_errors=True)
shutil.rmtree(self.source_directory, ignore_errors=True)
self.source_directory.mkdir(parents=True)
for path in ["usr/bin", "usr/share", "usr/lib"]:
for path in ["usr/bin", "usr/share", "usr/lib", "etc"]:
(self.source_directory / path).mkdir(parents=True)

def _populate_with_fetch_result(self, fetch_result: FetchResult) -> None:
Expand Down Expand Up @@ -152,11 +152,11 @@ def generate(self, fetch_results: dict[str, FetchResult]) -> None:
]:
self._render_template(template)

# if blueprint has no fetch instruction, we stay in the directory from which
# ops2deb was called, otherwise we run install and script from the fetch directory
cwd = self.fetch_directory if self.blueprint.fetch else Path(".")

with working_directory(cwd):
# if blueprint has no fetch instruction, we walk in the directory where ops2deb
# config file is, otherwise we run install and script from the fetch directory
with working_directory(
self.fetch_directory if self.blueprint.fetch else self.configuration_directory
):
# copy files / create here documents
self._install_files()
# run blueprint script
Expand Down
9 changes: 9 additions & 0 deletions tests/test_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,3 +202,12 @@ def test__install_files_should_render_cwd_and_debian_variable_in_source_destinat
blueprint = blueprint_factory(install=["{{cwd}}/test:{{debian}}/test"])
SourcePackage(blueprint, tmp_path, tmp_path)._install_files()
assert (tmp_path / "great-app_1.0.0_amd64/debian/test").is_file()


def test__init__should_use_absolute_paths(blueprint_factory, tmp_path):
blueprint = blueprint_factory()
package = SourcePackage(blueprint, tmp_path, tmp_path)
assert package.package_directory.is_absolute() is True
assert package.debian_directory.is_absolute() is True
assert package.source_directory.is_absolute() is True
assert package.configuration_directory.is_absolute() is True
53 changes: 32 additions & 21 deletions tests/test_ops2deb.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,18 +137,6 @@
"""


mock_configuration_single_blueprint_without_fetch = """\
name: cool-app
version: 1.0.0
arch: all
summary: Cool package
description: |
A detailed description of the cool package
script:
- install -m 755 cool-app.sh {{src}}/usr/bin/cool-app
"""


mock_configuration_single_blueprint_with_fetch = """\
name: great-app
version: 1.0.0
Expand Down Expand Up @@ -299,20 +287,27 @@ def test_ops2deb_generate_should_not_generate_packages_already_published_in_debi
assert result.exit_code == 0


def test_ops2deb_generate_should_run_script_from_current_directory_when_blueprint_has_not_fetch_instruction( # noqa: E501
tmp_path, tmp_working_directory, call_ops2deb
def test_ops2deb_generate_should_run_script_from_config_directory_when_blueprint_has_not_fetch_instruction( # noqa: E501
tmp_path, call_ops2deb
):
configuration_without_fetch = """\
name: cool-app
version: 1.0.0
arch: all
summary: Cool package
description: |
A detailed description of the cool package
script:
- install -m 755 cool-app.sh {{src}}/usr/bin/cool-app
"""
(tmp_path / "cool-app.sh").touch()
result = call_ops2deb(
"generate", configuration=mock_configuration_single_blueprint_without_fetch
)
result = call_ops2deb("generate", configuration=configuration_without_fetch)
assert result.exit_code == 0
assert (tmp_path / "cool-app_1.0.0_all/src/usr/bin/cool-app").is_file()


def test_ops2deb_generate_should_honor_only_argument(tmp_path, call_ops2deb):
result = call_ops2deb("generate", "--only", "great-app")
print(result.stdout)
assert list(tmp_path.glob("*_all")) == [tmp_path / "great-app_1.0.0_all"]
assert result.exit_code == 0

Expand All @@ -323,14 +318,31 @@ def test_ops2deb_generate_should_not_crash_when_archive_contains_a_dangling_syml
result = call_ops2deb(
"generate", configuration=mock_configuration_with_dangling_symlink_in_archive
)
print(result.stdout)
assert result.exit_code == 0


def test_ops2deb_generate_should_set_cwd_variable_to_config_directory_when_blueprint_has_a_fetch_and_path_to_config_is_relative( # noqa: E501
tmp_path, call_ops2deb, tmp_working_directory
):
configuration = """\
name: great-app
version: 1.0.0
summary: Great package
fetch:
url: http://testserver/{{version}}/great-app.tar.gz
sha256: f1be6dd36b503641d633765655e81cdae1ff8f7f73a2582b7468adceb5e212a9
script:
- mv great-app {{src}}/usr/bin/great-app
- cp {{cwd}}/test.conf {{src}}/etc/test.conf
"""
(tmp_path / "test.conf").touch()
result = call_ops2deb("generate", "-c", "ops2deb.yml", configuration=configuration)
assert result.exit_code == 0


def test_ops2deb_build_should_succeed_with_valid_configuration(tmp_path, call_ops2deb):
call_ops2deb("generate")
result = call_ops2deb("build")
print(result.stdout)
assert result.exit_code == 0
assert (tmp_path / "great-app_1.0.0-2~ops2deb_all.deb").is_file()

Expand All @@ -352,7 +364,6 @@ def test_ops2deb_default_should_build_and_generate_packages_when_configuration_i

def test_ops2deb_update_should_succeed_with_valid_configuration(tmp_path, call_ops2deb):
result = call_ops2deb("update")
print(result.stdout)
configuration = parse(tmp_path / "ops2deb.yml")
assert "great-app can be bumped from 1.0.0 to 1.1.1" in result.stdout
assert result.exit_code == 0
Expand Down
21 changes: 20 additions & 1 deletion tests/test_utils.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import os
from pathlib import Path

import pytest

from ops2deb.exceptions import Ops2debError
from ops2deb.utils import separate_results_from_errors
from ops2deb.utils import separate_results_from_errors, working_directory


def test_separate_results_from_errors_should_separate_results_from_ops2deb_exceptions():
Expand All @@ -18,3 +21,19 @@ def test_separate_results_from_errors_should_raise_when_exception_is_not_an_ops2
test = {0: error}
with pytest.raises(RuntimeError):
separate_results_from_errors(test)


def test_working_directory__should_set_current_working_directory_within_context(tmp_path):
origin = Path().absolute()
with working_directory(tmp_path):
assert Path(os.getcwd()) != origin
assert Path(os.getcwd()) == tmp_path


def test_working_directory__should_restore_current_directory_when_context_is_left(
tmp_path,
):
origin = Path().absolute()
with working_directory(tmp_path):
pass
assert Path(os.getcwd()) == origin

0 comments on commit 6bdacf7

Please sign in to comment.