Skip to content

Harden release security suggestions #1405

Harden release security suggestions

Harden release security suggestions #1405

Workflow file for this run

name: King Canonical Baseline
on:
push:
branches:
- '**'
pull_request:
branches:
- main
types:
- opened
- synchronize
- reopened
workflow_dispatch:
concurrency:
group: king-canonical-baseline-${{ github.event.pull_request.head.repo.full_name || github.repository }}-${{ github.event.pull_request.head.ref || github.ref_name }}
cancel-in-progress: true
permissions:
contents: read
pull-requests: read
env:
DEBIAN_FRONTEND: noninteractive
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
jobs:
branch-push-dedupe:
name: Branch push dedupe
runs-on: ubuntu-24.04
outputs:
run-heavy-jobs: ${{ steps.decide.outputs.run-heavy-jobs }}
reason: ${{ steps.decide.outputs.reason }}
steps:
- name: Decide whether this ref should run the full pipeline
id: decide
uses: actions/github-script@v8
with:
script: |
const eventName = context.eventName;
const refName = process.env.GITHUB_REF_NAME || '';
const branchName = (eventName === 'pull_request'
? context.payload.pull_request?.head?.ref
: refName
) || '';
let runHeavyJobs = 'true';
let reason = `${eventName} on ${branchName}: full pipeline.`;
core.setOutput('run-heavy-jobs', runHeavyJobs);
core.setOutput('reason', reason);
core.notice(reason);
lsquic-runtime:
name: Pinned LSQUIC Runtime ${{ matrix.arch-label }}
needs: branch-push-dedupe
if: needs.branch-push-dedupe.outputs.run-heavy-jobs == 'true'
runs-on: ${{ matrix.runner }}
timeout-minutes: 45
strategy:
fail-fast: false
matrix:
include:
- runner: king
arch-label: linux-amd64
local-lsquic-cache-dir: /opt/king/cache/lsquic/runtime
- runner: ubuntu-24.04-arm
arch-label: linux-arm64
local-lsquic-cache-dir: ""
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: Install system dependencies
run: bash ./infra/scripts/install-ci-system-dependencies.sh
- name: Restore local pinned LSQUIC runtime cache
id: restore-local-lsquic-runtime-cache
if: matrix.local-lsquic-cache-dir != ''
env:
KING_CI_LOCAL_LSQUIC_CACHE_DIR: ${{ matrix.local-lsquic-cache-dir }}
KING_LSQUIC_RUNTIME_PREFIX: ${{ github.workspace }}/.cache/king/lsquic/runtime/prefix
run: bash ./infra/scripts/local-lsquic-runtime-cache.sh restore --github-output "${GITHUB_OUTPUT}"
- name: Restore pinned LSQUIC runtime cache
id: restore-lsquic-runtime-cache
if: steps.restore-local-lsquic-runtime-cache.outputs.cache-hit != 'true'
uses: actions/cache/restore@v5
with:
path: .cache/king/lsquic/runtime/prefix
key: king-lsquic-runtime-${{ matrix.arch-label }}-${{ hashFiles('infra/scripts/lsquic-bootstrap.lock', 'infra/scripts/build-lsquic-runtime.sh') }}
- name: Verify pinned LSQUIC runtime cache
id: verify-lsquic-runtime-cache
env:
KING_LSQUIC_RUNTIME_PREFIX: ${{ github.workspace }}/.cache/king/lsquic/runtime/prefix
run: |
if bash ./infra/scripts/build-lsquic-runtime.sh --verify-current; then
echo "cache-current=true" >> "${GITHUB_OUTPUT}"
exit 0
fi
echo "cache-current=false" >> "${GITHUB_OUTPUT}"
- name: Build pinned LSQUIC runtime
if: steps.verify-lsquic-runtime-cache.outputs.cache-current != 'true'
env:
KING_LSQUIC_RUNTIME_PREFIX: ${{ github.workspace }}/.cache/king/lsquic/runtime/prefix
run: bash ./infra/scripts/build-lsquic-runtime.sh
- name: Save local pinned LSQUIC runtime cache
if: matrix.local-lsquic-cache-dir != '' && steps.restore-local-lsquic-runtime-cache.outputs.cache-hit != 'true'
env:
KING_CI_LOCAL_LSQUIC_CACHE_DIR: ${{ matrix.local-lsquic-cache-dir }}
KING_LSQUIC_RUNTIME_PREFIX: ${{ github.workspace }}/.cache/king/lsquic/runtime/prefix
run: bash ./infra/scripts/local-lsquic-runtime-cache.sh save
- name: Save pinned LSQUIC runtime cache
if: steps.verify-lsquic-runtime-cache.outputs.cache-current != 'true'
uses: actions/cache/save@v5
with:
path: .cache/king/lsquic/runtime/prefix
key: ${{ steps.restore-lsquic-runtime-cache.outputs.cache-primary-key }}
- name: Upload pinned LSQUIC runtime
uses: actions/upload-artifact@v6
with:
name: king-lsquic-runtime-${{ matrix.arch-label }}
if-no-files-found: error
path: |
.cache/king/lsquic/runtime/prefix/**
canonical-baseline:
name: Audit, Build, Test shard ${{ matrix.shard-index }}/3, Go-Live
needs:
- branch-push-dedupe
- lsquic-runtime
if: needs.branch-push-dedupe.outputs.run-heavy-jobs == 'true'
runs-on: ubuntu-24.04
timeout-minutes: 60
strategy:
fail-fast: false
matrix:
shard-index: [1, 2, 3]
steps:
- name: Checkout repository
uses: actions/checkout@v6
with:
submodules: recursive
- name: Resolve pinned PHP version
id: toolchain
run: bash ./infra/scripts/toolchain-lock.sh --github-output "${GITHUB_OUTPUT}"
- name: Setup PHP pinned canonical
uses: shivammathur/setup-php@v2
with:
php-version: "${{ steps.toolchain.outputs.canonical_php_version }}"
coverage: none
extensions: curl, mbstring, openssl, sockets
- name: Verify repository artifact hygiene
if: matrix.shard-index == 1
run: bash ./infra/scripts/check-repo-artifact-hygiene.sh
- name: Install system dependencies
run: bash ./infra/scripts/install-ci-system-dependencies.sh
- name: Download pinned LSQUIC runtime
uses: actions/download-artifact@v7
with:
name: king-lsquic-runtime-linux-amd64
path: .cache/king/lsquic/runtime/prefix
- name: Verify toolchain
run: |
php -v
phpize -v
- name: Lint public PHP stub surface
if: matrix.shard-index == 1
run: php -l stubs/king.php
- name: Run repo-local static checks
if: matrix.shard-index == 1
working-directory: extension
run: ../infra/scripts/static-checks.sh
- name: Audit active runtime surface
if: matrix.shard-index == 1
working-directory: extension
run: ../infra/scripts/audit-runtime-surface.sh
- name: Build canonical release profile
working-directory: extension
env:
KING_LSQUIC_RUNTIME_PREFIX: ${{ github.workspace }}/.cache/king/lsquic/runtime/prefix
run: ../infra/scripts/build-profile.sh release
- name: Verify public PHP stub parity
if: matrix.shard-index == 1
working-directory: extension
run: ../infra/scripts/check-stub-parity.sh
- name: Run model-optional inference verification matrix
if: matrix.shard-index == 1
working-directory: extension
run: ../bin/king-inference-verify-matrix --json
- name: Run canonical PHPT suite
working-directory: extension
env:
SHARD_TOTAL: "3"
SHARD_INDEX: "${{ matrix.shard-index }}"
KING_LSQUIC_LIBRARY: ${{ github.workspace }}/extension/build/profiles/release/runtime/liblsquic.so
run: |
mkdir -p ../compat-artifacts/phpt/canonical-shard-${{ matrix.shard-index }}
set +e
../infra/scripts/test-extension.sh 2>&1 | tee ../compat-artifacts/phpt/canonical-shard-${{ matrix.shard-index }}/run-tests.log
status=${PIPESTATUS[0]}
set -e
exit "${status}"
- name: Package canonical release archive
if: matrix.shard-index == 1
working-directory: extension
run: ../infra/scripts/package-release.sh --verify-reproducible --output-dir ../dist
- name: Upload canonical release package artifact
if: matrix.shard-index == 1
uses: actions/upload-artifact@v6
with:
name: king-release-package-php8.5-linux-amd64
if-no-files-found: error
path: |
dist/*.tar.gz
dist/*.tar.gz.sha256
- name: Collect canonical shard PHPT diagnostics
if: failure()
working-directory: extension
run: |
../infra/scripts/collect-phpt-failure-artifacts.sh \
--job-name "canonical-baseline-shard-${{ matrix.shard-index }}" \
--tests-dir tests \
--config-log config.log \
--run-log ../compat-artifacts/phpt/canonical-shard-${{ matrix.shard-index }}/run-tests.log \
--output-dir ../compat-artifacts/phpt/canonical-shard-${{ matrix.shard-index }}
- name: Classify canonical PHPT flaky failures
if: failure()
working-directory: extension
run: |
../infra/scripts/classify-phpt-flakes.sh \
--job-name "canonical-baseline-shard-${{ matrix.shard-index }}" \
--failed-tests ../compat-artifacts/phpt/canonical-shard-${{ matrix.shard-index }}/failed-tests.txt \
--output-dir ../compat-artifacts/phpt/canonical-shard-${{ matrix.shard-index }}/flake-classification
- name: Upload failure artifacts
if: failure()
uses: actions/upload-artifact@v6
with:
name: king-canonical-baseline-failures-shard-${{ matrix.shard-index }}
if-no-files-found: ignore
path: |
compat-artifacts/phpt/canonical-shard-${{ matrix.shard-index }}/
profile-smoke:
name: ${{ matrix.profile }} profile smoke
needs: branch-push-dedupe
if: needs.branch-push-dedupe.outputs.run-heavy-jobs == 'true'
runs-on: ubuntu-24.04
timeout-minutes: 60
strategy:
fail-fast: false
matrix:
profile:
- debug
- asan
- ubsan
steps:
- name: Checkout repository
uses: actions/checkout@v6
with:
submodules: recursive
- name: Resolve pinned PHP version
id: toolchain
run: bash ./infra/scripts/toolchain-lock.sh --github-output "${GITHUB_OUTPUT}"
- name: Setup PHP pinned canonical
uses: shivammathur/setup-php@v2
with:
php-version: "${{ steps.toolchain.outputs.canonical_php_version }}"
coverage: none
extensions: curl, mbstring, openssl, sockets
- name: Install system dependencies
run: bash ./infra/scripts/install-ci-system-dependencies.sh
- name: Build profile
working-directory: extension
run: ../infra/scripts/build-profile.sh "${{ matrix.profile }}"
- name: Smoke profile artifact
working-directory: extension
run: ../infra/scripts/smoke-profile.sh "${{ matrix.profile }}"
- name: Collect profile PHPT diagnostics
if: failure()
working-directory: extension
run: |
../infra/scripts/collect-phpt-failure-artifacts.sh \
--job-name "profile-smoke-${{ matrix.profile }}" \
--tests-dir tests \
--config-log config.log \
--output-dir ../compat-artifacts/phpt/profile-${{ matrix.profile }}
- name: Upload profile failure artifacts
if: failure()
uses: actions/upload-artifact@v6
with:
name: king-${{ matrix.profile }}-profile-failures
if-no-files-found: ignore
path: |
compat-artifacts/phpt/profile-${{ matrix.profile }}/
extension/build/profiles/${{ matrix.profile }}/
install-package-matrix:
name: Release Package Build & Install Smoke PHP ${{ matrix.php-version }} ${{ matrix.arch-label }}
needs:
- canonical-baseline
- lsquic-runtime
runs-on: ${{ matrix.runner }}
timeout-minutes: 60
strategy:
fail-fast: false
matrix:
include:
- php-version: "8.1"
runner: ubuntu-24.04
arch-label: linux-amd64
- php-version: "8.1"
runner: ubuntu-24.04-arm
arch-label: linux-arm64
- php-version: "8.2"
runner: ubuntu-24.04
arch-label: linux-amd64
- php-version: "8.2"
runner: ubuntu-24.04-arm
arch-label: linux-arm64
- php-version: "8.3"
runner: ubuntu-24.04
arch-label: linux-amd64
- php-version: "8.3"
runner: ubuntu-24.04-arm
arch-label: linux-arm64
- php-version: "8.4"
runner: ubuntu-24.04
arch-label: linux-amd64
- php-version: "8.4"
runner: ubuntu-24.04-arm
arch-label: linux-arm64
- php-version: "8.5"
runner: ubuntu-24.04
arch-label: linux-amd64
- php-version: "8.5"
runner: ubuntu-24.04-arm
arch-label: linux-arm64
steps:
- name: Checkout repository
uses: actions/checkout@v6
with:
submodules: recursive
- name: Resolve pinned PHP version
id: toolchain
run: bash ./infra/scripts/toolchain-lock.sh --github-output "${GITHUB_OUTPUT}"
- name: Setup PHP ${{ matrix.php-version }}
uses: shivammathur/setup-php@v2
with:
php-version: "${{ matrix.php-version }}"
coverage: none
extensions: curl, mbstring, openssl, sockets
- name: Install system dependencies
run: bash ./infra/scripts/install-ci-system-dependencies.sh
- name: Download pinned LSQUIC runtime
uses: actions/download-artifact@v7
with:
name: king-lsquic-runtime-${{ matrix.arch-label }}
path: .cache/king/lsquic/runtime/prefix
- name: Build canonical release profile
working-directory: extension
env:
KING_LSQUIC_RUNTIME_PREFIX: ${{ github.workspace }}/.cache/king/lsquic/runtime/prefix
run: ../infra/scripts/build-profile.sh release
- name: Package canonical release archive
id: package
working-directory: extension
run: |
output="$(../infra/scripts/package-release.sh --verify-reproducible --output-dir ../dist)"
printf '%s\n' "${output}"
archive_path="$(printf '%s\n' "${output}" | sed -n 's/^Package created: //p' | tail -n 1)"
if [[ -z "${archive_path}" ]]; then
echo "Failed to resolve packaged archive path." >&2
exit 1
fi
echo "archive_path=${archive_path}" >> "${GITHUB_OUTPUT}"
- name: Verify release-artifact supply-chain integrity
working-directory: extension
run: ../infra/scripts/verify-release-supply-chain.sh --archive "${{ steps.package.outputs.archive_path }}" --expected-git-commit "$(git rev-parse HEAD)"
- name: Verify packaged clean-host install path
working-directory: extension
run: ../infra/scripts/install-package-matrix.sh --archive "${{ steps.package.outputs.archive_path }}" --php-bins php
- name: Upload release package artifact
uses: actions/upload-artifact@v6
with:
name: king-release-package-php${{ matrix.php-version }}-${{ matrix.arch-label }}
if-no-files-found: error
path: |
dist/*.tar.gz
dist/*.tar.gz.sha256
- name: Upload package install failure artifacts
if: failure()
uses: actions/upload-artifact@v6
with:
name: king-package-install-${{ matrix.php-version }}-${{ matrix.arch-label }}-failures
if-no-files-found: ignore
path: |
dist/*.tar.gz
dist/*.tar.gz.sha256
extension/config.log
release-upgrade-compatibility:
name: Release Upgrade Compatibility
needs: canonical-baseline
runs-on: ubuntu-24.04
timeout-minutes: 90
steps:
- name: Checkout repository
uses: actions/checkout@v6
with:
fetch-depth: 0
submodules: recursive
- name: Resolve pinned PHP version
id: toolchain
run: bash ./infra/scripts/toolchain-lock.sh --github-output "${GITHUB_OUTPUT}"
- name: Setup PHP pinned canonical
uses: shivammathur/setup-php@v2
with:
php-version: "${{ steps.toolchain.outputs.canonical_php_version }}"
coverage: none
extensions: curl, mbstring, openssl, sockets
- name: Install system dependencies
run: bash ./infra/scripts/install-ci-system-dependencies.sh
- name: Resolve previous compatibility ref
id: previous
run: |
bash ./infra/scripts/resolve-previous-compatibility-ref.sh \
--event-name "${GITHUB_EVENT_NAME}" \
--push-before "${{ github.event.before }}" \
--pull-request-base "${{ github.event.pull_request.base.sha }}" \
--github-output "${GITHUB_OUTPUT}"
- name: Run release upgrade compatibility gate
working-directory: extension
run: ../infra/scripts/check-release-upgrade.sh --from-ref "${{ steps.previous.outputs.ref }}" --artifacts-dir ../compat-artifacts/release-upgrade
- name: Collect release upgrade PHPT diagnostics
if: failure()
working-directory: extension
run: |
../infra/scripts/collect-phpt-failure-artifacts.sh \
--job-name "release-upgrade-compatibility" \
--tests-dir tests \
--config-log config.log \
--output-dir ../compat-artifacts/phpt/release-upgrade
- name: Upload release upgrade failure artifacts
if: failure()
uses: actions/upload-artifact@v6
with:
name: king-release-upgrade-failures
if-no-files-found: ignore
path: |
compat-artifacts/release-upgrade/
compat-artifacts/phpt/release-upgrade/
release-downgrade-compatibility:
name: Release Downgrade Compatibility
needs: canonical-baseline
runs-on: ubuntu-24.04
timeout-minutes: 90
steps:
- name: Checkout repository
uses: actions/checkout@v6
with:
fetch-depth: 0
submodules: recursive
- name: Resolve pinned PHP version
id: toolchain
run: bash ./infra/scripts/toolchain-lock.sh --github-output "${GITHUB_OUTPUT}"
- name: Setup PHP pinned canonical
uses: shivammathur/setup-php@v2
with:
php-version: "${{ steps.toolchain.outputs.canonical_php_version }}"
coverage: none
extensions: curl, mbstring, openssl, sockets
- name: Install system dependencies
run: bash ./infra/scripts/install-ci-system-dependencies.sh
- name: Resolve previous compatibility ref
id: previous
run: |
bash ./infra/scripts/resolve-previous-compatibility-ref.sh \
--event-name "${GITHUB_EVENT_NAME}" \
--push-before "${{ github.event.before }}" \
--pull-request-base "${{ github.event.pull_request.base.sha }}" \
--github-output "${GITHUB_OUTPUT}"
- name: Run release downgrade compatibility gate
working-directory: extension
run: ../infra/scripts/check-release-downgrade.sh --from-ref "${{ steps.previous.outputs.ref }}" --artifacts-dir ../compat-artifacts/release-downgrade
- name: Collect release downgrade PHPT diagnostics
if: failure()
working-directory: extension
run: |
../infra/scripts/collect-phpt-failure-artifacts.sh \
--job-name "release-downgrade-compatibility" \
--tests-dir tests \
--config-log config.log \
--output-dir ../compat-artifacts/phpt/release-downgrade
- name: Upload release downgrade failure artifacts
if: failure()
uses: actions/upload-artifact@v6
with:
name: king-release-downgrade-failures
if-no-files-found: ignore
path: |
compat-artifacts/release-downgrade/
compat-artifacts/phpt/release-downgrade/
release-persistence-migration:
name: Release Persistence Migration
needs: canonical-baseline
runs-on: ubuntu-24.04
timeout-minutes: 90
steps:
- name: Checkout repository
uses: actions/checkout@v6
with:
fetch-depth: 0
submodules: recursive
- name: Resolve pinned PHP version
id: toolchain
run: bash ./infra/scripts/toolchain-lock.sh --github-output "${GITHUB_OUTPUT}"
- name: Setup PHP pinned canonical
uses: shivammathur/setup-php@v2
with:
php-version: "${{ steps.toolchain.outputs.canonical_php_version }}"
coverage: none
extensions: curl, mbstring, openssl, sockets
- name: Install system dependencies
run: bash ./infra/scripts/install-ci-system-dependencies.sh
- name: Resolve previous compatibility ref
id: previous
run: |
bash ./infra/scripts/resolve-previous-compatibility-ref.sh \
--event-name "${GITHUB_EVENT_NAME}" \
--push-before "${{ github.event.before }}" \
--pull-request-base "${{ github.event.pull_request.base.sha }}" \
--github-output "${GITHUB_OUTPUT}"
- name: Run release persistence migration gate
working-directory: extension
run: ../infra/scripts/check-persistence-migration.sh --from-ref "${{ steps.previous.outputs.ref }}" --artifacts-dir ../compat-artifacts/release-persistence-migration
- name: Collect release persistence PHPT diagnostics
if: failure()
working-directory: extension
run: |
../infra/scripts/collect-phpt-failure-artifacts.sh \
--job-name "release-persistence-migration" \
--tests-dir tests \
--config-log config.log \
--output-dir ../compat-artifacts/phpt/release-persistence-migration
- name: Upload release persistence migration failure artifacts
if: failure()
uses: actions/upload-artifact@v6
with:
name: king-release-persistence-migration-failures
if-no-files-found: ignore
path: |
compat-artifacts/release-persistence-migration/
compat-artifacts/phpt/release-persistence-migration/
release-config-state-compatibility:
name: Release Config-State Compatibility
needs: canonical-baseline
runs-on: ubuntu-24.04
timeout-minutes: 90
steps:
- name: Checkout repository
uses: actions/checkout@v6
with:
submodules: recursive
- name: Resolve pinned PHP version
id: toolchain
run: bash ./infra/scripts/toolchain-lock.sh --github-output "${GITHUB_OUTPUT}"
- name: Setup PHP pinned canonical
uses: shivammathur/setup-php@v2
with:
php-version: "${{ steps.toolchain.outputs.canonical_php_version }}"
coverage: none
extensions: curl, mbstring, openssl, sockets
- name: Install system dependencies
run: bash ./infra/scripts/install-ci-system-dependencies.sh
- name: Run release config-state compatibility matrix
working-directory: extension
run: ../infra/scripts/check-config-compatibility-matrix.sh --artifacts-dir ../compat-artifacts/release-config-state
- name: Collect release config-state PHPT diagnostics
if: failure()
working-directory: extension
run: |
../infra/scripts/collect-phpt-failure-artifacts.sh \
--job-name "release-config-state-compatibility" \
--tests-dir tests \
--config-log config.log \
--output-dir ../compat-artifacts/phpt/release-config-state
- name: Upload release config-state failure artifacts
if: failure()
uses: actions/upload-artifact@v6
with:
name: king-release-config-state-failures
if-no-files-found: ignore
path: |
compat-artifacts/release-config-state/
compat-artifacts/phpt/release-config-state/
sanitizer-soak:
name: ${{ matrix.mode }} sanitizer soak
needs: canonical-baseline
runs-on: ubuntu-24.04
timeout-minutes: 60
strategy:
fail-fast: false
matrix:
include:
- mode: asan
profile: asan
iterations: 5
- mode: ubsan
profile: ubsan
iterations: 5
- mode: leak
profile: asan
iterations: 3
steps:
- name: Checkout repository
uses: actions/checkout@v6
with:
submodules: recursive
- name: Resolve pinned PHP version
id: toolchain
run: bash ./infra/scripts/toolchain-lock.sh --github-output "${GITHUB_OUTPUT}"
- name: Setup PHP pinned canonical
uses: shivammathur/setup-php@v2
with:
php-version: "${{ steps.toolchain.outputs.canonical_php_version }}"
coverage: none
extensions: curl, mbstring, openssl, sockets
- name: Install system dependencies
run: bash ./infra/scripts/install-ci-system-dependencies.sh
- name: Build sanitizer profile
working-directory: extension
run: ../infra/scripts/build-profile.sh "${{ matrix.profile }}"
- name: Run sanitizer soak
working-directory: extension
run: ../infra/scripts/soak-runtime.sh "${{ matrix.mode }}" --iterations "${{ matrix.iterations }}" --artifacts-dir ../soak-artifacts/${{ matrix.mode }}
- name: Collect sanitizer PHPT diagnostics
if: failure()
working-directory: extension
run: |
../infra/scripts/collect-phpt-failure-artifacts.sh \
--job-name "sanitizer-soak-${{ matrix.mode }}" \
--tests-dir tests \
--config-log config.log \
--output-dir ../compat-artifacts/phpt/sanitizer-${{ matrix.mode }}
- name: Upload sanitizer soak failure artifacts
if: failure()
uses: actions/upload-artifact@v6
with:
name: king-${{ matrix.mode }}-soak-diagnostics
if-no-files-found: ignore
path: |
soak-artifacts/${{ matrix.mode }}/
compat-artifacts/phpt/sanitizer-${{ matrix.mode }}/
release-full-gate:
name: Full pipeline completed
needs:
- lsquic-runtime
- canonical-baseline
- profile-smoke
- install-package-matrix
- release-upgrade-compatibility
- release-downgrade-compatibility
- release-persistence-migration
- release-config-state-compatibility
- sanitizer-soak
- branch-push-dedupe
if: needs.branch-push-dedupe.outputs.run-heavy-jobs == 'true'
runs-on: ubuntu-24.04
steps:
- name: Full release pipeline passed
run: echo "Full pipeline passed and release packages are ready."