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
9 changes: 5 additions & 4 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Before making structural changes, read:

## Current scope: phase 1

Build **the core, the Discord adapter, and the Mastodon publisher (outbound only)**. Do not add Telegram, a database or account linking unless a human asks for it. Design for them, but don't build them. **Terraform:** bootstrap (`infra/bootstrap`, #8) is applied; the Container Apps module, `dev` (`infra/envs/dev`, #9, live) and `prod` (`infra/envs/prod`, #12) are in repo. **Do not apply prod** (`just tf-apply prod` refuses unless `PIXEL_APPLY_PROD=1`) and do not write prod secrets. **CD:** `just deploy-dev` rolls Azure `dev`; merges to `main` publish GHCR only. Prod and the docs site ship from the Release workflow (`workflow_dispatch` on `main`, Environment `prod` for Azure). Never copy the Mini / Pixel Dev Discord token into prod. Do **not** start Pixel locally on the same token while `pixel-dev` is up. Do **not** add Postgres or any database; access, schedules and planned linking are files. Do not treat old GitHub issues as ground truth if they disagree with this file, `docs/architecture.md` Deployment, `docs/infra.md`, or `docs/runbook.md`.
Build **the core, the Discord adapter, and the Mastodon publisher (outbound only)**. Do not add Telegram, a database or account linking unless a human asks for it. Design for them, but don't build them. **Terraform:** bootstrap (`infra/bootstrap`, #8) is applied; the Container Apps module, `dev` (`infra/envs/dev`, #9, live) and `prod` (`infra/envs/prod`, #12) are in repo. **Do not apply prod** (`just tf-apply prod` refuses unless `PIXEL_APPLY_PROD=1`) and do not write prod secrets. **CD:** `just deploy dev` rolls Azure `dev`; merges to `main` publish GHCR only. Prod and the docs site ship from the Release workflow (`workflow_dispatch` on `main`, Environment `prod` for Azure). Never copy the Mini / Pixel Dev Discord token into prod. Do **not** start Pixel locally on the same token while `pixel-dev` is up. Do **not** add Postgres or any database; access, schedules and planned linking are files. Do not treat old GitHub issues as ground truth if they disagree with this file, `docs/architecture.md` Deployment, `docs/infra.md`, or `docs/runbook.md`.

## Project at a glance

