File: conftest.py

package info (click to toggle)
python-semantic-release 10.4.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 3,828 kB
  • sloc: python: 41,692; sh: 340; makefile: 158
file content (158 lines) | stat: -rw-r--r-- 4,997 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
from __future__ import annotations

from pathlib import Path
from typing import TYPE_CHECKING

import pytest
from git import Repo

from semantic_release.hvcs.github import Github

from tests.const import MAIN_PROG_NAME, VERSION_SUBCMD
from tests.util import assert_successful_exit_code

if TYPE_CHECKING:
    from typing import Protocol, Sequence

    from click.testing import Result

    from tests.conftest import RunCliFn
    from tests.fixtures.example_project import UpdatePyprojectTomlFn
    from tests.fixtures.git_repo import (
        BuildRepoFromDefinitionFn,
        RepoActionConfigure,
        RepoActionConfigureMonorepo,
        RepoActionCreateMonorepo,
    )

    class InitMirrorRepo4RebuildFn(Protocol):
        def __call__(
            self,
            mirror_repo_dir: Path,
            configuration_steps: Sequence[
                RepoActionConfigure
                | RepoActionCreateMonorepo
                | RepoActionConfigureMonorepo
            ],
            files_to_remove: Sequence[Path],
        ) -> Path: ...

    class RunPSReleaseFn(Protocol):
        def __call__(
            self,
            next_version_str: str,
            git_repo: Repo,
            config_toml_path: Path = ...,
        ) -> Result: ...


@pytest.fixture(scope="session")
def init_mirror_repo_for_rebuild(
    build_repo_from_definition: BuildRepoFromDefinitionFn,
) -> InitMirrorRepo4RebuildFn:
    def _init_mirror_repo_for_rebuild(
        mirror_repo_dir: Path,
        configuration_steps: Sequence[
            RepoActionConfigure | RepoActionCreateMonorepo | RepoActionConfigureMonorepo
        ],
        files_to_remove: Sequence[Path],
    ) -> Path:
        # Create the mirror repo directory
        mirror_repo_dir.mkdir(exist_ok=True, parents=True)

        # Initialize mirror repository
        build_repo_from_definition(
            dest_dir=mirror_repo_dir,
            repo_construction_steps=configuration_steps,
        )

        with Repo(mirror_repo_dir) as mirror_git_repo:
            for filepath in files_to_remove:
                file = (
                    (mirror_git_repo.working_dir / filepath).resolve().absolute()
                    if not filepath.is_absolute()
                    else filepath
                )
                if (
                    Path(mirror_git_repo.working_dir) not in file.parents
                    or not file.exists()
                ):
                    continue

                mirror_git_repo.git.rm(str(file), force=True)

        return mirror_repo_dir

    return _init_mirror_repo_for_rebuild


@pytest.fixture(scope="session")
def run_psr_release(
    run_cli: RunCliFn,
    changelog_rst_file: Path,
    update_pyproject_toml: UpdatePyprojectTomlFn,
    pyproject_toml_file: Path,
) -> RunPSReleaseFn:
    base_version_cmd = [MAIN_PROG_NAME, "--strict", VERSION_SUBCMD]
    write_changelog_only_cmd = [
        *base_version_cmd,
        "--changelog",
        "--no-commit",
        "--no-tag",
        "--skip-build",
    ]

    def _run_psr_release(
        next_version_str: str,
        git_repo: Repo,
        config_toml_path: Path = pyproject_toml_file,
    ) -> Result:
        version_n_buildmeta = next_version_str.split("+", maxsplit=1)
        version_n_prerelease = version_n_buildmeta[0].split("-", maxsplit=1)

        build_metadata_args = (
            ["--build-metadata", version_n_buildmeta[-1]]
            if len(version_n_buildmeta) > 1
            else []
        )

        prerelease_args = (
            [
                "--as-prerelease",
                "--prerelease-token",
                version_n_prerelease[-1].split(".", maxsplit=1)[0],
            ]
            if len(version_n_prerelease) > 1
            else []
        )

        # Initial run to write the RST changelog
        # 1. configure PSR to write the RST changelog with the RST default insertion flag
        update_pyproject_toml(
            "tool.semantic_release.changelog.default_templates.changelog_file",
            str(changelog_rst_file),
            toml_file=config_toml_path,
        )
        cli_cmd = [*write_changelog_only_cmd, *prerelease_args, *build_metadata_args]
        result = run_cli(cli_cmd[1:], env={Github.DEFAULT_ENV_TOKEN_NAME: "1234"})
        assert_successful_exit_code(result, cli_cmd)

        # Reset the index in case PSR added anything to the index
        git_repo.git.reset("--mixed", "HEAD")

        # Add the changelog file to the git index but reset the working directory
        git_repo.git.add(str(changelog_rst_file.resolve()))
        git_repo.git.checkout("--", ".")

        # Actual run to release & write the MD changelog
        cli_cmd = [
            *base_version_cmd,
            *prerelease_args,
            *build_metadata_args,
        ]
        result = run_cli(cli_cmd[1:], env={Github.DEFAULT_ENV_TOKEN_NAME: "1234"})
        assert_successful_exit_code(result, cli_cmd)

        return result

    return _run_psr_release