Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
ba9a417
Test speed improvements
kristin-kronstain-brown Jul 29, 2026
0396ef0
Added timeout
kristin-kronstain-brown Jul 29, 2026
51bac7e
Added concurrency
kristin-kronstain-brown Jul 29, 2026
7e8edd8
Added leak tests
kristin-kronstain-brown Jul 29, 2026
ad6c299
Tab redesign
kristin-kronstain-brown Jul 29, 2026
caeab5c
Fix
kristin-kronstain-brown Jul 29, 2026
a0cd2d8
Remove old process
kristin-kronstain-brown Jul 30, 2026
27a969c
Fixed padding
kristin-kronstain-brown Jul 30, 2026
0346f7a
Tabs tweaks
kristin-kronstain-brown Jul 30, 2026
e40eed1
Sidebar: link single-page tab landings so they stay reachable
kristin-kronstain-brown Jul 30, 2026
9ba301d
Mobile drawer: keep open across a section/version switch
kristin-kronstain-brown Jul 30, 2026
dfa1613
Mobile drawer: AJAX-swap section/version instead of reloading
kristin-kronstain-brown Jul 30, 2026
b2f1ff6
Updates
kristin-kronstain-brown Jul 30, 2026
e358612
Table mobile fix
kristin-kronstain-brown Jul 30, 2026
062db21
Table mobile fix
kristin-kronstain-brown Jul 30, 2026
d8ea5ba
Version fix
kristin-kronstain-brown Jul 30, 2026
836bd0e
Updated changelog
kristin-kronstain-brown Jul 30, 2026
eef6305
Release testing
kristin-kronstain-brown Jul 30, 2026
3d33873
Added release skill
kristin-kronstain-brown Jul 31, 2026
7d312d8
Added go mod instructions
kristin-kronstain-brown Jul 31, 2026
77e0cf2
Merge remote-tracking branch 'origin/main' into kkb-0.1.24
kristin-kronstain-brown Jul 31, 2026
6097c5b
Fix link color in banner
kristin-kronstain-brown Jul 31, 2026
8f74ac5
Fixes
kristin-kronstain-brown Aug 3, 2026
28a0a12
Updated test
kristin-kronstain-brown Aug 3, 2026
333c30a
Updated date
kristin-kronstain-brown Aug 3, 2026
9ba8e1a
Cut back changelog details
kristin-kronstain-brown Aug 3, 2026
2c1e59c
Added hide sidebar
kristin-kronstain-brown Aug 3, 2026
295194f
Updates from review
kristin-kronstain-brown Aug 4, 2026
f4a32c9
Added fix
kristin-kronstain-brown Aug 4, 2026
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
129 changes: 129 additions & 0 deletions .claude/skills/release/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
---
name: release
description: Release workflow for docs-theme-extras — the consumer repos that pin the module and get bumped on every release, how beta tags are cut and pushed (the one push Claude may do itself), and the CHANGELOG section ordering. Use when cutting a beta tag, releasing a version, bumping the extras pin in consumer repos, or writing a changelog entry.
---

# docs-theme-extras release workflow

This skill documents the recurring release chores for `docs-theme-extras`: cutting
beta tags, bumping the module pin across the consumer repos, and ordering the
CHANGELOG. All repos below are sibling clones under `~/Documents/GitHub`.

## Consumer repos that pin the module

These repos import `github.com/solo-io/docs-theme-extras` and get their pin bumped
on essentially every release. Update **all six** together unless told otherwise.

| Nickname |
|----------|
| agw oss |
| agr oss |
| ambientmesh |
| docs (Solo.io hub) |
| kgw oss |
| kagent oss (note the `docs-site/` subdir, not repo root) |

The pin appears as `require github.com/solo-io/docs-theme-extras vX.Y.Z // indirect`.
Consumer bumps are deliberate, one version at a time — never a floating ref.

### Bumping the pin

Run from inside each consumer repo, using the version-pinned Hugo binary
(`hugo160`, not bare `hugo`):

```bash
hugo160 mod get github.com/solo-io/docs-theme-extras@vX.Y.Z
```

This updates both `go.mod` and `go.sum` with the correct hash. Then verify:

```bash
grep "docs-theme-extras vX.Y.Z " go.mod
grep "docs-theme-extras vX.Y.Z h1:" go.sum # hash should match across all repos
```

