From 87d8dcff6f103b8663b6ff920ca12af1cc4d3852 Mon Sep 17 00:00:00 2001 From: Dominique Lasserre Date: Sat, 4 Jan 2025 01:24:37 +0100 Subject: [PATCH] workflow: docker-build upload to DockerHub (#318) * workflow: docker-build upload to DockerHub - Upload on release, tag, push to main. - Build on pr to main (amd64 only). * docker: - Update documentation. - Temporarily set akkudoktor/eos:main in compose.yml (with releases/tags it should be replaced by latest again) --- .env | 2 +- .github/workflows/docker-build.yml | 161 ++++++++++++++++++++++------- Dockerfile | 2 +- README.md | 4 +- 4 files changed, 126 insertions(+), 43 deletions(-) diff --git a/.env b/.env index 55fd2f0e..5b21faf4 100644 --- a/.env +++ b/.env @@ -1,4 +1,4 @@ -EOS_VERSION=latest +EOS_VERSION=main EOS_PORT=8503 PYTHON_VERSION=3.12.6 diff --git a/.github/workflows/docker-build.yml b/.github/workflows/docker-build.yml index fac6f436..ff588bc3 100644 --- a/.github/workflows/docker-build.yml +++ b/.github/workflows/docker-build.yml @@ -1,27 +1,53 @@ name: docker-build on: - release: - types: [published] + # pipeline runs per trigger condition, so release trigger not required as tag is sufficient + #release: + # types: [published] + push: + branches: + - 'main' + - 'feature/config-overhaul' + tags: + - 'v*' + pull_request: + branches: + - 'main' + - 'feature/config-overhaul' env: - REGISTRY: ghcr.io - + DOCKERHUB_REPO: akkudoktor/eos + GHCR_REPO: ghcr.io/akkudoktor-eos/eos + EOS_LICENSE: Apache-2.0 + +# From https://docs.docker.com/build/ci/github-actions/multi-platform/ +# Changes: +# - adjusted rw permissions +# - manually set undetected license (label+annotation) +# - set description for index manifest +# - add attestation +# - conditionally don't push on pr +# - on pr just use amd64 platform jobs: - variables: + # Build platform matrix excludes. if-conditional with matrix on job level is not + # supported, see https://github.com/actions/runner/issues/1985 + platform-excludes: + runs-on: ubuntu-latest outputs: - repository: ${{ steps.var.outputs.repository}} - runs-on: "ubuntu-latest" + excludes: ${{ steps.excludes.outputs.matrix }} steps: - - name: Setting global variables - uses: actions/github-script@v6 - id: var - with: - script: | - core.setOutput('repository', '${{ github.repository }}'.toLowerCase()); + - id: excludes + run: | + if ${{ github.event_name == 'pull_request' }}; then + echo 'matrix=[ + {"platform": "linux/arm64"} + ]' | tr -d '[:space:]' >> $GITHUB_OUTPUT + else + echo 'matrix=[]' >> $GITHUB_OUTPUT + fi + build: - needs: - - variables + needs: platform-excludes runs-on: ubuntu-latest permissions: contents: read @@ -34,6 +60,7 @@ jobs: platform: - linux/amd64 - linux/arm64 + exclude: ${{ fromJSON(needs.platform-excludes.outputs.excludes) }} steps: - name: Prepare run: | @@ -44,35 +71,64 @@ jobs: id: meta uses: docker/metadata-action@v5 with: - images: "${{ env.REGISTRY }}/${{ needs.variables.outputs.repository }}" - - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 + images: | + ${{ env.DOCKERHUB_REPO }} + ${{ env.GHCR_REPO }} + labels: | + org.opencontainers.image.licenses=${{ env.EOS_LICENSE }} + annotations: | + org.opencontainers.image.licenses=${{ env.EOS_LICENSE }} + env: + DOCKER_METADATA_ANNOTATIONS_LEVELS: manifest,index + + # Prepare to extract description so it can be manually set for index manifest (group of platform manifests) + - name: Prepare description + id: get_description + run: | + echo "EOS_REPO_DESCRIPTION=$(jq -cr '.labels."org.opencontainers.image.description"' <<< "$DOCKER_METADATA_OUTPUT_JSON")" >> $GITHUB_ENV - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_PASSWORD }} - - name: Login to GitHub + - name: Login to GHCR uses: docker/login-action@v3 with: - registry: ${{ env.REGISTRY }} + registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + - name: Build and push by digest id: build uses: docker/build-push-action@v6 with: platforms: ${{ matrix.platform }} labels: ${{ steps.meta.outputs.labels }} - outputs: type=image,name=${{ env.REGISTRY }}/${{ needs.variables.outputs.repository }},push-by-digest=true,name-canonical=true,push=true + annotations: ${{ steps.meta.outputs.annotations }} + outputs: type=image,"name=${{ env.DOCKERHUB_REPO }},${{ env.GHCR_REPO }}",push-by-digest=true,name-canonical=true,"push=${{ github.event_name != 'pull_request' }}","annotation-index.org.opencontainers.image.description=${{ env.EOS_REPO_DESCRIPTION }}" + #push: ${{ github.event_name != 'pull_request' }} - - name: Generate artifact attestation - uses: actions/attest-build-provenance@v1 + - name: Generate artifact attestation DockerHub + uses: actions/attest-build-provenance@v2 with: - subject-name: "${{ env.REGISTRY }}/${{ needs.variables.outputs.repository }}" + subject-name: docker.io/${{ env.DOCKERHUB_REPO }} subject-digest: ${{ steps.build.outputs.digest }} - push-to-registry: true + push-to-registry: ${{ github.event_name != 'pull_request' }} + + - name: Generate artifact attestation GitHub + uses: actions/attest-build-provenance@v2 + with: + subject-name: ${{ env.GHCR_REPO }} + subject-digest: ${{ steps.build.outputs.digest }} + push-to-registry: ${{ github.event_name != 'pull_request' }} - name: Export digest run: | @@ -90,9 +146,14 @@ jobs: merge: runs-on: ubuntu-latest + permissions: + contents: read + packages: write + id-token: write needs: - build - - variables + # skip for pull requests + if: ${{ github.event_name != 'pull_request' }} steps: - name: Download digests uses: actions/download-artifact@v4 @@ -101,6 +162,19 @@ jobs: pattern: digests-* merge-multiple: true + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_PASSWORD }} + + - name: Login to GHCR + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 @@ -108,21 +182,30 @@ jobs: id: meta uses: docker/metadata-action@v5 with: - images: "${{ env.REGISTRY }}/${{ needs.variables.outputs.repository }}" - - - name: Login to GitHub - uses: docker/login-action@v3 - with: - registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} + images: | + ${{ env.DOCKERHUB_REPO }} + ${{ env.GHCR_REPO }} + tags: | + type=ref,event=branch + type=ref,event=pr + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + labels: | + org.opencontainers.image.licenses=${{ env.EOS_LICENSE }} + annotations: | + org.opencontainers.image.licenses=${{ env.EOS_LICENSE }} + env: + DOCKER_METADATA_ANNOTATIONS_LEVELS: manifest,index - name: Create manifest list and push working-directory: /tmp/digests run: | docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ - $(printf '${{ env.REGISTRY }}/${{ needs.variables.outputs.repository }}@sha256:%s ' *) + $(printf '${{ env.DOCKERHUB_REPO }}@sha256:%s ' *) + docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ + $(printf '${{ env.GHCR_REPO }}@sha256:%s ' *) - name: Inspect image run: | - docker buildx imagetools inspect ${{ env.REGISTRY }}/${{ needs.variables.outputs.repository }}:${{ steps.meta.outputs.version }} + docker buildx imagetools inspect ${{ env.DOCKERHUB_REPO }}:${{ steps.meta.outputs.version }} + docker buildx imagetools inspect ${{ env.GHCR_REPO }}:${{ steps.meta.outputs.version }} diff --git a/Dockerfile b/Dockerfile index 28e55dba..f9e46f2b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -35,6 +35,6 @@ ENTRYPOINT [] EXPOSE 8503 -CMD ["python", "-m", "akkudoktoreos.server.fastapi_server"] +CMD ["python", "-m", "akkudoktoreos.server.eos"] VOLUME ["${MPLCONFIGDIR}", "${EOS_CACHE_DIR}", "${EOS_OUTPUT_DIR}", "${EOS_CONFIG_DIR}"] diff --git a/README.md b/README.md index 58f4c31b..cf77a83f 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ See [CONTRIBUTING.md](CONTRIBUTING.md). ## Installation -The project requires Python 3.10 or newer. Currently there are no official packages or images published. +The project requires Python 3.10 or newer. Official docker images can be found at [akkudoktor/eos](https://hub.docker.com/r/akkudoktor/eos). Following sections describe how to locally start the EOS server on `http://localhost:8503`. @@ -49,7 +49,7 @@ Windows: ### Docker ```bash -docker compose up --build +docker compose up ``` ## Configuration