Skip to content
Merged
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
23 changes: 23 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,29 @@ jobs:
- name: Lint
run: make lint

# dbpantry and mesobia ship binaries for macOS and Windows, so cloudkit must
# build and pass there too. Pull requests test on Linux only; the other OSes
# run weekly and by hand.
cross-os:
if: github.event_name != 'pull_request'
runs-on: ${{ matrix.os }}
timeout-minutes: 15
strategy:
fail-fast: false
matrix:
os: [macos-latest, windows-latest]
steps:
- uses: actions/checkout@v7
with:
persist-credentials: false
- uses: actions/setup-go@v7
with:
go-version-file: src/go.mod
cache: false
- name: Gate
shell: bash
run: make ci

gitleaks:
if: github.event_name != 'pull_request' || !github.event.pull_request.draft
runs-on: ubuntu-latest
Expand Down
6 changes: 6 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ name: Release
#
# src/internal/policy's TestReleaseRunsOnlyOnAConfirmedDispatch fails if this
# file gains an automatic trigger or loses the confirmation.
#
# GitHub registers a workflow that has no push or pull_request trigger only
# when a push to the default branch changes the file; until then a dispatch
# answers 404 "workflow not found on the default branch". The repository's
# first push did not register it, so this comment's own merge is what did.
# Check before tagging: gh workflow list --repo simtabi/cloudkit shows Release.
on:
workflow_dispatch:
inputs:
Expand Down
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,10 @@ All notable changes to this project are documented here. The format follows
workflow triggers; action pinning.
- CI on pull requests, by dispatch and weekly; a release workflow that runs only on a confirmed
dispatch against a `v` tag.
- A weekly and on-demand CI leg on macOS and Windows; pull requests still test on Linux only.

### Changed

- The architecture guide states the scope split: cloudkit finds and connects to managed databases
but never administers them, and REST descriptors (planned) support writes behind signing or
explicit enablement, plans and the contract suite.
22 changes: 20 additions & 2 deletions docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@ provisioning hosts, and mesobia for its provider drivers.
| The generic path: SSH to any host, and a cloud-init renderer | What is installed on the host |
| One error model, one retry policy, one redaction rule | CLI, API, UI and configuration loading |
| A contract test kit every adapter passes | |
| Managed databases: finding them and returning connection details | All database administration, managed engines included |
| REST descriptors: providers without a compiled adapter, reads and writes | |

cloudkit has no database logic. It finds managed database instances (RDS, Cloud SQL, DigitalOcean
databases and the like) and says how to reach them, including a provider-issued short-lived connect
credential where one exists; creating users, databases or pools is the consumer's work, done through
its own engine adapters.

## Rules

Expand Down Expand Up @@ -46,6 +53,17 @@ Each consumer has its own command tree and configuration loader. A library that
config package would force them on both, so cloudkit takes plain structs and an injected
`*slog.Logger`, and each consumer maps its own configuration onto them.

## Why descriptors may write

Most providers in the long tail have an HTTP API and no maintained Go SDK. A descriptor maps that
API onto the same capability interfaces as a compiled adapter, reads and writes alike, so a new
provider needs no release. Writes keep every guarantee a compiled adapter has: each one is planned
against the live state, a destroy must declare what it loses and needs the name typed back, paths
outside the declared API hosts are rejected, a descriptor never holds a credential, and write
operations load only from a descriptor that is signed by a trusted key or enabled by the consumer
for that provider and account. Every descriptor passes the same contract suite as a compiled adapter
before it loads.

## Layout

| Path | Holds |
Expand All @@ -54,8 +72,8 @@ config package would force them on both, so cloudkit takes plain structs and an
| `src/internal/policy/` | repository-wide tests: forbidden symbols, workflow guards |

Planned packages are added when they have code: `providers/` (wave 1: Hetzner, DigitalOcean,
Linode, Vultr; plus `generic` for any SSH host), `ssh/`, `cloudinit/`, `transport/` and
`cloudkittest/`.
Linode, Vultr; plus `generic` for any SSH host), `ssh/`, `cloudinit/`, `transport/`, `descriptor/`
and `cloudkittest/`.

---

Expand Down
4 changes: 2 additions & 2 deletions docs/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,8 @@ URL with them before logging it.
## What comes next

The registry, capability probes, plans with drift refusal, the contract test kit, the SSH path, the
cloud-init renderer and the first provider adapters (Hetzner, DigitalOcean, Linode, Vultr) are
planned; see [Architecture](architecture.md).
cloud-init renderer, the first provider adapters (Hetzner, DigitalOcean, Linode, Vultr), managed
database discovery and REST descriptors are planned; see [Architecture](architecture.md).

---

Expand Down
3 changes: 3 additions & 0 deletions docs/release.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ and a GitHub release whose body is the version's CHANGELOG section. There are no

## Steps

0. Check the workflow is registered: `gh workflow list --repo simtabi/cloudkit` lists `Release`.
GitHub registers a dispatch-only workflow only when a push to `main` changes it, so a fresh copy
of the repository answers 404 until then.
1. Move the `[Unreleased]` entries in `CHANGELOG.md` under a dated `## [X.Y.Z] - YYYY-MM-DD`
heading, through a pull request.
2. After it merges, tag the merge commit and push the tag:
Expand Down
Loading