name: Reusable Container Build Workflow on: workflow_call: inputs: # Which suffix to look for with the Dockerfile. Can be dev or prod build_type: required: true type: string # For example 'alpha', for pre-release or weekly builds tag: required: false type: string # Is this a final release? Then we set this to true, so the 'latest' tag is updated tag_latest: required: false type: boolean # The container image dragonflydb/dragonfly image: required: true type: string # ghcr.io / hub.docker.com / quay.io / you name it registry: required: true type: string # Username used to login to the registry registry_username: required: true type: string # Do we have to fetch release assets? Then set this to true. # Not required for build_type == dev, as they entirely build from source # But for build_type == prod, as they're based on the release assets fetch_release: required: false type: boolean # Which version are we fetching? Should be identical to the release version. # For example v0.12.0 release_version: required: false type: string secrets: # Password used to login to the registry registry_password: required: true # Github Personal Access Token used to fetch assets from a release GH_TOKEN: required: false jobs: container-build: runs-on: ubuntu-latest strategy: matrix: include: - flavor: alpine dockerfile: tools/packaging/Dockerfile.alpine tag_main: false - flavor: ubuntu dockerfile: tools/packaging/Dockerfile.ubuntu tag_main: true steps: - name: checkout uses: actions/checkout@v4 with: fetch-depth: 1 submodules: true - if: inputs.fetch_release name: Fetch release asset uses: dsaltares/fetch-gh-release-asset@1.1.2 with: version: "tags/${{ inputs.release_version }}" regex: true file: "dragonfly-.*\\.tar\\.gz" target: 'releases/' token: ${{ secrets.GH_TOKEN }} - if: inputs.fetch_release name: Extract artifacts run: | echo "Event prerelease ${{ github.event.release.prerelease }}" echo "Input prerelease ${{ github.event.inputs.PRERELEASE }}" ls -l ls -l releases for f in releases/*.tar.gz; do tar xvfz $f -C releases; done rm releases/*.tar.gz - name: Set up QEMU id: qemu uses: docker/setup-qemu-action@v3 with: platforms: arm64,amd64 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Login to GitHub Container Registry uses: docker/login-action@v3 with: registry: ${{ inputs.registry }} username: ${{ inputs.registry_username }} password: ${{ secrets.registry_password }} - name: Docker meta id: metadata uses: docker/metadata-action@v5 with: images: | ${{ inputs.image }} tags: | # will set tag 'latest' for ubuntu build on production push # inputs.tag_latest will be true on when triggered by docker-release.yml # matrix.tag_main will only be true for ubuntu flavor type=raw,value=latest,enable=${{ matrix.tag_main && inputs.tag_latest }} # set a tag like 'alpine' or 'ubuntu', if we're setting 'latest' during this build as well type=raw,value=${{ matrix.flavor }},enable=${{ inputs.tag_latest }} # will set tag like 'alpha' for ubuntu build, if inputs.tag is not empty # but will set the non-flavored tag only, if matrix.tag_main is true type=raw,value=${{ inputs.tag }},enable=${{ inputs.tag != 'false' && matrix.tag_main }} # will set tag like 'alpha-(ubuntu|alpine)', if inputs.tag is not empty type=raw,value=${{ inputs.tag }}-${{ matrix.flavor }},enable=${{ inputs.tag != 'false' }} # will set tag like 'v0.12.0' for ubuntu build, if inputs.release_version is not empty # but will set the non-flavored tag only, if matrix.tag_main is true type=raw,value=${{ inputs.release_version }},enable=${{ matrix.tag_main && inputs.release_version != '' }} # will set tag like 'v0.12.0-(ubuntu|alpine)', if inputs.release_version is not empty type=raw,value=${{ inputs.release_version }}-${{ matrix.flavor }},enable=${{ inputs.release_version != '' }} # build is broken based on platforms as load: true is not supported with multi-platform builds - if: ${{ hashFiles(format('{0}-{1}', matrix.dockerfile, inputs.build_type)) }} name: Build release image for amd64 uses: docker/build-push-action@v5 with: context: . platforms: linux/amd64 build-args: | QEMU_CPU=max,pauth-impdef=on push: false tags: | ${{ steps.metadata.outputs.tags }} labels: ${{ steps.metadata.outputs.labels }} file: ${{ matrix.dockerfile }}-${{ inputs.build_type }} cache-from: type=gha cache-to: type=gha,mode=max # only load AMD64 image for testing load: true - if: ${{ hashFiles(format('{0}-{1}', matrix.dockerfile, inputs.build_type)) }} name: Build release image for arm64 uses: docker/build-push-action@v5 with: context: . platforms: linux/arm64 build-args: | QEMU_CPU=max,pauth-impdef=on push: false tags: | ${{ steps.metadata.outputs.tags }} labels: ${{ steps.metadata.outputs.labels }} file: ${{ matrix.dockerfile }}-${{ inputs.build_type }} cache-from: type=gha cache-to: type=gha,mode=max - if: ${{ hashFiles(format('{0}-{1}', matrix.dockerfile, inputs.build_type)) }} name: Test Docker run run: | # docker run with port-forwarding # install redis-tools sudo apt-get install redis-tools -y tag="${{ steps.metadata.outputs.tags }}" # use the first tag if multiple tags are provided if [[ $(echo "${tag}" | wc -l) -gt 1 ]]; then echo "Multiple tags provided, using the first one" tag=$(echo "${tag}" | head -n 1) fi echo "Testing ${tag}" docker run -d -p 6379:6379 ${tag} sleep 5 # ping with redis-cli and expect PONG if [[ $(redis-cli -h localhost ping) != "PONG" ]]; then echo "Redis ping failed" exit 1 else echo "Redis ping succeeded" exit 0 fi - if: ${{ hashFiles(format('{0}-{1}', matrix.dockerfile, inputs.build_type)) }} name: Push release image uses: docker/build-push-action@v5 with: context: . platforms: linux/amd64,linux/arm64 push: true build-args: | QEMU_CPU=max,pauth-impdef=on tags: | ${{ steps.metadata.outputs.tags }} labels: ${{ steps.metadata.outputs.labels }} file: ${{ matrix.dockerfile }}-${{ inputs.build_type }} cache-from: type=gha cache-to: type=gha,mode=max