Merge remote-tracking branch 'origin/master' into ci/serial-drill-concurrency

This commit is contained in:
Chinesezjc
2026-08-12 18:03:42 +08:00
414 changed files with 10670 additions and 1165 deletions

View File

@@ -4,10 +4,27 @@ name: Build single-exe
# .agents/notes/implemented/architecture/2026-07-10-single-file-executable-sdk-runtime-distribution.md.
# A full target run retains one SDK wheel and three runtime wheels; subset
# dispatch retains the SDK wheel and selected runtime wheels. Bare executables
# and source closures are test inputs. Run manually or label a PR
# `build-exe` (remove and reapply to rerun). Checkout uses the triggering ref,
# so dispatch needs no separate ref input.
# and source closures are test inputs. Run manually, label a PR `build-exe`
# (remove and reapply to rerun), or call it from the Python release workflow.
# Checkout uses the triggering ref, so dispatch needs no separate ref input.
on:
workflow_call:
inputs:
targets:
description: Comma-separated pkg targets to build; empty builds all three.
type: string
required: false
default: ''
release:
description: Run as the native builder for the Python release workflow.
type: boolean
required: false
default: false
ci:
description: Run as the required Linux x64 Python runtime pull-request check.
type: boolean
required: false
default: false
workflow_dispatch:
inputs:
targets:
@@ -22,7 +39,10 @@ on:
types: [labeled]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
# Keep the called workflow distinct from its caller's concurrency group;
# github.workflow identifies the caller inside a reusable workflow and keeps
# an ordinary CI run from cancelling a full release validation on the same ref.
group: build-single-exe-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
@@ -38,12 +58,13 @@ jobs:
# construct the matrix before the dependent jobs.
plan:
name: plan targets
if: github.event_name == 'workflow_dispatch' || github.event.label.name == 'build-exe'
if: inputs.ci || inputs.release || github.event_name == 'workflow_dispatch' || github.event.label.name == 'build-exe'
runs-on: ubuntu-latest
timeout-minutes: 5
outputs:
matrix: ${{ steps.plan.outputs.matrix }}
version: ${{ steps.version.outputs.version }}
repository-version: ${{ steps.version.outputs.repository-version }}
steps:
- uses: actions/checkout@v6
@@ -51,12 +72,15 @@ jobs:
id: version
run: |
set -euo pipefail
version="$(jq -r '.version // empty' package.json)"
[[ "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] || {
echo "::error::package.json version must be stable X.Y.Z, got '$version'"
exit 1
}
echo "version=$version" >> "$GITHUB_OUTPUT"
python3 - <<'PY' >> "$GITHUB_OUTPUT"
import runpy
release = runpy.run_path("scripts/build-python-release.py")
repository_version = release["repository_version"]()
wheel_version = release["pep440_version"](repository_version)
print(f"repository-version={repository_version}")
print(f"version={wheel_version}")
PY
- name: Compute matrix from targets input
id: plan
@@ -116,6 +140,7 @@ jobs:
name: deepseek_harness_sdk-${{ needs.plan.outputs.version }}-py3-none-any.whl
path: dist-python/deepseek_harness_sdk-${{ needs.plan.outputs.version }}-py3-none-any.whl
if-no-files-found: error
retention-days: 7
build:
needs: [plan, sdk-wheel]
@@ -157,6 +182,41 @@ jobs:
- name: Install (immutable)
run: pnpm install --frozen-lockfile
- name: Rebuild Linux node-pty against manylinux 2.28
if: runner.os == 'Linux'
env:
RUNNER_ARCH: ${{ runner.arch }}
run: |
set -euo pipefail
case "$RUNNER_ARCH" in
X64) image=quay.io/pypa/manylinux_2_28_x86_64 ;;
ARM64) image=quay.io/pypa/manylinux_2_28_aarch64 ;;
*) echo "::error::Unsupported Linux runner architecture $RUNNER_ARCH"; exit 1 ;;
esac
addon_dir="$(realpath packages/subprocess/subprocess-local/node_modules/node-pty)"
addon="$addon_dir/build/Release/pty.node"
[ -f "$addon_dir/build/Makefile" ] || {
echo "::error::node-pty install did not generate $addon_dir/build/Makefile"
exit 1
}
docker run --rm \
--user "$(id -u):$(id -g)" \
-v "$PWD:$PWD" \
-v "$HOME/.cache/node-gyp:$HOME/.cache/node-gyp:ro" \
-v "$HOME/setup-pnpm:$HOME/setup-pnpm:ro" \
-w "$addon_dir" \
"$image" \
bash -euxo pipefail -c \
'rm -rf build/Release && make -C build -j2 BUILDTYPE=Release'
[ -f "$addon" ] || { echo "::error::$addon missing after manylinux rebuild"; exit 1; }
readelf --version-info "$addon" | tee node-pty-glibc-versions.txt
maximum="$(sed -n 's/.*Name: GLIBC_\([0-9.]*\).*/\1/p' node-pty-glibc-versions.txt | sort -V | tail -1)"
[ -n "$maximum" ] || { echo "::error::No GLIBC requirements found in $addon"; exit 1; }
dpkg --compare-versions "$maximum" le 2.28 || {
echo "::error::node-pty addon requires GLIBC_$maximum but wheel claims manylinux_2_28"
exit 1
}
- name: Build single-exe
run: pnpm exec tsx scripts/build-exe-for-python-sdk.ts --targets=${{ matrix.target }}
@@ -173,7 +233,7 @@ jobs:
case "$platform" in
linux-x64) wheel=deepseek_harness_runtime_bin-$VERSION-py3-none-manylinux_2_28_x86_64.whl ;;
linux-arm64) wheel=deepseek_harness_runtime_bin-$VERSION-py3-none-manylinux_2_28_aarch64.whl ;;
macos-arm64) wheel=deepseek_harness_runtime_bin-$VERSION-py3-none-macosx_11_0_arm64.whl ;;
macos-arm64) wheel=deepseek_harness_runtime_bin-$VERSION-py3-none-macosx_14_0_arm64.whl ;;
*) echo "::error::Unsupported runtime platform $platform"; exit 1 ;;
esac
echo "platform=$platform" >> "$GITHUB_OUTPUT"
@@ -224,6 +284,14 @@ jobs:
exit 1
}
- name: Check macOS deployment target
if: runner.os == 'macOS'
env:
EXE: ${{ steps.runtime.outputs.exe }}
run: >-
python3 scripts/check-macos-deployment-target.py
"$EXE" "$EXE-spawn-helper"
- name: Run wheel in a manylinux 2.28 container
if: runner.os == 'Linux'
env:
@@ -236,7 +304,7 @@ jobs:
ARM64) image=quay.io/pypa/manylinux_2_28_aarch64 ;;
*) echo "::error::Unsupported Linux runner architecture $RUNNER_ARCH"; exit 1 ;;
esac
docker run --rm -e VERSION -v "$PWD:/work" -w /work "$image" bash -euxo pipefail -c '
docker run --rm -e VERSION -e DSH_TELEMETRY_DISABLED -v "$PWD:/work" -w /work "$image" bash -euxo pipefail -c '
/opt/python/cp310-cp310/bin/python -m venv /tmp/dsh-sdk
/tmp/dsh-sdk/bin/python -m pip install --find-links /work/dist-python deepseek-harness-sdk=="$VERSION"
/tmp/dsh-sdk/bin/python /work/scripts/smoke-python-runtime.py --scenario sdk-default
@@ -247,3 +315,4 @@ jobs:
name: ${{ steps.runtime.outputs.wheel }}
path: dist-python/${{ steps.runtime.outputs.wheel }}
if-no-files-found: error
retention-days: 7

