release: v0.1.6

This commit is contained in:
Joshua Walls 2026-06-22 08:50:12 -04:00
parent fd44432976
commit 0ade0b998a
6 changed files with 272 additions and 71 deletions

View file

@ -1,59 +0,0 @@
name: Release
on:
push:
tags:
- "*"
workflow_dispatch:
permissions:
contents: write
jobs:
package:
name: Package theme
runs-on: ubuntu-latest
steps:
- name: Check out repository
uses: actions/checkout@v4
- name: Validate release version
run: |
VERSION="$(jq -r '.version' manifest.json)"
if [ "$GITHUB_REF_TYPE" = "tag" ]; then
RELEASE_TAG="$GITHUB_REF_NAME"
if [ "$VERSION" != "$RELEASE_TAG" ]; then
echo "manifest.json version ($VERSION) must match tag ($RELEASE_TAG)."
exit 1
fi
else
RELEASE_TAG="$VERSION"
fi
echo "VERSION=$VERSION" >> "$GITHUB_ENV"
echo "RELEASE_TAG=$RELEASE_TAG" >> "$GITHUB_ENV"
- name: Build install zip
run: |
mkdir -p dist/Trailmark
cp manifest.json theme.css dist/Trailmark/
cd dist
zip -r "Trailmark-${VERSION}.zip" Trailmark
- name: Publish GitHub release
env:
GH_TOKEN: ${{ github.token }}
run: |
ZIP="dist/Trailmark-${VERSION}.zip"
if gh release view "$RELEASE_TAG" >/dev/null 2>&1; then
gh release upload "$RELEASE_TAG" "$ZIP" --clobber
else
gh release create "$RELEASE_TAG" "$ZIP" \
--target "$GITHUB_SHA" \
--title "Trailmark ${RELEASE_TAG}" \
--notes "Install zip for Trailmark ${RELEASE_TAG}."
fi

89
.github/workflows/tag-release.yml vendored Normal file
View file

@ -0,0 +1,89 @@
name: Release
on:
pull_request:
types: [closed]
branches: [main]
workflow_dispatch:
inputs:
tag:
description: "Existing release tag to publish manually"
required: true
type: string
jobs:
release:
if: >
github.event_name == 'workflow_dispatch' ||
(github.event.pull_request.merged == true &&
github.base_ref == 'main' &&
startsWith(github.head_ref, 'release/'))
runs-on: ubuntu-latest
permissions:
contents: write
id-token: write
attestations: write
outputs:
tag: ${{ steps.release_ref.outputs.tag }}
steps:
- name: Resolve release ref
id: release_ref
run: |
if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
echo "tag=${{ inputs.tag }}" >> "$GITHUB_OUTPUT"
echo "checkout_ref=${{ inputs.tag }}" >> "$GITHUB_OUTPUT"
else
BRANCH="${{ github.event.pull_request.head.ref }}"
VERSION="${BRANCH#release/}"
echo "tag=$VERSION" >> "$GITHUB_OUTPUT"
echo "checkout_ref=${{ github.event.pull_request.merge_commit_sha }}" >> "$GITHUB_OUTPUT"
fi
- name: Checkout
uses: actions/checkout@v5
with:
ref: ${{ steps.release_ref.outputs.checkout_ref }}
- name: Validate release version
run: |
VERSION="$(jq -r '.version' manifest.json)"
TAG="${{ steps.release_ref.outputs.tag }}"
if [[ "$VERSION" != "$TAG" ]]; then
echo "manifest.json version ($VERSION) must match release tag ($TAG)."
exit 1
fi
echo "VERSION=$VERSION" >> "$GITHUB_ENV"
- name: Build install zip
run: |
rm -rf dist/Trailmark
mkdir -p dist/Trailmark
cp manifest.json theme.css dist/Trailmark/
(
cd dist
zip -qr "Trailmark-${VERSION}.zip" Trailmark
)
- name: Create and push tag
if: ${{ github.event_name != 'workflow_dispatch' }}
run: |
git tag "$VERSION"
git push origin "$VERSION"
- name: Attest install zip
uses: actions/attest@v4
with:
subject-path: dist/Trailmark-${{ steps.release_ref.outputs.tag }}.zip
- name: Create release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ steps.release_ref.outputs.tag }}
body: Install zip for Trailmark ${{ steps.release_ref.outputs.tag }}.
files: dist/Trailmark-${{ steps.release_ref.outputs.tag }}.zip

