本文へ移動
cccskills
無料GitHub で公開

release

Cut a release of the Lyrion Dashboard. Use this whenever a task is about shipping a new version — bumping the version, tagging, the Release workflow, or how the Android APK and the Docker image get built and published. Covers the single source of truth for the version, the manual `Release` → publish → `android.yml` + `docker.yml` chain, the versionCode packing, and the F-Droid constraint that keeps versions static in source. Reach for it before touching `VERSION`, `release.yml`, or the Android `versionName`/`versionCode`.

インストール方法を見る

含まれるファイル(1)

  • SKILL.md5.9 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

Cutting a release

Releases are cut manually from the GitHub UI, not on every merge. The flow is deliberately two-step: a workflow prepares a draft, a human publishes it, and publishing triggers the APK build and the image push.

The version, and its two mirrors

The semantic version lives in three places that must agree, and the release workflow is what keeps them in sync:

  1. VERSION (repo root) — the single source of truth for the web app. config.py reads it at import and exposes it on /health.
  2. android/app/build.gradle.kts — versionName (the semver) and versionCode (an integer). These are static literals on purpose: F-Droid builds from the source at the tag and parses them from this file, so they must be committed, not computed at build time.
  3. The git tag vX.Y.Z.

versionCode packs the semver as X*10000 + Y*100 + Z (e.g. 0.2.1 → 201, 1.0.0 → 10000). Keep that formula — the Release workflow and the gradle comment both rely on it.

The Release workflow (.github/workflows/release.yml)

Triggered by workflow_dispatch with inputs version (X.Y.Z, no leading v) and prerelease. It:

  1. Validates the version is semver and the tag doesn't already exist.
  2. Bumps versionCode/versionName in build.gradle.kts (via sed, failing loudly if nothing changed) and writes VERSION.
  3. Commits chore(release): vX.Y.Z, tags vX.Y.Z, pushes both.
  4. Opens a draft GitHub release with auto-generated notes (--generate-notes), grouped by PR label into Features (feat), Fixes (fix), Dependencies and Other changes per .github/release.yml.

It stops there. Nothing is published automatically.

Publishing → the APK (.github/workflows/android.yml)

Publishing the draft fires android.yml on release: published, which:

  • Re-checks the tag matches versionName in build.gradle.kts (F-Droid coherence guard) — a mismatch fails the job.
  • Builds the release APK, which must be signed. The four repo secrets ANDROID_KEYSTORE_BASE64, ANDROID_KEYSTORE_PASSWORD, ANDROID_KEY_ALIAS, ANDROID_KEY_PASSWORD are all required: the job decodes the keystore, checks it opens with that password and holds that alias, and fails if any of it is missing or malformed. It never falls back to unsigned.
  • Verifies the built APK with apksigner and fails if Gradle produced app-release-unsigned.apk — a release published unsigned in the past (v0.2.1) because this check did not exist.
  • Attaches lyrion-dashboard-vX.Y.Z.apk to the release.

Note the ref subtlety: on a release event GitHub runs the workflow as it exists at the tagged commit. Recreating a release on an old tag replays that tag's workflows, not the current ones — so a fix to android.yml or docker.yml only takes effect for tags cut after it landed (or after the tag is moved).

