diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9737a26..0089ebf 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -121,6 +121,7 @@ jobs: runs-on: ubuntu-latest permissions: contents: write + pull-requests: write steps: - uses: actions/checkout@v6 @@ -143,19 +144,44 @@ jobs: # as required by the Obsidian community plugin format. run: npm run bundle --workspace=obsidian-plugin + - name: Sync Obsidian manifest metadata from tag + run: | + VERSION="${GITHUB_REF_NAME#v}" + npm run obsidian:sync-version -- "$VERSION" + - name: Package Obsidian plugin zip # Obsidian community plugins are installed by dropping main.js + manifest.json # (+ optional styles.css) into the vault plugins folder. We zip them for the release. run: | VERSION="${GITHUB_REF_NAME#v}" - # Stamp manifest.json version to match the release tag - jq --arg v "$VERSION" '.version = $v' obsidian-plugin/manifest.json > tmp.json && mv tmp.json obsidian-plugin/manifest.json mkdir -p obsidian-plugin/dist cp obsidian-plugin/out/main.js obsidian-plugin/dist/main.js cp obsidian-plugin/manifest.json obsidian-plugin/dist/manifest.json cd obsidian-plugin/dist zip "../../bindery-obsidian-${VERSION}.zip" main.js manifest.json + - name: Create PR to sync Obsidian release metadata on main + uses: peter-evans/create-pull-request@v7 + with: + commit-message: "chore(obsidian): sync metadata for ${{ github.ref_name }}" + branch: "chore/obsidian-sync-${{ github.ref_name }}" + delete-branch: true + title: "chore(obsidian): sync manifests for ${{ github.ref_name }}" + body: | + This automated PR keeps Obsidian plugin metadata in sync with the tagged release. + + Updated files: + - manifest.json + - obsidian-plugin/manifest.json + - obsidian-plugin/versions.json + + Triggered by release tag `${{ github.ref_name }}`. + base: main + add-paths: | + manifest.json + obsidian-plugin/manifest.json + obsidian-plugin/versions.json + - name: Upload Obsidian plugin zip to release uses: softprops/action-gh-release@v3 with: diff --git a/manifest.json b/manifest.json index 2a12ff1..f93ec9f 100644 --- a/manifest.json +++ b/manifest.json @@ -5,6 +5,6 @@ "minAppVersion": "1.12.7", "description": "Typography formatting and multi-format export for book projects written in Markdown.", "author": "Erik van der Boom", - "authorUrl": "https://github.com/evdboom/Bindery", + "authorUrl": "https://evdboom.nl/projects/bindery", "isDesktopOnly": true } diff --git a/obsidian-plugin/manifest.json b/obsidian-plugin/manifest.json index 2a12ff1..f93ec9f 100644 --- a/obsidian-plugin/manifest.json +++ b/obsidian-plugin/manifest.json @@ -5,6 +5,6 @@ "minAppVersion": "1.12.7", "description": "Typography formatting and multi-format export for book projects written in Markdown.", "author": "Erik van der Boom", - "authorUrl": "https://github.com/evdboom/Bindery", + "authorUrl": "https://evdboom.nl/projects/bindery", "isDesktopOnly": true } diff --git a/package.json b/package.json index e873954..797d4ab 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "scripts": { "build": "npm run build -ws --if-present", "test": "npm run test -ws --if-present", - "build:core": "npm run build --workspace=bindery-core" + "build:core": "npm run build --workspace=bindery-core", + "obsidian:sync-version": "node ./scripts/sync-obsidian-version.mjs" } } diff --git a/scripts/sync-obsidian-version.mjs b/scripts/sync-obsidian-version.mjs new file mode 100644 index 0000000..d40f74f --- /dev/null +++ b/scripts/sync-obsidian-version.mjs @@ -0,0 +1,73 @@ +#!/usr/bin/env node +import { readFileSync, writeFileSync } from "node:fs"; +import { resolve } from "node:path"; + +const AUTHOR_URL = "https://evdboom.nl/projects/bindery"; + +function parseJson(filePath) { + return JSON.parse(readFileSync(filePath, "utf8")); +} + +function writeJson(filePath, value) { + writeFileSync(filePath, `${JSON.stringify(value, null, 2)}\n`, "utf8"); +} + +function sortSemverKeys(keys) { + return [...keys].sort((a, b) => { + const pa = a.split(".").map(Number); + const pb = b.split(".").map(Number); + for (let i = 0; i < Math.max(pa.length, pb.length); i += 1) { + const na = Number.isFinite(pa[i]) ? pa[i] : 0; + const nb = Number.isFinite(pb[i]) ? pb[i] : 0; + if (na !== nb) { + return na - nb; + } + } + return 0; + }); +} + +function requireVersionArg() { + const raw = process.argv[2] || process.env.RELEASE_VERSION || process.env.GITHUB_REF_NAME || ""; + const normalized = raw.replace(/^v/, "").trim(); + if (!/^\d+\.\d+\.\d+$/.test(normalized)) { + throw new Error(`Expected version like 1.2.3, got: ${raw || ""}`); + } + return normalized; +} + +const repoRoot = process.cwd(); +const rootManifestPath = resolve(repoRoot, "manifest.json"); +const pluginManifestPath = resolve(repoRoot, "obsidian-plugin", "manifest.json"); +const versionsPath = resolve(repoRoot, "obsidian-plugin", "versions.json"); + +const version = requireVersionArg(); + +const rootManifest = parseJson(rootManifestPath); +const pluginManifest = parseJson(pluginManifestPath); +const versions = parseJson(versionsPath); + +rootManifest.version = version; +pluginManifest.version = version; + +rootManifest.authorUrl = AUTHOR_URL; +pluginManifest.authorUrl = AUTHOR_URL; + +const minAppVersion = pluginManifest.minAppVersion || rootManifest.minAppVersion; +if (!minAppVersion) { + throw new Error("Unable to determine minAppVersion from manifests."); +} + +if (!versions[version]) { + versions[version] = minAppVersion; +} +const sortedVersions = {}; +for (const key of sortSemverKeys(Object.keys(versions))) { + sortedVersions[key] = versions[key]; +} + +writeJson(rootManifestPath, rootManifest); +writeJson(pluginManifestPath, pluginManifest); +writeJson(versionsPath, sortedVersions); + +console.log(`Synced Obsidian metadata for version ${version}`);