Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
147 commits
Select commit Hold shift + click to select a range
e66a43c
rust: the shared core, and ports as the first widget ported
wiiiimm Aug 22, 2026
6656d05
rust: netwatch ported, and the first honest measurement
wiiiimm Aug 22, 2026
3545af0
rust: latency and matrix, and config loading in the core
wiiiimm Aug 22, 2026
a50783f
rust: link ported
wiiiimm Aug 22, 2026
552ca1b
rust: clocks ported, with the pomodoro
wiiiimm Aug 22, 2026
8cad6ac
rust: the pomodoro's flash and toast, which clocks was missing
wiiiimm Aug 22, 2026
60baf38
netwatch: average rates over a few seconds, not one interval
wiiiimm Aug 22, 2026
a9e92b6
rust: clocks reads the real config, and wears the right colours
wiiiimm Aug 22, 2026
280c9b2
rust: clocks gets its colours, its weekends, and a configurable week
wiiiimm Aug 22, 2026
8346dca
clocks: pin the office countdown at every point in a week
wiiiimm Aug 22, 2026
5802474
clocks: the pomodoro's controls, and a footer that reads properly
wiiiimm Aug 22, 2026
cf59483
clocks: the focus hint says both the step and the length
wiiiimm Aug 22, 2026
2d67119
link: match the Python, which the port had drifted from
wiiiimm Aug 22, 2026
a9d844e
ports: the half of the widget that does something
wiiiimm Aug 22, 2026
8c8214e
netwatch: the second screen, and a rate that was a terabyte a second
wiiiimm Aug 22, 2026
eab4c9f
tests: stop using this machine's own addresses as fixtures
wiiiimm Aug 22, 2026
936971c
clocks, netwatch: the keys and the flags that were left behind
wiiiimm Aug 22, 2026
532b383
help: say what the widgets now do
wiiiimm Aug 22, 2026
abc5956
core: understand both encodings of Home and End
wiiiimm Aug 22, 2026
f35ff96
latency, link: the charts netwatch already draws
wiiiimm Aug 22, 2026
fbbf62c
latency: port the widget, not a sketch of it
wiiiimm Aug 22, 2026
02bd35b
latency: the clock in the header is the machine's, not UTC
wiiiimm Aug 22, 2026
de54351
herdr-panes: port the board that says who is waiting on you
wiiiimm Aug 22, 2026
46f40d4
deployments: the first widget here that holds a secret
wiiiimm Aug 22, 2026
7b7aeda
start: the front door, for a directory that no longer exists
wiiiimm Aug 22, 2026
8caba7b
linear: how the work is moving, across every team
wiiiimm Aug 22, 2026
50ea5a7
start: list linear, and stop advertising a key that cannot exist
wiiiimm Aug 22, 2026
1d9d784
pr: the board, and a day that pr.py has never been counting
wiiiimm Aug 22, 2026
daef40b
github: throughput across every account, counted rather than sampled
wiiiimm Aug 22, 2026
84bc768
tailnet: who is online, and how you are actually reaching them
wiiiimm Aug 22, 2026
1fff3ab
usage: the shared half, and Claude
wiiiimm Aug 23, 2026
82c9d7f
usage: one file per agent, and a summary that draws real bars
wiiiimm Aug 23, 2026
92f3850
usage: read Codex
wiiiimm Aug 23, 2026
60defa3
usage: read Antigravity
wiiiimm Aug 23, 2026
2080dfa
usage: read Grok
wiiiimm Aug 23, 2026
f976edb
usage: read Copilot
wiiiimm Aug 23, 2026
f32de03
usage: read Cursor
wiiiimm Aug 23, 2026
7234113
usage: one midnight across all six calendars
wiiiimm Aug 23, 2026
9b89218
usage: the left key went forwards on the first tab
wiiiimm Aug 23, 2026
0fa08fc
usage: an agent's two screens must not disagree about its quota
wiiiimm Aug 23, 2026
37048f4
core: an unmapped key was arriving as several real ones
wiiiimm Aug 23, 2026
936a3b4
tailnet: a test fixture named a real device
wiiiimm Aug 23, 2026
4e92768
latency, link: one trace at a time, and one colour per cell
wiiiimm Aug 23, 2026
68548a5
netwatch: every rate read a quarter too high
wiiiimm Aug 23, 2026
e070570
usage: one instant read two ways, depending on how the zone was spelled
wiiiimm Aug 23, 2026
ea1b572
core: an external command that stops answering used to wait forever
wiiiimm Aug 23, 2026
3396b92
usage: copilot kept a sixth midnight
wiiiimm Aug 23, 2026
306915e
build: the poller guards did not exist in the shipped binary
wiiiimm Aug 23, 2026
75b98b8
core: cycle skipped the first choice when the current value was not one
wiiiimm Aug 23, 2026
983e1b7
latency, link: a fair turn, and a poller that says why it stopped
wiiiimm Aug 23, 2026
438a15b
clocks: the minute key moves the block you are in
wiiiimm Aug 23, 2026
de3cefe
AGENTS.md: dependencies are allowed; what ships must carry what it needs
wiiiimm Aug 23, 2026
ddd637f
clocks: the help promised persistence the binary did not have
wiiiimm Aug 23, 2026
046ce1c
linear: a timestamp with a wide character killed the poll thread
wiiiimm Aug 24, 2026
bd4cd19
AGENTS.md: two gotchas from letting a device name reach a public PR
wiiiimm Aug 24, 2026
083f088
herdr-panes: name the keys after what they toggle
wiiiimm Aug 24, 2026
63fe9b9
docs: point at the Linear issues rather than the project overview
wiiiimm Aug 24, 2026
e1ff49a
check.py, for the Rust - and the three things it found on its first run
wiiiimm Aug 24, 2026
f5a0b27
check: see the hints that are not written [k] immediately before a le…
wiiiimm Aug 24, 2026
bc9ca57
widgets: one way in and one way out, everywhere
wiiiimm Aug 24, 2026
f89d14c
docs: the checks to run are the Rust ones now
wiiiimm Aug 24, 2026
d6d2688
port: the review findings that were real, and three tests that were not
wiiiimm Aug 24, 2026
a1704cc
netwatch: the detail screen shows what it has, and scrolls
wiiiimm Aug 24, 2026
cc6f750
check: a config key someone deletes must land on a code default
wiiiimm Aug 24, 2026
9926f43
defaults: three the Rust did not match, and the check that finds the …
wiiiimm Aug 24, 2026
01bda51
netwatch: a cursor inside a section, and a heading over every column
wiiiimm Aug 24, 2026
d30827b
core: one more hint costs at most one more line
wiiiimm Aug 24, 2026
747a407
check: the help text was documentation nobody was checking
wiiiimm Aug 24, 2026
d619aca
herdr-panes: the help text names the key the widget has
wiiiimm Aug 24, 2026
6b97854
widgets: one section rule, in one place, and linear obeys it
wiiiimm Aug 24, 2026
f718b78
herdr-panes: the idle section could not be reached on a busy machine
wiiiimm Aug 24, 2026
1430933
AGENTS.md: a new check is green against your tree, not against the repo
wiiiimm Aug 24, 2026
4a9defe
herdr-panes: name the idle-section decision, and test it at every height
wiiiimm Aug 24, 2026
15f649c
AGENTS.md: a grep that finds nothing is as often a wrong pattern
wiiiimm Aug 24, 2026
9649f8b
netwatch: the process cursor could walk off the screen
wiiiimm Aug 24, 2026
5df0221
widgets: the sections read as one list under the arrows
wiiiimm Aug 24, 2026
57bb8a1
start: the menu cursor walked off a short pane
wiiiimm Aug 24, 2026
4f1326a
netwatch: the detail screen follows the cursor into a section
wiiiimm Aug 24, 2026
81aa94a
netwatch: name the socket by our end of it, and shout the column head…
wiiiimm Aug 24, 2026
b0caa9d
netwatch: LOCAL, which is what ss and netstat call that column
wiiiimm Aug 24, 2026
e1e1a0f
usage: grok's credit window rolls forward instead of reading "resetting"
wiiiimm Aug 24, 2026
1d0d214
usage: ask x.ai for grok's quota, or say plainly that nobody is asking
wiiiimm Aug 24, 2026
d2a6e51
usage: the grok note says what to do, not just which key exists
wiiiimm Aug 25, 2026
12efc8b
usage: antigravity says which thing went wrong, and says it under its…
wiiiimm Aug 25, 2026
e8fb2fb
usage: a star for cached, and the numbers a cached reading can still …
wiiiimm Aug 25, 2026
064071e
usage: a cached lane keeps its bar mark, its pace and its countdown, …
wiiiimm Aug 25, 2026
1f4cb0c
usage: keep our own claude reading, and stop trusting a cache its own…
wiiiimm Aug 25, 2026
e756a80
usage: pin the fossil on disk, so it cannot come back as a reading
wiiiimm Aug 25, 2026
d7f07d9
usage: ask claude every five minutes, and judge a reading by its age
wiiiimm Aug 25, 2026
03d9bcc
usage: say hours when the reset is inside a day
wiiiimm Aug 25, 2026
703e7ab
usage: one grok setting, because nobody wants half of it
wiiiimm Aug 25, 2026
7651a45
usage: back off when refused, and say what the refusal was
wiiiimm Aug 25, 2026
b5aff2c
tailnet: copy comes back to where it was opened, and the interval key…
wiiiimm Aug 25, 2026
666924f
deployments: show the build log, not just that a build failed
wiiiimm Aug 25, 2026
4901310
deployments: the detail scrolls, copy gets its own page, and both sta…
wiiiimm Aug 25, 2026
89144a8
widgets: every screen that answers q now says so
wiiiimm Aug 25, 2026
a920413
github: an account of its own, and a fortnight rather than a week
wiiiimm Aug 25, 2026
39a7d47
github: walk the oldest PRs and copy one
wiiiimm Aug 25, 2026
594c1bd
deployments: one filter you type, one you cycle, and the names say which
wiiiimm Aug 25, 2026
b3e9089
linear: a screen of its own for a cycle, and for a team its projects
wiiiimm Aug 25, 2026
9e9f7d4
linear: open a project from the team that owns it
wiiiimm Aug 25, 2026
ee47a66
linear: the board scrolls, and carries a project list of its own
wiiiimm Aug 25, 2026
b4415f3
linear, netwatch: a cycle lists what is in it, and headings say tab
wiiiimm Aug 25, 2026
63e9959
ports: name the program that is running, not the directory it sits in
wiiiimm Aug 25, 2026
ee4e90c
ports: the footer names the arrow that has always opened a port
wiiiimm Aug 25, 2026
37f7701
ports: what has actually gone through each port
wiiiimm Aug 25, 2026
eafe5b7
ports: the traffic column arrives when the names still fit
wiiiimm Aug 25, 2026
e804988
ports: the traffic chart is as wide as the pane
wiiiimm Aug 25, 2026
ac02b90
ports: the main screen shows what is moving, and each row its own shape
wiiiimm Aug 25, 2026
c1df434
docs: where the Rust and the Python differ on purpose
wiiiimm Aug 25, 2026
cd2bd3e
docs: the port's decisions, now that the Python is leaving
wiiiimm Aug 25, 2026
b6c3b8b
herdr-panes: the cursor stays on a row you can see
wiiiimm Aug 25, 2026
22a9bc7
rust moves to the root, and the Python goes
wiiiimm Aug 25, 2026
d629275
docs: fourteen binaries, and no second implementation
wiiiimm Aug 25, 2026
a2e96e5
README: fourteen, not ten
wiiiimm Aug 25, 2026
51b1d73
ports, latency: a dead poller says so, and the check can tell
wiiiimm Aug 25, 2026
cbe6008
four widgets: a grey you can read on a selected row
wiiiimm Aug 25, 2026
8b3f87c
docs: README and AGENTS.md against the tree as it is
wiiiimm Aug 25, 2026
661b165
release: a tag builds it, names it, and says what changed
wiiiimm Aug 25, 2026
ece2c66
review: what two reviewers found, and what the fix for them found
wiiiimm Aug 25, 2026
7a65f84
check: read a whole tint statement, not a line of one
wiiiimm Aug 26, 2026
ce05790
github, clocks: four the PR's reviewers were right about
wiiiimm Aug 26, 2026
1998e9a
core: three ways a helper turned a real answer into silence
wiiiimm Aug 26, 2026
71c51d7
linear, pr, github, deployments: walk the pages, or say the number is…
wiiiimm Aug 26, 2026
ad6ce04
herdr-panes, tailnet, latency: a probe that failed is not a quiet source
wiiiimm Aug 26, 2026
5e2b5c7
clocks: six that the day, the config and the shell each got wrong
wiiiimm Aug 26, 2026
dec9fa1
check: the config scanner could not see a read that wrapped
wiiiimm Aug 26, 2026
8606b23
link, netwatch: a wrapped port, a hung command, and a baseline half-kept
wiiiimm Aug 26, 2026
bff6789
usage: ask x.ai every five minutes, not every hour
wiiiimm Aug 26, 2026
dcdac01
usage: grok asked, was answered, and still said "not live"
wiiiimm Aug 26, 2026
05bf030
widgets: the code the port stopped using, and one doc that stopped be…
wiiiimm Aug 26, 2026
6a76fc5
core: the version stamp had stopped being rebuilt at all
wiiiimm Aug 26, 2026
25998e3
core: watch the git refs and the source trees, not everything and not…
wiiiimm Aug 26, 2026
5cac923
AGENTS.md: one rerun-if-* directive turns off all the others
wiiiimm Aug 26, 2026
f1fec79
usage: Grok Bot, the Cursor allowance that was not on any bar
wiiiimm Aug 26, 2026
1b33341
usage: the Grok Bot lane needed no cookie after all
wiiiimm Aug 26, 2026
bc1d629
usage: three the summary and the Grok tab were each telling differently
wiiiimm Aug 26, 2026
f19b154
usage: an omitted percentage is nought, and the answer proves it itself
wiiiimm Aug 26, 2026
783c69a
usage: antigravity was named as quiet without being asked why
wiiiimm Aug 26, 2026
db49a37
usage: the quiet agents are named before they are explained, not after
wiiiimm Aug 26, 2026
927b24d
usage: antigravity's quota does not need the app open after all
wiiiimm Aug 26, 2026
878ec57
usage: antigravity says which step failed, and the remote ask has a s…
wiiiimm Aug 26, 2026
8da8c2d
usage: antigravity gets a third source, and the widget may start it
wiiiimm Aug 26, 2026
08eb73b
docs: a README that points, and pages that point back
wiiiimm Aug 26, 2026
ad75b06
ci: CodeQL for Rust, in advanced setup, and why it cannot run yet
wiiiimm Aug 26, 2026
d981e01
ci: park CodeQL's triggers until the org config allows the upload
wiiiimm Aug 26, 2026
e1e917f
fix: restore the terminal on signal and reject a broken refresh
cursoragent Aug 26, 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
69 changes: 69 additions & 0 deletions .github/changelog.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#!/usr/bin/env bash
# Build a changelog for one release, from the commit subjects between two
# tags.
#
# The subjects here are prose, not conventional commits - "netwatch: every
# rate read a quarter too high" rather than "fix(netwatch): ...". There is no
# type to group by and inventing one would mean rewriting three hundred
# subjects. What every subject does carry is the part before the first colon,
# which is the widget or the area it touched, so that is the grouping: a
# reader asking "what changed in ports" gets an answer, which is the question
# a changelog for fourteen separate binaries is actually asked.
#
# A prefix only counts as a scope if it names something real - a widget in
# widgets/src/bin, or one of the areas below. Early history has subjects like
# "Add agents.py: every coding agent", where the part before the colon is the
# start of a sentence rather than a scope; taken at face value those made
# forty-seven sections out of three hundred commits. The widget list is read
# from the tree rather than written down here, so a new widget is a scope the
# day it lands.
#
# Usage: changelog.sh <tag> [previous-tag]
# With no previous tag it takes the whole history, which is what the first
# release needs and what it will get, there being no tags yet.
set -euo pipefail

