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
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,11 @@ jobs:
run: pnpm release:check

- name: Validate Home Assistant integration syntax
run: python3 -m compileall -q homeassistant/integration
run: python3 -m compileall -q custom_components/virtual_carillon

- name: Validate JSON metadata
run: |
python3 -m json.tool homeassistant/integration/manifest.json >/dev/null
python3 -m json.tool custom_components/virtual_carillon/manifest.json >/dev/null
python3 -m json.tool hacs.json >/dev/null

container:
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/publish-app.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,11 @@ jobs:
run: pnpm release:check -- "${RELEASE_VERSION#v}"

- name: Validate Home Assistant integration syntax
run: python3 -m compileall -q homeassistant/integration
run: python3 -m compileall -q custom_components/virtual_carillon

- name: Package HACS integration release
run: |
cd homeassistant/integration
cd custom_components/virtual_carillon
zip -r ../../virtual_carillon.zip . -x '__pycache__/*' '*.pyc'

- name: Publish GitHub release with HACS asset
Expand Down
4 changes: 2 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,15 +57,15 @@ Run the same combined checks locally with `pnpm ci:check` before requesting revi

## Development deployment helper

`scripts/push-live.sh` is available for testing Home Assistant integration changes on a configured remote Docker installation. It type-checks the project, copies the current working tree’s `homeassistant/integration` directory into the target Home Assistant container’s `/config/custom_components/virtual_carillon` location over SSH, restarts the container, and waits for it to become healthy.
`scripts/push-live.sh` is available for testing Home Assistant integration changes on a configured remote Docker installation. It type-checks the project, copies the current working tree’s `custom_components/virtual_carillon` directory into the target Home Assistant container’s `/config/custom_components/virtual_carillon` location over SSH, restarts the container, and waits for it to become healthy.

It reads `REMOTE_HOST` and `HA_CONTAINER` from a local ignored `dev.env` file. This is a development convenience, not a substitute for CI or the release process. Check the current branch, working tree, remote host, and target container before running it. It does not deploy the engine container or publish a release.

`scripts/reset-daily.sh` is another deployment helper. It clears Automatic-hymn history for today or a supplied date on the hosted engine. It is useful when testing selection repeatedly, but it changes persistent runtime state and should not be used casually on a shared installation.

## Releases

Release versions must agree in `package.json`, `homeassistant/integration/manifest.json`, `homeassistant/app/config.yaml`, and `Dockerfile`. Run:
Release versions must agree in `package.json`, `custom_components/virtual_carillon/manifest.json`, `add-on/config.yaml`, and `Dockerfile`. Run:

```bash
pnpm release:check
Expand Down
5 changes: 2 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ COPY package.json pnpm-lock.yaml ./
RUN pnpm install --prod --frozen-lockfile

FROM runtime-deps AS runtime
ARG BUILD_VERSION=0.1.0-beta.2
ARG BUILD_VERSION=0.1.0-beta.3
ARG BUILD_ARCH=amd64
LABEL \
io.hass.version="${BUILD_VERSION}" \
Expand All @@ -34,9 +34,8 @@ LABEL \
org.opencontainers.image.licenses="MIT"
COPY --from=build /app/engine/dist ./engine/dist
COPY engine/bin ./engine/bin
COPY homeassistant ./homeassistant
COPY README.md LICENSE ./
COPY homeassistant/app/entrypoint.mjs ./engine/bin/virtual-carillon-app-entrypoint.mjs
COPY add-on/entrypoint.mjs ./engine/bin/virtual-carillon-app-entrypoint.mjs
RUN mkdir -p /app/.data/cache
EXPOSE 9876
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Virtual Carillon

<p align="center">
<img src="homeassistant/integration/brand/logo@2x.png" alt="Virtual Carillon" width="480">
<img src="custom_components/virtual_carillon/brand/logo@2x.png" alt="Virtual Carillon" width="480">
</p>

Virtual Carillon turns your speakers into a programmable Church carillon.
Expand All @@ -20,7 +20,7 @@ You can also run the carillon on its own from the command line or connect to it

Most people will use Virtual Carillon with [Home Assistant](https://www.home-assistant.io/getting-started/), a free, self-hosted home-automation system. The included Home Assistant Integration provides a user-friendly GUI to interact with Virtual Carillon. We also provide Virtual Carillon as a standalone app for advanced users who are comfortable working from the command line and don't want to use Home Assistant.

[HACS](https://hacs.xyz/docs/use/) (Home Assistant Community Store) is the recommended way to install the Home Assistant integration. Releases include the HACS package; the repository keeps its source under `homeassistant/integration` so no HACS-specific top-level source directory is needed. If HACS is unavailable, use the manual installation fallback below.
[HACS](https://hacs.xyz/docs/use/) (Home Assistant Community Store) is the recommended way to install the Home Assistant integration. The integration is stored in the standard top-level `custom_components/virtual_carillon` directory, and releases include the HACS package. If HACS is unavailable, use the manual installation fallback below.

For either Home Assistant path, you must have at least one working Home Assistant `media_player` (speaker) before setting up Virtual Carillon.

Expand All @@ -46,7 +46,7 @@ Use this path when your Home Assistant installation has **Settings → Apps**. I
- Add `https://github.com/HPaulson/virtual-carillon` as an **Integration**, then choose **Download** for the latest release.
- Restart Home Assistant when HACS asks.

