diff --git a/.github/workflows/publish-aur.yml b/.github/workflows/publish-aur.yml index 29df2b8..577fb33 100644 --- a/.github/workflows/publish-aur.yml +++ b/.github/workflows/publish-aur.yml @@ -28,7 +28,13 @@ jobs: set -euo pipefail pacman -Sy --noconfirm --needed base-devel git openssh pacman-contrib jq + # The TAG, not the default branch. Without this the workflow publishes + # whatever main happens to contain while labelling it with the requested + # version -- so a release cut days ago would ship today's spec, PKGBUILD + # and manifests under the old version number. - uses: actions/checkout@v7 + with: + ref: v${{ inputs.version }} # The tag must exist and be pushed BEFORE publishing: PKGBUILD's source # points at the tag tarball, so a queued build would 404 partway through @@ -37,7 +43,13 @@ jobs: run: | set -euo pipefail tag="v${{ inputs.version }}" - git ls-remote --exit-code --tags origin "refs/tags/${tag}" >/dev/null || { + # Explicit URL, not the `origin` alias: inside a container the + # checkout's git config is not reliably readable, and `git ls-remote + # origin` then fails with "'origin' does not appear to be a git + # repository" -- which this step reported as "the tag does not exist". + # A misleading error about the wrong thing entirely. + repo="https://github.com/${{ github.repository }}.git" + git ls-remote --exit-code --tags "${repo}" "refs/tags/${tag}" >/dev/null || { echo "::error::${tag} does not exist on origin - push it before publishing" exit 1 } diff --git a/.github/workflows/publish-copr.yml b/.github/workflows/publish-copr.yml index 1f49717..b141bc5 100644 --- a/.github/workflows/publish-copr.yml +++ b/.github/workflows/publish-copr.yml @@ -29,7 +29,13 @@ jobs: # Needed for the pushed-tag check below. git config --global --add safe.directory '*' + # The TAG, not the default branch. Without this the workflow publishes + # whatever main happens to contain while labelling it with the requested + # version -- so a release cut days ago would ship today's spec, PKGBUILD + # and manifests under the old version number. - uses: actions/checkout@v7 + with: + ref: v${{ inputs.version }} # Source0 points at the tag tarball, so a queued build 404s partway through # if the tag is not pushed. Cheaper to catch here than in the build log. @@ -37,7 +43,13 @@ jobs: run: | set -euo pipefail tag="v${{ inputs.version }}" - git ls-remote --exit-code --tags origin "refs/tags/${tag}" >/dev/null || { + # Explicit URL, not the `origin` alias: inside a container the + # checkout's git config is not reliably readable, and `git ls-remote + # origin` then fails with "'origin' does not appear to be a git + # repository" -- which this step reported as "the tag does not exist". + # A misleading error about the wrong thing entirely. + repo="https://github.com/${{ github.repository }}.git" + git ls-remote --exit-code --tags "${repo}" "refs/tags/${tag}" >/dev/null || { echo "::error::${tag} does not exist on origin - push it before publishing" exit 1 } @@ -114,7 +126,12 @@ jobs: # `copr-cli list` prints "Name: " plus an indented block, not a # bare name, so grepping for the name alone never matches and the script # tries to create a project that already exists. - if ! copr-cli list 2>/dev/null | grep -qE "^Name:[[:space:]]+thinkutils$"; then + # Herestring, not a pipe into grep -q: grep -q exits on first match, + # the upstream command takes SIGPIPE, and pipefail turns a successful + # match into a failed test. That exact shape broke the aarch64 release + # verification, where finding the file reported it as missing. + projects="$(copr-cli list 2>/dev/null || true)" + if ! grep -qE "^Name:[[:space:]]+thinkutils$" <<<"$projects"; then echo ">> creating COPR project thinkutils" # Separate argv entries. "${CHROOTS[@]/#/--chroot }" looks equivalent # but puts the space INSIDE one argument, so copr-cli sees a single diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 93301f2..cb4b7b3 100755 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -144,10 +144,24 @@ jobs: V="${{ steps.version.outputs.version }}" deb="src-tauri/target/release/bundle/deb/thinkutils_${V}_${{ matrix.deb_arch }}.deb" - dpkg-deb --contents "$deb" | grep -q 'usr/bin/thinkutils' \ + # Listed ONCE into a variable, then matched with a herestring. + # + # `dpkg-deb --contents "$deb" | grep -q ...` is broken under pipefail + # and broken in the worst direction: grep -q exits the instant it + # matches, dpkg-deb takes SIGPIPE writing the rest of the listing, and + # pipefail propagates that non-zero status -- so FINDING the file makes + # the check report it missing. It is timing-dependent, which is why it + # passed on x86_64 and failed the aarch64 release with + # "tar subprocess was killed by signal (Broken pipe)". + # + # A herestring has no upstream process to kill. Piping into plain + # `grep` (no -q) also works, because grep then reads to EOF. + contents="$(dpkg-deb --contents "$deb")" + + grep -q 'usr/bin/thinkutils' <<<"$contents" \ || { echo "::error::.deb does not ship /usr/bin/thinkutils"; exit 1; } - dpkg-deb --contents "$deb" | grep -q 'applications/.*\.desktop' \ + grep -q 'applications/.*\.desktop' <<<"$contents" \ || { echo "::error::.deb ships no .desktop entry - the app would not appear in any launcher"; exit 1; } # The binary's real machine type, not the matrix's claim about it. This diff --git a/scripts/test-gui-packages-docker.sh b/scripts/test-gui-packages-docker.sh index eea9805..ce11f81 100755 --- a/scripts/test-gui-packages-docker.sh +++ b/scripts/test-gui-packages-docker.sh @@ -366,7 +366,7 @@ read -r -d '' VERDICT <<'VEOF' || true # counts. Take the first field and compare in awk, which handles 5.4e+10. DIFF="${RAW%% *}" echo "pixels changed vs the pre-launch display: ${RAW}" - if echo "${DIFF}" | grep -qE "^[0-9]+([.][0-9]+)?([eE][+-]?[0-9]+)?$"; then + if grep -qE "^[0-9]+([.][0-9]+)?([eE][+-]?[0-9]+)?$" <<<"${DIFF}"; then awk -v d="${DIFF}" "BEGIN{exit !(d>0)}" \ && echo "OK: ${DIFF} pixels changed after launch" \ || { echo "FAIL: display is pixel-identical to before launch"; fail=1; } @@ -413,7 +413,7 @@ read -r -d '' VERDICT <<'VEOF' || true else # The specific, nameable failure: WebKit rendered index.html's own static # text but templateLoader never ran. Every other check above passes here. - if echo "${OCRTXT}" | grep -qiE "quick settings and overview"; then + if grep -qiE "quick settings and overview" <<<"${OCRTXT}"; then echo "FAIL: only index.html's STATIC text is on screen - templateLoader.js" echo " never injected the sidebar or views. WebKit loaded the page;" echo " the JS did not run."