Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions .github/actions/docker-manifest-create-push/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: "Docker Manifest Create & Push"
description: "Create OCI manifest list for multi-arch images and push to registry"
author: "babelcloud"
inputs:
manifest-list:
description: "Final manifest list name (e.g. ghcr.io/owner/repo:tag)"
required: true
manifests:
description: "Comma separated list of image references to include"
required: true
post-clean:
description: "Remove manifest list locally after push"
required: false
default: "false"
runs:
using: "composite"
steps:
- shell: bash
run: |
set -euo pipefail
MANIFEST_LIST="${{ inputs.manifest-list }}"
MANIFESTS="${{ inputs.manifests }}"
IFS=',' read -ra IMAGES <<< "$MANIFESTS"
echo "📦 Creating manifest list $MANIFEST_LIST with: ${IMAGES[*]}"
docker manifest create "$MANIFEST_LIST" "${IMAGES[@]}"
docker manifest push "$MANIFEST_LIST"
if [[ "${{ inputs.post-clean }}" == "true" ]]; then
docker manifest rm "$MANIFEST_LIST" || true
fi
145 changes: 145 additions & 0 deletions .github/workflows/build-multiarch.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
name: Multi-Arch Appium Image Builder

on:
workflow_dispatch:
inputs:
tag:
description: "Image tag (default: commit SHA)"
type: string
required: false
default: ""
push:
description: "Push image to registry"
type: boolean
required: false
default: false
push:
branches: ["**"]
tags: ["*"]
pull_request:

jobs:
prepare:
runs-on: ubuntu-24.04
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
tag: ${{ steps.set-tag.outputs.tag }}
is_main: ${{ steps.set-tag.outputs.is_main }}
steps:
- uses: actions/checkout@v4

- id: set-tag
name: Compute image tag
run: |
TAG_INPUT='${{ github.event.inputs.tag }}'
if [[ -n "$TAG_INPUT" ]]; then
TAG="$TAG_INPUT"
elif [[ "${{ github.ref }}" == refs/tags/* ]]; then
TAG="${GITHUB_REF##*/}"
else
TAG="$(git rev-parse --short HEAD)"
fi
echo "tag=$TAG" | tee -a "$GITHUB_OUTPUT"

# detect main branch
if [[ "${{ github.ref }}" == "refs/heads/main" ]]; then
echo "is_main=true" | tee -a "$GITHUB_OUTPUT"
fi

- id: set-matrix
name: Generate build matrix
run: |
TAG='${{ steps.set-tag.outputs.tag }}'
MATRIX=$(jq -nc --arg tag "$TAG" '{include:[{"arch":"amd64","platform":"linux/amd64","suffix":"-amd64","tag":$tag},{"arch":"arm64","platform":"linux/arm64","suffix":"-arm64","tag":$tag}]}')
echo "matrix=$MATRIX" | tee -a "$GITHUB_OUTPUT"

build:
needs: prepare
name: Build (${{ matrix.arch }})
runs-on: ${{ matrix.arch == 'arm64' && 'ubuntu-24.04-arm' || 'ubuntu-24.04' }}
strategy:
fail-fast: true
matrix: ${{ fromJson(needs.prepare.outputs.matrix) }}
permissions:
contents: read
packages: write
env:
REGISTRY: ghcr.io
IMAGE_NAME: babelcloud/appium
IS_MAIN: ${{ needs.prepare.outputs.is_main }}
steps:
- uses: actions/checkout@v4

- name: Set up Buildx
uses: docker/setup-buildx-action@v3

- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ secrets.GH_TOKEN_USER }}
password: ${{ secrets.GH_TOKEN }}

- id: tags
name: Generate architecture-specific tags
run: |
IMAGE="${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}"
TAGS="$IMAGE:${{ matrix.tag }}${{ matrix.suffix }}"
if [[ "$IS_MAIN" == "true" ]]; then
TAGS="$TAGS,$IMAGE:latest${{ matrix.suffix }}"
fi
echo "tags=$TAGS" | tee -a "$GITHUB_OUTPUT"

