### This workflow setup instance then build and push images ### name: 4testing multiarch-build run-name: >- Build #${{ inputs.build }} [ ${{ inputs.amd64 && 'AMD64' || '-' }} ${{ inputs.arm64 && 'ARM64' || '-' }} ] [ ${{ inputs.community && 'CE' || '-' }} ${{ inputs.developer && 'DE' || '-' }} ${{ inputs.enterprise && 'EE' || '-' }} ] on: workflow_dispatch: inputs: build: description: 'Build number (ex. 45)' type: string required: true amd64: type: boolean description: 'Build AMD64' default: true arm64: type: boolean description: 'Build ARM64' default: true community: type: boolean description: 'Build Community Edition' default: true enterprise: type: boolean description: 'Build Enterprise Edition' default: true developer: type: boolean description: 'Build Developer Edition' default: true env: COMPANY_NAME: "onlyoffice" PRODUCT_NAME: "documentserver" jobs: prepare: runs-on: ubuntu-latest steps: - id: matrix env: BRANCH_NAME: ${{ github.ref_name }} AMD64: ${{ github.event.inputs.amd64 }} ARM64: ${{ github.event.inputs.arm64 }} COMMUNITY: ${{ github.event.inputs.community }} ENTERPRISE: ${{ github.event.inputs.enterprise }} DEVELOPER: ${{ github.event.inputs.developer }} run: | set -ex if ! [[ "$BRANCH_NAME" == develop || "$BRANCH_NAME" =~ hotfix || "$BRANCH_NAME" =~ release ]]; then echo "Wrong branch." exit 1 fi [ "${AMD64}" = true ] && PLATFORMS+=("amd64") [ "${ARM64}" = true ] && PLATFORMS+=("arm64") if [ -z ${PLATFORMS} ]; then echo "None of the platforms are selected." exit 1 fi [ "${COMMUNITY}" = true ] && EDITIONS+=("community") [ "${ENTERPRISE}" = true ] && EDITIONS+=("enterprise") [ "${DEVELOPER}" = true ] && EDITIONS+=("developer") if [ -z ${EDITIONS} ]; then echo "None of the editions are selected." exit 1 fi echo "editions=$(jq -n -c --arg s "${EDITIONS[*]}" '($s|split(" "))')" >> $GITHUB_OUTPUT echo "platforms=$(jq -c -n '$ARGS.positional' --args "${PLATFORMS[@]}")" >> $GITHUB_OUTPUT outputs: editions: ${{ steps.matrix.outputs.editions }} platforms: ${{ steps.matrix.outputs.platforms }} build: name: "Build ${{ matrix.image }}-${{ matrix.edition }}:${{ matrix.platform }}" runs-on: ${{ (matrix.platform == 'arm64') && 'ubuntu-24.04-arm' || 'ubuntu-latest' }} needs: prepare strategy: fail-fast: false matrix: image: ["documentserver"] edition: ${{ fromJSON(needs.prepare.outputs.editions) }} platform: ${{ fromJSON(needs.prepare.outputs.platforms) }} steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up Docker Buildx id: buildx uses: docker/setup-buildx-action@v3 - name: Login to Docker Hub uses: docker/login-action@v3 with: username: ${{ secrets.DOCKER_HUB_USERNAME }} password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }} - name: Prepare fonts cache id: fonts uses: actions/cache@v4 with: path: fonts key: fonts-${{ runner.os }}-v1 - name: Install fonts if not cached if: steps.fonts.outputs.cache-hit != 'true' run: | sudo apt-get update echo "ttf-mscorefonts-installer msttcorefonts/accepted-mscorefonts-eula select true" | sudo debconf-set-selections sudo apt-get install -y ttf-mscorefonts-installer mkdir -p fonts/msttcorefonts cp -a /usr/share/fonts/truetype/msttcorefonts/* fonts/msttcorefonts/ - name: Build 4testing id: build-ds env: BRANCH_NAME: ${{ github.ref_name }} PLATFORM: linux/${{ matrix.platform }} BUILD_NUMBER: ${{ github.event.inputs.build }} EDITION: ${{ matrix.edition }} IMAGE: ${{ matrix.image }} PACKAGE_BASEURL: ${{ secrets.REPO_BASEURL }} run: | set -eux ### ==>> At this step build variable declaration ### case "${EDITION}" in community) PRODUCT_EDITION="" ;; enterprise) PRODUCT_EDITION="-ee" ;; developer) PRODUCT_EDITION="-de" ;; esac if [ "$BRANCH_NAME" = develop ]; then BUILD_CHANNEL=nightly PRODUCT_VERSION=99.99.99 elif [[ "$BRANCH_NAME" =~ hotfix || "$BRANCH_NAME" =~ release ]]; then BUILD_CHANNEL=test PRODUCT_VERSION=${BRANCH_NAME#*/v} fi export PRODUCT_EDITION export PACKAGE_VERSION=${PRODUCT_VERSION}-${BUILD_NUMBER} export BUILD_CHANNEL export DOCKERFILE=Dockerfile export PREFIX_NAME=4testing- export TAG=${PRODUCT_VERSION}.${BUILD_NUMBER}-${{ matrix.platform }} ### ==>> Build and push images at this step ### docker buildx bake --sbom=true --provenance=mode=max -f docker-bake.hcl "${IMAGE}" --push echo "DONE: Build success" ### Set output for Zap scanner ### NOTE: Output will be used only in release/hotfix branches echo "version=${TAG}" >> "$GITHUB_OUTPUT" echo "branch=${BRANCH_NAME}" >> "$GITHUB_OUTPUT" shell: bash # Run scanner only when edition is community # and branch hit release/ or hotfix/ - name: Trigger zap manualy if: >- matrix.edition == 'community' && matrix.platform == 'amd64' && (startsWith(steps.build-ds.outputs.branch, 'release/') || startsWith(steps.build-ds.outputs.branch, 'hotfix/')) env: VERSION: ${{ steps.build-ds.outputs.version }} BRANCH: ${{ steps.build-ds.outputs.branch }} GITHUB_TOKEN: ${{ secrets.TOKEN }} REPO: ${{ github.repository }} run: | gh workflow run zap-ds.yaml \ --repo "${REPO}" \ -f branch="${BRANCH}" \ -f version="${VERSION}" shell: bash # Run Trivy scans for community and developer images from release/hotfix branches. - name: Trigger Trivy scan if: >- (matrix.edition == 'community' || matrix.edition == 'developer') && matrix.platform == 'amd64' && (startsWith(steps.build-ds.outputs.branch, 'release/') || startsWith(steps.build-ds.outputs.branch, 'hotfix/')) env: VERSION: ${{ steps.build-ds.outputs.version }} EDITION: ${{ matrix.edition }} BRANCH: ${{ steps.build-ds.outputs.branch }} GITHUB_TOKEN: ${{ secrets.TOKEN }} REPO: ${{ github.repository }} run: | gh workflow run trivy-ds.yml \ --repo "${REPO}" \ --ref "${BRANCH}" \ -f edition="${EDITION}" \ -f version="${VERSION}" shell: bash - name: Save build result to file if: always() run: | mkdir -p build-result cat > build-result/info.json < /dev/null 2>&1; then echo "Found image: $img" FROM_TAGS+=( "$img" ) return 0 fi echo "Image not found yet, retrying in ${interval}s..." sleep $interval elapsed=$(( elapsed + interval )) done echo "ERROR: Image not found after ${timeout}s: $img" return 1 } if [[ "${AMD64_STATUS}" == "success" ]]; then check_image "${COMPANY_NAME}/4testing-${PRODUCT_NAME}${PRODUCT_EDITION}:${TAG}-amd64" fi if [[ "${ARM64_STATUS}" == "success" ]]; then check_image "${COMPANY_NAME}/4testing-${PRODUCT_NAME}${PRODUCT_EDITION}:${TAG}-arm64" fi PUSH_TAGS=( -t "${COMPANY_NAME}/4testing-${PRODUCT_NAME}${PRODUCT_EDITION}:${TAG}" ) if [[ "${BUILD_CHANNEL}" == "nightly" ]]; then PUSH_TAGS+=( -t "${COMPANY_NAME}/4testing-${PRODUCT_NAME}${PRODUCT_EDITION}:latest" ) fi docker buildx imagetools create "${PUSH_TAGS[@]}" "${FROM_TAGS[@]}" ### ==>> Cleanup platform-specific tags ### REPO="${COMPANY_NAME}/4testing-${PRODUCT_NAME}${PRODUCT_EDITION}" echo "Getting Docker Hub token..." TOKEN=$(curl -s -X POST "https://hub.docker.com/v2/users/login" \ -H "Content-Type: application/json" \ -d "{\"username\": \"${DOCKER_PAT_USERNAME}\", \"password\": \"${DOCKER_PAT_ACCESS_TOKEN}\"}" \ | jq -r .token) if [ -z "${TOKEN}" ] || [ "${TOKEN}" = "null" ]; then echo "ERROR: Failed to get Docker Hub token" exit 1 fi echo "Docker Hub token obtained successfully" for IMG in "${FROM_TAGS[@]}"; do PLATFORM_TAG="${IMG##*:}" echo "Deleting tag: ${IMG}" HTTP_STATUS=$(curl -s -o /tmp/delete_response.json -w "%{http_code}" -X DELETE \ -H "Authorization: JWT ${TOKEN}" \ "https://hub.docker.com/v2/repositories/${REPO}/tags/${PLATFORM_TAG}/") echo "Response HTTP status: ${HTTP_STATUS}" echo "Response body: $(cat /tmp/delete_response.json)" if [ "${HTTP_STATUS}" = "204" ]; then echo "Successfully deleted: ${IMG}" else echo "WARNING: Unexpected status ${HTTP_STATUS} when deleting ${IMG}" fi done