View file

@ -2,16 +2,27 @@
This file is for maintainers.
## Package a Release
## Local Release Build
Releases are packaged by GitHub Actions when a version tag is pushed. The workflow creates a folder named `Trailmark` containing only `manifest.json` and `theme.css`, then uploads `Trailmark-<version>.zip` to the GitHub Release.
Use `release.sh` to update `manifest.json` and create a local install zip. The zip contains a `Trailmark` folder with only `manifest.json` and `theme.css`.
```sh
git tag 0.1.3
git push origin 0.1.3
./release.sh -version 0.1.6
```
Before publishing a release, confirm that the `version` field in `manifest.json` exactly matches the Git tag. Obsidian community themes expect `0.1.3`, not `v0.1.3`.
The local artifact is written to `dist/Trailmark-<version>.zip`.
## Publish a Release
Publishing follows the same release-branch flow as Forge and Lockblock:
```sh
./release.sh -version 0.1.6 -publish true
```
That creates or updates a `release/<version>` branch, commits the manifest version bump, and pushes the branch. Open a PR from `release/<version>` into `main`. When that PR is merged, `.github/workflows/tag-release.yml` creates the matching tag, builds `Trailmark-<version>.zip`, attests it, and publishes the GitHub Release.
Before publishing a release, confirm that the `version` field in `manifest.json` exactly matches the release branch suffix and final tag. Obsidian community themes expect `0.1.6`, not `v0.1.6`.
## Obsidian Community Theme Entry

View file

@ -1,6 +1,6 @@
{
"name": "Trailmark",
"version": "0.1.5",
"version": "0.1.6",
"minAppVersion": "0.16.0",
"author": "Joshua Walls"
}

157
release.sh Executable file
View file

@ -0,0 +1,157 @@
#!/usr/bin/env zsh
set -e
# =========================================
# Params
# =========================================
# Usage: ./release.sh -version <version> [-publish true|false] [-zip true|false]
# Example: ./release.sh -version 0.1.6
# ./release.sh -version 0.1.6 -publish true
VERSION=""
PUBLISH=false
CREATE_ZIP=true
THEME_NAME="Trailmark"
BRANCH_BASE="main"
while [[ $# -gt 0 ]]; do
case "$1" in
-version) VERSION="$2"; shift 2 ;;
-publish) PUBLISH="$2"; shift 2 ;;
-zip) CREATE_ZIP="$2"; shift 2 ;;
*)
echo "Unknown parameter: $1"
echo "Usage: ./release.sh -version <version> [-publish true|false] [-zip true|false]"
exit 1
;;
esac
done
if [[ -z "$VERSION" ]]; then
echo "Missing required parameter: -version"
echo "Usage: ./release.sh -version <version> [-publish true|false] [-zip true|false]"
exit 1
fi
if [[ "$PUBLISH" != true && "$PUBLISH" != false ]]; then
echo "-publish must be true or false"
exit 1
fi
if [[ "$CREATE_ZIP" != true && "$CREATE_ZIP" != false ]]; then
echo "-zip must be true or false"
exit 1
fi
# =========================================
# Verify dependencies
# =========================================
DEPS=(jq)
if [[ "$PUBLISH" == true ]]; then
DEPS+=(git)
fi
if [[ "$CREATE_ZIP" == true ]]; then
DEPS+=(zip)
fi
for cmd in "${DEPS[@]}"; do
if ! command -v "$cmd" >/dev/null 2>&1; then
echo "Missing dependency: $cmd"
exit 1
fi
done
# =========================================
# Create or enter release branch
# =========================================
BRANCH_NAME="release/${VERSION}"
if [[ "$PUBLISH" == true ]]; then
if ! git diff --quiet || ! git diff --cached --quiet; then
echo "Publish releases require a clean working tree. Commit or stash changes first."
exit 1
fi
git fetch origin "$BRANCH_BASE"
CURRENT_BRANCH=$(git branch --show-current)
if [[ "$CURRENT_BRANCH" == "$BRANCH_NAME" ]]; then
echo "Already on branch: $BRANCH_NAME"
elif [[ "$CURRENT_BRANCH" == "$BRANCH_BASE" ]]; then
if git show-ref --verify --quiet "refs/heads/$BRANCH_NAME"; then
git checkout "$BRANCH_NAME"
echo "Checked out existing branch: $BRANCH_NAME"
else
git checkout -b "$BRANCH_NAME" "origin/$BRANCH_BASE"
echo "Created branch: $BRANCH_NAME"
fi
else
echo "Must run publish from $BRANCH_BASE or $BRANCH_NAME. Currently on: $CURRENT_BRANCH"
exit 1
fi
if ! git merge-base --is-ancestor "origin/$BRANCH_BASE" HEAD; then
echo "$BRANCH_NAME is behind origin/$BRANCH_BASE. Delete and recreate it, or merge origin/$BRANCH_BASE before publishing."
exit 1
fi
fi
# =========================================
# Update manifest.json
# =========================================
TMP=$(mktemp)
jq --indent 4 --arg v "$VERSION" '.version = $v' manifest.json > "$TMP"
mv "$TMP" manifest.json
echo "Updated manifest.json -> $VERSION"
# =========================================
# Package local artifact
# =========================================
if [[ "$CREATE_ZIP" == true ]]; then
rm -rf "dist/${THEME_NAME}"
mkdir -p "dist/${THEME_NAME}"
cp manifest.json theme.css "dist/${THEME_NAME}/"
(
cd dist
zip -qr "${THEME_NAME}-${VERSION}.zip" "${THEME_NAME}"
)
echo "Created dist/${THEME_NAME}-${VERSION}.zip"
fi
if [[ "$PUBLISH" != true ]]; then
echo ""
echo "Local release build finished."
echo "Run with -publish true to create and push a release branch."
exit 0
fi
# =========================================
# Commit release branch
# =========================================
git add manifest.json
if git diff --cached --quiet; then
echo "Nothing to commit - branch is unchanged."
else
git commit -m "release: v${VERSION}"
fi
git push -u origin "$BRANCH_NAME"
git checkout "$BRANCH_BASE"
echo "Switched back to $BRANCH_BASE."
echo ""
echo "Branch pushed: $BRANCH_NAME"
echo ""
echo "Next steps:"
echo " 1. Open a PR from $BRANCH_NAME -> $BRANCH_BASE"
echo " 2. Merge the PR"
echo " 3. git pull origin $BRANCH_BASE"
echo ""
echo "The PR merge can build and publish the GitHub Release."