Notes:
- `hugo mod get` leaves the **old version's lines in `go.sum`**. They're harmless
(go.sum keeps historical hashes) and the build resolves fine. If a clean go.sum
matters, remove the two stale `vX.Y.(Z-1)` lines **by hand** — do NOT reach for
`tidy`.
- **Never run `hugo160 mod tidy` (or `go mod tidy`) to prune the pin.** In the
`docs` hub these modules (`docs-theme-extras`, `kgateway.dev`, `ambientmesh.io`)
are declared as **Hugo module imports in the hugo config, not Go source
imports**, so the Go tooling treats them as unused and `tidy` **deletes the
entire `require` block** — not just churn, it drops all three pins and breaks the
build. Same trap applies to any consumer whose extras pin is `// indirect`. If
you run it by reflex, `git checkout go.mod go.sum` and redo with `hugo mod get`
only.
- Leave the changes local. Do **not** commit or push consumer-repo changes
automatically — that's a user action (see the push rule below).

## Beta tags (and the one push Claude may do itself)

Tag convention: `vX.Y.Z-beta.N`. Betas increment `N` (`-beta.1`, `-beta.2`, …);
the final release drops the suffix (`vX.Y.Z`). Both beta and final tags are cut
the same way, from the current release branch (e.g. `release-next`).

**Pushing a tag is the ONLY push Claude is allowed to do on its own.** Everything
else (branch commits, `git push` of branches, opening PRs) waits for an explicit
user instruction — see `feedback_no_auto_push`.

Steps:

```bash
# 1. Confirm the working tree is clean and the branch is in sync with origin
git status -sb # want a clean tree, no ahead/behind on the branch

# 2. Pick the next tag by looking at existing tags
git tag --sort=-creatordate | head

# 3. Create an annotated tag on HEAD and push just that tag
git tag -a vX.Y.Z-beta.N -m "vX.Y.Z-beta.N"
git push origin vX.Y.Z-beta.N
```

There is no `make` release target; tagging is manual. After the tag lands on
GitHub, the Go module proxy can fetch it, and the consumer-repo bump above will
resolve.

## CHANGELOG ordering and entry rules

`CHANGELOG.md` lists **newest version first** (`## [vX.Y.Z] — YYYY-MM-DD`).

### Section order within a version

Order the `###` sections by type, most disruptive first:

1. **Breaking** — anything that requires content edits in consumer repos
2. **Add** / **Feature** — new shortcode, partial, or capability
3. **Fix** — non-breaking fix
4. **Test harness** / chore — last

