{"id":51701731,"url":"https://github.com/wireapp/wire-upgrade-tool","last_synced_at":"2026-07-16T11:35:53.747Z","repository":{"id":341862264,"uuid":"1170799752","full_name":"wireapp/wire-upgrade-tool","owner":"wireapp","description":null,"archived":false,"fork":false,"pushed_at":"2026-04-29T13:25:01.000Z","size":247,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-07-16T11:35:50.643Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/wireapp.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-02T14:35:10.000Z","updated_at":"2026-05-12T21:42:19.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/wireapp/wire-upgrade-tool","commit_stats":null,"previous_names":["wireapp/wire-upgrade-tool"],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/wireapp/wire-upgrade-tool","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wireapp%2Fwire-upgrade-tool","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wireapp%2Fwire-upgrade-tool/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wireapp%2Fwire-upgrade-tool/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wireapp%2Fwire-upgrade-tool/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wireapp","download_url":"https://codeload.github.com/wireapp/wire-upgrade-tool/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wireapp%2Fwire-upgrade-tool/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35542951,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-16T02:00:06.687Z","response_time":83,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-07-16T11:35:49.760Z","updated_at":"2026-07-16T11:35:53.738Z","avatar_url":"https://github.com/wireapp.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Wire Upgrade CLI\n\nCommand-line tool for performing Wire Server upgrade actions on **Kubespray-based\non-premises deployments**. It wraps helm/kubectl calls and helper scripts\npackaged with the Wire Server bundle.\n\n## Scope\n\nThis tool is designed for Wire Server deployments that:\n\n- Are running on-premises on bare-metal or VMs managed by **Kubespray**\n- Were originally deployed using a bundle built from the\n  [wire-server-deploy](https://github.com/wireapp/wire-server-deploy) repository\n- Have an existing running system with the old `wire-server-deploy` bundle\n  present on the admin host\n\n### Prerequisites\n\nComplete these steps **in order** before running any upgrade commands:\n\n1. An existing Wire Server deployment must be running (the **old bundle** at\n   e.g. `/home/demo/wire-server-deploy`)\n2. The **new bundle** (built from `wire-server-deploy`) must be copied to the\n   admin host (e.g. `/home/demo/new`)\n3. `wire-upgrade` must be installed on the admin host (see [Installation](#installation))\n4. Create `upgrade-config.json` pointing to both bundles:\n   ```sh\n   wire-upgrade init-config --new-bundle /home/demo/new --old-bundle /home/demo/wire-server-deploy\n   ```\n5. **Run `wire-upgrade setup-kubeconfig`** — this is mandatory before any other\n   command. It copies `admin.conf` from the old bundle into the new bundle and\n   patches `bin/offline-env.sh` so that `helm` and `kubectl` (run inside the\n   bundle's Docker container) can reach the cluster. Without this step all\n   Helm and Ansible commands will fail.\n\n---\n\n## Installation\n\n### From GitHub Releases (recommended)\n\nInstall the latest release directly on the admin host:\n\n```sh\npip install https://github.com/wireapp/wire-upgrade-tool/releases/download/v0.1.6/wire_upgrade-0.1.6-py3-none-any.whl\n```\n\nIf `wire-upgrade` is not found after install, pip placed the script in\n`~/.local/bin` which is not on `PATH`. Add it permanently:\n\n```sh\necho 'export PATH=\"$HOME/.local/bin:$PATH\"' \u003e\u003e ~/.bashrc \u0026\u0026 source ~/.bashrc\n```\n\n### Updating\n\nRe-run the same install command with `--upgrade`:\n\n```sh\npip install --upgrade https://github.com/wireapp/wire-upgrade-tool/releases/download/v0.1.6/wire_upgrade-0.1.6-py3-none-any.whl\n```\n\n### On an admin host without internet access\n\nDownload the wheel on a machine with internet access, copy it to the admin\nhost, then install:\n\n```sh\n# machine with internet access\ncurl -LO https://github.com/wireapp/wire-upgrade-tool/releases/download/v0.1.6/wire_upgrade-0.1.6-py3-none-any.whl\nscp wire_upgrade-0.1.1-py3-none-any.whl \u003cadmin-host\u003e:/tmp/\n\n# on the admin host\npip install --force-reinstall /tmp/wire_upgrade-0.1.1-py3-none-any.whl\n```\n\n### From source (development)\n\n```sh\ncd /path/to/wire-upgrade-tool\npython3 -m build\npip install --force-reinstall dist/wire_upgrade-*.whl\n```\n\nThe wheel bundles all Python modules and declares the runtime dependencies\n(`typer`, `rich`, `pydantic`, `PyYAML`), so nothing else is required.\n\n---\n\n## Configuration\n\nThe CLI reads options from a JSON config file named `upgrade-config.json`.\n`wire-upgrade init-config` will create a template:\n\n```json\n{\n  \"new_bundle\": \"/home/demo/new\",\n  \"old_bundle\": \"/home/demo/wire-server-deploy\",\n  \"kubeconfig\": null,\n  \"log_dir\": \"/var/log/upgrade-orchestrator\",\n  \"tools_dir\": null,\n  \"admin_host\": \"localhost\",\n  \"dry_run\": false,\n  \"snapshot_name\": null\n}\n```\n\nAny field may be overridden on the command line. `kubeconfig` is optional after\nrunning `setup-kubeconfig` — the tool auto-detects it from\n`new_bundle/ansible/inventory/offline/artifacts/admin.conf` (where\n`setup-kubeconfig` places it), falling back to a search in the old bundle root.\nIf set explicitly it must point to an existing file; there is no fallback to\n`~/.kube/config`. `tools_dir` defaults to the installed package directory.\n\nCommand-line flags take precedence over the config file.\n\n---\n\n## Commands\n\nAll commands support `-n/--namespace` when they talk to a namespaced resource;\nthe default is `default`.\n\n### init-config\nGenerate a new `upgrade-config.json` template:\n\n```sh\nwire-upgrade init-config --kubeconfig /path/to/kubeconfig \\\n    --new-bundle /home/demo/new --old-bundle /home/demo/old\n```\n\n### status\nDisplay cluster node/pod status and all Helm release information.\n\n```sh\nwire-upgrade status\nwire-upgrade status -n prod\n```\n\n### pre-check\nRun pre-upgrade sanity checks: cluster connectivity, inventory diff, Cassandra\nreachability, and MinIO connectivity.\n\n### sync\nRuns `sync-binaries` followed by `sync-images` in one step. Syncs all binaries\nand all container images with no filtering.\n\n```sh\nwire-upgrade sync\nwire-upgrade sync --dry-run\n```\n\n### sync-binaries\nExtracts binaries from bundle tar archives and rsyncs them to `/opt/assets` on\nthe assethost. After a successful sync, `serve-assets` is restarted so new\nfiles are served immediately. `/opt/assets` must already exist on the assethost.\n\n```sh\n# Sync all binaries from all tar archives (default)\nwire-upgrade sync-binaries\n\n# Sync only a specific group\nwire-upgrade sync-binaries --group postgresql\n\n# Sync multiple groups\nwire-upgrade sync-binaries --group postgresql --group cassandra\n\n# Restrict to a specific tar archive (skips scanning other tars)\nwire-upgrade sync-binaries --group postgresql --tar binaries\n\n# Preview what would be synced without transferring\nwire-upgrade sync-binaries --group postgresql --dry-run --verbose\n\n# Show per-file progress\nwire-upgrade sync-binaries --verbose\n```\n\n**`--tar` values:** `binaries`, `debs`, `containers-system`, `containers-helm`\n\n**`--group` values:**\n\n| Group | File prefixes |\n|---|---|\n| `postgresql` | `postgresql-*`, `repmgr*`, `libpq*`, `python3-psycopg2*`, `postgres_exporter*` |\n| `cassandra` | `apache-cassandra*`, `jmx_prometheus_javaagent*` |\n| `elasticsearch` | `elasticsearch*` |\n| `minio` | `minio.RELEASE.*`, `mc.RELEASE.*` |\n| `kubernetes` | `kubeadm`, `kubectl`, `kubelet`, `etcd*`, `crictl*`, `calicoctl*` |\n| `containerd` | `containerd*`, `cni-plugins*`, `nerdctl*`, `runc*` |\n| `helm` | `v3.*` |\n\nTars with no matching files are silently skipped — only processed archives\nappear in the output and audit log.\n\n### sync-images\nLoads container images into containerd on cluster nodes via Ansible.\n\n```sh\nwire-upgrade sync-images\nwire-upgrade sync-images --dry-run\n```\n\n### sync-chart-images\nSyncs only the images required by a specific Helm chart directly from the\nbundle tars to each k8s node's containerd (no assethost involved). Uses\n`helm template` to determine which images the chart needs, then streams\nmatching entries from `containers-helm.tar` (or `containers-system.tar`)\nvia SSH to each node.\n\n```sh\n# Sync wire-server images (default)\nwire-upgrade sync-chart-images\n\n# Sync a specific chart\nwire-upgrade sync-chart-images cassandra-external -n prod\n\n# Preview without loading\nwire-upgrade sync-chart-images --dry-run\n\n# Show ctr output per node\nwire-upgrade sync-chart-images --verbose\n\n# Search additional tar archive\nwire-upgrade sync-chart-images --tar containers-helm --tar containers-system\n\n# Resume after partial failure — skips images already present on each node\nwire-upgrade sync-chart-images wire-server --skip-existing\n\n# Retry a single image\nwire-upgrade sync-chart-images wire-server --image quay.io/wire/nginz:5.27.0\n\n# Retry multiple images\nwire-upgrade sync-chart-images wire-server \\\n    --image quay.io/wire/nginz:5.27.0 \\\n    --image quay.io/wire/brig:5.27.0\n```\n\n### backup\nCassandra snapshot management.\n\n```sh\nwire-upgrade backup                                   # create snapshot\nwire-upgrade backup --list-snapshots\nwire-upgrade backup --restore --snapshot-name \u003cname\u003e\nwire-upgrade backup --archive-snapshots --snapshot-name \u003cname\u003e\n```\n\nSee `wire-upgrade backup --help` for the full option list.\n\n### migrate\nRun Cassandra schema migrations and/or the migrate-features chart. At least one\nflag must be provided:\n\n```sh\nwire-upgrade migrate --cassandra-migrations -n prod\nwire-upgrade migrate --migrate-features -n prod\nwire-upgrade migrate --cassandra-migrations --migrate-features -n prod\n```\n\n`--cassandra-migrations` deploys the `cassandra-migrations` chart and polls\nuntil the migration job completes. `--migrate-features` deploys the\n`migrate-features` chart. Both support `--dry-run`.\n\n### check-schema\nCompare live Cassandra schema metadata against the expected versions from the\nbundle's chart:\n\n```sh\nwire-upgrade check-schema\nwire-upgrade check-schema -n prod\n```\n\n### sync-values\nFetch live helm values from the cluster and merge them into the bundle templates,\nwriting `values.yaml` / `secrets.yaml` in `values/{chart-name}/`.\n\n```sh\n# Sync wire-server (default)\nwire-upgrade sync-values\n\n# Sync a specific chart and release\nwire-upgrade sync-values wire-server -n prod\nwire-upgrade sync-values postgresql-external --release my-postgres -n prod\n```\n\nThe merge strategy keeps live cluster values as the source of truth — template\ndefaults only fill in keys that are absent from the cluster (e.g. new config\nfields introduced in the new Wire version). For `wire-server` it also syncs the\nPostgreSQL password from the `wire-postgresql-external-secret` k8s secret.\n\nAfter running, check the generated files then deploy:\n\n```sh\nwire-upgrade sync-values wire-server\nwire-upgrade install-or-upgrade wire-server\n```\n\n### validate-values\nValidate custom values files against a Helm chart without deploying. Runs four\nchecks and shows results for each:\n\n1. **Sub-chart dependencies** — `helm dependency list` (informational)\n2. **Template rendering** — `helm template` with your values applied; fails if\n   the chart cannot be rendered (e.g. missing required values, type errors)\n3. **Values diff** — shows what will change vs the currently deployed release\n4. **Chart defaults audit** — shows which chart default values are not covered\n   by your custom values files\n\n```sh\n# Validate wire-server (default)\nwire-upgrade validate-values\n\n# Validate a specific chart and release\nwire-upgrade validate-values postgresql-external --release my-postgres -n prod\n\n# Validate with explicit values files\nwire-upgrade validate-values wire-server \\\n    --values /home/demo/new/values/wire-server/values.yaml \\\n    --values /home/demo/new/values/wire-server/secrets.yaml\n```\n\nReturns exit code 0 if template rendering passes, 1 if it fails.\n\n### install-or-upgrade\nDeploy or upgrade a Helm chart. Automatically validates template rendering\nbefore deploying — if `helm template` fails the deployment is aborted.\n\n```sh\n# wire-server (default when no chart is given)\nwire-upgrade install-or-upgrade\nwire-upgrade install-or-upgrade wire-server -n prod\n\n# Custom chart — looks for chart at charts/{name} and values at values/{name}/\nwire-upgrade install-or-upgrade wire-utility\nwire-upgrade install-or-upgrade wire-utility --release my-release\n\n# Override chart path or values files explicitly\nwire-upgrade install-or-upgrade wire-utility --chart charts/wire-utility \\\n    --values /home/demo/new/values/wire-server/values.yaml \\\n    --values /home/demo/new/values/wire-server/secrets.yaml\n\n# Reuse existing release values (skips values file lookup, skips pre-validation)\nwire-upgrade install-or-upgrade wire-server --reuse-values\n\n# Dry-run (shows diff + helm --dry-run output, no actual deployment)\nwire-upgrade install-or-upgrade wire-server --dry-run\n\n# Skip helm template pre-validation (escape hatch)\nwire-upgrade install-or-upgrade wire-server --skip-validate\n```\n\n**Values auto-discovery:** for each chart, the tool looks for values files under\n`values/{chart-name}/` in the bundle (preferring `values.yaml` / `secrets.yaml`\nover `prod-values.example.yaml` / `prod-secrets.example.yaml`). Pass `--values`\nexplicitly to override.\n\n**Pre-flight validation:** before every deployment, `helm template` is run with\nthe same values files to catch rendering errors. Use `--skip-validate` to bypass\nthis check if needed. Pre-validation is also skipped when `--reuse-values` is\nset (no values files to validate against).\n\n### cleanup-containerd / cleanup-containerd-all\nRemove unused container images from containerd on one or all nodes.\n\n```sh\nwire-upgrade cleanup-containerd --dry-run          # preview (default)\nwire-upgrade cleanup-containerd --apply            # actually remove\nwire-upgrade cleanup-containerd --apply --sudo     # needed if containerd socket requires root\nwire-upgrade cleanup-containerd-all                # run --apply across all kube nodes\n```\n\n### inventory-sync / inventory-validate\nGenerate and validate the Ansible inventory for the new bundle.\n\n```sh\nwire-upgrade inventory-sync      # copy and adapt hosts.ini from old bundle\nwire-upgrade inventory-validate  # check required groups and variables\n```\n\n### setup-kubeconfig\nCopy `admin.conf` from the old bundle (created by kubespray) into the new\nbundle and update `bin/offline-env.sh` to pass `KUBECONFIG` into the docker\ncontainer. Must be run once after a new bundle is placed on the admin host.\n\n```sh\nwire-upgrade setup-kubeconfig\n```\n\nThis copies `ansible/inventory/offline/artifacts/admin.conf` from the old\nbundle to the same path in the new bundle, backs up the existing\n`bin/offline-env.sh`, and writes a new one that sets\n`-e KUBECONFIG=/$MOUNT_POINT/ansible/inventory/offline/artifacts/admin.conf`\ninside the `d()` docker function.\n\nAfter running this, `kubeconfig` is auto-detected from the new bundle — no\nneed to set it explicitly in `upgrade-config.json`.\n\n### assets-compare\nCompare asset indices between the bundle and a remote assethost.\n\n---\n\n## System Design\n\n### Full Upgrade Sequence\n\nThe recommended order of operations for a Wire Server upgrade:\n\n```mermaid\nflowchart TD\n    A([start]) --\u003e B[\"pre-check\u003cbr/\u003evalidate bundles, cluster, inventory,\u003cbr/\u003eCassandra, MinIO\"]\n    B --\u003e C[\"backup\u003cbr/\u003ecreate Cassandra snapshot\"]\n    C --\u003e D[\"sync-binaries\u003cbr/\u003ecopy binaries to nodes\"]\n    D --\u003e E[\"sync-images\u003cbr/\u003eload container images into containerd\"]\n    E --\u003e F[\"migrate --cassandra-migrations\u003cbr/\u003erun schema migrations\"]\n    F --\u003e G[\"check-schema\u003cbr/\u003everify schema versions\"]\n    G --\u003e H[\"migrate --migrate-features\u003cbr/\u003erun feature flag migrations\"]\n    H --\u003e I[\"sync-values wire-server\u003cbr/\u003efetch cluster values → bundle templates\"]\n    I --\u003e I2[\"install-or-upgrade wire-server\u003cbr/\u003evalidates + deploys\"]\n    I2 --\u003e J[\"cleanup-containerd\u003cbr/\u003eremove old images from nodes\"]\n    J --\u003e K([done])\n```\n\n---\n\n### Chart Upgrade Flow\n\nThe recommended four-step sequence to upgrade any single chart (e.g.\n`wire-server`, `account-pages`, `postgresql-external`):\n\n```\nsync-values  →  validate-values  →  sync-chart-images  →  install-or-upgrade\n```\n\n**Step 1 — sync-values**: fetch the live values from the running Helm release\nand merge them into the new bundle's template files. This produces\n`values/{chart}/values.yaml` and `values/{chart}/secrets.yaml` with your\ncluster's current config, extended with any new keys introduced in the new\nchart version.\n\n```sh\nwire-upgrade sync-values wire-server -n prod\n```\n\n**Step 2 — validate-values**: render the chart with the merged values and\ncompare against the currently deployed release. Catches rendering errors and\nshows exactly what will change before anything is deployed.\n\n```sh\nwire-upgrade validate-values wire-server -n prod\n```\n\nFix any issues in `values/{chart}/values.yaml` or `secrets.yaml` before\ncontinuing.\n\n**Step 3 — sync-chart-images**: load the images required by the new chart\nversion into containerd on every k8s node. Uses `helm template` to determine\nwhich images the chart needs, then streams matching entries from the bundle tar\ndirectly to each node via SSH.\n\n```sh\nwire-upgrade sync-chart-images wire-server\n# Resume after a partial failure (skips images already present):\nwire-upgrade sync-chart-images wire-server --skip-existing\n# Retry a single image:\nwire-upgrade sync-chart-images wire-server --image quay.io/wire/nginz:5.27.0\n```\n\n**Step 4 — install-or-upgrade**: deploy the chart. Runs `helm template`\npre-flight validation, shows a diff of what is changing, then executes\n`helm upgrade --install` with `--timeout 15m --wait`.\n\n```sh\nwire-upgrade install-or-upgrade wire-server -n prod\n```\n\n```mermaid\nflowchart TD\n    A([start]) --\u003e B[\"sync-values\\nfetch cluster values → merge into\\nbundle templates\"]\n    B --\u003e C[\"validate-values\\nhelm template + diff + defaults audit\"]\n    C --\u003e D{renders OK?}\n    D --\u003e|no — fix values| C\n    D --\u003e|yes| E[\"sync-chart-images\\nstream images from bundle tar\\nto each k8s node via SSH\"]\n    E --\u003e F[\"install-or-upgrade\\nhelm upgrade --install\\n--timeout 15m --wait\"]\n    F --\u003e G{deployed?}\n    G --\u003e|yes| H([done])\n    G --\u003e|no| I([check pod status / rollback])\n```\n\n---\n\n### sync-values Flow\n\n```mermaid\nflowchart TD\n    A[sync-values chart] --\u003e B[helm get values\\nfrom cluster release]\n    B --\u003e C[deep merge into\\nbundle templates]\n    C --\u003e D{chart == wire-server?}\n    D --\u003e|yes| E[kubectl get secret\\nwire-postgresql-external-secret]\n    E --\u003e F[set pgPassword in secrets.yaml\\nfor services with config.postgresql]\n    F --\u003e G([done — run install-or-upgrade to deploy])\n    D --\u003e|no| G\n```\n\n---\n\n### install-or-upgrade Flow\n\n```mermaid\nflowchart TD\n    A[install-or-upgrade chart] --\u003e B[auto-discover values files\\nvalues/chart-name/]\n    B --\u003e C{--skip-validate?}\n    C --\u003e|no| D[helm template\\npre-flight validation]\n    D --\u003e E{valid?}\n    E --\u003e|no| ERR([error — fix values])\n    E --\u003e|yes| F[show diff\\ncurrent cluster vs new values]\n    C --\u003e|yes| F\n    F --\u003e G[helm upgrade --install\\n--timeout 15m --wait]\n    G --\u003e H{success?}\n    H --\u003e|yes| I[kubectl get pods\\ncheck pod status]\n    I --\u003e J([done])\n    H --\u003e|no| K([error])\n```\n\n---\n\n### Values Sync Detail (sync-values)\n\n```mermaid\nflowchart LR\n    A[helm get values\\nrelease -n namespace] --\u003e B[parse YAML]\n    B --\u003e C[extract_values_for_template\\nfilter to values.yaml keys]\n    C --\u003e D[_fill_from_template\\ncluster is base —\\ntemplate adds missing keys only]\n    D --\u003e E[write values.yaml]\n    B --\u003e C2[extract_values_for_template\\nfilter to secrets.yaml keys]\n    C2 --\u003e D2[_fill_from_template\\ncluster is base —\\ntemplate adds missing keys only]\n    D2 --\u003e E2[write secrets.yaml]\n    E --\u003e F[write timestamped\\nbackup files]\n    E2 --\u003e F\n\n    G[kubectl get secret\\npg-external-secret] --\u003e H[base64 decode]\n    H --\u003e I[find services with\\nconfig.postgresql\\nin values.yaml]\n    I --\u003e J[set pgPassword\\nin secrets.yaml]\n```\n\n---\n\n### Component Architecture\n\n```mermaid\nflowchart TD\n    CLI[commands.py\\nTyper CLI] --\u003e ORC[orchestrator.py\\nUpgradeOrchestrator]\n\n    ORC --\u003e CI[chart_install.py\\ninstall_or_upgrade\\nfind_values_files\\nshow_values_diff]\n    ORC --\u003e VV[values_validate.py\\nvalidate_chart_values]\n    ORC --\u003e VS[values_sync.py\\nsync_chart_values\\nset_pg_password\\nfind_services_with_postgresql]\n    ORC --\u003e CB[cassandra_backup.py\\nsnapshot / restore]\n    ORC --\u003e CCL[cleanup_containerd_images.py\\nimage pruning]\n    ORC --\u003e INV[inventory_sync.py\\nhosts.ini management]\n    ORC --\u003e WSL[wire_sync_lib.py\\nbuild_offline_cmd\\nbuild_exec_argv]\n\n    CI --\u003e|helm upgrade --install| K8S[(Kubernetes\\nCluster)]\n    VS --\u003e|helm get values\\nkubectl get secret| K8S\n    ORC --\u003e|kubectl| K8S\n    WSL --\u003e|sources offline-env.sh\\nsets KUBECONFIG| K8S\n```\n\n---\n\n## How it works\n\nBefore running any upgrade command, the new Wire Server release bundle must be\ncopied to the admin host (e.g. `hetzner3`) and its path set as `new_bundle` in\n`upgrade-config.json`. The bundle is a directory that contains the Helm charts,\nAnsible playbooks, container images, and the `bin/offline-env.sh` script that\nconfigures the offline environment. Every command sources that script before\ninvoking `helm`, `kubectl`, or `ansible-playbook`, so the bundle must be present\nand intact on the host before the tool is used.\n\n`UpgradeOrchestrator` encapsulates configuration and provides one method per\ncommand. Kubernetes and Helm calls go through `run_kubectl()`, which sources\n`offline-env.sh` from the new bundle and optionally sets `KUBECONFIG` before\ninvoking the command. All subprocesses return `(rc, stdout, stderr)` tuples.\n\nChart installation logic lives in `wire_upgrade/chart_install.py`. Values\nsync logic lives in `wire_upgrade/values_sync.py`. The CLI command registration\nis in `wire_upgrade/commands.py`.\n\n---\n\n## Testing\n\n```sh\npython3 -m pytest tests/ -v\n```\n\nTests are in `tests/test_values_sync.py` and cover the values merge logic in\n`wire_upgrade/values_sync.py`:\n\n- **Unit tests** — `_fill_from_template`, `deep_merge`, `extract_values_for_template`\n- **Integration tests** — full `sync_chart_values` flow using fixture files in\n  `tests/VALUES/`\n\nThe fixture files committed to the repo use clearly-fake placeholder values\n(`AKIAIOSFODNN7EXAMPLE`, `cluster-brig-pg-password`, etc.). Production fixture\nfiles containing real cluster data are listed in `.gitignore` and kept locally.\n\n---\n\n## Development\n\n1. Create a venv: `python3 -m venv .venv \u0026\u0026 source .venv/bin/activate`\n2. Build: `python3 -m build`\n3. Install: `pip install --force-reinstall dist/wire_upgrade-*.whl`\n4. Deploy to test host: `scp dist/*.whl user@host:/tmp/ \u0026\u0026 ssh user@host pip install --force-reinstall /tmp/*.whl`\n\nRun `wire-upgrade COMMAND --help` for detailed option lists.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwireapp%2Fwire-upgrade-tool","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwireapp%2Fwire-upgrade-tool","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwireapp%2Fwire-upgrade-tool/lists"}