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
7 changes: 7 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ updates:
directory: "/infra"
schedule:
interval: "monthly"
groups:
infra:
patterns: ["*"]

- package-ecosystem: "github-actions"
directory: "/"
Expand All @@ -56,3 +59,7 @@ updates:
groups:
actions:
patterns: ["*"]
# As with pip above, advisories ignore the version-update group.
actions-security:
applies-to: security-updates
patterns: ["*"]
40 changes: 40 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# A tag is the deployable unit: bootstrap.sh pins every spoke's vendored
# templates to the latest one. So a tag must carry release notes and pass the
# same checks as a PR before it becomes a release.
#
# To release: add a `## [x.y.z] - date` section to CHANGELOG.md, merge, then
# git tag vx.y.z && git push origin vx.y.z
name: Release

on:
push:
tags: ["v*"]

permissions:
contents: write

jobs:
release:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
# gitleaks scans git history; a shallow clone would pass vacuously.
with:
fetch-depth: 0
- uses: extractions/setup-just@53165ef7e734c5c07cb06b3c8e7b647c5aa16db3 # v4.0.0
# The tag's section of CHANGELOG.md is the release body. No section, no
# release: the tag stays, so fix the changelog on main and re-tag.
- name: Extract release notes
run: |
v="${GITHUB_REF_NAME#v}"
awk -v v="$v" '/^## \[/{p=($0 ~ "^## \\[" v "\\]")} p' CHANGELOG.md \
| tail -n +2 > notes.md
grep -q '[^[:space:]]' notes.md \
|| { echo "error: CHANGELOG.md has no '## [$v]' section" >&2; exit 1; }
# 600, or the exposure guards refuse it as world-readable.
- run: install -m 600 .env.example .env
- run: just check
- run: gh release create "$GITHUB_REF_NAME" --title "$GITHUB_REF_NAME" --notes-file notes.md
env:
GH_TOKEN: ${{ github.token }}
31 changes: 22 additions & 9 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,28 @@ Notable changes to this stack. Format follows

## [0.3.1] - 2026-09-07

### Upgrade

- Re-vendor `compose.telemetry.yml` on each spoke at `v0.3.1` for Alloy
v1.19.2.

### Added

- Pushing a `v*` tag cuts the GitHub release. The workflow takes the tag's
section of this file as the body and refuses a tag without one, or one that
fails `just check`.

### Changed

- **`PrometheusCardinalityHigh` fires at 30k active series, not 100k.** 100k
would have put Prometheus near its 2g `mem_limit` before the warning
arrived; 30k is ~18 spokes of room.
- **New `PrometheusCardinalitySpike`**, on 5,000 new series in 30 minutes: a
label that explodes, which a ceiling cannot catch. One spoke onboarding adds
~1,400.
- Hub images: Grafana 13.2.1, Prometheus v3.14.0, otel-collector-contrib
0.160.0. Dependabot groups the `/infra` provider bumps and action advisories.

### Fixed

- **Prometheus rejected the ingest counters every few minutes**, so five of
Expand All @@ -23,15 +45,6 @@ Notable changes to this stack. Format follows
- `ProjectsUncovered` no longer fires for `demo/demo`, the pair `just demo`
sets. A real project named `demo` is still caught.

### Changed

- **`PrometheusCardinalityHigh` fires at 30k active series, not 100k.** 100k
would have put Prometheus near its 2g `mem_limit` before the warning
arrived; 30k is ~18 spokes of room.
- **New `PrometheusCardinalitySpike`**, on 5,000 new series in 30 minutes: a
label that explodes, which a ceiling cannot catch. One spoke onboarding adds
~1,400.

## [0.3.0] - 2026-09-06

The hub runs the department's telemetry in production, with one spoke on the
Expand Down
2 changes: 1 addition & 1 deletion compose.demo.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ services:
logging: *demo-logging

demo-load:
image: curlimages/curl:8.21.0@sha256:7c12af72ceb38b7432ab85e1a265cff6ae58e06f95539d539b654f2cfa64bb13
image: curlimages/curl:8.22.0@sha256:58adaa4e8dca9c988bae2aba4ab3434a0bb2da16bbe3f92dec39ec7785166777
restart: on-failure
depends_on: [demo-api]
command:
Expand Down
6 changes: 3 additions & 3 deletions compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ services:
logging: *default-logging

otel-collector:
image: otel/opentelemetry-collector-contrib:0.156.0@sha256:125bdbeb7590cc1952c5b3430ecf14063568980c2c93d5b38676cc0446ed8108
image: otel/opentelemetry-collector-contrib:0.160.0@sha256:799dc6cf12c96192af37b5bdba804da8c10b3bc563b43cb90c3f3c58d9572ad6
restart: unless-stopped
depends_on:
otel-queue-init:
Expand Down Expand Up @@ -111,7 +111,7 @@ services:
networks: [backend]

prometheus:
image: prom/prometheus:v3.13.2@sha256:508729e0e2d18e11fd742a5a5ca70e557b940a93948c3c95fd0123a6fd538b69
image: prom/prometheus:v3.14.0@sha256:5ce7540c3c00ef4ab0c9d2c995c6a5b9c421f44b4a115d97a2c7af3b1c21cbb0
restart: unless-stopped
volumes:
- ./config/prometheus.yaml:/etc/prometheus/prometheus.yaml:ro
Expand Down Expand Up @@ -163,7 +163,7 @@ services:
networks: [backend]

grafana:
image: grafana/grafana:13.1.4@sha256:9be3a3ccdb06bcbb127f888b0c4c1d151837443e478887897a63a27d7b348043
image: grafana/grafana:13.2.1@sha256:f772d434e8fab0049deb2b1b30abd43342bcfca1537614aa8d36080232cf4283
restart: unless-stopped
depends_on:
loki:
Expand Down
2 changes: 1 addition & 1 deletion templates/compose.telemetry.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ services:
logging: *default-logging

alloy:
image: grafana/alloy:v1.18.1@sha256:0f4434c92b3e6cdac38bb129b344e1790c246f7b6e2eaffcc16a5fa363240e33
image: grafana/alloy:v1.19.2@sha256:b8ec653c44235fbe910879145dac3597d66b0aaecf60bcbbe82580767771a839
restart: unless-stopped
# Root to read root-only files under the host mounts below. The Docker API is
# behind the proxy, so root here does not imply control of the daemon.
Expand Down