diff --git a/.github/workflows/_docker-build.yml b/.github/workflows/_docker-build.yml index 68f9de52a23b..2582d0fb6964 100644 --- a/.github/workflows/_docker-build.yml +++ b/.github/workflows/_docker-build.yml @@ -62,10 +62,11 @@ jobs: with open(os.environ['GITHUB_OUTPUT'], 'a') as fh: print(f"id={hash.hexdigest()}", file=fh) - - name: Create build args + - name: Format build args + uses: ./.github/actions/format-docker-build-args id: build-args - shell: python - run: python dev/create-docker-build-args.py + with: + build-args: ${{ inputs.build-args }} - name: Extract metadata (tags, labels) for Docker id: meta diff --git a/.github/workflows/_docker-test.yml b/.github/workflows/_docker-test.yml new file mode 100644 index 000000000000..aabe5557138e --- /dev/null +++ b/.github/workflows/_docker-test.yml @@ -0,0 +1,101 @@ +name: Reusable docker image test workflow + +on: + workflow_call: + inputs: + build-args: + description: "List of build-time variables." + required: false + type: string + ref: + required: false + type: string + secrets: + dockerhub-user: + required: true + dockerhub-token: + required: true + +permissions: + contents: read + +# based on https://docs.docker.com/build/ci/github-actions/multi-platform/#distribute-build-across-multiple-runners +jobs: + test: + name: Test image + runs-on: "ubuntu-22.04" + timeout-minutes: 180 + steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + ref: ${{ inputs.ref }} + + - name: Format build args + uses: ./.github/actions/format-docker-build-args + id: build-args + with: + build-args: ${{ inputs.build-args }} + + - id: matrix + run: | + python dev/build-docker-image-matrix.py --flwr-version e2e-test --simple > matrix.json + echo "matrix=$(cat matrix.json)" >> $GITHUB_OUTPUT + echo "base-file-dir=$(jq -r .base.images[0].file_dir matrix.json)" >> $GITHUB_OUTPUT + echo "base-namespace-repository=$(jq -r .base.images[0].namespace_repository matrix.json)" >> $GITHUB_OUTPUT + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@988b5a0280414f521da01fcc63a27aeeb4b104db # v3.6.1 + with: + # https://github.com/docker/build-push-action/issues/1116#issuecomment-2132899905 + driver: docker + + - name: Build base image + uses: Wandalen/wretry.action@6feedb7dedadeb826de0f45ff482b53b379a7844 # v3.5.0 + with: + action: docker/build-push-action@5cd11c3a4ced054e52742c5fd54dca954e0edd85 # v6.7.0 + attempt_limit: 60 # 60 attempts * (9 secs delay + 1 sec retry) = ~10 mins + attempt_delay: 9000 # 9 secs + with: | + pull: true + context: ${{ steps.matrix.outputs.base-file-dir }} + load: true + tags: ${{ steps.matrix.outputs.base-namespace-repository }}:e2e-test + build-args: | + ${{ steps.build-args.outputs.build-args }} + + - name: Build binary images + run: | + set -e -o pipefail + + jq -c '.binary.images[]' <<< '${{ steps.matrix.outputs.matrix }}' | while read -r i; do + FILE_DIR=$(echo "$i" | jq -r .file_dir) + NAMESPACE_REPOSITORY=$(echo "$i" | jq -r .namespace_repository) + docker build --build-arg BASE_IMAGE="e2e-test" -t "${NAMESPACE_REPOSITORY}:e2e-test" "${FILE_DIR}" + done + + - name: Bootstrap + uses: ./.github/actions/bootstrap + - name: Install Flower + run: python -m pip install . + + - name: Test images + env: + FLWR_VERSION: e2e-test + PROJECT_DIR: e2e-test + working-directory: src/docker/complete + run: | + docker images + + flwr new ${PROJECT_DIR} --framework NumPy --username flower + docker compose -f certs.yml up --build + docker compose -f compose.yml -f with-tls.yml up --build -d --pull never + + cat <<- EOT >> "${PROJECT_DIR}/pyproject.toml" + [tool.flwr.federations.local-deployment-tls] + address = "127.0.0.1:9093" + insecure = true + # root-certificates = "../superexec-certificates/ca.crt" + EOT + + flwr run ${PROJECT_DIR} local-deployment-tls + timeout 1000 docker compose logs -f | grep -q 'Run finished' diff --git a/.github/workflows/docker-test.yml b/.github/workflows/docker-test.yml new file mode 100644 index 000000000000..dbb4e3a2358a --- /dev/null +++ b/.github/workflows/docker-test.yml @@ -0,0 +1,43 @@ +name: Test Docker + +on: + push: + +jobs: + # parameters: + # if: github.repository == 'adap/flower' + # name: Collect docker build parameters + # runs-on: ubuntu-22.04 + # timeout-minutes: 10 + # outputs: + # pip-version: ${{ steps.versions.outputs.pip-version }} + # setuptools-version: ${{ steps.versions.outputs.setuptools-version }} + # flwr-version-ref: ${{ steps.versions.outputs.flwr-version-ref }} + # matrix: ${{ steps.versions.outputs.matrix }} + # steps: + # - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + + # - uses: ./.github/actions/bootstrap + # id: bootstrap + + # - id: versions + # run: | + # echo "pip-version=${{ steps.bootstrap.outputs.pip-version }}" >> "$GITHUB_OUTPUT" + # echo "setuptools-version=${{ steps.bootstrap.outputs.setuptools-version }}" >> "$GITHUB_OUTPUT" + # echo "flwr-version-ref=git+${{ github.server_url }}/${{ github.repository }}.git@${{ github.sha }}" >> "$GITHUB_OUTPUT" + # python dev/build-docker-image-matrix.py --flwr-version unstable --simple > matrix.json + # echo "matrix=$(cat matrix.json)" >> $GITHUB_OUTPUT + + build-docker-base-images: + name: Build base images + if: github.repository == 'adap/flower' + uses: ./.github/workflows/_docker-test.yml + # needs: parameters + with: + build-args: | + PIP_VERSION=24.1 + SETUPTOOLS_VERSION=70 + FLWR_VERSION=1.11.0 + secrets: + dockerhub-user: ${{ secrets.DOCKERHUB_USERNAME }} + dockerhub-token: ${{ secrets.DOCKERHUB_TOKEN }} diff --git a/matrix.json b/matrix.json new file mode 100644 index 000000000000..249989d46d31 --- /dev/null +++ b/matrix.json @@ -0,0 +1 @@ +{"base": {"images": [{"distro": {"name": "ubuntu", "version": "22.04"}, "python_version": "3.11", "namespace_repository": "flwr/base", "file_dir": "src/docker/base/ubuntu", "tag": "main-py3.11-ubuntu22.04", "flwr_version": "main"}]}, "binary": {"images": [{"namespace_repository": "flwr/superlink", "file_dir": "src/docker/superlink", "base_image": "main-py3.11-ubuntu22.04", "tags": ""}, {"namespace_repository": "flwr/supernode", "file_dir": "src/docker/supernode", "base_image": "main-py3.11-ubuntu22.04", "tags": ""}, {"namespace_repository": "flwr/serverapp", "file_dir": "src/docker/serverapp", "base_image": "main-py3.11-ubuntu22.04", "tags": ""}, {"namespace_repository": "flwr/superexec", "file_dir": "src/docker/superexec", "base_image": "main-py3.11-ubuntu22.04", "tags": ""}, {"namespace_repository": "flwr/clientapp", "file_dir": "src/docker/clientapp", "base_image": "main-py3.11-ubuntu22.04", "tags": ""}]}}