View file

@ -2908,17 +2908,17 @@ body[data-theme='dark'] {
/* Forge mobile action buttons: keep controls recognizable instead of loose text labels. */
.theme-dark .forge-health-dashboard :is(.forge-health-actions, .forge-health-section-actions, .forge-ms-actions, .forge-button-row),
.theme-light .forge-health-dashboard :is(.forge-health-actions, .forge-health-section-actions, .forge-ms-actions, .forge-button-row) {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
gap: 10px;
align-items: stretch;
display: flex;
flex-wrap: wrap;
gap: 8px;
align-items: center;
}
.theme-dark .forge-health-dashboard :is(.forge-health-actions, .forge-health-section-actions, .forge-ms-actions, .forge-button-row) button:not(.mod-cta):not(.forge-tab-btn),
.theme-dark .forge-health-dashboard button.forge-health-action:not(.mod-cta),
.theme-dark .forge-health-dashboard button.forge-action:not(.mod-cta) {
min-height: 40px;
width: 100%;
width: auto;
padding: 8px 14px;
border: 1px solid var(--trailmark-dark-border);
border-radius: 999px;
@ -2933,7 +2933,7 @@ body[data-theme='dark'] {
.theme-light .forge-health-dashboard button.forge-health-action:not(.mod-cta),
.theme-light .forge-health-dashboard button.forge-action:not(.mod-cta) {
min-height: 40px;
width: 100%;
width: auto;
padding: 8px 14px;
border: 1px solid var(--trailmark-light-border);
border-radius: 999px;
@ -2960,12 +2960,15 @@ body[data-theme='dark'] {
@media (max-width: 700px) {
.forge-health-dashboard :is(.forge-health-actions, .forge-health-section-actions, .forge-ms-actions, .forge-button-row) {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 8px;
align-items: stretch;
}
.forge-health-dashboard :is(.forge-health-actions, .forge-health-section-actions, .forge-ms-actions, .forge-button-row) button {
min-width: 0;
width: 100%;
white-space: normal;
}