Expand Down Expand Up @@ -42,13 +42,14 @@ just bump # cut [Unreleased] into a dated version and bump package.j
just tf-validate # terraform fmt -check and validate bootstrap + envs/dev
just tf-plan dev # plan the dev stack (needs Azure login; does not apply)
just tf-apply dev # apply the dev stack — only when a maintainer says so
just deploy-dev # local GHCR push + Azure pixel-dev (never prod; do not also just dev on that token)
just deploy dev # local GHCR push + Azure pixel-dev (never prod; do not also just dev on that token)
just register dev # slash commands on Pixel Dev / a test guild (.env.dev or .env)
just register prod # slash commands on the production guild (.env.prod, PIXEL_ENV=prod)
just ha-devices dev # pick HA devices and push them to that env's devices.yaml on Azure (also prod)
just env dev # where an env lives on Azure (names only); every laptop tool reads them from scripts/envs.ts
```

If you need a new repeatable task, add a `just` recipe instead of documenting a raw command.
If you need a new repeatable task, add a `just` recipe instead of documenting a raw command. A recipe or script that acts on `dev` or `prod` takes the env as an argument and gets everything about it from [`scripts/envs.ts`](scripts/envs.ts): Azure names, the env file and the guards (prod, subscription). TypeScript tools call `loadTarget` (`scripts/target.ts`); recipes `eval "$(pnpm exec tsx scripts/env.ts shell <env>)"`. Don't spell a subscription, resource group, vault or storage account anywhere else (a test checks the justfile).

## Layout

Expand All @@ -70,7 +71,7 @@ src/
config/ # *.example.yaml committed; real admins.yaml / members.yaml gitignored
data/ # runtime state; gitignored. Safe to delete EXCEPT schedules.yaml (the scheduled posts)
content/info/ # markdown for /info topics, one file per topic; PUBLIC, reviewed
scripts/ # register-commands, validate-config, changelog check/bump
scripts/ # envs (the one definition of dev/prod), register-commands, validate-config, changelog check/bump
docs/ # architecture, identity, infra, Home Assistant setup, ADRs, runbook;
# also the VitePress website: see docs/AGENTS.md before changing it
CHANGELOG.md # Keep a Changelog 1.1.0; most PRs add an Unreleased entry
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ Until 1.0.0, releases stay on 0.x: `Added` bumps minor, `Fixed`/`Changed` (and t
- The Discord DM sent when a capability is granted or revoked now really has mentions turned off. It was sent with `allowedMentions`, a field the Discord API ignores, instead of `allowed_mentions`.
- The Sentry heartbeat no longer runs when `PIXEL_ENV=local`. A laptop running `just dev` with a DSN used to check in to a shared `pixel-local` cron monitor, which opened an issue about ten minutes after anyone stopped it. Startup now logs `heartbeat.off` with the reason. `pixel-dev` and `pixel-prod` are unchanged.

### Changed

- Laptop tooling now shares one definition of each environment ([#116](https://github.com/pixelbar/pixel/issues/116)). `scripts/envs.ts` holds every Azure name (subscription, resource group, Container App, Key Vault, file share), the env file and the guards, and `just pull`/`push`, `secrets-pull`/`push`, `ha-devices`, `register`, `command-access`, `restart`, `deploy` and `tf-apply` all take them from there. New `just env dev|prod` shows where an environment lives. `just --list` is grouped (develop, environments, config, terraform, release, docs). `just deploy dev` replaces `just deploy-dev`, which still works for now; `just deploy prod` refuses because prod ships from the Release workflow. Discord tools load their env file in TypeScript rather than through a bash helper, still dropping anything `just` loaded from `.env`.

## [0.17.0] - 2026-10-15

### Added
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -158,16 +158,16 @@ Run `just` to list every recipe.
| `just tf-apply dev` | Apply `dev` — only when a maintainer says so |
| `just tf-plan prod` | Plan the `prod` stack |
| `PIXEL_APPLY_PROD=1 just tf-apply prod` | Apply `prod` — maintainer only; agents must not |
| `just deploy-dev` | Local GHCR push, roll onto Azure `pixel-dev`, Sentry release, `just register dev` (never prod) |
| `just deploy dev` | Local GHCR push, roll onto Azure `pixel-dev`, Sentry release, `just register dev` (never prod) |
| `just sentry-release` | Upload source maps; skipped unless Sentry org/token are set |

## CI

Every pull request and push to `main` runs [CI](.github/workflows/ci.yml). It runs `just check` (lint, type-check, tests with coverage thresholds) and the production build, and checks that the Docker image builds. Pull requests also run a [changelog](.github/workflows/changelog.yml) job that fails unless `CHANGELOG.md` changed, or the PR has the `skip-changelog` label. [Terraform](.github/workflows/terraform.yml) validates bootstrap, `infra/envs/dev` and `infra/envs/prod` only when `infra/`, that workflow, or the `justfile` change, then plans each env only if `infra/` Terraform files changed (fails closed without Environment `ARM_*`). [CD](.github/workflows/cd.yml) on `main` publishes `ghcr.io/pixelbar/pixel:<sha>` and uploads Sentry source maps (fails closed without org/token). It does **not** deploy prod. A [Release](.github/workflows/release.yml) is run by a maintainer on `main`: it cuts Unreleased, tags `vX.Y.Z`, opens a GitHub Release, publishes that image, rolls `pixel-prod` after Environment `prod` approval, and publishes the docs site. Azure `dev` is `just deploy-dev` from a local build. No Terraform apply on merge.
Every pull request and push to `main` runs [CI](.github/workflows/ci.yml). It runs `just check` (lint, type-check, tests with coverage thresholds) and the production build, and checks that the Docker image builds. Pull requests also run a [changelog](.github/workflows/changelog.yml) job that fails unless `CHANGELOG.md` changed, or the PR has the `skip-changelog` label. [Terraform](.github/workflows/terraform.yml) validates bootstrap, `infra/envs/dev` and `infra/envs/prod` only when `infra/`, that workflow, or the `justfile` change, then plans each env only if `infra/` Terraform files changed (fails closed without Environment `ARM_*`). [CD](.github/workflows/cd.yml) on `main` publishes `ghcr.io/pixelbar/pixel:<sha>` and uploads Sentry source maps (fails closed without org/token). It does **not** deploy prod. A [Release](.github/workflows/release.yml) is run by a maintainer on `main`: it cuts Unreleased, tags `vX.Y.Z`, opens a GitHub Release, publishes that image, rolls `pixel-prod` after Environment `prod` approval, and publishes the docs site. Azure `dev` is `just deploy dev` from a local build. No Terraform apply on merge.

## Deployment

Terraform **bootstrap** (`infra/bootstrap`, #8) is applied: remote state and GitHub OIDC. Container App **`pixel-dev`** is live (#9). **`infra/envs/prod`** (#12) is in repo; coding agents must not apply it. `just deploy-dev` (local GHCR push) rolls Azure `dev`; merges to `main` publish GHCR only. Prod and the docs site ship from a [Release](.github/workflows/release.yml). **No database.** See the [infra overview](docs/infra.md) (diagrams), [Deployment](docs/architecture.md#deployment), the [dev README](infra/envs/dev/README.md), the [prod README](infra/envs/prod/README.md), [ADR 0012](docs/adr/0012-prod-environment.md) and [ADR 0013](docs/adr/0013-release-workflow.md). If `pixel-dev` is up, do not also run `just dev` on the same Pixel Dev token.
Terraform **bootstrap** (`infra/bootstrap`, #8) is applied: remote state and GitHub OIDC. Container App **`pixel-dev`** is live (#9). **`infra/envs/prod`** (#12) is in repo; coding agents must not apply it. `just deploy dev` (local GHCR push) rolls Azure `dev`; merges to `main` publish GHCR only. Prod and the docs site ship from a [Release](.github/workflows/release.yml). **No database.** See the [infra overview](docs/infra.md) (diagrams), [Deployment](docs/architecture.md#deployment), the [dev README](infra/envs/dev/README.md), the [prod README](infra/envs/prod/README.md), [ADR 0012](docs/adr/0012-prod-environment.md) and [ADR 0013](docs/adr/0013-release-workflow.md). If `pixel-dev` is up, do not also run `just dev` on the same Pixel Dev token.

## Running and operating Pixel

Expand Down
Loading
Loading