- name: Build and push
uses: docker/build-push-action@v5
with:
context: ./Appium
file: ./Appium/Dockerfile
platforms: ${{ matrix.platform }}
tags: ${{ steps.tags.outputs.tags }}
push: true
build-args: |
TARGETARCH=${{ matrix.arch }}
provenance: false
cache-from: type=registry,ref=ghcr.io/babelcloud/appium:buildcache-${{ matrix.arch }}
cache-to: type=registry,ref=ghcr.io/babelcloud/appium:buildcache-${{ matrix.arch }},mode=max
labels: |
org.opencontainers.image.source=https://github.com/babelcloud/appium
annotations: |
org.opencontainers.image.source=https://github.com/babelcloud/appium

manifest:
needs: [prepare, build]
runs-on: ubuntu-24.04
permissions:
contents: read
packages: write
env:
REGISTRY: ghcr.io
IMAGE_NAME: babelcloud/appium
IS_MAIN: ${{ needs.prepare.outputs.is_main }}
TAG: ${{ needs.prepare.outputs.tag }}
steps:
- uses: actions/checkout@v4

- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ secrets.GH_TOKEN_USER }}
password: ${{ secrets.GH_TOKEN }}

- name: Create & Push Manifest (SHA)
uses: ./.github/actions/docker-manifest-create-push
with:
manifest-list: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ env.TAG }}
manifests: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ env.TAG }}-amd64,${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ env.TAG }}-arm64
post-clean: true

- name: Create & Push Manifest (latest)
if: ${{ env.IS_MAIN == 'true' }}
uses: ./.github/actions/docker-manifest-create-push
with:
manifest-list: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
manifests: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest-amd64,${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest-arm64
post-clean: true
3 changes: 2 additions & 1 deletion Appium/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ RUN apt-get -qqy update && \
#===============
# Set JAVA_HOME
#===============
ENV JAVA_HOME="/usr/lib/jvm/java-17-openjdk-amd64" \
ARG TARGETARCH=amd64
ENV JAVA_HOME="/usr/lib/jvm/java-17-openjdk-${TARGETARCH}" \
PATH=$PATH:$JAVA_HOME/bin

#===============================
Expand Down
27 changes: 27 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
.PHONY: help build buildx
.DEFAULT_GOAL := help

BASE_TAG := main
TAG := latest
NO_CACHE := false
PROGRESS := auto

help: ## Print help message
@printf "\nUsage: make <command>\n"
@grep -F -h "##" $(MAKEFILE_LIST) | grep -F -v grep -F | sed -e 's/\\$$//' | awk 'BEGIN {FS = ":*[[:space:]]*##"}; \
{ \
if($$2 == "") \
pass; \
else if($$0 ~ /^#/) \
printf "\n%s\n", $$2; \
else if($$1 == "") \
printf " %-28s%s\n", "", $$2; \
else \
printf " \033[34m%-28s\033[0m %s\n", $$1, $$2; \
}'

build: ## Build image locally
@bash app.sh build $(TAG)

buildx: ## Build image for multiple architectures and push to registry
@bash app.sh buildx $(TAG)
19 changes: 17 additions & 2 deletions app.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/bin/bash

IMAGE="appium/appium"
IMAGE="ghcr.io/babelcloud/appium"

if [ -z "$1" ]; then
read -p "Task (test|build|push) : " TASK
Expand All @@ -17,7 +17,19 @@ fi
function build() {
echo "Build docker image with version \"${VER}\""
docker build --no-cache -t ${IMAGE}:${VER} -f Appium/Dockerfile Appium
docker images
docker images ${IMAGE}:${VER}
}

function buildx() {
echo "Build docker image with version \"${VER}\""
docker buildx build \
--platform linux/amd64,linux/arm64 \
--push \
--annotation org.opencontainers.image.source=https://github.com/babelcloud/appium \
-t ${IMAGE}:${VER} \
-f Appium/Dockerfile \
Appium
docker images ${IMAGE}:${VER}
}

function test() {
Expand All @@ -36,6 +48,9 @@ case $TASK in
build)
build
;;
buildx)
buildx
;;
test)
test
;;
Expand Down