|
| 1 | +# Contributing to Komet Node |
| 2 | + |
| 3 | +## Development environment |
| 4 | + |
| 5 | +This repository ships a [devcontainer](.devcontainer/) that provisions the full |
| 6 | +toolchain (Nix, the flake's `nix develop` shell, the Claude Code CLI, and the |
| 7 | +GitHub CLI). Open the repo in a devcontainer-aware editor and everything below is |
| 8 | +available out of the box. |
| 9 | + |
| 10 | +## Using the GitHub CLI (`gh`) |
| 11 | + |
| 12 | +`gh` is preinstalled in the devcontainer for creating pull requests, reviewing |
| 13 | +issues, and other GitHub tasks from the terminal. |
| 14 | + |
| 15 | +### Authenticating |
| 16 | + |
| 17 | +Authenticate once with a personal access token: |
| 18 | + |
| 19 | +```bash |
| 20 | +gh auth login |
| 21 | +``` |
| 22 | + |
| 23 | +Choose **GitHub.com** → **HTTPS** → **Paste an authentication token** when |
| 24 | +prompted, then paste the token you create below. |
| 25 | + |
| 26 | +Your credentials are stored in `~/.config/gh` inside the container, which is |
| 27 | +backed by a named volume. This means **your token survives container rebuilds** — |
| 28 | +you only need to authenticate once, not every time the container is recreated. |
| 29 | + |
| 30 | +To check or reset your authentication at any time: |
| 31 | + |
| 32 | +```bash |
| 33 | +gh auth status # show the current login |
| 34 | +gh auth logout # remove stored credentials |
| 35 | +``` |
| 36 | + |
| 37 | +### Creating a token with minimal permissions |
| 38 | + |
| 39 | +Create a **fine-grained** personal access token at **GitHub → Settings → Developer |
| 40 | +settings → [Fine-grained personal access tokens](https://github.com/settings/personal-access-tokens/new)** |
| 41 | +with the least privilege for your work: |
| 42 | + |
| 43 | +- **Repository access** → *Only select repositories* → `runtimeverification/komet-node` |
| 44 | +- **Contents** → *Read and write* |
| 45 | +- **Pull requests** → *Read and write* |
| 46 | +- **Issues** → *Read and write* (only if you triage issues) |
| 47 | + |
| 48 | +`Metadata → Read` is selected automatically; leave everything else at *No access*. |
| 49 | + |
| 50 | +## Signing commits |
| 51 | + |
| 52 | +To sign commits made with `git`, add an SSH or GPG key of type **Signing key** to |
| 53 | +your GitHub account. |
| 54 | + |
| 55 | +> [!WARNING] |
| 56 | +> Never place an SSH key registered as an **Authentication key** in the container. |
| 57 | +> An authentication key grants full account-wide git access and would bypass the |
| 58 | +> minimal permissions of your fine-grained PAT. Use a **signing-only** key here. |
| 59 | +
|
| 60 | +## Deploying a release |
| 61 | + |
| 62 | +`scripts/deploy.sh` builds and publishes the komet-node release artifacts. It is |
| 63 | +the single source of truth for the deployment steps: the `Release` workflow |
| 64 | +(`.github/workflows/release.yml`) invokes its subcommands, and you run the same |
| 65 | +subcommands by hand when CI is unavailable. |
| 66 | + |
| 67 | +### What it does |
| 68 | + |
| 69 | +The script has three subcommands: |
| 70 | + |
| 71 | +| Subcommand | Action | |
| 72 | +| ----------- | ------ | |
| 73 | +| `nix-cache` | Builds `.#komet-node`, pushes the full build closure to the `k-framework` Cachix cache, publishes the kup-installable binary to the `k-framework-binary` cache, then verifies the push and pin. Both caches are public; `binary` is a historical name, not an access level. | |
| 74 | +| `docker` | Builds the runtime image from `Dockerfile`, runs `komet-node --help` in it as a smoke test, then pushes it to Docker Hub. | |
| 75 | +| `all` | Runs `nix-cache` then `docker`. | |
| 76 | + |
| 77 | +The image tag is `runtimeverificationinc/komet-node:ubuntu-jammy-<version>`, |
| 78 | +where `<version>` comes from `package/version`. |
| 79 | + |
| 80 | +### Prerequisites |
| 81 | + |
| 82 | +Both subcommands run from a checkout of the revision you are releasing, with the |
| 83 | +following tools on `PATH`: |
| 84 | + |
| 85 | +- `nix-cache` needs `nix` and `cachix`. It fetches `kup` from |
| 86 | + `github:runtimeverification/kup` itself, so you do not install kup separately. |
| 87 | +- `docker` needs `docker`. |
| 88 | + |
| 89 | +Each subcommand checks its tools up front and exits with a clear message if one |
| 90 | +is missing, before starting the build. |
| 91 | + |
| 92 | +The devcontainer provides all of these: `nix` and `cachix` are installed into the |
| 93 | +Nix profile, and the docker-in-docker feature supplies `docker`. If you added |
| 94 | +these to an existing container, rebuild it ("Dev Containers: Rebuild Container") |
| 95 | +so the new tools are present. |
| 96 | + |
| 97 | +Provide the secrets as environment variables. Everything else has a default (see |
| 98 | +the `Shared configuration` block in `deploy.sh`), so a normal checkout needs no |
| 99 | +further setup. |
| 100 | + |
| 101 | +| Subcommand | Required environment variables | |
| 102 | +| ----------- | ------------------------------ | |
| 103 | +| `nix-cache` | `CACHIX_PUBLIC_TOKEN`, `CACHIX_PRIVATE_KFB_TOKEN` | |
| 104 | +| `docker` | `DOCKERHUB_PASSWORD` | |
| 105 | + |
| 106 | +`OWNER_REPO` and `REV` default to the current checkout's `origin` remote and |
| 107 | +`HEAD`. Override them if you are publishing a revision other than the one checked |
| 108 | +out. `DOCKERHUB_USERNAME`, `DOCKERHUB_NAMESPACE`, and `DOCKERHUB_REPO` default to |
| 109 | +the release account and repository; override them only to publish elsewhere. |
| 110 | + |
| 111 | +Both subcommands refuse to run if the working tree is not clean. CI builds from a |
| 112 | +fresh checkout, so a manual build must too: uncommitted changes and untracked |
| 113 | +files would otherwise be baked into the published image or flake build without |
| 114 | +matching the `REV` they are published under. Commit, stash, or clean the tree |
| 115 | +first. `git status --porcelain` ignores `.gitignore`d paths, so runtime artifacts |
| 116 | +and dev caches do not count. Set `ALLOW_DIRTY=1` to override the check when you |
| 117 | +deliberately want to publish an uncommitted state. |
| 118 | + |
| 119 | +### Manual release while CI is down |
| 120 | + |
| 121 | +The workflow also drafts, cleans up, and finalizes the GitHub release around the |
| 122 | +deployment jobs. When you deploy by hand, run those `gh` steps yourself in this |
| 123 | +order. `nix-cache` runs once per architecture (the workflow uses an `x86_64` and |
| 124 | +an `ARM64` runner), so run it on a machine of each architecture that should be |
| 125 | +cached. |
| 126 | + |
| 127 | +```sh |
| 128 | +VERSION=v$(cat package/version) |
| 129 | + |
| 130 | +# 1. Draft the release. |
| 131 | +gh release create "$VERSION" --draft --title "$VERSION" --target "$(git rev-parse HEAD)" |
| 132 | + |
| 133 | +# 2. Deploy. Export the secrets first (see the table above). |
| 134 | +# Run nix-cache once per architecture; docker once. |
| 135 | +./scripts/deploy.sh nix-cache |
| 136 | +./scripts/deploy.sh docker |
| 137 | + |
| 138 | +# 3. Finalize the release once every deployment has succeeded. |
| 139 | +gh release edit "$VERSION" --draft=false |
| 140 | + |
| 141 | +# If a deployment fails, remove the draft instead: |
| 142 | +# gh release delete "$VERSION" --yes --cleanup-tag |
| 143 | +``` |
0 commit comments