onlyoffice/.github/workflows/4testing-build.yml
2026-07-21 16:50:49 +05:00

371 lines
12 KiB
YAML

### 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 <<EOF
{
"status": "${{ job.status }}"
}
EOF
- name: Upload build result artifact
if: always()
uses: actions/upload-artifact@v4
with:
name: build-result-${{ matrix.edition }}-${{ matrix.platform }}
path: build-result
make-images:
runs-on: ubuntu-latest
needs: [prepare,build]
if: always()
strategy:
fail-fast: false
matrix:
image: ["documentserver"]
edition: ${{ fromJSON(needs.prepare.outputs.editions) }}
steps:
- name: Download all build results
uses: actions/download-artifact@v4
with:
path: build-results
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
- name: "Make images documentserver"
env:
EDITION: ${{ matrix.edition }}
BUILD_NUMBER: ${{ github.event.inputs.build }}
BRANCH_NAME: ${{ github.ref_name }}
DOCKER_PAT_USERNAME: ${{ secrets.DOCKERHUB_USERNAME_PAT }}
DOCKER_PAT_ACCESS_TOKEN: ${{ secrets.DOCKERHUB_TOKEN_PAT }}
run: |
case "${EDITION}" in
community)
PRODUCT_EDITION=""
;;
enterprise)
PRODUCT_EDITION="-ee"
;;
developer)
PRODUCT_EDITION="-de"
;;
esac
AMD64_STATUS=$(cat ./build-results/build-result-${{ matrix.edition }}-amd64/info.json | jq -r .status)
ARM64_STATUS=$(cat ./build-results/build-result-${{ matrix.edition }}-arm64/info.json | jq -r .status)
echo "ARM64 status: ${ARM64_STATUS}"
echo "AMD64 status: ${AMD64_STATUS}"
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 TAG=${PRODUCT_VERSION}.${BUILD_NUMBER}
FROM_TAGS=()
PUSH_TAGS=()
check_image() {
local img="$1"
local timeout=120
local interval=20
local elapsed=0
echo "Checking for image: $img"
while (( elapsed < timeout )); do
if docker manifest inspect "$img" > /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