If HACS is unavailable, manually copy this repository’s `homeassistant/integration` directory to `/config/custom_components/virtual_carillon/`, then restart Home Assistant.
If HACS is unavailable, manually copy this repository’s `custom_components/virtual_carillon` directory to `/config/custom_components/virtual_carillon/`, then restart Home Assistant.

5. Open **Settings → Devices & services → Add integration**, search for **Virtual Carillon**, and enter:

Expand Down Expand Up @@ -90,7 +90,7 @@ Use this path when Home Assistant itself runs in a Docker container. Virtual Car
- Add `https://github.com/HPaulson/virtual-carillon` as an **Integration**, then choose **Download** for the latest release.
- Restart Home Assistant when HACS asks.

If HACS is unavailable, manually copy this repository’s `homeassistant/integration` directory to `/config/custom_components/virtual_carillon/`, then restart Home Assistant.
If HACS is unavailable, manually copy this repository’s `custom_components/virtual_carillon` directory to `/config/custom_components/virtual_carillon/`, then restart Home Assistant.

6. Open **Settings → Devices & services → Add integration**, search for **Virtual Carillon**, and enter:

Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion homeassistant/app/config.yaml → add-on/config.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: Virtual Carillon
version: 0.1.0-beta.2
version: 0.1.0-beta.3
slug: virtual_carillon
description: Virtual Carillon turns your speakers into a programmable carillon. Play Westminster Chimes, the Angelus, and liturgically-appropriate Catholic hymns.
url: https://github.com/HPaulson/virtual-carillon
Expand Down
File renamed without changes.
File renamed without changes
File renamed without changes
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"domain": "virtual_carillon",
"name": "Virtual Carillon",
"version": "0.1.0-beta.2",
"version": "0.1.0-beta.3",
"documentation": "https://github.com/HPaulson/virtual-carillon",
"issue_tracker": "https://github.com/HPaulson/virtual-carillon/issues",
"codeowners": [],
Expand Down
10 changes: 5 additions & 5 deletions docs/development.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ node engine/dist/cli/index.js schedule show

### `scripts/push-live.sh`

This script deploys the current working tree’s engine and Home Assistant integration to a remote Docker-based installation. It runs pnpm typecheck, archives `homeassistant/integration`, installs it into Home Assistant’s runtime `/config/custom_components/virtual_carillon` location, builds the engine image on the remote host for its architecture, and force-recreates the engine through its existing Compose project. It then restarts Home Assistant and waits for the Home Assistant health check. The engine’s persistent data volume is preserved and not modified. This is useful for live-testing the integration, though a local Home Assistant instance may also be used. The first run may take several minutes because the image installs FFmpeg and its dependencies.
This script deploys the current working tree’s engine and Home Assistant integration to a remote Docker-based installation. It runs pnpm typecheck, archives `custom_components/virtual_carillon`, installs it into Home Assistant’s runtime `/config/custom_components/virtual_carillon` location, builds the engine image on the remote host for its architecture, and force-recreates the engine through its existing Compose project. It then restarts Home Assistant and waits for the Home Assistant health check. The engine’s persistent data volume is preserved and not modified. This is useful for live-testing the integration, though a local Home Assistant instance may also be used. The first run may take several minutes because the image installs FFmpeg and its dependencies.

Create a local, ignored `dev.env` with at least:

Expand Down Expand Up @@ -168,8 +168,8 @@ Keep the major boundaries intact: audio synthesis, the asset library, persistenc
The project version is duplicated intentionally for the package, Home Assistant integration, Home Assistant app, and container metadata. These values must agree in:

- `package.json` (`version`);
- `homeassistant/integration/manifest.json` (`version`);
- `homeassistant/app/config.yaml` (`version`); and
- `custom_components/virtual_carillon/manifest.json` (`version`);
- `add-on/config.yaml` (`version`); and
- `Dockerfile` (`ARG BUILD_VERSION`).

