stouputils.continuous_delivery.git module#

This module contains utilities for generating changelogs from local git repositories.

  • changelog_cli: CLI interface for generating changelogs from local git history

  • get_commits_since_tag: Get all commits since a specific tag

  • get_commits_since_date: Get all commits since a specific date

  • get_commits_since_commit: Get all commits since a specific commit

  • parse_remote_url: Parse a git remote URL to extract the base URL for commit links

Usage:

stouputils changelog [tag|date|commit] [value] [–remote <remote>] [-o <file>]

Examples

stouputils changelog # Uses latest tag (default) stouputils changelog tag v1.9.0 # All commits since tag v1.9.0 stouputils changelog date 2026/01/05 # All commits since date stouputils changelog commit 847b27e # All commits since commit stouputils changelog –remote origin # Use origin remote for commit URLs stouputils changelog -o CHANGELOG.md # Output to file

run_git_command(
args: list[str],
cwd: str | None = None,
) str[source]#

Run a git command and return the output.

Parameters:
  • args (list[str]) – Git command arguments (without ‘git’ prefix)

  • cwd (str | None) – Working directory for the command

Returns:

Command output (stdout)

Return type:

str

Raises:

RuntimeError – If the git command fails

get_local_tags(
cwd: str | None = None,
) list[tuple[str, str]][source]#

Get all tags from the local git repository, sorted by version.

Parameters:

cwd (str | None) – Working directory for the git command

Returns:

List of (tag_name, commit_sha) tuples, sorted by version (newest first)

Return type:

list[tuple[str, str]]

get_latest_tag(
cwd: str | None = None,
exclude_version: str | None = None,
) tuple[str, str] | tuple[None, None][source]#

Get the latest tag from the local git repository.

Parameters:
  • cwd (str | None) – Working directory for the git command

  • exclude_version (str | None) – Version to exclude from the search

Returns:

(tag_name, commit_sha) or (None, None) if no tags exist

Return type:

tuple[str, str] | tuple[None, None]

get_commits_since_tag(
tag: str,
cwd: str | None = None,
) list[tuple[str, str]][source]#

Get all commits since a specific tag.

Parameters:
  • tag (str) – Tag name to start from (exclusive)

  • cwd (str | None) – Working directory for the git command

Returns:

List of (sha, message) tuples

Return type:

list[tuple[str, str]]

get_commits_since_date(
date_str: str,
cwd: str | None = None,
) list[tuple[str, str]][source]#

Get all commits since a specific date.

Parameters:
  • date_str (str) – Date string (supports multiple formats via dateutil)

  • cwd (str | None) – Working directory for the git command

Returns:

List of (sha, message) tuples

Return type:

list[tuple[str, str]]

get_commits_since_commit(
commit_sha: str,
cwd: str | None = None,
) list[tuple[str, str]][source]#

Get all commits since a specific commit (exclusive).

Parameters:
  • commit_sha (str) – Commit SHA to start from (this commit is excluded)

  • cwd (str | None) – Working directory for the git command

Returns:

List of (sha, message) tuples

Return type:

list[tuple[str, str]]

parse_date_fallback(date_str: str) str[source]#

Parse a date string without dateutil, trying common formats.

Parameters:

date_str (str) – Date string to parse

Returns:

ISO 8601 formatted date string

Return type:

str

Raises:

ValueError – If the date cannot be parsed

>>> parse_date_fallback("2026/01/15")
'2026-01-15T00:00:00'
>>> parse_date_fallback("2026-01-15")
'2026-01-15T00:00:00'
>>> parse_date_fallback("2026-01-15 14:30:00")
'2026-01-15T14:30:00'
>>> parse_date_fallback("2026-01-15T14:30:00")
'2026-01-15T14:30:00'
parse_commit_log(output: str) list[tuple[str, str]][source]#

Parse git log output into a list of (sha, message) tuples.

Parameters:

output (str) – Output from git log command

Returns:

List of (sha, full_message) tuples