View File

@@ -312,6 +312,18 @@ jobs:
- name: Run complete keyless Python suite
run: uv run --python 3.10 --group test --project python/sdk pytest
# One native target makes the complete release-shaped Python path required
# without duplicating platform-independent behavior across the release matrix.
# The reusable builder owns the executable, snapshot, wheel, clean-install,
# GLIBC, and manylinux checks; release validation retains all native targets.
python-runtime:
if: github.event_name == 'pull_request'
name: python runtime / release-shaped Linux x64
uses: ./.github/workflows/build-exe-for-python-sdk.yml
with:
targets: node24-linux-x64
ci: true
# The required pull-request Windows signal: the two blocking win32 surfaces
# (workspace build, production site) execute with real, checksum-verified
# Windows Node under Wine on standard hosted Linux. The independent
@@ -907,7 +919,7 @@ jobs:
&& github.event.pull_request.user.login != 'dependabot[bot]'
&& fromJSON('["self-hosted", "linux", "x64", "vm-backup"]')
|| 'ubuntu-latest' }}
needs: [node-24, node-24-coverage, node-24-consumers, node-compat, python-sdk, windows]
needs: [node-24, node-24-coverage, node-24-consumers, node-compat, python-sdk, python-runtime, windows]
if: always() && github.event_name == 'pull_request'
steps:
- name: Fail if any needed job did not succeed

