diff --git a/.github/workflows/fleet-lint.yml b/.github/workflows/fleet-lint.yml index 1ad3170..b76a4ec 100644 --- a/.github/workflows/fleet-lint.yml +++ b/.github/workflows/fleet-lint.yml @@ -10,7 +10,13 @@ name: fleet-lint on: push: branches: [main] + # `edited` joins the three default types because pr-title reads the title out + # of the event payload: without it, a title corrected in response to the + # check raises no event, and a re-run replays the payload that failed. The + # only way left to clear the gate would be another push, which a title fix + # does not have. pull_request: + types: [opened, synchronize, reopened, edited] # Periodic coverage: these tools grow rules between releases, so a repository # nobody has touched can start failing for a reason worth knowing about. schedule: @@ -209,7 +215,10 @@ jobs: # drives the compiler over the whole workspace, and a pull request that # touches no Rust cannot change what it would say. needs: changes - if: needs.changes.outputs.rust == 'true' + # Not on an edited title or body: nothing a description says changes what + # the compiler sees, and this is the one job here that can run half an + # hour. The rest are seconds and can afford to answer every event. + if: needs.changes.outputs.rust == 'true' && github.event.action != 'edited' steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 # Whether hawk applies is answered on the runner, after checkout: a diff --git a/.vale.ini b/.vale.ini index 0538725..42b5512 100644 --- a/.vale.ini +++ b/.vale.ini @@ -5,7 +5,12 @@ # clichés, redundancy — without imposing a voice on repositories whose readers # are each other. A style guide can come later, from writing that exists. StylesPath = .vale/styles -MinAlertLevel = warning + +# Errors only. The action runs reviewdog with fail-on-error, which fails a job on +# any annotation it posts — warnings included — so a level reported is a level +# enforced, whatever the rule's own severity says. Reporting errors alone is what +# makes the levelling below mean anything. Lower this locally to read the advice. +MinAlertLevel = error Packages = proselint, write-good @@ -20,8 +25,11 @@ BasedOnStyles = proselint, write-good write-good.ThereIs = warning write-good.So = warning -# Prose lives in sentences; a fenced block is code someone will run. -BlockIgnores = (?s) *(```.*?```) +# Prose lives in sentences; a fenced block is code someone will run. Anchored to +# line starts because the unanchored form silently matched nothing: a fence with +# no language tag was graded as prose, and `[PATHS]...` in a usage block read as +# an ellipsis waiting to be typeset. +BlockIgnores = (?sm)^ *```.*?^ *``` # `vale sync` writes the style packages here, README files and all, and Vale # then grades the prose of the linters it just downloaded. diff --git a/scripts/publish.sh b/scripts/publish.sh index 826c7a2..3db2b12 100755 --- a/scripts/publish.sh +++ b/scripts/publish.sh @@ -1,13 +1,20 @@ #!/usr/bin/env bash # Publish jawohl to crates.io. # +# Fleet-managed by conf (.ordnung/managed/publishing/rust/publish.sh): edit it +# there. The crate name is substituted from the repository name, so a crate +# named differently from its repository needs a copy of its own. +# # Publishing is irreversible: a version can be yanked but never deleted, and a # name/version pair can never be reused. The shape of this script follows from # that. # # - Dry run is the default. Uploading takes --execute. -# - A version the registry already has is skipped rather than attempted, so -# re-running a release for an existing tag is a no-op instead of a failure. +# - An upload of a version the registry already has is skipped rather than +# attempted, so re-running a release for an existing tag is a no-op instead +# of a failure. A dry run is never skipped: it packages and compiles every +# time, because a publish check that returns success without building +# anything is exactly the green light nobody should trust. # - Existing versions are read from the sparse index rather than the web API, # because the index is what cargo itself resolves against, and because # --index lets the whole path be rehearsed against a local registry. @@ -31,10 +38,6 @@ # CARGO_REGISTRIES__TOKEN ... or for --execute --registry . # Neither is ever logged. # -# Fleet-managed by conf (.ordnung/managed/publishing/rust/publish.sh): edit it -# there. The crate name is substituted from the repository name, so a crate -# named differently from its repository needs a copy of its own. -# # straitjacket-allow-file:no-comments — this is the procedure for the one # action in the repository that cannot be undone, and sh has no # documentation-comment syntax to hoist the reasoning into. @@ -54,7 +57,10 @@ while [ $# -gt 0 ]; do --registry) REGISTRY=${2:?--registry needs a name}; shift ;; --index) INDEX_BASE=${2:?--index needs a url or directory}; shift ;; --allow-dirty) ALLOW_DIRTY=1 ;; - -h|--help) sed -n '2,33p' "${BASH_SOURCE[0]}"; exit 0 ;; + # The header is the help text, read rather than duplicated, so the two + # cannot drift. It stops at the suppression marker below it, which is + # addressed to the linter rather than to anyone running --help. + -h|--help) awk 'NR>1 && /straitjacket-allow-file/ {exit} NR>1 && /^#/ {print; next} NR>1 {exit}' "${BASH_SOURCE[0]}"; exit 0 ;; -*) echo "publish: unknown flag $1" >&2; exit 2 ;; *) echo "publish: unexpected argument $1" >&2; exit 2 ;; esac @@ -121,8 +127,14 @@ already_published() { grep -q "\"vers\"[[:space:]]*:[[:space:]]*\"${VERSION}\"" <<<"$body" } -if already_published; then - echo "publish: ${CRATE} ${VERSION} is already on the registry; nothing to do" +# Only --execute is skipped for a version the registry already has: that upload +# can never succeed and re-running a release for an existing tag should be a +# no-op rather than a failure. A dry run still packages and compiles, because a +# publish check that returns success without building anything is exactly the +# green light nobody should trust -- and on every commit that does not bump the +# version, that is every run. +if [ "$MODE" = execute ] && already_published; then + echo "publish: ${CRATE} ${VERSION} is already on the registry; nothing to upload" exit 0 fi