Return type:

list[tuple[str, str]]

get_remotes(cwd: str | None = None) dict[str, str][source]#

Get all git remotes and their URLs.

Parameters:

cwd (str | None) – Working directory for the git command

Returns:

Dictionary mapping remote names to their push URLs

Return type:

dict[str, str]

parse_remote_url(
remote_url: str,
) tuple[str, str, str] | None[source]#

Parse a git remote URL to extract hosting info.

Supports: - SSH format: git@github.com:user/repo.git - SSH format: git@gitlab.example.com:group/repo.git - HTTPS format: https://github.com/user/repo.git - HTTPS format: https://gitlab.example.com/group/repo.git

Parameters:

remote_url (str) – Git remote URL

Returns:

(host_type, base_url, repo_path) or None if cannot parse

host_type: host_type: “github”, “gitlab”, or “unknown” base_url: Base URL for the repository (e.g., “https://github.com/user/repo”) repo_path: Repository path (e.g., “user/repo”)

Return type:

tuple[str, str, str] | None

>>> parse_remote_url("git@github.com:Stoupy51/stouputils.git")
('github', 'https://github.com/Stoupy51/stouputils', 'Stoupy51/stouputils')
>>> parse_remote_url("https://github.com/Stoupy51/stouputils.git")
('github', 'https://github.com/Stoupy51/stouputils', 'Stoupy51/stouputils')
>>> parse_remote_url("git@gitlab.example.com:group/project.git")
('gitlab', 'https://gitlab.example.com/group/project', 'group/project')
>>> parse_remote_url("https://gitlab.company.com/team/repo.git")
('gitlab', 'https://gitlab.company.com/team/repo', 'team/repo')
>>> parse_remote_url("git@custom-server.com:user/repo.git")
('gitlab', 'https://custom-server.com/user/repo', 'user/repo')
>>> parse_remote_url("invalid-url") is None
True
_detect_host_type(host: str) str[source]#

Detect the type of git hosting service from hostname.

Parameters:

host (str) – Hostname (e.g., “github.com”, “gitlab.example.com”)

Returns:

“github”, “gitlab”, or “unknown”

Return type:

str

>>> _detect_host_type("github.com")
'github'
>>> _detect_host_type("gitlab.com")
'gitlab'
>>> _detect_host_type("gitlab.example.com")
'gitlab'
>>> _detect_host_type("custom-server.com")
'gitlab'
>>> _detect_host_type("my-github-mirror.org")
'github'
create_url_formatter(
remote_url: str,
) tuple[Callable[[str], str], Callable[[str, str], str]] | None[source]#

Create URL formatter functions for a git remote.

Parameters:

remote_url (str) – Git remote URL

Returns:

(commit_url_formatter, compare_url_formatter) or None

Return type:

tuple[Callable, Callable] | None

generate_local_changelog(
mode: str = 'tag',
value: str | None = None,
remote: str | None = None,
cwd: str | None = None,
) str[source]#

Generate a changelog from local git history.

Parameters:
  • mode (str) – Mode for selecting commits - “tag”, “date”, or “commit”

  • value (str | None) – Value for the mode (tag name, date, or commit SHA). If None and mode is “tag”, uses the latest tag.

  • remote (str | None) – Remote name to use for commit URLs. If None, no URLs are generated.

  • cwd (str | None) – Working directory for git commands

Returns:

Generated changelog in Markdown format

Return type:

str

changelog_cli() None[source]#

CLI interface for generating changelogs from local git history.

Usage:

stouputils changelog [tag|date|commit] [value] [–remote <remote>] [-o <file>]

Examples

stouputils changelog # Uses latest tag (default) stouputils changelog tag v1.9.0 # All commits since tag v1.9.0 stouputils changelog date 2026/01/05 # All commits since date stouputils changelog commit 847b27e # All commits since commit stouputils changelog –remote origin # Use origin remote for commit URLs stouputils changelog -o CHANGELOG.md # Output to file