Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 9 additions & 21 deletions .github/workflows/aur.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
name: Publish AUR

on:
push:
branches:
- main
workflow_run:
workflows:
- Sync Version
types:
- completed
workflow_dispatch:

concurrency:
Expand All @@ -12,6 +14,7 @@ concurrency:

jobs:
aur:
if: github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success'
runs-on: ubuntu-latest
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
Expand All @@ -20,29 +23,14 @@ jobs:
- name: Checkout
uses: actions/checkout@v5
with:
ref: ${{ github.event_name == 'workflow_dispatch' && github.ref || github.event.workflow_run.head_branch }}
fetch-depth: 0

- name: Determine version from app config
id: version
run: |
# Usando Python para extrair a versão de forma robusta
PKGVER=$(python3 -c "
import re
import os

target = 'src/zashterminal/settings/config.py'
if not os.path.exists(target):
import sys; sys.exit(f'Erro: Arquivo {target} nao encontrado na raiz')

with open(target, 'r', encoding='utf-8') as f:
content = f.read()
# Regex simplificada que aceita aspas simples ou duplas
match = re.search(r'APP_VERSION\\s*=\\s*[\\\"\\']([^\\\"\\']+)[\\\"\\']', content)
if match:
print(match.group(1))
else:
import sys; sys.exit('Erro: Variavel APP_VERSION nao encontrada dentro do arquivo')
")
python3 scripts/sync_version.py --check
PKGVER=$(python3 scripts/sync_version.py --print-current)
echo "pkgver=$PKGVER" >> $GITHUB_OUTPUT

- name: Update PKGBUILD pkgver
Expand Down
64 changes: 64 additions & 0 deletions .github/workflows/version-bump.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
name: Sync Version

on:
push:
branches:
- main
workflow_dispatch:
inputs:
bump:
description: "Semantic bump type"
required: false
default: "patch"
type: choice
options:
- patch
- minor
- major
version:
description: "Explicit version override (optional, e.g. 0.8.2)"
required: false
type: string

permissions:
contents: write

jobs:
sync-version:
if: github.actor != 'github-actions[bot]'
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v5

- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: "3.x"

- name: Bump and sync version files
id: sync
run: |
if [ "${{ github.event_name }}" = "workflow_dispatch" ] && [ -n "${{ github.event.inputs.version }}" ]; then
OUTPUT=$(python3 scripts/sync_version.py --set "${{ github.event.inputs.version }}")
elif [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
OUTPUT=$(python3 scripts/sync_version.py --bump "${{ github.event.inputs.bump || 'patch' }}")
else
OUTPUT=$(python3 scripts/sync_version.py --bump patch)
fi
printf '%s\n' "$OUTPUT"
NEW_VERSION=$(printf '%s\n' "$OUTPUT" | head -n 1)
echo "version=$NEW_VERSION" >> "$GITHUB_OUTPUT"

- name: Commit changes
run: |
if git diff --quiet; then
echo "No version changes to commit."
exit 0
fi
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add src/zashterminal/settings/config.py locale/src/zashterminal/settings/config.py pyproject.toml locale/pyproject.toml default.nix locale/default.nix PKGBUILD scripts/sync_version.py
git commit -m "Bump version to ${{ steps.sync.outputs.version }}"
git push
25 changes: 25 additions & 0 deletions .github/workflows/version-consistency.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
name: Version Consistency

on:
push:
branches:
- main
pull_request:
workflow_dispatch:

jobs:
check-version:
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v5

- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: "3.x"

- name: Verify version alignment
run: |
python3 scripts/sync_version.py --check
2 changes: 1 addition & 1 deletion PKGBUILD
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
pkgname=zashterminal
# NOTE: CI updates this value automatically based on
# locale/src/zashterminal/settings/config.py (APP_VERSION).
pkgver=0.0.0
pkgver=0.8.1
pkgrel=1
pkgdesc="A modern GTK4/Adwaita terminal emulator with advanced session management, SSH integration, and security features."
arch=('any')
Expand Down
2 changes: 1 addition & 1 deletion default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

python3Packages.buildPythonApplication {
pname = "zashterminal";
version = "0.1.0";
version = "0.8.1";

src = ./.;

Expand Down
2 changes: 1 addition & 1 deletion locale/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

python3Packages.buildPythonApplication {
pname = "zashterminal";
version = "0.1.0";
version = "0.8.1";

src = ./.;

Expand Down
2 changes: 1 addition & 1 deletion locale/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ classifiers = [
"Programming Language :: Python :: 3",
"Topic :: Terminals :: Terminal Emulators/X Terminals",
]
version = "0.1.0"
version = "0.8.1"
authors = [
{ name = "Leonardo Berbert", email = "leo4berbert@gmail.com" },
]
Expand Down
2 changes: 1 addition & 1 deletion locale/src/zashterminal/settings/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class AppConstants:

APP_ID = "org.leoberbert.zashterminal"
APP_TITLE = "Zashterminal"
APP_VERSION = "0.8.0"
APP_VERSION = "0.8.1"
DEVELOPER_NAME = "Leonardo Berbert"
DEVELOPER_TEAM = ["Leonardo Berbert"]
COPYRIGHT = "© 2025 Leonardo Berbert"
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ classifiers = [
"Programming Language :: Python :: 3",
"Topic :: Terminals :: Terminal Emulators/X Terminals",
]
version = "0.1.0"
version = "0.8.1"
authors = [
{ name = "Leonardo Berbert", email = "leo4berbert@gmail.com" },
]
Expand Down
173 changes: 173 additions & 0 deletions scripts/sync_version.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
#!/usr/bin/env python3

from __future__ import annotations

import argparse
import re
import sys
from pathlib import Path


ROOT = Path(__file__).resolve().parents[1]

TARGETS = (
(
"src/zashterminal/settings/config.py",
r'(APP_VERSION\s*=\s*")([^"]+)(")',
"group3",
),
(
"locale/src/zashterminal/settings/config.py",
r'(APP_VERSION\s*=\s*")([^"]+)(")',
"group3",
),
("pyproject.toml", r'^(version\s*=\s*")([^"]+)(")\s*$', "group3"),
("locale/pyproject.toml", r'^(version\s*=\s*")([^"]+)(")\s*$', "group3"),
("default.nix", r'^( version\s*=\s*")([^"]+)(";\s*)$', "group3"),
("locale/default.nix", r'^( version\s*=\s*")([^"]+)(";\s*)$', "group3"),
("PKGBUILD", r"^(pkgver=)([^\n]+)$", "group2"),
)


def read_current_version() -> str:
config_path = ROOT / "src/zashterminal/settings/config.py"
content = config_path.read_text(encoding="utf-8")
match = re.search(r'APP_VERSION\s*=\s*"([^"]+)"', content)
if not match:
raise SystemExit(f"Unable to find APP_VERSION in {config_path}")
return match.group(1)


def bump_version(version: str, part: str) -> str:
match = re.fullmatch(r"(\d+)\.(\d+)\.(\d+)", version.strip())
if not match:
raise SystemExit(
f"Current version '{version}' is not semver-like (expected X.Y.Z)"
)

major, minor, patch = (int(piece) for piece in match.groups())
if part == "major":
return f"{major + 1}.0.0"
if part == "minor":
return f"{major}.{minor + 1}.0"
if part == "patch":
return f"{major}.{minor}.{patch + 1}"
raise SystemExit(f"Unsupported bump type: {part}")


def _replace_match(match: re.Match[str], new_version: str, mode: str) -> str:
if mode == "group2":
return f"{match.group(1)}{new_version}"
return f"{match.group(1)}{new_version}{match.group(3)}"


def replace_once(path: Path, pattern: str, new_version: str, mode: str) -> bool:
text = path.read_text(encoding="utf-8")
compiled = re.compile(pattern, re.MULTILINE)
updated, count = compiled.subn(
lambda match: _replace_match(match, new_version, mode), text, count=1
)
if count != 1:
raise SystemExit(f"Unable to update version in {path}")

if updated != text:
path.write_text(updated, encoding="utf-8")
return True
return False


def sync_all(new_version: str) -> list[str]:
changed: list[str] = []
for rel_path, pattern, mode in TARGETS:
path = ROOT / rel_path
if not path.exists():
continue
if replace_once(path, pattern, new_version, mode):
changed.append(rel_path)
return changed


def collect_mismatches(expected_version: str) -> list[str]:
mismatches: list[str] = []
for rel_path, pattern, _mode in TARGETS:
path = ROOT / rel_path
if not path.exists():
continue

text = path.read_text(encoding="utf-8")
match = re.search(pattern, text, re.MULTILINE)
if not match:
mismatches.append(f"{rel_path}: version marker not found")
continue

current_value = match.group(2)
if current_value != expected_version:
mismatches.append(f"{rel_path}: {current_value} != {expected_version}")

return mismatches


def build_parser() -> argparse.ArgumentParser:
parser = argparse.ArgumentParser(
description="Synchronize Zashterminal version across project files."
)
group = parser.add_mutually_exclusive_group()
group.add_argument("--set", dest="set_version", help="Set an explicit version.")
group.add_argument(
"--bump",
choices=("major", "minor", "patch"),
help="Increment the current semantic version.",
)
parser.add_argument(
"--print-current",
action="store_true",
help="Print the current APP_VERSION from config.py.",
)
parser.add_argument(
"--check",
action="store_true",
help="Fail if any tracked file is not aligned with APP_VERSION.",
)
return parser


def main() -> int:
parser = build_parser()
args = parser.parse_args()

current_version = read_current_version()

if args.check and not args.set_version and not args.bump:
mismatches = collect_mismatches(current_version)
if mismatches:
print(f"Version mismatch detected against APP_VERSION={current_version}:")
for item in mismatches:
print(item)
return 1
print(f"All tracked files are aligned with APP_VERSION={current_version}")
return 0

if args.print_current and not args.set_version and not args.bump:
print(current_version)
return 0

if args.set_version:
new_version = args.set_version.strip()
elif args.bump:
new_version = bump_version(current_version, args.bump)
else:
parser.error("Provide --print-current, --check, --set, or --bump.")

changed = sync_all(new_version)
print(new_version)
if changed:
print("Updated files:")
for rel_path in changed:
print(rel_path)
else:
print("No files changed.")
return 0


if __name__ == "__main__":
sys.exit(main())