here=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)
tag="${1:?usage: changelog.sh <tag> [previous-tag]}"
prev="${2:-}"

if [ -z "$prev" ]; then
prev=$(git describe --tags --abbrev=0 "${tag}^" 2>/dev/null || true)
fi
if [ -n "$prev" ]; then
range="${prev}..${tag}"
since="since ${prev}"
else
range="$tag"
since="everything so far"
fi

# Every widget, plus the places that are not one.
scopes=$(
{ ls "$here/widgets/src/bin" 2>/dev/null | sed -n 's/\.rs$//p'
printf '%s\n' core widgets docs tests ci rust release
} | sort -u
)

printf '## %s\n\n' "$tag"
printf '%s commits, %s.\n\n' "$(git log --oneline "$range" | wc -l | tr -d ' ')" "$since"

git log --format='%s' "$range" | awk -v known="$scopes" -F': ' '
BEGIN { n = split(known, k, "\n"); for (i = 1; i <= n; i++) if (k[i] != "") is[k[i]] = 1 }
{
if (NF < 2) { print "everything else\t" $0; next }
scope = $1
rest = substr($0, length(scope) + 3)
n = split(scope, parts, /, */)
# Every part has to be a real scope. "linear, netwatch" is two
# widgets; "Add agents.py" is a sentence that happens to contain a
# comma-free prefix and belongs whole, under everything else.
good = (n > 0)
for (i = 1; i <= n; i++) if (!(parts[i] in is)) good = 0
if (!good) { print "everything else\t" $0; next }
for (i = 1; i <= n; i++) print parts[i] "\t" rest
}
' | sort -f -s -t"$(printf '\t')" -k1,1 | awk -F'\t' '
$1 != seen { if (seen != "") printf "\n"; printf "### %s\n\n", $1; seen = $1 }
{ printf "- %s\n", $2 }
'
87 changes: 87 additions & 0 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# CodeQL, in advanced setup rather than default.
#
# Default setup cannot do this. Its API accepts only actions, c-cpp, csharp,
# go, java-kotlin, javascript-typescript, python, ruby and swift - `rust` is
# refused with a 422 - so the repository was still scanning `python` months
# after the last .py file was deleted, which is to say scanning nothing.
#
# Rust support is public preview, from CodeQL 2.22.1. It needs no build step:
# the extractor reads the sources, so there is no `autobuild` here and no
# `build-mode`, which is how github/codeql-action's own Rust check runs.
#
# `actions` is scanned alongside it, and is not padding - this repository
# publishes a release workflow that handles a tag and writes to the releases
# API, and that file is exactly the kind of thing the actions queries read.
#
# THIS FILE DOES NOT RUN YET, and that is not a mistake in it. GitHub disables
# advanced workflows while default setup is on, and default setup here is
# pinned by an enforced organisation configuration ("GitHub recommended"),
# so the repository cannot turn it off: the API answers 422, "controlled by
# organization administrators".
#
# The fix is not to detach this repository from that configuration. The same
# configuration enforces secret scanning, push protection, Dependabot alerts
# and private vulnerability reporting, and this repository is public with
# "secrets never enter the tree" as its first rule - trading push protection
# for Rust analysis would be a bad bargain. What is needed is a sibling
# configuration, identical but with code_scanning_default_setup disabled,
# attached to this repository alone. Then this file starts working and
# nothing else is given up.
name: CodeQL

