diff --git a/.github/workflows/builds.yml b/.github/workflows/builds.yml index c491b10a..dc4a0e47 100644 --- a/.github/workflows/builds.yml +++ b/.github/workflows/builds.yml @@ -330,256 +330,3 @@ jobs: else ./build.sh clean-all || true fi - - docker-build-x64: - name: Build (docker-linux-x64) - runs-on: ubuntu-latest - if: github.event_name == 'pull_request' - - steps: - - name: Checkout (with submodules) - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - submodules: recursive - fetch-depth: 0 - - - name: Check if Dockerfile.base changed - id: base_changed - shell: bash - run: | - set -euo pipefail - if git diff --name-only "origin/${{ github.base_ref }}...HEAD" | grep -q '^docker/Dockerfile\.base$'; then - echo "changed=true" >> "$GITHUB_OUTPUT" - else - echo "changed=false" >> "$GITHUB_OUTPUT" - fi - - - name: Free disk space - uses: jlumbroso/free-disk-space@54081f138730dfa15788a46383842cd2f914a1be # v1.3.1 - with: - tool-cache: false - android: true - dotnet: true - haskell: true - large-packages: true - docker-images: true - swap-storage: true - - - name: Pull base image from GHCR - if: steps.base_changed.outputs.changed == 'false' - shell: bash - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - set -euxo pipefail - owner="$(echo "${GITHUB_REPOSITORY_OWNER}" | tr '[:upper:]' '[:lower:]')" - echo "${GITHUB_TOKEN}" | docker login ghcr.io -u "${{ github.actor }}" --password-stdin - docker pull "ghcr.io/${owner}/client-sdk-cpp-base:base-main-amd64" - docker tag "ghcr.io/${owner}/client-sdk-cpp-base:base-main-amd64" \ - "livekit-cpp-sdk-base-x64:${{ github.sha }}" - - - name: Build base Docker image - if: steps.base_changed.outputs.changed == 'true' - run: | - docker build \ - --build-arg TARGETARCH=amd64 \ - -t livekit-cpp-sdk-base-x64:${{ github.sha }} \ - -f docker/Dockerfile.base \ - docker - - - name: Build SDK Docker image - run: | - docker build \ - --build-arg BASE_IMAGE=livekit-cpp-sdk-base-x64:${{ github.sha }} \ - -t livekit-cpp-sdk-x64:${{ github.sha }} \ - . \ - -f docker/Dockerfile.sdk - - - name: Verify installed SDK inside image - run: | - docker run --rm livekit-cpp-sdk-x64:${{ github.sha }} bash -c \ - 'test -f /opt/livekit-sdk/lib/cmake/LiveKit/LiveKitConfig.cmake' - - - name: Save Docker image artifact - run: | - docker save livekit-cpp-sdk-x64:${{ github.sha }} | gzip > livekit-cpp-sdk-x64-docker.tar.gz - - - name: Upload Docker image artifact - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 - with: - name: livekit-cpp-sdk-docker-x64 - path: livekit-cpp-sdk-x64-docker.tar.gz - retention-days: 7 - - docker-build-linux-arm64: - name: Build (docker-linux-arm64) - runs-on: ubuntu-24.04-arm - if: github.event_name == 'pull_request' - - steps: - - name: Checkout (with submodules) - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - submodules: recursive - fetch-depth: 0 - - - name: Check if Dockerfile.base changed - id: base_changed - shell: bash - run: | - set -euo pipefail - if git diff --name-only "origin/${{ github.base_ref }}...HEAD" | grep -q '^docker/Dockerfile\.base$'; then - echo "changed=true" >> "$GITHUB_OUTPUT" - else - echo "changed=false" >> "$GITHUB_OUTPUT" - fi - - - name: Free disk space - uses: jlumbroso/free-disk-space@54081f138730dfa15788a46383842cd2f914a1be # v1.3.1 - with: - tool-cache: false - android: true - dotnet: true - haskell: true - large-packages: true - docker-images: true - swap-storage: true - - - name: Pull base image from GHCR - if: steps.base_changed.outputs.changed == 'false' - shell: bash - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - set -euxo pipefail - owner="$(echo "${GITHUB_REPOSITORY_OWNER}" | tr '[:upper:]' '[:lower:]')" - echo "${GITHUB_TOKEN}" | docker login ghcr.io -u "${{ github.actor }}" --password-stdin - docker pull "ghcr.io/${owner}/client-sdk-cpp-base:base-main-arm64" - docker tag "ghcr.io/${owner}/client-sdk-cpp-base:base-main-arm64" \ - "livekit-cpp-sdk-base-arm64:${{ github.sha }}" - - - name: Build base Docker image - if: steps.base_changed.outputs.changed == 'true' - run: | - docker build \ - --build-arg TARGETARCH=arm64 \ - -t livekit-cpp-sdk-base-arm64:${{ github.sha }} \ - -f docker/Dockerfile.base \ - docker - - - name: Build SDK Docker image - run: | - docker build \ - --build-arg BASE_IMAGE=livekit-cpp-sdk-base-arm64:${{ github.sha }} \ - -t livekit-cpp-sdk:${{ github.sha }} \ - . \ - -f docker/Dockerfile.sdk - - - name: Verify installed SDK inside image - run: | - docker run --rm livekit-cpp-sdk:${{ github.sha }} bash -c \ - 'test -f /opt/livekit-sdk/lib/cmake/LiveKit/LiveKitConfig.cmake' - - - name: Save Docker image artifact - run: | - docker save livekit-cpp-sdk:${{ github.sha }} | gzip > livekit-cpp-sdk-arm64-docker.tar.gz - - - name: Upload Docker image artifact - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 - with: - name: livekit-cpp-sdk-docker-arm64 - path: livekit-cpp-sdk-arm64-docker.tar.gz - retention-days: 7 - - build-collections-linux-arm64: - name: Build (cpp-example-collection-linux-arm64) - runs-on: ubuntu-24.04-arm - needs: docker-build-linux-arm64 - if: github.event_name == 'pull_request' - - steps: - - name: Checkout - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - fetch-depth: 1 - - # Reclaim ~30GB before loading the multi-GB SDK image and building the - # example collection inside it. Mirrors the docker-build jobs; without it - # the x64 collection build has hit "no space left on device". - - name: Free disk space - uses: jlumbroso/free-disk-space@54081f138730dfa15788a46383842cd2f914a1be # v1.3.1 - with: - tool-cache: false - android: true - dotnet: true - haskell: true - large-packages: true - docker-images: true - swap-storage: true - - - name: Download Docker image artifact - uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 - with: - name: livekit-cpp-sdk-docker-arm64 - - - name: Load Docker image - run: gzip -dc livekit-cpp-sdk-arm64-docker.tar.gz | docker load - - - name: Build cpp-example-collection against installed SDK - run: | - cpp_ex_ref="$(git rev-parse HEAD:cpp-example-collection)" - docker run -e CPP_EX_REF="${cpp_ex_ref}" --rm livekit-cpp-sdk:${{ github.sha }} bash -lc ' - set -euxo pipefail - git clone https://github.com/livekit-examples/cpp-example-collection.git /tmp/cpp-example-collection - cd /tmp/cpp-example-collection - git fetch --depth 1 origin "$CPP_EX_REF" - git checkout "$CPP_EX_REF" - cmake -S . -B build -DLIVEKIT_LOCAL_SDK_DIR=/opt/livekit-sdk - cmake --build build --parallel - ' - build-collections-x64: - name: Build (cpp-example-collection-x64) - runs-on: ubuntu-latest - needs: docker-build-x64 - if: github.event_name == 'pull_request' - - steps: - - name: Checkout - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - fetch-depth: 1 - - # Reclaim ~30GB before loading the multi-GB SDK image and building the - # example collection inside it. The standard ubuntu-latest runner has hit - # "no space left on device" here without this step. - - name: Free disk space - uses: jlumbroso/free-disk-space@54081f138730dfa15788a46383842cd2f914a1be # v1.3.1 - with: - tool-cache: false - android: true - dotnet: true - haskell: true - large-packages: true - docker-images: true - swap-storage: true - - - name: Download Docker image artifact - uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 - with: - name: livekit-cpp-sdk-docker-x64 - - - name: Load Docker image - run: gzip -dc livekit-cpp-sdk-x64-docker.tar.gz | docker load - - - name: Build cpp-example-collection against installed SDK - run: | - cpp_ex_ref="$(git rev-parse HEAD:cpp-example-collection)" - docker run -e CPP_EX_REF="${cpp_ex_ref}" --rm livekit-cpp-sdk-x64:${{ github.sha }} bash -lc ' - set -euxo pipefail - git clone https://github.com/livekit-examples/cpp-example-collection.git /tmp/cpp-example-collection - cd /tmp/cpp-example-collection - git fetch --depth 1 origin "$CPP_EX_REF" - git checkout "$CPP_EX_REF" - cmake -S . -B build -DLIVEKIT_LOCAL_SDK_DIR=/opt/livekit-sdk - cmake --build build --parallel - ' diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 163fdae3..fd1adabf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,7 +11,7 @@ on: permissions: contents: read actions: read - packages: read + packages: write jobs: # Compute once which path groups changed; every other job references these @@ -23,6 +23,7 @@ jobs: runs-on: ubuntu-latest outputs: builds: ${{ steps.filter.outputs.builds }} + docker: ${{ steps.filter.outputs.docker }} tests: ${{ steps.filter.outputs.tests }} docs: ${{ steps.filter.outputs.docs }} cpp_checks: ${{ steps.filter.outputs.cpp_checks }} @@ -40,7 +41,6 @@ jobs: - cpp-example-collection/** - client-sdk-rust/** - cmake/** - - docker/** - CMakeLists.txt - CMakePresets.json - build* @@ -48,6 +48,16 @@ jobs: - vcpkg.json - .github/workflows/ci.yml - .github/workflows/builds.yml + docker: + - docker/** + - .dockerignore + - CMakeLists.txt + - CMakePresets.json + - build* + - .build* + - cmake/** + - .github/workflows/ci.yml + - .github/workflows/docker-images.yml tests: - src/** - include/** @@ -92,6 +102,13 @@ jobs: uses: ./.github/workflows/builds.yml secrets: inherit + # docker-images: + # name: Docker Images + # needs: changes + # if: ${{ needs.changes.outputs.docker == 'true' || github.event_name == 'workflow_dispatch' }} + # uses: ./.github/workflows/docker-images.yml + # secrets: inherit + tests: name: Tests needs: changes @@ -126,6 +143,7 @@ jobs: needs: - changes - builds + # - docker-images - tests - license-check - cpp-checks diff --git a/.github/workflows/docker-images.yml b/.github/workflows/docker-images.yml index 9c48faf0..d4055499 100644 --- a/.github/workflows/docker-images.yml +++ b/.github/workflows/docker-images.yml @@ -1,33 +1,16 @@ name: Docker Images on: - push: - branches: ["main"] - paths: - - src/** - - include/** - - client-sdk-rust/** - - CMakeLists.txt - - build.sh - - build.cmd - - build.h.in - - .build-info.json.in - - CMakePresets.json - - cmake/** - - data/** - - cpp-example-collection - - docker/Dockerfile.base - - docker/Dockerfile.sdk - - .github/workflows/docker-images.yml - - .github/workflows/docker-validate.yml + workflow_call: {} + workflow_dispatch: {} permissions: contents: read packages: write jobs: - detect-changes: - name: Detect Docker image changes + metadata: + name: Docker Metadata runs-on: ubuntu-latest outputs: base_changed: ${{ steps.changes.outputs.base_changed }} @@ -47,8 +30,10 @@ jobs: run: | set -euo pipefail owner="$(echo "${GITHUB_REPOSITORY_OWNER}" | tr '[:upper:]' '[:lower:]')" - echo "base_image=ghcr.io/${owner}/client-sdk-cpp-base" >> "$GITHUB_OUTPUT" - echo "sdk_image=ghcr.io/${owner}/client-sdk-cpp" >> "$GITHUB_OUTPUT" + { + echo "base_image=ghcr.io/${owner}/client-sdk-cpp-base" + echo "sdk_image=ghcr.io/${owner}/client-sdk-cpp" + } >> "$GITHUB_OUTPUT" - name: Hash base Dockerfile id: hash @@ -64,10 +49,13 @@ jobs: run: | set -euo pipefail - if [[ "${{ github.event.before }}" == "0000000000000000000000000000000000000000" ]]; then - changed_files="$(git ls-tree -r --name-only "${{ github.sha }}")" - else + if [[ "${{ github.event_name }}" == "pull_request" ]]; then + changed_files="$(git diff --name-only "origin/${{ github.base_ref }}...HEAD")" + elif [[ "${{ github.event_name }}" == "push" && + "${{ github.event.before }}" != "0000000000000000000000000000000000000000" ]]; then changed_files="$(git diff --name-only "${{ github.event.before }}" "${{ github.sha }}")" + else + changed_files="$(git ls-tree -r --name-only "${{ github.sha }}")" fi echo "Changed files:" @@ -92,24 +80,39 @@ jobs: fi case "${path}" in - docker/Dockerfile.sdk|src/*|include/*|client-sdk-rust/*|cmake/*|data/*|cpp-example-collection|CMakeLists.txt|build.sh|build.cmd|build.h.in|.build-info.json.in|CMakePresets.json|.github/workflows/docker-images.yml|.github/workflows/docker-validate.yml) + docker/*|.dockerignore|src/*|include/*|client-sdk-rust/*|cmake/*|data/*|cpp-example-collection|CMakeLists.txt|CMakePresets.json|build*|.build*|.github/workflows/docker-images.yml) sdk_changed=true ;; esac done <<< "${changed_files}" - echo "base_changed=${base_changed}" >> "$GITHUB_OUTPUT" - echo "sdk_changed=${sdk_changed}" >> "$GITHUB_OUTPUT" - - build-base-amd64: - name: Publish base image (amd64) - runs-on: ubuntu-latest - needs: detect-changes - if: needs.detect-changes.outputs.base_changed == 'true' + { + echo "base_changed=${base_changed}" + echo "sdk_changed=${sdk_changed}" + } >> "$GITHUB_OUTPUT" + + validate: + name: Validate Docker image (${{ matrix.name }}) + needs: metadata + if: needs.metadata.outputs.sdk_changed == 'true' + strategy: + fail-fast: false + matrix: + include: + - name: linux-x64 + runner: ubuntu-latest + arch: amd64 + - name: linux-arm64 + runner: ubuntu-24.04-arm + arch: arm64 + runs-on: ${{ matrix.runner }} steps: - - name: Checkout + - name: Checkout (with submodules) uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + submodules: recursive + fetch-depth: 0 - name: Free disk space uses: jlumbroso/free-disk-space@54081f138730dfa15788a46383842cd2f914a1be # v1.3.1 @@ -122,9 +125,6 @@ jobs: docker-images: true swap-storage: true - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0 - - name: Login to GHCR shell: bash env: @@ -133,23 +133,82 @@ jobs: set -euo pipefail echo "${GITHUB_TOKEN}" | docker login ghcr.io -u "${{ github.actor }}" --password-stdin - - name: Build and push base image + - name: Pull base image from GHCR + if: needs.metadata.outputs.base_changed == 'false' shell: bash run: | set -euxo pipefail - docker buildx build \ - --platform linux/amd64 \ - --push \ - -t "${{ needs.detect-changes.outputs.base_image }}:base-${{ needs.detect-changes.outputs.base_hash }}-amd64" \ - -t "${{ needs.detect-changes.outputs.base_image }}:base-main-amd64" \ + docker pull "${{ needs.metadata.outputs.base_image }}:base-main-${{ matrix.arch }}" + docker tag "${{ needs.metadata.outputs.base_image }}:base-main-${{ matrix.arch }}" \ + "livekit-cpp-sdk-base-${{ matrix.arch }}:${{ github.sha }}" + + - name: Build base Docker image + if: needs.metadata.outputs.base_changed == 'true' + shell: bash + run: | + set -euxo pipefail + DOCKER_BUILDKIT=1 docker build \ + --build-arg TARGETARCH=${{ matrix.arch }} \ + -t "livekit-cpp-sdk-base-${{ matrix.arch }}:${{ github.sha }}" \ -f docker/Dockerfile.base \ docker - build-base-arm64: - name: Publish base image (arm64) - runs-on: ubuntu-24.04-arm - needs: detect-changes - if: needs.detect-changes.outputs.base_changed == 'true' + - name: Build SDK Docker image + shell: bash + run: | + set -euxo pipefail + DOCKER_BUILDKIT=1 docker build \ + --build-arg BASE_IMAGE="livekit-cpp-sdk-base-${{ matrix.arch }}:${{ github.sha }}" \ + -t "livekit-cpp-sdk-${{ matrix.arch }}:${{ github.sha }}" \ + . \ + -f docker/Dockerfile.sdk + + - name: Verify installed SDK inside image + shell: bash + run: | + set -euxo pipefail + docker run --rm "livekit-cpp-sdk-${{ matrix.arch }}:${{ github.sha }}" bash -c \ + 'test -f /opt/livekit-sdk/lib/cmake/LiveKit/LiveKitConfig.cmake' + + - name: Build cpp-example-collection against installed SDK + shell: bash + run: | + set -euxo pipefail + cpp_ex_ref="$(git rev-parse HEAD:cpp-example-collection)" + docker run -e CPP_EX_REF="${cpp_ex_ref}" --rm "livekit-cpp-sdk-${{ matrix.arch }}:${{ github.sha }}" bash -lc ' + set -euxo pipefail + git clone https://github.com/livekit-examples/cpp-example-collection.git /tmp/cpp-example-collection + cd /tmp/cpp-example-collection + git fetch --depth 1 origin "$CPP_EX_REF" + git checkout "$CPP_EX_REF" + cmake -S . -B build -DLIVEKIT_LOCAL_SDK_DIR=/opt/livekit-sdk + cmake --build build --parallel + ' + + publish-base: + name: Publish base image (${{ matrix.name }}) + needs: + - metadata + - validate + if: | + github.event_name == 'push' && + github.ref == 'refs/heads/main' && + needs.metadata.outputs.base_changed == 'true' && + needs.validate.result == 'success' + permissions: + contents: read + packages: write + strategy: + fail-fast: false + matrix: + include: + - name: linux-x64 + runner: ubuntu-latest + arch: amd64 + - name: linux-arm64 + runner: ubuntu-24.04-arm + arch: arm64 + runs-on: ${{ matrix.runner }} steps: - name: Checkout @@ -182,21 +241,30 @@ jobs: run: | set -euxo pipefail docker buildx build \ - --platform linux/arm64 \ + --platform linux/${{ matrix.arch }} \ + --cache-from type=registry,ref="${{ needs.metadata.outputs.base_image }}:buildcache-base-${{ matrix.arch }}" \ + --cache-to type=registry,ref="${{ needs.metadata.outputs.base_image }}:buildcache-base-${{ matrix.arch }}",mode=max \ --push \ - -t "${{ needs.detect-changes.outputs.base_image }}:base-${{ needs.detect-changes.outputs.base_hash }}-arm64" \ - -t "${{ needs.detect-changes.outputs.base_image }}:base-main-arm64" \ + -t "${{ needs.metadata.outputs.base_image }}:base-${{ needs.metadata.outputs.base_hash }}-${{ matrix.arch }}" \ + -t "${{ needs.metadata.outputs.base_image }}:base-main-${{ matrix.arch }}" \ -f docker/Dockerfile.base \ docker publish-base-manifest: name: Publish base manifest - runs-on: ubuntu-latest needs: - - detect-changes - - build-base-amd64 - - build-base-arm64 - if: needs.detect-changes.outputs.base_changed == 'true' + - metadata + - publish-base + if: | + always() && + github.event_name == 'push' && + github.ref == 'refs/heads/main' && + needs.metadata.outputs.base_changed == 'true' && + needs.publish-base.result == 'success' + permissions: + contents: read + packages: write + runs-on: ubuntu-latest steps: - name: Set up Docker Buildx @@ -215,22 +283,42 @@ jobs: run: | set -euxo pipefail docker buildx imagetools create \ - -t "${{ needs.detect-changes.outputs.base_image }}:base-${{ needs.detect-changes.outputs.base_hash }}" \ - -t "${{ needs.detect-changes.outputs.base_image }}:base-main" \ - "${{ needs.detect-changes.outputs.base_image }}:base-${{ needs.detect-changes.outputs.base_hash }}-amd64" \ - "${{ needs.detect-changes.outputs.base_image }}:base-${{ needs.detect-changes.outputs.base_hash }}-arm64" + -t "${{ needs.metadata.outputs.base_image }}:base-${{ needs.metadata.outputs.base_hash }}" \ + -t "${{ needs.metadata.outputs.base_image }}:base-main" \ + "${{ needs.metadata.outputs.base_image }}:base-${{ needs.metadata.outputs.base_hash }}-amd64" \ + "${{ needs.metadata.outputs.base_image }}:base-${{ needs.metadata.outputs.base_hash }}-arm64" - build-sdk-amd64: - name: Publish SDK image (amd64) - runs-on: ubuntu-latest + publish-sdk: + name: Publish SDK image (${{ matrix.name }}) needs: - - detect-changes - - build-base-amd64 + - metadata + - validate + - publish-base + - publish-base-manifest if: | always() && - needs.detect-changes.outputs.sdk_changed == 'true' && - needs.build-base-amd64.result != 'failure' && - needs.build-base-amd64.result != 'cancelled' + github.event_name == 'push' && + github.ref == 'refs/heads/main' && + needs.metadata.outputs.sdk_changed == 'true' && + needs.validate.result == 'success' && + needs.publish-base.result != 'failure' && + needs.publish-base.result != 'cancelled' && + needs.publish-base-manifest.result != 'failure' && + needs.publish-base-manifest.result != 'cancelled' + permissions: + contents: read + packages: write + strategy: + fail-fast: false + matrix: + include: + - name: linux-x64 + runner: ubuntu-latest + arch: amd64 + - name: linux-arm64 + runner: ubuntu-24.04-arm + arch: arm64 + runs-on: ${{ matrix.runner }} steps: - name: Checkout @@ -265,45 +353,40 @@ jobs: shell: bash run: | set -euxo pipefail + if [[ "${{ needs.metadata.outputs.base_changed }}" == "true" ]]; then + base_ref="${{ needs.metadata.outputs.base_image }}:base-${{ needs.metadata.outputs.base_hash }}-${{ matrix.arch }}" + else + base_ref="${{ needs.metadata.outputs.base_image }}:base-main-${{ matrix.arch }}" + fi + docker buildx build \ - --platform linux/amd64 \ - --build-arg BASE_IMAGE="${{ needs.detect-changes.outputs.base_image }}:base-${{ needs.detect-changes.outputs.base_hash }}-amd64" \ + --platform linux/${{ matrix.arch }} \ + --build-arg BASE_IMAGE="${base_ref}" \ + --cache-from type=registry,ref="${{ needs.metadata.outputs.sdk_image }}:buildcache-sdk-${{ matrix.arch }}" \ + --cache-to type=registry,ref="${{ needs.metadata.outputs.sdk_image }}:buildcache-sdk-${{ matrix.arch }}",mode=max \ --push \ - -t "${{ needs.detect-changes.outputs.sdk_image }}:sha-${{ github.sha }}-amd64" \ - -t "${{ needs.detect-changes.outputs.sdk_image }}:main-amd64" \ + -t "${{ needs.metadata.outputs.sdk_image }}:sha-${{ github.sha }}-${{ matrix.arch }}" \ + -t "${{ needs.metadata.outputs.sdk_image }}:main-${{ matrix.arch }}" \ . \ -f docker/Dockerfile.sdk - build-sdk-arm64: - name: Publish SDK image (arm64) - runs-on: ubuntu-24.04-arm + publish-sdk-manifest: + name: Publish SDK manifest needs: - - detect-changes - - build-base-arm64 + - metadata + - publish-sdk if: | always() && - needs.detect-changes.outputs.sdk_changed == 'true' && - needs.build-base-arm64.result != 'failure' && - needs.build-base-arm64.result != 'cancelled' + github.event_name == 'push' && + github.ref == 'refs/heads/main' && + needs.metadata.outputs.sdk_changed == 'true' && + needs.publish-sdk.result == 'success' + permissions: + contents: read + packages: write + runs-on: ubuntu-latest steps: - - name: Checkout - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - submodules: recursive - fetch-depth: 0 - - - name: Free disk space - uses: jlumbroso/free-disk-space@54081f138730dfa15788a46383842cd2f914a1be # v1.3.1 - with: - tool-cache: false - android: true - dotnet: true - haskell: true - large-packages: true - docker-images: true - swap-storage: true - - name: Set up Docker Buildx uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0 @@ -315,37 +398,45 @@ jobs: set -euo pipefail echo "${GITHUB_TOKEN}" | docker login ghcr.io -u "${{ github.actor }}" --password-stdin - - name: Build and push SDK image + - name: Publish SDK manifest tags shell: bash run: | set -euxo pipefail - docker buildx build \ - --platform linux/arm64 \ - --build-arg BASE_IMAGE="${{ needs.detect-changes.outputs.base_image }}:base-${{ needs.detect-changes.outputs.base_hash }}-arm64" \ - --push \ - -t "${{ needs.detect-changes.outputs.sdk_image }}:sha-${{ github.sha }}-arm64" \ - -t "${{ needs.detect-changes.outputs.sdk_image }}:main-arm64" \ - . \ - -f docker/Dockerfile.sdk + docker buildx imagetools create \ + -t "${{ needs.metadata.outputs.sdk_image }}:sha-${{ github.sha }}" \ + -t "${{ needs.metadata.outputs.sdk_image }}:main" \ + "${{ needs.metadata.outputs.sdk_image }}:sha-${{ github.sha }}-amd64" \ + "${{ needs.metadata.outputs.sdk_image }}:sha-${{ github.sha }}-arm64" - publish-sdk-manifest: - name: Publish SDK manifest - runs-on: ubuntu-latest + validate-published: + name: Validate published Docker image (${{ matrix.name }}) needs: - - detect-changes - - build-sdk-amd64 - - build-sdk-arm64 + - metadata + - publish-sdk-manifest if: | always() && - needs.detect-changes.outputs.sdk_changed == 'true' && - needs.build-sdk-amd64.result != 'failure' && - needs.build-sdk-amd64.result != 'cancelled' && - needs.build-sdk-arm64.result != 'failure' && - needs.build-sdk-arm64.result != 'cancelled' + github.event_name == 'push' && + github.ref == 'refs/heads/main' && + needs.metadata.outputs.sdk_changed == 'true' && + needs.publish-sdk-manifest.result == 'success' + permissions: + contents: read + packages: read + strategy: + fail-fast: false + matrix: + include: + - name: linux-x64 + runner: ubuntu-latest + - name: linux-arm64 + runner: ubuntu-24.04-arm + runs-on: ${{ matrix.runner }} steps: - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0 + - name: Checkout + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + fetch-depth: 1 - name: Login to GHCR shell: bash @@ -355,12 +446,30 @@ jobs: set -euo pipefail echo "${GITHUB_TOKEN}" | docker login ghcr.io -u "${{ github.actor }}" --password-stdin - - name: Publish SDK manifest tags + - name: Pull SDK image shell: bash run: | set -euxo pipefail - docker buildx imagetools create \ - -t "${{ needs.detect-changes.outputs.sdk_image }}:sha-${{ github.sha }}" \ - -t "${{ needs.detect-changes.outputs.sdk_image }}:main" \ - "${{ needs.detect-changes.outputs.sdk_image }}:sha-${{ github.sha }}-amd64" \ - "${{ needs.detect-changes.outputs.sdk_image }}:sha-${{ github.sha }}-arm64" + time docker pull "${{ needs.metadata.outputs.sdk_image }}:sha-${{ github.sha }}" + + - name: Verify installed SDK inside image + shell: bash + run: | + set -euxo pipefail + docker run --rm "${{ needs.metadata.outputs.sdk_image }}:sha-${{ github.sha }}" bash -c \ + 'test -f /opt/livekit-sdk/lib/cmake/LiveKit/LiveKitConfig.cmake' + + - name: Build cpp-example-collection against installed SDK + shell: bash + run: | + set -euxo pipefail + cpp_ex_ref="$(git rev-parse HEAD:cpp-example-collection)" + docker run -e CPP_EX_REF="${cpp_ex_ref}" --rm "${{ needs.metadata.outputs.sdk_image }}:sha-${{ github.sha }}" bash -lc ' + set -euxo pipefail + git clone https://github.com/livekit-examples/cpp-example-collection.git /tmp/cpp-example-collection + cd /tmp/cpp-example-collection + git fetch --depth 1 origin "$CPP_EX_REF" + git checkout "$CPP_EX_REF" + cmake -S . -B build -DLIVEKIT_LOCAL_SDK_DIR=/opt/livekit-sdk + cmake --build build --parallel + ' diff --git a/.github/workflows/docker-validate.yml b/.github/workflows/docker-validate.yml deleted file mode 100644 index a69a3c65..00000000 --- a/.github/workflows/docker-validate.yml +++ /dev/null @@ -1,119 +0,0 @@ -name: Docker Validate - -on: - workflow_run: - workflows: ["Docker Images"] - types: [completed] - -permissions: - contents: read - packages: read - -jobs: - validate-x64: - name: Validate Docker image (linux-x64) - runs-on: ubuntu-latest - if: | - github.event.workflow_run.conclusion == 'success' && - github.event.workflow_run.event == 'push' && - github.event.workflow_run.head_branch == 'main' - - steps: - - name: Checkout - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - fetch-depth: 1 - - - name: Resolve image name - id: refs - shell: bash - run: | - set -euo pipefail - owner="$(echo "${GITHUB_REPOSITORY_OWNER}" | tr '[:upper:]' '[:lower:]')" - echo "sdk_image=ghcr.io/${owner}/client-sdk-cpp:sha-${{ github.event.workflow_run.head_sha }}" >> "$GITHUB_OUTPUT" - - - name: Login to GHCR - shell: bash - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - set -euo pipefail - echo "${GITHUB_TOKEN}" | docker login ghcr.io -u "${{ github.actor }}" --password-stdin - - - name: Pull SDK image - shell: bash - run: | - set -euxo pipefail - time docker pull "${{ steps.refs.outputs.sdk_image }}" - - - name: Verify installed SDK inside image - run: | - docker run --rm "${{ steps.refs.outputs.sdk_image }}" bash -c \ - 'test -f /opt/livekit-sdk/lib/cmake/LiveKit/LiveKitConfig.cmake' - - - name: Build cpp-example-collection against installed SDK - run: | - cpp_ex_ref="$(git rev-parse HEAD:cpp-example-collection)" - docker run -e CPP_EX_REF="${cpp_ex_ref}" --rm "${{ steps.refs.outputs.sdk_image }}" bash -lc ' - set -euxo pipefail - git clone https://github.com/livekit-examples/cpp-example-collection.git /tmp/cpp-example-collection - cd /tmp/cpp-example-collection - git fetch --depth 1 origin "$CPP_EX_REF" - git checkout "$CPP_EX_REF" - cmake -S . -B build -DLIVEKIT_LOCAL_SDK_DIR=/opt/livekit-sdk - cmake --build build --parallel - ' - - validate-arm64: - name: Validate Docker image (linux-arm64) - runs-on: ubuntu-24.04-arm - if: | - github.event.workflow_run.conclusion == 'success' && - github.event.workflow_run.event == 'push' && - github.event.workflow_run.head_branch == 'main' - - steps: - - name: Checkout - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - fetch-depth: 1 - - - name: Resolve image name - id: refs - shell: bash - run: | - set -euo pipefail - owner="$(echo "${GITHUB_REPOSITORY_OWNER}" | tr '[:upper:]' '[:lower:]')" - echo "sdk_image=ghcr.io/${owner}/client-sdk-cpp:sha-${{ github.event.workflow_run.head_sha }}" >> "$GITHUB_OUTPUT" - - - name: Login to GHCR - shell: bash - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - set -euo pipefail - echo "${GITHUB_TOKEN}" | docker login ghcr.io -u "${{ github.actor }}" --password-stdin - - - name: Pull SDK image - shell: bash - run: | - set -euxo pipefail - time docker pull "${{ steps.refs.outputs.sdk_image }}" - - - name: Verify installed SDK inside image - run: | - docker run --rm "${{ steps.refs.outputs.sdk_image }}" bash -c \ - 'test -f /opt/livekit-sdk/lib/cmake/LiveKit/LiveKitConfig.cmake' - - - name: Build cpp-example-collection against installed SDK - run: | - cpp_ex_ref="$(git rev-parse HEAD:cpp-example-collection)" - docker run -e CPP_EX_REF="${cpp_ex_ref}" --rm "${{ steps.refs.outputs.sdk_image }}" bash -lc ' - set -euxo pipefail - git clone https://github.com/livekit-examples/cpp-example-collection.git /tmp/cpp-example-collection - cd /tmp/cpp-example-collection - git fetch --depth 1 origin "$CPP_EX_REF" - git checkout "$CPP_EX_REF" - cmake -S . -B build -DLIVEKIT_LOCAL_SDK_DIR=/opt/livekit-sdk - cmake --build build --parallel - ' diff --git a/AGENTS.md b/AGENTS.md index 6eaae54d..cd3e35c5 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -391,18 +391,18 @@ all filtered stages; normal pull requests and pushes use the path filters. - `.github/workflows/generate-docs.yml` — Reusable Doxygen docs validation. - `.github/workflows/license_check.yml` — Cheap license check, run on every CI invocation. -- `.github/workflows/docker-images.yml` — Docker image build/publish workflow, - outside PR-review aggregation. -- `.github/workflows/docker-validate.yml` — Docker image validation workflow, - outside PR-review aggregation. +- `.github/workflows/docker-images.yml` — Reusable Docker packaging workflow. + Called by `ci.yml` when the `docker` filter matches; validates on PRs and + publishes images on `main`. When adding or renaming files that affect a CI stage, update the matching `ci.yml` `changes` filter in the same PR. For example, new build scripts, CMake files, package manifests, or reusable build workflows should be added to -the `builds` filter; test-only helpers to `tests`; formatting/static-analysis -configuration to `cpp_checks`; and docs generation inputs to `docs`. +the `builds` filter; Docker packaging inputs to `docker`; test-only helpers to +`tests`; formatting/static-analysis configuration to `cpp_checks`; and docs +generation inputs to `docs`. Keep broad agent guidance files such as `AGENTS.md` out of the expensive -`builds`, `tests`, `cpp_checks`, and `docs` filters unless they start affecting -generated docs or build artifacts. An `AGENTS.md`-only change should not trigger -those stages; only the always-on cheap checks should run. +`builds`, `docker`, `tests`, `cpp_checks`, and `docs` filters unless they start +affecting generated docs or build artifacts. An `AGENTS.md`-only change should +not trigger those stages; only the always-on cheap checks should run. diff --git a/docker/Dockerfile.sdk b/docker/Dockerfile.sdk index 6d31a878..2a263ee7 100644 --- a/docker/Dockerfile.sdk +++ b/docker/Dockerfile.sdk @@ -1,3 +1,5 @@ +# syntax=docker/dockerfile:1.7 +# # Copyright 2026 LiveKit # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -45,7 +47,11 @@ RUN mkdir -p /client-sdk-cpp/client-sdk-rust/.cargo \ # Build and install the SDK into a fixed prefix so downstream projects can # consume the image as a prebuilt LiveKit SDK environment. -RUN LLVM_VERSION="$(llvm-config --version | cut -d. -f1)" \ +RUN --mount=type=cache,target=/root/.cargo/registry,sharing=locked \ + --mount=type=cache,target=/root/.cargo/git,sharing=locked \ + --mount=type=cache,target=/client-sdk-cpp/client-sdk-rust/target,sharing=locked \ + --mount=type=cache,target=/client-sdk-cpp/build-release,sharing=locked \ + LLVM_VERSION="$(llvm-config --version | cut -d. -f1)" \ && export LIBCLANG_PATH="/usr/lib/llvm-${LLVM_VERSION}/lib" \ && export CXXFLAGS="-Wno-deprecated-declarations" \ && export CFLAGS="-Wno-deprecated-declarations" \