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
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ name: CI

on:
pull_request:
branches:
- develop
- main
types:
- opened
- reopened
Expand Down
121 changes: 5 additions & 116 deletions .github/workflows/edge-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: Publish Dev Builds
on:
push:
branches:
- main
- develop

permissions:
contents: read
Expand All @@ -16,7 +16,6 @@ concurrency:
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository_owner }}/navet
HACS_REPOSITORY: awesomestvi/navet-hacs

jobs:
tier-1-release-critical:
Expand Down Expand Up @@ -60,30 +59,22 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: main

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 22

- name: Read committed dev version
- name: Compute dev version
id: dev_version
run: |
VERSION=$(node --input-type=module -e 'import fs from "node:fs"; const content = fs.readFileSync("platform/home-assistant/addons/navet-dev/config.yaml", "utf8"); const match = content.match(/^version:\s*"?(.*?)"?\s*$/m); if (!match?.[1]) { throw new Error("Unable to read Navet Dev add-on version"); } process.stdout.write(match[1].trim());')
echo "value=$VERSION" >> "$GITHUB_OUTPUT"

- name: Validate committed dev version
env:
DEV_VERSION: ${{ steps.dev_version.outputs.value }}
run: |
PACKAGE_VERSION=$(node -p 'JSON.parse(require("node:fs").readFileSync("package.json", "utf8")).version')
DEV_VERSION="${PACKAGE_VERSION}-dev.$(date -u +%Y%m%d.%H%M%S)"
if [[ ! "$DEV_VERSION" =~ ^${PACKAGE_VERSION//./\\.}-dev\.[0-9]{8}\.[0-9]{6}$ ]]; then
echo "Expected platform/home-assistant/addons/navet-dev/config.yaml version to match ${PACKAGE_VERSION}-dev.YYYYMMDD.HHMMSS but received: $DEV_VERSION"
echo "Run: pnpm release:dev-version"
echo "Expected computed Navet Dev add-on version to match ${PACKAGE_VERSION}-dev.YYYYMMDD.HHMMSS but received: $DEV_VERSION"
exit 1
fi
echo "value=$DEV_VERSION" >> "$GITHUB_OUTPUT"

- name: Capture release sha
id: release_sha
Expand Down Expand Up @@ -248,105 +239,3 @@ jobs:
NAVET_RELEASE_CHANNEL=edge
NAVET_BUILD_VERSION=${{ steps.tags.outputs.build_version }}
tags: ${{ steps.tags.outputs.value }}

sync-hacs:
name: Sync HACS Integration
runs-on: ubuntu-latest
needs:
- tier-1-release-critical
- prepare-dev-release
concurrency:
group: hacs-sync-navet-hacs-main
cancel-in-progress: false
environment: edge
if: github.repository == 'awesomestvi/navet'
env:
NAVET_HACS_APP_ID: ${{ secrets.NAVET_HACS_APP_ID }}
NAVET_HACS_APP_PRIVATE_KEY: ${{ secrets.NAVET_HACS_APP_PRIVATE_KEY }}

steps:
- name: Check HACS sync secrets
id: hacs_preflight
run: |
if [[ -z "${NAVET_HACS_APP_ID}" || -z "${NAVET_HACS_APP_PRIVATE_KEY}" ]]; then
echo "enabled=false" >> "$GITHUB_OUTPUT"
echo "HACS sync secrets are missing; skipping sync job steps."
exit 0
fi

echo "enabled=true" >> "$GITHUB_OUTPUT"

- name: Checkout monorepo
if: steps.hacs_preflight.outputs.enabled == 'true'
uses: actions/checkout@v4
with:
ref: ${{ needs.prepare-dev-release.outputs.release_sha }}

- name: Create GitHub App token for HACS sync
if: steps.hacs_preflight.outputs.enabled == 'true'
id: hacs_app_token
uses: actions/create-github-app-token@v1
with:
app-id: ${{ secrets.NAVET_HACS_APP_ID }}
private-key: ${{ secrets.NAVET_HACS_APP_PRIVATE_KEY }}
owner: ${{ github.repository_owner }}
repositories: navet-hacs

- name: Checkout HACS repository
if: steps.hacs_preflight.outputs.enabled == 'true'
uses: actions/checkout@v4
with:
repository: ${{ env.HACS_REPOSITORY }}
ref: main
path: navet-hacs
token: ${{ steps.hacs_app_token.outputs.token }}

- name: Setup pnpm
if: steps.hacs_preflight.outputs.enabled == 'true'
uses: pnpm/action-setup@v4

- name: Setup Node.js
if: steps.hacs_preflight.outputs.enabled == 'true'
uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm
cache-dependency-path: pnpm-lock.yaml

- name: Install dependencies
if: steps.hacs_preflight.outputs.enabled == 'true'
run: pnpm install --frozen-lockfile

- name: Export HACS payload
if: steps.hacs_preflight.outputs.enabled == 'true'
env:
NAVET_HACS_EXPORT_ROOT: ${{ github.workspace }}/navet-hacs
run: node scripts/export-hacs-integration.mjs

- name: Commit and push HACS sync
if: steps.hacs_preflight.outputs.enabled == 'true'
working-directory: navet-hacs
run: |
set -euo pipefail
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add -A
if git diff --cached --quiet; then
echo "No HACS changes to publish."
exit 0
fi
git commit -m "chore: sync edge export from ${GITHUB_SHA::7}"
for attempt in 1 2 3; do
git fetch origin main
git rebase origin/main
if git push origin HEAD:main; then
exit 0
fi

if [[ "$attempt" -eq 3 ]]; then
echo "HACS sync push failed after ${attempt} attempts."
exit 1
fi

sleep $((attempt * 5))
done
110 changes: 110 additions & 0 deletions .github/workflows/published-branch-sync.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
name: Sync Published Branch Integrations

on:
push:
branches:
- main

permissions:
contents: read

concurrency:
group: published-branch-sync-${{ github.ref }}
cancel-in-progress: true

env:
HACS_REPOSITORY: awesomestvi/navet-hacs

jobs:
sync-hacs:
name: Sync HACS Integration
runs-on: ubuntu-latest
if: github.repository == 'awesomestvi/navet'
env:
NAVET_HACS_APP_ID: ${{ secrets.NAVET_HACS_APP_ID }}
NAVET_HACS_APP_PRIVATE_KEY: ${{ secrets.NAVET_HACS_APP_PRIVATE_KEY }}

steps:
- name: Check HACS sync secrets
id: hacs_preflight
run: |
if [[ -z "${NAVET_HACS_APP_ID}" || -z "${NAVET_HACS_APP_PRIVATE_KEY}" ]]; then
echo "enabled=false" >> "$GITHUB_OUTPUT"
echo "HACS sync secrets are missing; skipping sync job steps."
exit 0
fi

echo "enabled=true" >> "$GITHUB_OUTPUT"

- name: Checkout monorepo
if: steps.hacs_preflight.outputs.enabled == 'true'
uses: actions/checkout@v4

- name: Create GitHub App token for HACS sync
if: steps.hacs_preflight.outputs.enabled == 'true'
id: hacs_app_token
uses: actions/create-github-app-token@v1
with:
app-id: ${{ secrets.NAVET_HACS_APP_ID }}
private-key: ${{ secrets.NAVET_HACS_APP_PRIVATE_KEY }}
owner: ${{ github.repository_owner }}
repositories: navet-hacs

- name: Checkout HACS repository
if: steps.hacs_preflight.outputs.enabled == 'true'
uses: actions/checkout@v4
with:
repository: ${{ env.HACS_REPOSITORY }}
ref: main
path: navet-hacs
token: ${{ steps.hacs_app_token.outputs.token }}

- name: Setup pnpm
if: steps.hacs_preflight.outputs.enabled == 'true'
uses: pnpm/action-setup@v4

- name: Setup Node.js
if: steps.hacs_preflight.outputs.enabled == 'true'
uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm
cache-dependency-path: pnpm-lock.yaml

- name: Install dependencies
if: steps.hacs_preflight.outputs.enabled == 'true'
run: pnpm install --frozen-lockfile

- name: Export HACS payload
if: steps.hacs_preflight.outputs.enabled == 'true'
env:
NAVET_HACS_EXPORT_ROOT: ${{ github.workspace }}/navet-hacs
run: node scripts/export-hacs-integration.mjs

- name: Commit and push HACS sync
if: steps.hacs_preflight.outputs.enabled == 'true'
working-directory: navet-hacs
run: |
set -euo pipefail
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add -A
if git diff --cached --quiet; then
echo "No HACS changes to publish."
exit 0
fi
git commit -m "chore: sync published export from ${GITHUB_SHA::7}"
for attempt in 1 2 3; do
git fetch origin main
git rebase origin/main
if git push origin HEAD:main; then
exit 0
fi

if [[ "$attempt" -eq 3 ]]; then
echo "HACS sync push failed after ${attempt} attempts."
exit 1
fi

sleep $((attempt * 5))
done
2 changes: 1 addition & 1 deletion docs/VERSIONING.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Navet currently uses pre-`1.0` semantic versioning.
- current version: `0.7.0`
- current phase: public beta
- shared release line: standalone app, custom panel, and add-on ship from the same tagged version
- release channels: `edge` from `main`, `dev` as nightly add-on builds, `beta` from prerelease tags, `latest` from stable tags
- release channels: `edge` from `develop`, `dev` as nightly add-on builds, `beta` from prerelease tags, `latest` from stable tags

## Scheme

Expand Down
50 changes: 30 additions & 20 deletions docs/agents/release-and-publishing.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,34 +25,43 @@ This file defines release workflow constraints and publishing behavior for Navet

Recommended operator flow:

1. Decide whether the change is `patch`, `minor`, or `prerelease`.
2. Bump `package.json`.
3. Run `pnpm release:version-sync`.
4. Fetch Linear issues in the `Ready for Release` workflow state and use them as the release-note
1. Merge feature work into `develop`.
2. Decide whether the change is `patch`, `minor`, or `prerelease`.
3. Bump `package.json` on `develop`.
4. Run `pnpm release:version-sync`.
5. Fetch Linear issues in the `Ready for Release` workflow state and use them as the release-note
source. If the release has no matching issues, draft the changelog from commit history instead.
5. Add a matching `CHANGELOG.md` section for the release version. The GitHub Release workflow
6. Add a matching `CHANGELOG.md` section for the release version. The GitHub Release workflow
publishes this section as the release notes that HACS/Home Assistant can show before users
update.
6. Do not require maintainers to prebuild Home Assistant panel assets for HACS or release
7. Do not require maintainers to prebuild Home Assistant panel assets for HACS or release
publishing. The export and release workflows build them automatically.
Do not ask for `pnpm build:ha-panel` during local release prep unless the user explicitly wants
a separate manual panel build outside the normal release path.
7. Add or update the matching `platform/home-assistant/addons/navet/CHANGELOG.md` entry for every
8. Add or update the matching `platform/home-assistant/addons/navet/CHANGELOG.md` entry for every
versioned add-on release.
Keep it concise and add-on-facing, even when it mostly mirrors the main app changelog.
8. If the release meaning changed, update [../VERSIONING.md](../VERSIONING.md).
9. Run `pnpm release:check`.
10. Tag the monorepo commit with a version tag such as `v0.3.1-beta.1`, `v0.3.1-rc.1`, or
9. If the release meaning changed, update [../VERSIONING.md](../VERSIONING.md).
10. Run `pnpm release:check`.
11. Promote the selected `develop` commit to `main`.
12. Tag the promoted `main` commit with a version tag such as `v0.3.1-beta.1`, `v0.3.1-rc.1`, or
`v0.3.1`.
11. Push the tag to GitHub to trigger
13. Push the tag to GitHub to trigger
[../../.github/workflows/release.yml](../../.github/workflows/release.yml).
12. The tagged release workflow validates the committed release surfaces, packages the committed
14. The tagged release workflow validates the committed release surfaces, packages the committed
custom panel assets, and attaches `navet-panel-<tag>.tar.gz` to the GitHub release.
13. The tagged release workflow also syncs `awesomestvi/navet-hacs/main` and refreshes the matching
15. The tagged release workflow also syncs `awesomestvi/navet-hacs/main` and refreshes the matching
`awesomestvi/navet-hacs` tag.
14. For developer hardware testing from `main`, use
16. For developer hardware testing from `develop`, use
[../../.github/workflows/edge-publish.yml](../../.github/workflows/edge-publish.yml).

Branch flow:

- feature branch -> PR into `develop`
- `develop` owns preview and dev-channel automation
- `main` is release and published-branch only
- hotfix branches start from `main`, then merge back into `main` and `develop`

## Release Note Style

Release notes must be issue-led and concise. Fetch Linear first, then draft the changelog from the
Expand Down Expand Up @@ -139,7 +148,7 @@ internal, or release-only changes into the fewest useful user-facing bullets.
- Publish and release workflows should require Tier 1 validation before shipping.
- Tagged releases should build the custom-panel artifact in workflow before creating the GitHub
release.
- Pushes to `main` and tagged releases should also sync the exported HACS payload into
- Pushes to the published `main` branch and tagged releases should also sync the exported HACS payload into
`awesomestvi/navet-hacs/main`.
- Tagged releases should also create or refresh the matching Git tag in `awesomestvi/navet-hacs`
so both repositories expose the same release tag name.
Expand All @@ -154,14 +163,15 @@ internal, or release-only changes into the fewest useful user-facing bullets.
## Publishing Rules

- Cloudflare Pages deploys the demo at `/demo/` and Storybook at `/storybook/` from the website bundle.
- Cloudflare Pages builds directly from the repo; GitHub Pages is retired and there is no GitHub Pages or GitHub deploy workflow for the website bundle.
- Pushes to `main` publish edge app images: `ghcr.io/awesomestvi/navet:edge`, temporary `dev`,
- Cloudflare Pages builds directly from the `develop` branch; GitHub Pages is retired and there is no GitHub Pages or GitHub deploy workflow for the website bundle.
- Pushes to `develop` publish edge app images: `ghcr.io/awesomestvi/navet:edge`, temporary `dev`,
and `sha-*`.
- Standalone app prerelease tags publish the exact tag, `beta`, and `sha-*`.
- Standalone app stable tags publish the exact tag, `X.Y`, `latest`, and `sha-*`.
- Pushes to `main` publish the committed `Navet Dev` add-on version such as
`0.x.y-dev.YYYYMMDD.HHMMSS`, plus moving `edge`, temporary `dev`, and `sha-*` tags.
- Before pushing `main`, refresh that committed dev version locally with `pnpm release:dev-version`.
- Pushes to `develop` compute and publish a fresh `Navet Dev` add-on version such as
`0.x.y-dev.YYYYMMDD.HHMMSS` from the integration branch commit SHA.
- The published `main` branch remains the Home Assistant repository source of truth, so it should
only move when the corresponding dev or release artifacts are already ready for users.
- Tagged releases also update `awesomestvi/navet-hacs/main` and sync the same Git tag there.
- Tagged releases rebuild the committed custom-panel output and attach the downloadable panel
archive to the GitHub release.
Expand Down
Loading
Loading