244
.github/workflows/python-release.yml vendored Normal file
View File

@@ -0,0 +1,244 @@
name: Release (Python)
# A PR labeled python-release-dry-run or a manual run with publish=false builds
# and validates the complete release without registry credentials. Publication
# is accepted only from a manual run on the matching python-v* tag when the
# private publisher-repository identity and public-PyPI switch are configured.
on:
workflow_dispatch:
inputs:
publish:
description: Publish the validated wheels to public PyPI. Must run from a python-v* tag.
required: true
type: boolean
default: false
pull_request:
types: [labeled]
permissions:
contents: read
concurrency:
# Public runs stay globally serialized across tags. Dry runs remain isolated
# by ref so they do not block an intentional publication.
group: ${{ github.event_name == 'workflow_dispatch' && inputs.publish && 'python-publication' || format('{0}-{1}', github.workflow, github.ref) }}
cancel-in-progress: false
jobs:
build:
name: Build four wheels
if: github.event_name == 'workflow_dispatch' || github.event.label.name == 'python-release-dry-run'
uses: ./.github/workflows/build-exe-for-python-sdk.yml
with:
targets: node24-linux-x64,node24-linux-arm64,node24-macos-arm64
release: true
python-compat:
name: Python ${{ matrix.python }} / installed SDK
needs: build
runs-on: ubuntu-latest
timeout-minutes: 10
strategy:
fail-fast: false
matrix:
python: ['3.10', '3.14']
steps:
- uses: actions/checkout@v6
with:
persist-credentials: false
- uses: actions/setup-python@v6.3.0
with:
python-version: ${{ matrix.python }}
- uses: actions/download-artifact@v8
with:
pattern: deepseek_harness_*
path: dist
merge-multiple: true
- name: Resolve installed wheel version
id: compatibility-version
run: |
python - <<'PY' >> "$GITHUB_OUTPUT"
import runpy
release = runpy.run_path("scripts/build-python-release.py")
repository_version = release["repository_version"]()
print(f"version={release['pep440_version'](repository_version)}")
PY
- name: Install and run the published entry path
run: |
python -m pip install --find-links dist "deepseek-harness-sdk==${{ steps.compatibility-version.outputs.version }}"
python scripts/smoke-python-runtime.py --scenario sdk-default
validate:
name: Validate release candidate
needs: [build, python-compat]
runs-on: ubuntu-latest
timeout-minutes: 10
outputs:
version: ${{ steps.version.outputs.version }}
steps:
- uses: actions/checkout@v6
with:
persist-credentials: false
- uses: actions/setup-python@v6.3.0
with:
python-version: '3.10'
- name: Resolve release version
id: version
run: |
python3 - <<'PY' >> "$GITHUB_OUTPUT"
import runpy
release = runpy.run_path("scripts/build-python-release.py")
repository_version = release["repository_version"]()
wheel_version = release["pep440_version"](repository_version)
print(f"repository-version={repository_version}")
print(f"version={wheel_version}")
PY
- name: Authorize publication request
env:
PUBLISH: ${{ github.event_name == 'workflow_dispatch' && inputs.publish }}
PUBLIC_PYPI_RELEASE_ENABLED: ${{ vars.PUBLIC_PYPI_RELEASE_ENABLED }}
PYPI_PUBLISHER_REPOSITORY: ${{ vars.PYPI_PUBLISHER_REPOSITORY }}
REPOSITORY: ${{ github.repository }}
REF_NAME: ${{ github.ref_name }}
REF_TYPE: ${{ github.ref_type }}
REPOSITORY_VERSION: ${{ steps.version.outputs.repository-version }}
run: |
set -euo pipefail
if [ "$PUBLISH" = true ]; then
[ -n "$PYPI_PUBLISHER_REPOSITORY" ] || {
echo "::error::Set the repository variable PYPI_PUBLISHER_REPOSITORY before publication."
exit 1
}
[ "$REPOSITORY" = "$PYPI_PUBLISHER_REPOSITORY" ] || {
echo "::error::This repository is not the configured PyPI publisher repository."
exit 1
}
[ "$PUBLIC_PYPI_RELEASE_ENABLED" = true ] || {
echo "::error::Set PUBLIC_PYPI_RELEASE_ENABLED=true before public publication."
exit 1
}
[ "$REF_TYPE" = tag ] && [ "$REF_NAME" = "python-v$REPOSITORY_VERSION" ] || {
echo "::error::Publication must run from tag python-v$REPOSITORY_VERSION."
exit 1
}
fi
- uses: actions/download-artifact@v8
with:
pattern: deepseek_harness_*
path: dist
merge-multiple: true
- name: Check release contents
env:
VERSION: ${{ steps.version.outputs.version }}
run: |
set -euo pipefail
expected="$(mktemp)"
actual="$(mktemp)"
printf '%s\n' \
"deepseek_harness_runtime_bin-$VERSION-py3-none-macosx_14_0_arm64.whl" \
"deepseek_harness_runtime_bin-$VERSION-py3-none-manylinux_2_28_aarch64.whl" \
"deepseek_harness_runtime_bin-$VERSION-py3-none-manylinux_2_28_x86_64.whl" \
"deepseek_harness_sdk-$VERSION-py3-none-any.whl" > "$expected"
find dist -maxdepth 1 -type f -name '*.whl' -exec basename {} \; | sort > "$actual"
diff -u "$expected" "$actual"
while IFS= read -r wheel; do
size="$(stat -c '%s' "dist/$wheel")"
[ "$size" -lt 100000000 ] || {
echo "::error::$wheel is $size bytes; public PyPI accepts at most 100000000 bytes by default."
exit 1
}
done < "$actual"
- name: Validate package metadata
run: |
python -m pip install twine==6.2.0
python -m twine check dist/*.whl
- name: Record artifact hashes
run: |
cd dist
sha256sum *.whl | sort -k2 > SHA256SUMS
cat SHA256SUMS
- uses: actions/upload-artifact@v7
with:
name: python-release-${{ steps.version.outputs.version }}
path: dist/*
if-no-files-found: error
retention-days: 7
publish-runtime:
name: Publish runtime wheels to public PyPI
if: github.event_name == 'workflow_dispatch' && inputs.publish
needs: validate
runs-on: ubuntu-latest
timeout-minutes: 10
environment: pypi-runtime
permissions:
contents: read
id-token: write
steps:
- uses: actions/download-artifact@v8
with:
name: python-release-${{ needs.validate.outputs.version }}
path: dist
- name: Verify release artifact hashes
run: cd dist && sha256sum -c SHA256SUMS
- name: Select runtime wheels
run: |
mkdir -p dist/runtime
mv dist/deepseek_harness_runtime_bin-*.whl dist/runtime/
- name: Publish runtime wheels
uses: pypa/gh-action-pypi-publish@release/v1
with:
packages-dir: dist/runtime/
# Public attestations reveal the private publisher repository. OIDC
# authentication remains enabled without uploading that provenance.
attestations: false
# Keep the SDK in a dependent job. If its upload fails after the immutable
# runtime files arrive, "re-run failed jobs" resumes here without attempting
# to overwrite the runtime release.
publish-sdk:
name: Publish SDK wheel to public PyPI
if: github.event_name == 'workflow_dispatch' && inputs.publish
needs: [validate, publish-runtime]
runs-on: ubuntu-latest
timeout-minutes: 10
environment: pypi
permissions:
contents: read
id-token: write
steps:
- uses: actions/download-artifact@v8
with:
name: python-release-${{ needs.validate.outputs.version }}
path: dist
- name: Verify release artifact hashes
run: cd dist && sha256sum -c SHA256SUMS
- name: Select SDK wheel
run: |
mkdir -p dist/sdk
mv dist/deepseek_harness_sdk-*.whl dist/sdk/
- name: Publish SDK wheel
uses: pypa/gh-action-pypi-publish@release/v1
with:
packages-dir: dist/sdk/
attestations: false