From 98c95be233ed387e748d31b4e8e75dddde41ffe3 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 7 Nov 2026 07:36:22 +0000 Subject: [PATCH 1/2] Publish SolStatus to the alchemy.new registry instead of npm Mark the workspace packages private and track one release, release:solstatus, backed by the root VERSION file. Merging the version pull request tags v, and a registry job publishes that version to solzero/solstatus on alchemy.new through GitHub OIDC trusted publishing. The npm publish path and NPM_TOKEN are removed. BETTER_AUTH_SECRET is now required in the deploy manifest. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01Vdh4Z35oixu5a14A56pH3r --- .github/pull_request_template.md | 2 +- .github/workflows/release.yml | 94 +++++++++++++++++-- .../2026-10-02-drop-unused-uptime-orphans.md | 3 +- .tegami/2026-10-19-alchemy-beta-83.md | 6 +- .tegami/2026-10-19-deps-patch.md | 6 +- .tegami/2026-10-20-harden-api-auth.md | 3 +- ...2026-10-22-deps-dotenv-workers-recharts.md | 3 +- .tegami/2026-11-07-alchemy-dev-stack.md | 4 +- ...026-11-07-shared-lint-dashboard-renders.md | 2 +- .tegami/2026-11-07-solzeroai-repository.md | 6 +- AGENTS.md | 4 +- README.md | 15 +-- alchemy.new.jsonc | 11 ++- docs/releasing.md | 60 ++++++------ package.json | 1 + packages/api/package.json | 1 + packages/app/package.json | 1 + packages/common/package.json | 1 + packages/infra/package.json | 1 + scripts/releases/solstatus-release.ts | 84 +++++++++++++++++ scripts/tegami.mts | 25 ++--- 21 files changed, 237 insertions(+), 96 deletions(-) create mode 100644 scripts/releases/solstatus-release.ts diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 5cc98776..81c50e85 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -13,4 +13,4 @@ - [ ] I added a `.tegami/` release entry, or explained why this pull request uses `release:none`. - [ ] I ran `nub run typecheck`, `nub run lint`, `nub run format`, and `nub run test`. - [ ] I did not include credentials, private data, internal URLs, or organization-specific defaults. -- [ ] I did not change production deploys, npm publish, or paid spend. +- [ ] I did not change production deploys, registry publish, or paid spend. diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e0009c42..ef07bff8 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -21,7 +21,7 @@ concurrency: jobs: release: - name: Version or publish npm packages + name: Version or release SolStatus if: >- github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.event == 'push' && @@ -29,10 +29,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 15 # Writes go through the release app token. This job's GITHUB_TOKEN stays read-only. - # id-token: write stays for the npm publish step. permissions: contents: read - id-token: write + outputs: + published: ${{ steps.published.outputs.published }} + tag: ${{ steps.published.outputs.tag }} + sha: ${{ steps.published.outputs.sha }} steps: # The app opens tegami/version-packages, so pull_request workflows start. - name: Create release app token @@ -60,13 +62,26 @@ jobs: nub-version: 0.9.6 node-version-file: .nvmrc cache-dependency-path: nub.lock - registry-url: "https://registry.npmjs.org" - name: Install dependencies run: nub install --frozen-lockfile - - name: Build - run: nub run build + # Only the version commit releases, so the registry package publishes only from it. + - name: Skip registry publish when the version tag exists + id: published + env: + GH_TOKEN: ${{ github.token }} + RELEASE_COMMIT: ${{ startsWith(github.event.workflow_run.head_commit.message, 'Version Packages') && github.event.workflow_run.head_commit.author.email == '341870119+solzero-bot[bot]@users.noreply.github.com' }} + run: | + set -euo pipefail + version="$(tr -d '[:space:]' < VERSION)" + echo "sha=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT" + if [ "$RELEASE_COMMIT" = "true" ] && [[ "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] && ! gh api "repos/${GITHUB_REPOSITORY}/git/ref/tags/v${version}" >/dev/null 2>&1; then + echo "tag=v${version}" >> "$GITHUB_OUTPUT" + echo "published=true" >> "$GITHUB_OUTPUT" + else + echo "published=false" >> "$GITHUB_OUTPUT" + fi # Only the merge of the Tegami version pull request publishes, because only its Validate # run tests the release. Another master push only opens or updates the version pull @@ -80,5 +95,70 @@ jobs: fi env: GITHUB_TOKEN: ${{ steps.release-token.outputs.token }} - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} RELEASE_COMMIT: ${{ startsWith(github.event.workflow_run.head_commit.message, 'Version Packages') && github.event.workflow_run.head_commit.author.email == '341870119+solzero-bot[bot]@users.noreply.github.com' }} + + # The only job that requests id-token. The alchemy.new trusted publisher matches this + # repository, release.yml, the alchemy-new environment, and refs/heads/master. + registry: + name: Publish alchemy.new registry package + needs: release + if: needs.release.result == 'success' && needs.release.outputs.published == 'true' + runs-on: ubuntu-latest + timeout-minutes: 60 + environment: alchemy-new + permissions: + contents: read + id-token: write + steps: + - name: Check out release commit + uses: actions/checkout@v7 + with: + ref: ${{ needs.release.outputs.sha }} + + - name: Set up Nub + uses: nubjs/setup-nub@v0 + with: + nub-version: 0.9.6 + node-version-file: .nvmrc + cache-dependency-path: nub.lock + + - name: Install, build, and prune production dependencies + env: + # Nub's global virtual store symlinks node_modules/.store at a cache + # directory outside the repository. The publish action rejects those + # links. This install materializes the store inside the workspace. + NPM_CONFIG_ENABLE_GLOBAL_VIRTUAL_STORE: "false" + run: | + nub install --frozen-lockfile + nub run build + nub prune --prod + + # Keep the exclude list identical to registry-dry-run.yml. + - name: Publish to alchemy.new + uses: SolZeroAI/alchemy-new-publish-action@v1 + with: + version: ${{ needs.release.outputs.tag }} + exclude: | + **/*.md + **/*.map + node_modules/**/*.ts + node_modules/**/*.tsx + node_modules/**/*.mts + node_modules/**/*.cts + # Alchemy's Node export for this subpath is the TypeScript source. + !node_modules/**/alchemy/src/Runtime/Bootstrap/** + !node_modules/**/alchemy/src/Runtime/Bootstrap/**/*.ts + node_modules/.store/drizzle-kit@* + node_modules/.store/@electric-sql+* + node_modules/.store/workerd@*/node_modules/workerd/bin/workerd + # The 1.20261002.1 binary ships as @cloudflare/workerd-linux-64. + node_modules/.store/@cloudflare+workerd-linux-64@*/node_modules/@cloudflare/workerd-linux-64/bin/workerd + # esbuild's JavaScript API loads @esbuild/linux-x64. This path is a second copy. + node_modules/.store/esbuild@*/node_modules/esbuild/bin/esbuild + # TypeScript's native binary. Alchemy transpiles the stack with Oxc. + node_modules/.store/@typescript+typescript-linux-x64@* + # musl build of libsql. The deploy runner is glibc. D1 does not load libsql. + node_modules/.store/@libsql+linux-x64-musl@* + # Alchemy loads Cloudflare, not the GCP client. + node_modules/.store/@distilled.cloud+gcp@* + docs/dashboard-demo.gif diff --git a/.tegami/2026-10-02-drop-unused-uptime-orphans.md b/.tegami/2026-10-02-drop-unused-uptime-orphans.md index 1e4803f0..88769d43 100644 --- a/.tegami/2026-10-02-drop-unused-uptime-orphans.md +++ b/.tegami/2026-10-02-drop-unused-uptime-orphans.md @@ -1,7 +1,6 @@ --- packages: - "@solstatus/common": - type: major + "release:solstatus": patch --- ## Drop unused uptime check ID and patch schema diff --git a/.tegami/2026-10-19-alchemy-beta-83.md b/.tegami/2026-10-19-alchemy-beta-83.md index 3bf96c85..80c340d7 100644 --- a/.tegami/2026-10-19-alchemy-beta-83.md +++ b/.tegami/2026-10-19-alchemy-beta-83.md @@ -1,10 +1,6 @@ --- packages: - solstatus: patch - "@solstatus/common": patch - "@solstatus/api": patch - "@solstatus/app": patch - "@solstatus/infra": patch + "release:solstatus": patch --- ## Bump Alchemy to 2.0.0-beta.83 diff --git a/.tegami/2026-10-19-deps-patch.md b/.tegami/2026-10-19-deps-patch.md index 40a01855..9a3c69b7 100644 --- a/.tegami/2026-10-19-deps-patch.md +++ b/.tegami/2026-10-19-deps-patch.md @@ -1,10 +1,6 @@ --- packages: - "solstatus": patch - "@solstatus/api": patch - "@solstatus/app": patch - "@solstatus/common": patch - "@solstatus/infra": patch + "release:solstatus": patch --- ### Update minor and patch dependencies diff --git a/.tegami/2026-10-20-harden-api-auth.md b/.tegami/2026-10-20-harden-api-auth.md index 89539863..cc353eaa 100644 --- a/.tegami/2026-10-20-harden-api-auth.md +++ b/.tegami/2026-10-20-harden-api-auth.md @@ -1,7 +1,6 @@ --- packages: - "@solstatus/app": patch - "@solstatus/common": patch + "release:solstatus": patch --- ## Harden API authentication and query parameterization diff --git a/.tegami/2026-10-22-deps-dotenv-workers-recharts.md b/.tegami/2026-10-22-deps-dotenv-workers-recharts.md index ccda9069..42d911e3 100644 --- a/.tegami/2026-10-22-deps-dotenv-workers-recharts.md +++ b/.tegami/2026-10-22-deps-dotenv-workers-recharts.md @@ -1,7 +1,6 @@ --- packages: - solstatus: patch - "@solstatus/app": patch + "release:solstatus": patch --- ## Update dotenv and dashboard chart dependencies diff --git a/.tegami/2026-11-07-alchemy-dev-stack.md b/.tegami/2026-11-07-alchemy-dev-stack.md index 5e8f6ce9..18fc3576 100644 --- a/.tegami/2026-11-07-alchemy-dev-stack.md +++ b/.tegami/2026-11-07-alchemy-dev-stack.md @@ -1,8 +1,6 @@ --- packages: - "@solstatus/app": patch - "@solstatus/api": patch - "@solstatus/infra": patch + "release:solstatus": patch --- ## Run local development on the Alchemy dev stack diff --git a/.tegami/2026-11-07-shared-lint-dashboard-renders.md b/.tegami/2026-11-07-shared-lint-dashboard-renders.md index a8a82d79..be269adb 100644 --- a/.tegami/2026-11-07-shared-lint-dashboard-renders.md +++ b/.tegami/2026-11-07-shared-lint-dashboard-renders.md @@ -1,6 +1,6 @@ --- packages: - "@solstatus/app": patch + "release:solstatus": patch --- ## Dashboard renders follow the React Compiler rules diff --git a/.tegami/2026-11-07-solzeroai-repository.md b/.tegami/2026-11-07-solzeroai-repository.md index 8e9ce8bc..96d9d19f 100644 --- a/.tegami/2026-11-07-solzeroai-repository.md +++ b/.tegami/2026-11-07-solzeroai-repository.md @@ -1,10 +1,6 @@ --- packages: - solstatus: patch - "@solstatus/app": patch - "@solstatus/api": patch - "@solstatus/common": patch - "@solstatus/infra": patch + "release:solstatus": patch --- ## Point package and app links at SolZeroAI/solstatus diff --git a/AGENTS.md b/AGENTS.md index 1581e608..b1411aa3 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -73,9 +73,9 @@ A cloud-agent pull request that changes user-visible behavior must attach proof. ## Release management -- Follow `docs/releasing.md`. Add a Tegami release entry under `.tegami/` when a change has an observable effect on a published package. +- Follow `docs/releasing.md`. Add a Tegami release entry under `.tegami/` that targets `"release:solstatus"` when a change has an observable effect on a deployment. SolStatus publishes only to the alchemy.new registry. The workspace packages are private. - Use the `release:none` label for a change with no observable effect, and explain that choice in the pull request. -- Do not edit `VERSION`, package versions, `CHANGELOG.md`, or `.tegami/publish-lock.yaml` on a feature branch. The automated version pull request owns those files. +- Do not edit `VERSION`, `CHANGELOG.md`, or `.tegami/publish-lock.yaml` on a feature branch. The automated version pull request owns those files. ## Architecture diff --git a/README.md b/README.md index 38895203..38f460d0 100644 --- a/README.md +++ b/README.md @@ -67,16 +67,5 @@ See the [infra README](./packages/infra/README.md#database-management) for more ### Dependency Management Renovate opens dependency pull requests from the shared `SolZeroAI/renovate-config` preset and merges them when CI passes. -### npm Publishing -Tegami versions and publishes the npm packages after Validate succeeds on `master`: -- `solstatus` - Main CLI package -- `@solstatus/common` - Shared utilities and schemas -- `@solstatus/api` - API workers -- `@solstatus/app` - Web application -- `@solstatus/infra` - Infrastructure tools - -See [docs/releasing.md](./docs/releasing.md). To enable npm publishing: -1. Create an npm access token at https://www.npmjs.com/ -2. Add it as a GitHub secret named `NPM_TOKEN` -3. Enable **Allow GitHub Actions to create and approve pull requests** -4. Create the `release:none` label for toolchain-only pull requests +### Releases +Tegami versions SolStatus after Validate succeeds on `master`. Merging the version pull request tags `v` and publishes that version to the [alchemy.new](https://alchemy.new) registry as `solzero/solstatus`, through GitHub OIDC trusted publishing. The workspace packages are private and are not published to npm. See [docs/releasing.md](./docs/releasing.md). diff --git a/alchemy.new.jsonc b/alchemy.new.jsonc index 4c1bc2b8..3cddfacc 100644 --- a/alchemy.new.jsonc +++ b/alchemy.new.jsonc @@ -7,12 +7,13 @@ "name": "SolStatus", "description": "Self host a low-cost, globally-distributed uptime monitoring service on Cloudflare.", "publisher": { - "name": "SolStatus", - "github": "jonbeckman", + "name": "SolZero", + "github": "SolZeroAI", + "website": "https://solzero.dev", }, "source": { "kind": "registry", - "org": "jonbeckman", + "org": "solzero", "project": "solstatus", }, "deployment": { @@ -42,8 +43,8 @@ { "name": "BETTER_AUTH_SECRET", "label": "Session signing secret", - "description": "Signs dashboard sessions. SolStatus reads BETTER_AUTH_SECRET when it deploys. Leave this empty to deploy; the worker then receives an empty secret.", - "required": false, + "description": "Signs dashboard sessions. Use a random value of at least 32 characters, for example the output of `openssl rand -hex 32`. Keep the same value on later deploys, or every session ends.", + "required": true, "secret": true, "type": "string", }, diff --git a/docs/releasing.md b/docs/releasing.md index f68d6bfa..7c676147 100644 --- a/docs/releasing.md +++ b/docs/releasing.md @@ -1,18 +1,13 @@ # Releasing SolStatus -This repository publishes five npm packages: +SolStatus ships one release: the `solstatus` package in the +[alchemy.new](https://alchemy.new) registry, under the `solzero` org. A +deployer picks a version on alchemy.new and deploys it to their own Cloudflare +account. The workspace packages are private and are not published to npm. -- `solstatus` — CLI -- `@solstatus/common` — shared schema and utilities -- `@solstatus/api` — monitor workers -- `@solstatus/app` — TanStack Start dashboard -- `@solstatus/infra` — Alchemy and Wrangler infrastructure - -[Tegami](https://tegami.fuma-nama.dev) prepares versions, updates -`package.json` and the root `VERSION` file, and publishes to npm. - -`VERSION` and the root `solstatus` package stay on the same SemVer value. The -published release is the `version` in the root `package.json`. +[Tegami](https://tegami.fuma-nama.dev) tracks the release as +`release:solstatus`. It writes the next version to the root `VERSION` file, +prepends `CHANGELOG.md`, and tags `v`. ## Version policy @@ -27,14 +22,14 @@ version in `tegami/version-packages`. ## Add a release entry -Every pull request with an observable effect on a published package must add +Every pull request with an observable effect on a deployment must add a Markdown file under `.tegami/`. Use a clear file name such as `.tegami/2026-08-27-fix-monitor-interval.md`. ```md --- packages: - solstatus: patch + "release:solstatus": patch --- ## Fix monitor interval parsing @@ -42,14 +37,14 @@ packages: The CLI now rejects a check interval below 30 seconds. ``` -Target the package that changed. Choose `patch`, `minor`, or `major` -according to the version policy. Write the note for package consumers. Include +Target only `release:solstatus`. Choose `patch`, `minor`, or `major` +according to the version policy. Write the note for the people who deploy and run SolStatus. Include required action in the note. Tegami adds pull request and contributor links to the GitHub Release. Run `nub run tegami` to create an entry interactively. The pull request preview workflow posts the combined version and release-note preview. A change with no -observable effect on a published package can use the `release:none` label +observable effect on a deployment can use the `release:none` label after the pull request explains why it needs no entry. ## Automated release flow @@ -59,37 +54,48 @@ after the pull request explains why it needs no entry. `nub run tegami ci` only for same-repository `push` events. It opens or updates `tegami/version-packages` with the solzero-release GitHub App token, so that pull request runs normal CI. -3. Review the version pull request. It updates `package.json` and `VERSION`, +3. Review the version pull request. It updates `VERSION`, prepends `CHANGELOG.md`, consumes the pending entries, and writes `.tegami/publish-lock.yaml`. 4. Merge the version pull request. After validation, the release workflow - builds the packages, publishes them to npm, and creates the GitHub Release. - GitHub releases are not created until publish succeeds (`eager: false`). + tags `v` and creates the GitHub Release. Then the `registry` job + builds the stack, prunes development dependencies, and publishes that + version to alchemy.new with `SolZeroAI/alchemy-new-publish-action`. Do not edit generated version files in a feature pull request. Review them in the version pull request before merge. -This workflow versions and publishes npm packages. It does not deploy +This workflow versions and publishes the registry package. It does not deploy production Cloudflare infrastructure. +Every non-draft pull request runs `Registry dry run`, which packs the same +archive without uploading it. Keep its `exclude` list identical to the one in +the `registry` job. + ## Repository settings Enable **Allow GitHub Actions to create and approve pull requests** in the repository Actions settings. Keep workflow permissions restricted to the values in each workflow. The release workflow grants `contents: read` by default. -The version and publish job adds `id-token: write` for npm trusted publishing. Contents and pull request writes use the solzero-release app token -(`RELEASE_APP_ID` and `RELEASE_APP_PRIVATE_KEY`). The job `GITHUB_TOKEN` stays -read-only. +(`RELEASE_APP_CLIENT_ID` and `RELEASE_APP_PRIVATE_KEY`). The job `GITHUB_TOKEN` +stays read-only. + +Only the `registry` job requests `id-token: write`, and it runs in the +`alchemy-new` environment. The alchemy.new trusted publisher for +`solzero/solstatus` matches `SolZeroAI/solstatus`, `release.yml`, the +`alchemy-new` environment, and `refs/heads/master`. No registry token is +stored in the repository. Create the `release:none` label for pull requests that have no user-visible release note. ## Failure recovery -Re-run the failed `Release` workflow after a network, npm, or GitHub API -failure. Tegami checks existing tags, npm versions, and GitHub releases, so the -retry continues the same version without duplicating work. +Re-run the failed `Release` workflow after a network, registry, or GitHub API +failure. Tegami checks existing tags and GitHub releases, so the retry +continues the same version without duplicating work. If only the `registry` +job failed, re-run that job. If a released change has a defect, fix it in a new pull request and add a new release entry. Keep an existing release tag at its original commit. Never diff --git a/package.json b/package.json index 2352209d..f422b7b5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,7 @@ { "name": "solstatus", "version": "3.0.0", + "private": true, "description": "Self host a low-cost, globally-distributed uptime monitoring service on Cloudflare", "keywords": [ "cloudflare", diff --git a/packages/api/package.json b/packages/api/package.json index c8b5bc30..9846e854 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -1,6 +1,7 @@ { "name": "@solstatus/api", "version": "3.0.0", + "private": true, "description": "API workers for SolStatus uptime monitoring service", "keywords": [ "api", diff --git a/packages/app/package.json b/packages/app/package.json index b1675280..2191aef8 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -1,6 +1,7 @@ { "name": "@solstatus/app", "version": "3.0.0", + "private": true, "description": "Web application for SolStatus uptime monitoring service", "keywords": [ "dashboard", diff --git a/packages/common/package.json b/packages/common/package.json index 6411880b..3f37f409 100644 --- a/packages/common/package.json +++ b/packages/common/package.json @@ -1,6 +1,7 @@ { "name": "@solstatus/common", "version": "3.0.0", + "private": true, "description": "Common utilities and database schemas for SolStatus", "keywords": [ "database", diff --git a/packages/infra/package.json b/packages/infra/package.json index e4848f2f..99761a02 100644 --- a/packages/infra/package.json +++ b/packages/infra/package.json @@ -1,6 +1,7 @@ { "name": "@solstatus/infra", "version": "3.0.0", + "private": true, "description": "Infrastructure configuration and deployment tools for SolStatus", "keywords": [ "cloudflare", diff --git a/scripts/releases/solstatus-release.ts b/scripts/releases/solstatus-release.ts new file mode 100644 index 00000000..148a21b2 --- /dev/null +++ b/scripts/releases/solstatus-release.ts @@ -0,0 +1,84 @@ +import { readFile, writeFile } from "node:fs/promises" +import { join } from "node:path" +import { type TegamiPlugin, WorkspacePackage } from "tegami" +import { GitTagPublishTask } from "tegami/plugins/git" + +export const SOLSTATUS_PACKAGE_ID = "release:solstatus" +export const VERSION_FILE = "VERSION" + +// One SemVer release version, such as 4.1.0 or 4.1.0-beta.1. +const SEMVER = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/ + +class SolStatusReleasePackage extends WorkspacePackage { + readonly manager = "release" + readonly name = "solstatus" + readonly path: string + #version: string + + constructor(root: string, version: string) { + super() + this.path = root + this.#version = version + } + + get version(): string { + return this.#version + } + + setVersion(version: string): void { + this.#version = version + } +} + +class SolStatusGitTagPublishTask extends GitTagPublishTask {} + +async function readVersion(root: string): Promise { + const version = (await readFile(join(root, VERSION_FILE), "utf8")).trim() + + if (!SEMVER.test(version)) { + throw new Error(`${VERSION_FILE} must contain one valid SemVer version.`) + } + + return version +} + +export function solStatusRelease(): TegamiPlugin { + let pkg: SolStatusReleasePackage | undefined + + return { + name: "solstatus-release", + enforce: "post", + async resolve() { + pkg = new SolStatusReleasePackage(this.cwd, await readVersion(this.cwd)) + this.graph.add(pkg) + }, + async applyDraft(draft) { + if (!pkg) return + const nextVersion = draft.getPackageDraft(pkg.id)?.bumpVersion(pkg) + + if (!nextVersion || nextVersion === pkg.version) return + pkg.setVersion(nextVersion) + await writeFile(join(this.cwd, VERSION_FILE), `${nextVersion}\n`) + }, + initPublishPlan({ plan }) { + if (!pkg) return + const packagePlan = plan.packages.get(pkg.id) + + if (!packagePlan) return + packagePlan.git ??= {} + packagePlan.git.tag = `v${pkg.version}` + }, + publishPreflight({ pkg: candidate }) { + if (candidate instanceof SolStatusReleasePackage) return { shouldPublish: true } + }, + publishTasks({ plan }) { + return plan + .getPackagesToPublish() + .flatMap((candidate) => + candidate instanceof SolStatusReleasePackage + ? [new SolStatusGitTagPublishTask(candidate)] + : [], + ) + }, + } +} diff --git a/scripts/tegami.mts b/scripts/tegami.mts index ec45489c..9c822d0c 100644 --- a/scripts/tegami.mts +++ b/scripts/tegami.mts @@ -1,38 +1,31 @@ -import { writeFile } from "node:fs/promises" -import { join } from "node:path" import { tegami } from "tegami" import { runCli } from "tegami/cli" import { github } from "tegami/plugins/github" +import { solStatusRelease } from "./releases/solstatus-release.ts" -const publishedPackageId = "npm:solstatus" - +// SolStatus ships one release: the alchemy.new registry package. The workspace packages +// are private, so Tegami versions the root VERSION file and tags v. const release = tegami({ + ignore: [/^npm:/], npm: { client: "nub", + updateLockFile: false, }, plugins: [ github({ repo: "SolZeroAI/solstatus", release: { eager: false, + create({ pkg }) { + return { title: `SolStatus v${pkg.version}` } + }, }, versionPr: { base: "master", branch: "tegami/version-packages", }, }), - { - name: "root-version-file", - async applyDraft(draft) { - const pkg = this.graph.get(publishedPackageId) - - if (!pkg) return - const nextVersion = draft.getPackageDraft(pkg.id)?.bumpVersion(pkg) - - if (!nextVersion) return - await writeFile(join(this.cwd, "VERSION"), `${nextVersion}\n`) - }, - }, + solStatusRelease(), ], }) From af78e82820728d13941dc1acce9c9bc4a0347812 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 7 Nov 2026 07:37:37 +0000 Subject: [PATCH 2/2] Target the HttpApi release entry at release:solstatus Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01Vdh4Z35oixu5a14A56pH3r --- .tegami/2026-11-07-effect-httpapi-tanstack-query.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.tegami/2026-11-07-effect-httpapi-tanstack-query.md b/.tegami/2026-11-07-effect-httpapi-tanstack-query.md index 7af62710..f4a8942e 100644 --- a/.tegami/2026-11-07-effect-httpapi-tanstack-query.md +++ b/.tegami/2026-11-07-effect-httpapi-tanstack-query.md @@ -1,12 +1,10 @@ --- packages: - "@solstatus/app": minor - "@solstatus/api": patch - "@solstatus/common": patch + "release:solstatus": minor --- ## Serve the API with Effect HttpApi and load data with TanStack Query The dashboard API is now an Effect `HttpApi` with typed requests, responses, and errors. Signed-in users can read the OpenAPI document at `/api/openapi.json` and the API docs at `/api/docs`. The dashboard loads and refreshes data with TanStack Query, and the list filters, sorting, paging, and the detail time range are kept in the URL. -`POST /api/endpoint-monitors/{id}/execute-check` replaces the `GET` form of that endpoint. The Zod schemas exported from `@solstatus/common/db` are removed; use the Drizzle row types `EndpointMonitorRow` and `EndpointMonitorPatch` from `@solstatus/common/db/schema`. +`POST /api/endpoint-monitors/{id}/execute-check` replaces the `GET` form of that endpoint.