From 7e481248cd7069ee145028389d83d826e3b6e652 Mon Sep 17 00:00:00 2001 From: Imani Manyara Date: Tue, 3 Nov 2026 03:16:08 -0500 Subject: [PATCH 1/2] ci: test on macOS and Windows weekly and on dispatch dbpantry and mesobia ship binaries for macOS and Windows, so cloudkit has to build and pass there. Pull requests keep testing on Linux only. --- .github/workflows/ci.yml | 23 +++++++++++++++++++++++ CHANGELOG.md | 1 + 2 files changed, 24 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 87ebfbf..1296712 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -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 diff --git a/CHANGELOG.md b/CHANGELOG.md index 4ea4436..b2565e8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,3 +19,4 @@ 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. From 645615b51a88046544c1d8051fbecef4a7ce1203 Mon Sep 17 00:00:00 2001 From: Imani Manyara Date: Tue, 3 Nov 2026 05:17:49 -0500 Subject: [PATCH 2/2] docs: state the managed-database and descriptor scope; register release.yml Managed-database administration stays with the consumer and descriptors support writes (mesobia ADR 0046 in the design record). release.yml changes so its merge registers the dispatch-only workflow, which the first push did not. --- .github/workflows/release.yml | 6 ++++++ CHANGELOG.md | 6 ++++++ docs/architecture.md | 22 ++++++++++++++++++++-- docs/getting-started.md | 4 ++-- docs/release.md | 3 +++ 5 files changed, 37 insertions(+), 4 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0b1c53c..5fa4481 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -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: diff --git a/CHANGELOG.md b/CHANGELOG.md index b2565e8..86f7945 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,3 +20,9 @@ All notable changes to this project are documented here. The format follows - 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. diff --git a/docs/architecture.md b/docs/architecture.md index 0d312de..1395d6a 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -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 @@ -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 | @@ -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/`. --- diff --git a/docs/getting-started.md b/docs/getting-started.md index 34ecec9..45486b0 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -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). --- diff --git a/docs/release.md b/docs/release.md index 74c3822..00e5f23 100644 --- a/docs/release.md +++ b/docs/release.md @@ -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: