fix(git): fix 17 missing async/await bugs + UX overhaul

Backend:
- fix 17 missing 'await' in git route handlers causing silent no-ops
  (branches, diff, history, commit, push, pull, merge, promote, sync)
- fix async coroutine passed to run_blocking in git_plugin.py

Frontend:
- add collapsible 'How it works' onboarding (GitHelpPanel)
- add status legend with color-coded repository statuses
- i18n: add 50+ missing keys, replace hardcoded strings
- add Refresh button in modal header
- add PROD deploy confirmation dialog (replaces browser prompt())
- add CommitHistory to workspace tab with timeline nodes
- add post-commit success banner with next-step guidance
- increase success toast duration to 8s
- group local/remote branches in selector (optgroup)
- format last_modified dates timezone-aware
- change PROD badge from red to neutral indigo
- extract shared resolveGitStatusToken to git-utils.ts
- fix 'slug' label regression
- remove dead init_repo_button key

UI/UX audit fixes:
- add descriptions to Create/Init buttons in init panel
- add actionable CTA to server mismatch warning
- improve checkbox text phrasing
This commit is contained in:
2026-07-01 20:47:25 +03:00
parent 78d2664e2e
commit 87ac90bb8d
44 changed files with 1201 additions and 262 deletions

View File

@@ -121,13 +121,14 @@ class TestEncryptEnvPasswords:
# #endregion test_encrypt_skips_masked_and_empty
# #region test_encrypt_skips_already_encrypted [C:2] [TYPE Function]
# @BRIEF Password that decrypts successfully is already encrypted → skip.
# @BRIEF Password that looks like a Fernet token (via is_fernet_token) is skipped.
def test_encrypt_skips_already_encrypted(self):
mgr = _build_manager(MagicMock())
em = MagicMock()
em.decrypt.return_value = "plaintext"
mgr._encryption = em
payload = {"environments": [{"password": "already-encrypted-token"}]}
# 96-char base64 string that passes is_fernet_token() (decodes to 72 zero bytes)
fernet_like = "A" * 96
payload = {"environments": [{"password": fernet_like}]}
mgr._encrypt_env_passwords(payload)
em.encrypt.assert_not_called()
# #endregion test_encrypt_skips_already_encrypted
@@ -184,13 +185,15 @@ class TestDecryptEnvPasswords:
# #endregion test_decrypt_empty_password
# #region test_decrypt_success [C:2] [TYPE Function]
# @BRIEF Encrypted password is decrypted in-place.
# @BRIEF Fernet-format password is decrypted in-place.
def test_decrypt_success(self):
mgr = _build_manager(MagicMock())
em = MagicMock()
em.decrypt.return_value = "decrypted"
mgr._encryption = em
config = _make_config([_make_env(password="encrypted-token")])
# 96-char base64 string that passes is_fernet_token() (decodes to 72 zero bytes)
fernet_like = "A" * 96
config = _make_config([_make_env(password=fernet_like)])
mgr._decrypt_env_passwords(config)
assert config.environments[0].password == "decrypted"
# #endregion test_decrypt_success