Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Changelog-only tag releases

Status: implemented
Translation: pending
PR: https://github.com/LodyAI/Lody/pull/609

## Abstract

Tag pushes previously built three desktop platforms and published installers and
update feeds, with macOS signing credentials gating all publication. The replacement
opens a draft app-version synchronization PR and creates a changelog-only source
release. Tags remain immutable, so manifest synchronization lands separately on the
default branch. Existing binary releases remain intact, but new releases provide
no installer or auto-update assets.

## Decision and limits

The [workflow](../../../../.github/workflows/release.yml) accepts stable version tags,
enumerates direct app manifests, and uses one version-specific PR branch. It requires
only repository contents and pull-request write permissions; no dependencies,
submodules, signing credentials, packaging runners, or release environment are needed.
It preserves existing release notes and assets on reruns. It intentionally does not
move tags or directly commit version changes to the protected default branch.

The lockfile stores app dependencies rather than app manifest versions, so this
version-only operation does not change pnpm-lock.yaml. Superseded version PRs require
maintainer closure, and the repository must allow Actions to create pull requests.
Validation covers the version-edit operation and workflow structure locally; live
tag publication is not exercised. Full repository checks are limited by this nested
checkout's missing dependencies and uninitialized submodules.

Intent: [tag releases](../../../../specs/tag-releases.md).
286 changes: 0 additions & 286 deletions .github/workflows/release-electron.yml

This file was deleted.

79 changes: 79 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
name: Release

on:
push:
tags:
- 'v*'

permissions:
contents: read

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

jobs:
release:
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
env:
RELEASE_TAG: ${{ github.ref_name }}
GH_TOKEN: ${{ github.token }}
GH_REPO: ${{ github.repository }}
steps:
- name: Validate version
shell: bash
run: |
set -euo pipefail
if [[ ! "$RELEASE_TAG" =~ ^v(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)$ ]]; then
echo "Expected a stable version tag such as v0.90.0"
exit 1
fi
echo "RELEASE_VERSION=${RELEASE_TAG#v}" >> "$GITHUB_ENV"

- name: Checkout default branch for version synchronization
uses: actions/checkout@v4
with:
ref: ${{ github.event.repository.default_branch }}
persist-credentials: false

- name: Synchronize app versions
run: |
node --input-type=module <<'NODE'
import { readdirSync, existsSync, readFileSync, writeFileSync } from 'node:fs'
for (const entry of readdirSync('apps', { withFileTypes: true })) {
if (!entry.isDirectory()) continue
const file = `apps/${entry.name}/package.json`
if (!existsSync(file)) continue
const manifest = JSON.parse(readFileSync(file, 'utf8'))
manifest.version = process.env.RELEASE_VERSION
writeFileSync(file, `${JSON.stringify(manifest, null, 2)}\n`)
}
NODE

- name: Create version synchronization PR
uses: peter-evans/create-pull-request@22a9089034f40e5a961c8808d113e2c98fb63676 # v7
with:
branch: chore/app-versions-${{ env.RELEASE_TAG }}
base: ${{ github.event.repository.default_branch }}
add-paths: apps/*/package.json
commit-message: 'chore: sync app versions to ${{ env.RELEASE_TAG }}'
title: 'chore: sync app versions to ${{ env.RELEASE_TAG }}'
body: |
Synchronize all apps/*/package.json versions to `${{ env.RELEASE_VERSION }}`.
The release tag remains unchanged; this PR updates the default branch only.
draft: true

- name: Create changelog-only GitHub Release
shell: bash
run: |
set -euo pipefail
releases="$(gh api "repos/$GH_REPO/releases" --paginate --jq '.[].tag_name')"
if printf '%s\n' "$releases" | grep -Fxq "$RELEASE_TAG"; then
echo "Release already exists; preserving its notes and assets."
else
gh release create "$RELEASE_TAG" --verify-tag \
--title "Lody OSS $RELEASE_VERSION" --generate-notes
Comment on lines +77 to +78

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Keep changelog releases out of the Latest slot

When a newer stable tag is published after an installer-bearing release, this command creates a normal release that GitHub can automatically mark as Latest; the gh release create --help entry for --latest documents the default as "automatic based on date and version." The packaged macOS client hard-codes /releases/latest/download/appcast.xml in apps/electron/src/main/services/app-updater-sparkle-policy.ts:3-4, but this release uploads no appcast, so installed Macs receive a 404 and can no longer reach even the last preserved binary update. Publish changelog-only releases with --latest=false, or move the updater feed before creating them.

Useful? React with 👍 / 👎.

fi
Loading
Loading