Feat: add actions for secure rebuild ds images

This commit is contained in:
danilapog 2026-07-21 13:16:30 +00:00 committed by Alexey Golubev
parent 1a21bc0154
commit 3cdec1156e
7 changed files with 1338 additions and 321 deletions

View file

@ -0,0 +1,218 @@
#!/usr/bin/env bash
# Usage:
# update-secure-rebuild-config.sh \
# <source_tag> \
# <release_tag> \
# <release_number> \
# <editions_json>
set -euo pipefail
if [ "$#" -ne 4 ]; then
echo "Usage: $0 <source_tag> <release_tag> <release_number> <editions_json>" >&2
exit 2
fi
SOURCE_TAG="$1"
RELEASE_TAG="$2"
RELEASE_NUMBER="$3"
EDITIONS_JSON="$4"
CONFIG="${CONFIG:-.github/secure-rebuild.json}"
if ! [[ "${RELEASE_NUMBER}" =~ ^[1-9][0-9]*$ ]]; then
echo "Error: release_number must be a positive integer" >&2
exit 2
fi
if ! [[ "${RELEASE_TAG}" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "Error: release_tag must have format X.Y.Z.N" >&2
exit 2
fi
if [ ! -f "${CONFIG}" ]; then
echo "Error: config not found: ${CONFIG}" >&2
exit 1
fi
# Expected format:
# {
# "-ee": { "latest": true },
# "-de": { "latest": true }
# }
if ! jq -e '
type == "object"
and all(
.[];
type == "object"
and has("latest")
and (.latest | type == "boolean")
)
' >/dev/null 2>&1 <<< "${EDITIONS_JSON}"; then
echo 'Error: editions_json must look like {"-ee":{"latest":true}}' >&2
exit 2
fi
if ! jq -e '
type == "object"
and (.releases | type == "object")
' "${CONFIG}" >/dev/null 2>&1; then
echo "Error: ${CONFIG} must contain a releases object" >&2
exit 1
fi
# For release_tag 9.6.1.1:
# MINOR = 9.6.1
# SHORTER = 9.6
# MAJOR = 9
MINOR="${RELEASE_TAG%.*}"
SHORTER="${MINOR%.*}"
MAJOR="${RELEASE_TAG%%.*}"
MAJOR_KEY="v${MAJOR}"
TMP_FILE="$(mktemp "${CONFIG}.tmp.XXXXXX")"
cleanup() {
rm -f "${TMP_FILE}"
}
trap cleanup EXIT
jq \
--arg key "${MAJOR_KEY}" \
--arg src "${SOURCE_TAG}" \
--arg rel "${RELEASE_TAG}" \
--arg s1 "${MINOR}" \
--arg s2 "${SHORTER}" \
--argjson release_number "${RELEASE_NUMBER}" \
--argjson eds "${EDITIONS_JSON}" \
'
# Strips latest only for editions present in the new $eds.
# Uses exact key comparison via index() so that empty key ""
# does not match "-ee" or "-de".
def strip_latest_for_editions($eds):
($eds | keys) as $edition_keys
|
map(
.editions |= with_entries(
.key as $edition_key
|
if ($edition_keys | index($edition_key)) != null
then .value.latest = false
else .
end
)
);
# Removes a short tag by exact match.
def remove_exact_short_tag($tag):
map(
.short_tags |= map(
select(. != $tag)
)
);
# For subsequent rebuild releases, removes short tags
# from the previous record of the same patch version.
# Example: when adding 9.6.1.2, removes "9.6.1" and "9.6" from 9.6.1.1.
def remove_patch_short_tags($s1; $s2):
map(
if (.short_tags | index($s1)) != null
then
.short_tags |= map(
select(. != $s1 and . != $s2)
)
else
.
end
);
def new_record($src; $rel; $s1; $s2; $eds):
{
source_tag: $src,
release_tag: $rel,
short_tags: [$s1, $s2],
editions: $eds
};
# Remember whether the major branch existed before changes.
(.releases | has($key)) as $major_existed
|
# Idempotency guard: remove any existing record with the same release_tag
# to avoid duplicates on re-run.
.releases |= with_entries(
.value |= map(
select(.release_tag != $rel)
)
)
|
if $major_existed then
# Major branch already exists (e.g. v9).
.releases[$key] = (
.releases[$key]
# First release of a new minor (release_number == 1):
# remove the short minor tag (e.g. "9.6") from the previous record.
# Subsequent rebuild release:
# remove both "9.6.1" and "9.6" from the previous record
# of the same patch version.
|
if $release_number == 1
then remove_exact_short_tag($s2)
else remove_patch_short_tags($s1; $s2)
end
# Strip latest only for editions included in the new release.
|
strip_latest_for_editions($eds)
)
|
# Prepend the new release record.
.releases[$key] = [
new_record($src; $rel; $s1; $s2; $eds)
] + .releases[$key]
else
# A new major branch is being created (e.g. first v10).
# Strip latest for the corresponding editions across all existing major branches.
.releases |= with_entries(
.value |= strip_latest_for_editions($eds)
)
|
.releases[$key] = [
new_record($src; $rel; $s1; $s2; $eds)
]
|
# Keep only the two most recent major branches.
.releases = (
.releases
| to_entries
| sort_by(
.key
| ltrimstr("v")
| tonumber
)
| reverse
| .[0:2]
| from_entries
)
end
' "${CONFIG}" > "${TMP_FILE}"
# Validate that the result is valid JSON.
jq -e . "${TMP_FILE}" >/dev/null
mv "${TMP_FILE}" "${CONFIG}"
trap - EXIT
echo "Updated ${CONFIG}:"
cat "${CONFIG}"

195
.github/secure-rebuild.json vendored Normal file
View file

@ -0,0 +1,195 @@
{
"releases": {
"v9": [
{
"source_tag": "9.4.1.15",
"release_tag": "9.4.1.2",
"short_tags": [
"9.4.1",
"9.4"
],
"editions": {
"-ee": {
"latest": true
},
"-de": {
"latest": true
}
}
},
{
"source_tag": "9.4.1.15",
"release_tag": "9.4.1.1",
"short_tags": [],
"editions": {
"-ee": {
"latest": false
},
"-de": {
"latest": false
}
}
},
{
"source_tag": "9.4.0.129",
"release_tag": "9.4.0.2",
"short_tags": [
"9.4.0"
],
"editions": {
"-ee": {
"latest": false
},
"-de": {
"latest": false
}
}
},
{
"source_tag": "9.4.0.129",
"release_tag": "9.4.0.1",
"short_tags": [],
"editions": {
"": {
"latest": true
},
"-ee": {
"latest": false
},
"-de": {
"latest": false
}
}
},
{
"source_tag": "9.3.1.10",
"release_tag": "9.3.1.2",
"short_tags": [
"9.3.1",
"9.3"
],
"editions": {
"": {
"latest": false
},
"-ee": {
"latest": false
},
"-de": {
"latest": false
}
}
},
{
"source_tag": "9.3.1.8",
"release_tag": "9.3.1.1",
"short_tags": [],
"editions": {
"": {
"latest": false
},
"-ee": {
"latest": false
},
"-de": {
"latest": false
}
}
},
{
"source_tag": "9.3.0.138",
"release_tag": "9.3.0.1",
"short_tags": [
"9.3.0"
],
"editions": {
"": {
"latest": false
},
"-ee": {
"latest": false
},
"-de": {
"latest": false
}
}
},
{
"source_tag": "9.2.1.8",
"release_tag": "9.2.1.1",
"short_tags": [
"9.2.1",
"9.2"
],
"editions": {
"": {
"latest": false
},
"-ee": {
"latest": false
},
"-de": {
"latest": false
}
}
},
{
"source_tag": "9.2.0.98",
"release_tag": "9.2.0.1",
"short_tags": [
"9.2.0"
],
"editions": {
"": {
"latest": false
},
"-ee": {
"latest": false
},
"-de": {
"latest": false
}
}
},
{
"source_tag": "9.1.0.168",
"release_tag": "9.1.0.1",
"short_tags": [
"9.1.0",
"9.1"
],
"editions": {
"": {
"latest": false
},
"-ee": {
"latest": false
},
"-de": {
"latest": false
}
}
},
{
"source_tag": "9.0.4.50",
"release_tag": "9.0.4.1",
"short_tags": [
"9.0.4",
"9.0"
],
"editions": {
"": {
"latest": false
},
"-ee": {
"latest": false
},
"-de": {
"latest": false
}
}
}
]
}
}

View file

@ -1,224 +0,0 @@
---
name: Rebuild Docker-Documentserver
run-name: >
Rebuild DocumentServer with secure updates for repo: ${{ github.event.inputs.repo }}
on:
workflow_dispatch:
inputs:
repo:
type: choice
description: Please, choose upload repo..
options:
- '4test'
- 'stable'
permissions:
# All other permissions are set to none
contents: read
# Technically read access while waiting for images should be more than enough. However,
# there is a bug in GitHub Actions/Packages and in case private repositories are used, you get a permission
# denied error when attempting to just pull private image, changing the token permission to write solves the
# issue. This is not dangerous, because if it is for "ONLYOFFICE/Docker-DocumentServer", only maintainers can use ds-rebuild.yaml
# If it is for a fork, then the token is read-only anyway.
packages: read
env:
COMPANY_NAME: "onlyoffice"
PRODUCT_NAME: "documentserver"
REGISTRY_URL: "https://hub.docker.com/v2/repositories"
jobs:
rebuild-info:
name: "Rebuild-info"
runs-on: "ubuntu-22.04"
env:
REPO_INPUTS: ${{ github.event.inputs.repo }}
EVENT: ${{ github.event_name }}
outputs:
stable-versions: ${{ steps.selective-checks.outputs.stable-versions }}
ucs-versions: ${{ steps.selective-checks.outputs.ucs-versions }}
minor-tags: ${{ steps.selective-checks.outputs.minor-tags }}
ucs-rebuild-condition: ${{ steps.selective-checks.outputs.ucs-rebuild-condition }}
prefix-name: ${{ steps.selective-checks.outputs.prefix-name }}
repo: ${{ steps.selective-checks.outputs.repo }}
steps:
- name: Selective checks
id: selective-checks
run: |
set -e
REPO=${REPO_INPUTS:-"4test"}
if [ "${REPO}" == "stable" ]; then
UCS_REBUILD=true
UCS_VERSIONS=($(curl -s -H -X ${REGISTRY_URL}/${COMPANY_NAME}/${PRODUCT_NAME}-ucs/tags/?page_size=100 | \
jq -r '.results|.[]|.name' | grep -oxE '[0-9]{1,}.[0-9]{1,}.[0-9]{1,}.1' || true))
echo "ucs-versions=$(jq -c -n '$ARGS.positional' --args "${UCS_VERSIONS[@]}")" >> "$GITHUB_OUTPUT"
elif
[ "${REPO}" == "4test" ]; then
UCS_REBUILD=false
PREFIX_NAME=4testing-
fi
STABLE_VERSIONS=($(curl -s -H -X ${REGISTRY_URL}/${COMPANY_NAME}/${PRODUCT_NAME}/tags/?page_size=100 | \
jq -r '.results|.[]|.name' | grep -oxE '[0-9]{1,}.[0-9]{1,}.[0-9]{1,}.1' || true))
# When rebuilding stable versions of the document server,
# it is necessary to determine the version from which the
# minor x.x tag will need to be pushed.
VERSIONS=(${STABLE_VERSIONS[@]})
for i in {1..10}; do
if [ -z "${VERSIONS}" ]; then
break
else
TEMPLATE=${VERSIONS[0]%.*.*}
TEMPLATE_MINOR=$(printf -- '%s\n' "${VERSIONS[@]}" | grep -o -m 1 "${VERSIONS[0]%.*.*}.[0-9].[0-9]")
MINOR_TAGS+=(${TEMPLATE_MINOR%.*})
for v in ${MINOR_TAGS[@]}; do
VERSIONS=(${VERSIONS[@]//${v%.*}.*.*})
done
fi
done
echo "Stable releases that will be rebuilded"
echo "--------------------------------------"
echo "${STABLE_VERSIONS[@]}"
echo
echo
echo "Ucs releases that will be rebuilded"
echo "-----------------------------------"
echo "${UCS_VERSIONS[@]}"
echo "stable-versions=$(jq -c -n '$ARGS.positional' --args "${STABLE_VERSIONS[@]}")" >> "$GITHUB_OUTPUT"
echo "minor-tags=${MINOR_TAGS[@]}" >> "$GITHUB_OUTPUT"
echo "ucs-rebuild-condition=${UCS_REBUILD}" >> "$GITHUB_OUTPUT"
echo "prefix-name=${PREFIX_NAME}" >> "$GITHUB_OUTPUT"
echo "repo=${REPO}" >> "$GITHUB_OUTPUT"
shell: bash
re-build-stable:
name: "Rebuild stable:${{ matrix.version }} ${{ matrix.edition }}"
needs: [rebuild-info]
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
type: ["stable"]
edition: ["", "-ee", "-de"]
version: ${{fromJSON(needs.rebuild-info.outputs.stable-versions)}}
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
# Determines the new build number based
# on data from the hub.docker registry
- name: Declare release number
id: release-number
env:
REBUILD_VERSION: ${{ matrix.version }}
run: |
MINOR_VERSION=${REBUILD_VERSION%.*}
LAST_RELEASE=$(curl -s -H -X ${REGISTRY_URL}/${COMPANY_NAME}/${PRODUCT_NAME}/tags/?page_size=100 \
| jq -r '.results|.[]|.name' | grep -Eo -m1 "${MINOR_VERSION}.[0-9]{1,}")
LAST_RELEASE=${LAST_RELEASE#*.*.*.}
echo "release-number=$((LAST_RELEASE+1))" >> "$GITHUB_OUTPUT"
shell: bash
# Note: Rebuilding images with an
# extra layer to update security and
# all dependencies. Update tags got +1 to previous release.
- name: Re-build documentserver-stable
env:
MINOR_TAGS_ST: ${{ needs.rebuild-info.outputs.minor-tags }}
VERSION: ${{ matrix.version }}
RELEASE_NUMBER: ${{ steps.release-number.outputs.release-number }}
PREFIX_NAME: ${{ needs.rebuild-info.outputs.prefix-name }}
REPO: ${{ needs.rebuild-info.outputs.repo }}
PRODUCT_EDITION: ${{ matrix.edition }}
run: |
set -eux
export PULL_TAG=${VERSION}
export TAG=${VERSION%.*}.${RELEASE_NUMBER}
export SHORTER_TAG=${VERSION%.*}
export SHORTEST_TAG=${VERSION%.*.*}
if [ "${REPO}" == "stable" ]; then
MINOR_TAGS=(${MINOR_TAGS_ST})
for v in ${MINOR_TAGS[@]}; do
if [ "${SHORTER_TAG}" == "${v}" ]; then
export PUSH_MAJOR="true"
fi
done
if [ "${SHORTER_TAG}" == "${MINOR_TAGS[0]}" ]; then
export LATEST="true"
fi
fi
docker buildx bake -f docker-bake.hcl documentserver-stable-rebuild --push
shell: bash
re-build-ucs:
name: "Rebuild ucs: ${{ matrix.version }} ${{ matrix.edition }}"
if: needs.rebuild-info.outputs.ucs-rebuild-condition == 'true'
needs: [rebuild-info]
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
type: ["ucs"]
edition: ["", "-ee"]
version: ${{fromJSON(needs.rebuild-info.outputs.ucs-versions)}}
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
# Determines the new build number based
# on data from the hub.docker registry
- name: Declare release number
id: release-number
env:
REBUILD_VERSION: ${{ matrix.version }}
run: |
MINOR_VERSION=${REBUILD_VERSION%.*}
LAST_RELEASE=$(curl -s -H -X ${REGISTRY_URL}/${COMPANY_NAME}/${PRODUCT_NAME}/tags/?page_size=100 \
| jq -r '.results|.[]|.name' | grep -Eo -m1 "${MINOR_VERSION}.[0-9]{1,}")
LAST_RELEASE=${LAST_RELEASE#*.*.*.}
echo "release-number=$((LAST_RELEASE+1))" >> "$GITHUB_OUTPUT"
shell: bash
# Note: Rebuilding images with an
# extra layer to update security and
# all dependencies. Update tags +1 to previous release.
- name: Re-build documentserver-ucs
env:
VERSION: ${{ matrix.version }}
RELEASE_NUMBER: ${{ steps.release-number.outputs.release-number }}
PRODUCT_EDITION: ${{ matrix.edition }}
run: |
set -eux
export PULL_TAG=${VERSION}
export TAG=${VERSION%.*}.${RELEASE_NUMBER}
export SHORTER_TAG=${VERSION%.*}
export SHORTEST_TAG=${VERSION%.*.*}
export UCS_REBUILD=true
export UCS_PREFIX=-ucs
docker buildx bake -f docker-bake.hcl documentserver-stable-rebuild --push
shell: bash

565
.github/workflows/secure-rebuild.yml vendored Normal file
View file

@ -0,0 +1,565 @@
name: Secure rebuild
run-name: >-
Secure rebuild [
${{ github.event_name == 'workflow_dispatch' && inputs.dry_run && 'DRY-RUN' || 'PUBLISH' }}
]
on:
schedule:
- cron: '0 9 1,15 * *'
workflow_dispatch:
inputs:
dry_run:
type: boolean
description: "Dry run (build & test, do not retag release)"
required: false
default: false
concurrency:
group: secure-rebuild
cancel-in-progress: false
env:
COMPANY_NAME: "onlyoffice"
PRODUCT_NAME: "documentserver"
REBUILD_CONFIG: ".github/secure-rebuild.json"
jobs:
prepare:
name: Prepare rebuild matrices
runs-on: ubuntu-latest
outputs:
build_matrix: ${{ steps.matrix.outputs.build_matrix }}
retag_matrix: ${{ steps.matrix.outputs.retag_matrix }}
steps:
- name: Checkout code
uses: actions/checkout@v7
- name: Validate rebuild config
run: |
set -euo pipefail
if [ ! -f "${REBUILD_CONFIG}" ]; then
echo "Rebuild config was not found: ${REBUILD_CONFIG}" >&2
exit 1
fi
jq -e '
type == "object"
and (.releases | type == "object")
and all(
.releases[];
type == "array"
and all(
.[];
(.source_tag | type == "string")
and (.source_tag | length > 0)
and (.release_tag | type == "string")
and (.release_tag | length > 0)
and (.short_tags | type == "array")
and all(.short_tags[]; type == "string")
and (.editions | type == "object")
and (.editions | length > 0)
and all(
.editions[];
type == "object"
and has("latest")
and (.latest | type == "boolean")
)
)
)
' "${REBUILD_CONFIG}" >/dev/null
- name: Create build and retag matrices
id: matrix
run: |
set -euo pipefail
BUILD="$(jq -c '
{
include: (
[
.releases
| to_entries[]
| .value[]
| . as $release
| $release.editions
| to_entries[]
| {
source_tag: $release.source_tag,
test_tag: (
$release.release_tag
| split(".")
| .[0:3]
| join(".")
),
edition: .key
}
]
| unique_by([
.source_tag,
.edition
])
)
}
' "${REBUILD_CONFIG}")"
RETAG="$(jq -c '
{
include: [
.releases
| to_entries[]
| .value[]
| . as $release
| $release.editions
| to_entries[]
| {
source_tag: $release.source_tag,
release_tag: $release.release_tag,
short_tags: (
$release.short_tags
| join(",")
),
is_latest: (
.value.latest
| tostring
),
edition: .key
}
]
}
' "${REBUILD_CONFIG}")"
BUILD_COUNT="$(jq '.include | length' <<< "${BUILD}")"
RETAG_COUNT="$(jq '.include | length' <<< "${RETAG}")"
if [ "${BUILD_COUNT}" -eq 0 ]; then
echo "Build matrix is empty" >&2
exit 1
fi
if [ "${RETAG_COUNT}" -eq 0 ]; then
echo "Retag matrix is empty" >&2
exit 1
fi
echo "Build matrix contains ${BUILD_COUNT} entries:"
jq . <<< "${BUILD}"
echo "Retag matrix contains ${RETAG_COUNT} entries:"
jq . <<< "${RETAG}"
echo "build_matrix=${BUILD}" >> "${GITHUB_OUTPUT}"
echo "retag_matrix=${RETAG}" >> "${GITHUB_OUTPUT}"
rebuild:
name: "Rebuild ${{ matrix.source_tag }}${{ matrix.edition }}"
needs: prepare
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix: ${{ fromJSON(needs.prepare.outputs.build_matrix) }}
steps:
- name: Checkout code
uses: actions/checkout@v7
- name: Set up QEMU
uses: docker/setup-qemu-action@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
- name: Login to Docker Hub
uses: docker/login-action@v4
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
- name: Set up Node.js
uses: actions/setup-node@v6
with:
node-version: "20"
- name: Checkout tests
env:
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
TEST_TAG: ${{ matrix.test_tag }}
run: |
set -euo pipefail
git clone \
"https://${GITEA_TOKEN}@git.onlyoffice.com/ONLYOFFICE-QA/Dep.Tests.git" \
dep-tests
cd dep-tests
if git checkout "refs/tags/${TEST_TAG}" 2>/dev/null; then
echo "Checked out test tag ${TEST_TAG}"
else
echo "Test tag ${TEST_TAG} was not found" >&2
echo "Using fallback commit aa2d423f18" >&2
git checkout aa2d423f18
fi
df -h
- name: Initialize submodules
working-directory: dep-tests
env:
GITHUB_TOKEN: ${{ secrets.TOKEN }}
run: |
set -euo pipefail
git config --global \
url."https://${GITHUB_TOKEN}@github.com/".insteadOf \
"https://github.com/"
git submodule update \
--init
git config --global --unset url."https://${GITHUB_TOKEN}@github.com/".insteadOf
- name: Install dependencies
working-directory: dep-tests/puppeteer/engine
run: |
df -h
npm install --silent --no-progress > /dev/null 2>&1 || {
echo "Dependency installation failed"
exit 1
}
- name: mv Dep.Tests under context
run: |
mv dep-tests ../
- name: Build secure-patched image
id: build
env:
SOURCE_TAG: ${{ matrix.source_tag }}
EDITION: ${{ matrix.edition }}
run: |
set -euo pipefail
SOURCE_IMAGE="${COMPANY_NAME}/4testing-${PRODUCT_NAME}${EDITION}:${SOURCE_TAG}"
PATCHED_IMAGE="${COMPANY_NAME}/4testing-${PRODUCT_NAME}${EDITION}:${SOURCE_TAG}-secure"
echo "Source image: ${SOURCE_IMAGE}"
echo "Patched image: ${PATCHED_IMAGE}"
docker buildx imagetools inspect "${SOURCE_IMAGE}"
docker buildx build \
--platform "linux/amd64,linux/arm64" \
--build-arg "SOURCE_IMAGE=${SOURCE_IMAGE}" \
--tag "${PATCHED_IMAGE}" \
--file Dockerfile.secure \
--push \
.
echo "patched_image=${PATCHED_IMAGE}" >> "${GITHUB_OUTPUT}"
- name: Return dep.tests
run: |
mv ../dep-tests ./
- name: Clean-up
run: |
set -euo pipefail
docker rm --force documentserver 2>/dev/null || true
docker buildx prune -af
docker image prune -af
docker builder prune -af
- name: Pull test image
env:
IMAGE: ${{ steps.build.outputs.patched_image }}
run: |
set -euo pipefail
for attempt in $(seq 1 30); do
if docker pull "${IMAGE}"; then
echo "Image pulled successfully"
exit 0
fi
if [ "${attempt}" -eq 30 ]; then
echo "Image was not available after 5 minutes" >&2
exit 1
fi
echo "Image is not available yet, retrying in 10 seconds"
sleep 10
done
- name: Start test container
env:
IMAGE: ${{ steps.build.outputs.patched_image }}
run: |
set -euo pipefail
docker run \
--detach \
--publish 80:80 \
--name documentserver \
"${IMAGE}"
- name: Wait for healthcheck
run: |
set -euo pipefail
for attempt in $(seq 1 30); do
RESULT="$(
curl \
--fail \
--silent \
--show-error \
http://localhost/healthcheck \
2>/dev/null \
|| true
)"
echo "Healthcheck response: ${RESULT}"
if [ "${RESULT}" = "true" ]; then
echo "Healthcheck passed"
exit 0
fi
if [ "${attempt}" -eq 30 ]; then
echo "Healthcheck failed after 5 minutes" >&2
docker logs documentserver || true
exit 1
fi
sleep 10
done
- name: Start example service
run: |
set -euo pipefail
docker exec documentserver \
supervisorctl start ds:example
for attempt in $(seq 1 30); do
if curl \
--fail \
--silent \
--show-error \
http://localhost/example/ \
>/dev/null 2>&1; then
echo "Example service is ready"
exit 0
fi
if [ "${attempt}" -eq 30 ]; then
echo "Example service did not become ready" >&2
docker logs documentserver || true
exit 1
fi
sleep 5
done
- name: Start Xvfb
run: |
set -euo pipefail
Xvfb :99 \
-screen 0 1920x1080x24 \
>"${RUNNER_TEMP}/xvfb.log" \
2>&1 &
sleep 60
echo "DISPLAY=:99" >> "${GITHUB_ENV}"
- name: Install Chrome
uses: browser-actions/setup-chrome@v2
with:
chrome-version: "120"
- name: Run tests with retryes
uses: nick-fields/retry@v4
with:
timeout_minutes: 20
max_attempts: 3
retry_wait_seconds: 120
command: |
set -uo pipefail
cd dep-tests/puppeteer/engine
OUTPUT_FILE="../test-output.log"
RESULT=0
: > "${OUTPUT_FILE}"
tests=(
"tests/desktop/word/smoke/open-close-file-tab.js"
"tests/desktop/word/smoke/check_search_while_drawing.js"
"tests/desktop/spreadsheets/smoke/check_replace_all.js"
"tests/desktop/spreadsheets/smoke/data_entry_use_tab_button.js"
"tests/desktop/pdf/smoke/check_find_for_a_specific_pdf.js"
"tests/desktop/pdf/smoke/check_undo_after_add_text_comment.js"
)
for test in "${tests[@]}"; do
echo "Running ${test}" \
| tee -a "${OUTPUT_FILE}"
python3 run.py \
--config config_chrome_linux.json \
"${test}" \
--config_params \
"runOptions.disableAnimation=true" \
"testOptions.url=http://localhost/example" \
'puppeteerOptions.browserArgs.args=["--no-sandbox","--disable-setuid-sandbox"]' \
2>&1 \
| tee -a "${OUTPUT_FILE}"
TEST_RESULT="${PIPESTATUS[0]}"
if [ "${TEST_RESULT}" -ne 0 ]; then
echo "Test failed with exit code ${TEST_RESULT}: ${test}" \
| tee -a "${OUTPUT_FILE}"
RESULT=1
fi
done
exit "${RESULT}"
- name: Print test output
if: always()
run: |
if [ -f dep-tests/puppeteer/test-output.log ]; then
cat dep-tests/puppeteer/test-output.log
else
echo "Test output file was not created"
fi
- name: Print test reports
if: always()
run: |
if [ ! -d dep-tests/puppeteer/out ]; then
echo "Test report directory was not created"
exit 0
fi
find dep-tests/puppeteer/out \
-type f \
-name "report*.html" \
-print0 \
| sort -z \
| while IFS= read -r -d "" report; do
echo "=== ${report} ==="
cat "${report}"
echo
done
- name: Upload test artifacts
if: ${{ false }}
uses: actions/upload-artifact@v4
with:
name: smoke-tests-${{ matrix.source_tag }}${{ matrix.edition }}
path: |
dep-tests/puppeteer/test-output.log
dep-tests/puppeteer/out/
if-no-files-found: warn
retention-days: 14
- name: Remove test container
if: ${{ false }}
run: |
docker rm \
--force \
documentserver \
2>/dev/null \
|| true
retag:
name: "Retag ${{ matrix.release_tag }}${{ matrix.edition }}"
needs:
- prepare
- rebuild
if: >-
${{
github.event_name != 'workflow_dispatch'
|| !inputs.dry_run
}}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix: ${{ fromJSON(needs.prepare.outputs.retag_matrix) }}
steps:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
- name: Login to Docker Hub
uses: docker/login-action@v4
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
- name: Create multi-arch manifest with release tags
uses: nick-fields/retry@v4
env:
SOURCE_TAG: ${{ matrix.source_tag }}
RELEASE_TAG: ${{ matrix.release_tag }}
SHORT_TAGS: ${{ matrix.short_tags }}
IS_LATEST: ${{ matrix.is_latest }}
EDITION: ${{ matrix.edition }}
PRODUCT_NAME: ${{ env.PRODUCT_NAME }}
with:
timeout_minutes: 20
max_attempts: 3
retry_wait_seconds: 60
command: |
set -euo pipefail
RELEASE_IMAGE="${COMPANY_NAME}/${PRODUCT_NAME}${EDITION}"
SRC_IMAGE="${COMPANY_NAME}/4testing-${PRODUCT_NAME}${EDITION}:${SOURCE_TAG}-secure"
echo "Source image: ${SRC_IMAGE}"
echo "Release image: ${RELEASE_IMAGE}"
echo "Release tag: ${RELEASE_TAG}"
echo "Short tags: ${SHORT_TAGS}"
echo "Latest: ${IS_LATEST}"
docker buildx imagetools inspect "${SRC_IMAGE}"
PUSH_TAGS=(
--tag "${RELEASE_IMAGE}:${RELEASE_TAG}"
)
if [ -n "${SHORT_TAGS}" ]; then
IFS=',' read -r -a SHORTS <<< "${SHORT_TAGS}"
for tag in "${SHORTS[@]}"; do
if [ -n "${tag}" ]; then
PUSH_TAGS+=(
--tag "${RELEASE_IMAGE}:${tag}"
)
fi
done
fi
if [ "${IS_LATEST}" = "true" ]; then
PUSH_TAGS+=(
--tag "${RELEASE_IMAGE}:latest"
)
fi
docker buildx imagetools create \
"${PUSH_TAGS[@]}" \
"${SRC_IMAGE}"
docker buildx imagetools inspect \
"${RELEASE_IMAGE}:${RELEASE_TAG}"

View file

@ -31,9 +31,9 @@ on:
env:
COMPANY_NAME: "onlyoffice"
PRODUCT_NAME: "documentserver"
VERSION: ${{ github.event.inputs.tag }}
RELEASE_NUMBER: ${{ github.event.inputs.release_number }}
LATEST: ${{ github.event.inputs.latest }}
VERSION: ${{ inputs.tag }}
RELEASE_NUMBER: ${{ inputs.release_number }}
LATEST: ${{ inputs.latest }}
jobs:
setup:
@ -41,26 +41,32 @@ jobs:
runs-on: ubuntu-latest
outputs:
editions: ${{ steps.set.outputs.editions }}
editions_ucs: ${{ steps.set.outputs.editions_ucs }}
steps:
- name: Build editions list
id: set
shell: bash
env:
INPUT_C: ${{ github.event.inputs.community }}
INPUT_E: ${{ github.event.inputs.enterprise }}
INPUT_C: ${{ inputs.community }}
INPUT_E: ${{ inputs.enterprise }}
run: |
set -eux
editions=$(jq -nc \
--argjson c "$INPUT_C" \
--argjson e "$INPUT_E" \
'[ if $c then "" else empty end,
if $e then ("-ee", "-de") else empty end ]')
editions_ucs=$(echo "$editions" | jq -c 'map(select(. != "-de"))')
echo "editions=$editions" >> "$GITHUB_OUTPUT"
echo "editions_ucs=$editions_ucs" >> "$GITHUB_OUTPUT"
echo "Matrix editions: $editions"
echo "Matrix editions (UCS): $editions_ucs"
set -euo pipefail
editions="$(jq -nc \
--argjson community "${INPUT_C}" \
--argjson enterprise "${INPUT_E}" \
'[
if $community then "" else empty end,
if $enterprise then "-ee", "-de" else empty end
]'
)"
if [ "$(jq 'length' <<< "${editions}")" -eq 0 ]; then
echo "At least one edition must be selected" >&2
exit 1
fi
echo "editions=${editions}" >> "${GITHUB_OUTPUT}"
echo "Matrix editions: ${editions}"
build:
name: "Release image: DocumentServer${{ matrix.edition }}"
@ -74,35 +80,33 @@ jobs:
edition: ${{ fromJSON(needs.setup.outputs.editions) }}
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v7
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Docker Hub
uses: docker/login-action@v3
uses: docker/login-action@v4
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
- name: Build documentserver-release
env:
TARGET: ${{ matrix.images }}
PRODUCT_EDITION: ${{ matrix.edition }}
run: |
set -eux
TESTING_IMAGE=${COMPANY_NAME}/4testing-${PRODUCT_NAME}${PRODUCT_EDITION}
export PRODUCT_EDITION
export PULL_TAG=${VERSION}
set -eux
export SOURCE_IMAGE=${COMPANY_NAME}/4testing-${PRODUCT_NAME}${PRODUCT_EDITION}:${VERSION}
export RELEASE_IMAGE=${COMPANY_NAME}/${PRODUCT_NAME}${PRODUCT_EDITION}
export TAG=${VERSION%.*}.${RELEASE_NUMBER}
export SHORTER_TAG=${VERSION%.*}
export SHORTEST_TAG=${VERSION%.*.*}
docker buildx bake --sbom=true --provenance=mode=max -f docker-bake.hcl "${TARGET}" --push
echo "DONE: Build success >> exit with 0"
exit 0
PUSH_TAGS=(
-t "${RELEASE_IMAGE}:${TAG}"
-t "${RELEASE_IMAGE}:${SHORTER_TAG}"
-t "${RELEASE_IMAGE}:${SHORTEST_TAG}"
)
if [ "${LATEST}" = "true" ]; then
PUSH_TAGS+=( "-t" "$RELEASE_IMAGE:latest" )
fi
docker buildx imagetools create "${PUSH_TAGS[@]}" "${SOURCE_IMAGE}"
shell: bash
# Disable for now
@ -110,7 +114,7 @@ jobs:
# https://github.com/peter-evans/dockerhub-description/issues/294
#
#- name: Update Docker Hub README
# uses: peter-evans/dockerhub-description@v4
# uses: peter-evans/dockerhub-description@v5
# with:
# username: ${{ secrets.DOCKER_HUB_USERNAME }}
# password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
@ -123,26 +127,25 @@ jobs:
if: ${{ github.event.inputs.enterprise == 'true' }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
uses: actions/checkout@v7
- name: Login to Docker Hub
uses: docker/login-action@v3
uses: docker/login-action@v4
with:
username: ${{ secrets.DOCKER_HUB_USERNAME_ENTERPRISE }}
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN_ENTERPRISE }}
- name: release 4enterpise
shell: bash
run: |
export TAG=${VERSION%.*}.${RELEASE_NUMBER}
docker buildx imagetools create --tag onlyoffice4enterprise/documentserver-ee:${TAG} \
onlyoffice/4testing-documentserver-ee:${VERSION}
- name: Create release image tag
uses: nick-fields/retry@v4
with:
timeout_minutes: 10
max_attempts: 3
retry_wait_seconds: 60
command: |
export TAG=${VERSION%.*}.${RELEASE_NUMBER}
docker buildx imagetools create \
--tag onlyoffice4enterprise/documentserver-ee:${TAG} \
onlyoffice/4testing-documentserver-ee:${VERSION}
build-nonexample:
name: "Release image: DocumentServer${{ matrix.edition }}-nonExample"
@ -156,16 +159,16 @@ jobs:
edition: ${{ fromJSON(needs.setup.outputs.editions) }}
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v7
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
uses: docker/setup-qemu-action@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
uses: docker/setup-buildx-action@v4
- name: Login to Docker Hub
uses: docker/login-action@v3
uses: docker/login-action@v4
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
@ -181,41 +184,298 @@ jobs:
docker buildx bake --sbom=true --provenance=mode=max -f docker-bake.hcl "${TARGET}" --push
shell: bash
build-ucs-ubuntu20:
name: "Release image: DocumentServer${{ matrix.edition }}-ucs"
update-secure-rebuild-config:
name: "Update secure-rebuild config"
runs-on: ubuntu-latest
if: ${{ needs.setup.outputs.editions_ucs != '[]' }}
needs: [setup]
strategy:
fail-fast: false
matrix:
edition: ${{ fromJSON(needs.setup.outputs.editions_ucs) }}
platform: ["amd64"]
permissions:
contents: write
pull-requests: write
needs: [build]
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Docker Hub
uses: docker/login-action@v3
- uses: actions/checkout@v7
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
fetch-depth: 0
- name: build UCS
- name: Compute release metadata
id: release
env:
PACKAGE_BASEURL: ${{ secrets.REPO_BASEURL }}
PRODUCT_EDITION: ${{ matrix.edition }}
PLATFORM: linux/${{ matrix.platform }}
VERSION: ${{ inputs.tag }}
RELEASE_NUMBER: ${{ inputs.release_number }}
run: |
set -eux
export DOCKERFILE=Dockerfile
export BASE_VERSION=20.04
export PG_VERSION=12
export PACKAGE_SUFFIX=
export TAG=${VERSION%.*}.${RELEASE_NUMBER}
export PACKAGE_VERSION=$( echo ${VERSION} | sed -E 's/(.*)\./\1-/')
docker buildx bake --sbom=true --provenance=mode=max -f docker-bake.hcl documentserver-ucs --push
shell: bash
set -euo pipefail
BASE="${VERSION%.*}"
echo "source_tag=${VERSION}" >> "${GITHUB_OUTPUT}"
echo "release_tag=${BASE}.${RELEASE_NUMBER}" >> "${GITHUB_OUTPUT}"
- name: Update JSON
env:
COMMUNITY: ${{ inputs.community }}
ENTERPRISE: ${{ inputs.enterprise }}
LATEST: ${{ inputs.latest }}
SOURCE_TAG: ${{ steps.release.outputs.source_tag }}
RELEASE_TAG: ${{ steps.release.outputs.release_tag }}
RELEASE_NUMBER: ${{ inputs.release_number }}
run: |
set -euo pipefail
EDITIONS_JSON="$(jq -cn \
--argjson community "${COMMUNITY}" \
--argjson enterprise "${ENTERPRISE}" \
--argjson latest "${LATEST}" \
'{
editions: (
{}
+ (
if $community
then {"": {latest: $latest}}
else {}
end
)
+ (
if $enterprise
then {
"-ee": {latest: $latest},
"-de": {latest: $latest}
}
else {}
end
)
)
}
| .editions'
)"
if [ "$(jq 'length' <<< "${EDITIONS_JSON}")" -eq 0 ]; then
echo "No editions were selected" >&2
exit 1
fi
chmod +x .github/scripts/update-secure-rebuild-config.sh
.github/scripts/update-secure-rebuild-config.sh \
"${SOURCE_TAG}" \
"${RELEASE_TAG}" \
"${RELEASE_NUMBER}" \
"${EDITIONS_JSON}"
- name: Push branch and open PR in Gitea
env:
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
GITEA_URL: ${{ secrets.GITEA_URL }}
GITEA_REPO: ${{ secrets.GITEA_REPO }}
RELEASE_TAG: ${{ steps.release.outputs.release_tag }}
SOURCE_TAG: ${{ steps.release.outputs.source_tag }}
GITHUB_SOURCE_BRANCH: ${{ github.ref_name }}
run: |
set -euo pipefail
CONFIG_FILE=".github/secure-rebuild.json"
BRANCH="secure-rebuild-config/${RELEASE_TAG}"
WORK_DIR="${RUNNER_TEMP}/gitea-repo"
RESPONSE_FILE="$(mktemp)"
cleanup() {
rm -f "${RESPONSE_FILE}"
rm -rf "${WORK_DIR}"
}
trap cleanup EXIT
if [ ! -f "${CONFIG_FILE}" ]; then
echo "Config file was not found: ${CONFIG_FILE}" >&2
exit 1
fi
if [ -z "${GITEA_TOKEN}" ]; then
echo "GITEA_TOKEN is empty" >&2
exit 1
fi
if [ -z "${GITEA_URL}" ]; then
echo "GITEA_URL is empty" >&2
exit 1
fi
if [ -z "${GITEA_REPO}" ]; then
echo "GITEA_REPO is empty" >&2
exit 1
fi
GITEA_URL="${GITEA_URL%/}"
GITEA_HOST="${GITEA_URL#https://}"
GITEA_HOST="${GITEA_HOST#http://}"
AUTHENTICATED_REPO_URL="https://x-token:${GITEA_TOKEN}@${GITEA_HOST}/${GITEA_REPO}.git"
PUBLIC_REPO_URL="${GITEA_URL}/${GITEA_REPO}.git"
API_URL="${GITEA_URL}/api/v1/repos/${GITEA_REPO}/pulls"
BASE_BRANCH="${GITHUB_SOURCE_BRANCH#refs/heads/}"
if [ -z "${BASE_BRANCH}" ]; then
BASE_BRANCH="master"
fi
if git ls-remote \
--exit-code \
--heads \
"${AUTHENTICATED_REPO_URL}" \
"refs/heads/${BASE_BRANCH}" \
>/dev/null 2>&1; then
echo "Using matching Gitea branch as PR base: ${BASE_BRANCH}"
else
echo "Branch ${BASE_BRANCH} does not exist in Gitea"
BASE_BRANCH="master"
echo "Using fallback PR base: ${BASE_BRANCH}"
fi
if ! git ls-remote \
--exit-code \
--heads \
"${AUTHENTICATED_REPO_URL}" \
"refs/heads/${BASE_BRANCH}" \
>/dev/null 2>&1; then
echo "Base branch does not exist in Gitea: ${BASE_BRANCH}" >&2
exit 1
fi
rm -rf "${WORK_DIR}"
git clone \
--branch "${BASE_BRANCH}" \
--single-branch \
"${AUTHENTICATED_REPO_URL}" \
"${WORK_DIR}"
cd "${WORK_DIR}"
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git checkout -B "${BRANCH}"
mkdir -p "$(dirname "${CONFIG_FILE}")"
cp \
"${GITHUB_WORKSPACE}/${CONFIG_FILE}" \
"${CONFIG_FILE}"
jq -e . "${CONFIG_FILE}" >/dev/null
git add "${CONFIG_FILE}"
if git diff --cached --quiet; then
echo "The secure rebuild config is already up to date"
exit 0
fi
git commit \
-m "chore: update secure-rebuild config for ${RELEASE_TAG}"
git push \
origin \
"HEAD:refs/heads/${BRANCH}" \
--force
HTTP_CODE="$(curl \
--silent \
--show-error \
--output "${RESPONSE_FILE}" \
--write-out "%{http_code}" \
--get "${API_URL}" \
--header "Accept: application/json" \
--header "Authorization: token ${GITEA_TOKEN}" \
--data-urlencode "state=open" \
--data-urlencode "limit=50"
)"
if [ "${HTTP_CODE}" -lt 200 ] ||
[ "${HTTP_CODE}" -ge 300 ]; then
echo "Failed to query existing pull requests. HTTP status: ${HTTP_CODE}" >&2
jq . "${RESPONSE_FILE}" >&2 || cat "${RESPONSE_FILE}" >&2
exit 1
fi
EXISTING_PR_URL="$(jq -r \
--arg branch "${BRANCH}" \
--arg base "${BASE_BRANCH}" \
'
map(
select(
.head.ref == $branch
and .base.ref == $base
)
)
| first
| .html_url // empty
' "${RESPONSE_FILE}"
)"
if [ -n "${EXISTING_PR_URL}" ]; then
echo "Pull request already exists: ${EXISTING_PR_URL}"
exit 0
fi
PAYLOAD="$(jq -n \
--arg title "chore: update secure-rebuild config for ${RELEASE_TAG}" \
--arg head "${BRANCH}" \
--arg base "${BASE_BRANCH}" \
--arg body "Auto-generated after release of ${RELEASE_TAG} from source image tag ${SOURCE_TAG}." \
'{
title: $title,
head: $head,
base: $base,
body: $body
}'
)"
HTTP_CODE="$(curl \
--silent \
--show-error \
--output "${RESPONSE_FILE}" \
--write-out "%{http_code}" \
--request POST "${API_URL}" \
--header "Accept: application/json" \
--header "Content-Type: application/json" \
--header "Authorization: token ${GITEA_TOKEN}" \
--data "${PAYLOAD}"
)"
if [ "${HTTP_CODE}" -lt 200 ] ||
[ "${HTTP_CODE}" -ge 300 ]; then
echo "Failed to create pull request. HTTP status: ${HTTP_CODE}" >&2
jq . "${RESPONSE_FILE}" >&2 || cat "${RESPONSE_FILE}" >&2
exit 1
fi
PR_NUMBER="$(jq -r '.number // empty' "${RESPONSE_FILE}")"
PR_URL="$(jq -r '.html_url // empty' "${RESPONSE_FILE}")"
echo "Pull request created: #${PR_NUMBER}"
echo "Pull request base branch: ${BASE_BRANCH}"
if [ -n "${PR_URL}" ]; then
echo "Pull request URL: ${PR_URL}"
else
echo "Repository URL: ${PUBLIC_REPO_URL}"
fi
# The same step for GITHUB.
# Uncomment if need to open PR in github repository.
- name: Open PR Github
if: ${{ false }}
uses: peter-evans/create-pull-request@v6
with:
token: ${{ secrets.GITHUB_TOKEN }}
branch: "secure-rebuild-config/${{ steps.release.outputs.release_tag }}"
base: ${{ github.ref_name }}
commit-message: "chore: update secure-rebuild config for ${{ steps.release.outputs.release_tag }}"
title: "Update secure-rebuild config for ${{ steps.release.outputs.release_tag }}"
body: |
Auto-generated after release of `${{ steps.release.outputs.release_tag }}`
(source 4testing tag: `${{ steps.release.outputs.source_tag }}`,
release number: `${{ github.event.inputs.release_number }}`).
Please review and merge so next scheduled secure-rebuild picks up the new source.
delete-branch: true

