The existing tests pass unchanged whether a directory is labelled before
or after its contents, whether a failed descent still relabels the
directory, and whether following symlinks reports a cycle. Each of those
went wrong while moving off fts and none of them was caught.
Lock in the four: post-order labelling, an unreadable directory being
reported and left alone, a symlink loop under -L staying quiet, and
operands with several path components.
Every other sort in sort_entries falls back on the name when its key
ties. Sorting by time did not, so entries sharing a timestamp came out
in the order the directory was read in, and since the sort is unstable
that order was not guaranteed either.
GNU ls breaks the tie with the collation rather than with the bytes, so
the comparison Sort::Name already builds is hoisted out of the match and
the fallback uses that same one.
* .github/workflows/GnuTests.yml (Fetch reference results): Retry the
branch lookup and treat only a 404 as "nothing published yet"; a
transient API error used to look like a missing baseline and silently
skip both comparisons, letting a regression through unnoticed.
(Publish to the reference branch): Same for the published run id, which
guards the force-push. A suppressed error read as run id 0 would let
this run overwrite a reference a newer run had already placed.
* .github/workflows/NotifyTracking.yml: Do not name a cadence for the
tracking repository's fallback schedule, which is its own to change.
* .github/workflows/GnuTests.yml (Fetch reference results): Resolve the
reference branch tip once and read every file at that commit. The
branch is force-pushed by 'publish-reference', so reading each file by
branch name could straddle a publish and pair one file with another
reference's, comparing against a baseline that never existed.
* .github/workflows/NotifyTracking.yml (jobs.dispatch.if): Dispatch for
any completed run, not only a successful one. 'GnuTests' uploads its
results and only then fails the comparison when it finds a new failure,
and 'publish-reference' publishes regardless, so requiring success left
the graphs un-refreshed for exactly the regressions they exist to show.
* .github/workflows/NotifyTracking.yml (jobs.dispatch.env): Add
HAVE_APP_CREDENTIALS; the 'secrets' context is not available in a step's
'if:', where it fails with "Unrecognized named-value: 'secrets'", so the
check has to go through a job-level env var.
* .github/workflows/GnuTests.yml (jobs.publish-reference.concurrency):
Serialize publishing. The step reads the published run id and then
force-pushes, so two overlapping runs could interleave those and let an
older one overwrite a newer reference.
* .github/workflows/NotifyTracking.yml: New workflow sending a
repository_dispatch to uutils/coreutils-tracking once 'GnuTests' or
'make' has finished on the default branch.
The tracking repository polled our artifacts on a cron, so its graphs
lagged the data by up to six hours. Telling it when the data is ready
lets it refresh immediately; its schedule stays as a safety net.
A GITHUB_TOKEN only covers the repository it runs in, so this needs a
credential of its own: an organization-owned GitHub App installed on the
tracking repository, read from the TRACKING_APP_ID and
TRACKING_APP_PRIVATE_KEY secrets. Without them the step warns and the
tracking repository keeps refreshing on its own schedule.
* .github/workflows/GnuTests.yml (env): Add REFERENCE_BRANCH.
(on.push.branches): Exclude the reference branch, which carries no code.
(aggregate): Fetch the reference from that branch rather than resolving
and downloading a workflow artifact.
(publish-reference): New job publishing this run's results on a push to
the default branch.
An artifact is addressable only by run id, so finding one meant listing
workflow runs on the default branch. That listing's 'branch' filter is
served by an eventually consistent index which intermittently returns a
snapshot weeks out of date, making every test fixed on the default
branch since then look like a fix contributed by the pull request.
-v printed only the exec, not what it did to the environment first, so
the three lines GNU emits before it were missing:
$ env -v -u A FOO=1 true
unset: A
setenv: FOO=1
executing: true
arg[0]= 'true'
and 'cleaning environ' for -i. The individual unsets are not logged when
-i is in effect, since it has already emptied the environment.