# Manual only, until the organisation configuration above is sorted.
#
# This ran once on push and did exactly what it should: the Rust extractor
# read the whole crate and produced a database, and then the upload was
# refused - "CodeQL analyses from advanced configurations cannot be
# processed when the default setup is enabled". The analysis is fine; the
# submission is what is blocked.
#
# A check that can only ever be red teaches nothing, and would be red on
# every push to main after the port lands. So the automatic triggers are
# parked here, in the order they should be restored:
#
# push: { branches: [main] }
# pull_request: { branches: [main] }
# schedule: [ { cron: "17 4 * * 1" } ] # weekly, as default setup had
#
# Put those back the moment the repository is attached to a configuration
# with code_scanning_default_setup disabled, and delete this comment.
on:
workflow_dispatch:

permissions: {}

jobs:
analyze:
name: Analyze ${{ matrix.language }}
runs-on: ubuntu-24.04
timeout-minutes: 30
permissions:
# The three this needs and nothing else: read the code, write the
# findings, and read Actions metadata for the workflow scan.
contents: read
security-events: write
actions: read
strategy:
fail-fast: false
matrix:
language: [rust, actions]
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
with:
persist-credentials: false

- name: Initialise CodeQL
uses: github/codeql-action/init@486fec2a3ea2626afcd8c7e9208b4f515078dd7e # codeql-bundle-v2.26.4
with:
languages: ${{ matrix.language }}
# security-extended over the default suite. This is fourteen
# binaries that read a machine's own state and hold three API
# tokens; the extra queries are the point of running this at all.
queries: security-extended