(Recent versions drifted into author/commit order — e.g. v0.1.22 lists Fixes
before its Add. Re-sort to the order above when editing; don't copy the drift.)

### Writing an entry

The rules are also stated at the top of `CHANGELOG.md` — follow them:

- **Lead with *why*** — the bug, missing behavior, or failure mode — not just
what changed, so a reader gets the motivation without the diff.
- **Link a production page** that shows the bug or the fix. For additive features
with no single defect page, link a representative page where the new behavior is
observable and say how to verify it (view-source, a validator, etc.).
This link is required on every entry (see `feedback_changelog_production_link`).
- **State how it was verified** — the local build, the Playwright spec added, the
fixture exercised.
- Note that the change takes effect **when a consumer bumps its extras pin** (or,
for the `docs` hub where a local override shadows a module file, that a pin bump
alone won't change hub output).

## Typical end-to-end flow

1. Land the change on the release branch; write the CHANGELOG entry (correct
section order + production link + verification).
2. Cut a beta tag (`vX.Y.Z-beta.N`) and push it — allowed.
3. Bump the beta pin in the six consumer repos to smoke-test.
4. When ready, cut the final `vX.Y.Z` tag and push it — allowed.
5. Bump the six consumer repos to the final `vX.Y.Z`. Leave those edits local for
the user to commit/PR.
90 changes: 80 additions & 10 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,21 @@ on:
branches: [main]
workflow_dispatch:

# Supersede in-progress runs on the same PR: a new push to a PR branch cancels
# its own older, still-running run instead of stacking a second one. Keyed on
# github.ref so each PR cancels only its own runs, never another PR's. A hung
# run (see the install-step timeout below) is likewise cleared by the next push
# rather than lingering to the job timeout.
#
# Deliberately NOT applied to push:main. Cancellation there is keyed on the
# branch, not the commit, so two merges in quick succession would cancel the
# first one's run — leaving a merged commit on main with no completed sweep.
# Main is also the only place some coverage is guaranteed to have run, so its
# runs must be allowed to finish.
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}

permissions:
contents: read

Expand All @@ -20,10 +35,36 @@ env:
NODE_VERSION: '20'

jobs:
test-all:
brand:
runs-on: ubuntu-latest
timeout-minutes: 15

# The two brand layers are independent, so run them as parallel matrix
# jobs instead of sequentially in one `make test-all`. Wall-clock ~halves
# at the cost of a second runner. fail-fast off so an OSS failure doesn't
# cancel the enterprise job (and vice versa) — you want both reports.
strategy:
fail-fast: false
matrix:
brand: [oss, enterprise]

env:
# All three engines run on PRs, not just on main. cross-browser.spec.ts is
# a single 11-test file, the binaries come from the actions/cache below, so
# the marginal cost next to a ~1600-test suite is small — and a PR is where
# someone actually reads a failure. Restricting it to push:main would make
# main the only place an engine-specific regression can surface, i.e. after
# merge. If PR wall-clock needs trimming later, take it from the install
# step, not from dropping engines.
PW_BROWSERS: 'chromium firefox webkit'
# ubuntu-latest is a 4-core runner for public repos. The brand matrix above
# already halves wall-clock by giving each brand its own runner; also
# raising the worker count oversubscribes those cores, and firefox is the
# engine that shows it first (observed locally as page.goto timeouts on the
# everything page under high parallelism, clean at low). Keep this at or
# below the core count.
PW_WORKERS: '4'

steps:
- uses: actions/checkout@v7

Expand Down Expand Up @@ -59,43 +100,72 @@ jobs:
- name: Install npm dependencies
run: npm ci || npm install

# Every run installs the same three engines now, so the key needs no
# browser-set component (the PW_BROWSER_TAG split existed only to keep a
# PR's chromium-only cache from being restored by a main run that needed
# all three).
- name: Cache Playwright browsers
id: playwright-cache
uses: actions/cache@v6
with:
path: ~/.cache/ms-playwright
key: ${{ runner.os }}-playwright-${{ hashFiles('package-lock.json') }}

# timeout-minutes guards the `sudo apt-get` that --with-deps/install-deps
# runs: on a bad runner it can hang on a dpkg lock or a stalled mirror.
# The browser download + apt normally finishes in <1min, so 5 is generous
# — a genuine hang fails the step fast (and is re-runnable) instead of
# burning the whole 15-min job budget.
- name: Install Playwright browsers
if: steps.playwright-cache.outputs.cache-hit != 'true'
run: npx playwright install --with-deps chromium firefox webkit
timeout-minutes: 5
run: npx playwright install --with-deps ${{ env.PW_BROWSERS }}

- name: Install Playwright OS deps (cache-hit path)
if: steps.playwright-cache.outputs.cache-hit == 'true'
run: npx playwright install-deps
timeout-minutes: 5
run: npx playwright install-deps ${{ env.PW_BROWSERS }}

# Override HUGO=hugo160 (the local convention) with HUGO=hugo (what
# peaceiris/actions-hugo installs the binary as). Run both brand
# variants. test-all chains build-oss + test-oss + build-enterprise
# + test-enterprise.
- name: Run test-all
run: HUGO=hugo make test-all
# peaceiris/actions-hugo installs the binary as). Each matrix job runs a
# single brand: test-<brand> chains build-<brand> + test-<brand>.
- name: Run test-${{ matrix.brand }}
run: HUGO=hugo make test-${{ matrix.brand }}

- name: Upload Playwright HTML report on failure
if: failure()
uses: actions/upload-artifact@v7
with:
name: playwright-report
name: playwright-report-${{ matrix.brand }}
path: playwright-report
retention-days: 7

- name: Upload Hugo build logs on failure
if: failure()
uses: actions/upload-artifact@v7
with:
name: hugo-build-logs
name: hugo-build-logs-${{ matrix.brand }}
path: |
.build-oss.log
.build-enterprise.log
retention-days: 7
if-no-files-found: ignore

# Single stable status context for branch protection. The matrix above reports
# as "brand (oss)" / "brand (enterprise)", so requiring those directly would
# mean re-pointing branch protection every time the matrix changes shape. This
# job collapses them into one required check named `test-all` — the name the
# rule already used before the matrix split.
#
# `if: always()` so this runs even when a matrix leg fails; the step then
# asserts the aggregate result, and `cancelled`/`skipped` fail too (only a
# literal success passes).
test-all:
needs: [brand]
if: always()
runs-on: ubuntu-latest
steps:
- name: Assert every brand leg succeeded
run: |
echo "brand result: ${{ needs.brand.result }}"
[ "${{ needs.brand.result }}" = "success" ]
Loading
Loading