mirror of
https://github.com/sotashimozono/obsidian-remote-ssh.git
synced 2026-07-22 17:10:32 +00:00
Version shape is the single source of truth for the channel: - X.Y.Z-beta.N → next (BRAT --beta consumers) - X.Y.Z → main (Obsidian Community Plugins store) bump-version.mjs is now branch-aware: a beta bump only updates plugin/manifest.json + manifest-beta.json (root manifest.json + versions.json stay pinned to the last stable). A stable bump advances every file together. version-check.yml enforces the branch ↔ channel invariant: - PR into next: head must be > base (semver-aware), root manifest.json + versions.json must NOT have moved - PR into main: head must be plain X.Y.Z (no beta suffix), all manifests must agree - Sync PRs (head=main → base=next) skip the workflow entirely release.yml triggers on push to main AND next, picks prerelease vs stable from the version shape, and gates: stable-on-next pushes (promotion-staging commits) are skipped so only the eventual main push publishes the stable release. sync-main-to-next.yml automates the post-promotion sync: after a push to main, it opens a PR main → next and enables auto-merge so the histories rejoin without manual `git merge main` on next. commitlint also skips on sync PRs (the autogenerated merge titles don't follow Conventional Commits). New npm scripts (run from plugin/): - bump:beta:start → X.Y.Z → X.Y.(Z+1)-beta.0 (start of cycle) - bump:beta → -beta.N → -beta.N+1 (within cycle) - bump:stable → -beta.N suffix dropped (promotion) CONTRIBUTING.md documents the lifecycle + promotion flow. Self-test: this PR bumps next from 1.0.43 to 1.0.44-beta.0 using the new bump:beta:start script — only the beta-channel files moved.
117 lines
5 KiB
JavaScript
117 lines
5 KiB
JavaScript
// Sync `plugin/manifest.json`, the repo-root mirrors `manifest.json`,
|
|
// `manifest-beta.json` (BRAT --beta channel), `versions.json`, and
|
|
// `plugin/versions.json` with the version that npm has just written
|
|
// into `plugin/package.json`.
|
|
//
|
|
// Wired into `package.json`'s `"version"` lifecycle script so
|
|
// `npm version <X.Y.Z>` (run from `plugin/`) updates every file at
|
|
// once. The CI version-check workflow asserts they agree.
|
|
//
|
|
// ─── Branch-aware behaviour (beta vs stable channels) ───────────
|
|
//
|
|
// `next` (integration / beta) and `main` (stable) form a two-channel
|
|
// release model. The version shape selects the channel:
|
|
//
|
|
// • `X.Y.Z-beta.N` (beta) → next: BRAT --beta consumers
|
|
// • `X.Y.Z` (stable) → main: Obsidian Community Plugins
|
|
//
|
|
// On a beta bump (suffix detected) we only touch the artefacts that
|
|
// the beta channel exposes:
|
|
// • `plugin/manifest.json` — bundled into the .zip we ship
|
|
// • `manifest-beta.json` (root) — fetched by BRAT --beta from HEAD
|
|
//
|
|
// We deliberately do NOT touch:
|
|
// • `manifest.json` (root) — Obsidian Community Plugins fetches
|
|
// this from HEAD and must stay pinned to the last stable release
|
|
// • `versions.json` (both) — the stable compatibility map; betas
|
|
// should not appear here or Obsidian's installer will offer them
|
|
// as upgrades to non-BRAT users
|
|
//
|
|
// On a stable bump (no suffix) we update every file: the new stable
|
|
// version supersedes the previous beta on every channel, so
|
|
// `manifest-beta.json` is bumped to match `manifest.json` (a stable
|
|
// release IS valid for BRAT --beta — it just isn't pre-release).
|
|
//
|
|
// ─── Why a root mirror exists ────────────────────────────────────
|
|
// Obsidian's community plugin browser fetches
|
|
// `https://raw.githubusercontent.com/<repo>/HEAD/manifest.json` to
|
|
// discover plugin metadata. Plugin source lives under `plugin/` for
|
|
// repo-layout reasons (server/, proto/, deploy/ siblings), so we
|
|
// mirror to the root so Obsidian — and the obsidianmd/obsidian-releases
|
|
// registry validator — can find it.
|
|
//
|
|
// Manifest version → Obsidian's runtime view of the plugin
|
|
// (`this.manifest.version` in `main.ts`).
|
|
// versions.json → Obsidian's compatibility map: each stable plugin
|
|
// version maps to the minimum Obsidian app version
|
|
// it supports. Betas are intentionally absent.
|
|
|
|
import * as fs from 'fs';
|
|
import * as path from 'path';
|
|
import { fileURLToPath } from 'url';
|
|
|
|
const here = path.dirname(fileURLToPath(import.meta.url));
|
|
const pluginRoot = path.resolve(here, '..');
|
|
const repoRoot = path.resolve(pluginRoot, '..');
|
|
|
|
const packagePath = path.join(pluginRoot, 'package.json');
|
|
const manifestPath = path.join(pluginRoot, 'manifest.json');
|
|
const versionsPath = path.join(pluginRoot, 'versions.json');
|
|
const rootManifestPath = path.join(repoRoot, 'manifest.json');
|
|
const rootManifestBetaPath = path.join(repoRoot, 'manifest-beta.json');
|
|
const rootVersionsPath = path.join(repoRoot, 'versions.json');
|
|
|
|
const pkg = readJson(packagePath);
|
|
const manifest = readJson(manifestPath);
|
|
const versions = fs.existsSync(versionsPath) ? readJson(versionsPath) : {};
|
|
|
|
const newVersion = pkg.version;
|
|
// Accept either plain `X.Y.Z` (stable) or `X.Y.Z-beta.N` (prerelease).
|
|
// Other prerelease ids (alpha, rc) are rejected so we can't
|
|
// accidentally start a fourth channel.
|
|
if (typeof newVersion !== 'string'
|
|
|| !/^\d+\.\d+\.\d+(?:-beta\.\d+)?$/.test(newVersion)) {
|
|
console.error(
|
|
`bump-version: package.json has an unexpected version "${newVersion}".`
|
|
+ ' Expected X.Y.Z or X.Y.Z-beta.N.',
|
|
);
|
|
process.exit(1);
|
|
}
|
|
|
|
const isBeta = newVersion.includes('-beta.');
|
|
|
|
manifest.version = newVersion;
|
|
writeJson(manifestPath, manifest);
|
|
|
|
if (isBeta) {
|
|
// Beta-only update: ship the bundled manifest + advertise via BRAT.
|
|
// Leave root manifest.json + versions.json pinned to last stable.
|
|
writeJson(rootManifestBetaPath, manifest);
|
|
console.log(
|
|
`bump-version: BETA — synced plugin/manifest.json + manifest-beta.json `
|
|
+ `to ${newVersion}. Stable manifest.json + versions.json unchanged.`,
|
|
);
|
|
} else {
|
|
// Stable bump: all files advance together, including the
|
|
// versions.json compatibility map.
|
|
versions[newVersion] = manifest.minAppVersion;
|
|
writeJson(versionsPath, versions);
|
|
writeJson(rootManifestPath, manifest);
|
|
writeJson(rootManifestBetaPath, manifest);
|
|
writeJson(rootVersionsPath, versions);
|
|
console.log(
|
|
`bump-version: STABLE — synced plugin/manifest.json + manifest.json + `
|
|
+ `manifest-beta.json + versions.json (plugin + root) to ${newVersion} `
|
|
+ `(minAppVersion ${manifest.minAppVersion})`,
|
|
);
|
|
}
|
|
|
|
function readJson(p) {
|
|
return JSON.parse(fs.readFileSync(p, 'utf8'));
|
|
}
|
|
|
|
function writeJson(p, obj) {
|
|
// Match the existing file's trailing newline convention so diffs
|
|
// stay quiet between editors.
|
|
fs.writeFileSync(p, JSON.stringify(obj, null, 2) + '\n', 'utf8');
|
|
}
|