Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 3 additions & 18 deletions .github/workflows/measure-classic-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ on:
- tools/build-sdl3-mixer.sh
- tools/measure-classic-check-images.sh
- tools/smoke-classic-check.sh
- tools/curl-probe/**
- tools/run-classic-native-tests.ps1
- tools/smoke-git-lfs.sh
- tools/tests/**
- tools/validate-toolchains.sh
Expand Down Expand Up @@ -192,21 +194,4 @@ jobs:
- name: Execute every Classic Check native test
shell: pwsh
run: |
$bundle = (Resolve-Path "build/native-windows-tests").Path
$env:PATH = "${bundle};${env:PATH}"
$inventoryPath = Join-Path $bundle "classic-check-toolchain.json"
$tests = (Get-Content -Raw $inventoryPath | ConvertFrom-Json).verification.native_tests
if ($tests.Count -ne 6) { throw "Expected six declared native tests" }
foreach ($test in $tests) {
$executable = Join-Path $bundle $test.executable
$arguments = @($test.arguments | ForEach-Object {
if ([IO.Path]::IsPathRooted($_) -or $_ -like "../*" -or $_ -like "..\\*") {
throw "Unsafe native-test argument: $_"
}
Join-Path $bundle $_
})
& $executable @arguments
if ($LASTEXITCODE -ne 0) {
throw "$($test.executable) failed: ${LASTEXITCODE}"
}
}
& (Join-Path (Resolve-Path "build/native-windows-tests").Path "run-classic-native-tests.ps1")
42 changes: 42 additions & 0 deletions .github/workflows/publish-linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,48 @@ jobs:
type=gha,scope=classic-build-image
cache-to: type=gha,mode=max,scope=classic-build-image,ignore-error=true

- name: Read Classic cancellation qualification consumer
id: curl-consumer
run: echo "commit=$(jq -er '.consumer_validation.commit' classic-toolchain.json)" >> "${GITHUB_OUTPUT}"

- name: Check out Classic cancellation qualification consumer
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: atrinik/classic
ref: ${{ steps.curl-consumer.outputs.commit }}
path: build/curl-classic
persist-credentials: false

- name: Load Classic cancellation qualification image
uses: docker/build-push-action@c3c9e263c25d99ce0380d002d59b67737d91b0dc # v7
with:
context: .
file: linux/Dockerfile
target: classic-final
platforms: linux/amd64
load: true
tags: atrinik-classic-curl:qualification
cache-from: type=gha,scope=classic-build-image

- name: Qualify Classic cancellation and public TLS before publication
run: tools/smoke-classic-curl.sh atrinik-classic-curl:qualification build/curl-classic

- name: Load broad Linux cancellation qualification image
if: ${{ !inputs.candidate_only }}
uses: docker/build-push-action@c3c9e263c25d99ce0380d002d59b67737d91b0dc # v7
with:
context: .
file: linux/Dockerfile
target: final
platforms: linux/amd64
load: true
tags: atrinik-linux-curl:qualification
cache-from: type=gha,scope=linux-build-image

- name: Qualify broad Linux cancellation and public TLS before publication
if: ${{ !inputs.candidate_only }}
run: tools/smoke-classic-curl.sh atrinik-linux-curl:qualification build/curl-classic

# The portable target has its own ABI and real consumer; validate it before aliases move.
- name: Read portable consumer revision
if: ${{ !inputs.candidate_only }}
Expand Down
20 changes: 1 addition & 19 deletions .github/workflows/publish-windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -178,25 +178,7 @@ jobs:
- name: Execute every Classic Check native test
shell: pwsh
run: |
$bundle = (Resolve-Path "build/native-windows-tests").Path
$env:PATH = "${bundle};${env:PATH}"
$inventoryPath = Join-Path $bundle "classic-check-toolchain.json"
$tests = (Get-Content -Raw $inventoryPath | ConvertFrom-Json).verification.native_tests
if ($tests.Count -ne 6) { throw "Expected six declared native tests" }
foreach ($test in $tests) {
$executable = Join-Path $bundle $test.executable
$arguments = @($test.arguments | ForEach-Object {
if ([IO.Path]::IsPathRooted($_) -or $_ -like "../*" -or $_ -like "..\\*") {
throw "Unsafe native-test argument: $_"
}
Join-Path $bundle $_
})
& $executable @arguments
if ($LASTEXITCODE -ne 0) {
throw "$($test.executable) failed: ${LASTEXITCODE}"
}
}

& (Join-Path (Resolve-Path "build/native-windows-tests").Path "run-classic-native-tests.ps1")
promote:
name: Promote verified Windows image aliases
needs:
Expand Down
51 changes: 30 additions & 21 deletions .github/workflows/validate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ jobs:
classic-vulkan-toolchain.json | \
classic-vulkan-toolchain.spdx.json | \
classic-vulkan-packages.lock | \
toolchains.json | tools/audio/* | \
toolchains.json | classic-toolchain.json | windows/classic-check-toolchain.json | classic-curl-toolchain.json | tools/build-classic-curl.sh | tools/verify-classic-curl.sh | \
tools/curl-probe/* | tools/smoke-classic-curl.sh | tools/audio/* | \
tools/build-sdl3-mixer.sh | \
tools/install_classic_vulkan_toolchain.py | \
tools/require-image-checks.sh | \
Expand All @@ -68,7 +69,9 @@ jobs:
.dockerignore | .github/workflows/publish-linux.yml | \
.github/workflows/validate.yml | linux/* | \
audio-toolchain.json | audio-toolchain.spdx.json | \
classic-packages.lock | classic-toolchain.json | \
classic-packages.lock | classic-toolchain.json | windows/classic-check-toolchain.json | \
classic-curl-toolchain.json | tools/build-classic-curl.sh | tools/verify-classic-curl.sh | \
tools/curl-probe/* | tools/smoke-classic-curl.sh | \
classic-shader-toolchain.json | \
classic-shader-toolchain.spdx.json | \
classic-vulkan-toolchain.json | \
Expand All @@ -93,6 +96,8 @@ jobs:
.github/workflows/publish-windows.yml | \
.github/workflows/validate.yml | windows/* | \
audio-toolchain.json | audio-toolchain.spdx.json | \
classic-curl-toolchain.json | tools/verify-classic-curl.sh | \
tools/curl-probe/* | tools/run-classic-native-tests.ps1 | \
tools/audio/* | \
tools/build-sdl3-mixer.sh | \
tools/measure-classic-check-images.sh | \
Expand Down Expand Up @@ -124,6 +129,9 @@ jobs:
- name: Test Classic dependency preflight
run: python3 -m unittest tools/tests/test_verify_classic_check_dependencies.py

- name: Test Classic package runtime closure
run: python3 -m unittest tools/tests/test_verify_classic_check_package.py

- name: Test Classic shader toolchain installer
run: python3 -m unittest tools/tests/test_install_classic_shader_toolchain.py

Expand Down Expand Up @@ -157,6 +165,21 @@ jobs:
cache-from: type=gha,scope=linux-build-image
cache-to: type=gha,mode=max,scope=linux-build-image,ignore-error=true

- name: Read broad Linux cancellation qualification consumer
id: curl-consumer
run: echo "commit=$(jq -er '.consumer_validation.commit' classic-toolchain.json)" >> "${GITHUB_OUTPUT}"

- name: Check out broad Linux cancellation qualification consumer
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: atrinik/classic
ref: ${{ steps.curl-consumer.outputs.commit }}
path: build/curl-classic
persist-credentials: false

- name: Qualify broad Linux cancellation and public TLS
run: tools/smoke-classic-curl.sh atrinik-linux-validation:ci build/curl-classic

- name: Verify non-root gh-stack contract
run: |
docker run --rm \
Expand Down Expand Up @@ -344,25 +367,7 @@ jobs:
- name: Execute every Classic Check native test
shell: pwsh
run: |
$bundle = (Resolve-Path "build/native-windows-tests").Path
$env:PATH = "${bundle};${env:PATH}"
$inventoryPath = Join-Path $bundle "classic-check-toolchain.json"
$tests = (Get-Content -Raw $inventoryPath | ConvertFrom-Json).verification.native_tests
if ($tests.Count -ne 6) { throw "Expected six declared native tests" }
foreach ($test in $tests) {
$executable = Join-Path $bundle $test.executable
$arguments = @($test.arguments | ForEach-Object {
if ([IO.Path]::IsPathRooted($_) -or $_ -like "../*" -or $_ -like "..\\*") {
throw "Unsafe native-test argument: $_"
}
Join-Path $bundle $_
})
& $executable @arguments
if ($LASTEXITCODE -ne 0) {
throw "$($test.executable) failed: ${LASTEXITCODE}"
}
}

& (Join-Path (Resolve-Path "build/native-windows-tests").Path "run-classic-native-tests.ps1")
classic:
name: Classic CI image
needs: changes
Expand Down Expand Up @@ -408,6 +413,10 @@ jobs:
repository: atrinik/classic
ref: ${{ steps.consumer.outputs.commit }}
path: classic
persist-credentials: false

- name: Qualify Classic resolver cancellation and public TLS
run: tools/smoke-classic-curl.sh atrinik-classic-build:validation classic

- name: Run Classic client and server checks as the runner user
run: |
Expand Down
10 changes: 10 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,16 @@
revision, shader-toolchain inventory, GPU runtime, smoke/SBOM checks, and
published tags synchronized. Do not make it inherit the broad
replacement/development toolchain.
- `classic-curl-toolchain.json` pins the Classic c-ares resolver producer. Both
Linux images install its curl/c-ares closure in `/usr/local` without replacing
system OpenSSL 3.5.5; both MXE images explicitly pin OpenSSL 3.5.5 and compile
curl with c-ares and no threaded resolver. Preserve generated configuration,
header/runtime/license closure and native cancellation qualification; ASYNCHDNS
or a non-null c-ares field alone does not prove the selected backend.
Both Linux publication paths must run `tools/smoke-classic-curl.sh` against
their actual loaded candidate before publication; `candidate_only` retains
this gate. Windows validation/measurement/publication share the bundled
native runner, including cancellation, QUIC and pinned public-CA checks.
- The broad Linux and `classic-final` images include the snapshot-pinned Git LFS
client. Keep the Linux tool manifests, Classic package lock, non-root version
checks, and isolated worktree/payload smoke synchronized when changing this
Expand Down
42 changes: 42 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -467,3 +467,45 @@ Redistributors must retain the pinned source archives, notices, build recipes,
and Debian source coordinates and satisfy the corresponding-source and LGPL
replacement/relinking obligations in the contract. Authored game media remain
`content@main`, resources and sound inputs owned by their respective repositories.

### Classic curl resolver

The broad and slim Linux images install curl 8.18.0 and c-ares 1.34.6 in
`/usr/local`; the existing system OpenSSL 3.5.5 remains the TLS provider.
CMake and pkg-config use the installed headers and libraries there, and
`ldconfig` registers `libcurl.so.4` and `libcares.so.2`. System curl packages
remain recorded in the package lock for reproducibility; they are not the
Classic application's selected resolver provider.

Both MXE Windows images retain curl 8.21.0 in the standard shared target
prefix, add `libcares-2.dll` to that runtime directory, and explicitly pin
OpenSSL 3.5.5. The source pins are in `classic-curl-toolchain.json`. LDAP/LDAPS and RTMP are
excluded explicitly; HTTP/TLS, HTTP2, compression, PSL and IDN remain supported.
The generated curl configuration is retained in `share/atrinik/curl` and
`atrinik-verify-classic-curl` rejects threaded resolver macros: ASYNCHDNS and
a non-null c-ares version alone are insufficient for a pure c-ares backend.

Producer build checks establish the selected source and resolver configuration.
Activation additionally requires actual stalled-DNS cancellation through easy,
multi and global cleanup, HTTP/TLS including the public CA bundle, Classic
QUIC, and Linux ELF / Windows DLL closure checks against the immutable image.
Linux cross-build success does not establish native Windows execution.

Classic producer qualification runs the real library cancellation helper with
witnessed stalled DNS and HTTP, then verifies the pinned Classic public CA bundle
against `https://curl.se/`. Both Linux variants run these checks before candidate
or release publication. Windows candidates stage the portable helper probe and
native QUIC test with their resolved DLL closure; validation, measurement and
release pipelines execute all eight native tests with process deadlines and
verify actual public TLS before alias promotion. `tools/curl-probe` is explicitly
GPL-2.0-or-later, matching the linked Classic library; its sources and Classic
license/source coordinates accompany the native qualification bundle.

The Windows producer and native qualification bundle retain the exact c-ares
1.34.6 MIT notice, including its named copyright holders. The Windows inventory
pins its upstream source, installed path and checksum.

Windows smoke prepares and validates the GPU shader cohort through the pinned
Classic `tools/ci/prepare_gpu_shaders.sh` workflow before its offline MXE build.
The container consumes generated artifacts, so host shader-tool binaries do not
become container ABI dependencies.
61 changes: 61 additions & 0 deletions classic-curl-toolchain.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
{
"schema_version": 1,
"resolver": "c-ares",
"threaded_resolver": false,
"cares": {
"version": "1.34.6",
"url": "https://github.com/c-ares/c-ares/releases/download/v1.34.6/c-ares-1.34.6.tar.gz",
"sha256": "912dd7cc3b3e8a79c52fd7fb9c0f4ecf0aaa73e45efda880266a2d6e26b84ef5"
},
"linux": {
"curl_version": "8.18.0",
"curl_url": "https://curl.se/download/curl-8.18.0.tar.xz",
"curl_sha256": "40df79166e74aa20149365e11ee4c798a46ad57c34e4f68fd13100e2c9a91946",
"prefix": "/usr/local",
"ca_bundle": "/etc/ssl/certs/ca-certificates.crt",
"openssl_version": "3.5.5",
"build_packages": {
"libpsl-dev": "0.21.2-1.1build2"
},
"payload": {
"include": [
"include/curl",
"include/ares.h",
"include/ares_version.h",
"include/ares_build.h",
"include/ares_dns.h",
"include/ares_dns_record.h",
"include/ares_nameser.h"
],
"library_families": [
"lib/libcurl.so*",
"lib/libcares.so*"
],
"pkg_config": [
"lib/pkgconfig/libcurl.pc",
"lib/pkgconfig/libcares.pc"
],
"licenses": [
"share/licenses/curl/COPYING",
"share/licenses/c-ares/LICENSE.md"
],
"evidence": [
"share/atrinik/classic-curl-toolchain.json",
"share/atrinik/curl/curl_config.h",
"share/atrinik/curl/config.log"
]
}
},
"windows": {
"curl_version": "8.21.0",
"prefix": "/opt/mxe/usr/x86_64-w64-mingw32.shared",
"openssl_version": "3.5.5",
"openssl_sha256": "b28c91532a8b65a1f983b4c28b7488174e4a01008e29ce8e69bd789f28bc2a89",
"cares_runtime": "libcares-2.dll"
},
"excluded_features": [
"LDAP",
"LDAPS",
"RTMP"
]
}
9 changes: 5 additions & 4 deletions classic-packages.lock
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,15 @@ flex=2.6.4-8.2build2
g++=4:15.2.0-5ubuntu1
gcc=4:15.2.0-5ubuntu1
gcovr=7.2+really-2
git=1:2.53.0-1ubuntu1
git-lfs=3.7.1-1
git=1:2.53.0-1ubuntu1
jq=1.8.1-4ubuntu2
libcurl4-openssl-dev=8.18.0-1ubuntu2.3
libdrm2=2.4.131-1
libgd-dev=2.3.3-13ubuntu2
libidn2-dev=2.3.8-4build1
libminiupnpc-dev=2.3.3-2build1
libpsl-dev=0.21.2-1.1build2
libreadline-dev=8.3-4
libsdl3-dev=3.4.2+ds-1ubuntu1
libsdl3-image-dev=3.4.0+ds-1
Expand All @@ -29,13 +30,13 @@ libwayland-client0=1.24.0-2
libxml2-dev=2.15.2+dfsg-0.1ubuntu0.1
mesa-vulkan-drivers=26.0.3-1ubuntu1
ninja-build=1.13.2-1
openssl=3.5.5-1ubuntu3.3
openssl-provider-legacy=3.5.5-1ubuntu3.3
openssl=3.5.5-1ubuntu3.3
pkgconf=2.5.1-4
python3=3.14.3-0ubuntu2
python3-dev=3.14.3-0ubuntu2
python3=3.14.3-0ubuntu2
vulkan-tools=1.4.341.0+dfsg1-1
xauth=1:1.1.2-1.1build1
xvfb=2:21.1.22-1ubuntu1
zlib1g=1:1.3.dfsg+really1.3.1-1ubuntu3
zlib1g-dev=1:1.3.dfsg+really1.3.1-1ubuntu3
zlib1g=1:1.3.dfsg+really1.3.1-1ubuntu3
5 changes: 3 additions & 2 deletions classic-toolchain.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
],
"consumer_validation": {
"repository": "atrinik/classic",
"commit": "8fec1db157bcfdd050c1ba360e77365bce701bba"
}
"commit": "9136e13efabc0f6edd513517b3a437c927b5edea"
},
"curl_contract": "/usr/local/share/atrinik/classic-curl-toolchain.json"
}
Loading
Loading