diff --git a/.github/mesa-dist-win b/.github/mesa-dist-win index cbb7c31a..b41ecb7e 100644 --- a/.github/mesa-dist-win +++ b/.github/mesa-dist-win @@ -1,5 +1,5 @@ -version=26.2.0 -archive=mesa3d-26.2.0-release-msvc.7z -sha256=dcb2719ef346dab5b609fcb193a5f13cfc4b0502e3f4de1ad43d349477402f47 -file=x64/libgallium_wgl.dll 1a2e49cd5fdb1a857d98117ab04240d723b57da5dffe6d07f5386f42014557c1 -file=x64/opengl32.dll 33b217ed7947b48684baa987914475898a2b4d7d64cce96b078216c67a633582 +version=26.2.4 +archive=mesa3d-26.2.4-release-msvc.7z +sha256=351fc8c8b695878ffb3eaa044b3ead08672a48b1a045e3c3e3975811df0f6695 +file=x64/libgallium_wgl.dll 53e49adf87590d5b0cab8553b1e98084812040cc1fca8c487695b17b7af3702e +file=x64/opengl32.dll 75b295fc80df0eaa8f1264c28663f6932c8b72d36513eb092556608858b7f5e0 diff --git a/.github/osv-scanner-digest b/.github/osv-scanner-digest index 6a0431e7..98d1e65b 100644 --- a/.github/osv-scanner-digest +++ b/.github/osv-scanner-digest @@ -1 +1 @@ -sha256:71ad04ab2f8798be47870f9b18817ad317c2f8f2f97aa6726ba10d5578bc174a +sha256:d54770fe0b09493894e76a02aaed9f51a0513fa57c5186452a755d257b0068a6 diff --git a/.github/requirements-semgrep.in b/.github/requirements-semgrep.in index 39ca490d..ba847f3c 100644 --- a/.github/requirements-semgrep.in +++ b/.github/requirements-semgrep.in @@ -20,8 +20,8 @@ # # Licence read from the pinned version rather than recalled, on 2026-08-27: # LGPL-2.1-or-later, stated by the wheel metadata as a License-Expression and -# carried in full beside it. Read again for 1.180.0 on 2026-10-14, the same. -# It analyses the tree and is never linked into either binary. +# carried in full beside it. Read again for 1.180.0 on 2026-10-14 and for +# 1.181.0 on 2026-10-26, the same. It analyses the tree and is never linked into either binary. # # This is the one line a person writes. requirements-semgrep.txt next to it is # every package that line installs, pinned, and it is compiled from this file @@ -43,4 +43,12 @@ # job uses and the pip-tools Dependabot runs: # # docker run --rm -v "$PWD/.github:/w" -w /w python:3.14-slim sh -c "pip install -q pip==26.1.1 pip-tools==7.5.3 && pip-compile --strip-extras --no-emit-index-url --output-file=requirements-semgrep.txt requirements-semgrep.in" -semgrep==1.180.0 +# +# To raise every package rather than only what a new line needs, add --upgrade, +# and hold back what is younger than a week the way the cooldown in +# .github/dependabot.yml does, with --pip-args '--uploaded-prior-to='. A security fix is the exception, as it is +# for Dependabot: certifi 2026.10.23 (new roots, #204) is younger than that and +# was put back by hand on 2026-10-26. Then run the plain command above once +# more. If it changes nothing, pip accepts the set as it stands. +semgrep==1.181.0 diff --git a/.github/requirements-semgrep.txt b/.github/requirements-semgrep.txt index 2caef892..fa683060 100644 --- a/.github/requirements-semgrep.txt +++ b/.github/requirements-semgrep.txt @@ -168,11 +168,11 @@ ruamel-yaml-clib==0.2.15 # via semgrep semantic-version==2.10.0 # via semgrep -semgrep==1.180.0 +semgrep==1.181.0 # via -r requirements-semgrep.in sse-starlette==3.5.0 # via mcp -starlette==1.8.0 +starlette==1.9.0 # via # mcp # sse-starlette diff --git a/.github/scripts/tool_versions.py b/.github/scripts/tool_versions.py index 875dec0b..ac5254ff 100644 --- a/.github/scripts/tool_versions.py +++ b/.github/scripts/tool_versions.py @@ -1,86 +1,310 @@ -"""Are the tool versions pinned in ci.yml still the current ones? +"""Are the versions this repository's CI pins still the current ones? -Reads the pins out of the workflows rather than carrying its own copy, because +Covers what Dependabot does not read. Dependabot reads go.mod, `uses:` and +requirements-semgrep.in. Everything below is a version written into a shell +command or a file of our own, so nothing else will ever say it went stale: + +- `go run module@version` in the workflows - asked of the Go module proxy +- GO_VERSION in the workflows - asked of go.dev/dl +- the release of the software renderer in .github/mesa-dist-win - asked of + that project's GitHub releases +- `npm install package@version` in the workflows - asked of the npm registry +- python-version and the WiX version - held back on purpose, see HELD + +Reads the pins out of the repository rather than carrying its own copy, because a list copied into a checker stops describing the thing it checks the moment somebody edits the original. -Asks the Go MODULE PROXY, not the GitHub releases API, and that is the whole -correctness of this file. The first version asked GitHub and produced two false -alarms out of three: staticcheck releases under two names at once, so v0.8.1 was -reported behind "2026.2.1" when they are the same thing, and golang.org/x/vuln -answered with v1.1.4 as its latest while the pin was already on v1.7.0. A pin is -a MODULE VERSION - `go run module@version` - so the module system is the thing -that knows what the newest one is, and it answers in the same words the pin is -written in. +Each pin is asked of the registry its own install command reads, not of the +GitHub releases page, and that is the whole correctness of this file. The first +version asked GitHub and produced two false alarms out of three: staticcheck +releases under two names at once, so v0.8.1 was reported behind "2026.2.1" when +they are the same thing, and golang.org/x/vuln answered with v1.1.4 as its +latest while the pin was already on v1.7.0. A pin is written in the words of the +thing that installs it, so that thing is what knows what the newest one is. + +A version younger than a week is not yet due. That is the cooldown in +.github/dependabot.yml, which holds a release back for seven days because the +tj-actions and trivy-action compromises were poisoned releases pulled in within +hours of publication, and the owner chose the same hold for everything bumped by +hand on 2026-10-26. It is printed, so a reader sees it coming, and it does not +fail the run. The Go toolchain is the exception: its point releases are security +releases more often than not, and the cooldown does not hold back security fixes +for Dependabot either. + +For a Go module the age is its COMMIT time, the only date the module proxy +gives (`Time` in `.info`), and a commit is never later than its release - so a +tag pushed today onto an older commit counts as older than it is, and can be +due before a week has passed. golangci-lint 2.15.0: commit 10:51, release 11:33 +the same day. When the proxy first saw a version is known to index.golang.org, +but only as one feed of every module there is: on 2026-10-27 two thousand lines +covered nineteen minutes, so a week is half a million lines. Not asked, and +said here instead (review of #205). That matters more than tidiness here. A gate that cries wolf gets ignored, and -an ignored gate is what this whole file was written to replace. +an ignored gate is what this whole file was written to replace. For the same +reason a decision the owner has taken is printed as a note and not as a +failure every Monday - see HELD. -Exits non-zero when a pin is behind, and also when it finds no pin at all: a -checker that quietly checks nothing is the same failure wearing a green tick. +Exits non-zero when a pin is behind, when a registry cannot be asked after a +few tries, and when it finds no pin at all: a checker that quietly checks +nothing is the same failure wearing a green tick. """ +import datetime import json +import os import pathlib import re import sys +import time import urllib.request -WORKFLOWS = pathlib.Path(__file__).resolve().parents[1] / "workflows" -PROXY = "https://proxy.golang.org/{}/@latest" +ROOT = pathlib.Path(__file__).resolve().parents[2] +WORKFLOWS = ROOT / ".github" / "workflows" +RENDERER_PIN = ROOT / ".github" / "mesa-dist-win" +RENDERER_PROJECT = "pal1000/mesa-dist-win" + +HOLD = datetime.timedelta(days=7) + +# Pins the owner holds where they are on purpose. A newer line is printed with +# the reason and never fails the run. A newer release INSIDE the held line is +# still due, and fails like any other. +HELD = { + "python": "semgrep runs on Python 3.14 at most (owner, 2026-10-26)", + "wix": "WiX 6 and 7 come under the OSMF EULA, 5.0.2 is MS-RL with no agreement " + "(owner, 2026-10-26, docs/PACKAGING-2026-09-25.md section 6)", +} + +# A registry that does not answer is asked again before the run fails. The run +# of 2026-10-26 went red on one read timeout from the module proxy, with every +# pin current. +RETRY_WAITS = (0, 5, 20) + +# The most this reads of one answer. The largest real one, go.dev/dl with every +# Go release ever made, was 2.3 MB on 2026-10-27, and the npm document of +# mailparser 0.4 MB. An answer past this is refused rather than parsed. +MAX_ANSWER = 32 * 1024 * 1024 + + +class AnswerTooLarge(Exception): + """A registry answered with more than MAX_ANSWER bytes. Not asked again.""" + + +def ask(url, raw=False): + """The registry's answer, asked again after a pause when it does not come.""" + headers = {"User-Agent": "tool-versions"} + token = os.environ.get("GH_TOKEN") + if token and url.startswith("https://api.github.com/"): + headers["Authorization"] = "Bearer " + token + failure = None + for wait in RETRY_WAITS: + time.sleep(wait) + try: + request = urllib.request.Request(url, headers=headers) + with urllib.request.urlopen(request, timeout=30) as r: # noqa: S310 - fixed https hosts + body = r.read(MAX_ANSWER + 1) + if len(body) > MAX_ANSWER: + raise AnswerTooLarge(f"{url} answered with more than {MAX_ANSWER} bytes, which is not " + "the shape of a version list - refused rather than read") + text = body.decode("utf-8") + return text if raw else json.loads(text) + except AnswerTooLarge: + raise + except Exception as exc: # noqa: BLE001 - every failure is retried, then loud + failure = exc + raise RuntimeError(f"{url} did not answer after {len(RETRY_WAITS)} tries: {failure}") + + +def release_key(version): + """A version as a comparable tuple, or None for a pre-release.""" + bare = re.sub(r"^(v|go)", "", version) + if not re.fullmatch(r"\d+(\.\d+)*", bare): + return None + return tuple(int(part) for part in bare.split(".")) + + +def stamp(text): + """A registry's timestamp as an aware datetime.""" + return datetime.datetime.fromisoformat(text.replace("Z", "+00:00")) + +def workflow_text(): + return {p.name: p.read_text(encoding="utf-8") for p in sorted(WORKFLOWS.glob("*.yml"))} -def pins(): - """Every `go run module/path/cmd/x@version` this repository's workflows run.""" + +def single(found, what): + """The one value a pattern found across the workflows, or a failure.""" + values = sorted(set(found)) + if not values: + raise RuntimeError(f"no {what} was found in the workflows, so this checked nothing") + if len(values) > 1: + raise RuntimeError(f"the workflows disagree about {what}: {', '.join(values)}") + return values[0] + + +def due(pinned, released, now): + """Compare a pin with every release and its date: the row to print and whether it fails. + + released maps a version to when it was published. Only the newest release + outside the hold is due. A newer one inside it is mentioned. + """ + mine = release_key(pinned) + later = sorted( + ((release_key(v), v, when) for v, when in released.items() + if release_key(v) is not None and release_key(v) > mine), + reverse=True, + ) + owed = [v for _, v, when in later if now - when >= HOLD] + waiting = [(v, when) for _, v, when in later if now - when < HOLD] + note = "" + if waiting: + v, when = waiting[0] + note = f", {v} is {(now - when).days} day(s) old and waits out the week's hold" + if owed: + return f"BEHIND, {owed[0]} is due" + note, owed[0] + return "current" + note, None + + +def go_tools(texts, now): + """`go run module/cmd/x@version` - asked of the module proxy.""" + # Every pin of a module, not the last one read: golangci-lint is run in two + # steps of ci.yml, and a stale first step behind a current second one is + # still a stale tool (review of #205). found = {} - for path in sorted(WORKFLOWS.glob("*.yml")): - text = path.read_text(encoding="utf-8") + for text in texts.values(): for m in re.finditer(r"go run ([\w./-]+?)/cmd/[\w-]+@(v[\w.+-]+)", text): + found.setdefault(m.group(1), []).append(m.group(2)) + if not found: + raise RuntimeError("no `go run module@version` was found in the workflows, so this checked nothing") + rows = [] + for module, versions in sorted(found.items()): + pinned = single(versions, f"the version of {module}") + # Module paths are case encoded for the proxy: an upper case letter + # becomes "!" and the lower case letter. None of ours have one today, + # and doing it anyway costs a line and stops a silent 404 the day one does. + encoded = re.sub(r"[A-Z]", lambda c: "!" + c.group(0).lower(), module) + base = f"https://proxy.golang.org/{encoded}/@v/" + newer = [v for v in ask(base + "list", raw=True).split() + if release_key(v) is not None and release_key(v) > release_key(pinned)] + released = {v: stamp(ask(base + v + ".info")["Time"]) for v in newer} + rows.append((module, pinned) + due(pinned, released, now)) + return rows + + +def go_toolchain(texts): + """GO_VERSION - asked of go.dev/dl, without the hold.""" + pinned = single(re.findall(r'GO_VERSION:\s*"([\d.]+)"', "\n".join(texts.values())), "GO_VERSION") + line = pinned.rsplit(".", 1)[0] + stable = [x["version"][2:] for x in ask("https://go.dev/dl/?mode=json&include=all") if x.get("stable")] + same_line = sorted((v for v in stable if v.rsplit(".", 1)[0] == line), key=release_key) + newer_lines = sorted((v for v in stable if release_key(v)[:2] > release_key(pinned)[:2]), key=release_key) + newest = same_line[-1] if same_line else pinned + note = "" + if newer_lines: + note = (f", {newer_lines[-1]} starts a newer line - moving to it is a byte stability " + "question (D11) and the owner's call") + if release_key(newest) > release_key(pinned): + return [("go (GO_VERSION)", pinned, f"BEHIND, {newest} is due" + note, newest)] + return [("go (GO_VERSION)", pinned, "current" + note, None)] + + +def renderer(now): + """The release of the software renderer the Windows archive carries.""" + text = RENDERER_PIN.read_text(encoding="utf-8") + m = re.search(r"^version=(\S+)$", text, re.M) + if not m: + raise RuntimeError(f"{RENDERER_PIN.name} names no version, so this checked nothing") + pinned = m.group(1) + released = { + r["tag_name"]: stamp(r["published_at"]) + for r in ask(f"https://api.github.com/repos/{RENDERER_PROJECT}/releases?per_page=30") + if not r.get("draft") and not r.get("prerelease") and r.get("published_at") + } + return [(RENDERER_PROJECT, pinned) + due(pinned, released, now)] + + +def npm_packages(texts, now): + """`npm install package@version` - asked of the npm registry.""" + # An npm install that names no version is a failure, not a line skipped: + # without this a pin taken off the command would take the package off this + # check with it, and the run would stay green (review of #205). + found = {} + for name, text in texts.items(): + for line in text.splitlines(): + if "npm install" not in line or line.lstrip().startswith("#"): + continue + m = re.search(r"\s([@\w./-]+)@(\d[\w.+-]*)\s*$", line) + if not m: + raise RuntimeError(f"{name} runs an npm install that pins no version: {line.strip()}") found[m.group(1)] = m.group(2) - return found + rows = [] + for package, pinned in sorted(found.items()): + times = ask(f"https://registry.npmjs.org/{package}")["time"] + released = {v: stamp(t) for v, t in times.items() if release_key(v) is not None} + rows.append((package + " (npm)", pinned) + due(pinned, released, now)) + return rows -def latest(module): - """What the module proxy calls the newest version of this module.""" - # Module paths are case encoded for the proxy: an upper case letter becomes - # "!" and the lower case letter. None of ours have one today, and doing it - # anyway costs a line and stops a silent 404 the day one does. - encoded = re.sub(r"[A-Z]", lambda c: "!" + c.group(0).lower(), module) - with urllib.request.urlopen(PROXY.format(encoded), timeout=30) as r: # noqa: S310 - fixed https host - return json.load(r)["Version"] +def held(texts): + """Pins the owner holds: a newer line is a note, a newer release inside the line is due.""" + rows = [] + python = single(re.findall(r'python-version:\s*"([\d.]+)"', "\n".join(texts.values())), "python-version") + finals = [re.sub(r"^Python ", "", r["name"]) + for r in ask("https://www.python.org/api/v2/downloads/release/?is_published=true&pre_release=false")] + finals = sorted((v for v in finals if release_key(v) is not None), key=release_key) + state = "current" + if finals and release_key(finals[-1])[:2] > release_key(python)[:2]: + state = f"held, {finals[-1]} exists - {HELD['python']}" + # setup-python takes the newest patch of the line itself, so the line is the pin. + rows.append(("python (python-version)", python, state, None)) + wix = single(re.findall(r"dotnet tool install --global wix --version ([\d.]+)", "\n".join(texts.values())), "the WiX version") + stable = sorted((v for v in ask("https://api.nuget.org/v3-flatcontainer/wix/index.json")["versions"] + if release_key(v) is not None), key=release_key) + same_major = [v for v in stable if release_key(v)[0] == release_key(wix)[0]] + if same_major and release_key(same_major[-1]) > release_key(wix): + rows.append(("wix (dotnet tool)", wix, f"BEHIND, {same_major[-1]} is due", same_major[-1])) + elif stable and release_key(stable[-1])[0] > release_key(wix)[0]: + rows.append(("wix (dotnet tool)", wix, f"held, {stable[-1]} exists - {HELD['wix']}", None)) + else: + rows.append(("wix (dotnet tool)", wix, "current", None)) + return rows -def main(): - found = pins() - if not found: - print("FAIL: no pinned tool was found in the workflows, so this checked nothing") - return 1 - behind = [] - for module, pinned in sorted(found.items()): +def main(): + now = datetime.datetime.now(datetime.timezone.utc) + texts = workflow_text() + rows = [] + for check in (lambda: go_tools(texts, now), lambda: go_toolchain(texts), lambda: renderer(now), + lambda: npm_packages(texts, now), lambda: held(texts)): try: - now = latest(module) + rows.extend(check()) except Exception as exc: # noqa: BLE001 - any failure here has to be loud - print(f"FAIL: could not ask the module proxy about {module}: {exc}") + print(f"FAIL: {exc}") + print("Run the workflow again. If it fails the same way, the registry or the pin") + print("named above has changed shape, and this script has to follow it.") return 1 - state = "current" if now == pinned else f"BEHIND, latest is {now}" - print(f" {module:<42} {pinned:<10} {state}") - if now != pinned: - behind.append((module, pinned, now)) + + for name, pinned, state, _ in rows: + print(f" {name:<42} {pinned:<10} {state}") + behind = [(name, pinned, to) for name, pinned, _, to in rows if to] print() if not behind: - print(f"all {len(found)} pinned tool(s) are current") + print(f"all {len(rows)} pin(s) are current or held on purpose") return 0 - print(f"{len(behind)} pinned tool(s) are behind:") - for module, pinned, now in behind: - print(f" {module} {pinned} -> {now}") + print(f"{len(behind)} pin(s) are behind:") + for name, pinned, to in behind: + print(f" {name} {pinned} -> {to}") print() - print("Nothing else watches these. Dependabot reads go.mod and `uses:`, and these are shell") - print("commands, so this job is the only thing that will ever say so. Raise them in .github/") - print("workflows/ci.yml, and check the new version against this tree before merging - the last") - print("two of these to go stale had stopped working with the compiler entirely.") + print("Nothing else watches these. Dependabot reads go.mod, `uses:` and requirements-semgrep.in,") + print("and these are shell commands and files of our own, so this job is the only thing that will") + print("ever say so. Raise each where it is written - .github/workflows, or .github/mesa-dist-win") + print("together with internal/legal/companions.go and THIRD-PARTY-NOTICES.md - and check the new") + print("version against this tree before merging. The last two of the Go tools to go stale had") + print("stopped working with the compiler entirely.") return 1 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 11e6cdf7..5bd349fe 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -994,7 +994,7 @@ jobs: # Pinned by commit like every other action here. The scan is evidence, # not the document: its job is to ask whether the built binaries contain # something the registry does not know about. - uses: anchore/sbom-action@66cbf4bc1f1c0d2edc94016e65bc221b6bb0ad6c # v0.24.0 + uses: anchore/sbom-action@66cbf4bc1f1c0d2edc94016e65bc221b6bb0ad6c # v0.24.3 with: path: dist format: syft-json @@ -1397,7 +1397,7 @@ jobs: # licence gate then blocks two packages of it (review of #173, # docs/REVIEW-173-2026-10-07.md). Whether CI-only tools belong under # that gate is the owner's decision, not a fix. - npm install --prefix "$RUNNER_TEMP/mailparser" mailparser@3.9.36 + npm install --prefix "$RUNNER_TEMP/mailparser" mailparser@3.10.0 echo "TFG_MAILPARSER=$RUNNER_TEMP/mailparser/node_modules/mailparser" >> "$GITHUB_ENV" node -e "console.log('mailparser', require(process.argv[1] + '/package.json').version)" "$RUNNER_TEMP/mailparser/node_modules/mailparser" diff --git a/.github/workflows/osv-pull-request.yml b/.github/workflows/osv-pull-request.yml index baedae3c..3a21fba4 100644 --- a/.github/workflows/osv-pull-request.yml +++ b/.github/workflows/osv-pull-request.yml @@ -82,7 +82,7 @@ jobs: # function is reachable is what the govulncheck job answers. - name: scan the branch this merges into id: old - uses: google/osv-scanner-action/osv-scanner-action@a345acffa64b0eaede81a3d9aae6141214d9c8fc # v2.6.0 + uses: google/osv-scanner-action/osv-scanner-action@b1d267aea5211fa648d9d442fa64b90dbdcbdd36 # v2.7.0 continue-on-error: true with: scan-args: |- @@ -99,7 +99,7 @@ jobs: - name: scan the merge of this pull request id: new - uses: google/osv-scanner-action/osv-scanner-action@a345acffa64b0eaede81a3d9aae6141214d9c8fc # v2.6.0 + uses: google/osv-scanner-action/osv-scanner-action@b1d267aea5211fa648d9d442fa64b90dbdcbdd36 # v2.7.0 continue-on-error: true with: scan-args: |- @@ -138,7 +138,7 @@ jobs: # table come out byte for byte as they did under the deprecated # --output and --gh-annotations (docs/OSV-2-2026-10-15.md). - name: what this pull request adds - uses: google/osv-scanner-action/osv-reporter-action@a345acffa64b0eaede81a3d9aae6141214d9c8fc # v2.6.0 + uses: google/osv-scanner-action/osv-reporter-action@b1d267aea5211fa648d9d442fa64b90dbdcbdd36 # v2.7.0 with: scan-args: |- --old=osv-old.json diff --git a/.github/workflows/osv-weekly.yml b/.github/workflows/osv-weekly.yml index 9b2f0454..8f82a269 100644 --- a/.github/workflows/osv-weekly.yml +++ b/.github/workflows/osv-weekly.yml @@ -67,7 +67,7 @@ jobs: - name: scan id: scan - uses: google/osv-scanner-action/osv-scanner-action@a345acffa64b0eaede81a3d9aae6141214d9c8fc # v2.6.0 + uses: google/osv-scanner-action/osv-scanner-action@b1d267aea5211fa648d9d442fa64b90dbdcbdd36 # v2.7.0 continue-on-error: true with: scan-args: |- @@ -93,7 +93,7 @@ jobs: # way the deprecated --output printed it, measured byte for byte # 2026-10-15 (docs/OSV-2-2026-10-15.md). - name: results for the Security tab - uses: google/osv-scanner-action/osv-reporter-action@a345acffa64b0eaede81a3d9aae6141214d9c8fc # v2.6.0 + uses: google/osv-scanner-action/osv-reporter-action@b1d267aea5211fa648d9d442fa64b90dbdcbdd36 # v2.7.0 with: scan-args: |- --new=osv-results.json @@ -102,7 +102,7 @@ jobs: - name: upload to the Security tab if: ${{ !cancelled() && hashFiles('osv-results.sarif') != '' }} - uses: github/codeql-action/upload-sarif@24c54180a607b1449ed407dd24f251e4e9147c8d # v4.38.3 + uses: github/codeql-action/upload-sarif@6f2ac81f5cd81fe351a197ba0b00d91d03cd2aee # v4.39.0 with: sarif_file: osv-results.sarif category: osv-scanner diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml index c58709d7..d0623138 100644 --- a/.github/workflows/pages.yml +++ b/.github/workflows/pages.yml @@ -86,4 +86,4 @@ jobs: path: web/public - id: deployment - uses: actions/deploy-pages@368f82528645a54fb793d4d04e342629a3f51346 # v5.0.0 + uses: actions/deploy-pages@368f82528645a54fb793d4d04e342629a3f51346 # v5.0.1 diff --git a/.github/workflows/tool-versions.yml b/.github/workflows/tool-versions.yml index 68dc02b7..9fb76e25 100644 --- a/.github/workflows/tool-versions.yml +++ b/.github/workflows/tool-versions.yml @@ -1,9 +1,15 @@ -# Are the tools CI pins still the current ones? +# Are the versions CI pins still the current ones? # -# Dependabot cannot answer this. It reads go.mod for Go modules and `uses:` for -# actions, and staticcheck, govulncheck and golangci-lint are none of those - -# they are shell commands inside a workflow step. Measured 2026-09-02: thirty -# pull requests from that bot, not one about any of them. +# Dependabot cannot answer this. It reads go.mod for Go modules, `uses:` for +# actions and requirements-semgrep.in, and staticcheck, govulncheck and +# golangci-lint are none of those - they are shell commands inside a workflow +# step. Measured 2026-09-02: thirty pull requests from that bot, not one about +# any of them. Since 2026-10-27 the same job asks about GO_VERSION, the +# software renderer the Windows archive ships (.github/mesa-dist-win, which sat +# four releases behind with nothing to say so), the npm package the mail check +# installs, and the two pins the owner holds on purpose (Python, WiX), which it +# prints and does not fail on. What it asks and why: the docstring of +# .github/scripts/tool_versions.py. # # The cost of nobody watching was paid on 2026-09-01. staticcheck was pinned to # a version that could not read Go 1.27 at all, and govulncheck to one that diff --git a/CHANGELOG.md b/CHANGELOG.md index 055dfea7..e95c3a8c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,15 @@ because it turns other people's test suites red. `--user "$(id -u):$(id -g)"` to write there. README also shows a step that installs `tfg` on Windows and macOS runners in GitHub Actions. +### Changed + +- **The Windows archive of the window carries Mesa 26.2.4.** The software + OpenGL renderer in the `opengl` folder, which the window loads only after + the graphics toolkit could not open a window, or when it is started with + `--software-gl`, moves from 26.2.0 to 26.2.4, built with LLVM 23.1.2. Its + licences are the same. `THIRD-PARTY-NOTICES.md` names the new files and + their sums. + ### Fixed - **`tfg cleanup --yes` keeps a file that changed after it was checked.** diff --git a/THIRD-PARTY-NOTICES.md b/THIRD-PARTY-NOTICES.md index 910b4df6..d07cb68a 100644 --- a/THIRD-PARTY-NOTICES.md +++ b/THIRD-PARTY-NOTICES.md @@ -836,38 +836,39 @@ offered the toolkit less than it needs. | what | files in the archive | licence | copyright | |---|---|---|---| -| Mesa 3D, llvmpipe software renderer, 26.2.0 | `opengl/libgallium_wgl.dll` and `opengl/opengl32.dll` | MIT AND Apache-2.0 WITH LLVM-exception AND BSL-1.0 | Copyright (C) 1999-2007 Brian Paul, Copyright (C) 2008 VMware, Inc. | +| Mesa 3D, llvmpipe software renderer, 26.2.4 | `opengl/libgallium_wgl.dll` and `opengl/opengl32.dll` | MIT AND Apache-2.0 WITH LLVM-exception AND BSL-1.0 | Copyright (C) 1999-2007 Brian Paul, Copyright (C) 2008 VMware, Inc. | -The two files are taken from `x64/` of `mesa3d-26.2.0-release-msvc.7z`, the -MSVC release archive of the pal1000/mesa-dist-win project, version 26.2.0, +The two files are taken from `x64/` of `mesa3d-26.2.4-release-msvc.7z`, the +MSVC release archive of the pal1000/mesa-dist-win project, version 26.2.4, whose SHA-256 is -`dcb2719ef346dab5b609fcb193a5f13cfc4b0502e3f4de1ad43d349477402f47`. The +`351fc8c8b695878ffb3eaa044b3ead08672a48b1a045e3c3e3975811df0f6695`. The release workflow downloads that archive, checks the sum before it unpacks anything, and puts exactly these two files into the Windows archive of the window: | file | bytes | SHA-256 | |---|---|---| -| `opengl/libgallium_wgl.dll` | 61734400 | `1a2e49cd5fdb1a857d98117ab04240d723b57da5dffe6d07f5386f42014557c1` | -| `opengl/opengl32.dll` | 139264 | `33b217ed7947b48684baa987914475898a2b4d7d64cce96b078216c67a633582` | +| `opengl/libgallium_wgl.dll` | 61868032 | `53e49adf87590d5b0cab8553b1e98084812040cc1fca8c487695b17b7af3702e` | +| `opengl/opengl32.dll` | 139264 | `75b295fc80df0eaa8f1264c28663f6932c8b72d36513eb092556608858b7f5e0` | -The archive carries no licence file of its own - checked on 2026-09-17, it -holds one readme pointing at a web page - so what is compiled into the two +The archive carries no licence file of its own - checked on 2026-09-17 and +again for 26.2.4 on 2026-10-26, it holds one readme pointing at a web page +and two deployment scripts - so what is compiled into the two files was read from the sources of the pinned versions, and the bytes of the renderer were asked which of the build's components they hold: -- **Mesa 26.2.0** is MIT: the core, the llvmpipe driver and the WGL frontend. +- **Mesa 26.2.4** is MIT: the core, the llvmpipe driver and the WGL frontend. The core's line is quoted in the table, the driver is Copyright 2007 - VMware, Inc. Read from `docs/license.rst` and `licenses/` of - `mesa-26.2.0.tar.xz`. Two things in that tree carry a GPL identifier and + VMware, Inc. Read from `docs/license.rst` and `licenses/` of Mesa at the + `mesa-26.2.4` tag. Two things in that tree carry a GPL identifier and neither is in these files: Linux kernel headers under `include/drm-uapi`, and headers of the freedreno and svga drivers, none of which a Windows build compiles. -- **LLVM 22.1.8**, compiled in for llvmpipe's code generation, is Apache-2.0 +- **LLVM 23.1.2**, compiled in for llvmpipe's code generation, is Apache-2.0 WITH LLVM-exception. Its licence file states no copyright line under that licence, and the one it does carry - Copyright (c) 2003-2019 University of Illinois at Urbana-Champaign - belongs to the legacy licence the same file - reproduces. Read from `llvm/LICENSE.TXT` at `llvmorg-22.1.8`. + reproduces. Read from `llvm/LICENSE.TXT` at `llvmorg-23.1.2`. - The **C11 threads shim** Mesa compiles on Windows, `src/c11/impl/threads_win32.c`, is BSL-1.0, Copyright yohhoy 2012. - The **Direct3D 12 headers**, 1.619.5, used by the d3d12 driver that the same @@ -883,7 +884,7 @@ reproduced from the files named beside them. ### LLVM-exception -From `llvm/LICENSE.TXT` at `llvmorg-22.1.8`, the exceptions that follow the +From `llvm/LICENSE.TXT` at `llvmorg-23.1.2`, the exceptions that follow the Apache License, Version 2.0 there. ``` @@ -906,7 +907,7 @@ Software. ### BSL-1.0 -From `licenses/BSL-1.0` of `mesa-26.2.0.tar.xz`. +From `licenses/BSL-1.0` of Mesa at the `mesa-26.2.4` tag. ``` Boost Software License - Version 1.0 - August 17th, 2003 diff --git a/internal/guard/mutation/entries.py b/internal/guard/mutation/entries.py index 7878888f..16adc19d 100644 --- a/internal/guard/mutation/entries.py +++ b/internal/guard/mutation/entries.py @@ -9628,8 +9628,8 @@ # archive would be packed with the wrong name. "the registry names a file the window never loads", "internal/legal/companions.go", - "{Path: \"opengl/libgallium_wgl.dll\", Size: 61734400,", - "{Path: \"opengl/libgallium.dll\", Size: 61734400,", + "{Path: \"opengl/libgallium_wgl.dll\", Size: 61868032,", + "{Path: \"opengl/libgallium.dll\", Size: 61868032,", "TestTheRegistryNamesTheFilesTheWindowLoads", ), ( @@ -9656,8 +9656,8 @@ # the notices describe another. "the renderer pin names a release the registry does not", ".github/mesa-dist-win", - "version=26.2.0", - "version=26.2.1", + "version=26.2.4", + "version=26.2.5", "TestTheRendererPinAgreesWithTheRegistry", ), ( diff --git a/internal/guard/notelemetry_test.go b/internal/guard/notelemetry_test.go index d25bb2a4..ac0a2d58 100644 --- a/internal/guard/notelemetry_test.go +++ b/internal/guard/notelemetry_test.go @@ -189,7 +189,7 @@ var allowedURLs = map[string]string{ "internal/format/rtf/links.go|ftp://example.com/file.txt": "a link written into a document, on a domain kept for examples", "internal/format/rtf/links.go|https://example.org/new": "a link written into a document, on a domain kept for examples", "internal/format/rtf/links.go|https://example.net/tip": "a link written into a document, on a domain kept for examples", - "internal/legal/companions.go|https://github.com/pal1000/mesa-dist-win/releases/download/26.2.0/mesa3d-26.2.0-release-msvc.7z": "where the software " + + "internal/legal/companions.go|https://github.com/pal1000/mesa-dist-win/releases/download/26.2.4/mesa3d-26.2.4-release-msvc.7z": "where the software " + "renderer's bytes were downloaded FROM, by the release workflow and never by the program: written into the bill of " + "materials as the package's download location, and compared with the workflow's pin by a guard", } diff --git a/internal/guard/testdata/screens/about.xml b/internal/guard/testdata/screens/about.xml index 97fe2a5a..562591ed 100644 --- a/internal/guard/testdata/screens/about.xml +++ b/internal/guard/testdata/screens/about.xml @@ -1132,7 +1132,7 @@ Mesa 3D, llvmpipe software - renderer 26.2.0 + renderer 26.2.4 diff --git a/internal/legal/companions.go b/internal/legal/companions.go index c6963a30..c872fd19 100644 --- a/internal/legal/companions.go +++ b/internal/legal/companions.go @@ -75,12 +75,14 @@ type CompanionSource struct { // companions is the reviewed list. // // Everything below was read on 2026-09-17 from the files of the pinned -// versions: docs/license.rst and licenses/ of mesa-26.2.0.tar.xz from -// archive.mesa3d.org, buildinfo/msvc.txt of pal1000/mesa-dist-win at its -// 26.2.0 tag, llvm/LICENSE.TXT at llvmorg-22.1.8, and LICENSE of -// microsoft/DirectX-Headers at v1.619.5. What is inside the shipped file was -// measured in its bytes rather than taken from the build list: it names -// "Mesa 26.2.0" and "LLVM 22.1.8", carries the llvmpipe, d3d12, zink and +// versions, and again on 2026-10-26 for 26.2.4: docs/license.rst and +// licenses/ of Mesa at the mesa-26.2.4 tag, buildinfo/msvc.txt of +// pal1000/mesa-dist-win at its 26.2.4 tag, llvm/LICENSE.TXT at +// llvmorg-23.1.2 (byte for byte the file of llvmorg-22.1.8 that 26.2.0 was +// built with), and LICENSE of microsoft/DirectX-Headers at v1.619.5. What is +// inside the shipped file was measured in its bytes rather than taken from +// the build list: it names "Mesa 26.2.4" and "LLVM 23.1.2", carries the +// llvmpipe, d3d12, zink and // softpipe drivers and the D3D12 headers, and holds neither zlib's nor // zstd's code - the only mention of zlib is LLVM saying it was built without // it. Its imports are system libraries only, so it needs no runtime @@ -96,23 +98,23 @@ var companions = []Companion{ Binary: "tfg-gui", Platform: "windows/amd64", Files: []CompanionFile{ - {Path: "opengl/libgallium_wgl.dll", Size: 61734400, SHA256: "1a2e49cd5fdb1a857d98117ab04240d723b57da5dffe6d07f5386f42014557c1"}, - {Path: "opengl/opengl32.dll", Size: 139264, SHA256: "33b217ed7947b48684baa987914475898a2b4d7d64cce96b078216c67a633582"}, + {Path: "opengl/libgallium_wgl.dll", Size: 61868032, SHA256: "53e49adf87590d5b0cab8553b1e98084812040cc1fca8c487695b17b7af3702e"}, + {Path: "opengl/opengl32.dll", Size: 139264, SHA256: "75b295fc80df0eaa8f1264c28663f6932c8b72d36513eb092556608858b7f5e0"}, }, SPDX: "MIT AND Apache-2.0 WITH LLVM-exception AND BSL-1.0", Copyright: "Copyright (C) 1999-2007 Brian Paul, Copyright (C) 2008 VMware, Inc.", Source: CompanionSource{ Project: "pal1000/mesa-dist-win", - Version: "26.2.0", - Archive: "mesa3d-26.2.0-release-msvc.7z", - SHA256: "dcb2719ef346dab5b609fcb193a5f13cfc4b0502e3f4de1ad43d349477402f47", - URL: "https://github.com/pal1000/mesa-dist-win/releases/download/26.2.0/mesa3d-26.2.0-release-msvc.7z", + Version: "26.2.4", + Archive: "mesa3d-26.2.4-release-msvc.7z", + SHA256: "351fc8c8b695878ffb3eaa044b3ead08672a48b1a045e3c3e3975811df0f6695", + URL: "https://github.com/pal1000/mesa-dist-win/releases/download/26.2.4/mesa3d-26.2.4-release-msvc.7z", Inside: "x64/", }, Note: "OpenGL in software, for a machine whose graphics driver offers no OpenGL 2.1 - a virtual machine without 3D acceleration, a remote desktop, a server. " + "Loaded only after the toolkit could not open a window, or when the window is started with the flag that asks for it, and never otherwise. " + "Mesa is MIT (core, the llvmpipe driver and the WGL frontend - the core's line is quoted, the driver is Copyright 2007 VMware, Inc.). " + - "LLVM 22.1.8, compiled in for llvmpipe's code generation, is Apache-2.0 WITH LLVM-exception - its licence file states no copyright line under that licence, and the one it does carry, Copyright (c) 2003-2019 University of Illinois at Urbana-Champaign, belongs to the legacy licence the file also reproduces. " + + "LLVM 23.1.2, compiled in for llvmpipe's code generation, is Apache-2.0 WITH LLVM-exception - its licence file states no copyright line under that licence, and the one it does carry, Copyright (c) 2003-2019 University of Illinois at Urbana-Champaign, belongs to the legacy licence the file also reproduces. " + "The C11 threads shim Mesa compiles on Windows is BSL-1.0, Copyright yohhoy 2012. " + "The Direct3D 12 headers, 1.619.5, are MIT, Copyright (c) Microsoft Corporation. " + "Built and published by pal1000/mesa-dist-win, whose own scripts are MIT, Copyright (c) 2017-2020 pal1000, and whose archive carries no licence file - which is why the texts are read from the sources of the pinned versions and reproduced in the notices.",