- name: Analyse
uses: github/codeql-action/analyze@486fec2a3ea2626afcd8c7e9208b4f515078dd7e # codeql-bundle-v2.26.4
with:
category: "/language:${{ matrix.language }}"
119 changes: 119 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
# A tag produces a release: fourteen Linux binaries, their checksums, and a
# changelog built from the commit subjects since the last tag.
#
# Nothing here rewrites the source it is building. The version in Cargo.toml
# and the tag are checked against each other and the build stops if they
# disagree, rather than the workflow editing the manifest to make them match
# - a build that edits its own source produces a binary no checkout can
# reproduce, which is a strange thing to hand somebody.
name: release

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

permissions:
contents: write

jobs:
linux:
# Pinned, not `-latest`. The oldest glibc a binary runs on is the one it
# was built against, so that is a decision rather than something to
# inherit from whatever the runner image became this month. 22.04 is
# glibc 2.35.
runs-on: ubuntu-22.04
steps:
# Pinned to a commit, not a tag. A tag is mutable: re-running this
# workflow on the same release tag could execute different action code
# than the release was built with, which makes "reproducible" a word
# rather than a property. Comments carry the human-readable version so
# a reader can tell what these are without resolving them.
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
with:
# The changelog reads the history between two tags, and the build
# stamps the commit into --version. A shallow clone has neither.
fetch-depth: 0

