Skip to content
Open
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
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
.claude
*local*
.venv
__pycache__
__pycache__
*.DS_store
82 changes: 82 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,9 @@ The scripts backing the actions live in `src/ci_cd` and are packaged as a uv pro

- **`git-clone-ref`**: clones multiple repositories (used by the `git-clone` action)
- **`get-kube`**: downloads a kubeconfig from Proton Pass
- **`get-kube-rancher`**: downloads a kubeconfig from a Rancher-managed cluster
- **`put-kube`**: uploads a kubeconfig to a Proton Pass item, replacing the existing attachment with the same filename
- **`refresh-kube`**: generates a kubeconfig from Rancher and replaces the Proton Pass attachment in one command

### get-kube

Expand All @@ -151,6 +154,85 @@ export KUBECONFIG=$PWD/local.production_eu.kubeconfig.yaml

The file is saved readable only by its owner (`0600`), since it contains cluster credentials. Running `uv run get-kube` with no arguments prints the help.

### get-kube-rancher

Downloads the kubeconfig of a cluster managed by Rancher, using the Rancher v3 API. Each environment (`dev`, `e2e`, `prod`) has defaults hardcoded in the `ENVIRONMENTS` mapping in `src/ci_cd/get_kube_rancher.py`: the Rancher URL, the cluster ID or name, and the environment variable that holds the token.

**Setup:**
- Fill in `rancher_url` and `cluster` for each environment in `ENVIRONMENTS`.
- Export the token for the environment (`RANCHER_TOKEN_DEV`, `RANCHER_TOKEN_E2E`, `RANCHER_TOKEN_PROD`), or use `RANCHER_TOKEN` as a fallback. Create it in Rancher under **Account & API Keys** and use the **Bearer Token** (`token-xxxxx:secret`).

**Options:**
- **`-e, --environment`** (required, env `CICD_ENVIRONMENT`): `dev`, `e2e` or `prod`
- **`-c, --cluster`** (optional, env `CICD_RANCHER_CLUSTER`): Cluster ID or name, overriding the environment default
- **`-u, --rancher-url`** (optional, env `CICD_RANCHER_URL`): Rancher URL, overriding the environment default
- **`-o, --output-path`** (optional, env `CICD_OUTPUT_PATH`): Where to save the kubeconfig. Defaults to `local.<cluster>.kubeconfig.yaml`.

**Example:**
~~~bash
export RANCHER_TOKEN_DEV='token-xxxxx:yyyyyyyy'
uv run get-kube-rancher -e dev
export KUBECONFIG=$PWD/local.desp-dev.kubeconfig.yaml
~~~

The file is saved readable only by its owner (`0600`). On Rancher 2.8 and later the token embedded in a generated kubeconfig expires after about 30 days, so regenerate it at the start of each pipeline run rather than storing it as a long-lived secret.

### put-kube

Uploads a local kubeconfig file to an existing Proton Pass item. The project is the vault name, and the environment is the item within that vault. The script replaces the remote attachment whose filename matches the uploaded file's basename.

**Requirements:**
- `proton` CLI installed and on `PATH`
- Logged in with `proton account login`

**Required options:**
- **`--project <TEXT>`**: Name of the project/vault containing the kubeconfig
- **`--environment <TEXT>`**: Name of the Kubernetes environment item to update
- **`--path <PATH>`**: Path to the local kubeconfig file to upload

**Example:**
~~~bash
uv run put-kube --project my-project --environment production --path ./kubeconfig.yaml
~~~

The existing attachment in the item must have the same filename as the local file, because the script uses the local file's basename to replace it. Running `uv run put-kube` without arguments displays the help. The command exits with a nonzero status if the file is missing, a Proton CLI command fails, or the project or environment cannot be found.

### refresh-kube

Admin pipeline that combines `get-kube-rancher` and `put-kube`: it generates a fresh kubeconfig from Rancher, validates it with `kubectl`, saves a local copy, and replaces the `kubeconfig.yaml` attachment of the matching Proton Pass item.

One environment maps to one cluster and one Proton Pass item:

| `--environment` | Rancher | Cluster and Proton item |
| --- | --- | --- |
| `dev` | `https://rancher.dev.desp.space` | `desp-dev` |
| `e2e` | `https://rancher.e2e3.desp.space` | `desp-e2e3` |
| `prod` | `https://rancher.prod.desp.space` | `desp-prod` |

The Rancher defaults come from `ENVIRONMENTS` in `src/ci_cd/get_kube_rancher.py`. The Proton Pass vault and attachment name are configured in `PROTON_ENVIRONMENTS` in `src/ci_cd/refresh_kube.py`; pass `--project` or set `CICD_PROJECT` until the vault is filled in there.

**Requirements:**
- `proton` CLI installed and on `PATH`, logged in with `proton account login`
- `kubectl` installed and on `PATH` unless `--no-verify` is used
- The Rancher token exported as `RANCHER_TOKEN_DEV`, `RANCHER_TOKEN_E2E` or `RANCHER_TOKEN_PROD`

**Options:**
- **`-e, --environment`** (required, env `CICD_ENVIRONMENT`): `dev`, `e2e` or `prod`
- **`-p, --project`** (optional, env `CICD_PROJECT`): Proton Pass vault containing the kubeconfig item; overrides `PROTON_ENVIRONMENTS`
- **`--attachment`** (optional, env `CICD_ATTACHMENT`): Attachment name to replace, defaults to `kubeconfig.yaml`
- **`-o, --output-path`** (optional, env `CICD_OUTPUT_PATH`): Local copy path, defaults to `local.<cluster>.kubeconfig.yaml`
- **`--dry-run`**: generate, validate and write the local copy without uploading
- **`--verify/--no-verify`**: validate the kubeconfig and confirm the uploaded attachment matches; enabled by default

**Example:**
~~~bash
export RANCHER_TOKEN_E2E='token-xxxxx:yyyyyyyy'
uv run refresh-kube -e e2e -p my-project
export KUBECONFIG=$PWD/local.desp-e2e3.kubeconfig.yaml
~~~

The command fails before uploading if the generated kubeconfig cannot reach the cluster, so a broken Rancher token does not replace a working credential. The local copy and the temporary upload file are both written with mode `0600`.

## License

```
Expand Down
3 changes: 3 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ dependencies = [
[project.scripts]
git-clone-ref = "ci_cd.git_clone_ref:app"
get-kube = "ci_cd.get_kube:app"
get-kube-rancher = "ci_cd.get_kube_rancher:app"
put-kube = "ci_cd.put_kube:app"
refresh-kube = "ci_cd.refresh_kube:app"

[build-system]
requires = ["uv_build>=0.12.7,<0.13.0"]
Expand Down
Loading
Loading