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,11 @@
{
"actions": [
"After this PR merges, cut the first release from main: keep the charts at 0.1.0 (or run deploy/charts/set-version.sh <X.Y.Z> in a chore(release) PR and merge it), then push the tag: git tag -a v0.1.0 -m 'Coldframe 0.1.0' && git push origin v0.1.0.",
"Watch the Release workflow run for that tag and confirm it is green and that the GitHub Release v0.1.0 has coldframe-hub/node-0.1.0.bin and .elf, every <chart>-0.1.0.tgz, SHA256SUMS and the grouped notes with the docs/build/apps.md link.",
"Confirm ghcr.io/escendit/coldframe/{server,web,migrations,keycloak}:0.1.0 exist, then download the Release assets and run sha256sum --check --strict SHA256SUMS."
],
"parked_at": "2026-10-19",
"run_id": "20261012-230921-d74a",
"spec_file": "_bmad-output/implementation-artifacts/spec-10-1-releases-with-one-version-and-firmware-binaries.md",
"story_key": "10-1-releases-with-one-version-and-firmware-binaries"
}
126 changes: 126 additions & 0 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
# Checks the adopter docs (Story 10.2): every relative link and referenced repository path
# resolves, and every command block of the build guide (docs/build/*.md) either runs against the
# firmware crates (`<!-- ci:run <dir> -->`, builds only) or, when it needs a board
# (`<!-- ci:hardware -->`), names only real espflash subcommands. Nothing is ever flashed, and no
# external link is fetched. Not a required status check.
#
# Actions are pinned to a commit; the comment names the release. The firmware setup of the
# `commands` job is copied from the `firmware` job of ci.yml: keep the two in step.
name: Docs

on:
pull_request:
paths:
# Everything the docs link to or mirror (the toolchain pins of ci.yml and release.yml).
- "docs/**"
- "hardware/**"
- "README.md"
- "LICENSE"
- ".gitignore"
- "apps/**"
- "packages/**"
- "deploy/**"
- "tests/**"
- "aspire/**"
- ".github/workflows/**"
push:
branches:
- main
paths:
- "docs/**"
- "hardware/**"
- "README.md"
- "LICENSE"
- ".gitignore"
- "apps/**"
- "packages/**"
- "deploy/**"
- "tests/**"
- "aspire/**"
- ".github/workflows/**"
workflow_dispatch:

permissions:
contents: read

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}

jobs:
links:
name: Links
runs-on: ubuntu-24.04
timeout-minutes: 10
steps:
- name: Check out
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false

- name: Test the doc checks
run: docs/test.sh

- name: Check links and paths
run: docs/check-links.sh

commands:
name: Commands
runs-on: ubuntu-24.04
timeout-minutes: 60
env:
# The same pins as the `firmware` job of ci.yml.
ESPUP_VERSION: "0.17.1"
ESP_TOOLCHAIN_VERSION: "1.95.0.0"
ESPFLASH_VERSION: "4.5.0"
steps:
- name: Check out
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false

# cmake and ninja for the mbedTLS rebuild; libudev for espflash.
- name: Install build tools
run: sudo apt-get update && sudo apt-get install --yes --no-install-recommends cmake ninja-build libudev-dev pkg-config

- name: Cache
uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2
with:
workspaces: |
apps/rs/hub
apps/rs/node
key: espup-${{ env.ESPUP_VERSION }}-esp-${{ env.ESP_TOOLCHAIN_VERSION }}-espflash-${{ env.ESPFLASH_VERSION }}
cache-bin: "true"
cache-directories: |
~/.rustup/toolchains/esp
~/export-esp.sh

# On the runner's stable toolchain: apps/rs/hub/rust-toolchain.toml names `esp`, which is not
# installed until the next step.
- name: Install espup and espflash
working-directory: apps/rs/hub
run: |
if [[ "$(espup --version 2>/dev/null)" != "espup ${ESPUP_VERSION}" ]]; then
rustup run stable cargo install espup --version "${ESPUP_VERSION}" --locked --force
fi
if [[ "$(espflash --version 2>/dev/null)" != "espflash ${ESPFLASH_VERSION}" ]]; then
rustup run stable cargo install espflash --version "${ESPFLASH_VERSION}" --locked --force
fi

- name: Install the esp toolchain
working-directory: apps/rs/hub
env:
GITHUB_TOKEN: ${{ github.token }}
run: |
if [[ ! -f "${HOME}/export-esp.sh" ]] || ! rustup run esp rustc --version | grep -qF "(${ESP_TOOLCHAIN_VERSION})"; then
espup install --toolchain-version "${ESP_TOOLCHAIN_VERSION}" --targets esp32s3 --export-file "${HOME}/export-esp.sh"
fi
rustup run esp rustc --version

# The guide's own install block runs too; with the tools above already in place it reuses them.
- name: Run the documented commands
env:
GITHUB_TOKEN: ${{ github.token }}
run: |
docs/check-commands.sh --list
docs/check-commands.sh
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ and deployment all live in this repository.
## Start here

- [Developer quickstart](docs/quickstart.md): run the local stack and every test suite.
- [Build guide](docs/build/README.md): build, flash and add your own Node and Hub.
- [Hardware design](hardware/README.md): schematics, BOM, wiring, enclosure and probe sealing.
- [Hub radio coexistence spike](docs/spikes/hub-radio-coexistence.md): what the Hub's radio can do at once.

## Repository layout
Expand All @@ -21,7 +23,7 @@ and deployment all live in this repository.
| [`tests/`](tests) | All tests, split by language |
| [`aspire/`](aspire) | The local development stack, which is also the integration-test host |
| [`deploy/`](deploy) | Helm charts, Fleet bundles and a Compose example |
| [`hardware/`](hardware) | Schematics, PCB and enclosure |
| [`hardware/`](hardware) | The reference Node and Hub design: schematics, BOM, wiring, enclosure |
| [`docs/`](docs) | Guides and references |

## License
Expand Down
16 changes: 16 additions & 0 deletions _bmad-output/implementation-artifacts/deferred-work.md
Original file line number Diff line number Diff line change
Expand Up @@ -930,3 +930,19 @@ location: tests/cs/server.integration/Edge/InvitationTests.cs
source_spec: `spec-9-1-invite-someone-to-my-site.md`
reason: InvitationTests asserts the link equals the configured redirect URI and accepts by signing in on Keycloak directly; the web app is not part of the AppHost, so link -> web sign-in -> invitation required action is unverified end to end. Settle by running the web app against the AppHost and following the Mailpit link.
status: open

### DW-120: A v* tag on any commit publishes; the documented "tag only from main" rule is not enforced by the workflow.
origin: spec-deferred 7aa938ff9d90
location: .github/workflows/release.yml (mode job)
source_spec: `spec-10-1-releases-with-one-version-and-firmware-binaries.md`
severity: low
reason: Pre-existing since Story 2.1 (deploy/images/README.md already asks for a tag ruleset); the mode job accepts any v* push.
status: open

### DW-121: The tag-only branches of release.yml (ghcr login, --push, imagetools summary, verify, gh release create, --prerelease) never run in the dry run.
origin: spec-deferred bce640467f2d
location: .github/workflows/release.yml (publish, release jobs)
source_spec: `spec-10-1-releases-with-one-version-and-firmware-binaries.md`
severity: medium
reason: dry_run is true for every non-push event, so these steps are skipped on PRs; only a real v* tag exercises them. Owed as an operator action (cut the first release and check it).
status: open
Loading