- uses: dtolnay/rust-toolchain@6c977a6ca4077a0ceb28ffbe03f59d46e9ac8772 # master
with:
# An exact version, for the same reason. `stable` moves, and two
# builds of one tag compiled by different compilers are two
# different binaries wearing one version number.
toolchain: "1.98.0"

- name: The tag and the manifest must agree
run: |
tag="${GITHUB_REF_NAME#v}"
manifest=$(sed -n 's/^version = "\(.*\)"/\1/p' Cargo.toml | head -1)
if [ "$tag" != "$manifest" ]; then
echo "tag v$tag but Cargo.toml says $manifest" >&2
echo "bump the manifest and tag that commit, rather than having" >&2
echo "this workflow rewrite the source it is building" >&2
exit 1
fi
echo "v$tag"

- name: The release profile still unwinds
run: |
# Three widgets wrap their poll thread in catch_unwind and record
# why it stopped. Under panic = "abort" those arms are unreachable
# and the source reads as protected while the binary is not - it
# was shipped that way once. Costs about 4.5% of the total size,
# measured.
grep -q '^panic = "unwind"$' Cargo.toml || {
echo "Cargo.toml no longer sets panic = unwind" >&2; exit 1; }
# And nothing here may quietly override it.
if [ -n "${RUSTFLAGS:-}" ]; then
echo "RUSTFLAGS is set ($RUSTFLAGS) and could undo the profile" >&2
exit 1
fi

