Skip to content
42 changes: 42 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE/release.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<!--
Release PR — merges `dev` into `main` to cut a new version.

Open it from the dev...main compare with:
?expand=1&template=release.md
(base: main, compare: dev)

Bump manifest.json + versions.json + CHANGELOG.md on `dev` BEFORE opening this
PR. On merge, the Release workflow auto-tags `main` and publishes the release.
-->

## Release X.Y.Z

<!-- One-line summary of this release. -->

## Highlights

<!-- Mirror the new CHANGELOG.md section for X.Y.Z. -->
-

## Pre-merge checklist

- [ ] `manifest.json` `version` is set to **X.Y.Z**
- [ ] `versions.json` has `"X.Y.Z": "<minAppVersion>"` (matches `manifest.minAppVersion`)
- [ ] `CHANGELOG.md` has a dated `## [X.Y.Z]` section (moved out of *Unreleased*)
- [ ] `node --check main.js` and `node scripts/validate.mjs` pass locally
- [ ] CI (`validate`) is green on this PR
- [ ] Code-owner approval obtained

## After merge (automatic)

On merge into `main`, the **Release** workflow reads the version from
`manifest.json`, pushes the `X.Y.Z` tag, and publishes the GitHub release with
`main.js`, `manifest.json`, and `styles.css`. If that version is already
released, it does nothing.

Maintainer follow-up:

- [ ] Verify the release and its three assets appeared under
[Releases](https://github.com/Post-Math/Lookout/releases).
- [ ] Back-merge `main` into `dev` (a `chore/sync-dev-with-main` PR) to
reconcile history.
54 changes: 41 additions & 13 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,16 +1,25 @@
name: Release

# Releases are cut from `main`. Pushing a version tag (e.g. 1.2.0 — no `v`
# prefix, matching manifest.json, per Obsidian's convention) builds the
# release and attaches the plugin artifacts.
# Releases are cut automatically when `main` advances. The job reads the version
# from manifest.json and, if that version has not been released yet, creates and
# pushes the matching tag (bare version, no `v` prefix — Obsidian's convention)
# and publishes the GitHub release with the plugin artifacts.
#
# It is idempotent: a push to `main` that does NOT bump the version (e.g. a CI
# or docs change) finds the tag already exists and does nothing. Tag + release
# happen in the same job, so we don't rely on a tag push triggering a second
# workflow (GITHUB_TOKEN tag pushes don't trigger other workflows).
on:
push:
tags:
- "[0-9]+.[0-9]+.[0-9]+"
branches: [main]

permissions:
contents: write

concurrency:
group: release-main
cancel-in-progress: false

jobs:
release:
name: release
Expand All @@ -29,20 +38,39 @@ jobs:
node --check main.js
node scripts/validate.mjs

- name: Verify tag matches manifest version
- name: Read version from manifest
id: meta
run: echo "version=$(node -p "require('./manifest.json').version")" >> "$GITHUB_OUTPUT"

- name: Check whether this version is already released
id: guard
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
TAG="${GITHUB_REF_NAME}"
VERSION="$(node -p "require('./manifest.json').version")"
if [ "$TAG" != "$VERSION" ]; then
echo "::error::Tag '$TAG' does not match manifest version '$VERSION'."
exit 1
V="${{ steps.meta.outputs.version }}"
if gh release view "$V" >/dev/null 2>&1 \
|| [ -n "$(git ls-remote --tags origin "refs/tags/$V")" ]; then
echo "exists=true" >> "$GITHUB_OUTPUT"
echo "Version $V already released or tagged — nothing to do."
else
echo "exists=false" >> "$GITHUB_OUTPUT"
echo "Version $V is new — will tag and release."
fi

- name: Tag the release commit
if: steps.guard.outputs.exists == 'false'
run: |
V="${{ steps.meta.outputs.version }}"
git tag "$V"
git push origin "$V"

- name: Create GitHub release
if: steps.guard.outputs.exists == 'false'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh release create "$GITHUB_REF_NAME" \
V="${{ steps.meta.outputs.version }}"
gh release create "$V" \
main.js manifest.json styles.css \
--title "Lookout $GITHUB_REF_NAME" \
--title "Lookout $V" \
--generate-notes
33 changes: 33 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Changelog

All notable changes to Lookout are documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

_Nothing yet._

## [1.1.1] - 2026-06-23

Initial public release.

### Added

- Mermaid diagrams: pan (drag / wheel), zoom (`Ctrl`/`Cmd`+wheel or buttons), a
100 % gauge, fit-to-frame, and full-screen — with keyboard controls.
- Tables: a full-screen button for wide tables, in both Reading view and Live
Preview.
- Command: "Open the active note's first Mermaid diagram full screen".

### Fixed

- Mermaid: the inline frame now hugs the diagram's natural (100 %) height, so a
short diagram no longer sits inside an oversized frame with dead space.
- Tables: the full-screen button now appears in Live Preview (Obsidian's default
mode), not only in Reading view. The table being actively edited is left
untouched.

[Unreleased]: https://github.com/Post-Math/Lookout/compare/1.1.1...HEAD
[1.1.1]: https://github.com/Post-Math/Lookout/releases/tag/1.1.1
30 changes: 19 additions & 11 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,16 +100,24 @@ Please also:

## Releasing (maintainers)

1. Merge `dev` into `main` via PR.
2. Bump `version` in `manifest.json` and add the matching entry to
`versions.json` (`"<version>": "<minAppVersion>"`).
3. Tag the release commit on `main` with the bare version (no `v` prefix, to
match Obsidian's convention) and push the tag:
```bash
git tag 1.2.0
git push origin 1.2.0
```
4. The **Release** workflow validates the tag against `manifest.json` and
publishes a GitHub release with `main.js`, `manifest.json`, and `styles.css`.
Releases are **automatic on merge to `main`** — there is no manual tagging step.
The version bump lands on `dev` first:

1. On a branch off `dev`, prepare the release:
- bump `version` in `manifest.json`,
- add the matching entry to `versions.json` (`"<version>": "<minAppVersion>"`),
- move the `Unreleased` notes in [`CHANGELOG.md`](CHANGELOG.md) into a dated
`## [<version>]` section.

Open a PR into `dev` and merge it.
2. Open a **release PR** from `dev` into `main` using the release template
(append `?expand=1&template=release.md` to the compare URL) and merge it
after a code-owner approval.
3. On merge, the **Release** workflow reads the version from `manifest.json`,
pushes the bare-version tag (no `v` prefix, to match Obsidian's convention),
and publishes a GitHub release with `main.js`, `manifest.json`, and
`styles.css`. It is idempotent — a merge that does not bump the version
(e.g. a CI or docs change) is a no-op.
4. Back-merge `main` into `dev` so the histories stay reconciled.

Thank you for contributing! 🛰️