automated release notes
This commit is contained in:
parent
dfa1763e5e
commit
c70d904586
@ -0,0 +1,253 @@
|
|||||||
|
%{
|
||||||
|
title: "Automated release notes with 'demo' skill",
|
||||||
|
author: "Willem van den Ende",
|
||||||
|
tags: ~w(ai),
|
||||||
|
description: "Agents can make release notes, given the right tools and instructions. Showboat, Chrome DevTools MCP were quite easy to use. ",
|
||||||
|
published: true
|
||||||
|
}
|
||||||
|
---
|
||||||
|
|
||||||
|
Yesterday, I added scheduled posts to firehose. I let my coding agent write the [release notes](blog/releases/scheduled-publishing). It is fun to read the release notes like this, and see the screenshots. Do note that a coding agent might not care there is no navigation - it happily will remember the urls and navigate to them, so that is something you might want to double check with exploratory testing :-).
|
||||||
|
|
||||||
|
I've included the full skill below. It is not in the repository, it went straight to my home directory so I can use it in other porjects. This is the second project I have used it in. It helped me earlier do a fairly large archiectural spike for an RFP response, and include screenshots of a working application in the response document. Working software is still a great measure of progress.
|
||||||
|
|
||||||
|
# Demo skill - let your agent generate demos with screenshots for you
|
||||||
|
|
||||||
|
---
|
||||||
|
name: demo
|
||||||
|
description: >-
|
||||||
|
Generate a living demo document proving a feature works. Uses showboat
|
||||||
|
for Markdown assembly with captured command output and rodney for Chrome
|
||||||
|
browser screenshots. Use when the user says "demo this", "show me it works",
|
||||||
|
"create a demo", or after /build completes.
|
||||||
|
argument-hint: "<feature-name> [--scenario <description>] [--plan <path>]"
|
||||||
|
user-invocable: true
|
||||||
|
allowed-tools: Read, Write, Glob, Grep, Bash
|
||||||
|
---
|
||||||
|
|
||||||
|
# Demo
|
||||||
|
|
||||||
|
Role: worker. This command generates a standalone Markdown demo document that proves a feature works, using showboat for document assembly and rodney for browser automation.
|
||||||
|
|
||||||
|
You have been invoked with the `/demo` command.
|
||||||
|
|
||||||
|
## Parse Arguments
|
||||||
|
|
||||||
|
Arguments: $ARGUMENTS
|
||||||
|
|
||||||
|
- Positional: `<feature-name>` (required) — short name or description of the feature to demo
|
||||||
|
- `--scenario <description>`: Explicit demo scenario describing what to show. If omitted, infer from the plan and recent commits.
|
||||||
|
- `--plan <path>`: Path to the plan file. If omitted, search `plans/` for the most recently modified `.md` file with status `implemented` or `approved`.
|
||||||
|
|
||||||
|
## Steps
|
||||||
|
|
||||||
|
### 1. Check tool availability
|
||||||
|
|
||||||
|
Verify showboat and rodney are installed:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
showboat --help 2>/dev/null && echo "showboat: ok" || echo "showboat: missing"
|
||||||
|
rodney --help 2>/dev/null && echo "rodney: ok" || echo "rodney: missing"
|
||||||
|
```
|
||||||
|
|
||||||
|
If either tool is missing, tell the user:
|
||||||
|
|
||||||
|
> One or more demo tools are missing. Install them with:
|
||||||
|
> ```bash
|
||||||
|
> go install github.com/simonw/showboat@latest
|
||||||
|
> go install github.com/simonw/rodney@latest
|
||||||
|
> ```
|
||||||
|
|
||||||
|
Do not proceed until both tools are confirmed available.
|
||||||
|
|
||||||
|
### 2. Gather feature context
|
||||||
|
|
||||||
|
Build an understanding of what to demo from these sources (in priority order):
|
||||||
|
|
||||||
|
1. **Explicit scenario** (`--scenario`): If provided, use as primary guide.
|
||||||
|
2. **Plan file**: Read the plan's Goal, Acceptance Criteria, and completed Steps.
|
||||||
|
3. **Recent commits**: Run `git log --oneline -15` and `git diff main...HEAD --stat` to identify changed files and commit messages.
|
||||||
|
4. **Route map**: Cross-reference changed files against known LiveView routes in the router (`lib/hub_web/router.ex`).
|
||||||
|
|
||||||
|
From these sources, produce a **demo outline**:
|
||||||
|
- **Narrative**: 2-3 sentence description of what the feature does
|
||||||
|
- **Backend evidence**: mix commands, test output, or database queries to run
|
||||||
|
- **UI pages**: which routes to visit and what to look for
|
||||||
|
- **Interactions**: any clicks, form fills, or navigation sequences to perform
|
||||||
|
|
||||||
|
If no plan exists and commits are ambiguous, ask the user for a brief description of what to demo.
|
||||||
|
|
||||||
|
### 3. Check dev server
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -s -o /dev/null -w "%{http_code}" http://localhost:4000/ 2>/dev/null
|
||||||
|
```
|
||||||
|
|
||||||
|
If the server is not reachable:
|
||||||
|
|
||||||
|
> The Phoenix dev server is not running. Start it now?
|
||||||
|
> ```bash
|
||||||
|
> mix phx.server &
|
||||||
|
> ```
|
||||||
|
|
||||||
|
After starting, wait up to 10 seconds and verify connectivity. If it still fails, proceed with backend-only evidence (skip all browser screenshots) and note the limitation in the demo document.
|
||||||
|
|
||||||
|
### 4. Handle authentication
|
||||||
|
|
||||||
|
The app requires authentication for LiveView routes. Before capturing UI screenshots:
|
||||||
|
|
||||||
|
1. Ensure a demo user exists:
|
||||||
|
```bash
|
||||||
|
mix run -e "
|
||||||
|
alias Hub.Accounts
|
||||||
|
case Accounts.get_user_by_email(\"demo@example.com\") do
|
||||||
|
nil -> Accounts.register_user(%{email: \"demo@example.com\", password: \"demodemo1234\"})
|
||||||
|
user -> {:ok, user}
|
||||||
|
end
|
||||||
|
"
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Log in via rodney:
|
||||||
|
```bash
|
||||||
|
rodney start
|
||||||
|
rodney open http://localhost:4000/users/log-in
|
||||||
|
rodney wait "input[name='user[email]']"
|
||||||
|
rodney input "input[name='user[email]']" "demo@example.com"
|
||||||
|
rodney input "input[name='user[password]']" "demodemo1234"
|
||||||
|
rodney click "button[type='submit']"
|
||||||
|
rodney waitidle
|
||||||
|
```
|
||||||
|
|
||||||
|
If login fails, warn and proceed with backend-only evidence.
|
||||||
|
|
||||||
|
### 5. Initialize the demo document
|
||||||
|
|
||||||
|
Slugify the feature name (lowercase, hyphens, no special chars). Then:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
showboat init "demos/demo-$(date +%Y%m%d-%H%M%S)-<slug>.md" "Demo: <Feature Name>"
|
||||||
|
```
|
||||||
|
|
||||||
|
Store the demo file path for use in all subsequent steps.
|
||||||
|
|
||||||
|
### 6. Narrative introduction
|
||||||
|
|
||||||
|
```bash
|
||||||
|
showboat note <demo-file> "## Feature Overview
|
||||||
|
|
||||||
|
<2-3 sentence description derived from the plan or commits.>
|
||||||
|
|
||||||
|
**Branch**: $(git branch --show-current)
|
||||||
|
**Commits**: <N> commits ahead of main
|
||||||
|
**Plan**: <plan file path or 'none'>
|
||||||
|
"
|
||||||
|
```
|
||||||
|
|
||||||
|
### 7. Backend evidence
|
||||||
|
|
||||||
|
Capture backend proof via `showboat exec`. Always include relevant tests. Add narrative notes between evidence blocks explaining what each proves.
|
||||||
|
|
||||||
|
**Test output** (always include):
|
||||||
|
```bash
|
||||||
|
showboat note <demo-file> "## Test Suite"
|
||||||
|
showboat exec <demo-file> bash "mix test <relevant-test-files> --color"
|
||||||
|
showboat note <demo-file> "All <N> tests pass, confirming <specific criterion>."
|
||||||
|
```
|
||||||
|
|
||||||
|
**Compilation check**:
|
||||||
|
```bash
|
||||||
|
showboat note <demo-file> "## Compilation Check"
|
||||||
|
showboat exec <demo-file> bash "mix compile --warnings-as-errors"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Database state** (if relevant to the feature):
|
||||||
|
```bash
|
||||||
|
showboat note <demo-file> "## Database State"
|
||||||
|
showboat exec <demo-file> bash "mix run -e '<query expression>'"
|
||||||
|
```
|
||||||
|
|
||||||
|
### 8. UI screenshots
|
||||||
|
|
||||||
|
For each UI page identified in step 2, navigate with rodney, screenshot, and embed via showboat.
|
||||||
|
|
||||||
|
**Static page capture**:
|
||||||
|
```bash
|
||||||
|
rodney open http://localhost:4000/<route>
|
||||||
|
rodney waitidle
|
||||||
|
rodney screenshot demos/screenshots/<feature>-<page-name>.png
|
||||||
|
|
||||||
|
showboat note <demo-file> "### <Page Name>
|
||||||
|
|
||||||
|
<What this page shows and why it proves the feature works.>"
|
||||||
|
|
||||||
|
showboat image <demo-file> ''
|
||||||
|
```
|
||||||
|
|
||||||
|
**Interactive flow** (form submissions, navigation):
|
||||||
|
```bash
|
||||||
|
showboat note <demo-file> "### Interactive Flow: <Flow Name>"
|
||||||
|
|
||||||
|
# Before state
|
||||||
|
rodney screenshot demos/screenshots/<feature>-before.png
|
||||||
|
showboat image <demo-file> ''
|
||||||
|
|
||||||
|
# Perform interaction
|
||||||
|
rodney click "<selector>"
|
||||||
|
rodney input "<selector>" "<value>"
|
||||||
|
rodney click "<submit-selector>"
|
||||||
|
rodney waitidle
|
||||||
|
|
||||||
|
# After state
|
||||||
|
rodney screenshot demos/screenshots/<feature>-after.png
|
||||||
|
showboat image <demo-file> ''
|
||||||
|
```
|
||||||
|
|
||||||
|
### 9. Acceptance criteria checklist
|
||||||
|
|
||||||
|
If a plan file exists, map each acceptance criterion to evidence:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
showboat note <demo-file> "## Acceptance Criteria Verification
|
||||||
|
|
||||||
|
- [x] <Criterion 1> -- see Test Suite output above
|
||||||
|
- [x] <Criterion 2> -- see <Page Name> screenshot
|
||||||
|
- [x] <Criterion 3> -- see Database State output
|
||||||
|
"
|
||||||
|
```
|
||||||
|
|
||||||
|
If no plan, summarize what was demonstrated and what it proves.
|
||||||
|
|
||||||
|
### 10. Clean up
|
||||||
|
|
||||||
|
```bash
|
||||||
|
rodney stop 2>/dev/null || true
|
||||||
|
```
|
||||||
|
|
||||||
|
### 11. Report results
|
||||||
|
|
||||||
|
Display:
|
||||||
|
```
|
||||||
|
## Demo Complete
|
||||||
|
|
||||||
|
- **Document**: demos/<filename>.md
|
||||||
|
- **Screenshots**: <N> captured in demos/screenshots/
|
||||||
|
- **Evidence**: <N> backend commands, <N> UI screenshots
|
||||||
|
- **Acceptance criteria**: <N>/<M> demonstrated
|
||||||
|
```
|
||||||
|
|
||||||
|
## Error Handling
|
||||||
|
|
||||||
|
- **Tools not installed**: Show `go install` commands. Do not proceed without them.
|
||||||
|
- **Dev server not running**: Offer to start. If startup fails, produce backend-only demo and note the limitation.
|
||||||
|
- **Authentication failure**: Proceed with backend-only evidence. Note skipped UI screenshots in the document.
|
||||||
|
- **Screenshot failure**: Log the error as a note in the demo document, continue with remaining screenshots.
|
||||||
|
- **No plan found**: Infer from git commits and changed files. Ask the user for a description if commits are ambiguous.
|
||||||
|
- **Rodney/Chrome crash**: Run `rodney stop` then `rodney start` to reset. Retry once. If it fails again, degrade to backend-only.
|
||||||
|
|
||||||
|
## Integration
|
||||||
|
|
||||||
|
- `/build` can suggest running `/demo` after a successful build
|
||||||
|
- `/pr` can invoke `/demo` to generate evidence before or after PR creation
|
||||||
|
- `/plan` produces the acceptance criteria this command verifies visually
|
||||||
|
- Beads (`bd`) can reference demo documents as task completion evidence
|
||||||
|
- Reads plan files from `plans/` directory (same format as `/build`)
|
||||||
48
scripts/new-post.sh
Executable file
48
scripts/new-post.sh
Executable file
@ -0,0 +1,48 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
echo "Usage: $0 \"Post Title\" [blog]"
|
||||||
|
echo " blog: engineering (default) or release-notes"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
[[ $# -lt 1 ]] && usage
|
||||||
|
|
||||||
|
title="$1"
|
||||||
|
blog="${2:-engineering}"
|
||||||
|
|
||||||
|
# Title to slug: lowercase, spaces/underscores to hyphens, strip non-alphanumeric
|
||||||
|
slug=$(echo "$title" | tr '[:upper:]' '[:lower:]' | tr ' _' '-' | sed 's/[^a-z0-9-]//g' | sed 's/--*/-/g' | sed 's/^-//;s/-$//')
|
||||||
|
|
||||||
|
year=$(date +%Y)
|
||||||
|
month_day=$(date +%m-%d)
|
||||||
|
dir="app/priv/blog/${blog}/${year}"
|
||||||
|
file="${dir}/${month_day}-${slug}.md"
|
||||||
|
|
||||||
|
# Find repo root
|
||||||
|
cd "$(dirname "$0")/.."
|
||||||
|
|
||||||
|
mkdir -p "$dir"
|
||||||
|
|
||||||
|
if [[ -f "$file" ]]; then
|
||||||
|
echo "File already exists: $file"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
cat > "$file" <<EOF
|
||||||
|
%{
|
||||||
|
title: "${title}",
|
||||||
|
author: "Firehose Team",
|
||||||
|
tags: ~w(),
|
||||||
|
description: "",
|
||||||
|
published: false
|
||||||
|
}
|
||||||
|
---
|
||||||
|
EOF
|
||||||
|
|
||||||
|
echo "Created: $file"
|
||||||
|
|
||||||
|
if [[ -n "${EDITOR:-}" ]] && [[ -t 1 ]]; then
|
||||||
|
exec "$EDITOR" "$file"
|
||||||
|
fi
|
||||||
Loading…
x
Reference in New Issue
Block a user