ci: schedule nightly race and fuzz, pin actions, add release-check and docs drift
Test / test (push) Successful in 1m37s
Test / test (push) Successful in 1m37s
Assisted-by: GLM 5.3 Flash
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
# Fuzz smoke, Go. A nightly time-boxed run of the fuzz targets, and a hand
|
||||
# dispatch when a change asks for it.
|
||||
#
|
||||
# Fuzzing is exploration, so it never belongs to the push pipeline; a 30 second
|
||||
# smoke per target, run nightly, is the compromise that catches a new crash
|
||||
# within a day without holding the shared box. The targets run the seeds and
|
||||
# whatever the corpus has gathered; a failure leaves its crashing input in
|
||||
# testdata/fuzz, which the ordinary suite then reproduces on every push.
|
||||
#
|
||||
# Every step is one command, so the step that fails is the gate that failed.
|
||||
name: Fuzz
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
# Nightly at 03:30 UTC, after the race sweep has had the box first.
|
||||
- cron: "30 3 * * *"
|
||||
|
||||
env:
|
||||
# One core: parallelism buys no speed here and costs memory the box does not have.
|
||||
GOFLAGS: -p=1
|
||||
GOMAXPROCS: "2"
|
||||
|
||||
jobs:
|
||||
fuzz:
|
||||
runs-on: fedora
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
||||
|
||||
- uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
cache: true
|
||||
|
||||
- name: Fuzz the parser
|
||||
run: go test -run '^$' -fuzz FuzzParse -fuzztime=30s -timeout 10m .
|
||||
|
||||
- name: Fuzz the encoder
|
||||
run: go test -run '^$' -fuzz FuzzMarshal -fuzztime=30s -timeout 10m .
|
||||
@@ -1,14 +1,20 @@
|
||||
# Race, Go. Dispatched by hand, and run as part of the release gates.
|
||||
# Race, Go. Dispatched by hand, run nightly on a schedule, and run as part of
|
||||
# the release gates.
|
||||
#
|
||||
# The race detector roughly doubles both time and memory, which the shared runner box
|
||||
# cannot afford on every push. Locally it belongs to `just gates`, which runs it once per
|
||||
# task; here it is an explicit decision rather than a routine.
|
||||
# task; here it is an explicit decision rather than a routine. The schedule is the
|
||||
# nightly sweep: a failing race on development is known by morning without anyone
|
||||
# remembering to dispatch it.
|
||||
#
|
||||
# Every step is one command, so the step that fails is the gate that failed.
|
||||
name: Race
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
# Nightly at 03:00 UTC, the quietest hours of the shared box.
|
||||
- cron: "0 3 * * *"
|
||||
|
||||
env:
|
||||
# One core: parallelism buys no speed here and costs memory the box does not have.
|
||||
@@ -20,9 +26,9 @@ jobs:
|
||||
runs-on: fedora
|
||||
timeout-minutes: 45
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
||||
|
||||
- uses: actions/setup-go@v6
|
||||
- uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
cache: true
|
||||
|
||||
@@ -31,9 +31,9 @@ jobs:
|
||||
runs-on: fedora
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
||||
|
||||
- uses: actions/setup-go@v6
|
||||
- uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6
|
||||
with:
|
||||
# The module is the source of truth for the version, so it cannot drift.
|
||||
go-version-file: go.mod
|
||||
@@ -103,7 +103,7 @@ jobs:
|
||||
contents: read
|
||||
releases: write
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
||||
|
||||
- name: Install Perl
|
||||
# The runner images are minimal and Perl is not guaranteed. The install is a
|
||||
|
||||
@@ -43,9 +43,9 @@ jobs:
|
||||
runs-on: fedora
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
||||
|
||||
- uses: actions/setup-go@v6
|
||||
- uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6
|
||||
with:
|
||||
# The module is the source of truth for the version, so it cannot drift.
|
||||
go-version-file: go.mod
|
||||
|
||||
@@ -100,11 +100,13 @@ toml-test: build
|
||||
coverage-html: test
|
||||
go tool cover -html=coverage.out -o coverage.html
|
||||
|
||||
# Cross-compile smoke: the library and the command build for the foreign architectures; not a gate, it is a nightly convenience and runs std-lib only.
|
||||
# Cross-compile smoke: the library and the command build for the foreign architectures and the browser and edge runtimes; not a gate, it is a nightly convenience and runs std-lib only.
|
||||
cross:
|
||||
GOARCH=arm64 go build ./...
|
||||
GOARCH=loong64 go build ./...
|
||||
GOARCH=riscv64 go build ./...
|
||||
GOOS=js GOARCH=wasm go build ./...
|
||||
GOOS=wasip1 GOARCH=wasm go build ./...
|
||||
GOARCH=arm64 CGO_ENABLED=0 go build -o /dev/null {{package}}
|
||||
GOARCH=loong64 CGO_ENABLED=0 go build -o /dev/null {{package}}
|
||||
GOARCH=riscv64 CGO_ENABLED=0 go build -o /dev/null {{package}}
|
||||
@@ -112,3 +114,27 @@ cross:
|
||||
# Runs the example program under examples/basic; not standard because `run` runs the adapter, and an example is documentation, not the product.
|
||||
example:
|
||||
go run ./examples/basic
|
||||
|
||||
# The release pre-flight from the release skill, in one command: the branch, a clean tree, a sync with origin, the gates, and a CHANGELOG section ready to release. Not a gate, it is the checklist before a release may even be discussed.
|
||||
release-check version:
|
||||
#!/usr/bin/env perl
|
||||
my ($version) = @ARGV;
|
||||
$version =~ m{\Av?\d+\.\d+\.\d+\z} or die qq{usage: just release-check X.Y.Z\n};
|
||||
my $branch = qx{git rev-parse --abbrev-ref HEAD};
|
||||
chomp $branch;
|
||||
$branch eq q{development} or die qq{release-check: on '$branch', cut releases from development\n};
|
||||
my $dirty = qx{git status --porcelain};
|
||||
$dirty eq q{} or die qq{release-check: the working tree is dirty\n};
|
||||
system(qw{git fetch origin}) == 0 or die qq{release-check: git fetch failed\n};
|
||||
my $local = qx{git rev-parse development};
|
||||
my $remote = qx{git rev-parse origin/development};
|
||||
$local eq $remote or die qq{release-check: development is out of sync with origin\n};
|
||||
my $changelog = do { open(my $fh, q{<}, q{CHANGELOG.md}) or die qq{release-check: cannot read CHANGELOG.md: $!\n}; local $/; <$fh> };
|
||||
$changelog =~ m{## \[development\]\n\n### \w+} or die qq{release-check: the [development] section of CHANGELOG.md is missing or empty\n};
|
||||
print qq{branch, tree, sync and changelog verified; running the gates\n};
|
||||
system(qw{just gates}) == 0 or die qq{release-check: the gates failed\n};
|
||||
print qq{release-check: ready to release $version\n};
|
||||
|
||||
# Compares the toml-test counts the documentation names with the live suite run; not standard, it exists because a corpus change used to be corrected by hand.
|
||||
docs-drift:
|
||||
perl scripts/docs-drift.pl
|
||||
|
||||
Executable
+34
@@ -0,0 +1,34 @@
|
||||
#!/usr/bin/env perl
|
||||
# docs-drift compares the toml-test suite counts the documentation names with
|
||||
# the run this repository produces now. A corpus change moves the counts, and
|
||||
# README.md and docs/ARCHITECTURE.md quote them; this is the check that keeps
|
||||
# the quotation honest. Builtins only, and the toml-test binary on PATH.
|
||||
|
||||
use v5.40;
|
||||
|
||||
my $out = qx{toml-test test -decoder=bin/interpres-decode -encoder='bin/interpres-decode -encode' -toml=1.1 2>&1};
|
||||
die "docs-drift: toml-test failed to run; build the adapter first (just build)\n"
|
||||
if !defined $out || $out =~ /not found|No such file/;
|
||||
|
||||
my ($valid) = $out =~ /valid tests:\s+(\d+) passed/;
|
||||
my ($invalid) = $out =~ /invalid tests:\s+(\d+) passed/;
|
||||
die "docs-drift: could not read the suite counts from the toml-test output\n"
|
||||
unless defined $valid && defined $invalid;
|
||||
print "docs-drift: the suite now stands at $valid valid and $invalid invalid cases\n";
|
||||
|
||||
my $drift = 0;
|
||||
for my $file ('README.md', 'docs/ARCHITECTURE.md') {
|
||||
open(my $fh, '<', $file) or die "docs-drift: cannot read $file: $!\n";
|
||||
my $text = do { local $/; <$fh> };
|
||||
close($fh);
|
||||
while ($text =~ /(\d+)\s+(valid|invalid)/g) {
|
||||
my ($quoted, $kind) = ($1, $2);
|
||||
my $live = $kind eq 'valid' ? $valid : $invalid;
|
||||
if ($quoted != $live) {
|
||||
print "docs-drift: $file quotes $quoted $kind cases, the suite says $live\n";
|
||||
$drift = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
die "docs-drift: the documentation has drifted from the suite\n" if $drift;
|
||||
print "docs-drift: the documentation matches the suite\n";
|
||||
Reference in New Issue
Block a user