- run: cargo test --release

- run: cargo build --release

- name: Nothing dynamic beyond the C runtime
run: |
# rusqlite is taken with `bundled` so SQLite is compiled in, and
# the promise on the tin is that a binary needs nothing installed
# alongside it. Checked rather than asserted: a crate that starts
# wanting a system library would otherwise ship quietly.
allowed='linux-vdso|libc\.so|libm\.so|libgcc_s\.so|ld-linux'
bad=0
for b in $(cargo metadata --no-deps --format-version 1 \
| grep -o '"name":"[a-z-]*","src_path":"[^"]*bin/[a-z-]*\.rs"' \
| sed 's/.*bin\///; s/\.rs"//'); do
[ -x "target/release/$b" ] || continue
leaked=$(ldd "target/release/$b" | grep -vE "$allowed" | grep -v '^\s*$' || true)
if [ -n "$leaked" ]; then
echo "$b links something it should carry:" >&2
echo "$leaked" >&2
bad=1
fi
done
[ "$bad" = 0 ]

- name: Changelog
run: ./.github/changelog.sh "$GITHUB_REF_NAME" > CHANGELOG-release.md

- name: One tarball, and its checksum
run: |
name="terminal-toys-${GITHUB_REF_NAME}-x86_64-unknown-linux-gnu"
mkdir -p "dist/$name"
# The binaries, and the docs that explain them - `start` embeds
# them but a person reading the tarball has no other copy.
find target/release -maxdepth 1 -type f -executable ! -name '*.*' \
-exec cp {} "dist/$name/" \;
cp -r docs README.md LICENSE config.example.json "dist/$name/"
tar -C dist -czf "$name.tar.gz" "$name"
sha256sum "$name.tar.gz" > "$name.tar.gz.sha256"
ls -la "$name.tar.gz"

- name: Release
env:
GH_TOKEN: ${{ github.token }}
run: |
gh release create "$GITHUB_REF_NAME" \
--title "$GITHUB_REF_NAME" \
--notes-file CHANGELOG-release.md \
terminal-toys-*.tar.gz terminal-toys-*.tar.gz.sha256
11 changes: 7 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
__pycache__/
*.py[cod]
.venv/
venv/
target/
.DS_Store

# What a release build leaves behind, if one is run by hand.
dist/
terminal-toys-*.tar.gz
terminal-toys-*.tar.gz.sha256
CHANGELOG-release.md

# Personal settings, and now secrets: config.json holds the Vercel token.
# Variants are covered too, so a config.local.json or a stray .env cannot be
# committed by accident.
Expand Down
Loading
Loading