16
Dockerfile.secure Normal file
View file

@ -0,0 +1,16 @@
ARG SOURCE_IMAGE
FROM ${SOURCE_IMAGE}
ENV DEBIAN_FRONTEND=noninteractive
ENV ACCEPT_EULA=Y
RUN set -eux; \
printf '#!/bin/sh\nexit 101\n' > /usr/sbin/policy-rc.d; \
chmod +x /usr/sbin/policy-rc.d; \
apt-get update; \
apt-get -o Dpkg::Options::="--force-confold" \
-o Dpkg::Options::="--force-confdef" \
-y upgrade; \
rm -f /usr/sbin/policy-rc.d; \
apt-get clean; \
rm -rf /var/lib/apt/lists/*

View file

@ -2,19 +2,6 @@
ARG PULL_TAG=latest
ARG COMPANY_NAME=onlyoffice
ARG PRODUCT_EDITION=
### Rebuild arguments
ARG UCS_PREFIX=
ARG IMAGE=${COMPANY_NAME}/documentserver${PRODUCT_EDITION}${UCS_PREFIX}:${PULL_TAG}
### Build main-release ###
FROM ${COMPANY_NAME}/4testing-documentserver${PRODUCT_EDITION}:${PULL_TAG} as documentserver-stable
### Rebuild stable images with secure updates
FROM ${IMAGE} as documentserver-stable-rebuild
RUN echo "This is rebuild" \
&& apt-get update -y \
&& apt-get upgrade -y
### Build nonexample ###