From 115845f366107042804ffec51599caf37fefd899 Mon Sep 17 00:00:00 2001 From: Yuma Endo Date: Tue, 11 Aug 2026 15:48:44 +0900 Subject: [PATCH 1/4] fix: take split()'s arguments as string_view and retarget the Clang watch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit split() neither owns nor outlives its arguments and returns owning strings, so string_view is what the signature should have said. Callers passing string literals no longer construct a temporary std::string per argument. With the previous parameter types the body's `s | std::views::split(delimiter)` also failed to compile on compiler and standard library pairings the declared range promises, which is what the nightly watch has been reporting since it was added. The body itself is unchanged; what reaches it is not. This is a breaking API change: a caller passing a type that converts implicitly to std::string but not to std::string_view no longer compiles. There are no tags or releases yet, and every call site in the tree passes a string literal or a pointer to one. Declare and in the public header instead of relying on them being visible transitively through . The watch job installed the newest versioned Clang from the suite the upstream install script adds, and that is the release the required gates already build, so on the Clang axis it was watching nothing the verified range did not already cover. Point it at the smallest suffixed suite above the declared upper bound — the release most likely to enter the range next, so its evidence exists when that decision is made. Taking the largest available suite instead would skip past it. The version is pinned so it moves in the same commit as the declared range, the suite codename is read from the runner rather than written as a literal, and a release that is not published yet produces a notice and a skip rather than a failure. The unsuffixed development suite is never watched: -Werror is public here, so a newly added diagnostic would turn a healthy build red. The three documents that publish the support range present it as a flat list, and two of them say outright that CI verifies it. It does not: no required job builds Clang against the older libstdc++ releases available on Ubuntu 24.04, and neither GCC 14 nor Clang 21 has a required job. Say so in all three, provisionally, without changing the declared range itself. --- .github/workflows/nightly.yml | 113 ++++++++++++++++++++----- README.md | 6 ++ docs/sphinx/source/changelog.rst | 1 + docs/sphinx/source/contributing.rst | 6 ++ docs/sphinx/source/getting-started.rst | 9 +- include/dross/type.h | 4 +- src/type.cpp | 2 +- 7 files changed, 115 insertions(+), 26 deletions(-) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 4106da8..ba010de 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -6,11 +6,12 @@ on: - cron: '0 3 * * *' workflow_dispatch: -# Early warning for environments outside the verified range: the newest -# compilers and the floating runner labels. These jobs deliberately use the -# wiring the required gates avoid — floating OS labels and compilers from -# external repositories — because breaking here is the signal we want, ahead -# of users hitting it. They never gate a pull request and must not be added to +# Early warning for environments outside the verified range: the newest GCC, +# the Clang release next in line to enter the declared range, and the +# floating runner labels. These jobs deliberately use wiring the required +# gates avoid — floating OS labels, and (for Clang) a compiler from outside +# the declared range — because breaking here is the signal we want, ahead of +# users hitting it. They never gate a pull request and must not be added to # required status checks. jobs: @@ -59,43 +60,111 @@ jobs: name: Newest Clang runs-on: ubuntu-latest + # Watches the smallest "-N" apt.llvm.org suite above the declared Clang + # range (CLANG_WATCH_VERSION below), not the largest one available: + # taking the largest would skip past the release most likely to enter the + # declared range next, leaving it with no CI evidence at the moment the + # decision is made. The unsuffixed suite (a rolling development snapshot) + # is never watched either, because -Werror is a PUBLIC compile option + # (src/CMakeLists.txt) and a diagnostic newly added upstream would turn a + # healthy build red for reasons unrelated to this project. The pinned + # version below is bumped together with the declared range so both move + # in the same commit and the watched release stays visible in the diff. + # + # The apt source line is composed directly instead of fetching and + # running apt.llvm.org's install script: this job only needs one source + # line and one package, so there is no need to pull a remote script and + # execute it as root. The script's own version table also points its + # newest entries at the unsuffixed development suite, which is exactly + # what this job is designed to avoid. + env: + CLANG_WATCH_VERSION: '23' + steps: - uses: actions/checkout@v7 - # llvm.sh adds the apt.llvm.org repository for the current stable release, - # then we take the newest versioned clang package available. Tracking the - # stable release rather than trunk (llvm.sh all) is deliberate: this watches - # what users will actually reach for, not what is still in development. - - name: Install newest Clang + - name: Probe and install the watched Clang release + id: watch run: | - wget https://apt.llvm.org/llvm.sh - chmod +x llvm.sh - sudo ./llvm.sh - version=$(apt-cache search --names-only '^clang-[0-9]+$' \ - | sed 's/^clang-//; s/ .*//' | sort -n | tail -1) - if [ -z "$version" ]; then - echo "No versioned clang package found in the apt.llvm.org repository" >&2 + set -euo pipefail + . /etc/os-release + codename="${UBUNTU_CODENAME:-}" + if [ -z "$codename" ]; then + echo "Could not read UBUNTU_CODENAME from /etc/os-release" >&2 exit 1 fi - sudo apt-get install -y "clang-$version" - echo "CLANG_VERSION=$version" >> "$GITHUB_ENV" + + suite="llvm-toolchain-${codename}-${CLANG_WATCH_VERSION}" + base="https://apt.llvm.org/${codename}" + index_url="${base}/dists/${suite}/main/binary-amd64/Packages.gz" + + # A 200 on dists//Release would only prove the suite exists, + # not that the compiler package is in it, so the package index itself + # is what gets probed. Capture the HTTP status without letting a + # transport failure abort the script before the branch below runs. + status=$(curl -sS -L -o /tmp/Packages.gz -w '%{http_code}' "$index_url") || { + echo "Failed to reach $index_url (curl transport error)" >&2 + exit 1 + } + + case "$status" in + 200) + ;; + 404) + echo "::notice::$suite does not exist yet at $index_url; nothing above the declared range to watch." + echo "available=false" >> "$GITHUB_OUTPUT" + exit 0 + ;; + *) + echo "Unexpected HTTP $status probing $index_url" >&2 + exit 1 + ;; + esac + + # Decompression failure (corrupt/truncated download) and "package not + # listed" are different outcomes and must not be conflated: the first + # fails the job, the second is a plain notice-and-skip. + if ! gunzip -c /tmp/Packages.gz > /tmp/Packages 2>/tmp/gunzip.err; then + echo "Failed to decompress $index_url: $(cat /tmp/gunzip.err)" >&2 + exit 1 + fi + + if ! grep -q "^Package: clang-${CLANG_WATCH_VERSION}\$" /tmp/Packages; then + echo "::notice::$suite exists but clang-$CLANG_WATCH_VERSION is not published in it yet." + echo "available=false" >> "$GITHUB_OUTPUT" + exit 0 + fi + + sudo install -m 0755 -d /etc/apt/keyrings + curl -fsSL https://apt.llvm.org/llvm-snapshot.gpg.key \ + | sudo gpg --dearmor -o /etc/apt/keyrings/llvm-snapshot.gpg + sudo chmod a+r /etc/apt/keyrings/llvm-snapshot.gpg + echo "deb [signed-by=/etc/apt/keyrings/llvm-snapshot.gpg] $base/ $suite main" \ + | sudo tee /etc/apt/sources.list.d/llvm-watch.list > /dev/null + sudo apt-get update + sudo apt-get install -y "clang-$CLANG_WATCH_VERSION" + echo "available=true" >> "$GITHUB_OUTPUT" - name: Report toolchain versions + if: steps.watch.outputs.available == 'true' run: | - clang-"$CLANG_VERSION" --version + clang-"$CLANG_WATCH_VERSION" --version cmake --version - name: Configure CMake + if: steps.watch.outputs.available == 'true' run: | cmake -S . -B build \ -DCMAKE_BUILD_TYPE=Release \ - -DCMAKE_C_COMPILER=clang-"$CLANG_VERSION" \ - -DCMAKE_CXX_COMPILER=clang++-"$CLANG_VERSION" + -DCMAKE_C_COMPILER=clang-"$CLANG_WATCH_VERSION" \ + -DCMAKE_CXX_COMPILER=clang++-"$CLANG_WATCH_VERSION" - name: Build + if: steps.watch.outputs.available == 'true' run: cmake --build build -j"$(nproc)" - name: Test + if: steps.watch.outputs.available == 'true' run: ./build/test/dross_test --gtest_color=yes floating-runners: diff --git a/README.md b/README.md index 68f140f..e0b7d71 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,12 @@ - Linux: GCC 13–15, or Clang 20–22 with either libstdc++ or libc++ - macOS: the Apple Clang shipped with macOS 15 or 26 - Newer versions are best effort, exercised by the nightly toolchain watch + - Within the declared range, the required Linux jobs build GCC 13/15 and + Clang 20/22, with the Clang jobs pairing against Ubuntu 26.04's default + libstdc++ or against libc++. GCC 14, Clang 21, and Clang against the + older libstdc++ 13/14 that Ubuntu 24.04 installs are declared but not + yet built by a required job — verification for those combinations is to + be added; this note is provisional and will be removed once it is - **CMake 3.20+** ### Installation diff --git a/docs/sphinx/source/changelog.rst b/docs/sphinx/source/changelog.rst index 7cdcb9e..62ca96e 100644 --- a/docs/sphinx/source/changelog.rst +++ b/docs/sphinx/source/changelog.rst @@ -29,6 +29,7 @@ Changed - Enhanced error handling: ``timezone::from_string()`` returns ``std::optional`` - Simplified API: removed redundant timezone methods (``is_local()``, ``has_offset()``) - Updated documentation to reflect timestamp and timezone APIs +- **Breaking:** ``split()`` now takes its arguments as ``std::string_view`` instead of ``const std::string&``; callers passing a type that converts implicitly to ``std::string`` but not to ``std::string_view`` will no longer compile v0.1.0 - 2024-01-20 ------------------- diff --git a/docs/sphinx/source/contributing.rst b/docs/sphinx/source/contributing.rst index 0b56eec..476a379 100644 --- a/docs/sphinx/source/contributing.rst +++ b/docs/sphinx/source/contributing.rst @@ -36,6 +36,12 @@ Build Requirements - C++23 compatible compiler: on Linux, GCC 13-15, or Clang 20-22 with either libstdc++ or libc++; on macOS, the Apple Clang shipped with macOS 15 or 26. Newer versions are best effort. +- Within that range, the required Linux jobs currently build GCC 13/15 and + Clang 20/22, with Clang built against Ubuntu 26.04's default libstdc++ or + against libc++. GCC 14, Clang 21, and Clang against the libstdc++ 13/14 + that Ubuntu 24.04 installs are inside the declared range but not yet built + by a required job; verification for those combinations is to be added, and + this note will be removed once it lands. - CMake 3.20 or later - Git diff --git a/docs/sphinx/source/getting-started.rst b/docs/sphinx/source/getting-started.rst index ca190ec..57c937b 100644 --- a/docs/sphinx/source/getting-started.rst +++ b/docs/sphinx/source/getting-started.rst @@ -21,8 +21,13 @@ To build and use dross, you need: releases cannot compile this library's C++23 ``std::expected`` usage against the libstdc++ they are paired with on Ubuntu 24.04 — installing the libstdc++ 14 headers alongside them does not change that either. From Clang - 20 onwards both standard libraries work, and the build matrix verifies each - of them, so neither is imposed on you. + 20 onwards both standard libraries are supported, but the required build + matrix currently exercises only Clang 20 and 22 (not the intermediate 21), + and only against Ubuntu 26.04's default libstdc++ or against libc++ — not + against the libstdc++ 13/14 that Ubuntu 24.04 installs. GCC 14 sits inside + the declared range the same way, without a required job of its own yet. + Verification for these inside-range combinations is to be added; this + paragraph will be trimmed once it is. - **Build System**: CMake 3.20 or later - **Operating System**: Linux or macOS diff --git a/include/dross/type.h b/include/dross/type.h index dc51506..729ae49 100644 --- a/include/dross/type.h +++ b/include/dross/type.h @@ -66,6 +66,8 @@ #include #include +#include +#include #include /** @@ -91,7 +93,7 @@ namespace dross { * // Result: {"a", "b", "c"} * @endcode */ -std::vector split(const std::string& s, const std::string& delimiter); +std::vector split(std::string_view s, std::string_view delimiter); /** * @brief Join string tokens into a single string using a delimiter. diff --git a/src/type.cpp b/src/type.cpp index c70db68..9fc1577 100644 --- a/src/type.cpp +++ b/src/type.cpp @@ -5,7 +5,7 @@ namespace dross { -std::vector split(const std::string& s, const std::string& delimiter) +std::vector split(std::string_view s, std::string_view delimiter) { std::vector tokens; From bc0b5f362c169bdd4bd2d00a6919dfa24481f489 Mon Sep 17 00:00:00 2001 From: Yuma Endo Date: Tue, 11 Aug 2026 16:21:00 +0900 Subject: [PATCH 2/4] ci: tell a dead Clang watch apart from one with nothing to watch yet MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A 404 on the watched suite's package index was read as "not branched yet" whatever caused it. That is right for one cause and wrong for two others: if apt.llvm.org moves or recompresses the index, or if the floating runner label moves to a codename apt.llvm.org does not carry, the job reports the same notice and goes green having built nothing. A watch that is dead but green every night is worse than one that fails, and the GCC job next to it already fails loudly when its upstream query comes back empty. Ask two more questions, but only on the 404 path, so the ordinary run costs no extra requests. If the suite's release file is served while its index is not, upstream changed where or how the index is published and this job cannot follow that silently. If the codename's own unsuffixed suite is absent, the codename is not carried at all. Only when the suite is genuinely absent from a codename that is served does the run skip with a notice. The unsuffixed suite is read here purely as a codename oracle that does not depend on any version; it is still never built from. Separate "no match" from "grep could not run" when searching the index, for the same reason: both used to end in a quiet skip. Keep the decompressed index as a real file rather than piping it into grep — grep exits on the first match, gunzip dies of SIGPIPE, and pipefail would then report a published compiler as missing. Pin the redirect protocol on the key fetch, so "upstream will not send us to http" stops being an assumption, and record next to the keyring why the key must stay scoped to this one source: the signature check during apt-get update is what authenticates anything here, not the index probe above it. Name the job for what it watches, and say in the notice what was actually observed rather than asserting there is nothing above the declared range. Restore the header's description of both jobs: each takes a compiler from outside the distribution's own repositories, which was true of the GCC job before this and still is. In the requirements notes, drop two phrasings that stated more than is measured. Which libstdc++ a Clang driver selects is derived from its search for a GCC installation rather than measured here, and Ubuntu 24.04 does not install libstdc++ 14 by default. Close the truncated sentence in the readme. --- .github/workflows/nightly.yml | 92 +++++++++++++++++++++++--- README.md | 11 +-- docs/sphinx/source/contributing.rst | 11 +-- docs/sphinx/source/getting-started.rst | 10 +-- 4 files changed, 98 insertions(+), 26 deletions(-) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index ba010de..cc7d733 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -9,9 +9,10 @@ on: # Early warning for environments outside the verified range: the newest GCC, # the Clang release next in line to enter the declared range, and the # floating runner labels. These jobs deliberately use wiring the required -# gates avoid — floating OS labels, and (for Clang) a compiler from outside -# the declared range — because breaking here is the signal we want, ahead of -# users hitting it. They never gate a pull request and must not be added to +# gates avoid — floating OS labels, and compilers pulled from outside the +# distribution's own repositories at versions above what the required gates +# verify — because breaking here is the signal we want, ahead of users +# hitting it. They never gate a pull request and must not be added to # required status checks. jobs: @@ -57,7 +58,7 @@ jobs: run: ./build/test/dross_test --gtest_color=yes newest-clang: - name: Newest Clang + name: Next Clang runs-on: ubuntu-latest # Watches the smallest "-N" apt.llvm.org suite above the declared Clang @@ -111,7 +112,48 @@ jobs: 200) ;; 404) - echo "::notice::$suite does not exist yet at $index_url; nothing above the declared range to watch." + # A bare 404 here is ambiguous: it's the expected shape while + # the suite simply hasn't been branched yet, but it is also + # what a *dead* watch looks like if apt.llvm.org has moved the + # index (e.g. to .xz/.zst) or stopped serving this codename — + # and a dead watch reporting green every night is worse than + # one that fails loudly. Two follow-up requests, made only on + # this branch, tell those cases apart. + + # Does the suite exist at all, just not with an index at this + # path? A 200 here alongside the 404 on Packages.gz means + # upstream changed how (or where) the index is served, which + # this job cannot follow silently. + release_status=$(curl -sS -L -o /dev/null -w '%{http_code}' \ + --retry 2 --retry-connrefused \ + "${base}/dists/${suite}/Release") || { + echo "Failed to reach ${base}/dists/${suite}/Release (curl transport error)" >&2 + exit 1 + } + if [ "$release_status" = "200" ]; then + echo "$suite is published (${base}/dists/${suite}/Release is 200) but its package index is not at $index_url; apt.llvm.org may have moved or recompressed it." >&2 + exit 1 + fi + + # Is this codename served by apt.llvm.org at all? The + # codename's own unsuffixed suite is published independently + # of any -N release, so it works as a version-independent + # oracle here. This job still never builds from the unsuffixed + # suite (see the header comment above) — it's read here only + # to answer "does apt.llvm.org know this codename", never as a + # source of packages. + codename_status=$(curl -sS -L -o /dev/null -w '%{http_code}' \ + --retry 2 --retry-connrefused \ + "${base}/dists/llvm-toolchain-${codename}/Release") || { + echo "Failed to reach ${base}/dists/llvm-toolchain-${codename}/Release (curl transport error)" >&2 + exit 1 + } + if [ "$codename_status" != "200" ]; then + echo "apt.llvm.org does not serve codename '$codename' (${base}/dists/llvm-toolchain-${codename}/Release is $codename_status); the ubuntu-latest label may have moved to a codename apt.llvm.org doesn't carry yet." >&2 + exit 1 + fi + + echo "::notice::$suite's package index was not found at $index_url; apt.llvm.org serves codename '$codename', so this suite simply hasn't been branched yet." echo "available=false" >> "$GITHUB_OUTPUT" exit 0 ;; @@ -123,20 +165,48 @@ jobs: # Decompression failure (corrupt/truncated download) and "package not # listed" are different outcomes and must not be conflated: the first - # fails the job, the second is a plain notice-and-skip. + # fails the job, the second is a plain notice-and-skip. /tmp/Packages + # is a real file rather than a pipe for the same reason: piping + # straight into `grep -q` would let grep exit as soon as it matched, + # killing gunzip with SIGPIPE, and pipefail would then report the + # whole pipeline as failed — misclassifying "the compiler IS + # published" as "not published yet". if ! gunzip -c /tmp/Packages.gz > /tmp/Packages 2>/tmp/gunzip.err; then echo "Failed to decompress $index_url: $(cat /tmp/gunzip.err)" >&2 exit 1 fi - if ! grep -q "^Package: clang-${CLANG_WATCH_VERSION}\$" /tmp/Packages; then - echo "::notice::$suite exists but clang-$CLANG_WATCH_VERSION is not published in it yet." - echo "available=false" >> "$GITHUB_OUTPUT" - exit 0 + # grep's exit status distinguishes "no match" (1, the expected + # not-yet-published case) from "grep itself failed" (anything else, + # e.g. an unreadable file) — the two must not be conflated, or a + # broken probe would silently read as a routine skip. + if grep -q "^Package: clang-${CLANG_WATCH_VERSION}\$" /tmp/Packages; then + grep_status=0 + else + grep_status=$? fi + case "$grep_status" in + 0) + ;; + 1) + echo "::notice::$suite exists but clang-$CLANG_WATCH_VERSION is not published in it yet." + echo "available=false" >> "$GITHUB_OUTPUT" + exit 0 + ;; + *) + echo "grep exited $grep_status searching the decompressed index from $index_url for clang-$CLANG_WATCH_VERSION" >&2 + exit 1 + ;; + esac + + # apt-get update verifies this suite's InRelease signature against + # the keyring named by signed-by below, and package hashes chain + # from that signed release — which is why the key must stay scoped + # to this one source. sudo install -m 0755 -d /etc/apt/keyrings - curl -fsSL https://apt.llvm.org/llvm-snapshot.gpg.key \ + curl -fsSL --proto '=https' --proto-redir '=https' \ + https://apt.llvm.org/llvm-snapshot.gpg.key \ | sudo gpg --dearmor -o /etc/apt/keyrings/llvm-snapshot.gpg sudo chmod a+r /etc/apt/keyrings/llvm-snapshot.gpg echo "deb [signed-by=/etc/apt/keyrings/llvm-snapshot.gpg] $base/ $suite main" \ diff --git a/README.md b/README.md index e0b7d71..b64ed60 100644 --- a/README.md +++ b/README.md @@ -28,11 +28,12 @@ - macOS: the Apple Clang shipped with macOS 15 or 26 - Newer versions are best effort, exercised by the nightly toolchain watch - Within the declared range, the required Linux jobs build GCC 13/15 and - Clang 20/22, with the Clang jobs pairing against Ubuntu 26.04's default - libstdc++ or against libc++. GCC 14, Clang 21, and Clang against the - older libstdc++ 13/14 that Ubuntu 24.04 installs are declared but not - yet built by a required job — verification for those combinations is to - be added; this note is provisional and will be removed once it is + Clang 20/22, with the Clang jobs pairing against the libstdc++ present + on Ubuntu 26.04 or against libc++. GCC 14, Clang 21, and Clang against + the older libstdc++ releases available on Ubuntu 24.04 (13 and 14) are + declared but not yet built by a required job — verification for those + combinations is to be added; this note is provisional and will be + removed once it is added. - **CMake 3.20+** ### Installation diff --git a/docs/sphinx/source/contributing.rst b/docs/sphinx/source/contributing.rst index 476a379..45473b0 100644 --- a/docs/sphinx/source/contributing.rst +++ b/docs/sphinx/source/contributing.rst @@ -37,11 +37,12 @@ Build Requirements libstdc++ or libc++; on macOS, the Apple Clang shipped with macOS 15 or 26. Newer versions are best effort. - Within that range, the required Linux jobs currently build GCC 13/15 and - Clang 20/22, with Clang built against Ubuntu 26.04's default libstdc++ or - against libc++. GCC 14, Clang 21, and Clang against the libstdc++ 13/14 - that Ubuntu 24.04 installs are inside the declared range but not yet built - by a required job; verification for those combinations is to be added, and - this note will be removed once it lands. + Clang 20/22, with Clang built against the libstdc++ present on Ubuntu + 26.04 or against libc++. GCC 14, Clang 21, and Clang against the older + libstdc++ releases available on Ubuntu 24.04 (13 and 14) are inside the + declared range but not yet built by a required job; verification for + those combinations is to be added, and this note will be removed once it + lands. - CMake 3.20 or later - Git diff --git a/docs/sphinx/source/getting-started.rst b/docs/sphinx/source/getting-started.rst index 57c937b..fe86993 100644 --- a/docs/sphinx/source/getting-started.rst +++ b/docs/sphinx/source/getting-started.rst @@ -23,11 +23,11 @@ To build and use dross, you need: libstdc++ 14 headers alongside them does not change that either. From Clang 20 onwards both standard libraries are supported, but the required build matrix currently exercises only Clang 20 and 22 (not the intermediate 21), - and only against Ubuntu 26.04's default libstdc++ or against libc++ — not - against the libstdc++ 13/14 that Ubuntu 24.04 installs. GCC 14 sits inside - the declared range the same way, without a required job of its own yet. - Verification for these inside-range combinations is to be added; this - paragraph will be trimmed once it is. + and only against the libstdc++ present on Ubuntu 26.04 or against libc++ + — not against the older libstdc++ releases available on Ubuntu 24.04 + (13 and 14). GCC 14 sits inside the declared range the same way, without + a required job of its own yet. Verification for these inside-range + combinations is to be added; this paragraph will be trimmed once it is. - **Build System**: CMake 3.20 or later - **Operating System**: Linux or macOS From a39a5532c798a95377a85e3f8bcddb12ccc2e92b Mon Sep 17 00:00:00 2001 From: Yuma Endo Date: Tue, 11 Aug 2026 16:45:38 +0900 Subject: [PATCH 3/4] ci: only skip on evidence the release is absent, not on any odd response MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The two follow-up probes decided by asking whether the response was 200, and treated everything else as its absence. A 5xx or a 403 from the suite's release file is not evidence that the suite is unbranched, yet it flowed on toward the notice-and-skip and the run ended green. Judge each strictly: 200 and 404 mean what they say, and anything else fails the job on its own rather than being read as one of them. The same gap existed one level down. When the pinned version is not listed in the package index, that reads as "not published yet" only if the index lists clang packages under that name at all. If it contains no such entry whatsoever, the naming this job searches for has itself moved, which is the same kind of stale assumption a bare 404 was hiding. The index is already on disk, so checking costs nothing. Say what was observed before naming a cause, in the two messages that did not. The skip notice now allows that the release may not have been branched yet rather than declaring it, matching the hedging the failure messages already used. Give the main index probe the retry the two it spawns already had — it runs every night and is the one most exposed to a transient blip. The header claimed these jobs take compilers above what the required gates verify. That holds for the Clang job, whose version is pinned above the declared range, but the GCC job takes the newest versioned g++ apt can see once the PPA is in place, and never compares it against anything. Say what each job actually does. In the requirements notes, separate the two groups that were sharing one sentence. Clang against the older libstdc++ releases on Ubuntu 24.04 is a gap to close, so saying verification is to be added is right. GCC 14 and Clang 21 are the middle of declared ranges whose ends are what CI verifies; they are declared and unbuilt, and promising jobs for them commits to something nothing plans to do — and would leave the note impossible to withdraw honestly. Retargeting the watch also made the neighbouring sentence stale: it still described newer versions in general as exercised by the nightly watch, when the watch now covers one release above the range and deliberately skips the development snapshot. Describe what each half of it actually tracks. Note why the index path hardcodes an architecture, and break the changelog entry across lines rather than leaving it far longer than any other entry in its list. --- .github/workflows/nightly.yml | 65 ++++++++++++++++++++------ README.md | 14 +++--- docs/sphinx/source/changelog.rst | 5 +- docs/sphinx/source/contributing.rst | 10 ++-- docs/sphinx/source/getting-started.rst | 12 +++-- 5 files changed, 74 insertions(+), 32 deletions(-) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index cc7d733..4775d86 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -10,9 +10,11 @@ on: # the Clang release next in line to enter the declared range, and the # floating runner labels. These jobs deliberately use wiring the required # gates avoid — floating OS labels, and compilers pulled from outside the -# distribution's own repositories at versions above what the required gates -# verify — because breaking here is the signal we want, ahead of users -# hitting it. They never gate a pull request and must not be added to +# distribution's own repositories — because breaking here is the signal we +# want, ahead of users hitting it. The Clang job watches a release pinned +# above the declared range; the GCC job tracks the newest g++ the toolchain +# PPA offers, which is normally above that range too but is never checked +# against it. They never gate a pull request and must not be added to # required status checks. jobs: @@ -97,13 +99,17 @@ jobs: suite="llvm-toolchain-${codename}-${CLANG_WATCH_VERSION}" base="https://apt.llvm.org/${codename}" + # binary-amd64 is hardcoded: ubuntu-latest is an x86-64 runner today, + # so that's the architecture whose package index this job needs. index_url="${base}/dists/${suite}/main/binary-amd64/Packages.gz" # A 200 on dists//Release would only prove the suite exists, # not that the compiler package is in it, so the package index itself # is what gets probed. Capture the HTTP status without letting a # transport failure abort the script before the branch below runs. - status=$(curl -sS -L -o /tmp/Packages.gz -w '%{http_code}' "$index_url") || { + status=$(curl -sS -L -o /tmp/Packages.gz -w '%{http_code}' \ + --retry 2 --retry-connrefused \ + "$index_url") || { echo "Failed to reach $index_url (curl transport error)" >&2 exit 1 } @@ -118,7 +124,10 @@ jobs: # index (e.g. to .xz/.zst) or stopped serving this codename — # and a dead watch reporting green every night is worse than # one that fails loudly. Two follow-up requests, made only on - # this branch, tell those cases apart. + # this branch, tell those cases apart. Each is judged strictly + # against 200 vs. 404: anything else (a 5xx, a 403, ...) is not + # evidence of either outcome, so it fails the job on its own + # rather than falling through to the next check. # Does the suite exist at all, just not with an index at this # path? A 200 here alongside the 404 on Packages.gz means @@ -130,10 +139,18 @@ jobs: echo "Failed to reach ${base}/dists/${suite}/Release (curl transport error)" >&2 exit 1 } - if [ "$release_status" = "200" ]; then - echo "$suite is published (${base}/dists/${suite}/Release is 200) but its package index is not at $index_url; apt.llvm.org may have moved or recompressed it." >&2 - exit 1 - fi + case "$release_status" in + 200) + echo "$suite is published (${base}/dists/${suite}/Release is 200) but its package index is not at $index_url; apt.llvm.org may have moved or recompressed it." >&2 + exit 1 + ;; + 404) + ;; + *) + echo "Unexpected HTTP $release_status probing ${base}/dists/${suite}/Release" >&2 + exit 1 + ;; + esac # Is this codename served by apt.llvm.org at all? The # codename's own unsuffixed suite is published independently @@ -148,12 +165,20 @@ jobs: echo "Failed to reach ${base}/dists/llvm-toolchain-${codename}/Release (curl transport error)" >&2 exit 1 } - if [ "$codename_status" != "200" ]; then - echo "apt.llvm.org does not serve codename '$codename' (${base}/dists/llvm-toolchain-${codename}/Release is $codename_status); the ubuntu-latest label may have moved to a codename apt.llvm.org doesn't carry yet." >&2 - exit 1 - fi - - echo "::notice::$suite's package index was not found at $index_url; apt.llvm.org serves codename '$codename', so this suite simply hasn't been branched yet." + case "$codename_status" in + 200) + ;; + 404) + echo "${base}/dists/llvm-toolchain-${codename}/Release returned 404, so apt.llvm.org does not serve codename '$codename'; the ubuntu-latest label may have moved to a codename apt.llvm.org doesn't carry yet." >&2 + exit 1 + ;; + *) + echo "Unexpected HTTP $codename_status probing ${base}/dists/llvm-toolchain-${codename}/Release" >&2 + exit 1 + ;; + esac + + echo "::notice::$suite's package index was not found at $index_url; apt.llvm.org serves codename '$codename', so this suite may simply not have been branched yet." echo "available=false" >> "$GITHUB_OUTPUT" exit 0 ;; @@ -190,6 +215,16 @@ jobs: 0) ;; 1) + # The specific version wasn't found, but that reading only holds + # if this index lists clang packages under that name at all. If + # it has no "^Package: clang-" line whatsoever, the assumption + # behind the search has gone stale the same way a bare 404 + # would have — and the file is already local, so checking costs + # no extra request. + if ! grep -q "^Package: clang-" /tmp/Packages; then + echo "$index_url has no '^Package: clang-' entries at all; the index format or clang package naming may have changed upstream." >&2 + exit 1 + fi echo "::notice::$suite exists but clang-$CLANG_WATCH_VERSION is not published in it yet." echo "available=false" >> "$GITHUB_OUTPUT" exit 0 diff --git a/README.md b/README.md index b64ed60..5d7fea4 100644 --- a/README.md +++ b/README.md @@ -26,14 +26,16 @@ - **C++23** compatible compiler, verified in CI as: - Linux: GCC 13–15, or Clang 20–22 with either libstdc++ or libc++ - macOS: the Apple Clang shipped with macOS 15 or 26 - - Newer versions are best effort, exercised by the nightly toolchain watch + - Newer versions are best effort: the nightly toolchain watch tracks the + newest GCC the toolchain PPA offers, and the specific Clang release next + in line to enter this range - Within the declared range, the required Linux jobs build GCC 13/15 and Clang 20/22, with the Clang jobs pairing against the libstdc++ present - on Ubuntu 26.04 or against libc++. GCC 14, Clang 21, and Clang against - the older libstdc++ releases available on Ubuntu 24.04 (13 and 14) are - declared but not yet built by a required job — verification for those - combinations is to be added; this note is provisional and will be - removed once it is added. + on Ubuntu 26.04 or against libc++. Clang against the older libstdc++ + releases available on Ubuntu 24.04 (13 and 14) is not yet verified; + verification for that combination is to be added, and this note is + provisional and will be removed once it is. GCC 14 and Clang 21 are + inside the declared range but are not built by a required job. - **CMake 3.20+** ### Installation diff --git a/docs/sphinx/source/changelog.rst b/docs/sphinx/source/changelog.rst index 62ca96e..8f73e21 100644 --- a/docs/sphinx/source/changelog.rst +++ b/docs/sphinx/source/changelog.rst @@ -29,7 +29,10 @@ Changed - Enhanced error handling: ``timezone::from_string()`` returns ``std::optional`` - Simplified API: removed redundant timezone methods (``is_local()``, ``has_offset()``) - Updated documentation to reflect timestamp and timezone APIs -- **Breaking:** ``split()`` now takes its arguments as ``std::string_view`` instead of ``const std::string&``; callers passing a type that converts implicitly to ``std::string`` but not to ``std::string_view`` will no longer compile +- **Breaking:** ``split()`` now takes its arguments as ``std::string_view`` + instead of ``const std::string&``; callers passing a type that converts + implicitly to ``std::string`` but not to ``std::string_view`` will no + longer compile v0.1.0 - 2024-01-20 ------------------- diff --git a/docs/sphinx/source/contributing.rst b/docs/sphinx/source/contributing.rst index 45473b0..82f11b1 100644 --- a/docs/sphinx/source/contributing.rst +++ b/docs/sphinx/source/contributing.rst @@ -38,11 +38,11 @@ Build Requirements Newer versions are best effort. - Within that range, the required Linux jobs currently build GCC 13/15 and Clang 20/22, with Clang built against the libstdc++ present on Ubuntu - 26.04 or against libc++. GCC 14, Clang 21, and Clang against the older - libstdc++ releases available on Ubuntu 24.04 (13 and 14) are inside the - declared range but not yet built by a required job; verification for - those combinations is to be added, and this note will be removed once it - lands. + 26.04 or against libc++. Clang against the older libstdc++ releases + available on Ubuntu 24.04 (13 and 14) is not yet built by a required job; + verification for that combination is to be added, and this note will be + removed once it lands. GCC 14 and Clang 21 are inside the declared range + but are not built by a required job either. - CMake 3.20 or later - Git diff --git a/docs/sphinx/source/getting-started.rst b/docs/sphinx/source/getting-started.rst index fe86993..06dfb08 100644 --- a/docs/sphinx/source/getting-started.rst +++ b/docs/sphinx/source/getting-started.rst @@ -14,8 +14,10 @@ To build and use dross, you need: or libc++ - On macOS: the Apple Clang shipped with macOS 15 or 26 - Newer versions are best effort: they are exercised by the nightly toolchain - watch rather than by the required build matrix. + Newer versions are best effort: GCC is exercised by the nightly toolchain + watch tracking the newest the toolchain PPA offers, and Clang by the same + watch tracking the specific release next in line to enter this range, + rather than by the required build matrix. The Clang lower bound is higher than the GCC one because older Clang releases cannot compile this library's C++23 ``std::expected`` usage against @@ -25,9 +27,9 @@ To build and use dross, you need: matrix currently exercises only Clang 20 and 22 (not the intermediate 21), and only against the libstdc++ present on Ubuntu 26.04 or against libc++ — not against the older libstdc++ releases available on Ubuntu 24.04 - (13 and 14). GCC 14 sits inside the declared range the same way, without - a required job of its own yet. Verification for these inside-range - combinations is to be added; this paragraph will be trimmed once it is. + (13 and 14). Verification for that lower-bound combination is to be added; + this paragraph will be trimmed once it is. GCC 14 and Clang 21 sit inside + the declared range the same way, without a required job of their own. - **Build System**: CMake 3.20 or later - **Operating System**: Linux or macOS From a4346928239be1c1cf3538e2d3f4e757b97f5631 Mon Sep 17 00:00:00 2001 From: Yuma Endo Date: Tue, 11 Aug 2026 17:19:06 +0900 Subject: [PATCH 4/4] docs: describe the GCC watch by what it does, not where the version comes from MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three places said the watch tracks the newest g++ the toolchain PPA offers. The job adds the PPA and then takes the highest versioned g++ apt can see across every configured source; the PPA is what makes a newer one available, but the value is not necessarily from it. The accurate phrasing was already in this file, above the install step — the loose one sat in the header and in two of the requirements documents, describing the same mechanism two ways. Narrow the removal promise to the sentence it belongs to. Splitting the caveat left "this note will be removed" reading as though it governed the whole thing, including the sentence about GCC 14 and Clang 21, which is not going anywhere. The getting started guide already said the paragraph would be trimmed, which is the right shape when only part of it goes. --- .github/workflows/nightly.yml | 8 ++++---- README.md | 10 +++++----- docs/sphinx/source/contributing.rst | 6 +++--- docs/sphinx/source/getting-started.rst | 7 ++++--- 4 files changed, 16 insertions(+), 15 deletions(-) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 4775d86..95400c0 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -12,10 +12,10 @@ on: # gates avoid — floating OS labels, and compilers pulled from outside the # distribution's own repositories — because breaking here is the signal we # want, ahead of users hitting it. The Clang job watches a release pinned -# above the declared range; the GCC job tracks the newest g++ the toolchain -# PPA offers, which is normally above that range too but is never checked -# against it. They never gate a pull request and must not be added to -# required status checks. +# above the declared range; the GCC job tracks the newest versioned g++ +# available once the toolchain PPA is in place, which is normally above +# that range too but is never checked against it. They never gate a pull +# request and must not be added to required status checks. jobs: newest-gcc: diff --git a/README.md b/README.md index 5d7fea4..100a1ff 100644 --- a/README.md +++ b/README.md @@ -27,15 +27,15 @@ - Linux: GCC 13–15, or Clang 20–22 with either libstdc++ or libc++ - macOS: the Apple Clang shipped with macOS 15 or 26 - Newer versions are best effort: the nightly toolchain watch tracks the - newest GCC the toolchain PPA offers, and the specific Clang release next - in line to enter this range + newest versioned GCC available once the toolchain PPA is in place, and + the specific Clang release next in line to enter this range - Within the declared range, the required Linux jobs build GCC 13/15 and Clang 20/22, with the Clang jobs pairing against the libstdc++ present on Ubuntu 26.04 or against libc++. Clang against the older libstdc++ releases available on Ubuntu 24.04 (13 and 14) is not yet verified; - verification for that combination is to be added, and this note is - provisional and will be removed once it is. GCC 14 and Clang 21 are - inside the declared range but are not built by a required job. + verification for that combination is to be added, and this sentence + will be removed once it is. GCC 14 and Clang 21 are inside the declared + range but are not built by a required job. - **CMake 3.20+** ### Installation diff --git a/docs/sphinx/source/contributing.rst b/docs/sphinx/source/contributing.rst index 82f11b1..2d668cd 100644 --- a/docs/sphinx/source/contributing.rst +++ b/docs/sphinx/source/contributing.rst @@ -40,9 +40,9 @@ Build Requirements Clang 20/22, with Clang built against the libstdc++ present on Ubuntu 26.04 or against libc++. Clang against the older libstdc++ releases available on Ubuntu 24.04 (13 and 14) is not yet built by a required job; - verification for that combination is to be added, and this note will be - removed once it lands. GCC 14 and Clang 21 are inside the declared range - but are not built by a required job either. + verification for that combination is to be added, and this sentence will + be removed once it lands. GCC 14 and Clang 21 are inside the declared + range but are not built by a required job either. - CMake 3.20 or later - Git diff --git a/docs/sphinx/source/getting-started.rst b/docs/sphinx/source/getting-started.rst index 06dfb08..5e3c258 100644 --- a/docs/sphinx/source/getting-started.rst +++ b/docs/sphinx/source/getting-started.rst @@ -15,9 +15,10 @@ To build and use dross, you need: - On macOS: the Apple Clang shipped with macOS 15 or 26 Newer versions are best effort: GCC is exercised by the nightly toolchain - watch tracking the newest the toolchain PPA offers, and Clang by the same - watch tracking the specific release next in line to enter this range, - rather than by the required build matrix. + watch tracking the newest versioned GCC available once the toolchain PPA + is in place, and Clang by the same watch tracking the specific release + next in line to enter this range, rather than by the required build + matrix. The Clang lower bound is higher than the GCC one because older Clang releases cannot compile this library's C++23 ``std::expected`` usage against