perf(random-sun-flare): reuse flare layers across batches #460
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: PR | |
| on: | |
| pull_request: | |
| branches: [main] | |
| types: [opened, synchronize, reopened, ready_for_review, converted_to_draft, labeled, unlabeled] | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.event.pull_request.number }} | |
| cancel-in-progress: true | |
| jobs: | |
| plan: | |
| name: PR plan | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| outputs: | |
| plan_json: ${{ steps.plan.outputs.plan }} | |
| markdown: ${{ steps.plan.outputs.markdown }} | |
| lint: ${{ steps.plan.outputs.lint }} | |
| mypy: ${{ steps.plan.outputs.mypy }} | |
| pyrefly: ${{ steps.plan.outputs.pyrefly }} | |
| contracts: ${{ steps.plan.outputs.contracts }} | |
| compatibility: ${{ steps.plan.outputs.compatibility }} | |
| coverage: ${{ steps.plan.outputs.coverage }} | |
| primary: ${{ steps.plan.outputs.primary }} | |
| targeted: ${{ steps.plan.outputs.targeted }} | |
| pytorch: ${{ steps.plan.outputs.pytorch }} | |
| dependency_audit: ${{ steps.plan.outputs.dependency_audit }} | |
| workflow_audit: ${{ steps.plan.outputs.workflow_audit }} | |
| legal: ${{ steps.plan.outputs.legal }} | |
| package: ${{ steps.plan.outputs.package }} | |
| install_smoke: ${{ steps.plan.outputs.install_smoke }} | |
| release_preflight: ${{ steps.plan.outputs.release_preflight }} | |
| pytest_targets: ${{ steps.plan.outputs.pytest_targets }} | |
| version_change: ${{ steps.plan.outputs.version_change }} | |
| steps: | |
| - name: Checkout pull request | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| fetch-depth: 0 | |
| persist-credentials: false | |
| - name: Set up plan environment | |
| uses: ./.github/actions/setup-ci | |
| with: | |
| python-version: "3.12" | |
| dependency-group: ci-quality | |
| - name: Collect changed paths | |
| env: | |
| BASE_SHA: ${{ github.event.pull_request.base.sha }} | |
| HEAD_SHA: ${{ github.event.pull_request.head.sha }} | |
| run: | | |
| mkdir -p ci-plan | |
| git diff --name-only -z "${BASE_SHA}" "${HEAD_SHA}" -- > ci-plan/changed-files.z | |
| git show "${BASE_SHA}:pyproject.toml" > ci-plan/base-pyproject.toml | |
| cp pyproject.toml ci-plan/head-pyproject.toml | |
| git show "${BASE_SHA}:uv.lock" > ci-plan/base-uv.lock | |
| cp uv.lock ci-plan/head-uv.lock | |
| - name: Select pull-request checks | |
| id: plan | |
| env: | |
| DRAFT: ${{ github.event.pull_request.draft }} | |
| FORCE_FULL: ${{ contains(github.event.pull_request.labels.*.name, 'full-ci') }} | |
| run: >- | |
| python -m tools.ci_plan | |
| --paths-file ci-plan/changed-files.z --null | |
| --base-pyproject ci-plan/base-pyproject.toml | |
| --head-pyproject ci-plan/head-pyproject.toml | |
| --base-lock ci-plan/base-uv.lock | |
| --head-lock ci-plan/head-uv.lock | |
| --draft "${DRAFT}" --force-full "${FORCE_FULL}" | |
| --github-output "${GITHUB_OUTPUT}" | |
| --summary "${GITHUB_STEP_SUMMARY}" | |
| - name: Upload routing evidence | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 | |
| with: | |
| name: pr-ci-plan | |
| path: ci-plan/ | |
| if-no-files-found: error | |
| retention-days: 7 | |
| markdown: | |
| name: Markdown | |
| needs: plan | |
| if: needs.plan.outputs.markdown == 'true' | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| - name: Set up quality environment | |
| uses: ./.github/actions/setup-ci | |
| with: | |
| python-version: "3.12" | |
| dependency-group: ci-quality | |
| runtime-profile: torch-cpu | |
| - name: Download changed paths | |
| uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 | |
| with: | |
| name: pr-ci-plan | |
| path: ci-plan | |
| - name: Check changed Markdown | |
| run: python -m tools.quality_gate markdown --paths-file ci-plan/changed-files.z --null | |
| lint: | |
| name: Ruff and formatting | |
| needs: plan | |
| if: needs.plan.outputs.lint == 'true' | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| - name: Set up quality environment | |
| uses: ./.github/actions/setup-ci | |
| with: | |
| python-version: "3.12" | |
| dependency-group: ci-quality | |
| - name: Run Ruff and formatting checks | |
| run: python -m tools.quality_gate lint | |
| mypy: | |
| name: mypy | |
| needs: plan | |
| if: needs.plan.outputs.mypy == 'true' | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| - name: Set up typing environment | |
| uses: ./.github/actions/setup-ci | |
| with: | |
| python-version: "3.12" | |
| dependency-group: ci-quality | |
| - name: Run mypy | |
| run: python -m tools.quality_gate mypy | |
| pyrefly: | |
| name: Pyrefly | |
| needs: plan | |
| if: needs.plan.outputs.pyrefly == 'true' | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| - name: Set up typing environment | |
| uses: ./.github/actions/setup-ci | |
| with: | |
| python-version: "3.10" | |
| dependency-group: ci-types | |
| - name: Run Pyrefly | |
| run: python -m tools.quality_gate pyrefly | |
| contracts: | |
| name: Repository contracts | |
| needs: plan | |
| if: needs.plan.outputs.contracts == 'true' | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 15 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| - name: Set up contract environment | |
| uses: ./.github/actions/setup-ci | |
| with: | |
| python-version: "3.12" | |
| dependency-group: ci-quality | |
| runtime-profile: torch-cpu | |
| - name: Download changed paths | |
| uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 | |
| with: | |
| name: pr-ci-plan | |
| path: ci-plan | |
| - name: Run repository contracts | |
| run: python -m tools.quality_gate contracts --paths-file ci-plan/changed-files.z --null | |
| fast_checks: | |
| name: Fast checks | |
| needs: [plan, markdown, lint, mypy, pyrefly, contracts] | |
| if: ${{ always() }} | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 5 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| - name: Aggregate fast checks | |
| env: | |
| PLAN_JSON: ${{ needs.plan.outputs.plan_json }} | |
| run: >- | |
| python -m tools.ci_gate --gate fast --plan-json "${PLAN_JSON}" | |
| --result "markdown=${{ needs.markdown.result }}" | |
| --result "lint=${{ needs.lint.result }}" | |
| --result "mypy=${{ needs.mypy.result }}" | |
| --result "pyrefly=${{ needs.pyrefly.result }}" | |
| --result "contracts=${{ needs.contracts.result }}" | |
| compatibility: | |
| name: Compatibility (${{ matrix.operating-system }}, Python ${{ matrix.python-version }}, ${{ matrix.shard-label }}) | |
| needs: plan | |
| if: needs.plan.outputs.compatibility == 'true' | |
| runs-on: ${{ matrix.operating-system }} | |
| timeout-minutes: 15 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| operating-system: [ubuntu-latest, macos-latest] | |
| python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"] | |
| shard-count: [1] | |
| shard-index: [0] | |
| shard-label: [full] | |
| include: | |
| - operating-system: windows-latest | |
| python-version: "3.10" | |
| shard-count: 1 | |
| shard-index: 0 | |
| shard-label: full | |
| - operating-system: windows-latest | |
| python-version: "3.11" | |
| shard-count: 2 | |
| shard-index: 0 | |
| shard-label: 1-of-2 | |
| - operating-system: windows-latest | |
| python-version: "3.11" | |
| shard-count: 2 | |
| shard-index: 1 | |
| shard-label: 2-of-2 | |
| - operating-system: windows-latest | |
| python-version: "3.12" | |
| shard-count: 2 | |
| shard-index: 0 | |
| shard-label: 1-of-2 | |
| - operating-system: windows-latest | |
| python-version: "3.12" | |
| shard-count: 2 | |
| shard-index: 1 | |
| shard-label: 2-of-2 | |
| - operating-system: windows-latest | |
| python-version: "3.13" | |
| shard-count: 2 | |
| shard-index: 0 | |
| shard-label: 1-of-2 | |
| - operating-system: windows-latest | |
| python-version: "3.13" | |
| shard-count: 2 | |
| shard-index: 1 | |
| shard-label: 2-of-2 | |
| - operating-system: windows-latest | |
| python-version: "3.14" | |
| shard-count: 1 | |
| shard-index: 0 | |
| shard-label: full | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| - name: Set up test environment | |
| uses: ./.github/actions/setup-ci | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| dependency-group: ci-test | |
| runtime-profile: torch-cpu | |
| - name: Run duration-balanced base-suite shard | |
| shell: bash | |
| run: | | |
| set -o pipefail | |
| mkdir -p ci-evidence | |
| python -m tools.ci_shard select \ | |
| --shard-count "${{ matrix.shard-count }}" \ | |
| --shard-index "${{ matrix.shard-index }}" \ | |
| --exclude-file tests/test_pytorch.py \ | |
| --exclude-file tests/transforms3d/test_pytorch.py \ | |
| | xargs -0 python -m pytest \ | |
| -n 2 --dist=worksteal -m "not pytorch" \ | |
| --hypothesis-profile=ci-fast \ | |
| --junitxml=ci-evidence/junit.xml | |
| - name: Collect test environment evidence | |
| if: always() | |
| shell: bash | |
| run: >- | |
| python tools/collect_test_environment.py | |
| --output ci-evidence/environment.json | |
| --command "python -m pytest -n 2 --dist=worksteal -m not-pytorch" | |
| - name: Summarize pytest results | |
| if: always() | |
| run: >- | |
| python tools/pytest_summary.py | |
| --junit ci-evidence/junit.xml | |
| --output ci-evidence/pytest-summary.json | |
| --allow-incomplete | |
| - name: Upload compatibility evidence | |
| if: always() | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 | |
| with: | |
| name: compatibility-${{ matrix.operating-system }}-${{ matrix.python-version }}-${{ matrix.shard-label }} | |
| path: ci-evidence/ | |
| if-no-files-found: ignore | |
| retention-days: 7 | |
| coverage: | |
| name: Primary coverage | |
| needs: plan | |
| if: needs.plan.outputs.coverage == 'true' | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 15 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| - name: Set up test environment | |
| uses: ./.github/actions/setup-ci | |
| with: | |
| python-version: "3.12" | |
| dependency-group: ci-test | |
| runtime-profile: torch-cpu | |
| - name: Run base suite with branch coverage | |
| shell: bash | |
| run: | | |
| mapfile -d '' -t test_files < <( | |
| python -m tools.ci_shard select --shard-count 1 --shard-index 0 \ | |
| --exclude-file tests/test_pytorch.py \ | |
| --exclude-file tests/transforms3d/test_pytorch.py | |
| ) | |
| python -m pytest "${test_files[@]}" \ | |
| -n 2 --dist=worksteal -m "not pytorch" \ | |
| --hypothesis-profile=ci-fast \ | |
| --cov=albumentations --cov-branch --cov-report=xml | |
| - name: Upload coverage report | |
| continue-on-error: true | |
| uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0 | |
| with: | |
| token: ${{ secrets.CODECOV_TOKEN }} | |
| slug: albumentations-team/AlbumentationsX | |
| files: ./coverage.xml | |
| disable_search: true | |
| fail_ci_if_error: false | |
| use_pypi: true | |
| version: 11.3.1 | |
| primary: | |
| name: Primary suite | |
| needs: plan | |
| if: needs.plan.outputs.primary == 'true' | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 15 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| - name: Set up test environment | |
| uses: ./.github/actions/setup-ci | |
| with: | |
| python-version: "3.12" | |
| dependency-group: ci-test | |
| runtime-profile: torch-cpu | |
| - name: Run complete base suite | |
| shell: bash | |
| run: | | |
| mapfile -d '' -t test_files < <( | |
| python -m tools.ci_shard select --shard-count 1 --shard-index 0 \ | |
| --exclude-file tests/test_pytorch.py \ | |
| --exclude-file tests/transforms3d/test_pytorch.py | |
| ) | |
| python -m pytest "${test_files[@]}" \ | |
| -n 2 --dist=worksteal -m "not pytorch" --hypothesis-profile=ci-fast | |
| targeted: | |
| name: Targeted tests (${{ matrix.operating-system }}, Python ${{ matrix.python-version }}) | |
| needs: plan | |
| if: needs.plan.outputs.targeted == 'true' | |
| runs-on: ${{ matrix.operating-system }} | |
| timeout-minutes: 10 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - operating-system: ubuntu-latest | |
| python-version: "3.12" | |
| - operating-system: windows-latest | |
| python-version: "3.10" | |
| - operating-system: windows-latest | |
| python-version: "3.14" | |
| - operating-system: macos-latest | |
| python-version: "3.10" | |
| - operating-system: macos-latest | |
| python-version: "3.14" | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| - name: Set up test environment | |
| uses: ./.github/actions/setup-ci | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| dependency-group: ci-test | |
| runtime-profile: torch-cpu | |
| - name: Run changed test modules | |
| env: | |
| PYTEST_TARGETS: ${{ needs.plan.outputs.pytest_targets }} | |
| shell: bash | |
| run: | | |
| python -c 'import json, os, pathlib; pathlib.Path("targets.z").write_bytes(b"\0".join(path.encode() for path in json.loads(os.environ["PYTEST_TARGETS"])) + b"\0")' | |
| xargs -0 python -m pytest \ | |
| -n 2 --dist=worksteal -m "not pytorch" --hypothesis-profile=ci-fast \ | |
| < targets.z | |
| pytorch: | |
| name: PyTorch tests | |
| needs: plan | |
| if: needs.plan.outputs.pytorch == 'true' | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 15 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| - name: Set up PyTorch test environment | |
| uses: ./.github/actions/setup-ci | |
| with: | |
| python-version: "3.12" | |
| dependency-group: ci-test | |
| runtime-profile: torch-cpu | |
| - name: Run PyTorch-marked tests | |
| run: >- | |
| python -m pytest -n 2 --dist=worksteal -m pytorch | |
| tests/test_pytorch.py | |
| tests/transforms3d/test_pytorch.py | |
| tests/test_per_worker_seed.py | |
| tests/test_flip_masks_comprehensive.py | |
| tests/test_additional_targets.py | |
| tests/test_benchmark_coverage.py | |
| tests/test_serialization.py | |
| - name: Validate optional benchmark policy | |
| run: | | |
| python -m tools.benchmark_coverage check | |
| python -m tools.performance_budget check | |
| correctness: | |
| name: Correctness | |
| needs: [plan, compatibility, coverage, primary, targeted, pytorch] | |
| if: ${{ always() }} | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 5 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| - name: Aggregate correctness checks | |
| env: | |
| PLAN_JSON: ${{ needs.plan.outputs.plan_json }} | |
| run: >- | |
| python -m tools.ci_gate --gate correctness --plan-json "${PLAN_JSON}" | |
| --result "compatibility=${{ needs.compatibility.result }}" | |
| --result "coverage=${{ needs.coverage.result }}" | |
| --result "primary=${{ needs.primary.result }}" | |
| --result "targeted=${{ needs.targeted.result }}" | |
| --result "pytorch=${{ needs.pytorch.result }}" | |
| dependency_audit: | |
| name: Dependency audit | |
| needs: plan | |
| if: needs.plan.outputs.dependency_audit == 'true' | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| - name: Set up security environment | |
| uses: ./.github/actions/setup-ci | |
| with: | |
| python-version: "3.12" | |
| dependency-group: ci-security | |
| - name: Export locked runtime dependencies | |
| run: >- | |
| uv export --frozen --no-dev --no-emit-project | |
| --format requirements-txt --output-file runtime-requirements.txt | |
| - name: Audit locked runtime dependencies | |
| run: >- | |
| pip-audit --requirement runtime-requirements.txt | |
| --no-deps --disable-pip --format=json --output dependency-audit.json | |
| - name: Upload dependency audit evidence | |
| if: always() | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 | |
| with: | |
| name: dependency-audit-evidence | |
| path: dependency-audit.json | |
| if-no-files-found: ignore | |
| retention-days: 7 | |
| workflow_audit: | |
| name: GitHub Actions hardening audit | |
| needs: plan | |
| if: needs.plan.outputs.workflow_audit == 'true' | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| - name: Set up security environment | |
| uses: ./.github/actions/setup-ci | |
| with: | |
| python-version: "3.12" | |
| dependency-group: ci-security | |
| - name: Run zizmor | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| run: zizmor --format=github --min-severity=medium --min-confidence=medium .github | |
| legal: | |
| name: Legal source integrity | |
| needs: plan | |
| if: needs.plan.outputs.legal == 'true' | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| - name: Set up package environment | |
| uses: ./.github/actions/setup-ci | |
| with: | |
| python-version: "3.12" | |
| dependency-group: ci-package | |
| - name: Verify source-tree legal integrity | |
| run: python tools/verify_legal_integrity.py | |
| - name: Test legal-integrity verifier | |
| run: python -m pytest --noconftest -q tests/test_legal_integrity.py | |
| package: | |
| name: Package artifacts | |
| needs: plan | |
| if: needs.plan.outputs.package == 'true' | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| - name: Set up package environment | |
| uses: ./.github/actions/setup-ci | |
| with: | |
| python-version: "3.12" | |
| dependency-group: ci-package | |
| - name: Build wheel and source distribution | |
| run: uv build --out-dir dist | |
| - name: Verify packaged legal notices | |
| run: python tools/verify_legal_integrity.py --artifacts dist/*.whl dist/*.tar.gz | |
| - name: Check distribution metadata | |
| run: twine check dist/* | |
| install_smoke: | |
| name: Install smoke (${{ matrix.operating-system }}, Python ${{ matrix.python-version }}) | |
| needs: plan | |
| if: needs.plan.outputs.install_smoke == 'true' | |
| runs-on: ${{ matrix.operating-system }} | |
| timeout-minutes: 10 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| operating-system: [ubuntu-latest, windows-latest, macos-latest] | |
| python-version: ["3.10", "3.14"] | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| - name: Set up package environment | |
| uses: ./.github/actions/setup-ci | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| dependency-group: ci-package | |
| - name: Build wheel | |
| run: uv build --wheel --out-dir dist | |
| - name: Prepare Torch-free wheel environment | |
| id: install-contract | |
| run: >- | |
| python tools/install_contract.py prepare | |
| --wheel dist/*.whl --python "${{ matrix.python-version }}" | |
| - name: Install and verify CPU-only Torch | |
| uses: albumentations-team/ci-foundation/actions/torch-cpu@6b9045dbea58026a1e8f96b0392c411934a27199 | |
| with: | |
| mode: install | |
| python: ${{ steps.install-contract.outputs.python }} | |
| requirement: "torch>=2.13.0" | |
| - name: Smoke test wheel with CPU-only Torch | |
| run: >- | |
| python tools/install_contract.py smoke | |
| --python "${{ steps.install-contract.outputs.python }}" | |
| release_preflight: | |
| name: Release preflight | |
| needs: plan | |
| if: needs.plan.outputs.release_preflight == 'true' | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 45 | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: Checkout release source | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| fetch-depth: 0 | |
| persist-credentials: false | |
| - name: Set up exact release environment | |
| uses: ./.github/actions/setup-ci | |
| with: | |
| python-version: "3.12" | |
| dependency-group: ci-release | |
| runtime-profile: torch-cpu | |
| - name: Prepare release bundle | |
| id: metadata | |
| run: | | |
| mkdir -p \ | |
| "${RUNNER_TEMP}/release-bundle/dist" \ | |
| "${RUNNER_TEMP}/release-bundle/evidence" \ | |
| "${RUNNER_TEMP}/release-bundle/public" | |
| python -m tools.release_bundle metadata \ | |
| --source-root . \ | |
| --github-output "${GITHUB_OUTPUT}" | |
| - name: Build final distributions | |
| run: uv build --out-dir "${RUNNER_TEMP}/release-bundle/dist" | |
| - name: Verify distribution license and notice integrity | |
| run: >- | |
| python tools/verify_legal_integrity.py | |
| --artifacts "${RUNNER_TEMP}"/release-bundle/dist/*.whl "${RUNNER_TEMP}"/release-bundle/dist/*.tar.gz | |
| - name: Check final distribution metadata | |
| run: twine check "${RUNNER_TEMP}"/release-bundle/dist/* | |
| - name: Prepare Torch-free final wheel environment | |
| id: release-install-contract | |
| run: >- | |
| python tools/install_contract.py prepare | |
| --wheel "${RUNNER_TEMP}"/release-bundle/dist/*.whl --python "3.12" | |
| - name: Install and verify CPU-only Torch | |
| uses: albumentations-team/ci-foundation/actions/torch-cpu@6b9045dbea58026a1e8f96b0392c411934a27199 | |
| with: | |
| mode: install | |
| python: ${{ steps.release-install-contract.outputs.python }} | |
| requirement: "torch>=2.13.0" | |
| - name: Smoke test final wheel with CPU-only Torch | |
| run: >- | |
| python tools/install_contract.py smoke | |
| --python "${{ steps.release-install-contract.outputs.python }}" | |
| - name: Verify lock freshness | |
| run: uv lock --check | |
| - name: Collect release environment evidence | |
| run: >- | |
| python tools/collect_test_environment.py | |
| --output "${RUNNER_TEMP}/release-bundle/evidence/environment-release.json" | |
| --command "version-bump PR release preflight" | |
| - name: Run release correctness evidence tests | |
| run: | | |
| python tools/verify_regression_vectors.py --all | |
| python -m pytest -q tests/regression tests/property \ | |
| --hypothesis-profile=ci-fast \ | |
| --junitxml="${RUNNER_TEMP}/release-bundle/evidence/junit-release.xml" | |
| - name: Summarize release pytest results | |
| if: always() | |
| run: >- | |
| python tools/pytest_summary.py | |
| --junit "${RUNNER_TEMP}/release-bundle/evidence/junit-release.xml" | |
| --output "${RUNNER_TEMP}/release-bundle/evidence/pytest-summary-release.json" | |
| --allow-incomplete | |
| - name: Collect core benchmark coverage evidence | |
| run: | | |
| python -m tools.benchmark_coverage summary \ | |
| --output "${RUNNER_TEMP}/release-bundle/evidence/benchmark-coverage-release.json" | |
| python -m tools.benchmark_coverage details \ | |
| --output "${RUNNER_TEMP}/release-bundle/evidence/benchmark-coverage-detail-release.json" | |
| - name: Register release ASV machine profile | |
| working-directory: benchmark | |
| run: asv --config asv.conf.json machine --yes | |
| - name: Check release ASV suite importability | |
| working-directory: benchmark | |
| run: asv --config asv.conf.json check --verbose | |
| - name: Compare previous release with release candidate | |
| working-directory: benchmark | |
| env: | |
| RELEASE_HEAD_SHA: ${{ github.event.pull_request.head.sha }} | |
| run: | | |
| set -o pipefail | |
| CANDIDATE_REF="${RELEASE_HEAD_SHA:-HEAD}" | |
| BASELINE_REF="$(git describe --tags --abbrev=0 --match '[0-9]*' "$CANDIDATE_REF^")" | |
| BASELINE_SHA="$(git rev-parse "$BASELINE_REF")" | |
| CANDIDATE_SHA="$(git rev-parse "$CANDIDATE_REF")" | |
| BENCH_FILTER="$(python "$GITHUB_WORKSPACE/tools/select_benchmark_filters.py" --profile stf-core)" | |
| EVIDENCE_DIR="${RUNNER_TEMP}/release-bundle/evidence" | |
| printf '%s\n' "$BASELINE_REF" > "$EVIDENCE_DIR/benchmark-baseline-ref.txt" | |
| printf '%s\n' "$BASELINE_SHA" > "$EVIDENCE_DIR/benchmark-baseline-sha.txt" | |
| printf '%s\n' "$CANDIDATE_REF" > "$EVIDENCE_DIR/benchmark-candidate-ref.txt" | |
| printf '%s\n' "$CANDIDATE_SHA" > "$EVIDENCE_DIR/benchmark-candidate-sha.txt" | |
| printf '%s\n' "$BENCH_FILTER" > "$EVIDENCE_DIR/benchmark-filter.txt" | |
| ASV_EXIT_CODE=0 | |
| timeout 900 asv --config asv.conf.json continuous \ | |
| --factor 1.05 --split --show-stderr \ | |
| --attribute repeat=1 --attribute number=1 \ | |
| --bench "$BENCH_FILTER" "$BASELINE_REF" "$CANDIDATE_REF" \ | |
| 2>&1 | tee "$EVIDENCE_DIR/asv-continuous.txt" || ASV_EXIT_CODE=$? | |
| printf '%s\n' "$ASV_EXIT_CODE" > "$EVIDENCE_DIR/asv-continuous-exit-code.txt" | |
| - name: Summarize release ASV comparison | |
| if: always() | |
| run: | | |
| EVIDENCE_DIR="${RUNNER_TEMP}/release-bundle/evidence" | |
| ASV_EXIT_CODE="$(cat "$EVIDENCE_DIR/asv-continuous-exit-code.txt" 2>/dev/null || true)" | |
| python tools/asv_summary.py \ | |
| --input "$EVIDENCE_DIR/asv-continuous.txt" \ | |
| --output "$EVIDENCE_DIR/benchmark-asv-summary.json" \ | |
| --asv-exit-code "${ASV_EXIT_CODE:-1}" --allow-missing | |
| - name: Classify strict release performance budget | |
| if: always() | |
| run: > | |
| python -m tools.performance_budget summarize | |
| --coverage-summary "${RUNNER_TEMP}/release-bundle/evidence/benchmark-coverage-release.json" | |
| --coverage-detail "${RUNNER_TEMP}/release-bundle/evidence/benchmark-coverage-detail-release.json" | |
| --asv-summary "${RUNNER_TEMP}/release-bundle/evidence/benchmark-asv-summary.json" | |
| --core-only | |
| --require-comparison | |
| --fail-on-release-blockers | |
| --output "${RUNNER_TEMP}/release-bundle/evidence/benchmark-performance-budget-release.json" | |
| - name: Export locked runtime dependencies | |
| run: >- | |
| uv export --frozen --no-dev --no-emit-project | |
| --format requirements-txt | |
| --output-file "${RUNNER_TEMP}/release-bundle/evidence/runtime-requirements.txt" | |
| - name: Collect release security evidence | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| run: | | |
| pip-audit \ | |
| --requirement "${RUNNER_TEMP}/release-bundle/evidence/runtime-requirements.txt" \ | |
| --no-deps \ | |
| --disable-pip \ | |
| --format=json \ | |
| --output "${RUNNER_TEMP}/release-bundle/evidence/security-pip-audit.json" | |
| zizmor \ | |
| --format=json \ | |
| --min-severity=medium \ | |
| --min-confidence=medium \ | |
| .github > "${RUNNER_TEMP}/release-bundle/evidence/security-zizmor.json" | |
| - name: Generate CycloneDX SBOM | |
| env: | |
| PACKAGE_VERSION: ${{ steps.metadata.outputs.package_version }} | |
| run: >- | |
| cyclonedx-py requirements "${RUNNER_TEMP}/release-bundle/evidence/runtime-requirements.txt" | |
| --output-format JSON | |
| --output-file | |
| "${RUNNER_TEMP}/release-bundle/public/albumentationsx-${PACKAGE_VERSION}-sbom.cdx.json" | |
| - name: Generate correctness and compatibility report | |
| env: | |
| PACKAGE_VERSION: ${{ steps.metadata.outputs.package_version }} | |
| run: >- | |
| python tools/generate_correctness_report.py | |
| --evidence-dir "${RUNNER_TEMP}/release-bundle/evidence" | |
| --output | |
| "${RUNNER_TEMP}/release-bundle/public/albumentationsx-${PACKAGE_VERSION}-correctness-compatibility-report.md" | |
| - name: Finalize immutable release bundle | |
| id: finalize | |
| run: >- | |
| python -m tools.release_bundle finalize | |
| --bundle-dir "${RUNNER_TEMP}/release-bundle" | |
| --source-root . | |
| --check clean_install | |
| --check correctness | |
| --check legal | |
| --check lock | |
| --check package | |
| --check performance_core | |
| --check report | |
| --check security | |
| --retention-days 90 | |
| --github-output "${GITHUB_OUTPUT}" | |
| - name: Upload publishable release bundle | |
| if: success() | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 | |
| with: | |
| name: ${{ steps.finalize.outputs.artifact_name }} | |
| path: ${{ runner.temp }}/release-bundle/ | |
| include-hidden-files: true | |
| if-no-files-found: error | |
| retention-days: 90 | |
| - name: Upload failed preflight diagnostics | |
| if: failure() | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 | |
| with: | |
| name: release-diagnostics-${{ steps.metadata.outputs.package_version }}-${{ github.run_id }}-${{ github.run_attempt }} | |
| path: ${{ runner.temp }}/release-bundle/evidence/ | |
| if-no-files-found: ignore | |
| retention-days: 14 | |
| security_policy: | |
| name: Security and policy | |
| needs: [plan, dependency_audit, workflow_audit, legal, package, install_smoke, release_preflight] | |
| if: ${{ always() }} | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 5 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| - name: Aggregate security and policy checks | |
| env: | |
| PLAN_JSON: ${{ needs.plan.outputs.plan_json }} | |
| run: >- | |
| python -m tools.ci_gate --gate policy --plan-json "${PLAN_JSON}" | |
| --result "dependency-audit=${{ needs.dependency_audit.result }}" | |
| --result "workflow-audit=${{ needs.workflow_audit.result }}" | |
| --result "legal=${{ needs.legal.result }}" | |
| --result "package=${{ needs.package.result }}" | |
| --result "install-smoke=${{ needs.install_smoke.result }}" | |
| --result "release-preflight=${{ needs.release_preflight.result }}" |