android.yml also builds a debug APK on every push touching android/** (uploaded as a workflow artifact, not attached to a release).

Publishing → the image (.github/workflows/docker.yml)

The same release: published event builds the container image and pushes it to ghcr.io/werdeil/lyrion-dashboard for linux/amd64 and linux/arm64, tagged X.Y.Z, X.Y and latest — or X.Y.Z alone when the release is marked as a pre-release, so the moving tags stay on the last stable one. It re-checks the tag against VERSION first, the way android.yml checks it against versionName. Authentication is the job's own GITHUB_TOKEN with packages: write — there is no secret to provision.

No released tag is ever rebuilt, latest included: each is built once from the tagged commit, so a tag always resolves to the code of the release it names, and a base image fix ships with the next release rather than under a tag users already run. A merge to master publishes dev from unreleased code — never latest. The workflow is two jobs: verify builds linux/amd64 into the runner's own daemon and smoke-tests it against /health, and only then does publish build the multi-arch image and push it, so a broken build never reaches a tag. A PR touching the Dockerfile or requirements.txt runs verify alone. linux/arm64 is covered by the build succeeding, not by a run.

Doing a release

  1. Decide the new X.Y.Z.
  2. Run the Release workflow (Actions → Release → Run workflow) with that version; tick prerelease if applicable.
  3. Review the auto-generated notes on the resulting draft release, edit if needed, then Publish.
  4. Confirm android.yml ran and the signed APK is attached, and that docker.yml pushed the image.

Prefer this path over hand-editing versions: doing it manually risks the three mirrors drifting, which the F-Droid coherence guard will reject at release time. If you must bump by hand (e.g. prepping a PR), change all three consistently and keep the versionCode packing formula.

Checklist

  • Version bumped in VERSION and versionName/versionCode in android/app/build.gradle.kts, with versionCode = X*10000 + Y*100 + Z.
  • Tag vX.Y.Z matches versionName (else android.yml fails).
  • Release cut via the workflow, reviewed as a draft, then published.
  • Signed APK attached (signing secrets present) — verify on the release.
  • Image pushed to GHCR for both architectures, with the X.Y.Z, X.Y and latest tags (X.Y.Z alone for a pre-release).

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

同じリポジトリのスキル

概要と使いどころ

add-route

無料

Add or modify a Flask endpoint in the Lyrion Dashboard. Use this whenever a task adds a new URL/route, a JSON API endpoint, or a page — anything that registers a handler in `routes/`. Covers the repo's route → service → test layering, input validation, caching headers, security headers, i18n wiring, and the exact test pattern, so a new endpoint matches how `routes/` already works instead of reinventing the structure.

日本語の概要は準備中です。原文の説明を表示しています。

werdeil/lyrion-dashboard32026年10月15日 更新

android

無料

Work on the Android app — the thin WebView wrapper in `android/`. Use this whenever a task touches the Kotlin sources, the Gradle build, the WebView shell, the native settings screen, LMS server auto-discovery, the JS↔native bridge, app strings/i18n, or the Android CI/lint. Covers the "shell only, UI lives on the web" principle, the debug/release signing split, the static versioning F-Droid needs, and the min/target SDKs, so changes fit the wrapper.

日本語の概要は準備中です。原文の説明を表示しています。

werdeil/lyrion-dashboard32026年10月15日 更新

covers

無料

Work on album artwork — reading an image's dimensions, and embedding a folder's cover file into the tags of its tracks. Use this whenever a task touches `services/artwork.py`, the cover half of `services/tags.py`, or `scripts/embed_covers.py` / `embed_covers_cron.sh`. Covers why Lyrion shows the embedded artwork and never the folder file, how covers are compared, why images are never re-encoded, and what embedding costs in rewritten files.

日本語の概要は準備中です。原文の説明を表示しています。

werdeil/lyrion-dashboard32026年10月15日 更新

database

無料

Read data from Lyrion's SQLite databases — library stats, stored lyrics, album covers, recent plays. Use this whenever a task queries `library.db` or `persist.db`, adds or changes a statistic, or touches `services/database.py`. Covers the read-only connection model (RO open + `ATTACH persist.db`), the key tables, the `play_counts` view over the Alternative Play Count plugin, the single-flight stats cache, and why the app must never write to these DBs. Reach for it before writing any SQL against the Lyrion databases.

日本語の概要は準備中です。原文の説明を表示しています。

werdeil/lyrion-dashboard32026年10月15日 更新

frontend

無料

Work on the dashboard's frontend — the vanilla JS/CSS page with no framework or bundler. Use this whenever a task touches `static/nowplaying.js`, `static/style.css`, the Jinja templates (`templates/nowplaying.html`, `_icons.html`), the accent-color tinting, the karaoke lyrics sync, the now-playing poll, or the empty-state mosaic / recent-plays pile. Covers how the page is wired, how it reads i18n and data from the server, the ESLint gate, and the Android bridge, so changes match the existing patterns.

日本語の概要は準備中です。原文の説明を表示しています。

werdeil/lyrion-dashboard32026年10月15日 更新

i18n

無料

Add, change, or translate user-facing text in the Lyrion Dashboard, which ships bilingual FR/EN. Use this whenever a task introduces a new visible string (a label, tooltip, aria-label, empty state, stat name), changes wording, or touches the README or a `docs/` page — so every string lands in both languages and the EN/FR documentation pairs stay in sync. Covers `i18n.py`, how templates and JS consume translations, and the parity rule.

日本語の概要は準備中です。原文の説明を表示しています。

werdeil/lyrion-dashboard32026年10月15日 更新

werdeil のスキルをすべて見る

このスキルの問題を報告する