| title | redeploy — systemowe zarządzanie wersjami (version manifest) | ||||||||
|---|---|---|---|---|---|---|---|---|---|
| slug | redeploy-version-management-plan | ||||||||
| date | 2026-04-20 | ||||||||
| status | draft | ||||||||
| project | redeploy | ||||||||
| type | refactoring-plan | ||||||||
| part | 3 | ||||||||
| tags |
|
Część III planu refaktoryzacji redeploy. Poprzednie: część I (internal), część II (IaC parsers). Ta część adresuje trzecią oś: zarządzanie wersjami jako spójny podsystem, nie jako zbiór skryptów per-repo.
Uwaga: w aktualnym drzewie repo istnieje już pierwszy wariant tego subsystemu (
redeploy.version). Ten dokument porządkuje docelowy model, brakujące elementy i pełny scope, zamiast opisywać greenfield od zera.
Problem: redeploy weryfikuje wersje na deploy, ale nie uczestniczy w ich deklarowaniu i propagowaniu. Każde repo wymyśla własny bump-version.py (c2004: 13 plików, redeploy: 2 pliki, kolejne repo: kolejny skrypt).
Systemowa odpowiedź: .redeploy/version.yaml — deklaratywny manifest opisujący gdzie żyje wersja, a nie jak ją zbumpować. redeploy dostaje komendy version current/bump/set/verify/diff, które:
- czytają manifest,
- atomowo aktualizują wszystkie źródła wersji (plain, TOML, JSON, YAML, patterns w kodzie),
- integrują się z git tags i CHANGELOG,
- zamykają pętlę z istniejącym
version_checkna deploy.
Ten sam mechanizm obsługuje single-repo (redeploy: 2 źródła) i monorepo (c2004: 13 źródeł) — różni się tylko manifest.
Skala: 6–8 tygodni, bez nowych wymaganych dependencji dla core (tomllib/tomli i PyYAML już są).
| Obszar | Status | Notatka |
|---|---|---|
| Manifest loader/save | partial |
.redeploy/version.yaml działa, ale obecny model używa pola version, nie current; schema z packages: pozostaje docelowa |
| Source adapters | partial |
Zaimportowane są plain, toml, json, yaml, regex; brak dockerfile, a zapis YAML/TOML jest nadal heurystyczny |
| Transakcja plikowa | partial |
Jest prepare/commit/rollback, ale „atomowość" kończy się na rename per plik, nie na pełnym rollbacku po częściowym commit() |
| Git integration | partial |
require_clean, commit/tag/push/sign istnieją; brak automatycznego rollbacku po nieudanym kroku git |
| Conventional commits | done |
Parser, analiza bump type i raport są zaimplementowane oraz pokryte testami |
| Changelog | partial |
Jest ChangelogManager i flaga --changelog w version bump, ale brak osobnej komendy version changelog |
| CLI version | partial |
Działają current, list, verify, bump, init; brak set, diff, zakresu monorepo i domknięcia deploy loop |
| Deploy loop closure | todo |
Brak @manifest, preflightu w redeploy run, detect --with-version, version diff --live/--spec/--image |
| Monorepo policy | todo |
Brak packages: w modelu, --package, --all-packages i constraints |
Dwa warianty, które zwykle padają:
redeploy/scripts/bump-version.py (uproszczona kopia z c2004)
Czemu to nie działa:
- Każde nowe repo wymaga kopii + dostosowania listy plików
- Rozjazd między repo: redeploy bump używa innej logiki niż c2004 bump → przy zmianie konwencji trzeba edytować N skryptów
- Brak standaryzacji: jedni używają
poetry version, drudzybump2version, trzeci własnego skryptu - Skrypt żyje w repo, ale logika dotyczy całej organizacji — zła lokalizacja własności
Czemu to nie działa:
- Rozłączność:
redeploynie wie, jaką wersję deployuje, dopóki nie spojrzy wmigration.yaml(który user musiał ręcznie zaktualizować) - Classic failure mode: bump kodu v1.0.21, ale w
migration.yamlwciążtarget.version: 1.0.20→ deploy starej wersji, alarm fałszywy - Redeploy ma narzędzia do weryfikacji (
version_check, probe live version), ale nie może wykryć tego błędu przed deployem
Problem nie jest „brakuje skryptu". Problem to: redeploy ma połowę cyklu wersji (weryfikacja), brakuje mu drugiej połowy (deklaracja i propagacja). Bez tej drugiej połowy weryfikacja jest reakcyjna („deploy się wysypał na version_check") zamiast prewencyjnej („nie pozwolę ci zacommitować rozjazdu").
Zanim zaproponujemy konkretne API, cztery zasady które odrzucają większość „skryptowych" rozwiązań:
Gdzie żyje wersja i w jakim formacie to dane, nie kod. Manifest opisuje sources; logika bumpowania jest generyczna.
Bump N plików to jedna transakcja. Jeśli zapis do pliku 7/13 się wywali, pliki 1–6 wracają do stanu sprzed. Implementacja: staging w tempfiles + atomic rename, albo commit-based rollback przez git.
Wersja zadeklarowana w manifest → wersja w migration.yaml → wersja build image → wersja runtime na hoście. redeploy zna wszystkie cztery i może wykryć drift na każdym kroku.
Ten sam kod obsługuje VERSION (plain), pyproject.toml (TOML), package.json (JSON), __init__.py (regex), Chart.yaml (YAML), docker-compose.yml (YAML z image tag pattern). Nowe formaty to nowy source adapter, nie nowa komenda.
Status 2026-04-20: partial. Obecny kod umie już czytać i zapisywać manifest, ale nie implementuje jeszcze dokładnie schematu z tej sekcji. W praktyce VersionManifest oczekuje dziś pola version jako stringa oraz listy sources na tym samym poziomie; pola current: i blok packages: są nadal target state.
# .redeploy/version.yaml
# Systemowa deklaracja gdzie żyje wersja projektu
version:
current: "1.0.20"
scheme: semver # semver | calver | integer | custom
policy: synced # synced | independent (dla monorepo)
# Źródła wersji — gdzie jest zapisana
sources:
- path: VERSION
format: plain
- path: pyproject.toml
format: toml
key: project.version
- path: package.json
format: json
key: version
- path: src/backend/__init__.py
format: regex
pattern: '__version__\s*=\s*"([^"]+)"'
- path: helm/Chart.yaml
format: yaml
key: appVersion
- path: docker-compose.yml
format: yaml
key: services.backend.image
value_pattern: '.*:v?(.+)'
write_pattern: 'ghcr.io/org/app:v{version}'
- path: README.md
format: regex
pattern: 'Version\]\(https://img\.shields\.io/badge/version-([^-]+)-'
optional: true
# Git integration
git:
tag_format: "v{version}"
tag_message: "Release {version}"
commit_message: "chore(release): {version}"
sign_tag: true
require_clean: true
# Changelog (opcjonalnie)
changelog:
path: CHANGELOG.md
format: keepachangelog
unreleased_header: "## [Unreleased]"
# Conventional commits → bump type
commits:
analyze: true
convention: conventional
rules:
breaking: major
feat: minor
fix: patch
perf: patch
refactor: patch
docs: none
chore: none
test: none
# Release channels (opcjonalnie)
channels:
stable:
pattern: '^\d+\.\d+\.\d+$'
rc:
pattern: '^\d+\.\d+\.\d+-rc\.\d+$'
dev:
pattern: '^\d+\.\d+\.\d+-dev\.[a-f0-9]{7,}$'Dla c2004 (13 plików, ale jeden produkt — policy synced):
version:
current: "1.0.20"
policy: synced
sources:
- path: VERSION
- path: pyproject.toml
key: project.version
# ...11 pozostałychDla monorepo z niezależnymi paczkami:
# .redeploy/version.yaml (monorepo root)
packages:
backend:
current: "2.3.1"
sources:
- path: packages/backend/pyproject.toml
key: project.version
- path: packages/backend/src/__init__.py
format: regex
pattern: '__version__\s*=\s*"([^"]+)"'
frontend:
current: "4.1.0"
sources:
- path: packages/frontend/package.json
key: version
firmware:
current: "0.9.5"
sources:
- path: firmware/src/version.h
format: regex
pattern: '#define\s+FW_VERSION\s+"([^"]+)"'
# Cross-package rules
constraints:
- "backend >= 2.0 requires frontend >= 4.0"Komendy z --package backend targetują konkretny pakiet, bez flagi — wszystkie synced.
redeploy/
├── version/ # NEW module
│ ├── __init__.py # Public API
│ ├── manifest.py # VersionManifest pydantic model
│ ├── sources/ # Source adapters
│ │ ├── base.py # SourceAdapter protocol
│ │ ├── plain.py # VERSION file
│ │ ├── toml_.py # pyproject.toml
│ │ ├── json_.py # package.json
│ │ ├── yaml_.py # Chart.yaml, compose
│ │ ├── regex.py # pattern-based (Python, C, etc.)
│ │ └── dockerfile.py # LABEL version=...
│ ├── scheme/ # Version scheme adapters
│ │ ├── base.py # VersionScheme protocol
│ │ ├── semver.py # default
│ │ ├── calver.py # YYYY.MM.DD
│ │ └── integer.py # monotonic int
│ ├── transaction.py # Atomic multi-source update
│ ├── git_integration.py # Tag, commit, require_clean
│ ├── changelog.py # keepachangelog generator
│ ├── commits.py # Conventional commits analyzer
│ └── bump.py # Public bump operations
Status 2026-04-20:
done:manifest.py,transaction.py,git_integration.py,git_transaction.py,bump.py,commits.py,changelog.py, oraz adapteryplain,toml_,json_,yaml_,regexpartial:sources/base.pyistnieje jako wspólna baza, ale nie jako formalnyProtocol; zapisy TOML/YAML nadal bazują głównie na regex replacement, nie na pełnym round-trip serializertodo:sources/dockerfile.py, katalogscheme/, jawny model monorepopackages:
# redeploy/version/sources/base.py
class SourceAdapter(Protocol):
"""Adapter dla jednego typu pliku."""
format_name: str # "toml", "json", "yaml", "plain", "regex"
def read(self, path: Path, config: SourceConfig) -> str:
"""Odczyt aktualnej wersji z pliku."""
def write(self, path: Path, config: SourceConfig, new_version: str) -> None:
"""Zapis nowej wersji — atomowy, nie uszkadza pozostałego contentu."""
def stage(self, path: Path, config: SourceConfig, new_version: str) -> Path:
"""Zapisuje do temp file, zwraca ścieżkę. Używane przez transaction."""Kluczowe: adaptery nie piszą do docelowych plików w trakcie stage(). Najpierw wszystkie 13 źródeł idzie do tempfiles. Dopiero gdy wszystkie przeszły walidację, następuje atomic rename w pętli. Jeśli cokolwiek fails — tempfiles się kasuje, docelowe pliki nietknięte.
# redeploy/version/transaction.py
class VersionBumpTransaction:
def __init__(self, manifest: VersionManifest, new_version: str):
self.manifest = manifest
self.new_version = new_version
self.staged: list[tuple[Path, Path]] = [] # (temp, final)
def prepare(self) -> list[StagingResult]:
"""Stage wszystkie zmiany w tempfiles. Nie tyka docelowych."""
results = []
for source in self.manifest.sources:
adapter = get_adapter(source.format)
try:
temp = adapter.stage(source.path, source, self.new_version)
self.staged.append((temp, source.path))
results.append(StagingResult(source, ok=True))
except Exception as e:
results.append(StagingResult(source, ok=False, error=e))
return results
def commit(self) -> None:
"""Atomic rename — jeśli cokolwiek przeszło prepare(), commit powinien nie failować."""
for temp, final in self.staged:
os.replace(temp, final) # atomic na POSIX
def rollback(self) -> None:
"""Usuń tempfiles, docelowe pliki nietknięte."""
for temp, _ in self.staged:
temp.unlink(missing_ok=True)Wzorzec prepare/commit/rollback jest istotny — daje semantykę dwufazowego commitu bez potrzeby transakcji plikowych na poziomie systemu.
# Odczyt
redeploy version # partial: dziś głównie group/help, nie skrót do current
redeploy version current # done
redeploy version verify # done: sources only, bez git checks
redeploy version list # done
# Zapis
redeploy version bump patch # done
redeploy version bump minor # done
redeploy version bump major # done
redeploy version bump prerelease # done
redeploy version bump --analyze # done
redeploy version set 1.2.3 # todo
# Dry-run wszędzie
redeploy version bump patch --dry-run # done
# Git integration flags
redeploy version bump patch --tag --commit --push # done
redeploy version bump patch --no-tag # todo: brak jawnego negującego flag alias
redeploy version bump patch --sign # done
# Changelog
redeploy version bump patch --changelog # partial: działa tylko jako flaga bump
redeploy version changelog --unreleased # todo
redeploy version changelog --prepare # todo
# Drift detection
redeploy version diff # todo
redeploy version diff --live root@vps.example.com # todo
redeploy version diff --spec migration.yaml # todo
redeploy version diff --image ghcr.io/org/app:latest # todo
# Monorepo
redeploy version bump patch --package backend # todo
redeploy version current --package frontend # todo
redeploy version list --all-packages # todo
# Init
redeploy version init # done
redeploy version init --scan # partial: dziś wykrywa tylko VERSION / pyproject.toml / package.jsonStatus 2026-04-20: partial. Najważniejsze read/bump flows już działają, ale surface opisany powyżej jest nadal szerszy niż obecne CLI.
Kluczowy argument dla systemowego podejścia: redeploy już ma version_check. Manifest zamyka pętlę.
Jeśli .redeploy/version.yaml istnieje w cwd, redeploy run dodaje implicit kroki:
1. Read manifest → declared_version
2. Read migration.yaml → target.version
3. IF declared != target → FAIL "Version drift: manifest says 1.0.21, spec says 1.0.20"
4. IF git HEAD != tag for declared_version → WARN "HEAD not tagged for 1.0.21"
5. Standard detect → plan → apply
6. After apply: probe live version, compare to declared_version
7. IF mismatch → rollback
Ten flow wcześniej wyłapuje „zapomniałem bumpnąć migration.yaml" niż to robi obecny version_check (który sprawdza dopiero po deployu).
Zamiast hardkodowanego version:, można odwołać się do manifest:
target:
host: root@vps.example.com
version: "@manifest"
verify_version: "@manifest"Albo explicit dla pinowanych deploy'ów:
target:
version: "1.0.20"
version_check_against: manifestProbe wersji na live host porównany z manifest:
redeploy detect --host root@vps.example.com --app c2004 --with-version
# Output:
# Host: root@vps.example.com
# App: c2004
# Runtime: docker
# Services: c2004-backend, c2004-frontend
# Version comparison:
# Manifest (local): 1.0.21
# Running (live): 1.0.20 ⚠ drift
# Image tag registry: 1.0.21
# → Deploy pending (manifest > running)Status 2026-04-20: partial. Integracja git jest już realna w CLI, ale nie domyka jeszcze pełnej transakcji opisanej niżej.
Większość „bump scriptów" traktuje git jako afterthought. W naszym planie tag + commit + changelog to integralna część transakcji.
1. prepare() — stage wszystkie version sources (tempfiles)
2. prepare_changelog() — stage CHANGELOG.md z nową sekcją
3. require_clean() — git status porcelain, fail if dirty
4. commit_files() — os.replace wszystkie tempfiles
5. git_add() — add wszystkie touched files
6. git_commit() — commit z manifest.git.commit_message.format(version=new)
7. git_tag() — create annotated (signed jeśli manifest.git.sign_tag)
8. IF error na krokach 4–7 → rollback last successful step
Opcjonalny krok 9 (if --push):
9. git push --follow-tags
Różnica vs obecny kod: dziś require_clean, commit, tag i push działają, ale rollback po kroku git jest manualny. Dodatkowo --changelog zapisuje CHANGELOG.md przed głównym bump transaction, więc changelog nie jest jeszcze częścią tej samej dwufazowej transakcji.
manifest.git.require_clean: true → bump odmawia jeśli git status --porcelain niepuste. Chroni przed:
- zacommitowaniem przypadkowych zmian w ramach bump
- bumpem na niestabilnym kodzie
- race condition z innymi zmianami
Flaga --allow-dirty dla świadomego obejścia (np. staged conflicts).
Dla manifest.changelog.format: keepachangelog:
# Changelog
## [Unreleased]
### Added
- Parser for docker-compose files (#142)
### Fixed
- k3s iptables flush race condition (#156)
## [1.0.20] — 2026-04-15
...Po redeploy version bump patch:
# Changelog
## [Unreleased]
## [1.0.21] — 2026-04-20
### Added
- Parser for docker-compose files (#142)
### Fixed
- k3s iptables flush race condition (#156)
## [1.0.20] — 2026-04-15
...Opcjonalnie --auto-sections wyciąga sekcje z conventional commits od ostatniego tagu.
Status 2026-04-20: done dla parsera i analizy bump type, partial dla pełnego UX release, bo brak osobnej komendy version changelog i jeszcze nie ma połączenia z version diff / deploy preflight.
redeploy version bump --analyze czyta commity od ostatniego tagu:
# redeploy/version/commits.py
def analyze(since_tag: str, manifest: VersionManifest) -> BumpAnalysis:
commits = git.log(f"{since_tag}..HEAD", format="%H %s%n%b")
bumps = []
for c in commits:
parsed = parse_conventional(c.message)
if parsed.breaking or "BREAKING CHANGE" in c.body:
bumps.append("major")
elif parsed.type in manifest.commits.rules:
bumps.append(manifest.commits.rules[parsed.type])
# Highest wins
if "major" in bumps: return BumpAnalysis("major", ...)
if "minor" in bumps: return BumpAnalysis("minor", ...)
if "patch" in bumps: return BumpAnalysis("patch", ...)
return BumpAnalysis(None, reason="no bump-worthy commits")Output:
$ redeploy version bump --analyze --dry-run
Analysis: 14 commits since v1.0.20
→ 2× feat (minor)
→ 7× fix (patch)
→ 1× feat! (breaking → major)
→ 4× chore (ignored)
Proposed bump: major
Next version: 2.0.0
Files to update:
VERSION 1.0.20 → 2.0.0
pyproject.toml 1.0.20 → 2.0.0
packages/backend/__init__.py 1.0.20 → 2.0.0
...13 files total
Run without --dry-run to apply.Obecny stan c2004: bump-version.py updateuje 13 plików. Po migracji na manifest:
# c2004/.redeploy/version.yaml
version:
current: "1.0.20"
scheme: semver
policy: synced
sources:
- path: VERSION
format: plain
- path: pyproject.toml
format: toml
key: project.version
- path: packages/backend/pyproject.toml
format: toml
key: project.version
- path: packages/frontend/package.json
format: json
key: version
- path: packages/frontend/src/version.ts
format: regex
pattern: 'export const VERSION = "([^"]+)"'
- path: firmware/include/version.h
format: regex
pattern: '#define\s+FW_VERSION\s+"([^"]+)"'
- path: docker-compose.vps.yml
format: yaml
key: services.backend.image
value_pattern: '.*:v?(.+)'
write_pattern: 'ghcr.io/softreck/c2004-backend:v{version}'
- path: helm/Chart.yaml
format: yaml
key: version
- path: helm/Chart.yaml
format: yaml
key: appVersion
# ... pozostałe 4
git:
tag_format: "v{version}"
require_clean: true
changelog:
path: CHANGELOG.md
format: keepachangelogIstniejący scripts/bump-version.py i .github/workflows/release.yml znikają. Komendy:
# Zamiast: python scripts/bump-version.py patch
redeploy version bump patch
# Zamiast: custom GHA workflow
# Wystarczy:
# - run: redeploy version bump --analyze
# - run: git push --follow-tagsZysk: identyczna komenda w redeploy (2 source) i c2004 (13 sources). Nowe repo dziedziczy mechanizm za darmo, tylko pisze .redeploy/version.yaml.
| Narzędzie | Co robi | Czego brakuje vs nasz plan |
|---|---|---|
bump2version / bumpversion |
Multi-file version update przez regex | Brak integracji z deploy, brak atomowej transakcji, brak monorepo policy |
poetry version |
TOML-only | Single-file, brak multi-source |
npm version |
package.json + git tag | JS-only, brak multi-source |
semantic-release |
Conventional commits → auto release | Wymaga node, dużo plugins, brak integracji z live host verification |
release-please (Google) |
PR-based release automation | GitHub-specific, złożony, brak loop z deployem |
changesets |
Manual changelog entries | Manual, brak auto-bump |
git-version-bump |
Git-based versioning | Brak multi-file, brak changelogu |
Helm appVersion vs version |
Rozdzielenie chart/app version | Helm-specific |
Terraform required_version |
Version constraints | Nie bumpuje, tylko enforce |
Kluczowa różnica naszego planu: żaden z powyższych nie zamyka pętli z live deployment verification. redeploy to zrobi, bo już ma version_check i probe. Manifest domyka brakującą połowę cyklu.
- Conventional commits parser —
conventional-commits-parser(node) lubcommitizen(python) jako wzorzec - keepachangelog format — ustandaryzowany, łatwy do generowania
- Keep sync policy z changesets — prosty model dla monorepo
- Nie wymagamy CI runnera — wszystko działa z CLI lokalnie, CI to opcja
- Nie generujemy kodu — manifest opisuje gdzie jest wersja, nie jak ją stworzyć
- Integrujemy z deploy — bump nie jest celem sam w sobie, jest częścią łańcucha release → deploy → verify
Komenda skanuje projekt i proponuje manifest:
$ cd c2004
$ redeploy version init --scan
Skanowanie projektu...
Znalezione potencjalne version sources:
[✓] VERSION (plain) current: 1.0.20
[✓] pyproject.toml (toml, project.version) current: 1.0.20
[✓] packages/backend/pyproject.toml current: 1.0.20
[✓] packages/frontend/package.json current: 1.0.20
[✓] packages/frontend/src/version.ts current: 1.0.20 (regex match)
[✓] firmware/include/version.h current: 1.0.20 (regex match)
[?] docker-compose.vps.yml image tag: v1.0.20 (niepewne)
[?] README.md badge version: 1.0.20
[!] legacy/VERSION.txt current: 0.9.5 (rozjazd!)
Czy zapisać do .redeploy/version.yaml? [Y/n]Użytkownik akceptuje, edytuje [?] (dodaje/usuwa), rozstrzyga [!] (conflict).
Status 2026-04-20: partial. W obecnym kodzie init --scan robi tylko prostą heurystykę dla VERSION, pyproject.toml i package.json; nie ma jeszcze interaktywnego potwierdzania, regex scan ani wykrywania driftu.
$ redeploy version verify
Manifest current: 1.0.20
Source check:
VERSION 1.0.20 ✓
pyproject.toml 1.0.20 ✓
packages/backend/pyproject.toml 1.0.20 ✓
...
All sources in sync: ✓
Git check:
HEAD tagged as v1.0.20: ✓
Working directory clean: ✓Status 2026-04-20: partial. Dzisiejsze redeploy version verify sprawdza spójność sources, ale nie wypisuje jeszcze sekcji Git check.
$ rm scripts/bump-version.py
$ rm .github/workflows/release.yml # jeśli zastępowany$ redeploy version bump patch --analyzeStatus 2026-04-20: partial.
VersionManifestpydantic model + walidacjaSourceAdapterprotocol- Adapters:
plain,toml - CLI:
version current,version list,version verify - Testy na redeploy własnym (2 źródła)
Status 2026-04-20: partial.
json,yaml,regex,dockerfile- Edge cases: YAML value_pattern + write_pattern (docker-compose image tags)
- Testy na sample projektach
Status 2026-04-20: partial.
VersionBumpTransactionz prepare/commit/rollback- CLI:
version bump patch|minor|major,version set X.Y.Z - Semver scheme
- Dry-run mode
- Testy na c2004 (13 źródeł)
Status 2026-04-20: partial.
require_clean,--tag,--commit,--push,--sign- Staging git changes jako część transakcji
- Error handling gdy git operations fail mid-transaction
Status 2026-04-20: partial.
- Commit parser
--analyzeflag- Changelog generator (keepachangelog)
version changelog --prepare
Status 2026-04-20: todo.
target.version: "@manifest"w migration.yaml- Preflight check w
redeploy run redeploy detect --with-versionredeploy version diff --live/--spec/--image
Status 2026-04-20: todo.
packages:struktura w manifest--packageflag- Policy
syncedvsindependent - Cross-package constraints (basic)
Status 2026-04-20: partial.
version init --scanheurystyka- Import z bumpversion / poetry config
- Dokumentacja migration per format
Suma: ok. 10 tygodni dla pełnego scope. MVP (fazy 0–3) w 5.5 tygodnia.
| Ryzyko | Prawdopodobieństwo | Mitygacja |
|---|---|---|
| YAML source adapter psuje formatting (komentarze, quoting) | Wysokie | ruamel.yaml z round-trip zamiast PyYAML dla zapisu |
| Regex adapter fails silently | Średnie | Hard-fail przy optional: false, testy negatywne |
| Transakcja atomowa nie jest atomic przez NFS / sieciowe FS | Niskie | Dokumentacja: wymagane lokalne FS z os.replace |
--analyze ma false positives (np. commit z "fix" w tytule ale nie fix) |
Średnie | Tylko header commita, nie body; flagi --force-type |
| Git sign tag wymaga interaktywnego prompt (GPG) | Średnie | Obsługa GPG_TTY, dokumentacja |
| Istniejące projekty mają niestandardowe bump scripts | Wysokie | init --scan + --import-from bumpversion.cfg |
Podwójny update YAML (Chart.yaml ma version + appVersion) |
Średnie | Manifest pozwala na wiele entry na ten sam plik |
- Default scheme: semver hard-coded jako default, czy explicit required?
- Location manifest:
.redeploy/version.yamlczyredeploy.yamltop-level keyversion:? - Relacja do części II (parsers): czy parser docker-compose automatycznie emituje source entry dla image tag?
- Fallback dla projektów bez manifest: best-effort detection jak obecny
probe_version, czy require manifest? - Breaking changes detection:
!po typie (feat!) tylko, czy teżBREAKING CHANGE:footer?
Rekomendacja autora: semver default, .redeploy/version.yaml (pozwala gitignore per użytkownika jeśli lokalne), parser z cz. II sugeruje source entry ale nie auto-dodaje, fallback best-effort z WARN, oba sposoby breaking.
Po zakończeniu faz 0–5 (MVP + git + commits + deploy loop):
redeploy version bump patchdziała identycznie na redeploy (2 sources) i c2004 (13 sources)redeploy version verifywyłapuje rozjazdy między sourcesredeploy runw repo z manifest odmawia deployu przy rozjeździespec.version ↔ manifest.currentredeploy version diff --livepokazuje drift między declared a running- Changelog auto-generowany z conventional commits
- Zero nowych wymaganych dependencji (PyYAML, tomllib stdlib już są)
- Istniejące
scripts/bump-version.pyw c2004 można usunąć bez utraty funkcjonalności
Świadomie odkładamy:
- Dependency version management (jak NPM lock, Cargo.lock) — to inny problem
- Version constraint resolution między paczkami — zaawansowany monorepo scope, po v1.0
- Release automation na PyPI/npm — tylko tag + commit, publikacja zostaje w user's pipeline
- Backward compat z bumpversion / semantic-release configs —
init --import-fromtylko best-effort - Semver range parsing (
>=1.0,<2.0) — tylko wconstraints:, nie w daily bump flow - Web UI / dashboard — CLI only
- Signing commits (nie tylko tags) — tylko tags w v1
| Ta część | Część I (internal) | Część II (parsers) |
|---|---|---|
| Manifest schema | Fleet model (faza 2) — osobne rzeczy, ale podobny wzorzec pydantic | |
@manifest w migration.yaml |
Public API (faza 1) — manifest musi być w public API | |
Source adapter yaml + dockerfile |
Część II ma parsery dla tych formatów — współdzielenie kodu | |
| Deploy preflight | Patterns (faza 4 cz. I) — preflight to nowy „pattern" | |
| Live version probe | probe_health (istniejące) — rozszerzenie o probe_version |
Kluczowe: źródła (sources) z tej części i parsery z części II mogą współdzielić YAML / TOML / JSON readers. Warto najpierw zaprojektować wspólną warstwę redeploy/formats/ zanim obie części ruszą.
- Walidacja planu — przegląd z kontrybutorami, 1 tydzień
- Decyzja lokacji manifest —
.redeploy/version.yamlvs top-level key - Spike Faza 0 — implementacja dla redeploy-self (2 sources, trivial) jako proof
- Koordynacja z cz. II — wspólna warstwa
formats/ - Milestone w GitHub — per faza, z trackingiem MVP (0–3) i full (0–7)
Plany powiązane:
- Część I: redeploy — plan refaktoryzacji (internal)
- Część II: redeploy — plan integracji z IaC/CI-CD (parsery)
- doql: doql — plan refaktoryzacji (poza bieżącym workspace)