Check them with:
Expand Down Expand Up @@ -218,8 +218,8 @@ The standard Home Assistant path is speaker-agnostic. The integration turns a re
| `engine/src/library/` | Bundled assets, imported recordings, hymn catalog, metadata, and rendering. |
| `engine/src/liturgical/` | LitCal retrieval and caching, taxonomy, conditions, and hymn queries. |
| `engine/src/scheduling/` and `engine/src/database/` | Schedule validation, matching, claims, events, and completed-hymn history. |
| `homeassistant/integration/` | Config flow, schedule runner, media source, services, sensor, and branding. |
| `homeassistant/app/` | Home Assistant Supervisor app definition and entrypoint. |
| `custom_components/virtual_carillon/` | Config flow, schedule runner, media source, services, sensor, and branding. |
| `add-on/` | Home Assistant Supervisor app definition and entrypoint. |

Schedules with Home Assistant `mediaPlayers` are claimed by the integration. Schedules with native `outputs`, or no target list, are evaluated by the engine’s native timer. Claims use the local date, minute, and schedule revision to avoid duplicate delivery after restarts.

Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "virtual-carillon",
"version": "0.1.0-beta.2",
"version": "0.1.0-beta.3",
"description": "A virtual carillon with Catholic bells, hymn arrangements, and Home Assistant integration.",
"license": "MIT",
"repository": {
Expand All @@ -26,7 +26,7 @@
"files": [
"engine/dist",
"engine/bin",
"homeassistant",
"add-on",
"README.md",
"LICENSE"
],
Expand Down
4 changes: 2 additions & 2 deletions scripts/check-ci.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ async function check(label, callback) {
}

function checkPythonMetadata() {
run('python3', ['-m', 'compileall', '-q', 'homeassistant/integration']);
run('python3', ['-m', 'json.tool', 'homeassistant/integration/manifest.json']);
run('python3', ['-m', 'compileall', '-q', 'custom_components/virtual_carillon']);
run('python3', ['-m', 'json.tool', 'custom_components/virtual_carillon/manifest.json']);
run('python3', ['-m', 'json.tool', 'hacs.json']);
}

Expand Down
6 changes: 4 additions & 2 deletions scripts/check-release.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,14 @@ if (packageJson.version !== expectedVersion) {
failures.push(`package.json is ${packageJson.version}, expected ${expectedVersion}`);
}

const manifest = JSON.parse(await readFile('homeassistant/integration/manifest.json', 'utf8'));
const manifest = JSON.parse(
await readFile('custom_components/virtual_carillon/manifest.json', 'utf8'),
);
if (manifest.version !== expectedVersion) {
failures.push(`Home Assistant manifest is ${manifest.version}, expected ${expectedVersion}`);
}

const appConfig = await readFile('homeassistant/app/config.yaml', 'utf8');
const appConfig = await readFile('add-on/config.yaml', 'utf8');
if (!new RegExp(`^version: ${expectedVersion.replaceAll('.', '\\.')}$`, 'm').test(appConfig)) {
failures.push(`Home Assistant app config does not declare ${expectedVersion}`);
}
Expand Down
4 changes: 2 additions & 2 deletions scripts/push-live.sh
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ COPYFILE_DISABLE=1 tar \
--exclude='__pycache__' \
--exclude='**/*.pyc' \
-czf "$LOCAL_ARCHIVE" \
-C "$ROOT_DIR/homeassistant/integration" \
-C "$ROOT_DIR/custom_components/virtual_carillon" \
.
scp "$LOCAL_ARCHIVE" "$REMOTE_HOST:$REMOTE_ARCHIVE"
ssh "$REMOTE_HOST" "docker cp '$REMOTE_ARCHIVE' '$HA_CONTAINER:/tmp/virtual-carillon-ha.tar.gz'"
Expand All @@ -67,7 +67,7 @@ COPYFILE_DISABLE=1 tar \
--exclude='*.sqlite-wal' \
-czf "$ENGINE_ARCHIVE" \
-C "$ROOT_DIR" \
Dockerfile package.json pnpm-lock.yaml tsconfig.json eslint.config.mjs .prettierrc.json scripts engine homeassistant README.md LICENSE
Dockerfile package.json pnpm-lock.yaml tsconfig.json eslint.config.mjs .prettierrc.json scripts engine add-on README.md LICENSE
scp "$ENGINE_ARCHIVE" "$REMOTE_HOST:$REMOTE_ENGINE_ARCHIVE"

echo "==> Rebuilding and restarting the Virtual Carillon engine"
Expand Down
Loading